MCP control plane (OAuth-authenticated)
/mcp
The endpoint an MCP client (Claude Desktop, a claude.ai connector, Cursor) connects to after the user signs in to Elaichi. JSON-RPC 2.0 over the MCP Streamable HTTP transport, stateless, and it exposes the whole organization for one user: the control-plane operation catalog (members, teams, roles, connections, templates, toolboxes…) as `elaichi__*` tools and — when the grant carries `mcp:tools` — the user's own connected third-party tools (every tool of every connection they can use, resolved through their virtual `global:{user_id}` toolbox) under their own `{account}__{tool}` names. **Authentication.** `Authorization: Bearer <MCP OAuth access token>` from `POST /oauth/token`. Session cookies and org API tokens are not accepted here. The organization is pinned on the grant at consent time, so `X-Organization-Id` is neither sent nor honoured. **Discovery.** A 401 carries a `WWW-Authenticate: Bearer resource_metadata="…"` header pointing at `/.well-known/oauth-protected-resource`. That header is how a client that holds no credential finds the authorization server and starts the OAuth flow — a bare 401 is a dead end. A valid token that simply lacks a scope gets `error="insufficient_scope"` with the required `scope`, meaning re-authorize for more rather than re-authenticate. **Authorization.** Two independent gates, both of which must pass: the grant's scopes (what the user let this client do) and the user's RBAC permissions, re-read per request so a revoked role takes effect before the token expires. `tools/list` advertises only what the scopes cover, and `tools/call` re-checks server-side. Revoking the grant kills the token on its very next request. Requires an active Gold or Black subscription; a non-member gets 403, not 401. Rate limited per token.
Request Body
String or number. Omitted for notifications, which answer 202 with no body.
2.0
MCP method: initialize, notifications/initialized, tools/list, tools/call, ping, and the empty resources/list / prompts/list.
Response Body
JSON-RPC error object. Transport-level failures use HTTP status codes instead.
2.0
curl -X POST 'https://api.elaichi.ai/mcp' \
-H 'Authorization: Bearer $ELAICHI_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"your_method","params":{}}'const body = {
"jsonrpc": "2.0",
"method": "your_method",
"params": {}
};
const response = await fetch('https://api.elaichi.ai/mcp', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.ELAICHI_API_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
const data = await response.json();
console.log(data);import os
import requests
url = "https://api.elaichi.ai/mcp"
headers = {
"Authorization": f"Bearer {os.environ['ELAICHI_API_TOKEN']}",
"Content-Type": "application/json",
}
payload = {
"jsonrpc": "2.0",
"method": "your_method",
"params": {}
}
response = requests.post(url, headers=headers, json=payload)
print(response.json())