mcp-server
# MCP Server
An SDK-first MCP (Model Context Protocol) learning and production-readiness
project built in Python with the official MCP SDK.
The goal is to understand MCP deeply while building a practical MCP server that
can serve as a real integration-testing target for other AI/agent codebases.
## Status
- **Phase 6 — LLM / Agent Integration** (current): a provider-agnostic agent
(`examples/agent.py`) that discovers tools, selects them, invokes them, and
feeds results back (demoed with a deterministic mock LLM).
- **Phase 5 — MCP Client**: an example client (`examples/mcp_client.py`) that
connects over stdio and exercises the full lifecycle (tools, resources,
prompts, failures).
- **Phase 4 — Prompts**: reusable prompt templates (`profile_review`,
`analyze_profiles`, `server_overview`).
- **Phase 3 — Resources**: resources exposed by URI — application metadata
(`mcp://server/info`), static config (`mcp://server/config`), and profile data
(`data://profiles`, `data://profile/{user_id}`).
- **Phase 2 — Tools**: deterministic MCP tools (`add`, `multiply`, `echo`,
`get_user_profile`, `fail`) alongside the Phase 1 `health` tool.
- **Phase 1 — Minimal MCP Server**: a small, runnable server using the
`MCPServer` abstraction over stdio, with a minimal `health` capability.
See [`docs/roadmap.md`](docs/roadmap.md) for the full plan,
[`docs/mcp-basics.md`](docs/mcp-basics.md) for MCP concepts,
[`docs/tools.md`](docs/tools.md) for tools, [`docs/resources.md`](docs/resources.md)
for resources, [`docs/prompts.md`](docs/prompts.md) for prompts,
[`docs/client.md`](docs/client.md) for the client lifecycle, and
[`docs/agent.md`](docs/agent.md) for agent integration.
## Requirements
- Python 3.11+
- [uv](https://docs.astral.sh/uv/)
## Setup
```bash
uv sync
```
This creates a virtual environment and installs the MCP SDK and dev tools
(including pytest).
## Running the server
```bash
uv run mcp-server
```
The server starts over **stdio** — the appropriate transport for local
development. It stays alive until the connecting client closes the stream. To
interact with it you need an MCP client (see the MCP basics doc).
## Running the example client
```bash
uv run python examples/mcp_client.py
```
The client launches the server over stdio and demonstrates the full lifecycle:
initializing, listing/calling tools, listing/reading resources, listing/getting
prompts, and handling failures. See [`docs/client.md`](docs/client.md).
## Running the example agent
```bash
uv run python examples/agent.py
```
The agent discovers the server's tools, selects them for a user request, invokes
them, and feeds the results back — running several tool calls in one session. It
is provider-agnostic and ships a deterministic `MockLLM`, so it runs with no API
key. See [`docs/agent.md`](docs/agent.md).
## Running the tests
```bash
uv run pytest
```
## Project layout
```
src/mcp_server/ # MCP server implementation
server.py # server construction, health tool, stdio entry point
tools.py # deterministic tools (business logic + registration)
resources.py # resources exposed by URI (data + registration)
prompts.py # reusable prompt templates (messages + registration)
examples/
mcp_client.py # example client driving the full lifecycle over stdio
agent.py # example agent (discover/select/call tools, mock LLM)
tests/
unit/ # business-logic unit tests
integration/ # end-to-end tests (real MCP client over stdio)
docs/ # roadmap and concept documentation
```
## How a client talks to this server
```
Application / Host
↓
MCP Client
↓
MCP Protocol
↓
MCP Server
↓
Application logic
```
See [`docs/mcp-basics.md`](docs/mcp-basics.md) for a deeper explanation.
TDQS
Scored across 6 tools
Each tool has a clearly distinct purpose: health checks connectivity, add and multiply perform arithmetic, echo returns text, get_user_profile fetches a profile, and fail deliberately raises an error. There is no meaningful overlap between any pair of tools.
Most tools use short, lowercase names like add, multiply, echo, and fail, but health is a noun rather than an action and get_user_profile uses a verb_noun pattern. The naming is readable overall but mixes conventions.
Six tools is a reasonable size for a small server, and each tool contributes something distinct. However, the set feels like a grab bag of unrelated utilities rather than a tightly scoped collection.
There is no coherent domain that the tool set fully covers: the math tools only support add and multiply, and the user profile surface has only a single get operation with no list, create, update, or delete. This makes the overall surface feel incomplete and ad hoc.