MCP Tool Server
by nuvolalabs
README.md
# MCP Tool Server
A **Model Context Protocol (MCP)** server implemented from scratch over stdio
using **JSON-RPC 2.0** — plus a tiny client to drive it. No SDK, no
dependencies: ~350 lines that show exactly how MCP handshakes and tool calls
work on the wire.
## Why MCP
MCP is the emerging standard for connecting LLM agents to external tools and
data. This repo demonstrates the protocol mechanics — `initialize`,
`notifications/initialized`, `tools/list`, `tools/call`, `ping` — so an agent
(Claude, Copilot, custom) can discover and invoke tools over a pipe.
## Architecture
```
MCP client ──JSON-RPC over stdio──▶ mcp_server
(client.py) newline-delimited ├── protocol.py (errors, envelopes)
{jsonrpc,id,method} ├── server.py (dispatch + stdio loop)
└── tools.py (echo, add, sqrt, now_utc)
```
## Quickstart
```bash
# run the demo client against a live server subprocess
PYTHONPATH=src python3 client.py
# run the server directly (speak JSON-RPC on stdin)
PYTHONPATH=src python3 -m mcp_server
# tests (in-process dispatch + a real spawned-subprocess handshake)
python3 tests/test_mcp_server.py
```
## Protocol coverage
| Method | Behaviour |
|---|---|
| `initialize` | Negotiates protocol version, returns capabilities + serverInfo |
| `notifications/initialized` | Marked initialized; **no response** (correct notification semantics) |
| `tools/list` | Returns each tool's `name`, `description`, `inputSchema` |
| `tools/call` | Runs the handler; **tool errors return in-band** (`isError: true`) |
| `ping` | Liveness check |
Malformed JSON → `-32700` parse error; unknown method → `-32601`; bad params →
`-32602`. Notifications never get a reply, as the spec requires.
## Design notes
- **Handler errors never kill the server** — they're converted to JSON-RPC errors
or in-band tool results, so one bad call can't take the transport down.
- **Injectable streams** (`serve(lines=..., stdout=...)`) make the stdio loop
unit-testable without spawning processes; a separate test does the real spawn.
- **Tool schemas are JSON Schema**, matching MCP's `inputSchema` contract.
## Skills demonstrated
`Model Context Protocol (MCP)` · `JSON-RPC 2.0` · `stdio transport` · `tool schemas`
· `protocol error handling` · `subprocess integration testing` · `Python packaging`
## License
MIT
TDQS
B3.2/5.0
Scored across 4 tools
Disambiguation5/5
Each tool has a clearly distinct operation: echoing, addition, square root, and current UTC time. There is no realistic overlap or ambiguity between them.
Naming Consistency4/5
All names are short, lowercase, and readable, with only now_utc using an underscore. The set is mostly consistent, though it does not follow a single verb_noun convention.
Tool Count5/5
Four tools is a reasonable size for a small utility server, and each tool covers a distinct basic operation. None feels redundant or out of place.
Completeness3/5
The surface is usable but thin: math support only includes add and sqrt, missing subtract/multiply/divide, and time support only exposes current UTC time. These are notable gaps for a general utility toolset.
Maintenance
ActivitySlowing
ResponsivenessNo recent community issues