MCP Configuration
All MCP configuration lives under the top-level mcp: block in harperdb-config.yaml. Each profile (operations, application) is enabled by the presence of its sub-block — there is no separate enabled flag. A minimal "turn it on" config is therefore just:
mcp:
operations: {}
application: {}
That boots both profiles with default settings: the operations profile mounts at /mcp on the operations server, the application profile mounts at /mcp on the application HTTP server, and the default allow lists / rate limits apply.
mcp.operations.*
Configures the operations-profile MCP endpoint that wraps Harper's operation catalog.
mcp.operations.mountPath
Type: string
Default: /mcp
URL path the MCP endpoint mounts on. Change it if /mcp collides with another route in your application.
mcp.operations.allow
Type: array<string> (glob patterns or literal operation names)
Default: ['describe_*', 'list_*', 'search_*', 'get_job', 'get_status', 'get_analytics', 'get_metrics', 'system_information', 'read_log', 'read_audit_log']
Operations exposed as MCP tools. Glob * matches any sequence of characters; literal names match exactly. Setting allow replaces the default list; it does not merge. To add destructive or sensitive operations to the surface (e.g. set_configuration, drop_table), include them here explicitly.
The default list intentionally avoids get_* as a glob because that pulls in get_configuration (which can return TLS / S3 / authentication secrets), get_components / get_component_file / get_custom_function* (which return component source that can embed secrets), get_backup, and get_deployment*. These are all gated by verifyPerms at dispatch, but defaulting to "expose them to an LLM if a super_user calls them" is the wrong default — opt them in deliberately.
mcp.operations.deny
Type: array<string> (glob patterns or literal operation names)
Default: []
Operations to filter out after the allow list has been applied. Useful for taking back a single operation that a broad allow glob would otherwise expose.
mcp.operations.maxTools
Type: integer (minimum 1)
Default: 200
Maximum number of tools returned in a single tools/list response page. The MCP cursor is used to page through any overflow.
mcp.operations.rateLimit.*
See mcp.<profile>.rateLimit.* below — the schema is identical for both profiles.
Default per-profile values for operations: perToolPerSecond: 10, perToolBurst: 20, sessionConcurrency: 25, sessionPerSecond: 100.
mcp.application.*
Configures the application-profile MCP endpoint that walks your exported Resource classes. All mcp.operations.* keys above also apply here; the additional knob is:
mcp.application.searchMaxResults
Type: integer (minimum 1)
Default: 1000
Hard cap on the number of records a generated search_<resource> tool can return per call. Clients still pass limit, but the server clamps to this ceiling regardless of what the client requests — bounded to keep a runaway agent from exhausting memory.
Default per-profile rate-limit values for application: perToolPerSecond: 25, perToolBurst: 50, sessionConcurrency: 50, sessionPerSecond: 200.
mcp.<profile>.rateLimit.*
Per-session, per-tool token-bucket rate limits. A bucket exists per (session, tool) pair plus one per-session bucket across all tools. When either bucket is exhausted, tools/call returns result.isError = true with kind: "rate_limited" — not a JSON-RPC error — so the LLM can read the message and back off without the transport tearing down.
mcp.<profile>.rateLimit.perToolPerSecond
Type: number (minimum 0)
Default: 10 (operations) / 25 (application)
Sustained rate at which the per-tool token bucket refills. Set to 0 to disable per-tool throttling on this profile.
mcp.<profile>.rateLimit.perToolBurst
Type: number (minimum 0)
Default: 20 (operations) / 50 (application)
Burst capacity of the per-tool token bucket — how many back-to-back calls a single tool can absorb before sustained-rate refill kicks in.
mcp.<profile>.rateLimit.sessionConcurrency
Type: integer (minimum 0)
Default: 25 (operations) / 50 (application)
Maximum number of tools/call invocations a single session may have in flight at once. Subsequent attempts return kind: "rate_limited" with scope: "concurrency".
mcp.<profile>.rateLimit.sessionPerSecond
Type: number (minimum 0)
Default: 100 (operations) / 200 (application)
Sustained per-session rate across all tools combined. Protects a worker from a single session that spreads its calls across many distinct tools (and so would otherwise dodge perTool*).
mcp.session.*
Settings that apply to MCP session lifecycle on both profiles.
mcp.session.idleTimeoutSeconds
Type: integer (minimum 1)
Default: 1800 (30 minutes)
Idle window after which a session record in system.mcp_session is TTL-evicted. The next request bearing the evicted session id receives HTTP 404 and the client is expected to re-initialize.
mcp.session.allowClientDelete
Type: boolean
Default: false
When true, Harper accepts client-issued DELETE /mcp requests that explicitly terminate a session. When false (the default), DELETE returns 405 with an Allow header — sessions only end via idle eviction or explicit server-side cleanup.
Example
A common deployment pattern that locks down the operations profile to a small explicit set, enables MCP DELETE for graceful client logout, and raises per-tool throughput for the application profile:
mcp:
operations:
allow:
- describe_all
- describe_database
- system_information
- get_job
rateLimit:
perToolPerSecond: 5
perToolBurst: 10
application:
searchMaxResults: 500
rateLimit:
perToolPerSecond: 50
perToolBurst: 100
session:
idleTimeoutSeconds: 3600
allowClientDelete: true