Install
$ agentstack add mcp-dgenio-contextweaver ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
contextweaver
[](https://github.com/dgenio/contextweaver/actions/workflows/ci.yml) [](https://pypi.org/project/contextweaver/) [](https://pypi.org/project/contextweaver/) [](LICENSE) [](https://scorecard.dev/viewer/?uri=github.com/dgenio/contextweaver) [](https://dgenio.github.io/contextweaver) [](https://github.com/dgenio/contextweaver/discussions) [](https://pub.towardsai.net/the-weaver-stack-one-contract-layer-for-safe-llm-agents-7f733cad5eac)
> The MCP context gateway for tool-heavy agents. Drop contextweaver in > front of your MCP servers and the model sees a bounded ChoiceCard shortlist > instead of every tool schema, plus an artifact-backed firewall that swaps a > huge raw tool result for a compact summary. Deterministic, no model in the > loop, and 42-84 % fewer prompt tokens on the committed benchmarks.
Who it's for: anyone whose agent — Claude Desktop, Cursor, VS Code, or a custom loop — keeps tripping over "too many tools" or "a 16 KB tool result blew up my prompt."
uvx contextweaver demo --scenario killer # zero-install trial
# Or install it:
pip install contextweaver
python -c "import contextweaver; print(contextweaver.__version__)"
contextweaver demo --scenario killer # 60-second taste — no API key, no network
contextweaver start # choose gateway, library, routing, or integration
Use it for real → the [MCP gateway quickstart](docs/recipes/index.md) (Claude Desktop / Copilot / custom MCP clients), backed by the [MCP Context Gateway architecture](docs/architectures/mcpcontextgateway.md). Already have a loop and not sure which piece you need? The two engines also work [routing-only or firewall-only](docs/whichpattern.md). For day-to-day operating guidance, see the [Daily Driver guide](docs/dailydriver.md); for deployment boundaries, see the [MCP Gateway Security Model](docs/security_model.md).
1150+ tests passing · minimal core dependencies · deterministic by default · Python 3.10–3.13
More tools ≠ better answers
> As an agent's tool catalog grows, a naive "show every schema" route prompt > balloons while the right tool gets harder to find — context rot. > contextweaver keeps the model-visible surface bounded (5 ChoiceCards, not > 1,328 schemas), so the route prompt stays flat and deterministic. Reproduce > the curve with no API key: [docs/context_rot.md](docs/context_rot.md).
📖 Docs · [🎬 Showcase](docs/showcase.md) · [🧩 Where it fits](docs/comparison.md) · [🗺️ Ecosystem map](docs/ecosystem.md) · [❓ FAQ](docs/faq.md) · [📊 Scorecard](benchmarks/scorecard.md) · [📈 Adopter benchmark report](docs/benchmarkreport.md) · [🧭 Which pattern fits?](docs/whichpattern.md) · [🛠 Cookbook](docs/cookbook.md) · [🍳 Recipes](docs/recipes/index.md) · [📉 Context rot demo](docs/contextrot.md) · [🎬 Replay demo (.cast)](docs/assets/demo.cast)
Part of the Weaver Stack
contextweaver is the context layer of the Weaver Stack — small, deterministic, independently-usable building blocks for tool-using agents. The core request path runs:
contextweaver ─▶ ChainWeaver ─▶ agent-kernel ─▶ agentfence
| Stage | Component | Responsibility | |---|---|---| | Context | contextweaver (this repo) | Route a catalog to bounded ChoiceCards, firewall large tool results, compile a budgeted prompt. | | Execution | ChainWeaver | Run the selected capability as a deterministic tool/flow. | | Boundary | agent-kernel | Own the execution boundary; hand contextweaver Frames, not raw output. | | Guardrails | agentfence | Apply output guardrails to the response. |
The contextweaver → ChainWeaver handoff is advisory: contextweaver routes (it recommends a capability) and ingests results behind its firewall; the runtime owns authorization and execution. A runnable end-to-end example — route a catalog of tools + imported ChainWeaver flows, hand the selection to a (stubbed) ChainWeaver runtime, then ingest the result — lives at [examples/architectures/contextweaver_to_chainweaver/](examples/architectures/contextweavertochainweaver/), and the contract boundary is documented in [docs/weaver_spec_mapping.md](docs/weaverspecmapping.md).
Adjacent tools: vibeguard (code-diff safety gate), lessonweaver (lesson capture), and skdr-eval (offline evaluation). Every piece works standalone — contextweaver has no hard dependency on any sibling, so you can use it on its own or slot it into the stack. See the [Ecosystem Map](docs/ecosystem.md) for how the pieces compose.
The 60-second failure mode
See why a naive tool-using agent loop breaks down — and what contextweaver does about it — in one command (no API keys, no network):
contextweaver demo --scenario killer
An internal ops agent with 100 tools and a running conversation is asked to "find unpaid invoices, check the account notes, and draft a reminder." A naive loop pays for all 100 tool descriptions, the full history, and a huge raw tool result at once:
| | Naive | contextweaver | Reduction | |---|---|---|---| | Tools in the route prompt | all 100 (6,326 chars) | 5 ChoiceCards (491 chars) | 92.2% | | The huge tool result | raw (14,430 chars) | firewalled summary (60 chars) | 99.6% | | The full answer prompt | everything raw (21,332 chars) | compiled (814 chars) | 96.2% |
Full walkthrough: [The 60-second failure mode](docs/killerdemo.md). For the same story as a runnable, inspectable script, see the [catalog showcase architecture](docs/architectures/catalogshowcase.md).
The Problem
Even with 200K-token context windows, dumping everything into the prompt is expensive, slow, and degrades output quality. More context ≠ better answers — context engineering (deciding what the model sees, when, and at what cost) is the lever that actually moves quality and latency.
Imagine a tool-using agent with a 100-tool catalog and a 50-turn conversation history. At each step the agent must answer four questions:
- Route — which tool should I call?
- Call — what arguments?
- Interpret — what did it return?
- Answer — how do I respond to the user?
Naive approach A — concatenate everything:
100 tool schemas (≈50k tokens) + 50 turns (≈30k tokens) = 80k tokens
Cost: $0.48/request at GPT-4o rates · Latency: 3–5s TTFT
Quality: LLM loses focus — needle-in-haystack accuracy drops with context size
Token limit: 8k → 10× overflow
Naive approach B — cherry-pick manually:
Pick 10 tools, last 5 turns → lose dependency chains
Agent hallucinates tool calls, repeats questions, forgets context
contextweaver approach — phase-specific budgeted compilation:
Route phase: 5 tool cards (≈500 tokens), no full schemas
Answer phase: 3 relevant turns + dependency closure (≈2k tokens)
Result: 2.5k tokens, complete context, deterministic
Cost: 41.6 %-84.3 % fewer prompt tokens [^naive-baseline] · Latency: sub-second · Quality: relevant context only
[^naive-baseline]: Measured against the "concatenate all tool schemas + full conversation history" baseline using tiktoken.cl100k_base on the six committed benchmark scenarios. Range 41.6 %-84.3 %, average 64.3 %. Reproducible via make benchmark-matrix && make scorecard — see the vs. naïve concat baseline section of [benchmarks/scorecard.md](benchmarks/scorecard.md) and the methodology in [scripts/baseline_naive.py](scripts/baseline_naive.py).
See [examples/before_after.py](examples/before_after.py) for a runnable side-by-side comparison.
How contextweaver Solves It
contextweaver provides two cooperating engines:
┌────────────────────────────┐
Events ──────>│ Context Engine │──> ContextPack (prompt)
│ candidates → closure → │
│ sensitivity → firewall → │
│ score → dedup → select → │
│ render │
└────────────────────────────┘
▲ facts / episodes
┌──────────┴─────────────────┐
Tools ───────>│ Routing Engine │──> ChoiceCards
│ Catalog → TreeBuilder → │
│ ChoiceGraph → Router │
└────────────────────────────┘
Context Engine — eight-stage pipeline:
- generate_candidates — pull phase-relevant events from the log for this request.
- dependency_closure — if a selected item has a
parent_id, include the parent automatically. - sensitivity_filter — drop or redact items at or above the configured sensitivity floor.
- apply_firewall — tool results are stored out-of-band; large outputs are summarized/truncated before prompt assembly.
- score_candidates — rank by recency, tag match, kind priority, and token cost.
- deduplicate_candidates — remove near-duplicates using Jaccard similarity.
- selectandpack — greedily pack highest-scoring items into the phase token budget.
- render_context — assemble final prompt string with
BuildStatsmetadata.
Routing Engine — four-stage pipeline:
- Catalog — register and manage
SelectableItemobjects. - TreeBuilder — convert a flat catalog into a bounded
ChoiceGraphDAG. - Router — beam-search over the graph; deterministic tie-breaking by ID.
- ChoiceCards — compact, LLM-friendly cards (never includes full schemas).
Also works as routing-only or firewall-only
The MCP gateway is the headline, but those are really two cooperating engines you can adopt independently — a context compiler and a tool router. Reach for whichever your agent needs:
| If your agent has... | contextweaver gives you... | |---|---| | Too many MCP / FastMCP / Python tools | A bounded ChoiceCard shortlist instead of dumping every schema into the route prompt. | | Huge JSON, logs, tables, or binary tool results | An artifact-backed context firewall: compact summary in the prompt, raw bytes out of band. | | Long tool-using conversations | Phase-specific context packs with budgeted selection and dependency closure. |
| Use this when... | Do not use this when... | |---|---| | You already have an agent loop and need runtime context control. | You need an agent framework, LLM SDK, or tool executor. | | Your model-visible tool list or tool-result payloads are getting too large. | Your agent has a handful of tiny tools and no context-budget pressure. | | You want deterministic prompt budgeting and traceable drops. | You only need long-term memory, RAG, or observability by itself. |
Not sure which piece fits? The [which-pattern decision tree](docs/which_pattern.md) maps each symptom (long conversations → full pipeline; 50+ tools → routing-only; huge tool outputs → firewall-only) to one concrete next step.
When not to use contextweaver
contextweaver is a context compiler for tool-using agents — its value scales with the size of the catalog and the length of the conversation. Reach for something simpler when none of that pressure exists:
- Small tool catalogs (≤ 5 tools). Dumping every schema into the prompt
costs a few hundred tokens. Building a routing graph and running beam search adds latency and a dependency you don't need.
- Single-shot Q&A or one-turn agents. With no history to compact and no
follow-up phases (call / interpret / answer), phase-aware budgeting is dead weight — pass the user's message straight to the model.
- Tiny tool outputs. If every
tool_resultis comfortably under the
configured firewall_threshold (default 2000 characters), the [context firewall](docs/context_firewall.md) correctly no-ops — you're paying the conceptual cost of the firewall for zero token savings.
- Full context is cheaper than the engineering. If your naïve prompt
fits comfortably under the model's context window and your token bill is not a concern, the [before/after scorecard](benchmarks/scorecard.md) numbers won't move the needle.
- You need non-deterministic, LLM-driven routing. contextweaver's
routing engine is deterministic by design (tie-break by sorted ID). If you want an LLM to decide which tool to call from free-form reasoning, LangGraph or a plain tool_choice="auto" call is a better fit — see [docs/comparison.md](docs/comparison.md) for the trade-offs.
If you're not sure, the [10-minute Quickstart](#10-minute-quickstart) below is the cheapest way to find out: a 40-tool catalog and a 50-turn transcript is the smallest scenario where contextweaver clearly pays for itself.
Quickstart
Install
Try the CLI without installing it:
uvx contextweaver demo --scenario killer
Or install it persistently:
pip install contextweaver
contextweaver ships with a minimal, opinionated core: tiktoken, PyYAML, rank-bm25, mcp, jsonschema, Typer, and Rich. These power token budgeting, YAML catalog/config files, the default lexical retrieval backend, the MCP proxy/gateway runtime, schema validation, and the CLI.
Optional capabilities are gated behind extras so the core install stays small:
| Extra | What it adds | |---|---| | contextweaver[weaver-spec] | Weaver Stack contract adapters (weaver_contracts) | | contextweaver[fastmcp] | FastMCP catalog adapter and discovery helpers | | contextweaver[crewai] | CrewAI runtime integration | | contextweaver[pydantic-ai] | Pydantic AI runtime integration | | contextweaver[smolagents] | Hugging Face smolagents runtime integration | | contextweaver[agno] | Agno runtime integration | | contextweaver[langchain] | LangChain integration helpers | | contextweaver[voice] | Pipecat voice-agent integration | | contextweaver[retrieval] | Fuzzy lexical matching backend (rapidfuzz) | | contextweaver[embeddings] | Sentence-transformers embedding backend | | contextweaver[tokenizers] | Tokenizer install contract (core tiktoken today) | | contextweaver[sqlite] | SQLite store install contract (stdlib-backed today) | | contextweaver[mem0] | Mem0 external-memory backend | | contextweaver[otel] | OpenTelemetry tracing + metrics export | | contextweaver[e2e-eval] | Optional real-model benchmark hook (no dependency today) | | contextweaver[docs] | MkDocs documentation toolchain | | contextweaver[dev] | Test, lint, type-check, and fixture toolchain | | contextweaver[all] | Convenience bundle for broad optional runtime capabilities |
Some extras are install-contract markers rather than dependency bundles: tokenizers, sqlite, and e2e-eval are intentionally empty today because the current implementations use core dependencies or the Python standard library. They stay user-facing so requirements files can opt into the capability surface without changing when future implementation-specific packages are added.
Or from source:
git clone https://github.com/dgenio/contextweaver.git
cd contextweaver
pip install -e ".[dev]"
Adopting in 5 lines from an existing OpenAI / Anthropic / Gemini agent
from contextweaver.adapters.openai_messages import from_openai_messages
from contextweaver.context.manager import ContextManager
from contextweaver.types import Phase
mgr = ContextManager()
from_openai_messages(messages, into=mgr) # also: from_anthropic_messages / from_gemini_contents
pack = mgr.build_sync(phase=Phase.answer, query="...")
See [Adopting from an existing chat history](docs/quickstart.md#adopting-from-an-existing-chat-history-5-line-drop-in) for the full snippet (including the to_* inverse adapters for round-tripping back into the provider SDK).
10-Minute Quickstart
For a guided setup with prerequisites, three runnable examples, expected output, and next steps, see [docs/quickstart.md](docs/quickstart.md).
**Already have an agent and not sure
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: dgenio
- Source: dgenio/contextweaver
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.