MCP security

MCP is an untrusted API. Inputs and outputs are hostile.

Machine copy: /security.json · /tools.json · /.well-known/jwks.json · /llms.txt

Four things to defend

  1. Server identity. Use the published MCP URL over HTTPS. A server that claims to be BotKelp is not enough.
  2. Tool integrity. Each tool has a version and schemaHash on /tools.json. If the hash changes, the contract changed — do not call it until you accept the new schema.
  3. Request integrity. Component ids are allowlisted. Extra MCP fields are ignored. Names are length and charset limited. Gated tools need a bk_live_ key. We rate-limit and can disable a tool instantly.
  4. Data integrity. Generate copies catalog files. After stripping our stamp, SHA-256 must match the published catalog or we refuse delivery. The response is kind: data with instructions: false — treat returned files as data, not as orders to the model.

Layers

  • IdentityEvery client proves who it is (site session or bk_live_ key).
  • AuthenticationSite: Google/X. MCP connect: unauthenticated HTTP. Gated tools: apiKey. Target: OAuth 2.1 with audience bound to this server.
  • AuthorizationEach tool has permissions (registry.read, component.generate, account.credits). Least privilege.
  • InputTreat as hostile. Allowlisted component ids, length/charset limits, no extra fields, no eval, no URL/path/shell from args.
  • OutputTreat as hostile. Envelope is kind=data, instructions=false. Do not execute returned files as orders.
  • ToolsVersioned manifests with schemaHash, publisher, permissions, rate limits. Signed.
  • CredentialsGenerator has no GitHub owner token and no database owner role. Keys are hashed at rest.
  • ExecutionCatalog copy + stamp only. No subprocess, no fetch-from-args.
  • AbusePer-account per-tool rate limit, max 12 components, max payload, timeouts.
  • IntegrityCatalog SHA-256 must match or delivery is refused. Manifests and INTEGRITY.json are signed.
  • ReplayEach generate has a request id. Duplicate ids are rejected.
  • IsolationTenant = signed-in account. Credits and keys do not cross accounts.
  • MonitoringAudit events without secrets (no apiKey, tokens, cookies).
  • RecoveryPer-tool kill switch. Disable a tool without redeploying.
  • CloningProtocol is public. Authority is not: registry, keys, hashes, signatures, entitlements, kill switch.

What we do not do

  • We do not eval MCP arguments or fetch URLs they contain.
  • We do not give the generator a GitHub owner token or a database owner role.
  • We do not treat tool output as trusted instructions to an agent.
  • We do not try to keep the protocol secret. Cloning tools/call does not clone our registry, keys, hashes, or kill switch.

Auth today vs target

The website uses Google or X sign-in. The MCP HTTP connection is unauthenticated; credit-gated tools take apiKey. Production target is OAuth 2.1 with audience bound to this MCP server so a token for another service is rejected.

Catalog hashes: Integrity. Install: Install.