Model Context ProtocolMCP Python SDK 2.2 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
27 small wins to finish your pathNext lesson →

Integrations: real client, model and transport

Integrations are the real backends that replace each stand-in this course ran on: a client over a real transport, a real model, and a deployed server.

Last updated: 28 Sep, 2026 · MCP 2.2

Every runnable lesson so far used an in-process Client(mcp) and, in part 6, a stand-in that chose tools from the message. Both are keyless and deterministic, which is why they run here. This lesson maps each one to the version you run in production, and shows that the swap changes one line, not the agent.

What you ran on, and its real version

What you ran onA real oneThe package or transport
Client(mcp), a server objectA client over stdio or Streamable HTTPStdioServerParameters or a URL, from mcp (the stdio and Streamable HTTP lessons)
The stand-in choose_toolA model that reads tool descriptions and returns tool callsanthropic or openai, fed by to_model_tools (the MCP-tools-to-a-model lesson)
A local python shop.pyA deployed, remote MCP serverStreamable HTTP behind a host name, with transport_security
The ORDERS dictA real databaseA driver opened once in the lifespan (the Lifespan lesson)

Swapping the client to stdio

The agent from the MCP-tools-to-a-model, stand-in-model and agent-loop lessons talks to a client. It never cares how that client connects, so moving off the in-process client changes only the argument you pass to Client:

python
# in memory, as the earlier lessons ran it:
async with Client(mcp) as client:
    ...

# the same agent, now over stdio:
server = StdioServerParameters(command=sys.executable, args=["shop.py"])
async with Client(server) as client:
    ...

Here is the agent running unchanged over stdio, against shop.py started as a child process:

Exampledesk_stdio.py over stdio
python desk_stdio.py
  • The agent code did not change. Only the object handed to Client did, from mcp to StdioServerParameters.
  • The server ran as its own process, the way a desktop host launches it, and gave the same answers as in memory.

Swapping in a real model

The stand-in returned a name and arguments. A real model returns the same thing from a tool call, so it drops into choose_tool's place. This needs a key and a current model id, so it is shown, not run:

python
from anthropic import Anthropic

client_llm = Anthropic()  # reads ANTHROPIC_API_KEY
MODEL = "..."              # a current model id, read from config, not hardcoded here


def choose_tool(message, model_tools):
    # Anthropic takes name, description and input_schema at the top level (lesson 20)
    tools = [t["function"] for t in model_tools]
    reply = client_llm.messages.create(model=MODEL, max_tokens=512, tools=tools,
                                        messages=[{"role": "user", "content": message}])
    for block in reply.content:
        if block.type == "tool_use":
            return {"name": block.name, "arguments": block.input}
    return None

The rest of run_agent stays as it is: it still lists the tools, calls the chosen one over MCP, and reads is_error. The model decides which tool to call; the server still decides what each tool is allowed to do.

Where real backends replace the stand-ins

  • The client swaps to stdio or Streamable HTTP with no change to the agent loop.
  • The stand-in swaps to a real model that reads the same tool list.
  • The ORDERS dict swaps to a database opened once in the lifespan.
Watch out
A real model is not deterministic and may call a tool you did not expect. Keep the offered tool list tight and enforce every rule in the server, as the refund resolver does, rather than trusting the model.
Try it yourself
  • Change desk_stdio.py to the HTTP client from the Streamable HTTP lesson, start python shop.py, and run the same messages.
  • Add a real model call from LLM Fundamentals, using to_model_tools, behind an if os.environ.get("ANTHROPIC_API_KEY") guard.
  • Replace the ORDERS dict with a small SQLite database opened in a lifespan (the Lifespan lesson).

Every expert started right here.