Skip to navigation

Create an MCP server

View as Markdown

Registers an MCP server with the voice engine and stores it for the workspace. There are two ways to create one.

A custom server needs name and serverUrl. Its approval mode defaults to always_ask and its transport to the voice engine’s default (SSE) unless you send transport. Most hosted MCP servers speak streamable HTTP: with the wrong transport the server registers but never answers a tool call. A custom server reaches no agent until you call POST /api/agents/{agentId}/mcp-servers.

A hosted provider (provider: zapier, alegra or make; see GET /api/mcp-servers/providers) needs only its token in secretToken: name, description, endpoint, transport (STREAMABLE_HTTP) and approval mode (no_approval) come from the catalogue. Make hosts per region, so serverUrl is required for it. Alegra authenticates with HTTP Basic: send usuario:token as secretToken. A provider URL pasted without provider is recognised from its host and held to the same rules; a token found in its query string or path is moved into the secret so the stored URL never carries a credential. A hosted provider server is attached to every provisioned agent right away (agents at their plan cap, or still provisioning, are skipped silently).

Refused with 400 and the field in details.fieldErrors: a transport other than the provider’s, a missing token, a serverUrl on another host than the provider’s, a malformed Alegra secret, or a URL that is not http(s) or targets a private/internal address. A hostname that passes that check but resolves to a private or internal address is also refused with 400, without details and without naming the address. toolOverrides requires approvalMode: fine_grained, accepts at most 50 entries and rejects disabled (these three answer 400 without details). When decisions are sent, the response carries toolOverridesSync; if any failed to apply the status is 207 instead of 201, the server is still created, and toolOverrides shows only what was applied.

Side effects. Creates the server in the voice engine and pushes per-tool approval decisions; with a hosted provider, also updates every agent’s MCP server list in the voice engine. The token and custom headers are stored encrypted. Writes an mcp.manage audit entry.

Idempotency. Not idempotent. A retry registers a second, independent server (and, for a hosted provider, attaches that copy to every agent too, using another slot of each agent’s cap). After a timeout, check GET /api/mcp-servers before retrying.

Webhook events. audit.log_recorded for the audit entry, if you subscribe to it. See Webhooks.

Access

  • Required scope: write. Any workspace role.
  • Rate limit: General API — 120 (Starter), 200 (Growth), 300 (Business) or 600 (Enterprise) requests/min per workspace, checked by two counters of the same size. See Rate limits.
  • Plan: Requires an active subscription (active, trialing or past_due); without one the request is refused with 403 BILLING_ERROR (metadata.kind: subscription_required). Automatic attachment of a hosted provider respects the MCP-servers-per-agent cap (Starter 1, Growth 3, Business 10).

Authentication

AuthorizationBearer

Workspace API key: jl_ followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (Settings → API Keys) and sent as Authorization: Bearer jl_.... The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys.

ScopeGET / HEADPOST / PUT / PATCH / DELETEAdmin-only routes
readYesNoNo
writeYesYesNo
fullYesYesYes

Operations restricted to admins or owners reject keys without the full scope with 403, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See Authentication.

Request

Unknown keys are ignored. Empty or whitespace-only strings are treated as absent.

providerenumOptional

Hosted provider preset: zapier, alegra or make. When set, name and description are optional and default to the provider’s.

Allowed values:
namestringOptional1-200 characters

Display name, trimmed. Required without provider.

descriptionstringOptional<=2000 characters

Sent to the voice engine and read by the agent to decide when to use the server’s tools. Defaults to the provider’s agent-facing description when provider is set.

serverUrlstringOptionalformat: "uri"<=2000 characters

The server’s MCP endpoint (http or https). Required without provider, and for make. Must not target localhost or private/internal addresses; with a provider it must be on the provider’s host.

secretTokenstringOptional<=2000 characters

Credential, stored encrypted and never returned. Sent to the server as Authorization: Bearer <token>, or as HTTP Basic for alegra (send usuario:token). Required with a provider unless customHeaders already carries Authorization.

customHeadersmap from strings to stringsOptionalDefaults to {}

Extra HTTP headers sent to the server on every request (at most 20; names up to 200 characters, values up to 2000). Stored encrypted and never returned.

approvalModeenumOptional

Approval policy for the server’s tools: always_ask, fine_grained or no_approval. Defaults to always_ask for a custom server and to no_approval with a provider.

Allowed values:
transportenumOptional

SSE or STREAMABLE_HTTP. Fixed to STREAMABLE_HTTP for providers (a different value is refused). Omitted on a custom server, the voice engine’s default (SSE) applies and transport is stored as null.

Allowed values:
toolOverridesmap from strings to enumsOptionalDefaults to {}

Per-tool approval keyed by the tool name the server advertises: auto_approved or requires_approval. Only with approvalMode: fine_grained; at most 50 entries; disabled is rejected with 400 (remove the assignment instead). A tool the server does not advertise is reported in toolOverridesSync.failures.

Allowed values:

Response

Created. toolOverridesSync is present only when per-tool decisions were sent.

dataobject

A single MCP server as returned by the create, retrieve and update endpoints: the summary fields plus deleted_at and the applied per-tool decisions. secret_token and custom_headers are never returned.

toolOverridesSyncobjectOptional

What happened when per-tool decisions were pushed to the voice engine. Present only when decisions were sent, or re-applied after a re-registration or cleanup of legacy values.

Errors

400
Bad Request Error
401
Unauthorized Error
403
Forbidden Error
429
Too Many Requests Error
502
Bad Gateway Error