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.
Files changed (52) hide show
  1. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/PKG-INFO +206 -51
  2. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/README.md +205 -50
  3. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/pyproject.toml +1 -1
  4. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/__init__.py +1 -1
  5. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/config.py +44 -0
  6. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/errors.py +7 -0
  7. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/middleware.py +268 -13
  8. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/grounding_guard.py +131 -0
  9. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/output_budget.py +119 -0
  10. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/rate_limit.py +50 -10
  11. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/response_scanner.py +62 -0
  12. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/session_offload.py +93 -0
  13. mcp_bastion_python-1.0.17/src/mcp_bastion/pillars/tokens.py +105 -0
  14. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/policy_simulator.py +1 -0
  15. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/.gitignore +0 -0
  16. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/LICENSE +0 -0
  17. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/NOTICE +0 -0
  18. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/README.md +0 -0
  19. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/app.py +0 -0
  20. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/chart.umd.js.map +0 -0
  21. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/chart.umd.min.js +0 -0
  22. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/dashboard-app.js +0 -0
  23. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/mcp-bastian.png +0 -0
  24. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/dashboard/static/mcp-bastian.svg +0 -0
  25. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/base.py +0 -0
  26. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/cli.py +0 -0
  27. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/demo_dashboard_metrics.py +0 -0
  28. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/demo_live_traffic.py +0 -0
  29. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/doctor.py +0 -0
  30. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/governance_beacon.py +0 -0
  31. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/otel.py +0 -0
  32. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/__init__.py +0 -0
  33. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/alerts.py +0 -0
  34. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/audit_hash_chain.py +0 -0
  35. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/audit_log.py +0 -0
  36. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/circuit_breaker.py +0 -0
  37. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/content_filter.py +0 -0
  38. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/cost_tracker.py +0 -0
  39. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/external_policy.py +0 -0
  40. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/metrics.py +0 -0
  41. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/pii_redaction.py +0 -0
  42. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/pricing.py +0 -0
  43. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/prompt_guard.py +0 -0
  44. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/rbac.py +0 -0
  45. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/replay_guard.py +0 -0
  46. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/schema_validation.py +0 -0
  47. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/semantic_cache.py +0 -0
  48. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/semantic_firewall.py +0 -0
  49. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/sensitive_classifier.py +0 -0
  50. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/pillars/telemetry_sinks.py +0 -0
  51. {mcp_bastion_python-1.0.16 → mcp_bastion_python-1.0.17}/src/mcp_bastion/redteam.py +0 -0
  52. {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.16
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
- [![Total Downloads](https://img.shields.io/badge/total%20downloads-3.4K-brightgreen)](https://pepy.tech/projects/mcp-bastion-python)
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
- [![PyPI Version](https://img.shields.io/pypi/v/mcp-bastion-python)](https://pypi.org/project/mcp-bastion-python/)
111
- [![PyPI downloads](https://img.shields.io/pepy/dt/mcp-bastion-python)](https://pepy.tech/projects/mcp-bastion-python)
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/)
114
+ [![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)
112
115
  [![Python](https://img.shields.io/pypi/pyversions/mcp-bastion-python)](https://pypi.org/project/mcp-bastion-python/)
113
116
  [![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)
117
+ [![Docker: GHCR mcp-bastion-proxy (port 8080)](https://img.shields.io/badge/docker%20%28ghcr%29-mcp--bastion--proxy%20%7C%208080-2496ED?logo=docker)](https://github.com/vaquarkhan/MCP-Bastion/pkgs/container/mcp-bastion-proxy)
118
+ [![Docker: GHCR mcp-bastion-dashboard (port 7000)](https://img.shields.io/badge/docker%20%28ghcr%29-mcp--bastion--dashboard%20%7C%207000-2496ED?logo=docker)](https://github.com/vaquarkhan/MCP-Bastion/pkgs/container/mcp-bastion-dashboard)
114
119
  [![License: Source Available](https://img.shields.io/badge/license-Source%20Available-orange.svg)](LICENSE)
120
+ [![Website](https://img.shields.io/badge/website-vaquarkhan.github.io/MCP--Bastion-blue?logo=github)](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
- **Enterprise-Grade Security Middleware for the Model Context Protocol**
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
- > Releases are published to npm and PyPI via GitHub Actions on tag push.
231
+ **Policy-as-code instead?** Copy `bastion.yaml.example` `bastion.yaml`, then `pip install mcp-bastion-python[policy]`:
119
232
 
120
- **Documentation:** structured paths for **policy** and **LLM integration** live in [docs/README.md](docs/README.md) and [docs/index.md](docs/index.md). **Community:** open a GitHub **Issue** for bugs or gaps, a **Discussion** for integration questions (if enabled on the repo), or a **PR** for docs and examples—those help every adopter.
233
+ ```python
234
+ from mcp_bastion import build_middleware_from_config
121
235
 
122
- **Hello world (minimal Bastion on code):** see **[docs/QUICK_START.md](docs/QUICK_START.md)** — FastMCP helper `secure_fastmcp(mcp)` (wires `MCPBastionMiddleware` into tool dispatch), or two-line `build_middleware_from_config()` for full `bastion.yaml` policy, plus a **CI validate** snippet for pipeline-driven installs.
236
+ middleware = build_middleware_from_config() # loads bastion.yaml
237
+ ```
123
238
 
124
- The Model Context Protocol (MCP) has rapidly become the universally accepted standard for connecting AI agents to enterprise databases and APIs. However, this connectivity introduces a massive new attack surface: unpredictable, non-deterministic agentic behavior.
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
- MCP-Bastion is a lightweight, drop-in security middleware designed to wrap around any existing Python or TypeScript MCP server. Instead of relying on passive logging, human-in-the-loop approvals, or third-party APIs, MCP-Bastion provides an active, 100% local defense layer. It intercepts standard JSON-RPC traffic to stop threats before they cross the enterprise boundary.
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
- Under 5ms proxy overhead. MCP-Bastion provides:
247
+ ### How it works
129
248
 
130
- - **Prompt Injection Defense:** Meta PromptGuard runs locally to block adversarial payloads and jailbreaks.
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
- Secure your MCP server without changing business logic.
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 — pillars, dashboard, and integrations"
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.16
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-python
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 mcp_bastion import MCPBastionMiddleware, compose_middleware
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 args for prompt injection
582
- - Redacts PII from resource responses
583
- - Blocks sessions over 15 calls or 60s
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, dependency audit, and reporting vulnerabilities, see [docs/SECURITY.md](docs/SECURITY.md).
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