MCP Proxies
An MCP Proxy puts the AIronClaw firewall in front of a Model Context Protocol server. Every tool call, resource read and prompt request the agent makes is parsed, inspected and policy-checked before reaching the upstream.
The MCP Proxy object#
The proxy record stores the upstream MCP URL, the optional upstream auth (bearer token) the firewall should inject, and the inbound auth method clients use to talk to the firewall. The the gateway plumbing — Service, Routes, plugin instances — is created automatically on first save and torn down on delete.
Fields
none or bearer.{ "mode": "aifw_api_key" } or { "mode": "jwt", "jwksJson": "..." }./tools). Each entry has name, description, JSON schema, etc.authToken plaintext, authTokenEnc ciphertext and any internal IDs are stripped from every response. The bearer you write is encrypted at rest and only decrypted in-plugin at request time.
Manage proxies#
List proxies#
curl https://app.aironclaw.com/api/mcp \
-H "Authorization: Bearer $AIFW_PAT"Create a proxy#
Validates the URL against the SSRF allow-list, enforces the per-user MCP quota, persists the record, and wires the gateway + the aifw plugin in one shot. Returns 403 if the quota is exhausted.
Body
bearer or none (default).authType is bearer. Encrypted before persistence; never returned.{ "mode": "aifw_api_key" }. Provide { "mode": "jwt", "jwksJson": "{...}" } for JWT validation.curl -X POST https://app.aironclaw.com/api/mcp \
-H "Authorization: Bearer $AIFW_PAT" \
-H "Content-Type: application/json" \
-d '{
"name": "filesystem-prod",
"url": "https://mcp.example.com/filesystem",
"authType": "bearer",
"authToken": "upstream-secret-...",
"auth": { "mode": "aifw_api_key" }
}'Retrieve a proxy#
Returns the proxy record plus the current upstream DNS pin (when available) so you can verify routing.
curl https://app.aironclaw.com/api/mcp/$ID \
-H "Authorization: Bearer $AIFW_PAT"Update a proxy#
Partial update. Changing urlre-validates against SSRF rules and rewires the gateway's upstream + DNS pin. Setting authToken rotates the encrypted upstream bearer. Setting auth swaps the inbound auth method (and re-pushes config to the aifw plugin).
curl -X PATCH https://app.aironclaw.com/api/mcp/$ID \
-H "Authorization: Bearer $AIFW_PAT" \
-H "Content-Type: application/json" \
-d '{ "url": "https://mcp.example.com/filesystem-v2" }'Delete a proxy#
Tears down gateway resources, removes the Redis record, and stripsmcp:<id>:tool:* / mcp:<id>:resource:* tags from every API key owned by the caller.
curl -X DELETE https://app.aironclaw.com/api/mcp/$ID \
-H "Authorization: Bearer $AIFW_PAT"Re-resolve upstream IP#
Forces an immediate DNS resolve + upstream DNS target update, short-circuiting the 60-second background timer. Useful right after a cloud LB cutover.
curl -X POST https://app.aironclaw.com/api/mcp/$ID/re-resolve \
-H "Authorization: Bearer $AIFW_PAT"Tools#
Discover tools#
Performs a live MCP tools/list handshake against the upstream (using the stored bearer if any), persists the result to the proxy record, and returns the discovered catalog. Use this whenever the upstream MCP adds, removes or renames a tool. Returns 502 if the upstream is unreachable.
curl -X POST https://app.aironclaw.com/api/mcp/$ID/tools \
-H "Authorization: Bearer $AIFW_PAT"Resources#
Resources let you serve static content (templates, prompts, docs, context) to the agent under MCP's resource API, without forwarding the request to the upstream. Resources live in a per-user repository and can be linked to zero or more MCP proxies via attachedMcpIds; deleting an MCP only detaches its id, never deletes the resource itself.
List resources#
curl https://app.aironclaw.com/api/resources \
-H "Authorization: Bearer $AIFW_PAT"Create resource#
Body
curl -X POST https://app.aironclaw.com/api/resources \
-H "Authorization: Bearer $AIFW_PAT" \
-H "Content-Type: application/json" \
-d '{
"uri": "file:///prompts/system.md",
"name": "System prompt",
"mimeType": "text/markdown",
"content": "You are a helpful assistant. Always...",
"attachedMcpIds": ["$MCP_ID"]
}'Retrieve resource#
curl https://app.aironclaw.com/api/resources/$RID \
-H "Authorization: Bearer $AIFW_PAT"Update resource#
Partial update on any of the fields above, including attachedMcpIds to re-link the resource to a different set of MCPs.
curl -X PATCH https://app.aironclaw.com/api/resources/$RID \
-H "Authorization: Bearer $AIFW_PAT" \
-H "Content-Type: application/json" \
-d '{ "content": "Updated body...", "attachedMcpIds": ["$MCP_A", "$MCP_B"] }'Delete resource#
curl -X DELETE https://app.aironclaw.com/api/resources/$RID \
-H "Authorization: Bearer $AIFW_PAT"Rules#
MCP proxies accept a richer rule grammar than LLM proxies. The allowed rule_type values are: ip_acl, rate_limit, tool_description_inject, response_replace, static_cache, mcp_resource and lambda (with phase either access or response). Every rule must include a tools array — use ["*"] to apply globally.
List rules#
curl https://app.aironclaw.com/api/mcp/$ID/rules \
-H "Authorization: Bearer $AIFW_PAT"Replace rules#
Replaces the full rule set in one shot. Validation mirrors the Lua plugin schema; common errors are missing tools, invalid CIDRs, and rate_limit rules without aname.
curl -X PUT https://app.aironclaw.com/api/mcp/$ID/rules \
-H "Authorization: Bearer $AIFW_PAT" \
-H "Content-Type: application/json" \
-d '{
"rules": [
{
"rule_type": "rate_limit",
"name": "delete-burst",
"tools": ["delete_file"],
"match_key": "consumer",
"threshold": 10,
"timespan": 60,
"ban_after_n_exceeded": 3,
"ban_timespan": 600
},
{
"rule_type": "tool_description_inject",
"tools": ["*"],
"inject_text": "Never run shell commands without explicit user approval.",
"inject_position": "append"
},
{
"rule_type": "static_cache",
"tools": ["list_dir"],
"cache_ttl": 600
}
]
}'Detection & Guardrails#
The MCP rule grammar covers the response-side and abuse-side of defense in depth. For request-side prompt-injection detection (regex catalog + LLM judge), pair the MCP with an LLM Proxy in front of your agent — see the layering note at the end of this section.
DLP via response_replace#
The response_replace rule applies a regex find-and-replace over the JSON-RPC result payload of any tool call before it reaches the agent. The DLP catalog ships seven categories of curated regexes — emails, IBAN and credit cards (Luhn / mod-97 validated), IPs, URLs, vendor API keys, PII patterns, generic high-entropy tokens. Add custom rules with your own pattern + replacement.
{
"rule_type": "response_replace",
"tools": ["*"],
"pattern": "[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}",
"replacement": "***",
"dlp_rule_id": "emails"
}Replacements apply to Streamable HTTP sync responses (the result body of the POST) and to async-mode (where a 202 POST is followed by the result on the open SSE channel) — both paths are inspected and rewritten before the bytes reach the agent.
Cross-call abuse via rate_limit + ban#
rate_limit is the cross-call abuse-detection layer. Scope on match_key = consumer, api_key or ip; set threshold + timespan for the window; reset_expire_on_hit for sliding-window semantics. Escalate from rate-limit to identity ban with ban_after_n_exceeded + ban_timespan — the identity is rejected for the ban duration once it crosses the threshold N additional times.
{
"rule_type": "rate_limit",
"name": "delete-burst",
"tools": ["delete_file", "drop_table"],
"match_key": "consumer",
"threshold": 5,
"timespan": 60,
"reset_expire_on_hit": true,
"ban_after_n_exceeded": 2,
"ban_timespan": 3600
}rate_limit blocks volume abuse for a single identity. It does not reason about a sequence of different tool calls that individually look legitimate but cumulatively constitute an attack — the classic agent-trajectory problem. Sequence-level detection is on the roadmap. For custom multi-step heuristics today, write a Function on phase="access" that maintains state in the request context.
Layering MCP with an LLM Proxy#
For full coverage, route your agent traffic through an AIronClaw LLM Proxy for the model-facing leg AND an MCP Proxy for the tool- facing leg. The LLM Proxy applies prompt_guard (regex catalog + LLM judge, including multimodal coverage when the judge is a vision model) on the prompt; the MCP Proxy applies DLP, rate-limit-with-ban and tool_description_inject on tool I/O. Each layer catches a different attack class and the failures are independent.
Cache#
The static_cache rule stores deterministic responses for a tool keyed on its arguments. Use the cache endpoint when you want to forcibly invalidate cached entries — e.g. after a backend data update.
Purge tool cache#
Query
curl -X DELETE "https://app.aironclaw.com/api/mcp/$ID/cache?tool=list_dir" \
-H "Authorization: Bearer $AIFW_PAT"JWKS test#
Validate JWKS document#
Sanity-checks a JWKS JSON document before you save it on a proxy's auth.jwksJson. Pure-validation: no network calls are made (avoids DNS-rebinding on user-supplied IdP URLs). Always returns 200; check the ok field.
Body
curl -X POST https://app.aironclaw.com/api/mcp/jwks/test \
-H "Authorization: Bearer $AIFW_PAT" \
-H "Content-Type: application/json" \
-d '{ "jwksJson": "{\"keys\":[{\"kid\":\"abc\",\"kty\":\"RSA\",...}]}" }'