AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified Apache-2.0 Self-run

Mcp Bastion

mcp-gowthaman90-mcp-bastion · by Gowthaman90

Reliability + security proxy for the Model Context Protocol (MCP): self-healing connections, runtime tool-security (rug-pull/poisoning detection), and a compliance-mapped audit trail.

No reviews yet
0 installs
16 views
0.0% view→install

Install

$ agentstack add mcp-gowthaman90-mcp-bastion

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution Used
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-gowthaman90-mcp-bastion)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Mcp Bastion? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

🛡️ 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://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.

📖 Launch story: Medium · dev.to

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-recoverablebastion__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) — structured, tamper-evident 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

1. Add Bastion to your client, pointing it at a config file:

// 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):

{
  "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.

Demo

See the whole thing in action — a server crashing mid-session and healing itself:

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": "" }) without human intervention. | | bastion__security | Per-tool security report: pin status (approved vs changed), poisoning findings, and shadowing. | | bastion__approve | Re-approve a changed tool (arguments: { "server": "...", "tool": "..." }) to clear a rug-pull block. | | bastion__compliance | Audit summary of recent activity mapped to NIST AI RMF / OWASP LLM Top 10 (requires audit.enabled). |

Configuration

| Key | Type | Default | Description | | ------------------------------ | -------------------------- | -------------------- | ---------------------------------------------------- | | servers | map | — | Upstream servers to proxy (required, at least one). | | servers..command | string | — | Executable to launch (e.g. npx, node). | | servers..args | string[] | [] | Arguments to command. | | servers..env | map | — | Env overrides merged over the process env. | | servers..cwd | string | — | Working directory for the spawned process. | | reconnect.auto | boolean | true | Auto-reconnect after an unexpected disconnect. | | reconnect.maxRetries | number | 10 | Max attempts before giving up (-1 = unlimited). | | reconnect.initialBackoffMs | number | 500 | Initial backoff, doubled each attempt. | | reconnect.maxBackoffMs | number | 30000 | Backoff ceiling. | | healthCheck.enabled | boolean | true | Enable periodic liveness probing. | | healthCheck.intervalMs | number | 30000 | Interval between probes. | | healthCheck.timeoutMs | number | 5000 | Per-probe timeout. | | namespace.strategy | prefix \| passthrough | prefix | How upstream tool names are exposed. | | namespace.separator | string | __ | Separator used by the prefix strategy. | | security.pinTools | boolean | true | Pin tool definitions and detect later changes. | | security.onRugPull | block \| warn | block | Action when a pinned tool's definition changed. | | security.inspectDescriptions | boolean | true | Run poisoning heuristics on tool descriptions. | | security.onPoisoning | block \| warn | warn | Action on a high-severity poisoning finding. | | audit.enabled | boolean | false | Record an audit event for every tool call. | | audit.includeArgs | none\|redacted\|full | none | How tool arguments are recorded. | | audit.tamperEvident | boolean | false | Hash-chain events so tampering is detectable. | | audit.sinks | array | console | Destinations: console, file, webhook, otlp. | | servers..transport | stdio \| http | stdio | Local subprocess or remote endpoint. | | servers..url | string | — | Remote MCP URL (required for http). | | servers..headers | map | — | Headers for http upstreams (e.g. Authorization). | | listen.mode | stdio \| http | stdio | Serve Bastion over stdio or Streamable HTTP. | | listen.host / listen.port | string / number | 127.0.0.1 / 3000 | Bind address for http mode. |

Transports

Bastion speaks two transports on both faces:

  • stdio (default) — the client spawns Bastion, and Bastion spawns local servers.
  • Streamable HTTP — connect to remote MCP servers (servers. with transport: "http",

a url, and optional auth headers), and/or serve Bastion over HTTP to multiple/remote clients (listen.mode: "http", or --http ).

HTTP upstreams configured without an authentication header are flagged (authenticated: false) in bastion__status and warned at connect time.

Runtime security

New in v0.2. Bastion adds a security layer in the tool-call path (an interceptor pipeline), enabled by default:

  • Rug-pull detection (tool pinning). Each tool's definition is pinned on first use. If a server

later changes that definition, the tool is blocked (onRugPull: "block") until you review it and re-approve with bastion__approve. This catches a server that looks benign at install time and turns malicious afterward.

  • Poisoning inspection. Tool names and descriptions are scanned for manipulation heuristics

(instruction override, secret access, data exfiltration, covert instructions, embedded directives, hidden/zero-width characters). Because heuristics can false-positive, the default is warn (logged and reported, not blocked); set onPoisoning: "block" to enforce.

  • Shadowing. When two servers expose a tool with the same name, it's surfaced in the report.

Review everything with the bastion__security tool. These checks apply to local stdio servers today; authentication checks for remote servers arrive with HTTP transport support.

Audit & compliance

New in v0.3, opt-in. Enable audit to record a structured, versioned event for every tool call — including calls blocked by the security layer:

"audit": {
  "enabled": true,
  "includeArgs": "redacted",     // none | redacted | full
  "tamperEvident": true,          // hash-chain events
  "sinks": [
    { "type": "file", "path": "./bastion-audit.jsonl" },
    { "type": "webhook", "url": "https://collector.example/v1/audit" }
  ]
}
  • Pluggable sinks. console (stderr JSONL), file (JSONL append), webhook (batched POST), and

otlp (native OpenTelemetry logs export — point it at an OTel Collector to fan out to any SIEM/cloud backend). The sink interface makes new destinations additive.

  • Compliance mapping. Each event is mapped to NIST AI RMF functions and OWASP LLM Top 10

categories; bastion__compliance returns an aggregate report of recent activity.

  • Tamper-evidence. With tamperEvident, events are hash-chained; the exported verifyChain helper

detects any retroactive edit or deletion.

  • Redaction. Arguments are omitted by default; set includeArgs to redacted to keep structure

while masking sensitive keys.

Client setup

The steps are identical for every client — only the config file location differs:

| Client | Where to add the bastion entry | | -------------- | -------------------------------------------------- | | Claude Code | project .mcp.json (or claude mcp add) | | Cursor | ~/.cursor/mcp.json or project .cursor/mcp.json | | Claude Desktop | claude_desktop_config.json | | Cline | cline_mcp_settings.json | | Windsurf | ~/.codeium/windsurf/mcp_config.json |

> Gradual adoption: you don't have to route every server through Bastion — put only your flaky or > untrusted servers behind it and leave the rest connected directly.

Architecture

Bastion is organized into clear layers with a one-directional dependency flow, so each concern is independently testable and easy to evolve:

src/
├── cli.ts              # thin CLI entrypoint (parse → wire → serve)
├── index.ts            # public library API
├── errors.ts           # error hierarchy (BastionError, …)
├── config/             # schema (Zod) + loader
├── core/               # domain: upstream connection lifecycle, aggregation & routing
├── proxy/              # client-facing MCP server + control tools
├── observability/      # logging (audit sinks in v0.3)
└── internal/           # small cross-cutting utilities

Design details — including the client-agnostic rationale, the interceptor pipeline, and the audit-sink strategy — live in the project's design docs.

Development

npm install
npm run check      # format:check + lint + typecheck + test (the full gate)
npm test           # unit + end-to-end (in-memory transport) tests
npm run build      # bundle to dist/ (CLI + library)
npm run dev -- --config bastion.config.json

| Script | Does | | ------------------------- | ----------------------------------- | | build | Bundle CLI + library with tsup. | | dev | Run the CLI from source with tsx. | | typecheck | tsc --noEmit (strict). | | lint / `li

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.