{"slug": "sentinelmcp-an-open-source-firewall-for-ai-agents-that-use-mcp", "title": "SentinelMCP – An open-source firewall for AI agents that use MCP", "summary": "Technosive Ltd. released SentinelMCP, an open-source security firewall for AI agents using the Model Context Protocol (MCP). The tool enforces policies, redacts PII and secrets, and provides audit logging at runtime, supporting both a sidecar proxy and an in-process Go SDK. SentinelMCP aims to secure AI agent tool calls with sub-millisecond latency and human-in-the-loop approval workflows.", "body_md": "**The Open-Source MCP Security Gateway for AI Agents**\n\nBuilt by [Technosive Ltd.](https://technosive.co.uk)\n\n⚠️ Alpha Software — v0.1SentinelMCP is currently in\n\nAlpha. The project is under active development and APIs, configuration formats, and graph behaviorsmay changein future releases without advance notice.\n\nProduction warning:This software is provided as-is. While we strive for security, an Alpha-stage proxy shouldnotbe your sole defense in a highly regulated production environment without thorough testing. Use at your own risk.We actively seek early adopters and feedback. If you encounter issues, have suggestions, or want to contribute — please\n\n[open an issue]. Your input directly shapes the roadmap.\n\nSentinelMCP is a security enforcement engine for the **Model Context Protocol (MCP)** that secures AI agent tool calls at runtime. It provides inspection, policy enforcement, PII/secret redaction, and audit logging — sitting between your AI agents and the tools they invoke.\n\nBuilt in high-performance Go with runtime-native graph orchestration, interrupt/resume capabilities, and sub-millisecond enforcement — enabling human-in-the-loop approval workflows without custom plumbing.\n\nSentinelMCP can be deployed in two ways, depending on your architecture:\n\nA standalone sidecar binary that intercepts HTTP/SSE MCP traffic. Works with **any language** (Python, TypeScript, Go, etc.) and any agent framework. Zero code changes required — just route your MCP traffic through the proxy.\n\n```\nAI Agent (any language) → SentinelMCP Proxy → MCP Server\n```\n\nA Go library imported directly into your application. Wraps MCP tool calls **in-memory** with zero-copy graph orchestration. Provides sub-millisecond latency and deep context awareness — no network hop, no separate process.\n\n```\nGo AI Application → SentinelMCP SDK (in-process) → MCP Server\n```\n\nThis dual-mode architecture is SentinelMCP's key differentiator: competitors like Permit or Envoy only offer network proxies. With the Inline SDK, Go applications get the same security enforcement at a fraction of the latency.\n\n**MCP Proxy (Sidecar)**— Drop-in HTTP/SSE proxy for any MCP client. Transparent to existing agent frameworks.** Inline SDK (Go)**— Native Go module for in-process enforcement. Sub-millisecond overhead on the Allow path (19μs p99).** Policy Engine**— Local YAML-based policy definitions with hot-reloading. Risk levels (low/medium/high) map to enforcement actions (allow/redact/block/interrupt).**Data Loss Prevention (DLP)**— Regex-based PII and secret redaction in tool arguments and responses. 6 built-in patterns (private keys, passwords, API keys, credit cards, SSNs, emails) plus custom regex support.**Human-in-the-Loop (HITL)**— Interrupt high-risk tool calls via generic Webhooks and resume via a local API endpoint. BoltDB-backed checkpoints for durable interrupt/resume.**Audit Logging**— Structured JSON logging to`stdout`\n\nand native OpenTelemetry (OTel) integration for SIEM pipelines.**State Management**— BoltDB-backed checkpoints for durable interrupt/resume across process restarts.\n\nSentinelMCP is built with a strict separation of concerns to ensure maintainability, testability, and a seamless Open-Core experience.\n\nThe `gateway/`\n\npackage defines all core interfaces and domain types (Policy, DLP, Risk, Audit) with **zero dependencies** on the underlying Eino framework or MCP transport libraries. The `adapter/eino/`\n\npackage is the *only* package that imports Eino types.\n\nThis architectural boundary provides three major benefits:\n\n**Framework Agnostic:** If the underlying orchestration framework ever needs to change, only a new adapter is required; the core security engine remains untouched.**Independently Testable:** Core domain logic (policy evaluation, DLP redaction, risk analysis) can be unit-tested cleanly without spinning up MCP servers or LLM graphs.**Architecturally Enforced Open-Core:** Enterprise implementations (Teams/Slack HITL, Nightfall DLP, Control Plane APIs) simply swap into the`GatewayConfig`\n\nvia interfaces. Zero changes to this OSS codebase are required.\n\n**1. Start the sidecar with Docker:**\n\n```\ndocker run --name sentinelmcp \\\n  -p 8080:8080 -p 9090:9090 \\\n  -v ./policies.yaml:/etc/sentinelmcp/config.yaml \\\n  ghcr.io/technosiveuk-ui/sentinelmcp:latest\n```\n\nPort `8080`\n\nis the MCP proxy; `9090`\n\nis the admin API (health checks and the approval-resume endpoint used by high-risk interrupts). Add `-d`\n\nto run detached, then follow logs with `docker logs -f sentinelmcp`\n\n.\n\n**2. Define your policy ( policies.yaml):**\n\n```\nschema_version: \"1.0\"\n\nglobal:\n  default_risk: low                 # risk for tools with no explicit entry (set medium for a stricter default)\n  redaction_mask: \"***REDACTED***\"\n\nsidecar:\n  listen_addr: \":8080\"\n  health_addr: \":9090\"\n  transport: streamable_http\n  upstream_servers:                 # your MCP tool servers — at least one is required\n    - name: my-tools\n      url: \"http://localhost:3001/mcp\"\n\ntools:\n  read_file:\n    risk: low                       # allow — args and response are still DLP-scanned\n    redact_patterns: [PASSWORD, API_KEY]\n\n  write_file:\n    risk: medium                    # redact — sensitive argument fields are masked before the tool runs\n\n  exec_command:\n    risk: high                      # interrupt — pauses for human approval, then runs or blocks\n    require_approval: true\n    approval_reason: \"Shell commands can modify system state\"\n\n  \"db_*\":                           # glob patterns are supported\n    risk: high\n    require_approval: true\n\ndlp_patterns:                       # six patterns are built in (PRIVATE_KEY, PASSWORD, API_KEY,\n  INTERNAL_HOSTNAME:                # CREDIT_CARD, SSN, EMAIL); define your own here as needed\n    regex: '\\b[a-z]+\\.internal\\.company\\.com\\b'\n    type: pii\n```\n\n**3. Point your MCP client at the proxy:**\n\n```\nhttp://localhost:8080/mcp\n```\n\nThe proxy speaks standard Streamable HTTP MCP, so any client — Python, TypeScript, or Go — connects to that URL with no SDK changes. Point `upstream_servers`\n\nat your own MCP tool server(s) and the proxy enforces the policy above on every call.\n\nSecure tool calls **in-process** with a small builder API — no sidecar, no network hop, sub-millisecond overhead. Full guide: [ docs/INLINE-SDK.md](/technosiveuk-ui/SentinelMCP/blob/main/docs/INLINE-SDK.md).\n\nRequires v0.2.0+.The Inline SDK (`sdk/`\n\npackage) shipped in v0.2.0.\n\n```\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"log\"\n\n    \"github.com/technosiveuk-ui/sentinelmcp/gateway\"\n    \"github.com/technosiveuk-ui/sentinelmcp/sdk\"\n)\n\nfunc main() {\n    // Register plain Go functions as secured tools.\n    invoker := sdk.NewFuncInvoker().\n        Register(\"read_file\", func(_ context.Context, args map[string]any) (string, error) {\n            return fmt.Sprintf(\"contents of %v\", args[\"path\"]), nil\n        }).\n        Register(\"exec_command\", func(_ context.Context, args map[string]any) (string, error) {\n            return fmt.Sprintf(\"ran %v\", args[\"cmd\"]), nil\n        })\n\n    // Build the pipeline. StrictDefaults routes unknown tools to redact.\n    pipeline, err := sdk.New(invoker).\n        WithRisk(\"exec_command\", gateway.RiskHigh). // interrupt for approval\n        StrictDefaults().\n        Build()\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Every call is inspected, DLP-scanned, policy-checked, and audited.\n    result, err := pipeline.Run(context.Background(), \"read_file\", map[string]any{\n        \"path\": \"/etc/config.yaml\",\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n    fmt.Println(\"Result:\", result)\n}\n```\n\nRun the complete allow / redact / interrupt example:\n\n```\ngo run ./examples/inline-sdk\nphp\nflowchart LR\n    A[AI Agent] --> S[SentinelMCP]\n    S --> I[Inspect Tool Call]\n    I --> D{Policy Decision}\n    D -->|Allow| E[Execute Tool]\n    D -->|Redact| R[Redact PII] --> E\n    D -->|Block| X[Return Error]\n    D -->|Interrupt| H[Human Approval]\n    H -->|Approved| E\n    H -->|Denied| X\n    E --> O[Inspect Response]\n    O --> A\n    E --> MCP[MCP Server]\n    MCP --> O\n```\n\n**Pipeline flow:**\n\n**Inspect**— Serialize tool arguments, run DLP scanning, look up risk level in policy DB** Policy Decision**— Route by risk: low→allow, medium→redact, high→interrupt for approval, or block** Execute**— Call the upstream MCP tool (with redacted arguments if applicable)** Inspect Response**— DLP-scan the tool response, redact findings, emit structured audit event\n\n```\nsentinelmcp/\n├── gateway/               # Core domain (ZERO Eino imports)\n│   ├── types.go           # GatewayContext, AuditEvent, DLPFinding, RiskLevel, Decision\n│   ├── graph.go           # Pipeline, ToolInvoker, GatewayConfig, MetricsRecorder\n│   ├── policy.go          # Policy interface + DefaultPolicy\n│   ├── redact.go          # DLPScanner, Redactor + RegexDLPScanner + DefaultRedactor\n│   ├── dlp_multi.go       # MultiDLPScanner (compose regex + external)\n│   ├── dlp_external.go    # DLPEndpoint interface + ExternalDLPScanner adapter\n│   ├── riskdb.go          # RiskDB interface + YAMLRiskDB\n│   ├── audit.go           # AuditEmitter interface + Stdout/FileAuditEmitter\n│   ├── audit_sink.go      # AuditSink + WriterAuditSink + CompositeAuditEmitter\n│   ├── metrics.go         # MetricsRecorder interface + NOPMetricsRecorder\n│   └── webhook_approval.go # WebhookApprovalProvider + CLIApprovalProvider\n├── sdk/                   # Inline SDK: ergonomic builder over gateway + adapter\n│   ├── builder.go         # Builder API (New, With*, StrictDefaults, Build)\n│   ├── func_invoker.go    # FuncInvoker — secure plain Go functions\n│   └── defaults.go        # Convenience constructors (BuiltinDLP, StdoutAudit, …)\n├── adapter/eino/          # Eino framework adapter (ONLY package with Eino imports)\n│   ├── graph.go           # BuildGraph() → 3-node graph with interrupt/resume\n│   ├── otel_metrics.go    # OTelMetricsRecorder (counters + histograms)\n│   ├── otel_audit_emitter.go # OTelAuditEmitter (audit → span events)\n│   └── bolt_checkpoint.go # BoltCheckPointStore\n├── adapter/sidecar/       # Sidecar proxy adapters\n│   ├── invoker.go         # SidecarInvoker (routes to upstream MCP servers)\n│   └── discovery.go       # DiscoverTools (upstream MCP server discovery)\n├── adapter/siem/          # SIEM audit sink implementations\n│   ├── splunk_hec.go      # SplunkHECSink (batching + retry)\n│   └── file_rotation.go   # FileRotationSink (size-based + gzip)\n├── config/                # YAML config loading, validation, hot-reload\n│   ├── config.go          # Load, Validate, ToRiskDB, ToDLPPatterns\n│   └── watcher.go         # ConfigWatcher (fsnotify + debounce)\n├── cmd/\n│   ├── sentinelmcp/       # Sidecar proxy binary\n│   │   ├── main.go        # Bootstrap: config → discover → pipeline → proxy → admin\n│   │   ├── proxy.go       # Proxy MCP server wrapping the pipeline\n│   │   ├── health.go      # Admin server: /healthz, /readyz, /api/v1/approval/resume\n│   │   └── config.go      # GatewayConfig wiring (audit sinks, approval, OTel)\n│   ├── upstream/          # Demo upstream MCP server (3 tools)\n│   ├── testclient/        # Demo test client (3 enforcement flows)\n│   └── demo/              # In-process demo (4 MCP servers)\n├── examples/\n│   └── inline-sdk/        # Runnable allow/redact/interrupt SDK demo\n├── Dockerfile             # Multi-stage distroless build\n├── docker-compose.yml     # One-command demo\n└── config/\n    ├── config.yaml        # Default config\n    └── docker-config.yaml # Docker-specific config\n```\n\n| Feature | OSS (This Repo — Apache 2.0) | Enterprise (Commercial) |\n|---|---|---|\nDeployment |\nSidecar Proxy + Inline Go SDK | Centralized Control Plane |\nPolicies |\nLocal YAML with hot-reload | Centralized API/DB, Web UI |\nDLP |\nRegex-based (6 built-in + custom) | Enterprise DLP connectors (API-based) |\nHITL Approval |\nGeneric Webhook + CLI | Corporate communication channels |\nAudit |\nJSON stdout + OTel | SIEM Aggregation, Compliance PDFs |\nAuth |\nNone (single-tenant) | SSO, RBAC, multi-tenant |\nState |\nBoltDB (local) | Distributed (Postgres) |\n\nNote:The Enterprise Control Plane connects to the sidecar/SDK by implementing the`gateway/`\n\ninterfaces (`Policy`\n\n,`DLPScanner`\n\n,`AuditEmitter`\n\n,`ApprovalProvider`\n\n, etc.). Zero changes to this OSS codebase are required.\n\nBenchmarks on Apple M1 Pro (Go 1.26):\n\n| Path | Latency | Allocations |\n|---|---|---|\n| Allow (critical path) | 19μs |\n182 |\n| Redact | 19μs | 185 |\n| Interrupt | 33μs | 303 |\n| DLP scan | 9.3μs | 0 |\n| RiskDB lookup | 71ns | 0 |\n| Policy decide | 193ns | 4 |\n\n| NFR | Target | Validated By |\n|---|---|---|\n| p99 latency | ≤500μs Allow | `BenchmarkPipeline_Allow` — 19μs (26× under budget) |\n| Memory | <10MB heap per 1k calls | `TestMemory_*` — 0.73MB concurrent |\n| Concurrency | 100+ concurrent, no deadlock | `TestLoad_*` — 1000 concurrent, 0 deadlocks |\n| Default-deny | Block on all failures | `TestDegradation_*` — all error paths block |\n\n90+ tests across 6 packages, 7 benchmarks, all passing with `-race`\n\n:\n\n```\n# Run all tests\ngo test ./... -race -count=1\n\n# NFR validation\ngo test ./adapter/eino/ -run \"TestLoad_|TestMemory_|TestDegradation_\" -race -v\n\n# Sidecar E2E\ngo test ./cmd/sentinelmcp/ -race -v\n\n# Benchmarks\ngo test ./adapter/eino/ -bench=. -benchmem\n```\n\nContributions are welcome! Please read [CONTRIBUTING.md](/technosiveuk-ui/SentinelMCP/blob/main/CONTRIBUTING.md) for details.\n\nAll contributors must sign off on their commits (DCO — Developer Certificate of Origin) to ensure they have the right to submit their code under the Apache 2.0 license.\n\n```\nSigned-off-by: Your Name <your.email@example.com>\n```\n\n**Open Source Code:**\nThe code in this repository, including the `gateway/`\n\ninterfaces and `adapter/`\n\nimplementations, is licensed under the [Apache 2.0 License](/technosiveuk-ui/SentinelMCP/blob/main/LICENSE). You are free to use, modify, and distribute this code in accordance with that license.\n\n**Enterprise Extensions & Interface Implementations:**\nThis repository defines extensibility interfaces (e.g., `Policy`\n\n, `DLPScanner`\n\n, `ApprovalProvider`\n\n, `AuditEmitter`\n\n) in the `gateway/`\n\npackage to allow for custom integrations. While the interfaces themselves are Apache 2.0, **proprietary implementations of these interfaces provided by Technosive Ltd.** (such as the SentinelMCP Enterprise Control Plane, corporate communication HITL integrations, and advanced DLP connectors) are licensed separately under a commercial license and are not included in this repository.\n\nImplementing these interfaces in your own code does not require you to license your implementations under Apache 2.0, nor does it obligate you to open-source your custom integrations.\n\n**Trademark:**\n\"SentinelMCP\" and the SentinelMCP logo are trademarks of Technosive Ltd. The Apache 2.0 license does not grant you the right to use the SentinelMCP trademark to endorse or promote products or services derived from this software without prior written permission from Technosive Ltd.", "url": "https://wpnews.pro/news/sentinelmcp-an-open-source-firewall-for-ai-agents-that-use-mcp", "canonical_source": "https://github.com/technosiveuk-ui/SentinelMCP", "published_at": "2026-06-13 01:51:11+00:00", "updated_at": "2026-06-13 02:20:23.168359+00:00", "lang": "en", "topics": ["ai-safety", "ai-agents", "ai-infrastructure", "developer-tools", "ai-tools"], "entities": ["Technosive Ltd.", "SentinelMCP", "Model Context Protocol", "MCP", "Go", "BoltDB", "OpenTelemetry", "Eino"], "alternates": {"html": "https://wpnews.pro/news/sentinelmcp-an-open-source-firewall-for-ai-agents-that-use-mcp", "markdown": "https://wpnews.pro/news/sentinelmcp-an-open-source-firewall-for-ai-agents-that-use-mcp.md", "text": "https://wpnews.pro/news/sentinelmcp-an-open-source-firewall-for-ai-agents-that-use-mcp.txt", "jsonld": "https://wpnews.pro/news/sentinelmcp-an-open-source-firewall-for-ai-agents-that-use-mcp.jsonld"}}