mcp-document-chat

mcp-document-chat

Exposes a document store over MCP tools, resources, and prompts for reading, editing, summarizing, and formatting documents in a chat interface.

Category
Visit Server

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, so git log shows 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 UnboundLocalError instead of being reported back to Claude.
  • A bare /format killed the REPL. The command parser indexed the argument without checking it was there, and the loop only caught KeyboardInterrupt.
  • 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 TypeError for any id containing "id".
  • The format prompt was malformed. An unclosed <document_id tag, an instruction that trailed off mid-sentence, and a reference to an edit_document tool that is registered as edit_doc.
  • /summarize was 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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured