mcp-bastion-python 1.0.16__tar.gz → 1.0.17__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.16 → mcp_bastion_python-1.0.17}/PKG-INFO +206 -51
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/README.md +205 -50
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/pyproject.toml +1 -1
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/__init__.py +1 -1
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/config.py +44 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/errors.py +7 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/middleware.py +268 -13
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/grounding_guard.py +131 -0
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/output_budget.py +119 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/rate_limit.py +50 -10
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/response_scanner.py +62 -0
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/session_offload.py +93 -0
- mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/tokens.py +105 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/policy_simulator.py +1 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/.gitignore +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/LICENSE +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/NOTICE +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/README.md +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/app.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/chart.umd.js.map +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/chart.umd.min.js +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/dashboard-app.js +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/mcp-bastian.png +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/mcp-bastian.svg +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/base.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/cli.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/demo_dashboard_metrics.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/demo_live_traffic.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/doctor.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/governance_beacon.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/otel.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/__init__.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/alerts.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/audit_hash_chain.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/audit_log.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/circuit_breaker.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/content_filter.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/cost_tracker.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/external_policy.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/metrics.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/pii_redaction.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/pricing.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/prompt_guard.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/rbac.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/replay_guard.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/schema_validation.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/semantic_cache.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/semantic_firewall.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/sensitive_classifier.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/telemetry_sinks.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/redteam.py +0 -0
- {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/tenant.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-bastion-python
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.17
|
|
4
4
|
Summary: Security middleware for MCP servers protecting LLM agents from prompt injection, resource exhaustion, and PII leakage
|
|
5
5
|
Project-URL: Homepage, https://github.com/mcp-bastion/mcp-bastion
|
|
6
6
|
Project-URL: Repository, https://github.com/mcp-bastion/mcp-bastion
|
|
@@ -97,41 +97,186 @@ Provides-Extra: policy
|
|
|
97
97
|
Requires-Dist: pyyaml>=6.0; extra == 'policy'
|
|
98
98
|
Description-Content-Type: text/markdown
|
|
99
99
|
|
|
100
|
-
<p align="center">
|
|
101
|
-
<img src="images/mcp-bastian.png" alt="MCP-Bastion" width="520" />
|
|
102
|
-
</p>
|
|
103
|
-
|
|
104
100
|
# MCP-Bastion
|
|
105
101
|
|
|
106
102
|
<!-- mcp-name: io.github.vaquarkhan/mcp-bastion -->
|
|
107
103
|
|
|
108
|
-
|
|
104
|
+
<p align="center">
|
|
105
|
+
<img
|
|
106
|
+
src="images/mcp-bastian.png"
|
|
107
|
+
alt="MCP-Bastion — Fortifying the Model Context Protocol"
|
|
108
|
+
width="720"
|
|
109
|
+
style="max-width:100%; height:auto;"
|
|
110
|
+
/>
|
|
111
|
+
</p>
|
|
109
112
|
|
|
110
|
-
[](https://pypi.org/project/mcp-bastion-python/1.0.17/)
|
|
114
|
+
[](https://pepy.tech/projects/mcp-bastion-python)
|
|
112
115
|
[](https://pypi.org/project/mcp-bastion-python/)
|
|
113
116
|
[](https://github.com/vaquarkhan/MCP-Bastion/actions/workflows/ci.yml)
|
|
117
|
+
[](https://github.com/vaquarkhan/MCP-Bastion/pkgs/container/mcp-bastion-proxy)
|
|
118
|
+
[](https://github.com/vaquarkhan/MCP-Bastion/pkgs/container/mcp-bastion-dashboard)
|
|
114
119
|
[](LICENSE)
|
|
120
|
+
[](https://vaquarkhan.github.io/MCP-Bastion/)
|
|
121
|
+
|
|
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.
|
|
123
|
+
|
|
124
|
+
### Why developers adopt it
|
|
125
|
+
|
|
126
|
+
| You need… | MCP-Bastion gives you… |
|
|
127
|
+
|-----------|-------------------------|
|
|
128
|
+
| **Guardrails without a rewrite** | Drop-in middleware: `secure_fastmcp(mcp)` or one `bastion.yaml` |
|
|
129
|
+
| **Privacy your legal team accepts** | PromptGuard + Presidio run **in your process**; data stays on your network |
|
|
130
|
+
| **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 |
|
|
132
|
+
| **Something that ships today** | PyPI, npm, Docker on GHCR, FastMCP, TypeScript wrapper, CI validate, live dashboard |
|
|
133
|
+
| **Policy your team can review** | `bastion.yaml` in Git, hot reload, OWASP-aligned controls ([docs/PILLARS.md](docs/PILLARS.md)) |
|
|
134
|
+
|
|
135
|
+
### FinOps & abuse protection (denial-of-wallet)
|
|
136
|
+
|
|
137
|
+
Agents can loop on expensive tools (search, LLM calls, paid APIs) until your bill spikes. Bastion enforces **session-level FinOps at the MCP boundary** before each `tools/call`:
|
|
138
|
+
|
|
139
|
+
| Attack pattern | What Bastion does | Default |
|
|
140
|
+
|----------------|---------------------|---------|
|
|
141
|
+
| **Infinite tool loop** | Blocks after max iterations per session | **On** (15 calls) |
|
|
142
|
+
| **Long-running session abuse** | Session timeout | **On** (60s) |
|
|
143
|
+
| **Token / context budget burn** | Token budget per session; optional output offload | **On** (50k tokens); offload opt-in |
|
|
144
|
+
| **Same tool hammered** | Per-tool call cap (`max_per_tool`) | Opt-in |
|
|
145
|
+
| **Paid API spend runaway** | USD caps via cost tracker | Opt-in |
|
|
146
|
+
| **Flaky or hostile tool cascade** | Circuit breaker opens after failures | Opt-in in example config |
|
|
147
|
+
| **Tool sprawl in one session** | Cap distinct tools per session | Opt-in |
|
|
148
|
+
|
|
149
|
+
Blocked calls return standard errors (`RateLimitExceededError` **-32002**, `TokenBudgetExceededError` **-32003**, `CostBudgetExceededError` **-32009**) and show up in the dashboard and audit log. See [docs/ATTACK_PREVENTION.md](docs/ATTACK_PREVENTION.md#3-rate-exhaustion--denial-of-wallet).
|
|
150
|
+
|
|
151
|
+
### Token reduction & cost saving
|
|
152
|
+
|
|
153
|
+
Bastion does not only **block** runaway spend — it **reduces** how many tokens reach the model on every turn:
|
|
154
|
+
|
|
155
|
+
| Savings lever | What it does | Default |
|
|
156
|
+
|---------------|--------------|---------|
|
|
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 |
|
|
160
|
+
| **Token budget caps** | Hard stop before session token burn exceeds your limit | **On** (50k tokens) |
|
|
161
|
+
| **USD session/day limits** | Dollar ceilings via cost tracker | Opt-in |
|
|
162
|
+
|
|
163
|
+
Less context per turn means lower LLM input cost — without sending prompts to a third-party optimizer API.
|
|
164
|
+
|
|
165
|
+
**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
|
+
|
|
167
|
+
### OWASP MCP Top 10 + production attacks
|
|
168
|
+
|
|
169
|
+
All **10** [OWASP MCP Top 10](https://owasp.org/www-project-mcp-top-10/) risks are mitigated at the MCP boundary (see controls below). Bastion also blocks **FinOps and abuse** patterns that OWASP does not list separately.
|
|
170
|
+
|
|
171
|
+
<p align="center">
|
|
172
|
+
<img
|
|
173
|
+
src="images/mcp-bastion-owasp-coverage.png"
|
|
174
|
+
alt="MCP-Bastion: OWASP MCP Top 10, FinOps abuse attacks, token reduction and cost saving, 16 security pillars"
|
|
175
|
+
width="960"
|
|
176
|
+
style="max-width:100%; height:auto; border-radius:12px; border:1px solid #1e293b;"
|
|
177
|
+
/>
|
|
178
|
+
</p>
|
|
179
|
+
|
|
180
|
+
**OWASP MCP Top 10** (all addressed)
|
|
181
|
+
|
|
182
|
+
| ID | Risk | Bastion controls |
|
|
183
|
+
|----|------|------------------|
|
|
184
|
+
| MCP01 | Token / secret exposure | PII redaction, audit trail, outbound response scan |
|
|
185
|
+
| MCP02 | Privilege escalation | RBAC, rate limits, cost caps, session tool scope |
|
|
186
|
+
| MCP03 | Tool poisoning | Prompt guard, content filter, response scan, metadata guard, grounding guard |
|
|
187
|
+
| MCP04 | Supply chain | Circuit breaker, `doctor` CLI, audit, observability |
|
|
188
|
+
| MCP05 | Command injection | Prompt guard, content filter, schema validation |
|
|
189
|
+
| MCP06 | Intent subversion | Rate limits, replay guard, per-tool caps, semantic firewall |
|
|
190
|
+
| MCP07 | Weak authentication | RBAC, edge auth |
|
|
191
|
+
| MCP08 | Audit & telemetry | Audit log, dashboard, Prometheus, OTEL, alerts |
|
|
192
|
+
| MCP09 | Shadow MCP servers | Central `bastion.yaml` policy, metrics, discovery filter |
|
|
193
|
+
| MCP10 | Context injection | PII redaction, response scan, output budget, discovery filter |
|
|
194
|
+
|
|
195
|
+
**FinOps & abuse attacks (beyond OWASP)**
|
|
196
|
+
|
|
197
|
+
| Attack | Controls |
|
|
198
|
+
|--------|----------|
|
|
199
|
+
| Denial of wallet | Iteration cap, token budget, cost tracker, output budget |
|
|
200
|
+
| Runaway tool loops | Session timeout, rate limiter, circuit breaker |
|
|
201
|
+
| Per-tool hammering | `max_per_tool` session caps |
|
|
202
|
+
| API spend runaway | USD session/day caps |
|
|
203
|
+
| Session tool sprawl | Distinct-tool limit per session |
|
|
204
|
+
| Replay abuse | Replay guard + nonces |
|
|
205
|
+
|
|
206
|
+
**Token reduction & cost saving**
|
|
207
|
+
|
|
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 |
|
|
214
|
+
|
|
215
|
+
Deep-dive mapping and integration hooks: [docs/SECURITY_OBSERVABILITY.md](docs/SECURITY_OBSERVABILITY.md) · [docs/ATTACK_PREVENTION.md](docs/ATTACK_PREVENTION.md)
|
|
216
|
+
|
|
217
|
+
### Secure your MCP server in 3 lines (FastMCP)
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
pip install mcp mcp-bastion-fastmcp
|
|
221
|
+
```
|
|
115
222
|
|
|
116
|
-
|
|
223
|
+
```python
|
|
224
|
+
from mcp.server.fastmcp import FastMCP
|
|
225
|
+
from mcp_bastion_fastmcp import secure_fastmcp
|
|
226
|
+
|
|
227
|
+
mcp = FastMCP("My Server")
|
|
228
|
+
secure_fastmcp(mcp) # wires prompt guard, PII redaction, rate limits into tools/call
|
|
229
|
+
```
|
|
117
230
|
|
|
118
|
-
|
|
231
|
+
**Policy-as-code instead?** Copy `bastion.yaml.example` → `bastion.yaml`, then `pip install mcp-bastion-python[policy]`:
|
|
119
232
|
|
|
120
|
-
|
|
233
|
+
```python
|
|
234
|
+
from mcp_bastion import build_middleware_from_config
|
|
121
235
|
|
|
122
|
-
|
|
236
|
+
middleware = build_middleware_from_config() # loads bastion.yaml
|
|
237
|
+
```
|
|
123
238
|
|
|
124
|
-
|
|
239
|
+
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/)**
|
|
125
240
|
|
|
126
|
-
|
|
241
|
+
- **Prompt injection defense:** Meta PromptGuard blocks adversarial payloads locally.
|
|
242
|
+
- **PII redaction:** Presidio masks SSN, email, phone in outbound content.
|
|
243
|
+
- **Denial-of-wallet protection:** Token buckets, iteration caps, token budget, cost tracking.
|
|
244
|
+
- **Response scan:** Blocks jailbreak patterns in outbound tool/resource text.
|
|
245
|
+
- **Output budget & grounding guard:** Optional response truncation and path verification (opt-in).
|
|
127
246
|
|
|
128
|
-
|
|
247
|
+
### How it works
|
|
129
248
|
|
|
130
|
-
- **
|
|
131
|
-
- **PII Redaction:** Uses Microsoft Presidio to detect and mask PII before it reaches the LLM context.
|
|
132
|
-
- **Infinite Loop Protection:** Token buckets and cycle detection stop runaway agents from burning API budget.
|
|
249
|
+
MCP-Bastion sits **in-process** on your MCP server and inspects every `tools/call` before it reaches databases, APIs, or shell tools — then redacts sensitive data on the way back.
|
|
133
250
|
|
|
134
|
-
|
|
251
|
+
```mermaid
|
|
252
|
+
flowchart LR
|
|
253
|
+
Agent["AI agent / LLM client"]
|
|
254
|
+
Server["Your MCP server"]
|
|
255
|
+
Bastion["MCP-Bastion<br/>middleware"]
|
|
256
|
+
Tools["Tools & upstream APIs"]
|
|
257
|
+
|
|
258
|
+
Agent -->|"JSON-RPC"| Server
|
|
259
|
+
Server --> Bastion
|
|
260
|
+
Bastion -->|"✓ allow / ✗ block"| Tools
|
|
261
|
+
Tools -->|"raw result"| Bastion
|
|
262
|
+
Bastion -->|"PII masked · audited"| Server
|
|
263
|
+
Server --> Agent
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Three ways to adopt
|
|
267
|
+
|
|
268
|
+
```mermaid
|
|
269
|
+
flowchart TB
|
|
270
|
+
Start(["Protect my MCP server"])
|
|
271
|
+
Start --> FastMCP["FastMCP · Python<br/><code>secure_fastmcp(mcp)</code>"]
|
|
272
|
+
Start --> Policy["Policy-as-code<br/><code>build_middleware_from_config()</code>"]
|
|
273
|
+
Start --> TS["TypeScript<br/><code>wrapWithMcpBastion(server)</code>"]
|
|
274
|
+
FastMCP --> Docs["docs/QUICK_START.md · path A"]
|
|
275
|
+
Policy --> Yaml["bastion.yaml + CI validate"]
|
|
276
|
+
TS --> Sidecar["Rate limit in-process · ML via sidecar"]
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
> **Releases:** npm, PyPI, and prebuilt **Docker** on GHCR — see [DOCKER.md](DOCKER.md). **Community:** GitHub **Issues**, **Discussions**, **PRs**. **Security:** [SECURITY.md](SECURITY.md).
|
|
135
280
|
|
|
136
281
|
---
|
|
137
282
|
|
|
@@ -163,7 +308,7 @@ Hooks into MCP SDKs (TypeScript, Python) and FastMCP via standard middleware. No
|
|
|
163
308
|
|
|
164
309
|
### Complete feature catalog
|
|
165
310
|
|
|
166
|
-
**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.).
|
|
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).
|
|
167
312
|
|
|
168
313
|
> **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.
|
|
169
314
|
|
|
@@ -218,6 +363,18 @@ Hooks into MCP SDKs (TypeScript, Python) and FastMCP via standard middleware. No
|
|
|
218
363
|
|
|
219
364
|
**🎥 Demo (screen recording):** [Watch on Vimeo](https://vimeo.com/1186084574) — overview of the dashboard and metrics (link opens the player on Vimeo).
|
|
220
365
|
|
|
366
|
+
<p align="center">
|
|
367
|
+
<a href="https://vimeo.com/1186084574" title="Watch MCP-Bastion dashboard demo on Vimeo">
|
|
368
|
+
<img
|
|
369
|
+
src="docs/images/dashboard.png"
|
|
370
|
+
alt="MCP-Bastion dashboard — request KPIs, block rate, PII redacted, cost, top tools, and forensics"
|
|
371
|
+
width="920"
|
|
372
|
+
style="max-width:100%; height:auto; border-radius:12px; border:1px solid #e2e8f0;"
|
|
373
|
+
/>
|
|
374
|
+
</a>
|
|
375
|
+
</p>
|
|
376
|
+
<p align="center"><sub>Click the screenshot for the video demo · Seed demo data: <code>mcp-bastion dashboard --demo</code></sub></p>
|
|
377
|
+
|
|
221
378
|
Run the optional dashboard for a live view of requests, blocked count, PII redacted, cost, top tools, and recent alerts.
|
|
222
379
|
|
|
223
380
|
```bash
|
|
@@ -232,6 +389,16 @@ mcp-bastion dashboard --port 7000
|
|
|
232
389
|
| [http://localhost:7000/api/health](http://localhost:7000/api/health) | `{"status": "ok"}` |
|
|
233
390
|
| [http://localhost:7000/metrics](http://localhost:7000/metrics) | Prometheus text format for Grafana/Datadog |
|
|
234
391
|
|
|
392
|
+
<p align="center">
|
|
393
|
+
<img
|
|
394
|
+
src="docs/images/api-metrics.png"
|
|
395
|
+
alt="Example /api/metrics JSON — requests_total, blocked_total, pii_redacted_total, cost_total, top_tools"
|
|
396
|
+
width="720"
|
|
397
|
+
style="max-width:100%; height:auto; border-radius:8px; border:1px solid #e2e8f0;"
|
|
398
|
+
/>
|
|
399
|
+
</p>
|
|
400
|
+
<p align="center"><sub><code>/api/metrics</code> JSON for Grafana, Datadog, or custom pollers</sub></p>
|
|
401
|
+
|
|
235
402
|
*Dashboard: total requests, blocked count and %, PII redacted, cost; blocked-by-reason bars; top tools; cost by user; recent alerts — open [http://localhost:7000/](http://localhost:7000/) while `mcp-bastion dashboard` is running.*
|
|
236
403
|
|
|
237
404
|
- **Alerts:** Slack webhook and cost-threshold alerts. See [dashboard/README.md](dashboard/README.md).
|
|
@@ -344,7 +511,7 @@ See **[docs/SECURITY_OBSERVABILITY.md](docs/SECURITY_OBSERVABILITY.md)** for the
|
|
|
344
511
|
<p align="center">
|
|
345
512
|
<img
|
|
346
513
|
src="images/mcp-bastian-features.png"
|
|
347
|
-
alt="MCP-Bastion features at a glance
|
|
514
|
+
alt="MCP-Bastion features at a glance"
|
|
348
515
|
width="920"
|
|
349
516
|
style="max-width:100%; height:auto; border-radius:12px;"
|
|
350
517
|
/>
|
|
@@ -396,7 +563,7 @@ uv add mcp-bastion-python
|
|
|
396
563
|
# or
|
|
397
564
|
pip install mcp-bastion-python
|
|
398
565
|
# pinned latest
|
|
399
|
-
pip install mcp-bastion-python==1.0.
|
|
566
|
+
pip install mcp-bastion-python==1.0.17
|
|
400
567
|
```
|
|
401
568
|
|
|
402
569
|
**Prerequisites (recommended)**
|
|
@@ -527,46 +694,28 @@ See `VALIDATION_CHECKLIST.md` and `SETUP_GUIDE.md`.
|
|
|
527
694
|
|
|
528
695
|
### Python Tutorial: FastMCP Server
|
|
529
696
|
|
|
530
|
-
FastMCP server with MCP-Bastion.
|
|
697
|
+
FastMCP server with MCP-Bastion via `secure_fastmcp` (patches tool dispatch — see [integrations/mcp-bastion-fastmcp/README.md](integrations/mcp-bastion-fastmcp/README.md)).
|
|
531
698
|
|
|
532
699
|
**Step 1: Install dependencies**
|
|
533
700
|
|
|
534
701
|
```bash
|
|
535
|
-
pip install mcp mcp-bastion-
|
|
702
|
+
pip install mcp mcp-bastion-fastmcp
|
|
536
703
|
```
|
|
537
704
|
|
|
538
705
|
**Step 2: Create your server file** (`server.py`)
|
|
539
706
|
|
|
540
707
|
```python
|
|
541
708
|
from mcp.server.fastmcp import FastMCP
|
|
542
|
-
from
|
|
709
|
+
from mcp_bastion_fastmcp import secure_fastmcp
|
|
543
710
|
|
|
544
|
-
# Create the MCP server
|
|
545
711
|
mcp = FastMCP("My Secure Server")
|
|
712
|
+
secure_fastmcp(mcp) # call right after FastMCP(), before mcp.run()
|
|
546
713
|
|
|
547
|
-
# Create MCP-Bastion middleware
|
|
548
|
-
# It intercepts tool calls and resource reads before they execute
|
|
549
|
-
bastion = MCPBastionMiddleware(
|
|
550
|
-
enable_prompt_guard=True, # Block malicious prompts via PromptGuard
|
|
551
|
-
enable_pii_redaction=True, # Mask PII in outgoing content
|
|
552
|
-
enable_rate_limit=True, # Cap at 15 iterations, 60s timeout
|
|
553
|
-
)
|
|
554
|
-
|
|
555
|
-
# Compose middleware chain (pass to your server's middleware config if supported)
|
|
556
|
-
middleware = compose_middleware(bastion)
|
|
557
|
-
|
|
558
|
-
# Register a tool (protected when middleware is wired into your server)
|
|
559
714
|
@mcp.tool()
|
|
560
715
|
def get_weather(city: str) -> str:
|
|
561
716
|
"""Get weather for a city."""
|
|
562
717
|
return f"Weather in {city}: 22C, sunny"
|
|
563
718
|
|
|
564
|
-
# Resource (PII redacted)
|
|
565
|
-
@mcp.resource("user://profile/{user_id}")
|
|
566
|
-
def get_profile(user_id: str) -> str:
|
|
567
|
-
"""Get user profile. PII redacted."""
|
|
568
|
-
return f"User {user_id}: John Doe, SSN 123-45-6789, john@example.com"
|
|
569
|
-
|
|
570
719
|
if __name__ == "__main__":
|
|
571
720
|
mcp.run(transport="streamable-http")
|
|
572
721
|
```
|
|
@@ -577,10 +726,12 @@ if __name__ == "__main__":
|
|
|
577
726
|
python server.py
|
|
578
727
|
```
|
|
579
728
|
|
|
580
|
-
MCP-Bastion:
|
|
581
|
-
- Scans tool
|
|
582
|
-
- Redacts PII
|
|
583
|
-
-
|
|
729
|
+
MCP-Bastion (via `secure_fastmcp`):
|
|
730
|
+
- Scans **tool arguments** for prompt injection before execution
|
|
731
|
+
- Redacts PII in **tool results** on the way out
|
|
732
|
+
- Enforces default rate limits (**15** calls per session, **60s** timeout — see `TokenBucketRateLimiter`)
|
|
733
|
+
|
|
734
|
+
For **full** `bastion.yaml` policy or **resource** (`resources/read`) PII redaction, use the low-level MCP `Server` with `build_middleware_from_config()` — see [docs/QUICK_START.md](docs/QUICK_START.md) path B.
|
|
584
735
|
|
|
585
736
|
**Alternative: Policy-as-Code**
|
|
586
737
|
|
|
@@ -633,6 +784,7 @@ bastion_no_pii = MCPBastionMiddleware(enable_pii_redaction=False)
|
|
|
633
784
|
Extend `Middleware` to add logging, metrics, or custom logic:
|
|
634
785
|
|
|
635
786
|
```python
|
|
787
|
+
from mcp_bastion import MCPBastionMiddleware
|
|
636
788
|
from mcp_bastion.base import Middleware, MiddlewareContext, compose_middleware
|
|
637
789
|
|
|
638
790
|
class LoggingMiddleware(Middleware):
|
|
@@ -641,6 +793,7 @@ class LoggingMiddleware(Middleware):
|
|
|
641
793
|
# log method, elapsed, etc.
|
|
642
794
|
return result
|
|
643
795
|
|
|
796
|
+
bastion = MCPBastionMiddleware() # or use the configured instance from above
|
|
644
797
|
middleware = compose_middleware(bastion, LoggingMiddleware())
|
|
645
798
|
```
|
|
646
799
|
|
|
@@ -663,7 +816,6 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
663
816
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
664
817
|
import {
|
|
665
818
|
wrapWithMcpBastion,
|
|
666
|
-
wrapCallToolHandler,
|
|
667
819
|
} from "@mcp-bastion/core";
|
|
668
820
|
|
|
669
821
|
const server = new Server({ name: "my-mcp-server", version: "1.0.0" });
|
|
@@ -710,7 +862,7 @@ npx tsx server.ts
|
|
|
710
862
|
For prompt injection and PII redaction, run a Python HTTP service that exposes `/prompt-guard` and `/pii-redact` endpoints (see the Python package for sidecar implementation). Then:
|
|
711
863
|
|
|
712
864
|
```bash
|
|
713
|
-
# Start the Python sidecar, then the TypeScript server
|
|
865
|
+
# Start the Python sidecar, then the TypeScript server (sidecarUrl or MCP_BASTION_URL)
|
|
714
866
|
MCP_BASTION_SIDECAR=http://localhost:8000 npx tsx server.ts
|
|
715
867
|
```
|
|
716
868
|
|
|
@@ -792,6 +944,7 @@ When MCP-Bastion blocks a request, it returns standard MCP/JSON-RPC errors:
|
|
|
792
944
|
| -32014 | `ToolNotAllowedError` | Tool not on allowlist |
|
|
793
945
|
| -32015 | `SessionScopeExceededError` | Too many distinct tools per session (scope creep) |
|
|
794
946
|
| -32016 | `ToolMetadataPoisoningError` | Tool list / metadata failed safety checks |
|
|
947
|
+
| -32017 | `GroundingViolationError` | Ungrounded file reference in tool output |
|
|
795
948
|
|
|
796
949
|
```python
|
|
797
950
|
# Python: exceptions
|
|
@@ -812,6 +965,7 @@ from mcp_bastion.errors import (
|
|
|
812
965
|
ToolNotAllowedError,
|
|
813
966
|
SessionScopeExceededError,
|
|
814
967
|
ToolMetadataPoisoningError,
|
|
968
|
+
GroundingViolationError,
|
|
815
969
|
)
|
|
816
970
|
import logging
|
|
817
971
|
logger = logging.getLogger(__name__)
|
|
@@ -835,6 +989,7 @@ except (
|
|
|
835
989
|
ToolNotAllowedError,
|
|
836
990
|
SessionScopeExceededError,
|
|
837
991
|
ToolMetadataPoisoningError,
|
|
992
|
+
GroundingViolationError,
|
|
838
993
|
) as e:
|
|
839
994
|
logger.warning("blocked: %s", e.to_mcp_error())
|
|
840
995
|
```
|
|
@@ -888,7 +1043,7 @@ npx -y @modelcontextprotocol/inspector
|
|
|
888
1043
|
|
|
889
1044
|
## Third-Party Components
|
|
890
1045
|
|
|
891
|
-
See `NOTICE` for licenses. MCP-Bastion uses Meta Llama Prompt Guard 2 (Llama 4 Community License) and Microsoft Presidio. For OWASP-relevant mitigations
|
|
1046
|
+
See `NOTICE` for licenses. MCP-Bastion uses Meta Llama Prompt Guard 2 (Llama 4 Community License) and Microsoft Presidio. For OWASP-relevant mitigations and dependency audit, see [docs/SECURITY.md](docs/SECURITY.md). To report vulnerabilities privately, see [SECURITY.md](SECURITY.md).
|
|
892
1047
|
|
|
893
1048
|
## License
|
|
894
1049
|
|