Skip to main content
Glama

mcp-test — learning the Model Context Protocol

A minimal MCP server in Python: one tool that returns the current temperature for a city. Plus a client that calls it, so you can see both halves of the protocol as plain Python.

No API key required — it uses Open-Meteo, which is free and needs no signup.

server.py        the MCP server — one tool, get_temperature
test_client.py   a real MCP client that launches the server over stdio

Run it

Requires uv and Python 3.12+.

uv run test_client.py

That launches server.py as a subprocess, connects over stdio, and walks through four things: tool discovery, a successful call, a recoverable error, and schema validation rejecting a bad argument.

Related MCP server: MCP Weather Server Demo

⚠️ This uses SDK v2, not v1

The MCP Python SDK is at v2.x, a major rework. Most tutorials online are v1 and will not run against it:

v1 (most tutorials)

v2 (this repo)

from mcp.server.fastmcp import FastMCP

from mcp.server import MCPServer

ClientSession + stdio_client

from mcp import Client (one class)

tool.inputSchema

tool.input_schema (snake_case)

What the code demonstrates

The three primitives, split by who decides to use them: tools (the model decides), resources (the application decides), prompts (the user decides). This server exposes a tool, because "get the temperature" is a model-driven action.

Your function is the contract. From async def get_temperature(city: str) -> Temperature, the SDK derives the tool name, the description (from the docstring), the input schema (from the type hints), and the output schema (from the return annotation). No JSON Schema is written by hand — and the type hints are enforced, so a client sending city=42 is rejected before the function runs.

Two results, two audiences. Every call returns content (text the model reads) and structured_content (typed data the application reads). Returning a Pydantic model rather than a string is what makes the second one useful.

Errors: raise, never return. A ToolError comes back with is_error=True and your message where the model can read it, so the model can retry. A returned error string has is_error=False — the model would read it as the answer.

stdio means stdout is the wire. The client launches the server as a subprocess and speaks JSON-RPC over its stdin/stdout, so a stray print() in a server corrupts the protocol stream. Use logging, which writes to stderr.

Try it in the MCP Inspector

A browser UI over your server, showing the raw protocol messages (needs npx):

uv run mcp dev server.py

Connect it to Claude Code

claude mcp add weather -- uv run --directory "$PWD" server.py

Available Tools

1 tool
get_temperatureA

Get the current air temperature for a city, by name.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
cityYesThe place name as resolved by the geocoder
countryYesCountry the place was resolved to
latitudeYes
longitudeYes
observed_atYesLocal observation time, ISO 8601
temperature_cYesCurrent air temperature in Celsius

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

There are no annotations, so the description carries the burden. 'Current' conveys that the result is a real-time or latest reading, and 'get' implies a read-only operation. However, it does not disclose units, freshness behavior, or any other side-effect-related details beyond the basic action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one short, front-loaded sentence with no redundant words or filler. Every word contributes to understanding what the tool does.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a simple one-parameter look-up tool with an output schema available. The description covers the input semantics and the result type sufficiently; return-value details are reasonably delegated to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does add useful semantics by specifying that the 'city' parameter is a city name, distinguishing it from coordinates or IDs. For a single-parameter tool, this is sufficient meaningful guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Get') and resource ('current air temperature') plus the input criterion ('for a city, by name'). It clearly states what the tool does and leaves no ambiguity about its scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied by the description: call this when you need the current air temperature for a named city. However, it provides no explicit when-to-use guidance, exclusions, or alternatives, so the guidance is minimal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 1 tool updatev0.1.0
    • First observedget_temperature

TDQS

A3.9/5.0
Disambiguation5/5

Only one tool exists, so there is no possibility of overlapping purposes or misselection. The single get_temperature action is completely unambiguous.

Naming Consistency5/5

The one tool uses a clear get_ + noun naming convention. There are no competing conventions or mixed styles to create inconsistency.

Tool Count2/5

A single tool is on the 'too few' end of the scale, making the server feel like a minimal stub rather than a useful service. Unless the intended purpose is literally only a current temperature lookup, this is insufficient.

Completeness2/5

For a temperature/weather-related domain, the surface lacks related operations such as unit selection, forecast, geocoding, or validation. The single lookup creates a dead end and leaves obvious gaps for broader temperature use cases.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jonathan-daidai/mcp-test'

If you have feedback or need assistance with the MCP directory API, please join our Discord server