MCP (Model Context Protocol) is an integration provider layer that sits beneath the SYRIS Tool Runtime. MCP servers appear in the tool registry as normal RegisteredTool entries; the full SYRIS safety, gating, idempotency, and audit stack applies before any MCP tool invocation.
For the decision to adopt this architecture, see adr/0002-mcp-integration.
[Tool Runtime / ToolRegistry]
│
└── [MCPProvider] ─── registers MCP tools as RegisteredTool entries
│
└── [MCPConnectionManager] ─── per-server persistent connection
│
└── MCP server (external, JSON-RPC)The gate matrix, scope checks, idempotency, and audit emit in tools/executor.py run before any call reaches the MCP layer. MCP does not bypass SYRIS safety controls.
Located in integrations/mcp/connection.py.
AuditEvent on all connection lifecycle events.Located in integrations/mcp/provider.py.
ToolRegistry.TrustPolicy to assign risk levels, scopes, and idempotency contracts to each tool.Located in integrations/mcp/adapter.py.
BaseTool for a single MCP tool.execute() calls MCPConnectionManager.call(tool_name, args) and translates the response to ToolResult.unknown in idempotency_outcomes rather than assuming success or failure.Located in integrations/mcp/trust.py. Per-server and per-tool policy.
TrustPolicy
risk_override: RiskLevel | None — Overrides MCP annotations (untrusted)
scopes_mapping: dict[str, list[str]] — Maps MCP tool name → SYRIS scopes
idempotency_contract: IdempotencyContract — none | provider_managed | syris_managed
supports_preview: boolMCP tool annotations are treated as untrusted by default. risk_override in TrustPolicy is the authoritative source for risk level; MCP metadata is ignored unless the server is explicitly trusted via policy.
All MCP tools are classified as high risk until explicitly allowlisted in TrustPolicy. This means:
CONFIRM before execution in A2 and below.TrustPolicy entries to lower risk levels for trusted tools.TrustPolicy; MCP server-provided annotations are ignored.| Event | Audit type | Notes |
|---|---|---|
| Connection established | mcp.connected | Includes tool count from initial discovery |
| Tools list synced | mcp.tools_synced | Includes added/removed tool diff |
| Connection lost | mcp.disconnected | Triggers reconnect with backoff |
| Tool call mid-disconnect | tool_call.unknown | Outcome stored as unknown; reconciled on reconnect |
| Consecutive errors ≥ threshold | Alarm raised | Integration health degrades in dashboard |
When an MCP server disconnects, tool.health.status transitions to unavailable. The dashboard reflects this within 30 seconds via the GET /integrations endpoint.