Security¶
What you'll learn here: how to enable bearer token authentication, which endpoints it protects, how signed upload/download URLs work, and what clients must send.
Auth is disabled by default¶
Out of the box the adapter accepts requests without credentials. This is intentional for local development. Before exposing the adapter to a network, enable auth under core.auth.
core:
auth:
enabled: true
header_name: "X-Mcp-Adapter-Auth-Token"
token: "${MCP_ADAPTER_TOKEN}"
The token field supports ${ENV_VAR} and ${ENV_VAR:-default} interpolation. Never commit the token value directly to your config file.
Header auth semantics¶
When auth is enabled, adapter token auth is an exact header-value match. If the header is missing or wrong, the adapter returns HTTP 403.
There is no role system, no JWT parsing, and no OAuth. It is one shared token per adapter instance.
A correctly authenticated MCP request looks like this:
POST /mcp/playwright HTTP/1.1
Mcp-Session-Id: a3f8c2d1-7b4e-4f9a-85cc-0e3d1f6a9b12
X-Mcp-Adapter-Auth-Token: my-secret-token
Content-Type: application/json
Public vs protected endpoints¶
When auth is enabled, these endpoints are always public:
/healthz/docs/redoc/openapi.json/.well-known/oauth-authorization-server/.well-known/openid-configuration
Everything else is protected. In practice:
/mcp/<server_id>requires the configured auth header./upload/<server_id>uses signed upload credentials when enabled (below)./artifacts/...accepts signed download URLs when enabled; otherwise it requires adapter auth and matching session context.
Signed upload URLs¶
When a client calls <server_id>_get_upload_url(...), the adapter can return a signed, time-limited upload URL.
Signing uses:
core.auth.signing_secretwhen set- otherwise
core.auth.token
URL lifetime is core.auth.signed_upload_ttl_seconds (default: 120).
For signed uploads, clients send:
Mcp-Session-Idheader- signed query params from
<server_id>_get_upload_url(...) - multipart
filefields (andsha256fields if required)
The adapter auth header is not required on that upload POST when signed credentials are valid.
If signed credentials are missing, invalid, replayed, or expired, the upload is rejected with HTTP 403.
Signed download URLs¶
When core.allow_artifacts_download is enabled, artifact tool results may include meta.artifact.download_url. When signing is active, this URL includes signed query params and can be fetched without the adapter auth header.
Signed download URL TTL is:
artifacts.ttl_secondswhen set- otherwise
core.auth.signed_upload_ttl_seconds
If signed download params are missing or invalid, the request falls back to normal auth/session checks.
What clients must send¶
When auth is enabled:
- Send
X-Mcp-Adapter-Auth-Token: <token>(or your configuredheader_name) on MCP requests (/mcp/<server_id>). - For uploads, call
<server_id>_get_upload_url(...), then POST to the returned URL withMcp-Session-Idand signed query params. - For artifact HTTP downloads without a valid signed URL, send adapter auth plus matching session context (
Mcp-Session-Idheader orsession_idquery param).
Example GitHub Copilot config:
{
"servers": {
"playwright": {
"url": "http://localhost:8932/mcp/playwright",
"type": "http",
"headers": {
"X-Mcp-Adapter-Auth-Token": "${input:mcp-adapter-token}"
}
}
},
"inputs": [
{
"type": "promptString",
"id": "mcp-adapter-token",
"description": "Enter the authentication token for the MCP adapter",
"password": true
}
]
}
Next steps¶
- See also: Configuration - practical config examples.
- See also: Config Reference - full
core.authreference. - See also: Getting Started - IDE/agent connection examples.