AI Codex
Agents & ToolsHow It Works

Connecting Claude Agents to Production Systems with MCP

In brief

The MCP connector lets a Claude agent reach live production systems — CRMs, databases, internal APIs — at runtime, without you building custom tool integrations for each one. Here's how to structure that connection safely and what breaks when you don't.

Contents

Sign in to save

Model Context Protocol (MCP) is a standard for connecting AI agents to external systems. Claude supports it natively via the MCP connector in the Messages API and as a built-in capability in Claude Managed Agents. As of February 2026, the connector is generally available — no beta header required.

This guide covers the implementation decisions that matter when you're connecting agents to production systems: authentication, permission scoping, error handling, and the failure modes that show up in real deployments.

What MCP gives you

Without MCP, connecting Claude to an external system means writing a custom tool — a function that calls the API, handles auth, formats the response, and returns structured data. That's one tool per integration.

MCP lets external systems expose their own tools through a standard server interface. Claude connects to the MCP server at session time and discovers what tools are available. You configure the connection; the tool definitions come from the server.

For a single-integration agent this barely matters. For an agent that needs to touch five systems — a CRM, a ticketing tool, a database, a docs platform, and an internal API — MCP eliminates five separate tool implementations.

Connecting to an MCP server in Claude Managed Agents

In Claude Managed Agents, MCP servers are attached at agent creation time:

const agent = await client.beta.agents.create({
  model: "claude-opus-4-7-20260416",
  name: "Sales Research Agent",
  system: "You are a sales research assistant with access to our CRM and knowledge base.",
  mcp_servers: [
    {
      type: "url",
      url: "https://crm.internal.example.com/mcp",
      name: "CRM",
      authorization_token: process.env.CRM_MCP_TOKEN
    },
    {
      type: "url",
      url: "https://docs.internal.example.com/mcp",
      name: "KnowledgeBase",
      authorization_token: process.env.DOCS_MCP_TOKEN
    }
  ]
});

The agent discovers available tools from each server when a session starts. Claude's system prompt sees the tool names and descriptions from the MCP server's manifest.

Connecting via the Messages API

For agents built directly on the Messages API, attach MCP servers in the request:

const response = await client.beta.messages.create({
  model: "claude-sonnet-4-6-20260217",
  max_tokens: 4096,
  mcp_servers: [
    {
      type: "url",
      url: "https://crm.internal.example.com/mcp",
      name: "CRM",
      authorization_token: process.env.CRM_MCP_TOKEN
    }
  ],
  messages: [{ role: "user", content: "Pull the last 30 days of deals for the enterprise segment." }]
}, {
  headers: { "anthropic-beta": "mcp-client-2025-04-04" }
});

Authentication patterns

Each MCP server connection takes an authorization_token passed as a Bearer token. In practice, this maps to three patterns:

Static API key. The MCP server validates a long-lived token. Simplest to set up, hardest to rotate. Fine for internal services with tight network controls. Pass the token as an environment variable; never hardcode it.

Short-lived token per session. Before creating each session, fetch a fresh token from your auth system and pass it in. The token expires with the session. Better for external-facing deployments where you want clear session boundaries.

// Fetch a scoped token before each session
const token = await getSessionToken({
  userId: user.id,
  scopes: ["crm:read", "tickets:write"],
  ttl: 3600
});

const session = await client.beta.sessions.create({
  agent: agentId,
  environment_id: envId,
  // Override the agent's default MCP config with a session-scoped token
  mcp_servers: [
    {
      type: "url",
      url: "https://crm.internal.example.com/mcp",
      name: "CRM",
      authorization_token: token
    }
  ]
});

OAuth. For MCP servers that support it, OAuth lets the agent act on behalf of a specific user with that user's permissions. The MCP server handles the OAuth flow; you pass the resulting access token as authorization_token.

Scoping permissions

The most common production mistake: attaching a full-access token when the agent only needs read access.

Set the minimum scope the agent needs for its task. If the agent reads deal data to generate reports, give it crm:read — not crm:admin. This matters for two reasons:

Blast radius. If the agent misinterprets a task or a user input causes unexpected tool calls, a read-only token limits the damage.

Prompt injection. An agent that fetches data from external sources (web pages, emails, documents) can be manipulated by content embedded in that data — instructions disguised as normal content. A narrow-scoped token means a successful injection can only do what the token allows.

Structure your MCP servers to expose scoped surfaces rather than full system access. A CRM server might expose one tool endpoint for deal reads and a separate one for deal writes, each requiring a different scope.

Error handling

MCP tool calls can fail in ways that don't fail your application — the agent receives the error and decides how to proceed. What you control is what errors look like and how persistent they are.

Surface useful errors. When an MCP tool fails, Claude sees the error message in the tool result. If your MCP server returns "Internal server error", Claude has nothing actionable. Return structured errors with enough context for the agent to try an alternative: "Rate limit reached for crm:search. Try a narrower date range or wait 60 seconds."

Set timeout limits. Long-running MCP tool calls hold up the session. Configure timeouts on your MCP server and in your session environment. An agent waiting indefinitely on a slow tool call will exhaust your session budget.

Handle auth failures explicitly. A 401 from an MCP server should surface as a clear "authentication failed" message, not a generic error. Claude can then tell the user what happened rather than trying to retry indefinitely.

// In your MCP server handler
if (!isValidToken(req.headers.authorization)) {
  return {
    error: {
      code: "auth_failed",
      message: "MCP authorization token is invalid or expired. Re-authenticate to continue."
    }
  };
}

What breaks in production

Tool discovery drift. MCP servers can add, remove, or rename tools without warning. If Claude's system prompt references a tool by name that no longer exists, the agent will try it, get an error, and may hallucinate an alternative. Pin your MCP server versions. Run integration tests that verify tool discovery against each connected server.

Context window pressure. MCP tool results return full payloads. A CRM tool that returns 200 deal records as JSON can consume tens of thousands of tokens in a single tool call. Design MCP tools to return paginated or filtered results. Pass filtering instructions in the tool's description so Claude uses them.

Shared MCP servers in multi-tenant deployments. If multiple users' agent sessions connect to the same MCP server, the server must enforce tenant isolation — Claude cannot do this. The MCP server is responsible for ensuring each token only accesses the right tenant's data.

Logging and observability

MCP tool calls appear in the Managed Agents event stream as ordinary agent.tool_use and agent.tool_result events. Log these — they tell you which tools the agent actually called, with what inputs, and what came back. This is your audit trail for production debugging.

For the Messages API, tool use and results appear in the response content blocks. Log the full request and response at the application layer.


This guide is based on the April 22, 2026 Anthropic blog post "Building agents that reach production systems with MCP" and the MCP connector documentation.

Related tools

Weekly brief

For people actually using Claude at work.

Each week: one thing Claude can do in your work that most people haven't figured out yet — plus the failure modes to avoid. No tutorials. No hype.

No spam. Unsubscribe anytime.

What to read next

All articles →