Claude Code and MCP servers: how external tools get integrated

Martin

Out of the box, Claude Code can read your filesystem, run shell commands, and edit files. That covers the codebase — but most real engineering work touches more than the codebase. Your database, your issue tracker, your internal API, your CI system. The standard way to wire Claude Code into all of those is the Model Context Protocol (MCP).

This article covers how MCP fits into Claude Code, how you connect a server, and the permission discipline that makes it safe in practice. For a quick definition of the protocol itself, see the MCP glossary entry.

How Claude Code wires MCP servers in

Claude Code reads MCP server configuration from .mcp.json (per project) or your global Claude config. A typical entry looks like this:

{
  "mcpServers": {
    "my-db": {
      "command": "node",
      "args": ["./mcp-servers/db/index.js"],
      "env": { "DATABASE_URL": "postgres://..." }
    }
  }
}

Two transport flavors exist:

  • Local stdio servers. Claude Code spawns the server as a child process and talks to it over stdin/stdout. Fast, simple, and the right choice for anything that runs on the same machine — local databases, scripts, project-specific tools.
  • Remote HTTP / SSE servers. Claude Code connects to a long-running server over the network. Right choice for shared infrastructure: a team-wide issue-tracker bridge, a managed search service, an internal data API.

Once a server is configured and the Claude Code session starts, its tools appear under names like mcp__my-db__list-rows and are callable by the agent like any built-in tool.

What an MCP server exposes

An MCP server can expose three kinds of capabilities:

  • Tools. The most common case — callable functions with typed arguments. create-ticket, list-table-rows, approve-table-row, set-status. Tools are how the agent does things.
  • Resources. Read-only context the server can hand back to the model: file contents, dataset snapshots, schema definitions. Think of it as “stuff the model can request to read.”
  • Prompts. Server-supplied prompt templates that surface as slash commands. Useful for codifying common workflows your team runs frequently.

Most third-party servers focus on tools; resources and prompts are the polish layer.

Concrete use cases

Where MCP pays off most reliably:

  • Your own database. A server that exposes list-rows, read-row, and update-row against your schema lets the agent answer questions like “what’s the status of order 4711?” without you copy-pasting query results into the chat. With the right permission discipline, it can also update records — close tickets, approve rows, set flags.
  • Issue tracker integration. Linear, Jira, GitHub Issues. The agent can create tickets from bug reports, update statuses after fixes, or sync work-in-progress items to a backlog.
  • Internal APIs. Anything you’ve built that has an HTTP surface — a deployment trigger, a feature-flag system, a content store. Wrapping it as an MCP server makes it first-class for the agent without you teaching it curl incantations.
  • Custom workflow tools. Project-specific helpers — code generators, schema migrators, content publishers — that your team uses regularly. As MCP tools they’re discoverable, typed, and permission-managed.

Security: every MCP tool call runs through the auto-classifier

This is the part people miss. An MCP tool is not a free pass. Every call goes through the same auto-classifier that gates built-in tools (see the auto-classifier article for the full picture).

That has two implications:

  1. You don’t need to over-engineer the tool itself with safety prompts. The classifier catches “set status to approved” when the conversation never authorized an approval.
  2. You still need the tool to enforce its own invariants. Don’t rely on the classifier — it’s a second line, not the only line. Validate state transitions, check ownership, return clear error codes (E_INVALID_STATE_TRANSITION, 403_NOT_OWNER, etc.). The classifier and the tool logic are independent defenses precisely because each one can fail.

A real example: an approve-table-row MCP tool that validates the state machine internally. The classifier blocks unauthorized approvals from the conversation side; the tool blocks invalid transitions from the data-integrity side. Both layers exist on purpose.

Permission discipline for production MCP

If your MCP server touches anything that matters, run it with a clear permission strategy:

  • Allowlist the frequent reads. /permissions add for mcp__my-db__list-rows, mcp__my-db__read-row, and similar. Reads are cheap and noisy — having to confirm each one breaks the flow without adding safety.
  • Keep writes explicit. Don’t allowlist mcp__my-db__update-row, mcp__my-db__delete-row, mcp__tracker__create-ticket. Let the classifier and the per-call prompt do their job. The friction is the feature.
  • Scope credentials tightly. The MCP server’s database credentials should match its actual job. Read-only role for a read-only tool. Don’t hand the server a superuser key “just in case.”
  • Log every write. Audit-trail every state-changing tool call. If anything goes sideways, you want to see what happened, not guess.

Bottom line

MCP is what makes Claude Code more than a codebase assistant. It’s the standard, open way to plug the agent into the rest of your stack — database, tracker, internal APIs, whatever custom tools your team runs.

The good news is that the permission and classifier system extends cleanly to MCP tools. The discipline you need is: enforce invariants inside the tool, allowlist only reads, keep writes explicit, scope credentials tightly. Do that, and MCP turns Claude Code from a code editor into a real engineering partner against the whole system — without giving up the safety net.