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.
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/LICENSE +1 -1
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/PKG-INFO +166 -35
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/README.md +155 -28
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/app.py +134 -3
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/static/chart.umd.min.js +1 -2
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/static/dashboard-app.js +111 -10
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/pyproject.toml +12 -6
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/__init__.py +1 -1
- mcp_bastion_python-2.0.0/src/mcp_bastion/audit_jsonl.py +42 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/benchmarks/__init__.py +5 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/benchmarks/finops_rbac.py +221 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/cli.py +126 -5
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/config.py +267 -6
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/demo_dashboard_metrics.py +6 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/doctor.py +387 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/errors.py +55 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/middleware.py +511 -31
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/otel.py +6 -1
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/agent_iam.py +231 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/alerts.py +13 -1
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/argument_guards.py +124 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/audit_log.py +6 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/budget_principal.py +42 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/content_filter.py +10 -4
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/content_normalize.py +31 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/cost_tracker.py +245 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/external_policy.py +31 -16
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/injection_heuristics.py +47 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/metrics.py +44 -1
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/output_budget.py +22 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/prompt_guard.py +167 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/rate_limit.py +221 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/rbac.py +92 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/replay_guard.py +25 -9
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/response_scanner.py +8 -20
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/schema_validation.py +55 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/server_verification.py +192 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/state_backend.py +194 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/stdio_guard.py +87 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/pillars/tool_metadata_fingerprint.py +61 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/policy_simulator.py +3 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/redteam.py +79 -6
- mcp_bastion_python-2.0.0/src/mcp_bastion/serve.py +48 -0
- mcp_bastion_python-2.0.0/src/mcp_bastion/transport_hardening.py +152 -0
- mcp_bastion_python-1.0.17/dashboard/static/chart.umd.js.map +0 -1
- mcp_bastion_python-1.0.17/src/mcp_bastion/doctor.py +0 -97
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/cost_tracker.py +0 -103
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/prompt_guard.py +0 -97
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/rate_limit.py +0 -159
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/rbac.py +0 -56
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/.gitignore +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/NOTICE +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/README.md +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/static/mcp-bastian.png +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/dashboard/static/mcp-bastian.svg +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/base.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/demo_live_traffic.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/governance_beacon.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/__init__.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/audit_hash_chain.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/circuit_breaker.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/grounding_guard.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/pii_redaction.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/pricing.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/semantic_cache.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/semantic_firewall.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/sensitive_classifier.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/session_offload.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/telemetry_sinks.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/pillars/tokens.py +0 -0
- {mcp_bastion_python-1.0.17 → mcp_bastion_python-2.0.0}/src/mcp_bastion/tenant.py +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-bastion-python
|
|
3
|
-
Version:
|
|
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/
|
|
6
|
-
Project-URL: Repository, https://github.com/
|
|
7
|
-
Project-URL: Documentation, https://github.com/
|
|
8
|
-
Author:
|
|
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
|
|
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.
|
|
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
|
-
[](https://pypi.org/project/mcp-bastion-python/2.0.0/)
|
|
114
118
|
[](https://pepy.tech/projects/mcp-bastion-python)
|
|
115
119
|
[](https://pypi.org/project/mcp-bastion-python/)
|
|
116
120
|
[](https://github.com/vaquarkhan/MCP-Bastion/actions/workflows/ci.yml)
|
|
@@ -119,7 +123,104 @@ Description-Content-Type: text/markdown
|
|
|
119
123
|
[](LICENSE)
|
|
120
124
|
[](https://vaquarkhan.github.io/MCP-Bastion/)
|
|
121
125
|
|
|
122
|
-
**The
|
|
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,
|
|
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
|
|
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
|
-
| **
|
|
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
|
-
|
|
264
|
+
There is **no honest single “X% prompt reduction”** figure — savings 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
|
|
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 |
|
|
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
|
|
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.)
|
|
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
|
-
| **
|
|
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 **
|
|
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 **<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 (<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==
|
|
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
|
-
- **
|
|
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
|