Skip to main content
mcp-gate is a policy-gating proxy for MCP (Model Context Protocol) servers. Your AI client connects to mcp-gate instead of the upstream MCP server. Sentrail evaluates every tools/call and either forwards it, blocks it, or defers it for approval.
Sentrail supports remote MCP servers over HTTP(S) only. Use the Sentrail /mcp-gate/sse endpoint from clients such as Claude Code or Cursor. stdio-based MCP servers are not supported.

How it works

Connecting your MCP server

Go to Tools → MCP → Connect and enter:
FieldDescription
Server URLHTTP or SSE endpoint of your upstream MCP server
Auth typebearer (default) or token
Access tokenBearer token forwarded to the upstream server (optional)
These values are stored in tool_connections for the mcp tool:
  • mcp_server_url — upstream server URL
  • mcp_auth_typebearer or token
  • mcp_transportsse or http
  • config.access_token — forwarded as Authorization: Bearer <token> or Authorization: token <token>

Endpoint

POST https://<project-ref>.supabase.co/functions/v1/mcp-gate/sse
Authorization: Bearer agk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
All three MCP methods (initialize, tools/list, tools/call) are sent to the same endpoint.

initialize

// Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize"
}

// Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": { "tools": { "listChanged": false } },
    "serverInfo": { "name": "sentrail-mcp-gate", "version": "1.0.0" }
  }
}

tools/list

mcp-gate forwards tools/list to the upstream server and caches the result for 60 seconds.
// Request
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list"
}

// Response (forwarded from upstream)
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "create_issue",
        "description": "Create a GitHub issue",
        "inputSchema": {
          "type": "object",
          "properties": {
            "title": { "type": "string" },
            "body": { "type": "string" }
          },
          "required": ["title"]
        }
      }
    ]
  }
}

tools/call

mcp-gate evaluates the call against your policies before forwarding.
// Request
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "create_issue",
    "arguments": {
      "title": "Fix login bug",
      "body": "The logout button is broken on mobile."
    }
  }
}
Allowed response (forwarded from upstream with Sentrail metadata):
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [{ "type": "text", "text": "Issue created: #42" }],
    "_meta": {
      "sentrail": {
        "status": "allowed",
        "auditLogId": "...",
        "correlationId": "...",
        "matchedPolicyId": "..."
      }
    }
  }
}
Blocked response:
{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32001,
    "message": "Blocked by Sentrail policy",
    "data": {
      "reason": "Policy 'Block delete operations' matched",
      "auditLogId": "...",
      "correlationId": "...",
      "matchedPolicyId": "..."
    }
  }
}
Require approval response:
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "⏳ Sentrail requires approval before running `create_pr`. Poll /mcp-gate/status/APPROVAL_ID for the decision."
      }
    ],
    "isError": false,
    "_meta": {
      "sentrail": {
        "status": "require_approval",
        "approvalRequestId": "550e8400-e29b-41d4-a716-446655440000",
        "auditLogId": "...",
        "correlationId": "..."
      }
    }
  }
}

Polling approval status

GET https://<project-ref>.supabase.co/functions/v1/mcp-gate/status/:approvalId
Authorization: Bearer agk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{
  "ok": true,
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "executed",
  "reviewedAt": "2026-04-20T10:35:00.000Z",
  "reviewedBy": "user-uuid",
  "reviewReason": "Looks good",
  "executionResult": { "content": [{ "type": "text", "text": "PR created: #15" }] },
  "expiresAt": "2026-04-21T10:00:00.000Z"
}

Risk level inference for MCP tools

Risk level is inferred from the tool name:
Tool name patternRisk level
Starts with get, list, readlow
Contains delete, destroy, drop, removehigh
Contains create, update, write, post, send, mergemedium
Everything elsemedium
You can override the inferred risk level by passing _risk in the arguments:
{ "arguments": { "_risk": "critical", "target": "..." } }

Claude Code configuration

{
  "mcpServers": {
    "sentrail": {
      "url": "https://<project-ref>.supabase.co/functions/v1/mcp-gate/sse",
      "headers": {
        "Authorization": "Bearer agk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "X-Agent-Id": "claude-code"
      },
      "transport": "sse"
    }
  }
}

Cursor configuration

{
  "mcpServers": {
    "sentrail": {
      "url": "https://<project-ref>.supabase.co/functions/v1/mcp-gate/sse",
      "headers": {
        "Authorization": "Bearer agk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "X-Agent-Id": "cursor"
      },
      "transport": "sse"
    }
  }
}