mcp-bastion-python 1.0.17__tar.gz → 2.0.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.
Files changed (71) hide show
  1. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/LICENSE +1 -1
  2. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/PKG-INFO +166 -35
  3. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/README.md +155 -28
  4. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/app.py +134 -3
  5. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/static/chart.umd.min.js +1 -2
  6. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/static/dashboard-app.js +111 -10
  7. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/pyproject.toml +12 -6
  8. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/__init__.py +1 -1
  9. mcp_bastion_python-2.0.0/src/mcp_bastion/audit_jsonl.py +42 -0
  10. mcp_bastion_python-2.0.0/src/mcp_bastion/benchmarks/__init__.py +5 -0
  11. mcp_bastion_python-2.0.0/src/mcp_bastion/benchmarks/finops_rbac.py +221 -0
  12. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/cli.py +126 -5
  13. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/config.py +267 -6
  14. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/demo_dashboard_metrics.py +6 -0
  15. mcp_bastion_python-2.0.0/src/mcp_bastion/doctor.py +387 -0
  16. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/errors.py +55 -0
  17. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/middleware.py +511 -31
  18. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/otel.py +6 -1
  19. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/agent_iam.py +231 -0
  20. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/alerts.py +13 -1
  21. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/argument_guards.py +124 -0
  22. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/audit_log.py +6 -0
  23. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/budget_principal.py +42 -0
  24. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/content_filter.py +10 -4
  25. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/content_normalize.py +31 -0
  26. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/cost_tracker.py +245 -0
  27. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/external_policy.py +31 -16
  28. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/injection_heuristics.py +47 -0
  29. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/metrics.py +44 -1
  30. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/output_budget.py +22 -0
  31. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/prompt_guard.py +167 -0
  32. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/rate_limit.py +221 -0
  33. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/rbac.py +92 -0
  34. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/replay_guard.py +25 -9
  35. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/response_scanner.py +8 -20
  36. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/schema_validation.py +55 -0
  37. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/server_verification.py +192 -0
  38. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/state_backend.py +194 -0
  39. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/stdio_guard.py +87 -0
  40. mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/tool_metadata_fingerprint.py +61 -0
  41. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/policy_simulator.py +3 -0
  42. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/redteam.py +79 -6
  43. mcp_bastion_python-2.0.0/src/mcp_bastion/serve.py +48 -0
  44. mcp_bastion_python-2.0.0/src/mcp_bastion/transport_hardening.py +152 -0
  45. mcp_bastion_python-1.0.17/dashboard/static/chart.umd.js.map +0 -1
  46. mcp_bastion_python-1.0.17/src/mcp_bastion/doctor.py +0 -97
  47. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/cost_tracker.py +0 -103
  48. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/prompt_guard.py +0 -97
  49. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/rate_limit.py +0 -159
  50. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/rbac.py +0 -56
  51. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/.gitignore +0 -0
  52. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/NOTICE +0 -0
  53. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/README.md +0 -0
  54. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/static/mcp-bastian.png +0 -0
  55. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/static/mcp-bastian.svg +0 -0
  56. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/base.py +0 -0
  57. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/demo_live_traffic.py +0 -0
  58. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/governance_beacon.py +0 -0
  59. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/__init__.py +0 -0
  60. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/audit_hash_chain.py +0 -0
  61. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/circuit_breaker.py +0 -0
  62. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/grounding_guard.py +0 -0
  63. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/pii_redaction.py +0 -0
  64. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/pricing.py +0 -0
  65. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/semantic_cache.py +0 -0
  66. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/semantic_firewall.py +0 -0
  67. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/sensitive_classifier.py +0 -0
  68. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/session_offload.py +0 -0
  69. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/telemetry_sinks.py +0 -0
  70. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/tokens.py +0 -0
  71. {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/tenant.py +0 -0
@@ -1,7 +1,7 @@
1
1
  MCP-Bastion Community and Commercial License
2
2
  Version 1.0
3
3
 
4
- Copyright (c) 2026 Viquar Khan
4
+ Copyright (c) 2026 Vaquar Khan
5
5
  All rights reserved.
6
6
 
7
7
  1. Definitions
@@ -1,15 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-bastion-python
3
- Version: 1.0.17
3
+ Version: 2.0.0
4
4
  Summary: Security middleware for MCP servers protecting LLM agents from prompt injection, resource exhaustion, and PII leakage
5
- Project-URL: Homepage, https://github.com/mcp-bastion/mcp-bastion
6
- Project-URL: Repository, https://github.com/mcp-bastion/mcp-bastion
7
- Project-URL: Documentation, https://github.com/mcp-bastion/mcp-bastion#readme
8
- Author: Viquar Khan
5
+ Project-URL: Homepage, https://github.com/vaquarkhan/MCP-Bastion
6
+ Project-URL: Repository, https://github.com/vaquarkhan/MCP-Bastion
7
+ Project-URL: Documentation, https://github.com/vaquarkhan/MCP-Bastion#readme
8
+ Author: Vaquar Khan
9
9
  License: MCP-Bastion Community and Commercial License
10
10
  Version 1.0
11
11
 
12
- Copyright (c) 2026 Viquar Khan
12
+ Copyright (c) 2026 Vaquar Khan
13
13
  All rights reserved.
14
14
 
15
15
  1. Definitions
@@ -74,9 +74,10 @@ Classifier: Programming Language :: Python :: 3
74
74
  Classifier: Programming Language :: Python :: 3.10
75
75
  Classifier: Programming Language :: Python :: 3.11
76
76
  Classifier: Programming Language :: Python :: 3.12
77
+ Classifier: Programming Language :: Python :: 3.13
77
78
  Classifier: Topic :: Security
78
79
  Requires-Python: >=3.10
79
- Requires-Dist: mcp>=1.0.0
80
+ Requires-Dist: mcp>=1.2.0
80
81
  Requires-Dist: presidio-analyzer>=2.2.0
81
82
  Requires-Dist: presidio-anonymizer>=2.2.0
82
83
  Requires-Dist: spacy>=3.5.0
@@ -94,7 +95,10 @@ Requires-Dist: opentelemetry-api>=1.20.0; extra == 'otel'
94
95
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20.0; extra == 'otel'
95
96
  Requires-Dist: opentelemetry-sdk>=1.20.0; extra == 'otel'
96
97
  Provides-Extra: policy
98
+ Requires-Dist: jsonpath-ng>=1.6.0; extra == 'policy'
97
99
  Requires-Dist: pyyaml>=6.0; extra == 'policy'
100
+ Provides-Extra: redis
101
+ Requires-Dist: redis>=5.0.0; extra == 'redis'
98
102
  Description-Content-Type: text/markdown
99
103
 
100
104
  # MCP-Bastion
@@ -110,7 +114,7 @@ Description-Content-Type: text/markdown
110
114
  />
111
115
  </p>
112
116
 
113
- [![PyPI: mcp-bastion-python 1.0.17](https://img.shields.io/pypi/v/mcp-bastion-python?logo=python)](https://pypi.org/project/mcp-bastion-python/1.0.17/)
117
+ [![PyPI: mcp-bastion-python 2.0.0](https://img.shields.io/pypi/v/mcp-bastion-python?logo=python)](https://pypi.org/project/mcp-bastion-python/2.0.0/)
114
118
  [![PePy all-time downloads (mcp-bastion-python)](https://img.shields.io/pepy/dt/mcp-bastion-python?label=PePy%20all-time%20downloads)](https://pepy.tech/projects/mcp-bastion-python)
115
119
  [![Python](https://img.shields.io/pypi/pyversions/mcp-bastion-python)](https://pypi.org/project/mcp-bastion-python/)
116
120
  [![CI](https://img.shields.io/github/actions/workflow/status/vaquarkhan/MCP-Bastion/ci.yml?branch=main&label=CI)](https://github.com/vaquarkhan/MCP-Bastion/actions/workflows/ci.yml)
@@ -119,7 +123,104 @@ Description-Content-Type: text/markdown
119
123
  [![License: Source Available](https://img.shields.io/badge/license-Source%20Available-orange.svg)](LICENSE)
120
124
  [![Website](https://img.shields.io/badge/website-vaquarkhan.github.io/MCP--Bastion-blue?logo=github)](https://vaquarkhan.github.io/MCP-Bastion/)
121
125
 
122
- **The security layer MCP servers are missing.** Your agent can call databases, APIs, and shell tools. One bad prompt can leak PII; one runaway loop can burn your API budget in minutes. MCP-Bastion wraps your MCP server with **local** guardrails: injection blocking, PII redaction, and **denial-of-wallet caps** (iteration limits, token budget, optional USD ceilings), under **5ms overhead**, with no third-party safety API.
126
+ **The Zero-Trust control plane for MCP agents.** Your agent can call databases, APIs, and shell tools. One bad prompt can leak PII; one runaway loop can burn your API budget in minutes; three agents on one server with no identity boundary is a confused-deputy incident waiting to happen. MCP-Bastion wraps your MCP server with **local** guardrails: **agent IAM**, supply-chain checksums, injection blocking, PII redaction, and **denial-of-wallet caps**, under **5ms overhead**, with no third-party safety API.
127
+
128
+ <p align="center">
129
+ <img
130
+ src="images/mcp-bastion-mcp-surface-scale.png"
131
+ alt="MCP-Bastion 2.0.0: full MCP method coverage and Redis shared state for multi-replica deployments"
132
+ width="960"
133
+ style="max-width:100%; height:auto; border-radius:12px; border:1px solid #1e293b;"
134
+ />
135
+ </p>
136
+
137
+ ## Why MCP-Bastion? (Solving the 2026 MCP Security Crisis)
138
+
139
+ As noted in the NSA's recent Cybersecurity Information Sheet on MCP security and the OWASP MCP Top 10, traditional AppSec tools cannot secure agentic workflows. The gap is **runtime governance** and the **confused deputy problem**: multiple AI agents sharing one MCP server with no native identity boundary. Public registry typosquatting and unverified servers have made supply-chain verification a board-level concern.
140
+
141
+ MCP-Bastion acts as the **Zero-Trust Control Plane** for your agents, addressing the hardest production problems:
142
+
143
+ 1. **The Confused Deputy (Agent IAM):** Identity-aware routing binds API tokens to **Agent Identities** and enforces strict per-tool RBAC. Your customer-support bot can call `search_docs`, not `delete_user`.
144
+ 2. **Supply chain & typosquatting defense:** Cryptographic SHA-256 manifest verification blocks traffic when MCP server artifacts drift from your signed-off checksums.
145
+ 3. **Data exfiltration & injection prevention:** PromptGuard heuristics + ML block jailbreaks locally; Presidio scrubs outbound PII before it hits a model context window.
146
+
147
+ ### Define your agent policies (`bastion.yaml`)
148
+
149
+ ```yaml
150
+ # Stop the Confused Deputy Problem — Identity-Aware Routing
151
+ agent_iam:
152
+ enabled: true
153
+ token_metadata_key: bastion_agent_token
154
+ agents:
155
+ - id: customer_support_bot
156
+ token_env: BASTION_TOKEN_SUPPORT
157
+ allowed_tools: ["search_docs", "get_ticket_status"]
158
+ blocked_tools: ["execute_sql", "delete_user"]
159
+ rate_limit:
160
+ max_iterations: 5
161
+
162
+ # Supply-chain checksums before any tool executes
163
+ server_verification:
164
+ enabled: true
165
+ on_mismatch: block
166
+ base_path: .
167
+ manifest_path: mcp-server.manifest.json
168
+ ```
169
+
170
+ Generate a manifest after a trusted build: `mcp-bastion manifest server.py pyproject.toml -o mcp-server.manifest.json`
171
+
172
+ Deep dive: [docs/RUNTIME_GOVERNANCE.md](docs/RUNTIME_GOVERNANCE.md) · [docs/ROADMAP.md](docs/ROADMAP.md)
173
+
174
+ ### Full MCP surface + horizontal scale (2.0.0)
175
+
176
+ Previously, most pillars ran only on **`tools/call`**. **2.0.0** extends the pipeline to **`resources/read`**, **`prompts/get`**, **`sampling/createMessage`**, and **`elicitation/create`** — closing exfil/injection gaps on the rest of the MCP surface.
177
+
178
+ For **multi-replica** deployments, enable **`state_backend.type: redis`** so rate limits, replay nonces, cost budgets, and session tool scope are shared across pods (default `memory` is single-process).
179
+
180
+ ```yaml
181
+ state_backend:
182
+ type: redis
183
+ redis_url: redis://127.0.0.1:6379/0
184
+ ```
185
+
186
+ `pip install mcp-bastion-python[redis]` · Deep dive: [docs/MCP_SURFACE_AND_SCALE.md](docs/MCP_SURFACE_AND_SCALE.md)
187
+
188
+ ### Production hardening adopted in 2.0.0
189
+
190
+ Battle-tested patterns from the broader MCP gateway ecosystem, wired into the middleware stack:
191
+
192
+ | Feature | What you get |
193
+ |--------|----------------|
194
+ | **JSONPath argument guards** | Block or redact tool arguments by **tool glob + JSONPath + regex** before execution (argv-array evasion aware). `pip install mcp-bastion-python[policy]` |
195
+ | **RBAC fnmatch globs** | Role permissions like `read_*` / `files_*` with **specificity-aware** matching |
196
+ | **Audit JSONL + `mcp-bastion tail`** | Append-only compliance log; `audit.jsonl_path` in config or `mcp-bastion tail -p audit.jsonl` |
197
+ | **Cost checkpoint** | Optional disk persistence for session totals across restarts (`cost_tracker.checkpoint_path`, memory backend only) |
198
+
199
+ ```yaml
200
+ argument_guards:
201
+ enabled: true
202
+ rules:
203
+ - name: block_shell
204
+ match: "run_*"
205
+ arg: "$.command"
206
+ pattern: "(rm\\s+-rf|curl\\s+.*\\|.*sh)"
207
+ action: block
208
+
209
+ audit:
210
+ jsonl_path: .bastion/audit.jsonl
211
+
212
+ cost_tracker:
213
+ checkpoint_path: .bastion/cost-checkpoint.json
214
+ ```
215
+
216
+ <p align="center">
217
+ <img
218
+ src="images/mcp-bastion-runtime-governance.png"
219
+ alt="MCP-Bastion 2.0.0 Zero-Trust Runtime Governance: full MCP surface, Redis scale, Agent IAM, and beyond-OWASP coverage"
220
+ width="960"
221
+ style="max-width:100%; height:auto; border-radius:12px; border:1px solid #1e293b;"
222
+ />
223
+ </p>
123
224
 
124
225
  ### Why developers adopt it
125
226
 
@@ -128,7 +229,7 @@ Description-Content-Type: text/markdown
128
229
  | **Guardrails without a rewrite** | Drop-in middleware: `secure_fastmcp(mcp)` or one `bastion.yaml` |
129
230
  | **Privacy your legal team accepts** | PromptGuard + Presidio run **in your process**; data stays on your network |
130
231
  | **Stop runaway agents & budget burn** | **On by default:** 15 tool calls/session, 60s timeout, 50k token budget. **Optional:** per-tool caps, USD session/day limits, response offload |
131
- | **Shrink context & cut token spend** | **Opt-in:** discovery filter (fewer tools in `tools/list`), output budget + session offload, semantic cache — less context in every turn |
232
+ | **Shrink context & cut token spend** | **Opt-in:** discovery filter (fewer tools in `tools/list`), output budget + session offload (**up to ~99% on oversized tool outputs**), lexical similarity cache — [measured benchmarks](docs/BENCHMARKS.md) |
132
233
  | **Something that ships today** | PyPI, npm, Docker on GHCR, FastMCP, TypeScript wrapper, CI validate, live dashboard |
133
234
  | **Policy your team can review** | `bastion.yaml` in Git, hot reload, OWASP-aligned controls ([docs/PILLARS.md](docs/PILLARS.md)) |
134
235
 
@@ -150,17 +251,29 @@ Blocked calls return standard errors (`RateLimitExceededError` **-32002**, `Toke
150
251
 
151
252
  ### Token reduction & cost saving
152
253
 
153
- Bastion does not only **block** runaway spend — it **reduces** how many tokens reach the model on every turn:
254
+ Bastion does not only **block** runaway spend — it **reduces** how much **tool output and tool-catalog** tokens reach the model on each turn (not the user’s LLM prompt text itself):
154
255
 
155
256
  | Savings lever | What it does | Default |
156
257
  |---------------|--------------|---------|
157
- | **Discovery filter** | Hides unused tools from `tools/list` so agents carry a smaller tool catalog in context | Opt-in |
158
- | **Output budget + offload** | Truncates oversized tool responses; stores the rest in-session for `bastion_get_offloaded` | Opt-in |
159
- | **Semantic cache** | Skips redundant tool calls when inputs match a prior result | Opt-in |
258
+ | **Discovery filter** | Hides unused tools from `tools/list` so agents carry a smaller tool catalog in context (~**85%** fewer catalog tokens in [benchmarks](docs/BENCHMARKS.md) with 20→3 tools) | Opt-in |
259
+ | **Output budget + offload** | Truncates oversized tool responses; stores the rest in-session for `bastion_get_offloaded` (**up to ~99.7%** on 50k-token dumps; **0%** when already under budget) | Opt-in |
260
+ | **Lexical similarity cache** | Skips redundant tool calls when queries are near-identical (Jaccard word overlap — not embedding “semantic” search) | Opt-in |
160
261
  | **Token budget caps** | Hard stop before session token burn exceeds your limit | **On** (50k tokens) |
161
262
  | **USD session/day limits** | Dollar ceilings via cost tracker | Opt-in |
162
263
 
163
- Less context per turn means lower LLM input costwithout sending prompts to a third-party optimizer API.
264
+ There is **no honest single “X% prompt reduction”** figuresavings are **input-dependent**. See **[docs/BENCHMARKS.md](docs/BENCHMARKS.md)** for reproducible pytest benchmarks and live numbers.
265
+
266
+ <p align="center">
267
+ <img
268
+ src="images/mcp-bastion-finops-benchmarks.png"
269
+ alt="MCP-Bastion benchmarks: RBAC tool-level matrix, output budget up to 99% on large tool responses, discovery filter catalog savings, lexical cache hit/miss"
270
+ width="960"
271
+ style="max-width:100%; height:auto; border-radius:12px; border:1px solid #1e293b;"
272
+ />
273
+ </p>
274
+ <p align="center"><sub>Reproduce: <code>PYTHONPATH=src python -m pytest tests/test_benchmarks_finops_rbac.py -v</code> · Regenerate report: <code>python scripts/generate_benchmark_report.py</code></sub></p>
275
+
276
+ Less tool output and catalog noise per turn means lower LLM input cost — without sending prompts to a third-party optimizer API.
164
277
 
165
278
  **Bottom line:** MCP turned every server into an agent gateway overnight. Bastion is the firewall that makes that gateway safe to run in production — in **three lines of code** or one config file.
166
279
 
@@ -182,12 +295,12 @@ All **10** [OWASP MCP Top 10](https://owasp.org/www-project-mcp-top-10/) risks a
182
295
  | ID | Risk | Bastion controls |
183
296
  |----|------|------------------|
184
297
  | MCP01 | Token / secret exposure | PII redaction, audit trail, outbound response scan |
185
- | MCP02 | Privilege escalation | RBAC, rate limits, cost caps, session tool scope |
298
+ | MCP02 | Privilege escalation | RBAC, **agent IAM**, rate limits, cost caps, session tool scope |
186
299
  | MCP03 | Tool poisoning | Prompt guard, content filter, response scan, metadata guard, grounding guard |
187
- | MCP04 | Supply chain | Circuit breaker, `doctor` CLI, audit, observability |
300
+ | MCP04 | Supply chain | Circuit breaker, **`server_verification` checksums**, `doctor` CLI, `mcp-bastion manifest`, audit |
188
301
  | MCP05 | Command injection | Prompt guard, content filter, schema validation |
189
302
  | MCP06 | Intent subversion | Rate limits, replay guard, per-tool caps, semantic firewall |
190
- | MCP07 | Weak authentication | RBAC, edge auth |
303
+ | MCP07 | Weak authentication | RBAC, edge auth, **agent IAM** (per-agent tokens) |
191
304
  | MCP08 | Audit & telemetry | Audit log, dashboard, Prometheus, OTEL, alerts |
192
305
  | MCP09 | Shadow MCP servers | Central `bastion.yaml` policy, metrics, discovery filter |
193
306
  | MCP10 | Context injection | PII redaction, response scan, output budget, discovery filter |
@@ -205,12 +318,12 @@ All **10** [OWASP MCP Top 10](https://owasp.org/www-project-mcp-top-10/) risks a
205
318
 
206
319
  **Token reduction & cost saving**
207
320
 
208
- | Lever | Controls |
209
- |-------|----------|
210
- | Smaller tool catalog in context | Discovery filter on `tools/list` |
211
- | Less output in every turn | Output budget, session offload, `bastion_get_offloaded` |
212
- | Fewer redundant calls | Semantic cache |
213
- | Predictable spend | Token budget caps, USD session/day limits |
321
+ | Lever | Controls | Benchmark |
322
+ |-------|----------|-----------|
323
+ | Smaller tool catalog in context | Discovery filter on `tools/list` | ~85% catalog tokens (20→3 tools) — [BENCHMARKS.md](docs/BENCHMARKS.md) |
324
+ | Less tool output in every turn | Output budget, session offload, `bastion_get_offloaded` | Up to ~99.7% on oversized dumps; 0% when under budget |
325
+ | Fewer redundant calls | Lexical similarity cache (Jaccard overlap) | Exact repeat hits; paraphrase misses at 0.9 |
326
+ | Predictable spend | Token budget caps, USD session/day limits | Session defaults on |
214
327
 
215
328
  Deep-dive mapping and integration hooks: [docs/SECURITY_OBSERVABILITY.md](docs/SECURITY_OBSERVABILITY.md) · [docs/ATTACK_PREVENTION.md](docs/ATTACK_PREVENTION.md)
216
329
 
@@ -238,7 +351,7 @@ middleware = build_middleware_from_config() # loads bastion.yaml
238
351
 
239
352
  More paths (TypeScript, CI validate, Docker): **[docs/QUICK_START.md](docs/QUICK_START.md)** · **[docs/README.md](docs/README.md)** · **[website](https://vaquarkhan.github.io/MCP-Bastion/)**
240
353
 
241
- - **Prompt injection defense:** Meta PromptGuard blocks adversarial payloads locally.
354
+ - **Prompt injection defense:** Heuristic jailbreak blocking out of the box; Meta PromptGuard ML when Hugging Face access is configured.
242
355
  - **PII redaction:** Presidio masks SSN, email, phone in outbound content.
243
356
  - **Denial-of-wallet protection:** Token buckets, iteration caps, token budget, cost tracking.
244
357
  - **Response scan:** Blocks jailbreak patterns in outbound tool/resource text.
@@ -308,7 +421,7 @@ Hooks into MCP SDKs (TypeScript, Python) and FastMCP via standard middleware. No
308
421
 
309
422
  ### Complete feature catalog
310
423
 
311
- **Pillar definitions:** Security controls, `bastion.yaml` sections, and how they relate to dashboard health rows are documented in [docs/PILLARS.md](docs/PILLARS.md) (canonical reference; avoids ambiguous “total pillar” counts). The same page lists **extended** features restored in 1.0.16+ (semantic firewall, sensitive classifier, external policy, edge auth, tool allowlist, session scope, tool metadata guard, multi-tenant, audit hash chain, pricing hooks, telemetry sinks, **red team** and **doctor** CLIs, etc.) and **FinOps/context** pillars in 1.0.17+ (output budget, discovery filter, response scan, grounding guard).
424
+ **Pillar definitions:** Security controls, `bastion.yaml` sections, and how they relate to dashboard health rows are documented in [docs/PILLARS.md](docs/PILLARS.md) (canonical reference; avoids ambiguous “total pillar” counts). The same page lists **extended** features restored in 1.0.16+ (semantic firewall, sensitive classifier, external policy, edge auth, tool allowlist, session scope, tool metadata guard, multi-tenant, audit hash chain, pricing hooks, telemetry sinks, **red team** and **doctor** CLIs, etc.), **FinOps/context** pillars in 1.0.17+ (output budget, discovery filter, response scan, grounding guard), and **runtime governance** (agent IAM, server verification — introduced in 1.0.18+, **shipped in 2.0.0**).
312
425
 
313
426
  > **Deeper context:** [docs/SECURITY_OBSERVABILITY.md](docs/SECURITY_OBSERVABILITY.md) — **OWASP MCP Top 10** alignment, attack scenarios, and SIEM/log integrations. **Framework add-ons** (LangChain, OpenAI, Bedrock, …) are listed under [Framework Integrations](#framework-integrations) below.
314
427
 
@@ -324,7 +437,12 @@ Hooks into MCP SDKs (TypeScript, Python) and FastMCP via standard middleware. No
324
437
 
325
438
  | Feature | What you get |
326
439
  |--------|----------------|
327
- | **RBAC** | **Tool-level** allow/deny by **role** (from request metadata); map roles to tool names in `bastion.yaml`. |
440
+ | **Agent IAM (Confused Deputy)** | Bind **API tokens** to **agent identities**; per-agent `allowed_tools` / `blocked_tools`, **resource URI** allow/block, optional rate limits — stops a support bot from calling admin tools or reading secret resources. See [docs/RUNTIME_GOVERNANCE.md](docs/RUNTIME_GOVERNANCE.md). |
441
+ | **Full MCP surface guards (2.0.0)** | **`resources/read`**, **`prompts/get`**, **`sampling/createMessage`**, **`elicitation/create`** — same inbound/outbound pillars as tool calls (not only `tools/call`). [docs/MCP_SURFACE_AND_SCALE.md](docs/MCP_SURFACE_AND_SCALE.md) |
442
+ | **Distributed state (2.0.0)** | **`state_backend: redis`** — shared rate limits, replay nonces, cost caps, session scope across replicas. `pip install mcp-bastion-python[redis]` |
443
+ | **Server verification (supply chain)** | SHA-256 **manifest checksums** verified at startup and on every `tools/call`; `mcp-bastion manifest` generates trusted manifests after a signed-off build. |
444
+ | **RBAC** | **Tool-level** allow/deny by **role** (from request metadata); **fnmatch globs** (`read_*`) with specificity-aware matching in `bastion.yaml`. **Pair with Agent IAM or edge auth** — alone, roles are only as trustworthy as whatever sets `metadata["role"]`. [Live matrix →](docs/BENCHMARKS.md#rbac-tool-level-opt-in) |
445
+ | **Argument guards (2.0.0)** | **JSONPath + regex** block/redact on `tools/call` arguments before schema validation — stops shell injection and secret exfil in argv-style payloads. |
328
446
  | **Schema validation** | Validate `tools/call` arguments against **JSON Schema** before the tool runs (block malformed or bypass attempts). |
329
447
  | **Replay guard** | **Nonce** tracking to reject replayed requests (configurable **require_nonce**). |
330
448
  | **Rate limiting** | **Token-bucket** style limits: **max iterations** per session, **timeout**, **token budget**—stops runaway loops and brute-force patterns. |
@@ -334,15 +452,15 @@ Hooks into MCP SDKs (TypeScript, Python) and FastMCP via standard middleware. No
334
452
 
335
453
  | Feature | What you get |
336
454
  |--------|----------------|
337
- | **Cost tracker** | Per-**session** and optional per-**day** USD caps; blocks when budget is exceeded. |
338
- | **Semantic cache** | Optional **similarity-based** caching for tool semantics (reduce duplicate expensive calls). |
455
+ | **Cost tracker** | Per-**session** and optional per-**day** USD caps; blocks when budget is exceeded. Optional **disk checkpoint** for restart-safe totals (memory backend). |
456
+ | **Semantic cache** (lexical) | Optional **Jaccard word-overlap** cache for near-identical tool queries not embedding-based; see [benchmarks](docs/BENCHMARKS.md#lexical-similarity-cache-opt-in-semantic-cache-in-config). |
339
457
  | **Low overhead** | Middleware on the hot path targeting **&lt;5 ms** typical overhead (see [docs/METRICS.md](docs/METRICS.md)). |
340
458
 
341
459
  #### Audit, metrics & alerting
342
460
 
343
461
  | Feature | What you get |
344
462
  |--------|----------------|
345
- | **Audit logging** | Structured **allow/deny** decisions with **reason**, **tool**, **tenant_id**, **trace_id**, **request_id**—feed SOC / compliance. |
463
+ | **Audit logging** | Structured **allow/deny** decisions with **reason**, **tool**, **tenant_id**, **trace_id**, **request_id**—feed SOC / compliance. Optional **JSONL file sink** + **`mcp-bastion tail`**. |
346
464
  | **Alert sinks** | **Slack** incoming webhook; **generic HTTP** webhooks (PagerDuty, Teams, custom APIs); **multiple URLs**; **retry**, **backoff**, **timeout** in `bastion.yaml`. |
347
465
  | **In-memory metrics** | **Global MetricsStore**: requests, blocks, PII counts, cost, per-tool stats, latency samples, rolling **time series** buckets. |
348
466
  | **Real-time dashboard** | **Web UI** with a top **KPI summary** (totals, block %, top threat, active users/tenants), **traffic & block charts**, **blocked-by-reason/kind** (with readable reasons / tooltips), **PII by entity** (severity-style coloring, e.g. high-risk types emphasized), **top tools**, **cost by user**, **latency P50/P95/P99**, **forensics table** (tenant filter, trace/replay helpers), **recent alerts**, **insights & anomalies** (heuristic signals), **dark/light theme**, **Prometheus** `/metrics`, **JSON** `/api/metrics`, loading/empty guidance instead of a blank first paint. |
@@ -355,7 +473,7 @@ Hooks into MCP SDKs (TypeScript, Python) and FastMCP via standard middleware. No
355
473
  | **Policy-as-code** | Single **`bastion.yaml`**: toggles for all request-path controls plus audit, alerts, and hot reload ([docs/PILLARS.md](docs/PILLARS.md)); load via `load_config` / `build_middleware_from_config`. |
356
474
  | **Hot reload** | Optional **reload `bastion.yaml` on change** without restarting the MCP server ([docs/POLICY_AS_CODE.md](docs/POLICY_AS_CODE.md)). |
357
475
  | **Composable middleware** | **`compose_middleware`** ordering; **`MCPBastionMiddleware`** flags for each pillar. |
358
- | **CLI** | **`mcp-bastion validate`**, **`serve`** (HTTP MCP), **`dashboard`** (optional **`--reload`** / **`--demo`**), **`redteam`**, **`doctor`** — [docs/CLI.md](docs/CLI.md). |
476
+ | **CLI** | **`mcp-bastion validate`**, **`manifest`** (SHA-256 manifest for server verification), **`serve`** (HTTP MCP), **`dashboard`** (optional **`--reload`** / **`--demo`**), **`redteam`**, **`doctor`** — [docs/CLI.md](docs/CLI.md). |
359
477
  | **Python + TypeScript** | **`mcp-bastion-python`** on PyPI; **`@mcp-bastion/core`** on npm for TypeScript MCP servers (rate limits in-process; prompt/PII via optional sidecar). |
360
478
  | **Containers** | **Dockerfile**, **docker-compose** profiles (proxy + optional dashboard) — [DOCKER.md](DOCKER.md). **Prebuilt images (GHCR):** [`mcp-bastion-proxy`](https://github.com/vaquarkhan/MCP-Bastion/pkgs/container/mcp-bastion-proxy), [`mcp-bastion-dashboard`](https://github.com/vaquarkhan/MCP-Bastion/pkgs/container/mcp-bastion-dashboard) — published on each `v*` tag ([publish-docker.yml](.github/workflows/publish-docker.yml)). |
361
479
 
@@ -429,6 +547,7 @@ Full index: **[docs/README.md](docs/README.md)** (docs hub) · published site en
429
547
  | [docs/SUPPLY_CHAIN.md](docs/SUPPLY_CHAIN.md) | CI merge gates, releases, npm provenance, PyPI Trusted Publishing |
430
548
  | [docs/INTEGRATION_MODELS.md](docs/INTEGRATION_MODELS.md) | Middleware + `bastion.yaml` vs “change base URL”; bridge for Python, TS, Desktop, HTTP, integrations |
431
549
  | [examples/ci/README.md](examples/ci/README.md) | Copy-paste GitHub Actions snippet to run `mcp-bastion validate` on your policy file |
550
+ | [docs/BENCHMARKS.md](docs/BENCHMARKS.md) | **Measured** RBAC matrix, output-budget reduction (up to ~99% on large tool outputs), discovery filter, lexical cache — pytest + report generator |
432
551
  | [docs/REDTEAM.md](docs/REDTEAM.md) | Interpreting harness / red-team scores; which `bastion.yaml` pillars to enable; Node vs Python **scope** (`packages/core/README.md`) |
433
552
  | [docs/SECURITY_OBSERVABILITY.md](docs/SECURITY_OBSERVABILITY.md) | **OWASP MCP Top 10**, integration hooks, **fleet-scale `bastion.yaml` rollout**, **SIEM / SOC audit** patterns |
434
553
  | [docs/METRICS.md](docs/METRICS.md) | Performance overhead (&lt;5ms) and effectiveness metrics (dashboard, Prometheus, OTEL) |
@@ -437,6 +556,7 @@ Full index: **[docs/README.md](docs/README.md)** (docs hub) · published site en
437
556
  | [docs/QUICK_START.md](docs/QUICK_START.md) | Minimal FastMCP / `bastion.yaml` / CI snippets (time-to-value) |
438
557
  | [docs/DISCOVERY.md](docs/DISCOVERY.md) | Registry and ecosystem discovery checklist |
439
558
  | [docs/ROADMAP.md](docs/ROADMAP.md) | High-level directions; execution tracked in GitHub Issues |
559
+ | [docs/ENGINEERING_10_10.md](docs/ENGINEERING_10_10.md) | Strategic path to 10/10 on injection depth, tool poisoning, gateway maturity, FinOps metrics, project maturity |
440
560
  | [CONTRIBUTING.md](CONTRIBUTING.md) | Contributor guide and **`good first issue`** ideas |
441
561
 
442
562
  ### One-Line Docker
@@ -489,7 +609,7 @@ On every pull request and push to `main`, [`.github/workflows/ci.yml`](.github/w
489
609
 
490
610
  1. `pip install -e ".[dev,policy,dashboard]"` — install the Python package with tests, YAML policy loading, and FastAPI for dashboard tests.
491
611
  2. `mcp-bastion validate --config bastion.yaml.example` — ensure the example policy file loads.
492
- 3. `pytest --cov=mcp_bastion --cov-fail-under=92` — full Python test suite with **≥92%** line coverage on `src/mcp_bastion` (see `[tool.coverage.*]` in `pyproject.toml` for measured paths and gates).
612
+ 3. `python -m pytest --cov=mcp_bastion --cov-fail-under=92` — full Python test suite with **≥92%** line coverage on `src/mcp_bastion` (see `[tool.coverage.*]` in `pyproject.toml` for measured paths and gates).
493
613
  4. `npm ci` and `npm test` — TypeScript workspace tests.
494
614
 
495
615
  To validate **your** repo’s `bastion.yaml` in CI without cloning MCP-Bastion, see [examples/ci/README.md](examples/ci/README.md).
@@ -563,7 +683,7 @@ uv add mcp-bastion-python
563
683
  # or
564
684
  pip install mcp-bastion-python
565
685
  # pinned latest
566
- pip install mcp-bastion-python==1.0.17
686
+ pip install mcp-bastion-python==2.0.0
567
687
  ```
568
688
 
569
689
  **Prerequisites (recommended)**
@@ -574,7 +694,9 @@ pip install mcp-bastion-python==1.0.17
574
694
  - **Policy-as-Code (`bastion.yaml`):** install YAML support:
575
695
  `pip install mcp-bastion-python[policy]`
576
696
  (adds `pyyaml`; otherwise you may get `ImportError` when loading policy files).
577
- - **PromptGuard fail-open:** if the PromptGuard model fails to load or inference errors, MCP-Bastion **allows** the request and logs a warning. Treat this as a security degradation and fix the model/runtime before production.
697
+ - **Prompt injection (PromptGuard):** two layers:
698
+ 1. **Regex heuristics** (always on) block obvious jailbreak strings such as “ignore previous instructions” — no model download required.
699
+ 2. **Meta Llama Prompt Guard 2** (`meta-llama/Llama-Prompt-Guard-2-86M`) is a **gated** Hugging Face model. Request access, then run `huggingface-cli login`. Without ML, obvious attacks are still blocked; unverified payloads are **blocked** when `fail_open: false` (default). Run `mcp-bastion doctor` to verify ML availability.
578
700
 
579
701
  The PyPI wheel ships the full `mcp_bastion` tree (including `config`, `cli`, `otel`, dashboard metrics, and alert sinks). If you use an older wheel that omits modules, upgrade to the current release.
580
702
 
@@ -945,6 +1067,9 @@ When MCP-Bastion blocks a request, it returns standard MCP/JSON-RPC errors:
945
1067
  | -32015 | `SessionScopeExceededError` | Too many distinct tools per session (scope creep) |
946
1068
  | -32016 | `ToolMetadataPoisoningError` | Tool list / metadata failed safety checks |
947
1069
  | -32017 | `GroundingViolationError` | Ungrounded file reference in tool output |
1070
+ | -32018 | `PromptGuardUnavailableError` | PromptGuard ML unavailable and fail-closed (or heuristics disabled) |
1071
+ | -32019 | `AgentAccessDeniedError` | Authenticated agent attempted a tool outside its IAM policy |
1072
+ | -32020 | `ServerVerificationError` | MCP server file checksums do not match trusted manifest |
948
1073
 
949
1074
  ```python
950
1075
  # Python: exceptions
@@ -966,6 +1091,9 @@ from mcp_bastion.errors import (
966
1091
  SessionScopeExceededError,
967
1092
  ToolMetadataPoisoningError,
968
1093
  GroundingViolationError,
1094
+ PromptGuardUnavailableError,
1095
+ AgentAccessDeniedError,
1096
+ ServerVerificationError,
969
1097
  )
970
1098
  import logging
971
1099
  logger = logging.getLogger(__name__)
@@ -990,6 +1118,9 @@ except (
990
1118
  SessionScopeExceededError,
991
1119
  ToolMetadataPoisoningError,
992
1120
  GroundingViolationError,
1121
+ PromptGuardUnavailableError,
1122
+ AgentAccessDeniedError,
1123
+ ServerVerificationError,
993
1124
  ) as e:
994
1125
  logger.warning("blocked: %s", e.to_mcp_error())
995
1126
  ```
@@ -1029,7 +1160,7 @@ Connect via HTTP (`http://localhost:8000/mcp`) or stdio, then:
1029
1160
 
1030
1161
  ```bash
1031
1162
  # Python (PYTHONPATH=src on Windows: $env:PYTHONPATH="src")
1032
- pytest tests/ -v
1163
+ python -m pytest tests/ -v
1033
1164
 
1034
1165
  # TypeScript
1035
1166
  npm run test --workspace=@mcp-bastion/core