Platform Integration Guides
Two ways in: connect an MCP client directly to /api/mcp, or drop a single
webhook URL into any automation tool. Either path runs through the same pipeline and
produces the same audit record.
How it works
Stryda is a control plane. Your platform calls Stryda — not the other way around — and Stryda returns an authorized / escalated / denied decision in under 100 ms. Your automation reads the response and either continues or stops.
MCP clients
One hosted MCP server exposes every tool. A user running Claude Desktop + Cursor + a custom agent connects all three to the same URL and gets the same policy enforcement on every call. No per-SaaS MCP to set up, no pasted platform API keys.
Claude Desktop
Add the server to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"stryda": {
"url": "https://mcp.stryda.ai/api/mcp",
"headers": { "Authorization": "Bearer whsec_YOUR_TOKEN" }
}
}
} Generate the bearer token in Settings → MCP Clients. Claude Desktop discovers the namespaced tool catalog on startup; every tool call runs through the validate → policy → approval → adapter → audit pipeline.
Cursor
Same JSON shape; add to .cursor/mcp.json or paste into the Cursor settings UI.
{
"mcpServers": {
"stryda": {
"url": "https://mcp.stryda.ai/api/mcp",
"headers": { "Authorization": "Bearer whsec_YOUR_TOKEN" }
}
}
} Custom client (JSON-RPC over HTTP)
Stryda speaks MCP Streamable HTTP (JSON-RPC 2.0). Any HTTP client can call it directly:
curl -sS -X POST https://mcp.stryda.ai/api/mcp \
-H "Authorization: Bearer whsec_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "comms.send_slack_message",
"arguments": { "channel": "#general", "text": "hello from my agent" }
}
}' Zapier
Zapier ships two products — linear Zaps and autonomous Zapier Agents. Stryda governs both via the webhook path.
Governing Zaps
- Open Platforms in the dashboard, pick Zapier, copy the webhook URL.
- In the Zap, add a Webhooks by Zapier → POST step before the step you want to govern.
- URL: your Stryda webhook URL. Payload Type: JSON.
{
"agent_id": "{{zap_id}}",
"action_type": "email_send",
"action_detail": {
"to": "{{email}}",
"subject": "{{subject}}"
},
"cost_estimate": 0.01,
"source_platform": "zapier"
} - Add a Filter step:
resultexactly matchesauthorized. - Your consequential action lives on the authorized side of the filter — it only runs if Stryda approved.
Governing Zapier Agents
Zapier Agents are autonomous — they reason and pick tools dynamically. Integrate by adding Stryda as a tool the agent calls before consequential actions. The agent sends its intent, Stryda returns a decision, the agent respects it.
Auto-discover Zaps (optional)
Add your Zapier API key during onboarding and Stryda calls api.zapier.com/v2/zaps
to enumerate your Zaps. Without it, add the webhook step to each Zap by hand — the
enforcement is identical.
n8n
n8n is the deepest webhook integration. The HTTP Request node supports full governance checks with pause-and-resume escalation callbacks.
- Copy your n8n webhook URL from Platforms.
- Add an HTTP Request node before any AI action.
- Method: POST. URL: the webhook. Body Content Type: JSON.
{
"agent_id": "={{ $workflow.id }}",
"action_type": "api_call",
"action_detail": {
"workflow_name": "={{ $workflow.name }}",
"node_name": "={{ $node.name }}",
"operation": "={{ $json.operation }}"
},
"cost_estimate": 0.01,
"source_platform": "n8n"
} - Add an IF node after the HTTP Request. Condition:
{{ $json.result }}equalsauthorized. - True branch: the AI action. False branch: notification or stop.
Alternative: Function node
const response = await $http.request({
method: 'POST',
url: 'YOUR_WEBHOOK_URL',
headers: { 'X-Webhook-Secret': 'YOUR_SECRET' },
body: {
agent_id: $workflow.id,
action_type: 'api_call',
action_detail: { node: $node.name },
cost_estimate: 0.01,
source_platform: 'n8n',
},
});
if (response.result !== 'authorized') {
throw new Error(`Blocked by Stryda: ${response.reason}`);
}
return [{ json: response }]; Make
- Copy your Make webhook URL (region-specific) from Platforms.
- Add an HTTP → Make a request module before your AI action module.
- Method: POST. Body type: Raw. Content type: JSON.
{
"agent_id": "{{scenario_id}}",
"action_type": "api_call",
"action_detail": {
"module": "{{module_name}}",
"operation": "{{operation}}",
"target": "{{target_app}}"
},
"cost_estimate": 0.01,
"source_platform": "make"
} - Add a Router after the HTTP module.
- Authorized route: filter
{{3.data.result}}equalsauthorized. Connect to the AI action. - Blocked route: filter where result is not authorized. Connect to notification or stop.
ElevenLabs
Govern voice synthesis and conversational agents. Every TTS generation and agent conversation is logged with character counts and cost.
import requests, os
# Before calling ElevenLabs TTS
gov = requests.post(
os.environ["STRYDA_WEBHOOK_URL"],
json={
"agent_id": "my-voice-agent",
"action_type": "voice_synthesis",
"action_detail": {
"voice_id": "21m00Tcm4TlvDq8ikWAM",
"voice_name": "Rachel",
"text_length": len(text),
"model_id": "eleven_multilingual_v2",
},
"cost_estimate": len(text) * 0.0003, # ~$0.30 per 1K chars
"source_platform": "elevenlabs",
},
).json()
if gov["result"] != "authorized":
raise RuntimeError(f"Blocked: {gov['reason']}")
audio = elevenlabs.generate(text=text, voice="Rachel") Auto-discover with an API key (optional)
With your xi-api-key, Stryda pulls:
- Conversational AI agents via
/v1/convai/agents— name, language, voice config. - Voices via
/v1/voices— voice ID, category, labels. - Usage history via
/v1/history— character counts, voice used, model, timestamps.
Gumloop
- Copy your Gumloop webhook URL from Platforms.
- Add an HTTP Request node before any AI action.
- Method: POST. URL: the webhook. Body (JSON):
{
"agent_id": "{{flow_id}}",
"action_type": "api_call",
"action_detail": {
"flow_name": "{{flow_name}}",
"node": "{{node_name}}",
"operation": "{{operation}}"
},
"cost_estimate": 0.01,
"source_platform": "gumloop"
} - Add a conditional. Check
resultequalsauthorized. - Only proceed with the AI action on the authorized branch.
What gets logged
Every MCP tool call and every webhook call produces the same pair of records — one for the ledger (compliance-grade, hash-chained), one for the operational audit log (what the UI queries). Each carries:
| Field | Meaning |
|---|---|
| Authorization decision | authorized, escalated, or denied — with the specific reason and scope rule that applied. |
| Action detail | What the agent was trying to do: tool name, arguments, target resource. |
| Cost | Estimated cost of the action. Used for budget enforcement and spend reporting. |
| Source platform | Which surface the call came from — an MCP client kind, or one of the webhook platforms. |
| Integrity hash | SHA-256 of the ledger entry, carrying the prior row's hash. The chain makes deletion detectable. |
| Scope snapshot | The authorization rules at the exact moment of evaluation. Immutable evidence. |
Data is retained per workspace policy and viewable in the Data Explorer. Export to CSV, JSON, or a framework-specific evidence bundle anytime.