title: YAML reference description: Every YAML key in mcp-test config: server, oidc, api_keys, auth, database, audit, portal, tools. Defaults and environment overrides.
YAML reference¶
Every config key with its type, default, and environment-variable
override. The binary loads --config <path> (default
configs/mcp-test.yaml), expands ${VAR} and ${VAR:-default}
forms against the process environment, applies defaults, and
validates. Plain $VAR is intentionally left alone so DSNs and other
shell-shaped values round-trip.
server¶
Top-level HTTP listener and lifecycle.
server:
name: mcp-test
address: ":8080"
base_url: "http://localhost:8080"
instructions: "..." # see configuration/instructions.md
read_header_timeout: 10s
shutdown:
grace_period: 25s
pre_shutdown_delay: 2s
tls:
enabled: false
cert_file: ""
key_file: ""
streamable:
session_timeout: 30m
stateless: false
json_response: false
server.name
mcp-test
Reported in the MCP initialize response and in the audit log.
server.address
:8080
Listen address; MCPTEST_PORT env interpolation common.
server.base_url
http://localhost:<port>
Public origin used for the protected-resource metadata document and OIDC redirect URIs. Set this to your real hostname behind TLS terminators.
server.instructions
Returned to MCP clients via initialize.result.instructions. Most clients pass this to the LLM as system context. See Server Instructions for the shipped default.
server.read_header_timeout
10s
Standard http.Server.ReadHeaderTimeout.
server.shutdown.grace_period
25s
Maximum time http.Server.Shutdown waits for in-flight requests during drain.
server.shutdown.pre_shutdown_delay
2s
After SIGINT / SIGTERM, the server flips /readyz to 503 and sleeps this long before starting the shutdown so load balancers notice.
server.tls.enabled
false
If true, listens with TLS using the cert / key files below. Most deployments terminate TLS upstream and leave this false.
server.tls.cert_file
""
PEM-encoded certificate path.
server.tls.key_file
""
PEM-encoded private key path.
server.streamable.session_timeout
30m
Idle MCP session timeout passed to mcp.StreamableHTTPOptions.
server.streamable.stateless
false
If true, the SDK does not validate Mcp-Session-Id and uses ephemeral sessions. Useful behind external session stores; we don't ship one.
server.streamable.json_response
false
If true, responses are application/json instead of text/event-stream.
oidc¶
External OIDC delegation. When enabled, mcp-test validates incoming bearer tokens against the issuer's JWKS.
oidc:
enabled: true
issuer: "http://localhost:8081/realms/mcp-test"
audience: "mcp-test"
client_id: "mcp-test-portal"
client_secret: ""
allowed_clients: []
clock_skew_seconds: 30
jwks_cache_ttl: 1h
skip_signature_verification: false
oidc.enabled
false
Master toggle. With it off, only API keys (file / DB) and anonymous mode (if enabled) authenticate.
oidc.issuer
The IdP's issuer URL. mcp-test fetches <issuer>/.well-known/openid-configuration to find the JWKS and authorization endpoints.
oidc.audience
Required aud claim value. Tokens that don't carry this audience are rejected.
oidc.client_id
""
The OIDC client ID used by the browser PKCE login flow.
oidc.client_secret
""
Optional. Confidential clients should set this; public PKCE clients leave it empty.
oidc.allowed_clients
[]
Optional azp / client_id allowlist. Empty means any client of the issuer is accepted.
oidc.clock_skew_seconds
30
Leeway applied when validating exp / iat / nbf.
oidc.jwks_cache_ttl
1h
How long fetched JWKS keys are cached. The cache transparently refreshes on any unknown kid.
oidc.skip_signature_verification
false
Trust the IdP's TLS without verifying JWT signatures. Refused unless MCPTEST_INSECURE=1 is set in the environment.
See Authentication for the full identity model and auth-chain semantics.
api_keys¶
Two API-key sources, used in series (file first, DB on miss).
api_keys:
file:
- name: dev-local
key: "${MCPTEST_DEV_KEY:-}"
description: "local dev only"
db:
enabled: true
api_keys.file
[]
List of {name, key, description} entries. The plaintext key is constant-time compared against the inbound X-API-Key header. Empty key values are skipped (so an unset env var doesn't enable an empty credential).
api_keys.db.enabled
false
If true, the binary opens the bcrypt-hashed api_keys Postgres table for read+write. The portal's API Keys page manages entries.
Both sources contribute to the same auth chain: an inbound API key is matched against file entries first (cheap O(N) constant-time compare), then DB entries (bcrypt scan) on miss.
auth¶
Top-level auth toggles applied across MCP and portal routes.
auth.allow_anonymous
false
If true, missing credentials on /mcp resolve to a synthetic Anonymous identity. Useful for some gateway tests where you want to validate header pass-through without auth in the way. The portal still requires a credential.
auth.require_for_mcp
true
Gate the / endpoint. Currently the auth gateway checks for credential presence and 401s without one (unless anonymous is allowed).
auth.require_for_portal
true
Gate every /portal/* and /api/v1/* route. The portal auth middleware is independent of allow_anonymous.
database¶
Postgres connection used for migrations, audit, and DB-backed API keys.
database:
url: "postgres://mcp:mcp@localhost:5432/mcp_test?sslmode=disable"
max_open_conns: 25
max_idle_conns: 5
conn_max_lifetime: 1h
database.url
A PostgreSQL DSN that the pgx driver understands. The migration runner rewrites postgres:// to pgx5:// internally so the golang-migrate driver picks it up.
database.max_open_conns
25
Max active connections in the pgxpool.
database.max_idle_conns
5
Min idle connections held open.
database.conn_max_lifetime
1h
Recycle connections older than this.
See Database & Migrations for the schema details.
audit¶
Audit-log behavior.
audit:
enabled: true
retention_days: 30
redact_keys: [password, token, secret, authorization, cookie, api_key, credentials]
audit.enabled
true
Disables the audit pipeline entirely when false (no rows written, no portal data).
audit.retention_days
30
Documented retention target. mcp-test does not currently auto-prune; deploy a cron job against the audit_events table if you need it.
audit.redact_keys
[password, token, secret, authorization, api_key, credentials]
Case-insensitive substring match. Any tool-call argument key matching one of these gets its value replaced with [redacted] before the row is written.
portal¶
The embedded React 19 SPA and its session cookie.
portal:
enabled: true
cookie_name: mcp_test_session
cookie_secret: "${MCPTEST_COOKIE_SECRET}"
cookie_secure: true
oidc_redirect_path: /portal/auth/callback
portal.enabled
false
Master toggle. Disabling skips loading the session store and mounting the portal / admin APIs and SPA.
portal.cookie_name
mcp_test_session
Name of the HMAC-signed session cookie.
portal.cookie_secret
At least 16 bytes, 32+ recommended. HMAC key for cookie signing.
portal.cookie_secure
true
Sets the Secure cookie attribute. Leave on in production; turn off for local HTTP-only dev.
portal.oidc_redirect_path
/portal/auth/callback
OIDC redirect URI path. Whatever you set must match what the IdP has registered for the portal client.
tools¶
Per-toolkit enable flags.
tools:
identity: { enabled: true }
data: { enabled: true }
failure: { enabled: true }
streaming: { enabled: true }
tools.identity.enabled
false
whoami, echo, headers.
tools.data.enabled
false
fixed_response, sized_response, lorem.
tools.failure.enabled
false
error, slow, flaky.
tools.streaming.enabled
false
progress, long_output, chatty.
A toolkit must be enabled in config for its tools to be registered with the MCP server. The example and dev configs enable all four.
Validation¶
config.Validate() fails fast at startup on impossible setups:
database.urlmust be set.portal.cookie_secretis required whenportal.enabled=true.oidc.issueris required whenoidc.enabled=true.oidc.skip_signature_verificationrequiresMCPTEST_INSECURE=1in the environment.- At least one auth method must be enabled (OIDC, file API keys, DB API keys, or anonymous).
The binary refuses to start if any of these checks fail and prints a human-readable summary listing every problem.