MCP API
Complete API reference for the MCP Gateway — servers, tools, policies, approvals, proxy.
All MCP endpoints require API-key authentication (Authorization: Bearer {project_api_key}) and additionally enforce a role floor. Editor: register, scan, create policy. Admin: activate / pause / reject / delete a server, emergency-stop, set a tool verdict, delete a policy.
Servers
List servers
GET /api/v1/mcp/serversReturns all registered MCP servers for the project with tool count.
Register a server (Editor)
POST /api/v1/mcp/servers{
"name": "GitHub MCP Server",
"server_url": "https://api.githubcopilot.com/mcp/",
"connector_type": "custom",
"description": "Optional description",
"is_proxied": true
}connector_type is an optional free-form label (defaults to custom). New servers start in PENDING_APPROVAL; registering does not trigger a scan.
Update a server (Editor)
PATCH /api/v1/mcp/servers/{id}Fields: name, description, auth_method, auth_config. This route is metadata-only — it cannot change status. Status transitions go exclusively through the audited lifecycle actions below.
Delete a server (Admin)
DELETE /api/v1/mcp/servers/{id}Cascades to this server's tools and policies. Audited.
Lifecycle actions (Admin, audited)
Status changes only through these dedicated, admin-audited routes:
POST /api/v1/mcp/servers/{id}/activate # PENDING_APPROVAL → ACTIVE (approve) or BLOCKED → ACTIVE (resume)
POST /api/v1/mcp/servers/{id}/pause # ACTIVE → BLOCKED
POST /api/v1/mcp/servers/{id}/reject # PENDING_APPROVAL → removedActivation also freezes the per-tool approval anchor (name + description + input schema) for every tool of the server. Each action writes an entry to the immutable admin-audit trail (mapped to OCSF for SIEM export).
Scan tools (Editor)
POST /api/v1/mcp/servers/{id}/scanConnects to the MCP server, discovers tools, classifies each tool's risk, and seeds a starting verdict per tool (LOW → ALLOW, MEDIUM → LOG_ONLY, HIGH/CRITICAL → REQUIRE_APPROVAL; no DENY seeded). The scan does not activate the server.
The response mirrors the outcome honestly:
// reached and scanned
{ "scanned": true, "tool_count": 12, "policies_bound": 2, "policies_seeded": 12, "server_status": "ACTIVE" }
// target could not be scanned (still HTTP 200 — not a Palveron 5xx)
{ "scanned": false, "reason": "unreachable", "detail": "refused", "target": "https://…", "server_status": "ERROR" }reason ∈ unreachable · bad_status · rpc_error · invalid_response. A forbidden (private/internal) URL is rejected with 400 (validation), not a scan result.
List server tools
GET /api/v1/mcp/servers/{id}/toolsEach tool carries risk_level, category, description_hash, the effective policy_action and is_auto_generated (auto-seeded vs. set by you), plus the approval anchor: approved_hash, approved_at, and the derived matches_approved (true = unchanged since approval, false = drifted, null = never approved).
Set a tool verdict (Admin)
POST /api/v1/mcp/servers/{id}/tools/{tool_id}/verdict{ "action": "LOG_ONLY", "reason": "Reviewed — safe to log only" }Sets (or loosens) the tool's single server-wide verdict slot, collapsing it to the new action so loosening actually takes effect. Audited. There is no update endpoint for policies — use this, or delete + create.
Registry (catalog)
GET /api/v1/mcp/registry?q={search}&frontable=true&cursor={registry_name}&limit=50Returns Palveron's mirror of the official MCP registry — the catalog behind the one-click connect flow. Each item: registry_name, version, description, remote_url, frontable (has a usable HTTP remote), website_url, registry_status, and the trust signals registry_updated_at, published_at, repository_url. The response carries items, an optional keyset next_cursor (over registry_name), and total.
Proxy
Forward a tool call
POST /api/v1/mcp/proxy/{server_id}Accepts any JSON-RPC 2.0 request. Optionally send an X-Agent-Id header with a registered agent id (plain CUID) so calls are attributed to that agent — an unknown id is treated as anonymous. For the tools/call method, the following checks run in order:
- Server active — any status other than
ACTIVEis refused (PENDING_APPROVAL→-32002, otherwise-32001) - Upstream auth attach — if the server's auth cannot be attached, the call is refused fail-closed (
-32008) - Approval anchor / poisoning — for approved tools, a surface that drifted from the approved fingerprint is blocked (
-32002,APPROVED_FINGERPRINT_MISMATCH); never-approved tools fall back to the legacy poisoning check (-32002) - Policy evaluation —
DENY→-32003,REQUIRE_APPROVAL→-32004 - Forward to the MCP server, then create a trace with
traceType: MCP_TOOL_CALL
Non-tool-call methods (initialize, tools/list) pass through without policy evaluation.
Error codes:
| Code | Meaning |
|---|---|
-32001 | Server not active (blocked / non-ACTIVE) |
-32002 | Call blocked — server awaiting approval (PENDING_APPROVAL), a poisoning-suspect tool, or a tool that drifted from the approved state (APPROVED_FINGERPRINT_MISMATCH) |
-32003 | Tool denied by policy |
-32004 | Tool requires approval (queued; carries the request id) |
-32005 | Limit exceeded — returned when too many approvals are already pending for the agent (resolve or wait before requesting more) |
-32006 | Invalid response / protocol error from the MCP server |
-32007 | MCP server unreachable |
-32008 | Server authentication could not be attached (fail-closed; HTTP 403) |
Policies
List policies
GET /api/v1/mcp/policiesCreate a policy (Editor)
POST /api/v1/mcp/policies{
"action": "DENY",
"mcp_tool_id": "clxyz...",
"agent_id": "ckagent...",
"reason": "Shell execution not allowed"
}All fields except action are optional (mcp_tool_id, agent_id, reason, conditions). Valid actions: ALLOW, LOG_ONLY, REQUIRE_APPROVAL, DENY — any other value returns 400 listing the allowed set. There is no update endpoint; to change a tool's verdict use the set-verdict route above.
Delete a policy (Admin)
DELETE /api/v1/mcp/policies/{id}Approvals
List pending
GET /api/v1/mcp/approvalsReturns only PENDING approvals that have not yet expired.
Decide
POST /api/v1/mcp/approvals/{id}/decide{ "approved": true, "comment": "Reviewed — one-time access granted" }An approval is one-shot and bound to the exact arguments it was requested for: the grant stores a canonical hash of the tool arguments, and only a call with those same arguments redeems it — once, then the grant is consumed. A call with different arguments does not match the grant and opens a new approval request.
Emergency Stop (Admin)
POST /api/v1/mcp/emergency-stop{ "scope": "all", "reason": "Security incident" }Scopes: all (block all servers), server (block a specific server, target_id required), agent (lock all tools for an agent, target_id required). Expires all pending approvals. Admin-gated and recorded as a Flare-attested audit trace.