# ๐ก๏ธ mcp-bastion
**A reliability & security proxy for the Model Context Protocol (MCP).**
_Self-healing connections, runtime tool-security, and a compliance-mapped audit trail for your MCP servers._
[](https://www.npmjs.com/package/mcp-bastion)
[](https://www.npmjs.com/package/mcp-bastion)
[](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.Gowthaman90/mcp-bastion)
[](https://github.com/Gowthaman90/mcp-defense-bench)
[](https://glama.ai/mcp/servers/Gowthaman90/mcp-bastion)
[](https://github.com/Gowthaman90/mcp-bastion/actions/workflows/ci.yml)
[](./LICENSE)
[](https://nodejs.org)
[](https://www.typescriptlang.org/)
[](#contributing)
---
`mcp-bastion` sits between your MCP client (Claude Code, Cursor, Cline, Windsurf, Zed, Claude
Desktop, or any MCP-compliant agent) and your MCP servers. It is **client-agnostic** โ it works with
any compliant client through configuration alone, with zero client-specific code โ and **non-invasive**:
your servers run unchanged, and removing Bastion is a one-line config revert.
๐ฆ **Package:** [`mcp-bastion` on npm](https://www.npmjs.com/package/mcp-bastion) ยท ๐๏ธ **Official MCP Registry:** `io.github.Gowthaman90/mcp-bastion`
๐ **Security, measured:** on the open, vendor-neutral [mcp-defense-bench](https://github.com/Gowthaman90/mcp-defense-bench), Bastion covers **63% of the MCP attack surface (15.0/24 vectors; 11 enforced)** at zero false positives โ the broadest of the proxies measured.
๐ **Launch story:** [Medium](https://medium.com/p/e74f638e9e15) ยท [dev.to](https://dev.to/gowthaman90/the-mcp-reliability-security-gap-and-an-open-source-proxy-that-fills-it-3ppo)
๐ค **Created & maintained by [Gowthaman Arumugam](https://github.com/Gowthaman90)** โ Independent Researcher. Companion benchmark: [mcp-defense-bench](https://github.com/Gowthaman90/mcp-defense-bench).
## Contents
- [Why](#why)
- [How it works](#how-it-works)
- [Features](#features)
- [Quick start](#quick-start)
- [Demo](#demo)
- [Control tools](#control-tools)
- [Configuration](#configuration)
- [Transports](#transports)
- [Runtime security](#runtime-security)
- [Audit & compliance](#audit--compliance)
- [Client setup](#client-setup)
- [Architecture](#architecture)
- [Development](#development)
- [Roadmap](#roadmap)
- [Contributing](#contributing)
- [Security](#security)
- [License](#license)
## Why
When an MCP server disconnects mid-session, the agent only sees a generic _"No such tool available"_
error โ **indistinguishable from a tool that never existed** โ and it cannot reconnect; only a human
can. Long agent sessions silently lose capabilities and fail in confusing ways.
Bastion closes that gap. It health-checks every server, auto-reconnects with backoff, and โ crucially โ
exposes control tools so the **agent itself** can inspect connection health and recover a dropped
server without human intervention.
> Bastion now spans three layers: **reliability** (v0.1), **runtime security** (v0.2 โ tool pinning /
> rug-pull & poisoning detection), and **audit & compliance** (v0.3 โ pluggable sinks mapped to NIST
> AI RMF / OWASP LLM Top 10). See the [roadmap](#roadmap).
## How it works
Today your client connects **directly** to each server. With Bastion, your client connects to
**Bastion**, which connects to those same servers on your behalf โ so it sits in the tool-call path
and can add reliability (and, later, security) transparently.
```
Before: Client โโถ server A / server B / server C
After: Client โโถ mcp-bastion โโถ server A
โโถ server B
โโถ server C
```
Bastion is a standard MCP **server** to your client and a standard MCP **client** to each upstream.
Because it speaks the protocol faithfully, it works with every compliant client automatically โ the
only per-client difference is where you put a few lines of config.
## Features
- ๐ **Client-agnostic** โ one binary, config-only integration; no per-client plugins.
- โป๏ธ **Self-healing** โ health checks + capped exponential-backoff auto-reconnect for stdio servers.
- ๐งญ **Agent-recoverable** โ `bastion__status` and `bastion__reconnect` let the agent detect and fix
drops itself, instead of hitting an opaque "no such tool" wall.
- ๐งฉ **Transparent aggregation** โ merges many servers into one, with per-server tool namespacing to
prevent collisions and tool-shadowing.
- ๐ฌ **Legible failures** โ a dropped server yields an actionable message, not a crash.
- ๐ก๏ธ **Runtime security** _(new in v0.2)_ โ pins each tool's definition and blocks "rug pulls" (a
server changing a tool after approval); heuristically inspects descriptions for poisoning; detects
cross-server shadowing. See [Runtime security](#runtime-security).
- ๐ **Audit & compliance** _(new in v0.3, opt-in)_ โ structured, integrity-hash-chained audit events to
pluggable sinks (console / file / webhook), mapped to NIST AI RMF & OWASP LLM Top 10. See
[Audit & compliance](#audit--compliance).
- ๐ชถ **Non-invasive & reversible** โ your servers run unchanged; uninstall is a config revert.
- ๐งฑ **Enterprise-grade codebase** โ strict TypeScript, layered architecture, ESLint + Prettier, and
unit + end-to-end tests.
## Quick start
Bastion is published on npm as [`mcp-bastion`](https://www.npmjs.com/package/mcp-bastion) โ the
`npx` command below fetches it automatically, so there's nothing to install first.
**1. Add Bastion to your client**, pointing it at a config file:
```jsonc
// your client's mcpServers config
{
"mcpServers": {
"bastion": {
"command": "npx",
"args": ["-y", "mcp-bastion", "--config", "bastion.config.json"],
},
},
}
```
**2. List your real servers in `bastion.config.json`** (moved verbatim from the client):
```jsonc
{
"servers": {
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] },
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"],
},
},
"reconnect": { "auto": true },
"healthCheck": { "enabled": true },
}
```
**3. Restart your client.** Your tools now appear namespaced (e.g. `github__create_issue`) alongside
Bastion's control tools. See [`bastion.config.example.json`](./bastion.config.example.json) for the
full set of options.
> ๐ **Security is on by default.** Out of the box, Bastion runs the `balanced` enforcement profile:
> it **blocks** high-confidence attacks (rug-pulls, argument/command injection, cross-server
> exfiltration) and **warns** on heuristic ones (description/response
> poisoning), while redacting leaked secrets from tool results. Set `security.enforcementProfile` to
> `observe` (warn-only) or `strict` (block-all), or tune any individual control โ see
> [Runtime security](#runtime-security).
## Demo
See the whole thing in action โ a server crashing mid-session and healing itself:
```bash
npm run demo
```
It boots Bastion in front of a server that crashes on command, shows the agent getting an actionable
"reconnect" message instead of a cryptic error, and then the connection auto-recovering with no human
involved. To record it as a GIF: `asciinema rec demo.cast -c "npm run demo" && agg demo.cast assets/demo.gif`.
## Control tools
Bastion injects control tools so the agent can manage connections and review security itself, using
only standard MCP calls:
| Tool | Purpose |
| --------------------- | ---------------------------------------------------------------------------------------------------------- |
| `bastion__status` | Health of every proxied server: connected / disconnected / reconnecting / failed, tool counts, last error. |
| `bastion__reconnect` | Reconnect a named server (argument: `{ "server": "