Ralti exposes an MCP transport at /api/mcp. It is separate from the ordinary app session API. A connection is personal, bound to one actor and workspace, and limited by selected scopes, expiry, revocation, and the user’s current permissions. The server uses the MCP SDK for stateless and legacy-stateless protocol handling.
Create a connection through an authenticated app session#
{
"name": "Example analysis client",
"scopes": [
"records:read",
"drafts:propose"
],
"days": 7
}Send that object to POST /api/mcp/connections. A registered account is required. Expiration choices are 7, 30, or 90 days; the name is 1–80 characters. drafts:propose requires both records:read and editing permission. The server returns HTTP 201 with connection metadata and the full token once. Listing connections later returns only metadata and a prefix. Treat the token as a secret.
| Scope | Exposed tool names |
|---|---|
| records:read | search_records, read_record, query_records, discover_sheets, describe_sheet, list_records, related_records |
| email:read | list_mailboxes, search_emails, read_email_thread, read_email_threads, read_email_message |
| drafts:propose | validate_changes, propose_changes |
The available tools are filtered by the actual connection scopes. Email retrieval is restricted to the actor’s owned permitted mailboxes. Tool calls recheck the active connection and workspace access before and after work. Discover sheet schemas and follow pagination/truncation indicators before claiming that a search covers an entire workspace.
Use a protocol-aware client#
POST /api/mcp HTTP/1.1
Host: app.your-domain.example
Authorization: Bearer <token-returned-at-connection-creation>
Content-Type: application/json
<JSON-RPC message produced by your MCP client>Configure the application’s actual HTTPS endpoint and the issued connection token in an MCP-capable client, and let it negotiate protocol headers and messages. Do not use a Clerk JWT, local session token, or server secret as the MCP token. The route explicitly exports POST, GET, and DELETE, but the SDK determines whether a particular method/message is valid. An exported GET or DELETE is not a separate REST operation for reading or deleting your workspace.
The transport accepts at most 1 MiB per request. Host validation rejects unapproved names, browser Origin must match the configured app origin when supplied, and non-local external origins require HTTPS. These checks occur before token lookup. No remote wildcard-origin mode is provided.
Proposals stay behind review#
validate_changes checks a proposal against current schema, references, and permissions without saving or applying it. propose_changes validates and saves a durable draft with an idempotencyKey and the current revision. The result includes a review destination for the user. Validation does not reserve a revision; another edit can make later proposal submission stale.
There is no external tool for applying a draft, sending mail, running a workflow, or executing arbitrary database statements. The user reviews the saved proposal in Ralti and applies through the same checked action boundary as ordinary app edits. Granting drafts:propose therefore does not authorize unattended workspace mutation.
Handle errors and revoke access#
MCP responses follow the SDK transport rather than the app’s conventional JSON envelope. Authentication/service errors can return a JSON-RPC error with code -32001; a 401 response includes WWW-Authenticate. Early host/origin failures may have a simpler error shape. A tool can return isError:true inside a valid protocol response, so inspect tool results as well as HTTP status.
Use GET /api/mcp/connections to review your own workspace connections and DELETE /api/mcp/connections/{id} to revoke one. There can be at most 25 active connections per actor. Revocation and membership loss prevent later authorized tool work; they do not erase information already returned to an external client. Choose narrow scopes and a short useful lifetime when sharing a workspace with another tool.