2026Author
Winnow
Feeding raw documents to a model is expensive on tokens and quietly unsafe, because a document can carry instructions that hijack the model before you ever read them.
The result
A Model Context Protocol server written from scratch with no SDK, speaking JSON-RPC 2.0 over stdio, that compacts documents to Markdown (25 to 75% fewer tokens) and scans them for prompt injection before they reach the model.
Winnow is an MCP server built by hand in Python, no SDK involved. It implements the protocol directly as JSON-RPC 2.0 over stdio and connects to Claude as a tool. Its job is to sit between a document and the model: it compacts the document to Markdown to save tokens, and it scans that content for prompt-injection attempts before any of it is handed to the model.
- Protocol
- JSON-RPC 2.0
- SDK
- None
- Token reduction
- 25-75%
- Guardrail
- Injection scan
Architecture
Claude
calls Winnow as a tool
JSON-RPC 2.0 over stdio
no SDK
Winnow MCP server
Source document
loaded
Compact to Markdown
25 to 75% fewer tokens
Prompt-injection scan
before the model sees it
Clean content to model
Claude calls Winnow as a tool. The request arrives as JSON-RPC 2.0 over stdio, handled by a server that implements the Model Context Protocol directly rather than through an SDK. Winnow loads the source document and compacts it to Markdown, which is where the 25 to 75% token reduction comes from. The injection scan runs on that content before anything is returned, so the check happens while the material is still just data to the server and has not yet become instructions the model might obey. Only the cleaned content goes back to Claude.
Key decisions and trade-offs
No SDK, protocol implemented by hand
Writing JSON-RPC 2.0 over stdio directly, instead of importing an MCP SDK, meant understanding the protocol at the wire level: how a tool advertises itself, how requests and responses are framed, where errors go. An SDK would have been faster to stand up, but it also hides the exact contract, and for a project meant to demonstrate how MCP actually works, hiding the contract defeats the purpose.
Scan for prompt injection before the model sees the document
The order matters more than the scanner. Once content reaches the model it can be interpreted as instructions, so any check that runs after that point is already too late. Scanning while the document is still inert data on the server side is the only placement that can actually prevent an injected instruction from being acted on.
Compact to Markdown as a token-cost decision
Stripping a document down to Markdown before it enters the context window cuts 25 to 75% of the tokens, which is real money and real context budget on every call. Markdown is the sweet spot: structured enough to preserve meaning, lean enough to drop the markup a model does not need.
Results
- JSON-RPC 2.0 over stdio, implemented with no SDK.
- Document compaction to Markdown yields 25 to 75% fewer tokens.
- Prompt-injection scan runs before content reaches the model.
- Connects to Claude as a tool.