The deterministic execution boundary for AI agents.
Build governed LangGraph workflows with ramen-foundry.
Standard safety filters catch basic syntax. They fail against encoded payloads and corporate jargon. We challenge you to bypass our semantic firewall using the zero-day evasion vectors in our official Red Team Guide.
Below is a simulation of the Grok/Bankr heist. We fed the raw adversarial prompt directly into our sandbox. It uses a social engineering wrapper (claiming a visual impairment) to smuggle a 3,000,000,000 DRB transfer instruction encoded in Morse code. The firewall evaluated the underlying semantic intent, intercepted the unauthorized financial transfer, and blocked it pre-execution, issuing a verified Ed25519 receipt.
To use this integration, you must mint an API Key.
We offer a Free Starter Tier (1,000 evaluations/month, BYOK) which includes full access to our Core IT Security bundle. Mint your key at:
Provider configuration is optional at the integration level so Enterprise managed-provider mode remains available. The Starter and Professional tiers use your own LLM provider key for inference, so those tiers need two keys:
| Key | Purpose | Where to get it |
|---|---|---|
RAMEN_API_KEY |
Authenticates you to the ramen-ai platform | ramenai.dev/pricing |
OPENAI_API_KEY (or ANTHROPIC_API_KEY) |
Forwarded as X-Provider-Key for LLM inference |
Your provider's developer portal |
export RAMEN_API_KEY=ramen_ak_...
export OPENAI_API_KEY=sk-... # or ANTHROPIC_API_KEYThe proxy forwards the provider key and matching provider name together. It
infers openai or anthropic from the selected key unless RAMEN_PROVIDER is
set. OPENAI_API_KEY takes precedence if both keys are present. Without a
provider key, Starter and Professional requests return 402 Payment Required.
Enterprise tier users have keys managed server-side. Omit
OPENAI_API_KEY, ANTHROPIC_API_KEY, and RAMEN_PROVIDER entirely. The proxy
then sends neither providerKey nor providerName, allowing ramen-ai to use
platform-managed inference.
A universal MCP stdio proxy that intercepts tools/call JSON-RPC messages at the transport layer, evaluates them against the ramen-ai L2 Semantic Firewall, and blocks malicious payloads pre-execution — before they ever reach the downstream MCP server.
Works with any MCP server that uses stdio transport: filesystem, fetch, GitHub, Brave Search, custom servers, and more. No SDK changes required. Drop it in front of any existing server in under two minutes.
Claude Desktop / MCP client
│
│ stdin (newline-delimited JSON-RPC)
▼
┌─────────────────────────────────────────────┐
│ mcp-shield-proxy │
│ │
│ tools/call? │
│ → evaluate: {tool, arguments} │
│ ALLOWED + verified receipt │
│ → forward to child stdin │
│ BLOCKED or unverified │
│ → synthesise isError response │
│ back to client stdout │
│ │
│ anything else → forward unchanged │
└─────────────────────────────────────────────┘
│
│ stdin (only allowed tool calls reach here)
▼
Downstream MCP server (child process)
│
│ stdout (responses, notifications)
▼
Claude Desktop / MCP client
Every tools/call is intercepted and evaluated against the ramen-ai PaaS API
before being forwarded. All other MCP messages — initialize, tools/list,
resources/read, notifications — pass through unchanged. The proxy is
transparent to the MCP client.
Fail-closed: if the ramen-ai API is unreachable or returns an error, the
tool call is blocked and an isError: true response is returned. An
unavailable firewall never becomes an open door.
Verified ALLOW only: an allowed: true verdict is not enough to reach the
downstream server. Matching ramen-foundry's RamenToolNode, the proxy forwards
a call only when all of these hold:
- A Schema V5 receipt is present.
@ramen-ai/node-coreverified it against the exact evaluated input (Ed25519 signature under the pinnedramen_pk_v1key, and thepayload_hashbinding).- The signed payload records
verdict: 1(ALLOW), with matchingkidandid.
The third check closes a gap in the second: a genuine, validly signed BLOCK
receipt for the same input, returned with allowed flipped to true, passes
the input binding but not the signed verdict. Any failure blocks the call with
isError: true and a steering message saying the verdict could not be
cryptographically verified. A server-side signing outage (receipt_alert)
therefore blocks allowed calls rather than releasing them unsigned.
npm install -g @ramen-ai/mcp-shield-proxy
# or run directly without installing:
npx @ramen-ai/mcp-shield-proxy --helpnpm: https://www.npmjs.com/package/@ramen-ai/mcp-shield-proxy
Claude Desktop's claude_desktop_config.json normally points directly at your
MCP server. To add the firewall, wrap the server command with
mcp-shield-proxy.
Before (direct connection):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"],
"env": {}
}
}
}After (firewall-wrapped, Starter/Professional BYOK):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@ramen-ai/mcp-shield-proxy",
"--bundle-ids", "ramen__shield_core_it",
"--",
"npx", "-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"
],
"env": {
"RAMEN_API_KEY": "ramen_ak_...",
"OPENAI_API_KEY": "sk-..."
}
}
}
}For Enterprise managed-provider mode, keep RAMEN_API_KEY and remove all
provider entries from env.
The -- separator marks the boundary between proxy flags and the downstream
server command. Everything after -- is spawned as the child process.
| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
mcp-shield-proxy [options] -- <command> [args...]
Options:
--target <cmd> Target MCP server command (quoted, alternative to --)
--bundle-ids <ids> Comma-separated bundle slugs
--policy-ids <ids> Comma-separated policy UUIDs (alternative to --bundle-ids)
--log-level <level> silent | info | debug (default: info)
--forge-url <url> ramen forge base URL for query_domain_memory
(default: https://forge.ramenai.dev; https only, http for localhost)
--domain <slug> Default memory and provenance domain (default: general)
--help Show this message
# Wrap the MCP filesystem server in Enterprise managed-provider mode
RAMEN_API_KEY=ramen_ak_... \
mcp-shield-proxy --bundle-ids ramen__shield_core_it \
-- npx -y @modelcontextprotocol/server-filesystem /home/user
# Wrap the Brave Search MCP server (Starter/Professional BYOK)
RAMEN_API_KEY=ramen_ak_... \
OPENAI_API_KEY=sk-... \
mcp-shield-proxy --bundle-ids ramen__shield_core_it \
-- npx -y @modelcontextprotocol/server-brave-search
# Use explicit policy UUIDs instead of a bundle
RAMEN_API_KEY=ramen_ak_... \
mcp-shield-proxy --policy-ids 6c787849-96db-4c92-8df9-10aa8d035527 \
-- node ./my-mcp-server.js
# Debug mode — logs every intercepted message to stderr
RAMEN_API_KEY=ramen_ak_... \
mcp-shield-proxy --bundle-ids ramen__shield_core_it --log-level debug \
-- npx -y @modelcontextprotocol/server-filesystem /tmp| Variable | Required | Description |
|---|---|---|
RAMEN_API_KEY |
yes | ramen-ai PaaS API key (ramen_ak_...). Never pass as a CLI argument. |
OPENAI_API_KEY |
Starter/Pro only | Optional integration setting; required for OpenAI BYOK on Starter/Professional. Forwarded as X-Provider-Key and takes precedence if both provider keys are set. |
ANTHROPIC_API_KEY |
Starter/Pro only | Optional integration setting; alternative Anthropic BYOK key used when OPENAI_API_KEY is absent. |
RAMEN_PROVIDER |
no | Optional provider override: openai | anthropic | google. Used only with a provider key; otherwise inferred from the selected key. |
RAMEN_BASE_URL |
no | Override the ramen-ai API base URL (for staging/testing). |
BYOK is an optional provider mode for the integration and is required for
Starter and Professional usage. Pass a provider key via OPENAI_API_KEY or
ANTHROPIC_API_KEY; the proxy forwards the selected key and automatically
routes it to openai or anthropic. OPENAI_API_KEY takes precedence when
both are set. Use RAMEN_PROVIDER only when an explicit provider override is
needed. Without a provider key, the API returns 402 Payment Required on these
tiers.
Enterprise managed-provider mode remains available without BYOK. Omit all provider variables so the proxy sends neither provider field and ramen-ai can use platform-managed inference.
When a tool call is blocked, the proxy synthesises a valid MCP tool result
with isError: true and returns it to the client. The downstream server never
sees the request. The response content contains the verdict, statutory anchors,
and the steering instruction:
{
"jsonrpc": "2.0",
"id": 42,
"result": {
"content": [
{
"type": "text",
"text": "[BLOCKED] Tool 'drop_database_table' was blocked by the ramen-ai L2 Semantic Firewall.\nStatutory anchors: OWASP ASI-06\nSteering: Refuse destructive operations on production databases.\nReceipt verified (Ed25519): true"
}
],
"isError": true
}
}The MCP client (for example, Claude Desktop) surfaces this as a tool error and the model receives the steering instruction, enabling deterministic recovery rather than a silent failure.
The proxy adds its own read-only tool to the downstream server's tools/list
response, so MCP clients such as Claude Desktop and Cursor can look up
codified lessons on ramen forge before calling a
tool:
{
"name": "query_domain_memory",
"inputSchema": {
"type": "object",
"properties": {
"domain": { "type": "string", "description": "e.g. fintech, industrial_iot, devsecops" },
"tool_name": { "type": "string", "description": "Name of the tool about to be invoked" },
"query": { "type": "string", "description": "Optional keyword search string" }
},
"required": ["tool_name"]
}
}- The proxy answers this tool itself and never forwards it to the downstream
server. It is a read of public, advisory data with no side effects, so it is
not sent to the ramen-ai firewall. Every other
tools/callstill is. - Results come back as text for the model and as
structuredContent(up to 5 lessons: violation, statutory anchor, steering directive, failed and repaired arguments, receipt id, and whether the forge holds a signature). domaindefaults to--domain. Reads fail open: if ramen forge is unreachable the tool returns an empty result instead of an error.- Recalled lessons are untrusted guidance. Anyone with a forge write token can contribute one, and the proxy never writes to ramen forge.
- If the downstream server already exposes a tool named
query_domain_memory, the proxy does not add or shadow it; calls go to the server through the governed path.
Each governed tools/call result carries a provenance envelope under
result._meta["ramenai.dev/provenance"], both for allowed calls (merged into
the downstream server's result, keeping its own _meta) and for blocked
responses. query_domain_memory results carry one describing the top lesson.
{
"source": "ramen-local",
"version": "1.0",
"domain": "fintech",
"tool_name": "read_file",
"exemplar_id": null,
"statutory_anchor": null,
"receipt_id": "c29be406-7de5-4bd1-85d2-eea74a321a38",
"prevention_summary": null,
"audit_uri": null
}The shape is RamenProvenanceEnvelope from @ramen-ai/node-core, the same
envelope ramen-foundry emits as _ramen_provenance. MCP requires _meta keys
to begin with a letter or digit, so the proxy namespaces it as
ramenai.dev/provenance. source is ramen-forge only when the envelope
points at a ramen forge lesson; lesson fields are null otherwise.
| Bundle slug | Coverage |
|---|---|
ramen__shield_core_it |
Destructive execution, prompt injection, secret exfiltration, OWASP ASI-06 indirect injection |
ramen__eu_ai_act_baseline |
EU AI Act Articles 5, 10, and 50 — prohibited practices, data governance, transparency |
ramen__industrial_iot_actuation_invariance |
Industrial actuation invariants, including Robotics Physical Safety & Biomechanical Invariance (1fc71052-eb7e-43fe-9bfa-7ee06afe5b95) |
Full bundle reference and pricing: https://ramenai.dev/pricing
- Secrets in config files:
claude_desktop_config.jsonis stored on disk. On shared machines, prefer settingRAMEN_API_KEYand provider keys as system-level environment variables rather than hardcoding them in the config. - Pass-through traffic: only
tools/callmessages are evaluated, except the proxy's own read-onlyquery_domain_memory. All other MCP message types (resource reads, prompt fetches, notifications) pass through without evaluation. If you need to evaluate those, use the ramen-ai SDK directly in your server implementation. - Logging: at
--log-level debug, tool names and argument shapes are logged to stderr. Do not use debug mode in production environments where stderr may be captured to persistent logs.
npm install
npm run build # tsc → dist/
npm test # vitest run (35 tests)
npm run typecheck # tsc --noEmit
