mcp-document-chat
Exposes a document store over MCP tools, resources, and prompts for reading, editing, summarizing, and formatting documents in a chat interface.
README
MCP Document Chat
A command-line chat client for Claude that reaches its capabilities through a
Model Context Protocol server rather than
hard-coded functions. The server exposes a document store over all three MCP
primitives — tools, resources and prompts — and the CLI wires them into a
tool-use loop, @-mention context injection and /-slash commands.
Built with FastMCP and the Anthropic Python SDK.
> /summarize deposition.md
> Tell me about @report.pdf and @plan.md
> Reformat @spec.txt as markdown
Why this exists
Most "chat with an LLM" samples bolt tools directly onto the model call. This one puts an MCP server in between, which is the part worth practising: the server is a separate process that could be swapped, reused by any MCP host (Claude Desktop, an IDE, another agent), and tested on its own.
Attribution
This started from the MCP project in Anthropic's Building with the Claude API course. To keep the record straight:
- Provided by the course — the CLI shell (
core/,main.py), packaging and the original README. The first commit in this repository is that scaffold, unmodified, sogit logshows exactly what was given. - My work — the MCP server and client (
mcp_server.py,mcp_client.py), which the exercise leaves as stubs, plus everything after: the FastMCP migration, the bug fixes described below, the test suite and the tooling.
Architecture
main.py wires config, clients and the CLI together
core/cli.py prompt-toolkit REPL, completion for / and @
core/cli_chat.py expands @mentions, dispatches /commands
core/chat.py the tool-use loop
core/claude.py Anthropic Messages API wrapper
core/tools.py collects MCP tools, executes tool_use blocks
mcp_client.py async MCP client over stdio
|
| stdio (JSON-RPC)
v
mcp_server.py FastMCP server over the document store
The server exposes:
| Primitive | Name | Purpose |
|---|---|---|
| Tool | read_doc_contents |
Return a document's contents |
| Tool | edit_doc |
Exact-match string replacement in a document |
| Resource | docs://documents |
The document index |
| Resource | docs://documents/{doc_id} |
A single document |
| Prompt | format |
Rewrite a document as markdown |
| Prompt | summarize |
Summarize a document in three sentences |
Resources back the @-mention autocompletion, prompts back the /-commands,
and tools are what Claude calls during the loop.
Setup
Requires Python 3.10+ and an Anthropic API key.
git clone <this-repo>
cd mcp-document-chat
cp .env.example .env # then add your ANTHROPIC_API_KEY
uv sync # or: pip install -e .
uv run main.py # or: python main.py
.env holds ANTHROPIC_API_KEY, CLAUDE_MODEL and USE_UV; see
.env.example. .env is gitignored — do not commit a real key.
Usage
| Input | Effect |
|---|---|
plain text |
Ordinary chat turn; Claude may call the MCP tools |
@doc_id |
Inlines that document's contents as context |
/format <doc_id> |
Runs the format prompt from the server |
/summarize <doc_id> |
Runs the summarize prompt from the server |
Tab completes both document ids and command names. Ctrl+C or Ctrl+D exits.
Development
uv sync --all-groups
uv run pytest # 27 tests, no network or API key needed
uv run ruff check .
uv run ruff format .
The server tests drive it through FastMCP's in-memory client transport, so the real MCP request path is exercised without spawning a subprocess.
Notes on the implementation
Beyond completing the stubs, working through this surfaced a handful of defects in the scaffold, each fixed in its own commit with a regression test:
- Tool errors crashed the session. The handler for a failed tool call read
a variable that only gets bound by the call that had just raised, so every
transport failure surfaced as
UnboundLocalErrorinstead of being reported back to Claude. - A bare
/formatkilled the REPL. The command parser indexed the argument without checking it was there, and the loop only caughtKeyboardInterrupt. - Document completion never fired. The completer treated resource ids as
dicts when they are strings, so its guard was silently false for every
document — and would have raised
TypeErrorfor any id containing "id". - The
formatprompt was malformed. An unclosed<document_idtag, an instruction that trailed off mid-sentence, and a reference to anedit_documenttool that is registered asedit_doc. /summarizewas documented but never implemented, so the first command a new user copied out of the README failed.
The server was also migrated from FastMCP 1.x (the snapshot vendored into the
MCP Python SDK as mcp.server.fastmcp) to the standalone fastmcp package,
including the move from Field() defaults to
Annotated[str, Field(description=...)], which the FastMCP docs prefer.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.