MCP

2 min read
On trails:AGPROTOstep 2/4

MCP is agent to tool communication. Anthropic open-sourced it in November 2024 as a standard for connecting AI applications to the systems where data lives, and it standardizes how a model gets context and calls toolsTool useFunction calling gives the model hands: it asks, and code does the work.Opens in a new tab. A tool written once as an MCP server can be reused by any client that speaks MCP.

Client, protocol, server

An agent application, the host, holds an MCP client. The client talks JSON-RPC over stdio or Streamable HTTP to an MCP server, which reaches the data or API behind it. HOST: THE AGENT APP MCP client one per server JSON-RPC 2.0 stdio or Streamable HTTP MCP server tools, resources, prompts Data, APIs
The host creates one client per server.

The host is the agent application. It creates one MCP client per server, and each client keeps a connection to exactly one server. Messages are JSON-RPC 2.0. A server offers three kinds of thing: tools (functions the model can call), resources (data for context) and prompts (reusable templates). The steps of one tool call are in the MCP lifecycleMCP lifecycleDiscovery, order, delivery: how one tool call moves between client and server.Opens in a new tab.

Transports

The current spec defines two. stdio is for a local server: the client launches it as a subprocess and they exchange newline-delimited messages. Streamable HTTP is for a remote one: every message is an HTTP POST to a single MCP endpoint, and the reply is either one JSON object or an SSE stream scoped to that request.

So SSE is still in the picture, but only as the streaming format inside Streamable HTTP. The older HTTP+SSE transport from 2024 is deprecated, and new servers should not adopt it.

In Python

server.pyPython
from mcp.server import MCPServer mcp = MCPServer("Weather")  @mcp.tool()def get_weather(city: str) -> str:    """Current weather for a city."""    return f"Sunny in {city}"  if __name__ == "__main__":    mcp.run(transport="streamable-http")

The decorator registers the function, and its type hints and docstring become the tool’s schema and description. The last line picks the transport.

client.pyPython
from langchain.agents import create_agentfrom langchain.mcp import MCPAdapter  async def main():    async with MCPAdapter("http://localhost:8000/mcp") as adapter:        tools = await adapter.list_tools()        agent = create_agent("claude-sonnet-5", tools)        return await agent.ainvoke(            {"messages": [{"role": "user", "content": "Weather in Colombo?"}]}        )

On the client side, list_tools() asks the server for its menu and the tools go straight to the agent. LangChain marks langchain.mcp as beta, so expect the API to move.

The catch

MCP is only the protocol for exchanging context. It does not decide how the application uses the model or manages that context, and it does not make a tool safe. The spec asks for a human who can deny tool calls (see human in the loopHuman in the loopA pause in the agent's decision, where a person approves before a high-risk action runs.Opens in a new tab), and a server is still code you are choosing to trust (see secure toolingSecure toolingTools are where an agent touches the world, so each one is described, versioned and watched.Opens in a new tab). For agent to agent, see A2AA2A, ACP and AG-UIThe other three protocols: agent to agent, the one that merged, and agent to user.Opens in a new tab.


Sources