mcp-context-budget 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_context_budget-0.4.0/LICENSE +21 -0
- mcp_context_budget-0.4.0/PKG-INFO +290 -0
- mcp_context_budget-0.4.0/README.md +276 -0
- mcp_context_budget-0.4.0/mcp_context_budget/__init__.py +5 -0
- mcp_context_budget-0.4.0/mcp_context_budget/__main__.py +6 -0
- mcp_context_budget-0.4.0/mcp_context_budget/budget.py +110 -0
- mcp_context_budget-0.4.0/mcp_context_budget/cli.py +512 -0
- mcp_context_budget-0.4.0/mcp_context_budget/compress.py +156 -0
- mcp_context_budget-0.4.0/mcp_context_budget/config_audit.py +173 -0
- mcp_context_budget-0.4.0/mcp_context_budget/config_edit.py +564 -0
- mcp_context_budget-0.4.0/mcp_context_budget/demo.py +119 -0
- mcp_context_budget-0.4.0/mcp_context_budget/live_stdio.py +623 -0
- mcp_context_budget-0.4.0/mcp_context_budget/loaders.py +189 -0
- mcp_context_budget-0.4.0/mcp_context_budget/models.py +67 -0
- mcp_context_budget-0.4.0/mcp_context_budget/reporting.py +71 -0
- mcp_context_budget-0.4.0/mcp_context_budget/selector.py +68 -0
- mcp_context_budget-0.4.0/mcp_context_budget/semantic.py +314 -0
- mcp_context_budget-0.4.0/mcp_context_budget/tokens.py +12 -0
- mcp_context_budget-0.4.0/mcp_context_budget.egg-info/PKG-INFO +290 -0
- mcp_context_budget-0.4.0/mcp_context_budget.egg-info/SOURCES.txt +32 -0
- mcp_context_budget-0.4.0/mcp_context_budget.egg-info/dependency_links.txt +1 -0
- mcp_context_budget-0.4.0/mcp_context_budget.egg-info/entry_points.txt +2 -0
- mcp_context_budget-0.4.0/mcp_context_budget.egg-info/requires.txt +4 -0
- mcp_context_budget-0.4.0/mcp_context_budget.egg-info/top_level.txt +1 -0
- mcp_context_budget-0.4.0/pyproject.toml +37 -0
- mcp_context_budget-0.4.0/setup.cfg +4 -0
- mcp_context_budget-0.4.0/tests/test_cli.py +95 -0
- mcp_context_budget-0.4.0/tests/test_compress.py +98 -0
- mcp_context_budget-0.4.0/tests/test_config_audit.py +117 -0
- mcp_context_budget-0.4.0/tests/test_config_contract.py +239 -0
- mcp_context_budget-0.4.0/tests/test_config_edit.py +140 -0
- mcp_context_budget-0.4.0/tests/test_core.py +104 -0
- mcp_context_budget-0.4.0/tests/test_live_stdio.py +181 -0
- mcp_context_budget-0.4.0/tests/test_semantic.py +338 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dan Mercede
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp-context-budget
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Local-first MCP context budget and tool-selection verifier
|
|
5
|
+
Author-email: Dan Mercede <dan@danmercede.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
12
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# mcp-context-budget
|
|
16
|
+
|
|
17
|
+
Local-first MCP context budget and tool-selection verifier for agentic coding
|
|
18
|
+
environments.
|
|
19
|
+
|
|
20
|
+
MCP servers can load enough tool schema and response data to burn a large
|
|
21
|
+
fraction of an agent context window before useful work starts. This tool gives
|
|
22
|
+
developers a repeatable budget gate:
|
|
23
|
+
|
|
24
|
+
- scan MCP config or `tools/list` fixtures
|
|
25
|
+
- estimate schema and response-token cost
|
|
26
|
+
- select a smaller task-relevant tool set with deterministic SQLite FTS5/BM25
|
|
27
|
+
- optionally prove semantic tool selection from fixture or Ollama embeddings
|
|
28
|
+
- write a lockfile for CI
|
|
29
|
+
- fail builds when schema or response budgets regress
|
|
30
|
+
- compress recorded response fixtures under a response budget
|
|
31
|
+
- apply selected-tool locks back to caller-owned MCP config files
|
|
32
|
+
- opt into local stdio `tools/list` introspection for command-discovered servers
|
|
33
|
+
- audit MCP configs for plaintext secret exposure without printing values
|
|
34
|
+
- prove the spine with a Docker demo
|
|
35
|
+
|
|
36
|
+
No private Orion services are required. The core CLI has no external runtime
|
|
37
|
+
service dependency. Semantic selection can optionally call Ollama only when the
|
|
38
|
+
`--embedding-backend ollama` flag is explicitly selected. Live stdio
|
|
39
|
+
introspection can optionally start a caller-owned local MCP command only when
|
|
40
|
+
`--allow-start` is explicitly selected.
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python3.11 -m venv .venv
|
|
46
|
+
. .venv/bin/activate
|
|
47
|
+
pip install -e '.[dev]'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Quick Demo
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
mcp-context-budget demo \
|
|
54
|
+
--task "triage a GitHub issue and update one ticket" \
|
|
55
|
+
--max-tools 8 \
|
|
56
|
+
--max-schema-tokens 6000 \
|
|
57
|
+
--max-response-tokens 4000
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Expected spine proof:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
DEMO_CATALOG_SERVERS=5
|
|
64
|
+
DEMO_CATALOG_TOOLS=120
|
|
65
|
+
BEFORE_SCHEMA_TOKENS=<large>
|
|
66
|
+
SELECTED_TOOLS=<8-or-less>
|
|
67
|
+
AFTER_SCHEMA_TOKENS=<cap-or-less>
|
|
68
|
+
OVERSIZED_RESPONSE_FIXTURE=flagged
|
|
69
|
+
BUDGET_STATUS=PASS
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Commands
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
mcp-context-budget scan --tool-list fixtures/demo-tools.json --out mcp-budget.report.md --lock-out mcp-budget.lock.json
|
|
76
|
+
mcp-context-budget select --tool-list fixtures/demo-tools.json --task "triage a GitHub issue" --max-tools 8 --max-schema-tokens 6000 --out-lock mcp-budget.lock.json
|
|
77
|
+
mcp-context-budget semantic-select --tool-list fixtures/demo-tools.json --task "triage a GitHub issue" --embedding-backend fixture --embedding-file embeddings.json --out-lock mcp-budget.lock.json
|
|
78
|
+
mcp-context-budget check --lock mcp-budget.lock.json --max-schema-tokens 6000 --max-response-tokens 4000
|
|
79
|
+
mcp-context-budget compress-responses --fixtures responses/ --max-response-tokens 4000 --out-dir compressed-responses --report compression-report.json
|
|
80
|
+
mcp-context-budget config-apply --config mcp.json --lock mcp-budget.lock.json --dry-run --patch-out mcp-config.patch.json
|
|
81
|
+
mcp-context-budget config-audit --config mcp.json --json-out mcp-config-audit.json --fail-on high
|
|
82
|
+
mcp-context-budget export --lock mcp-budget.lock.json --format sarif --out mcp-budget.sarif
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`scan --config` supports Claude/Cursor/Codex-style JSON with an `mcpServers`
|
|
86
|
+
object. Server entries may include `toolsListPath` to point at a recorded
|
|
87
|
+
`tools/list` JSON fixture. Server entries may also include `stdioFraming`
|
|
88
|
+
(`auto`, `json-lines`, or `content-length`) when a local stdio server needs a
|
|
89
|
+
fixed transport framing. Environment values are redacted in reports.
|
|
90
|
+
|
|
91
|
+
`--allow-start` is intentionally conservative. It is never implied by default,
|
|
92
|
+
never required for static `toolsListPath` or inline-tool configs, and never
|
|
93
|
+
starts a hosted service. When explicitly selected, the tool starts the
|
|
94
|
+
caller-owned local stdio command as argv with `shell=False`, sends MCP
|
|
95
|
+
`initialize` and `tools/list`, enforces timeout and stdio-byte caps, redacts env
|
|
96
|
+
metadata, and exits the process after listing tools. The default
|
|
97
|
+
`--stdio-framing auto` prefers the current MCP SDK JSON-lines stdio transport
|
|
98
|
+
and falls back to the legacy `Content-Length` fixture transport; pass
|
|
99
|
+
`--stdio-framing json-lines` or `--stdio-framing content-length` to force one.
|
|
100
|
+
|
|
101
|
+
For command-discovered servers that need to become enforceable by
|
|
102
|
+
`config-apply`, combine `--allow-start` with `--materialize-tools-list`:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
mcp-context-budget config-apply \
|
|
106
|
+
--config mcp.json \
|
|
107
|
+
--lock mcp-budget.lock.json \
|
|
108
|
+
--write \
|
|
109
|
+
--allow-start \
|
|
110
|
+
--start-timeout-seconds 2 \
|
|
111
|
+
--max-stdio-bytes 65536 \
|
|
112
|
+
--stdio-framing auto \
|
|
113
|
+
--materialize-tools-list materialized-tools/
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This writes a local `toolsListPath` sidecar for the discovered tools, applies
|
|
117
|
+
the selected-tool lock there, and leaves later `scan`/`select` runs static again.
|
|
118
|
+
|
|
119
|
+
### Semantic Selection
|
|
120
|
+
|
|
121
|
+
`semantic-select` keeps the v0.1 lockfile shape but ranks tools by embedding
|
|
122
|
+
similarity before applying `--max-tools` and `--max-schema-tokens`.
|
|
123
|
+
|
|
124
|
+
Fixture mode is deterministic and requires no service:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
mcp-context-budget semantic-select \
|
|
128
|
+
--tool-list tools.json \
|
|
129
|
+
--task "diagnose bug report" \
|
|
130
|
+
--embedding-backend fixture \
|
|
131
|
+
--embedding-file embeddings.json \
|
|
132
|
+
--out-lock semantic.lock.json
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The fixture file must contain:
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"queries": {"diagnose bug report": [1.0, 0.0]},
|
|
140
|
+
"tools": {"github/get_issue": [1.0, 0.0]}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Ollama mode uses stdlib HTTP and adds no Python package dependency:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
mcp-context-budget semantic-select \
|
|
148
|
+
--tool-list tools.json \
|
|
149
|
+
--task "diagnose bug report" \
|
|
150
|
+
--embedding-backend ollama \
|
|
151
|
+
--ollama-url http://localhost:11434 \
|
|
152
|
+
--ollama-model nomic-embed-text
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Response Fixture Compression
|
|
156
|
+
|
|
157
|
+
`compress-responses` reads one response fixture or a directory of `*.json`
|
|
158
|
+
fixtures, writes compressed copies, and emits a JSON report.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
mcp-context-budget compress-responses \
|
|
162
|
+
--fixtures responses/ \
|
|
163
|
+
--max-response-tokens 4000 \
|
|
164
|
+
--out-dir compressed-responses \
|
|
165
|
+
--report compression-report.json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The v0.2 strategy is deterministic extractive compression. It preserves common
|
|
169
|
+
identifier fields and writes a `summary` when large body fields need to be cut.
|
|
170
|
+
|
|
171
|
+
### Config Apply
|
|
172
|
+
|
|
173
|
+
`config-apply` turns a selected-tool lock into a safe local MCP config patch.
|
|
174
|
+
Dry-run is the default posture; `--write` is required before the config file is
|
|
175
|
+
changed, and write mode creates a backup.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
mcp-context-budget config-apply \
|
|
179
|
+
--config mcp.json \
|
|
180
|
+
--lock mcp-budget.lock.json \
|
|
181
|
+
--mode disable-unselected \
|
|
182
|
+
--dry-run \
|
|
183
|
+
--patch-out mcp-config.patch.json
|
|
184
|
+
|
|
185
|
+
mcp-context-budget config-apply \
|
|
186
|
+
--config mcp.json \
|
|
187
|
+
--lock mcp-budget.lock.json \
|
|
188
|
+
--mode disable-unselected \
|
|
189
|
+
--write \
|
|
190
|
+
--backup-dir backups/
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Reports redact environment values.
|
|
194
|
+
|
|
195
|
+
The apply contract is enforced, not advisory:
|
|
196
|
+
|
|
197
|
+
- **Inline and `toolsListPath` tools are both patched.** A server whose tools
|
|
198
|
+
live in an external `tools/list` JSON has that file patched (and backed up)
|
|
199
|
+
too — not silently skipped.
|
|
200
|
+
- **The lock is bound to the config.** Each lock records a `config_fingerprint`
|
|
201
|
+
of its tool universe; `config-apply` refuses a lock whose fingerprint does not
|
|
202
|
+
match the target config (a foreign/stale lock would otherwise disable every
|
|
203
|
+
tool and still report success). Override with `--allow-fingerprint-mismatch`.
|
|
204
|
+
- **Honest status, never a false PASS.** A command-discovered server (no inline
|
|
205
|
+
`tools`, no `toolsListPath`) cannot be enforced without live startup, so it is
|
|
206
|
+
reported under `not_patchable` and the status is `PARTIAL`, not `PASS`.
|
|
207
|
+
- **Opt-in materialization closes the PARTIAL gap.** With `--allow-start` and
|
|
208
|
+
`--materialize-tools-list`, command-discovered tools are listed through local
|
|
209
|
+
stdio, saved to a caller-owned sidecar, and enforced as a normal
|
|
210
|
+
`toolsListPath` catalog.
|
|
211
|
+
- **Disabling takes effect.** The loader honors `enabled: false`, so a disabled
|
|
212
|
+
tool (or server) drops out of the budget on the next `scan`/`select`.
|
|
213
|
+
|
|
214
|
+
### Config Secret Audit
|
|
215
|
+
|
|
216
|
+
`config-audit` is a read-only hygiene check for MCP config files. It flags
|
|
217
|
+
high-confidence literal secrets in env values, args, and nested config fields,
|
|
218
|
+
while treating `${TOKEN}` references, `op://...` references, and redacted
|
|
219
|
+
placeholders as safe references.
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
mcp-context-budget config-audit \
|
|
223
|
+
--config mcp.json \
|
|
224
|
+
--json-out mcp-config-audit.json \
|
|
225
|
+
--fail-on high
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Reports include the config path, finding path, severity, secret class, length
|
|
229
|
+
bucket, and a short fingerprint. Literal secret values are never printed.
|
|
230
|
+
|
|
231
|
+
## Docker
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
docker build -t mcp-context-budget:local .
|
|
235
|
+
docker run --rm mcp-context-budget:local demo \
|
|
236
|
+
--task "triage a GitHub issue and update one ticket" \
|
|
237
|
+
--max-tools 8 \
|
|
238
|
+
--max-schema-tokens 6000 \
|
|
239
|
+
--max-response-tokens 4000
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The image exposes no service port.
|
|
243
|
+
|
|
244
|
+
v0.2 also includes independent Docker proof commands for the new capabilities:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
docker run --rm mcp-context-budget:local semantic-demo \
|
|
248
|
+
--task "diagnose bug report" \
|
|
249
|
+
--max-tools 3 \
|
|
250
|
+
--max-schema-tokens 3000
|
|
251
|
+
docker run --rm mcp-context-budget:local compress-demo --max-response-tokens 4000
|
|
252
|
+
docker run --rm mcp-context-budget:local config-demo
|
|
253
|
+
docker run --rm mcp-context-budget:local allow-start-demo --start-timeout-seconds 2 --max-stdio-bytes 65536 --stdio-framing auto
|
|
254
|
+
docker run --rm mcp-context-budget:local semantic-demo --task "diagnose bug report" --max-tools 3 --max-schema-tokens 3000 --embedding-backend fixture
|
|
255
|
+
docker run --rm mcp-context-budget:local prove-parallel-ollama-demo
|
|
256
|
+
docker run --rm mcp-context-budget:local config-audit-demo
|
|
257
|
+
docker run --rm mcp-context-budget:local config-multiserver-demo
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Expected v0.3 proof lines:
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
LIVE_INTROSPECTION_STATUS=PASS
|
|
264
|
+
AFTER_CONFIG_NOT_PATCHABLE=0
|
|
265
|
+
CONFIG_AUDIT_STATUS=PASS
|
|
266
|
+
CONFIG_AUDIT_SECRET_VALUES_REDACTED=true
|
|
267
|
+
CONFIG_MULTISERVER_STATUS=PASS
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Out of v0.3
|
|
271
|
+
|
|
272
|
+
### Locked Out
|
|
273
|
+
|
|
274
|
+
- Live runtime MCP proxy/gateway that intercepts and routes actual tool calls.
|
|
275
|
+
- Browser UI.
|
|
276
|
+
- Organization-wide background scanner.
|
|
277
|
+
- Vendor-specific hosted dashboards.
|
|
278
|
+
|
|
279
|
+
These are not v0.4 commitments; they break the local-first CLI verifier shape.
|
|
280
|
+
|
|
281
|
+
### Shipped in v0.4
|
|
282
|
+
|
|
283
|
+
- Parallelized Ollama embeddings for `semantic-select` when
|
|
284
|
+
`--embedding-backend ollama` is explicitly selected (fixture backend remains
|
|
285
|
+
the default for CI/docker).
|
|
286
|
+
|
|
287
|
+
### Deferred to v0.5
|
|
288
|
+
|
|
289
|
+
- Automatic response compression for arbitrary live MCP servers.
|
|
290
|
+
- Broader CLI polish.
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# mcp-context-budget
|
|
2
|
+
|
|
3
|
+
Local-first MCP context budget and tool-selection verifier for agentic coding
|
|
4
|
+
environments.
|
|
5
|
+
|
|
6
|
+
MCP servers can load enough tool schema and response data to burn a large
|
|
7
|
+
fraction of an agent context window before useful work starts. This tool gives
|
|
8
|
+
developers a repeatable budget gate:
|
|
9
|
+
|
|
10
|
+
- scan MCP config or `tools/list` fixtures
|
|
11
|
+
- estimate schema and response-token cost
|
|
12
|
+
- select a smaller task-relevant tool set with deterministic SQLite FTS5/BM25
|
|
13
|
+
- optionally prove semantic tool selection from fixture or Ollama embeddings
|
|
14
|
+
- write a lockfile for CI
|
|
15
|
+
- fail builds when schema or response budgets regress
|
|
16
|
+
- compress recorded response fixtures under a response budget
|
|
17
|
+
- apply selected-tool locks back to caller-owned MCP config files
|
|
18
|
+
- opt into local stdio `tools/list` introspection for command-discovered servers
|
|
19
|
+
- audit MCP configs for plaintext secret exposure without printing values
|
|
20
|
+
- prove the spine with a Docker demo
|
|
21
|
+
|
|
22
|
+
No private Orion services are required. The core CLI has no external runtime
|
|
23
|
+
service dependency. Semantic selection can optionally call Ollama only when the
|
|
24
|
+
`--embedding-backend ollama` flag is explicitly selected. Live stdio
|
|
25
|
+
introspection can optionally start a caller-owned local MCP command only when
|
|
26
|
+
`--allow-start` is explicitly selected.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python3.11 -m venv .venv
|
|
32
|
+
. .venv/bin/activate
|
|
33
|
+
pip install -e '.[dev]'
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Demo
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
mcp-context-budget demo \
|
|
40
|
+
--task "triage a GitHub issue and update one ticket" \
|
|
41
|
+
--max-tools 8 \
|
|
42
|
+
--max-schema-tokens 6000 \
|
|
43
|
+
--max-response-tokens 4000
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Expected spine proof:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
DEMO_CATALOG_SERVERS=5
|
|
50
|
+
DEMO_CATALOG_TOOLS=120
|
|
51
|
+
BEFORE_SCHEMA_TOKENS=<large>
|
|
52
|
+
SELECTED_TOOLS=<8-or-less>
|
|
53
|
+
AFTER_SCHEMA_TOKENS=<cap-or-less>
|
|
54
|
+
OVERSIZED_RESPONSE_FIXTURE=flagged
|
|
55
|
+
BUDGET_STATUS=PASS
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Commands
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
mcp-context-budget scan --tool-list fixtures/demo-tools.json --out mcp-budget.report.md --lock-out mcp-budget.lock.json
|
|
62
|
+
mcp-context-budget select --tool-list fixtures/demo-tools.json --task "triage a GitHub issue" --max-tools 8 --max-schema-tokens 6000 --out-lock mcp-budget.lock.json
|
|
63
|
+
mcp-context-budget semantic-select --tool-list fixtures/demo-tools.json --task "triage a GitHub issue" --embedding-backend fixture --embedding-file embeddings.json --out-lock mcp-budget.lock.json
|
|
64
|
+
mcp-context-budget check --lock mcp-budget.lock.json --max-schema-tokens 6000 --max-response-tokens 4000
|
|
65
|
+
mcp-context-budget compress-responses --fixtures responses/ --max-response-tokens 4000 --out-dir compressed-responses --report compression-report.json
|
|
66
|
+
mcp-context-budget config-apply --config mcp.json --lock mcp-budget.lock.json --dry-run --patch-out mcp-config.patch.json
|
|
67
|
+
mcp-context-budget config-audit --config mcp.json --json-out mcp-config-audit.json --fail-on high
|
|
68
|
+
mcp-context-budget export --lock mcp-budget.lock.json --format sarif --out mcp-budget.sarif
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`scan --config` supports Claude/Cursor/Codex-style JSON with an `mcpServers`
|
|
72
|
+
object. Server entries may include `toolsListPath` to point at a recorded
|
|
73
|
+
`tools/list` JSON fixture. Server entries may also include `stdioFraming`
|
|
74
|
+
(`auto`, `json-lines`, or `content-length`) when a local stdio server needs a
|
|
75
|
+
fixed transport framing. Environment values are redacted in reports.
|
|
76
|
+
|
|
77
|
+
`--allow-start` is intentionally conservative. It is never implied by default,
|
|
78
|
+
never required for static `toolsListPath` or inline-tool configs, and never
|
|
79
|
+
starts a hosted service. When explicitly selected, the tool starts the
|
|
80
|
+
caller-owned local stdio command as argv with `shell=False`, sends MCP
|
|
81
|
+
`initialize` and `tools/list`, enforces timeout and stdio-byte caps, redacts env
|
|
82
|
+
metadata, and exits the process after listing tools. The default
|
|
83
|
+
`--stdio-framing auto` prefers the current MCP SDK JSON-lines stdio transport
|
|
84
|
+
and falls back to the legacy `Content-Length` fixture transport; pass
|
|
85
|
+
`--stdio-framing json-lines` or `--stdio-framing content-length` to force one.
|
|
86
|
+
|
|
87
|
+
For command-discovered servers that need to become enforceable by
|
|
88
|
+
`config-apply`, combine `--allow-start` with `--materialize-tools-list`:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
mcp-context-budget config-apply \
|
|
92
|
+
--config mcp.json \
|
|
93
|
+
--lock mcp-budget.lock.json \
|
|
94
|
+
--write \
|
|
95
|
+
--allow-start \
|
|
96
|
+
--start-timeout-seconds 2 \
|
|
97
|
+
--max-stdio-bytes 65536 \
|
|
98
|
+
--stdio-framing auto \
|
|
99
|
+
--materialize-tools-list materialized-tools/
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This writes a local `toolsListPath` sidecar for the discovered tools, applies
|
|
103
|
+
the selected-tool lock there, and leaves later `scan`/`select` runs static again.
|
|
104
|
+
|
|
105
|
+
### Semantic Selection
|
|
106
|
+
|
|
107
|
+
`semantic-select` keeps the v0.1 lockfile shape but ranks tools by embedding
|
|
108
|
+
similarity before applying `--max-tools` and `--max-schema-tokens`.
|
|
109
|
+
|
|
110
|
+
Fixture mode is deterministic and requires no service:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
mcp-context-budget semantic-select \
|
|
114
|
+
--tool-list tools.json \
|
|
115
|
+
--task "diagnose bug report" \
|
|
116
|
+
--embedding-backend fixture \
|
|
117
|
+
--embedding-file embeddings.json \
|
|
118
|
+
--out-lock semantic.lock.json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The fixture file must contain:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"queries": {"diagnose bug report": [1.0, 0.0]},
|
|
126
|
+
"tools": {"github/get_issue": [1.0, 0.0]}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Ollama mode uses stdlib HTTP and adds no Python package dependency:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
mcp-context-budget semantic-select \
|
|
134
|
+
--tool-list tools.json \
|
|
135
|
+
--task "diagnose bug report" \
|
|
136
|
+
--embedding-backend ollama \
|
|
137
|
+
--ollama-url http://localhost:11434 \
|
|
138
|
+
--ollama-model nomic-embed-text
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Response Fixture Compression
|
|
142
|
+
|
|
143
|
+
`compress-responses` reads one response fixture or a directory of `*.json`
|
|
144
|
+
fixtures, writes compressed copies, and emits a JSON report.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
mcp-context-budget compress-responses \
|
|
148
|
+
--fixtures responses/ \
|
|
149
|
+
--max-response-tokens 4000 \
|
|
150
|
+
--out-dir compressed-responses \
|
|
151
|
+
--report compression-report.json
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The v0.2 strategy is deterministic extractive compression. It preserves common
|
|
155
|
+
identifier fields and writes a `summary` when large body fields need to be cut.
|
|
156
|
+
|
|
157
|
+
### Config Apply
|
|
158
|
+
|
|
159
|
+
`config-apply` turns a selected-tool lock into a safe local MCP config patch.
|
|
160
|
+
Dry-run is the default posture; `--write` is required before the config file is
|
|
161
|
+
changed, and write mode creates a backup.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
mcp-context-budget config-apply \
|
|
165
|
+
--config mcp.json \
|
|
166
|
+
--lock mcp-budget.lock.json \
|
|
167
|
+
--mode disable-unselected \
|
|
168
|
+
--dry-run \
|
|
169
|
+
--patch-out mcp-config.patch.json
|
|
170
|
+
|
|
171
|
+
mcp-context-budget config-apply \
|
|
172
|
+
--config mcp.json \
|
|
173
|
+
--lock mcp-budget.lock.json \
|
|
174
|
+
--mode disable-unselected \
|
|
175
|
+
--write \
|
|
176
|
+
--backup-dir backups/
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Reports redact environment values.
|
|
180
|
+
|
|
181
|
+
The apply contract is enforced, not advisory:
|
|
182
|
+
|
|
183
|
+
- **Inline and `toolsListPath` tools are both patched.** A server whose tools
|
|
184
|
+
live in an external `tools/list` JSON has that file patched (and backed up)
|
|
185
|
+
too — not silently skipped.
|
|
186
|
+
- **The lock is bound to the config.** Each lock records a `config_fingerprint`
|
|
187
|
+
of its tool universe; `config-apply` refuses a lock whose fingerprint does not
|
|
188
|
+
match the target config (a foreign/stale lock would otherwise disable every
|
|
189
|
+
tool and still report success). Override with `--allow-fingerprint-mismatch`.
|
|
190
|
+
- **Honest status, never a false PASS.** A command-discovered server (no inline
|
|
191
|
+
`tools`, no `toolsListPath`) cannot be enforced without live startup, so it is
|
|
192
|
+
reported under `not_patchable` and the status is `PARTIAL`, not `PASS`.
|
|
193
|
+
- **Opt-in materialization closes the PARTIAL gap.** With `--allow-start` and
|
|
194
|
+
`--materialize-tools-list`, command-discovered tools are listed through local
|
|
195
|
+
stdio, saved to a caller-owned sidecar, and enforced as a normal
|
|
196
|
+
`toolsListPath` catalog.
|
|
197
|
+
- **Disabling takes effect.** The loader honors `enabled: false`, so a disabled
|
|
198
|
+
tool (or server) drops out of the budget on the next `scan`/`select`.
|
|
199
|
+
|
|
200
|
+
### Config Secret Audit
|
|
201
|
+
|
|
202
|
+
`config-audit` is a read-only hygiene check for MCP config files. It flags
|
|
203
|
+
high-confidence literal secrets in env values, args, and nested config fields,
|
|
204
|
+
while treating `${TOKEN}` references, `op://...` references, and redacted
|
|
205
|
+
placeholders as safe references.
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
mcp-context-budget config-audit \
|
|
209
|
+
--config mcp.json \
|
|
210
|
+
--json-out mcp-config-audit.json \
|
|
211
|
+
--fail-on high
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Reports include the config path, finding path, severity, secret class, length
|
|
215
|
+
bucket, and a short fingerprint. Literal secret values are never printed.
|
|
216
|
+
|
|
217
|
+
## Docker
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
docker build -t mcp-context-budget:local .
|
|
221
|
+
docker run --rm mcp-context-budget:local demo \
|
|
222
|
+
--task "triage a GitHub issue and update one ticket" \
|
|
223
|
+
--max-tools 8 \
|
|
224
|
+
--max-schema-tokens 6000 \
|
|
225
|
+
--max-response-tokens 4000
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The image exposes no service port.
|
|
229
|
+
|
|
230
|
+
v0.2 also includes independent Docker proof commands for the new capabilities:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
docker run --rm mcp-context-budget:local semantic-demo \
|
|
234
|
+
--task "diagnose bug report" \
|
|
235
|
+
--max-tools 3 \
|
|
236
|
+
--max-schema-tokens 3000
|
|
237
|
+
docker run --rm mcp-context-budget:local compress-demo --max-response-tokens 4000
|
|
238
|
+
docker run --rm mcp-context-budget:local config-demo
|
|
239
|
+
docker run --rm mcp-context-budget:local allow-start-demo --start-timeout-seconds 2 --max-stdio-bytes 65536 --stdio-framing auto
|
|
240
|
+
docker run --rm mcp-context-budget:local semantic-demo --task "diagnose bug report" --max-tools 3 --max-schema-tokens 3000 --embedding-backend fixture
|
|
241
|
+
docker run --rm mcp-context-budget:local prove-parallel-ollama-demo
|
|
242
|
+
docker run --rm mcp-context-budget:local config-audit-demo
|
|
243
|
+
docker run --rm mcp-context-budget:local config-multiserver-demo
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Expected v0.3 proof lines:
|
|
247
|
+
|
|
248
|
+
```text
|
|
249
|
+
LIVE_INTROSPECTION_STATUS=PASS
|
|
250
|
+
AFTER_CONFIG_NOT_PATCHABLE=0
|
|
251
|
+
CONFIG_AUDIT_STATUS=PASS
|
|
252
|
+
CONFIG_AUDIT_SECRET_VALUES_REDACTED=true
|
|
253
|
+
CONFIG_MULTISERVER_STATUS=PASS
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Out of v0.3
|
|
257
|
+
|
|
258
|
+
### Locked Out
|
|
259
|
+
|
|
260
|
+
- Live runtime MCP proxy/gateway that intercepts and routes actual tool calls.
|
|
261
|
+
- Browser UI.
|
|
262
|
+
- Organization-wide background scanner.
|
|
263
|
+
- Vendor-specific hosted dashboards.
|
|
264
|
+
|
|
265
|
+
These are not v0.4 commitments; they break the local-first CLI verifier shape.
|
|
266
|
+
|
|
267
|
+
### Shipped in v0.4
|
|
268
|
+
|
|
269
|
+
- Parallelized Ollama embeddings for `semantic-select` when
|
|
270
|
+
`--embedding-backend ollama` is explicitly selected (fixture backend remains
|
|
271
|
+
the default for CI/docker).
|
|
272
|
+
|
|
273
|
+
### Deferred to v0.5
|
|
274
|
+
|
|
275
|
+
- Automatic response compression for arbitrary live MCP servers.
|
|
276
|
+
- Broader CLI polish.
|