ProdCraft
Subscribe
Security

Secure MCP Servers in Production: OAuth, Tool Scopes and Trust Boundaries

Harden production MCP servers with OAuth, least-privilege tool scopes, input validation, audit logs, secret handling and deployment controls.

ProdCraft5 min read
Humanoid robot wearing an identification badge representing MCP tool registry governance, identity and capability access

Model Context Protocol servers can expose databases, ticket systems, repositories and operational tools to AI clients. That convenience also creates a security boundary: a model may request an action, but the server must decide whether the authenticated principal is allowed to perform it. Treat an MCP server as an API with privileged capabilities, not as a trusted extension of the model.

Authenticate the client and authorize each operation

Use a supported OAuth flow for remote clients and validate issuer, audience, signature, expiry and intended resource. Do not accept a token merely because it is syntactically valid. Map the authenticated identity to explicit scopes or policy rules. A read-only support role should not inherit write access because another tool in the same server needs it.

Make tool permissions narrow

Prefer separate tools such as ticket.read, ticket.comment and ticket.close rather than one generic administrative operation. For destructive actions, require a separate approval step, an idempotency key and an auditable actor identity. Validate resource ownership and tenant boundaries on the server for every call.

Validate all inputs

Tool descriptions help a model choose arguments; they are not validation. Enforce strict schemas, maximum lengths, enumerated values, path allowlists and query limits. Prevent command injection by avoiding shell interpolation. If a tool must run a command, use a fixed executable and pass arguments as an array.

Protect secrets and logs

Keep OAuth client secrets and upstream credentials in a secret manager. Never put bearer tokens in tool descriptions, model context or error messages. Log the caller, tool name, authorization decision, resource identifier and result status. Redact sensitive arguments and response payloads before sending logs to a central system.

Production checklist

  • Use TLS and validate token audience and issuer.
  • Apply authorization independently to every tool call.
  • Separate read, write and destructive capabilities.
  • Set timeouts, rate limits and bounded response sizes.
  • Test prompt-injection attempts against connected resources.
  • Rotate credentials and document emergency revocation.

Finally, isolate the server process and restrict network egress to required upstreams. A compromised tool should not become a route to the entire private network. Related reading: MCP capability discovery and AI agent identity and least privilege.

Engineering considerations

Write down the server’s trust boundary before connecting production systems. List every upstream service, network destination, credential and data class the server can access. Treat model-generated arguments as untrusted even when the client has authenticated. The server must independently validate resource identifiers, tenant boundaries and operation types. Isolate the process from unrelated internal networks and allow outbound connections only to required upstream services. A compromised tool should not become a route into the entire private infrastructure.

Implementation details

Validate OAuth tokens against the expected issuer, audience, signature, expiry and resource binding using the authorization server’s supported metadata. A token intended for another API must not be accepted simply because it is correctly signed. Prefer short-lived credentials and supported user authorization flows. When acting on behalf of a user, preserve that identity and scopes in downstream calls rather than silently replacing them with a broad service account. Define refresh, revocation and signing-key rotation procedures.

Security and reliability controls

Keep authentication and authorization separate. Authentication establishes who is calling; authorization determines which resource and action that identity may access. A valid token does not grant access to every ticket, repository or customer record. Derive tenant identity from trusted claims or a server-side mapping, never from a model-supplied argument. Check ownership for every operation and reject mismatches between caller, tenant and target resource. Repeat checks at downstream services where possible.

Testing strategy

Create separate capabilities for reading, writing and destructive actions. Sending a message, changing billing, deploying code or deleting a record should not be hidden inside a generic administrative tool. Require human confirmation for high-impact operations, show the exact target and proposed mutation, and bind approval to the payload. Use idempotency keys so retries after timeouts do not repeat side effects. Record who initiated, approved and executed each action.

Operational monitoring

Connected tickets, documents and web pages may contain prompt-injection instructions. Treat their contents as data, not authority. A document telling the agent to export every customer record must not override server policy. Enforce permissions in code, limit tool outputs to necessary fields and avoid unrestricted shell or database access. Test adversarial documents in realistic workflows, including attempts to redirect calls to a different tenant or resource.

Failure diagnosis

Set timeouts, bounded pagination, response-size limits and rate limits by identity and tool. Add circuit breakers for failing upstream services. Return structured errors without stack traces, internal hostnames, SQL fragments or tokens. Use correlation IDs to connect MCP calls to downstream audit records while avoiding unnecessary duplication of sensitive payloads. Monitor denied requests, unusual call frequency, latency and access to sensitive resources.

Rollout and maintenance

Run the server with a dedicated operating-system identity, minimal container image and read-only filesystem where practical. Store credentials in a managed secret store and rotate them. Review tool schemas whenever upstream APIs or permissions change. Maintain an emergency procedure to revoke credentials, disable a dangerous capability and isolate the process. Test the procedure before an incident; an emergency control that has never been exercised may fail when it matters most.

Operational handover

Before handing this capability to an operations team, document the configuration owner, supported versions, dependency map and escalation path. Include the commands or dashboard views needed to verify normal operation, along with the expected values and known limitations. Store configuration in version control, review changes through the normal deployment process and keep a tested rollback procedure. Schedule periodic reviews because upstream components, security requirements and workload patterns change. A short runbook should explain how to identify a failed component, what evidence to collect, which actions are safe to retry and when to escalate. Test that runbook during a maintenance exercise rather than waiting for an outage. Finally, measure the result against a baseline: reliability improvements should be visible in error rates, latency, resource consumption, recovery time or reduced manual work. This makes the implementation maintainable after the original developer has moved to another project.

Share this article

Written by

ProdCraft

ProdCraft publishes practical engineering guides on DevOps, Kubernetes, Docker, Linux, databases, cloud and LLMs — written for engineers who ship.

227 articles View profile

The weekly ops & AI brief

One email a week with the best new guides, tools and incident write-ups. No spam, unsubscribe anytime.

Leave a Reply

Your email address will not be published. Required fields are marked *