new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

MCP · Building servers and clients · all subjects

client: python

10 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Python MCP client: Client + stdio_client + StdioServerParameters

In the Python MCP SDK (2.0.0 or higher), a client is built from three pieces: `StdioServerParameters(command=..., args=[...])` is pure configuration, `stdio_client(params)` turns it into a stdio transport, and `Client(transport)` opens that transport. Typical usage: `async with Client(stdio_client(server_params(sys.argv[1]))) as client:`. Imports are `from mcp import Client, StdioServerParameters` and `from mcp.client.stdio import stdio_client`.

Python client connection lifecycle is the async with block

For the Python MCP `Client`, the `async with` block is the entire connection lifecycle: entering it launches the server subprocess and negotiates a protocol version; leaving it disconnects and shuts the subprocess down. There is no connect/close pair to call by hand and nothing to clean up afterwards.

Do not block the event loop with input() in an async client

Because `input()` blocks, an async MCP client chat loop should run it on a worker thread: `query = (await asyncio.to_thread(input, "\nQuery: ")).strip()`. This keeps the event loop free to service the MCP connection while the user types. Catch `EOFError` to exit when standard input closes.

Python MCP client project setup with uv

Create a Python MCP client with `uv init mcp-client`, `uv venv`, activate (`source .venv/bin/activate` or `.venv\Scripts\activate`), then `uv add mcp anthropic python-dotenv`. Run it with `uv run client.py path/to/server.py` for a Python server or `uv run client.py path/to/build/index.js` for a Node server. The Python MCP SDK must be version 2.0.0 or higher.

Python server logging example with logging module

A Python MCP server logs with the standard logging module rather than print: `import logging; from mcp.server import MCPServer; logger = logging.getLogger(__name__); mcp = MCPServer("reports")` and inside an `@mcp.tool()` async function `fetch_report(report_id: str) -> str` call `logger.info("Fetching report %s", report_id)` before returning the result.

Python ClientCredentialsOAuthProvider with streamable_http_client

In Python (`pip install mcp`), import ClientCredentialsOAuthProvider from mcp.client.auth.extensions.client_credentials, construct it with server_url, storage (an object implementing get_tokens/set_tokens/get_client_info/set_client_info returning OAuthToken and OAuthClientInformationFull from mcp.shared.auth), client_id, client_secret and scopes (e.g. "read write"). Then pass the provider as the `auth` of an httpx AsyncClient and give that http_client to `streamable_http_client(url, http_client=...)`, and use `async with Client(transport) as client` with `await client.list_tools()`.

Python PrivateKeyJWTOAuthProvider and SignedJWTParameters

For JWT assertions in Python, build SignedJWTParameters(issuer="my-service", subject="my-service", signing_key=<PEM text>, signing_algorithm="RS256", lifetime_seconds=300) and pass `assertion_provider=jwt_params.create_assertion_provider()` to PrivateKeyJWTOAuthProvider(server_url=..., storage=..., client_id=..., scopes="read write"), both imported from mcp.client.auth.extensions.client_credentials.

Token storage interface required by Python auth providers

Python MCP OAuth providers require a storage object with four async methods: get_tokens() -> OAuthToken | None, set_tokens(tokens: OAuthToken) -> None, get_client_info() -> OAuthClientInformationFull | None, and set_client_info(client_info: OAuthClientInformationFull) -> None. A simple in-memory class holding `tokens` and `client_info` attributes satisfies it.

Python SDK: discovery happens during connect

In the MCP Python SDK, discovery happens while the client connects, and results are then available on the client object. Pseudo-code: `async with Client(stdio_client(server_config)) as client: if client.server_capabilities.tools: app.register_mcp_server(client, supports_tools=True)`.

Python SDK Pydantic already generates 2020-12 schemas

The Python SDK is already compatible with JSON Schema 2020-12. It uses Pydantic for schema generation, which defaults to 2020-12 via the .model_json_schema() method.

Give your agent this brain