Washington | 27°C (few clouds)
Model Context Protocol (MCP) for Developers – A Practical Overview

Simplify AI tool integrations with the Model Context Protocol

A hands‑on look at MCP, the standard that lets Claude and other LLMs talk to external services without bespoke code.

When you start building AI‑driven assistants, you quickly discover that every new service – a calendar, a database, a custom calculator – seems to demand its own quirky integration code. The Model Context Protocol, or MCP, was invented to stop that madness. Think of it as a common language that both the model (Claude, for example) and the tool‑provider understand, so you can plug‑in a service and walk away.

MCP lives on two tracks. The first is a thin connector baked straight into the Messages API; you tell the API where your remote server lives, and the model can call it over HTTP. The second track is a client‑side SDK you run yourself – handy when you want to talk to a locally‑hosted tool or need the extra knobs that the simple connector doesn’t expose.

1️⃣ The MCP Connector (in‑API)

With the connector you don’t spin up a separate client process. You just add an mcp_servers entry to your request and list the tools you’d like Claude to see. Under the hood the API does two things: it registers the remote endpoint (URL, auth token, name) and it marshals the tool definitions into a format Claude can understand.

Here’s a minimal Python snippet:

response = client.beta.messages.create(
    model="claude-opus-5",
    max_tokens=1000,
    messages=[{"role": "user", "content": "What tools are available?"}],
    mcp_servers=[{
        "type": "url",
        "url": "https://example-server.modelcontextprotocol.io/sse",
        "name": "example-mcp",
        "authorization_token": "YOUR_TOKEN"
    }],
    tools=[{"type": "mcp_toolset", "mcp_server_name": "example-mcp"}],
    betas=["mcp-client-2025-11-20"]
)

Things to remember: the server must be reachable via plain HTTP (or SSE), and the connector only talks to remote endpoints – it won’t reach a local stdio server.

2️⃣ The Client‑Side SDK

If you need more control – say you’re developing a prototype that runs on your laptop, or you want to stream data through stdin/stdout – the SDK is the way to go. It gives you a full MCP session, handles the low‑level protocol, and even wraps raw MCP definitions into Claude‑ready tool objects.

Typical usage looks like this:

from anthropic.lib.tools.mcp import async_mcp_tool
from mcp import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client

server_params = StdioServerParameters(command="mcp-server")
async with stdio_client(server_params) as (read, write):
    async with ClientSession(read, write) as mcp_client:
        await mcp_client.initialize()
        tools_result = await mcp_client.list_tools()
        runner = client.beta.messages.tool_runner(
            model="claude-opus-5",
            max_tokens=1024,
            messages=[{"role": "user", "content": "What tools are available?"}],
            tools=[async_mcp_tool(tool, mcp_client) for tool in tools_result.tools]
        )

The SDK does the heavy lifting: it converts MCP tool descriptions into the JSON blocks the Claude API expects, lets you upload files, and even turns MCP prompts into regular message content.

How a tool call actually flows

Behind the scenes, a call follows four simple steps:

  1. Claude decides a user request matches a tool it knows about.
  2. It emits an mcp_tool_use block that contains the server name, tool name, and the arguments.
  3. The designated MCP server receives that payload, runs the underlying functionality, and packages the outcome.
  4. The result arrives back in the same conversation as an mcp_tool_result block.

If the question is purely factual – something Claude already knows – no tool call is made; the model answers directly.

Controlling what Claude can do

Exposing every method on a remote service is rarely wise. MCP lets you whitelist or blacklist tools through the default_config and per‑tool enabled flags. A common pattern is to start with everything disabled, then turn on only the read‑only actions you need, keeping destructive calls like delete_all_events safely out of reach.

Three control styles are useful:

  • Enable everything – omit the config and let all tools be callable.
  • Allowlist – set default_config.enabled = false and explicitly enable a handful of safe tools.
  • Denylist – keep most tools on, but set enabled = false on the risky ones.

When you have a massive toolbox, combine an allowlist with defer_loading. That way the server only sends tool descriptions when Claude explicitly asks, keeping the prompt size small.

Some practical tips

  • You can attach several servers in a single request – just add multiple entries to mcp_servers and pair each with its own mcp_toolset.
  • Pair defer_loading with the built‑in “Tool search” helper if you need to browse a large catalog without flooding the model with noise.
  • The connector works in the normal messages endpoint, so you don’t need a separate “MCP‑only” route.

All in all, MCP turns what used to be a dozen lines of custom glue code into a handful of declarative JSON snippets. Whether you’re building a quick prototype or a production‑grade assistant, it gives you a clean, reusable contract between the model and the world outside.

Comments 0
Please login to post a comment. Login
No approved comments yet.

Editorial note: Nishadil may use AI assistance for news drafting and formatting. Readers can report issues from this page, and material corrections are reviewed under our editorial standards.