MCPPlatform
Connect your REST API and get a hosted MCP server with generated tools, policy controls, approvals, credential management, and complete tool-call auditing.
Documentation
Developer documentation
Everything to go from an OpenAPI spec to a live, governed MCP server — and to call it from an agent.
Quickstart
The fastest way to see a governed MCP server working is to connect Claude to one that's already live — no signup, no API key. This uses Cat Facts, one of 5 public example servers running on the platform, and takes under 5 minutes.
- In Claude, open Settings → Connectors → Add custom connector.
- Paste in the MCP endpoint URL (name it whatever you like, e.g. "Cat Facts"): https://mcpplatform.dev/mcp/srv\_c7dcf1cd45
- Save the connector. Claude calls initialize and tools/list behind the scenes and discovers one tool, get_cat_fact.
- Ask Claude something that makes it reach for the tool: Use the Cat Facts connector to tell me a random cat fact.
Claude issues a tools/call and gets real content back over the same JSON-RPC connection:
POST /mcp/srv_c7dcf1cd45 { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "get_cat_fact", "arguments": {} } } → 200 { "result": { "content": [{ "type": "text", "text": "{\"fact\": \"Cats only sweat through their paws...\", \"length\": 65}" }], "isError": false } }
Claude reads that JSON and answers you in plain English with the fact — that's the whole loop: connect, discover tools, call, respond.
Zero setup: srv_c7dcf1cd45 is one of 5 public, no-auth example servers live on the platform right now — safe to connect to directly, nothing to configure or sign up for.
Prefer to see the raw request/response before opening Claude? Try the live sandbox — it fires the same tools/list/tools/call requests straight from your browser, no signup required.
Ready to publish your own governed MCP server from an OpenAPI spec instead of a demo one? Sign up to create a tenant, then pick up at Import a contract below.
Core concepts
Tenant
An isolated customer workspace. All servers, contracts, tools, and audit belong to exactly one tenant, enforced at the database layer.
Contract
An OpenAPI spec or REST base URL you register. Each operation is mapped to a tool.
MCP server
A published, versioned bundle of tools, resources, and prompts that an agent installs by URL.
Policy decision point
The runtime component that decides allow, allow_with_confirmation, allow_with_approval, or denied for every call.
Import a contract
In the console go to Build → Contracts → Import. Provide a spec URL or paste JSON/YAML, choose an environment, and we validate it. The validation report flags missing schemas and risky defaults before publish.
Configure policy
For each tool set its risk class and required scopes. The mapping to decisions:
- Read-only within scope → allow
- Financial / side-effecting → allow_with_confirmation
- Destructive → allow_with_approval (held for a human)
- Missing scope or over rate limit → denied
Connect credentials
Under Secure → Credentials, connect an OAuth provider or store a secret. The runtime brokers short-lived downstream tokens per call — the agent never sees the raw key.
API reference
GET /v1/bootstrap
Returns the full tenant-scoped dataset the console renders — tenants, servers, tools, contracts, audit, and reference docs. Tenant-scoped via RLS.
GET /mcp/:serverId/tools/list
Lists a server's tools (name, description, method, path, risk, scopes). Discovery only — no side effects, not billed.
POST /mcp/:serverId/tools/call
Invokes a tool. Body: { toolName, args, ctx? }. Returns the policy decision, the downstream response, and the audit row written.
POST /mcp/mcp_msg/tools/call { "toolName": "delete_message", "args": { "sid": "SM1" } } → 200 { "result": { "decision": "allow_with_approval",... } }
Runtime & decisions
Each call runs a fixed pipeline: resolve tenant (RLS scope) → validate scope → rate limit → policy decision → broker credentials → invoke downstream → append audit. A denial short-circuits before any downstream call is made.
Security & RLS
The application connects to Postgres as a non-privileged role subject to Row-Level Security. Every tenant-owned table carries a tenant_id and a policy:
CREATE POLICY tenant_isolation ON tool USING (tenant_id = current_setting('app.tenant_id', true)) WITH CHECK (tenant_id = current_setting('app.tenant_id', true));
Because RLS is enforced by the database, a query that forgets its WHERE clause still cannot read or write another tenant's rows. Migrations run as a separate BYPASSRLS owner role.
Verify it yourself: request /v1/bootstrap with a different X-Tenant-Id and you'll see zero rows from other tenants.
Self-host on GCP
The platform runs on Cloud SQL for PostgreSQL (multitenant store), Cloud Run (control + data plane), a global HTTPS load balancer with Cloud Armor, and Cloud KMS for the vault. See the full runbook in doc/gcp-deployment-runbook.md.