AgentStack
MCP verified Apache-2.0 Self-run

SentinelMCP

mcp-technosiveuk-ui-sentinelmcp · by technosiveuk-ui

The Open-Source MCP Firewall & Security Gateway for AI Agents. Inspect, redact, and control tool calls. Proxy mode (universal) and Inline SDK mode (Go).

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

Install

$ agentstack add mcp-technosiveuk-ui-sentinelmcp

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

Are you the author of SentinelMCP? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

SentinelMCP

The Open-Source MCP Security Gateway for AI Agents

Built by Technosive Ltd.

[](LICENSE) [](go.mod) [](https://github.com/technosiveuk-ui/SentinelMCP/actions/workflows/ci.yml)


> ⚠️ Alpha Software — v0.1 > > SentinelMCP is currently in Alpha. The project is under active development and APIs, configuration formats, and graph behaviors may change in future releases without advance notice. > > Production warning: This software is provided as-is. While we strive for security, an Alpha-stage proxy should not be 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 open an issue. Your input directly shapes the roadmap.


What is SentinelMCP?

SentinelMCP 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.

Built 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.


Two Deployment Modes

SentinelMCP can be deployed in two ways, depending on your architecture:

1. Proxy Mode (Universal)

A 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.

AI Agent (any language) → SentinelMCP Proxy → MCP Server

2. Inline SDK Mode (Go Native)

A 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.

Go AI Application → SentinelMCP SDK (in-process) → MCP Server

This 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.


Key Features

  • 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.
  • Transport & Auth Security — A security gateway must harden its own transport too. Loopback-plaintext-default with fail-closed hardening: opt-in inbound TLS, API-key authentication, an admin token gating approval-resume, strict mode that rejects plaintext/IP-literal upstreams, upstream cert pinning, outbound credential injection, and an egress allowlist. See [Transport Security](docs/transport-security.md).
  • 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 and native OpenTelemetry (OTel) integration for SIEM pipelines.
  • State Management — BoltDB-backed checkpoints for durable interrupt/resume across process restarts.

🏗️ Architecture & Extensibility

SentinelMCP is built with a strict separation of concerns to ensure maintainability, testability, and a seamless Open-Core experience.

The gateway/ package 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/ package is the only package that imports Eino types.

This architectural boundary provides three major benefits:

  1. Framework Agnostic: If the underlying orchestration framework ever needs to change, only a new adapter is required; the core security engine remains untouched.
  2. Independently Testable: Core domain logic (policy evaluation, DLP redaction, risk analysis) can be unit-tested cleanly without spinning up MCP servers or LLM graphs.
  3. Architecturally Enforced Open-Core: Enterprise implementations (Teams/Slack HITL, Nightfall DLP, Control Plane APIs) simply swap into the GatewayConfig via interfaces. Zero changes to this OSS codebase are required.

Quickstart

Proxy Mode

1. Start the sidecar. The fastest path is the bundled three-service demo — an upstream MCP server with demo tools, the sidecar, and a test client that exercises every enforcement flow:

docker compose up --build --abort-on-container-exit

For a persistent sidecar against your own upstream, run a single container (or locally: go run ./cmd/sentinelmcp -config policies.yaml):

docker run --name sentinelmcp \
  -p 8080:8080 -p 9090:9090 \
  -v ./policies.yaml:/etc/sentinelmcp/config.yaml \
  ghcr.io/technosiveuk-ui/sentinelmcp:latest

Port 8080 is the MCP proxy; 9090 is the admin API (health probes and the approval-resume endpoint used by high-risk interrupts). Add -d to run detached, then follow logs with docker logs -f sentinelmcp. The example config below binds loopback, which suits a local run; a non-loopback bind (e.g. 0.0.0.0 inside a container) requires TLS or the --insecure-dev-mode flag — see [Transport Security](docs/transport-security.md).

2. Define your policy (policies.yaml):

schema_version: "1.0"

global:
  default_risk: low                 # risk for tools with no explicit entry (set medium for a stricter default)
  redaction_mask: "***REDACTED***"

sidecar:
  listen_addr: "localhost:8080"     # loopback bind → plaintext HTTP is safe here
  health_addr: "localhost:9090"     # admin server (health + approval-resume); loopback enforced
  transport: streamable_http
  strict: false                     # DEMO ONLY — the local upstream below is plaintext. Production
                                    # MUST set strict: true and dial https:// upstreams.
  admin_token: ""                   # gates /api/v1/approval/resume — set via SENTINELMCP_ADMIN_TOKEN
  # tls:                            # opt-in inbound TLS; required when listen_addr is non-loopback
  #   cert_file: "/etc/sentinelmcp/tls.crt"
  #   key_file:  "/etc/sentinelmcp/tls.key"
  upstream_servers:                 # your MCP tool servers — at least one is required
    - name: my-tools
      url: "http://localhost:3001/mcp"

auth:
  api_keys: {}                      # inbound key → principal; enforced on every call when non-empty
                                    # e.g. { "key-abc": "agent-prod" } via Authorization: Bearer / X-API-Key

tools:
  read_file:
    risk: low                       # allow — args and response are still DLP-scanned
    redact_patterns: [PASSWORD, API_KEY]

  write_file:
    risk: medium                    # redact — sensitive argument fields are masked before the tool runs

  exec_command:
    risk: high                      # interrupt — pauses for human approval, then runs or blocks
    require_approval: true
    approval_reason: "Shell commands can modify system state"

  "db_*":                           # glob patterns are supported
    risk: high
    require_approval: true

dlp_patterns:                       # six patterns are built in (PRIVATE_KEY, PASSWORD, API_KEY,
  INTERNAL_HOSTNAME:                # CREDIT_CARD, SSN, EMAIL); define your own here as needed
    regex: '\b[a-z]+\.internal\.company\.com\b'
    type: pii

3. Point your MCP client at the proxy:

http://localhost:8080/mcp

The proxy speaks standard Streamable HTTP MCP, so any client — Python, TypeScript, or Go — connects to that URL with no SDK changes. Point upstream_servers at your own MCP tool server(s) and the proxy enforces the policy above on every call.

Inline SDK Mode

Secure tool calls in-process with a small builder API — no sidecar, no network hop, sub-millisecond overhead. Full guide: [docs/INLINE-SDK.md](docs/INLINE-SDK.md).

> Requires v0.2.0+. The Inline SDK (sdk/ package) shipped in v0.2.0.

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/technosiveuk-ui/sentinelmcp/gateway"
    "github.com/technosiveuk-ui/sentinelmcp/sdk"
)

func main() {
    // Register plain Go functions as secured tools.
    invoker := sdk.NewFuncInvoker().
        Register("read_file", func(_ context.Context, args map[string]any) (string, error) {
            return fmt.Sprintf("contents of %v", args["path"]), nil
        }).
        Register("exec_command", func(_ context.Context, args map[string]any) (string, error) {
            return fmt.Sprintf("ran %v", args["cmd"]), nil
        })

    // Build the pipeline. StrictDefaults routes unknown tools to redact.
    pipeline, err := sdk.New(invoker).
        WithRisk("exec_command", gateway.RiskHigh). // interrupt for approval
        StrictDefaults().
        Build()
    if err != nil {
        log.Fatal(err)
    }

    // Every call is inspected, DLP-scanned, policy-checked, and audited.
    result, err := pipeline.Run(context.Background(), "read_file", map[string]any{
        "path": "/etc/config.yaml",
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Result:", result)
}

Run the complete allow / redact / interrupt example:

go run ./examples/inline-sdk

How It Works

flowchart LR
    A[AI Agent] --> S[SentinelMCP]
    S --> I[Inspect Tool Call]
    I --> D{Policy Decision}
    D -->|Allow| E[Execute Tool]
    D -->|Redact| R[Redact PII] --> E
    D -->|Block| X[Return Error]
    D -->|Interrupt| H[Human Approval]
    H -->|Approved| E
    H -->|Denied| X
    E --> O[Inspect Response]
    O --> A
    E --> MCP[MCP Server]
    MCP --> O

Pipeline flow:

  1. Inspect — Serialize tool arguments, run DLP scanning, look up risk level in policy DB
  2. Policy Decision — Route by risk: low→allow, medium→redact, high→interrupt for approval, or block
  3. Execute — Call the upstream MCP tool (with redacted arguments if applicable)
  4. Inspect Response — DLP-scan the tool response, redact findings, emit structured audit event

Transport & Auth Security

SentinelMCP is a security gateway, so its own transport surface is hardened, not left plaintext. It follows a loopback-plaintext-default model: on a loopback address (127.0.0.1, ::1, localhost) the sidecar may run plaintext HTTP with no auth — the host boundary carries trust, like redis or postgres on a local socket. The moment it binds a non-loopback interface or dials a network upstream, it fail-closes to TLS and authentication instead of degrading to plaintext.

  • Strict mode (default true) rejects plaintext http:// and IP-literal upstream URLs at config load.
  • Inbound TLS is opt-in on loopback, required off-loopback (sidecar.tls).
  • API-key auth (auth.api_keys) validates every inbound call in constant time; the resolved principal reaches the policy and audit layers.
  • Admin token (sidecar.admin_token / SENTINELMCP_ADMIN_TOKEN) always gates the approval-resume endpoint, even on loopback.
  • Upstream identity can be pinned per-server (ca_bundle, server_name, pinned_sha256); InsecureSkipVerify is never set.
  • Outbound credentials are injected from a mode-0600 secrets.yaml or env, and never logged.
  • Egress allowlist (sidecar.egress_allowlist) bounds which upstream hosts may be dialed.
  • Secrets at rest: a group/world-readable config.yaml containing secrets, or a secrets.yaml, is refused at load.

Full rationale, the bind-policy matrix, and the complete fail-closed contract live in [docs/transport-security.md](docs/transport-security.md). The two open-core seams — gateway/auth.Authenticator and gateway/secrets.Provider — are where Enterprise implementations (mTLS, OAuth2/OIDC, HashiCorp Vault) attach behind the same pure interfaces.


Architecture

sentinelmcp/
├── gateway/               # Core domain (ZERO Eino imports)
│   ├── types.go           # GatewayContext, AuditEvent, DLPFinding, RiskLevel, Decision
│   ├── graph.go           # Pipeline, ToolInvoker, GatewayConfig, MetricsRecorder
│   ├── policy.go          # Policy, RiskDB interfaces + DefaultPolicy, YAMLRiskDB
│   ├── policy_action.go   # Action-based PolicySet (allow/redact/block/interrupt by rule)
│   ├── policy_reload.go   # Hot policy reload (atomic swap on config change)
│   ├── redact.go          # DLPScanner, Redactor, ScanArgs + RegexDLPScanner, DefaultRedactor
│   ├── dlp_multi.go       # MultiDLPScanner (compose regex + external)
│   ├── dlp_external.go    # DLPEndpoint interface + ExternalDLPScanner adapter
│   ├── audit.go           # AuditEmitter interface + Stdout/FileAuditEmitter
│   ├── audit_sink.go      # AuditSink + WriterAuditSink + CompositeAuditEmitter
│   ├── metrics.go         # MetricsRecorder interface + NOPMetricsRecorder
│   ├── webhook_approval.go # WebhookApprovalProvider + CLIApprovalProvider
│   ├── auth/              # Authenticator interface + APIKeyAuthenticator (open-core seam)
│   │   └── auth.go        #   pure — no net/http; key→principal, constant-time
│   └── secrets/           # secrets.Provider interface + FileEnvProvider (open-core seam)
│       └── secrets.go     #   pure — resolves credentials_ref; secrets.yaml (0600) or env
├── sdk/                   # Inline SDK: ergonomic builder over gateway + adapter
│   ├── builder.go         # Builder API (New, With*, StrictDefaults, Build)
│   ├── func_invoker.go    # FuncInvoker — secure plain Go functions
│   └── defaults.go        # Convenience constructors (BuiltinDLP, StdoutAudit, …)
├── adapter/eino/          # Eino framework adapter (ONLY package with Eino imports)
│   ├── graph.go           # BuildGraph() → 3-node graph with interrupt/resume
│   ├── otel_metrics.go    # OTelMetricsRecorder (counters + histograms)
│   ├── otel_audit_emitter.go # OTelAuditEmitter (audit → span events)
│   └── bolt_checkpoint.go # BoltCheckPointStore
├── adapter/sidecar/       # Sidecar proxy adapters
│   ├── invoker.go         # SidecarInvoker (routes to upstream MCP servers)
│   └── discovery.go       # DiscoverTools (upstream MCP server discovery)
├── adapter/siem/          # SIEM audit sink implementations
│   ├── splunk_hec.go      # SplunkHECSink (batching + retry)
│   └── file_rotation.go   # FileRotationSink (size-based + gzip)
├── config/                # YAML config loading, validation, hot-reload
│   ├── config.go          # Load, Validate, ToRiskDB, ToDLPPatterns
│   └── watcher.go         # ConfigWatcher (fsnotify + debounce)
├── cmd/
│   ├── sentinelmcp/       # Sidecar proxy binary
│   │   ├── main.go        # Bootstrap: config → discover → pipeline → proxy → admin
│   │   ├── proxy.go       # Proxy MCP server wrapping the pipeline
│   │   ├── health.go      # Admin server: /healthz, /readyz, /api/v1/approval/resume
│   │   └── config.go      # GatewayConfig wiring (audit sinks, approval, OTel)
│   ├── upstream/          # Demo upstream MCP server (3 tools)
│   ├── testclient/        # Demo test client (3 enforcement flows)
│   └── demo/              # In-process demo (4 MCP servers)
├── examples/
│   └── inline-sdk/        # Runnable allow/redact/interrupt SDK demo
├── Dockerfile

…

## Source & license

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

- **Author:** [technosiveuk-ui](https://github.com/technosiveuk-ui)
- **Source:** [technosiveuk-ui/SentinelMCP](https://github.com/technosiveuk-ui/SentinelMCP)
- **License:** Apache-2.0
- **Homepage:** https://technosive.co.uk/sentinelmcp

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.