mcp-winnow
Enables agents to use many MCP servers without context bloat by exposing meta-tools (search, load, call, run_code) that reduce token usage via progressive disclosure and result trimming.
README
Winnow
Keep the grain, drop the bloat.
Winnow (mcp-winnow) is an embedded TypeScript SDK that lets an agent use many MCP servers without context bloat — it winnows away both tool-definition bloat and tool-result bloat, and works the same attended or headless.
Full design + decision log: docs/DESIGN.md. Validation numbers: bench/RESULTS.md (reference surface) and bench/REAL-RESULTS.md (real MCP servers over stdio); reproduce the real hosted MCPs over HTTP with bench/README.md (npm run bench:public).
The idea
- Definition bloat → the model sees ~4 meta-tools (
search_tools,load_tool,call_tool,run_code) instead of hundreds of full schemas. Full defs stay inside the SDK; the agent searches, loads only what it needs, then calls. - Result bloat → every result is trimmed by a JMESPath projection and a hard token cap the agent can only lower — so even a forgotten projection can't leak an unbounded blob.
Measured on a representative surface: ~10× (call) / 26× (exec) end-to-end token reduction; hybrid search 100% recall@8. Against real servers (server-everything + server-filesystem, 27 tools): 90.4% fewer tool-definition tokens, 60–80% off real tool results via the cap — see bench/REAL-RESULTS.md (cd bench && npm i && npm run bench:real). And against real public/hosted MCPs over HTTP — DeepWiki, GitMCP, plus GitHub's hosted MCP folded in: transport + search + auth validated end to end, and ~75% off a real remote doc payload via the cap. In one gh-authed example run (numbers vary with the token's visible toolset and the network), the GitHub catalog pushed the surface to 52 tools across 3 servers for a 97.7% tool-definition reduction (11,137 → 259). Reproduce with npm run bench:public — it folds in GitHub via a gh login or a PAT; see bench/README.md.
Quickstart
npm install
npm run demo # end-to-end: search -> loadTool -> call, with token savings
npm test # core unit + integration tests
npm run typecheck
import { Winnow } from "mcp-winnow";
const client = new Winnow({ upstreams: [/* your MCP server connections */] });
await client.init();
const hits = await client.searchTools("list open pull requests"); // minimal entries + score
const [def] = client.loadTool(hits[0].id); // full schema on demand
const res = await client.call(hits[0].id, { state: "open" }, {
project: "[].{number: number, title: title}", // trim before it hits context
});
Documentation
- Usage guide — task recipes: connecting servers, auth, result-filter projections,
exec, agent integration, the gateway, cache & watch, troubleshooting. - API reference — the
Winnowclass, options, and types. - Config reference — the full
winnow.config.jsonschema. - Examples — what each runnable example demonstrates.
- Design spec — architecture and the why behind every decision.
Status
| Area | State |
|---|---|
| Catalog / progressive disclosure (C1) | ✅ implemented |
| Hybrid search: Orama BM25 + optional embedder + RRF (S1) | ✅ implemented |
| Result-filter: JMESPath + hard cap + base64 stubbing (F1) | ✅ implemented |
Config + ${ENV} interpolation, zod fail-fast (G1) |
✅ implemented |
Public Winnow facade + 4 meta-tool adapter (A2) |
✅ implemented |
| Pluggable upstream + in-memory mock | ✅ implemented |
Real stdio transport (buildUpstreams) |
✅ implemented — verified against the reference server-everything (see examples/real-stdio.ts) |
| Real Streamable-HTTP transport + bearer auth | ✅ implemented + verified live against a local server, incl. 401 on bad token (examples/real-http.ts) |
Winnow.fromConfig() |
✅ implemented |
| Code-exec sandbox: sync QuickJS-WASM in a worker + Atomics bridge (X1) | ✅ implemented — npx tsx examples/exec-demo.ts (30 fat PRs → 117 tok, 74×) |
Persistent catalog cache: disk-keyed by upstream identity, zero-connection warm start, refresh() (P1) |
✅ implemented (cache/cacheDir/cacheTtlMs; default on) |
Live tools/list_changed watch mode: auto-refresh catalog on a server change (P6) |
✅ implemented (opt-in watch: true) |
| HTTP auth: static bearer / pre-provisioned OAuth / client_credentials grant (P2) | ✅ implemented — all browserless, live-verified (test/http-auth.test.ts) |
| Gateway: run Winnow as an MCP server, stdio + HTTP (P4) | ✅ implemented — npx tsx examples/gateway-demo.ts (host → gateway → real upstream) |
Packaged for publish: dist build, types, mcp-winnow bin (P3) |
✅ npm run build; verified via npm pack → clean install → bin runs |
Every part of the spec is implemented, plus the gateway that makes it installable into any MCP host, packaged so npx -y mcp-winnow works.
Install into any MCP host (gateway)
Winnow can run as an MCP server exposing just the 4 meta-tools — so a host connects to ONE server and sees FOUR tools while Winnow hides N upstream servers behind search/load/call/run_code. run_code runs server-side in Winnow's sandbox, so hosts that can't import TS still get the full composition win.
Winnow speaks standard MCP over stdio (the host spawns mcp-winnow gateway) or Streamable HTTP (--http, for hosts/remotes that connect to a URL). winnow.config.json lists the upstream servers to aggregate (same schema as Winnow.fromConfig). Build the bin with npm run build, or run from source: npx tsx src/gateway/cli.ts --config winnow.config.json. Copy-paste the snippet for your agent:
Claude Desktop / Cursor — stdio
// claude_desktop_config.json or .cursor/mcp.json
"mcpServers": {
"winnow": { "command": "npx", "args": ["-y", "mcp-winnow", "gateway", "--config", "winnow.config.json"] }
}
Claude Code — plugin
Winnow ships as a Claude Code plugin (plugin/, listed in .claude-plugin/marketplace.json):
/plugin marketplace add Cambrionic/winnow
/plugin install winnow@winnow
Then drop a winnow.config.json in your project root. (Requires mcp-winnow on npm, or a local npm link — see plugin/README.md.)
Codex CLI — stdio
~/.codex/config.toml (or project-scoped .codex/config.toml):
[mcp_servers.winnow]
command = "npx"
args = ["-y", "mcp-winnow", "gateway", "--config", "winnow.config.json"]
Or one-shot: codex mcp add winnow -- npx -y mcp-winnow gateway --config winnow.config.json. For a remote/hosted gateway, swap command/args for url = "https://…" + bearer_token_env_var = "WINNOW_TOKEN".
Pi — Streamable HTTP
Pi connects to MCP over HTTP, so run the gateway with --http and register the URL in Pi (via its /mcp extension; stored in ~/.pi/agent/mcp/servers.json):
# 1. start the gateway over HTTP (bearer optional via WINNOW_GATEWAY_TOKEN)
npx -y mcp-winnow gateway --config winnow.config.json --http --port 8080
# 2. in Pi:
/mcp add winnow http://localhost:8080
With a bearer: set WINNOW_GATEWAY_TOKEN on the gateway, then /mcp add winnow http://localhost:8080 Authorization=Bearer <token> in Pi.
Layout
src/ SDK: client, catalog, search, filter, config, adapter, sandbox, upstream/, gateway/
examples/ runnable demos + mock servers (see examples/README.md)
test/ unit + integration tests (offline)
bench/ validation benchmarks (token reduction + search recall)
docs/ USAGE, API, CONFIG guides + DESIGN.md (the build-ready spec)
plugin/ the Claude Code plugin package
wayfinder/ the decision map this project was designed through
Contributing
Contributions are welcome! See CONTRIBUTING.md for dev setup and workflow, and please follow the Code of Conduct. New to the code? docs/DESIGN.md explains every decision, and wayfinder/ records how they were reached.
- 🐛 Bugs & ✨ features: open an issue
- 🔒 Security: see SECURITY.md — please report privately
License
MIT © Cambrionic — see LICENSE.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。