Skip to content

Latest commit

 

History

History
139 lines (106 loc) · 4.4 KB

File metadata and controls

139 lines (106 loc) · 4.4 KB

Cheatsheet

One page. Written against MCP 2026-07-28 / Python SDK mcp 2.0.


Commands

make setup                          # create the workshop virtualenv
make check                          # verify this machine is ready
make server                         # run the MCP server over stdio
make client                         # module 4a — client, no LLM
make agent Q="..."                  # module 4b — the hand-written loop
make web                            # module 5  — browser UI on :7932
make inspector                      # MCP Inspector (needs Node 22.19+)
make jsonrpc METHOD=tools/list      # raw JSON-RPC

./scripts/raw_jsonrpc.sh tools/call '{"name":"get_weather","arguments":{"city":"Tokyo"}}'

One virtualenv: .venv runs the MCP 2 server, clients, agent loop, and web UI.


Server

from typing import Annotated, Literal
from mcp.server import MCPServer
from pydantic import BaseModel, Field

mcp = MCPServer("travel", instructions="What this server is for.")

class Weather(BaseModel):                       # -> outputSchema
    city: str
    temperature_c: int = Field(description="Degrees Celsius.")

@mcp.tool()                                     # model-controlled
def get_weather(
    city: Annotated[str, Field(description='City name, e.g. "Tokyo".')],
    days: Annotated[int, Field(ge=1, le=7)] = 3,
    units: Literal["celsius", "fahrenheit"] = "celsius",
) -> Weather:
    """Description the model reads when choosing this tool."""
    raise ValueError("Readable message")        # -> isError result, not a crash

@mcp.resource("travel://destinations")          # app-controlled
def catalog() -> str: ...

@mcp.prompt()                                   # user-controlled
def plan_a_trip(city: str, nights: int = 3) -> str: ...

mcp.run(transport="stdio")                      # or "streamable-http"

Docstring Args: sections do not become parameter descriptions — use Annotated[..., Field(description=...)].

Client

from mcp import Client, StdioServerParameters, stdio_client

async with Client(stdio_client(StdioServerParameters(command=..., args=[...]))) as c:
    c.protocol_version                          # "2026-07-28"
    tools = (await c.list_tools()).tools
    r = await c.call_tool("get_weather", {"city": "Tokyo"})
    r.structured_content                        # typed dict
    r.content[0].text                           # text block
    r.is_error                                  # errors are results
    await c.read_resource("travel://destinations")
    await c.get_prompt("plan_a_trip", {"city": "Tokyo", "nights": "4"})

MCP tools → OpenAI tools

[{"type": "function",
  "function": {"name": t.name,
               "description": t.description or "",
               "parameters": t.input_schema}}   # snake_case in v2
 for t in tools]

Browser app

from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from agent_raw import run

async def chat(request):
    question = (await request.json())["question"]
    calls = []
    answer = await run(question, lambda name, args: calls.append((name, args)))
    return JSONResponse({"answer": answer, "tools": calls})

app = Starlette(routes=[Route("/api/chat", chat, methods=["POST"])])

v1 → v2

v1 v2
from mcp.server.fastmcp import FastMCP from mcp.server import MCPServer
stdio_client + ClientSession + initialize() Client(...)
tool.inputSchema / result.isError tool.input_schema / result.is_error
initialize handshake none — _meta on every request
server → client sampling / roots MRTR (resultType: "input_required")
HTTP+SSE transport Streamable HTTP

Raw JSON-RPC envelope

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

Methods: server/discover · tools/list · tools/call · resources/list · resources/read · prompts/list · prompts/get

Primitives

Controlled by Like
Tools the model POST
Resources the application GET
Prompts the user a slash command