Skysay
Connect AI assistants to your Skysay workspace to inspect and manage voice agents, phone numbers, calls, SMS and campaigns through OAuth or scoped API keys.
Hosted MCP Server
npx add-mcp 'https://api.skysay.ai/mcp'Installs into Claude Code, Codex, Cursor and more
Documentation
MCP overview
Connect an assistant with OAuth or an API key, inspect tool schemas, and control workspace permissions.
Skysay speaks MCP (Model Context Protocol). An MCP-capable client points at the hosted endpoint, connects with OAuth or a scoped API key, and the Skysay tools appear in tools/list — ready to call. This is the universal path; the OpenClaw connector and the REST API are convenience wrappers around the same tools.
The endpoint
POST https://api.skysay.ai/mcp
Authorization: Bearer sky_your_scoped_key
Standard JSON-RPC: tools/list to discover, tools/call to invoke.
Connect with OAuth
For an assistant that supports remote MCP authorization, enter https://api.skysay.ai/mcp as the server URL and choose OAuth. Sign into Skysay, check the client and workspace shown on the consent screen, and approve the permissions you want to grant. Adding a custom connection does not require Skysay to be listed in that assistant's public directory.
The initial permissions read workspace, agent, call metadata, coverage, number and onboarding information, and evaluate policy. Reading conversation content or performing supported writes requires additional consent. Check each consent screen: some permissions allow actions that contact people or spend your Skysay balance. A connection cannot access a different workspace by passing its organization ID.
Manage and revoke connections from Connected apps on the API keys page in the Skysay workspace. Revocation invalidates the connection's tokens. Existing API keys continue to work independently and must be revoked separately.
Setting, changing or resetting your Skysay password also revokes your OAuth connections. Sign in again and reconnect the assistant with fresh consent. See workspace sign-in and recovery.
OAuth client configuration
| Setting | Value |
|---|---|
| MCP resource | https://api.skysay.ai/mcp |
| Authorization server | https://api.skysay.ai |
| Resource discovery | https://api.skysay.ai/.well-known/oauth-protected-resource/mcp |
| Authorization server discovery | https://api.skysay.ai/.well-known/oauth-authorization-server |
| Authorization endpoint | https://api.skysay.ai/oauth/authorize |
| Token endpoint | https://api.skysay.ai/oauth/token |
| Dynamic registration endpoint | https://api.skysay.ai/oauth/register |
| Revocation endpoint | https://api.skysay.ai/oauth/revoke |
Use the authorization-code flow with PKCE S256 and public-client token authentication (none); no client secret is required. Both Client ID Metadata Documents (CIMD) and dynamic client registration (DCR) are supported. CIMD documents may advertise supported authentication methods as a list containing none, even when their legacy preference is a different method. Redirect URIs must match the client's metadata or registration. Authorization responses include the issuer (iss).
Access tokens expire after one hour. Refresh tokens rotate, expire after 30 days without renewal, and have a maximum family lifetime of 90 days. Reconnect when the client asks you to sign in again. An unauthenticated MCP request returns a 401 discovery challenge; a supported tool that needs more consent returns a 403 scope challenge. Only the scopes advertised by the authorization server can be granted through OAuth; the API-key catalogue is broader. Skysay does not currently provide OpenID Connect UserInfo or the openid and email scopes for ChatGPT Enterprise workspace-domain restrictions.
Read-only connector for Claude
Use https://api.skysay.ai/mcp/read-only for a connection that can inspect workspace data without generating audio or performing writes. It exposes exactly five tools:
account_overview: inspect your workspace overview.list_agents: list your agents.get_agent: read one agent's configuration.list_numbers: list your phone numbers.list_calls: inspect call metadata, without recordings or transcripts.
All other tool calls are refused at this endpoint, even with a broad API key. OAuth consent accepts only account:read, agents:read, calls:read, and numbers:read. Its discovery document is https://api.skysay.ai/.well-known/oauth-protected-resource/mcp/read-only, and its OAuth resource is https://api.skysay.ai/mcp/read-only. Tokens for this resource cannot be used at /mcp, and tokens for /mcp cannot be used at the read-only endpoint. Both connections use the same sign-in, PKCE, consent, refresh and revocation flow described above.
Try “Show my Skysay workspace overview,” “List my Skysay agents,” or “Show my Skysay phone numbers.” A new workspace may return empty lists; the connector will not create sample data or provision numbers to fill them.
Connect from the workspace
You do not have to assemble the configuration by hand. The API keys page in the workspace carries a Connect an AI assistant card: create a key with only the scopes the assistant should have, then copy the ready-made server entry it shows and paste it into the assistant's MCP settings, replacing the placeholder with that key.
{
"url": "https://api.skysay.ai/mcp",
"headers": {
"Authorization": "Bearer sky_YOUR_KEY"
}
}
Use this canonical API URL for every new connection. The assistant can do exactly what the key allows and nothing more, and revoking the key disconnects it.
Results, errors and tool metadata
Tool calls return a text content block containing JSON and the same data in result.structuredContent. List results use { "items": [...] } in structured content. A refused tool returns result.isError: true and structuredContent.error with type and message. Unexpected failures use internal_error and a request_id to quote to support. An unknown tool, or a params, name or arguments that is not the right shape, remains a JSON-RPC error (-32602); anything that goes wrong once the tool runs is a refused tool result.
Every tool has a title and read-only or destructive hints. Required scopes are in _meta["ai.skysay/required_scopes"]; alternatives are in _meta["ai.skysay/alternative_required_scopes"]. The catalogue lists all tools, even when your credential lacks their scopes. A call whose credential lacks a tool's scopes fails closed with a refused tool result naming the missing scopes.
organization_id is optional on all tools and defaults to your credential's workspace. A different workspace is refused. Streamable HTTP negotiates 2025-11-25, 2025-06-18 or 2025-03-26. Notifications receive 202 with no body; ping is supported; GET and HEAD return 405, with no SSE stream.
Migration for custom MCP clients
Read result.structuredContent instead of result.content[0].json, inspect result.isError and structuredContent.error.type instead of error.type, and read scope metadata from _meta instead of annotations.required_scopes. Standard MCP clients already understand these result types.
Prefix scopes
Some scopes are grouped by prefix — for example sms:* covers both sms:read and sms:send. Grant the specific leaf scope for least privilege, or the prefix when an agent legitimately needs the whole group.
Capabilities that a deployment can switch off
A few tools belong to capabilities an operator enables per deployment — the Simulations Lab is one. tools/list publishes them regardless, because it is a catalog of what Skysay can do rather than an inventory of what your instance has switched on. Calling one where the capability is off returns the same not-found the equivalent REST route returns.
When a tool call is refused
A refused call is a tool result with isError: true, so the assistant reads it and can correct itself. structuredContent.error names the refusal's type and message. When the same request over REST would answer with a structured body, that body is under error.body: for example, the issues of a refused configuration, or the current revision after a conflict. A missing MCP scopes or workspace refusal carries no body.
Configure an agent from MCP
An organization-scoped key with agents:read and agents:write can complete the normal customer configuration loop without switching to REST:
- Call
get_agent_catalogto discover selectable STT, LLM, and TTS options plus conversation engines. It accepts eitheragents:readorcoverage:read; usemetered_only: truewhen you need only component-metered choices. Passvoice_frontend: "gpt_live"oncreate_agentorset_agent_voice_stackto select GPT-Live 1; omit it to keep Standard. - Call
create_agent, then uselist_agentsfor a bounded newest-first page orget_agentfor one current safe agent projection. - Use
update_agentfor the ordinary mutable fields andset_agent_voice_stackto publish a selected stack. Read the published configuration back withget_agent_voice_stack. - Use
preview_voiceonly as an explicit Listen action. It can contact a provider or validate a BYOK credential, is rate-limited per workspace, and may write safe preview-rate or voice-availability state. It is not a read-only or free preview.
list_agents is deliberately a bounded MCP collection: it returns the same safe agent items as REST inside { agents, pagination }, with up to 50 agents per page (the default and maximum). Follow pagination.next_cursor only while pagination.has_more is true. The legacy REST collection remains a separate compatibility response.
list_audio_environments is the same catalogue as GET /v1/audio-environments, with the same account:read scope. It is a read-only, provider-independent discovery call: it returns Off plus the currently packaged versioned presets and never changes an agent or starts a preview. Use its exact preset ID and asset version when configuring output ambience or a Simulation Lab caller condition; do not maintain a client-side copy of the catalogue.
The key's organization is authoritative. You may omit the redundant organization_id input from create, list, and preview calls; if supplied, it must match the key's workspace. Agent IDs, optional project filters, saved voice pins, preview rate limits, credential ownership, and provider/BYOK validation stay in the same services as the REST workflow.
Browser sessions stay a browser workflow
For local stdio MCP, set both SKYSAY_MCP_SCOPES and SKYSAY_MCP_ORGANIZATION_ID before calling any tool. An absent organization fails closed; tools/list remains schema discovery only.
Superseded: /docs/agents
Content fields
Conversation content needs its content scope wherever it appears, over MCP and REST. Tools that combine content with other data stay callable at their base scope and omit the content fields:
account_overview(account:read) omits each SMS message'sbody,metadata,errorandidempotency_keywithoutsms:read.send_sms(sms:send) andsend_agent_template_message(sms:send+agents:read) return the message ID and delivery status;body,metadata,errorandidempotency_keycome back only withsms:read. This includes a retry that replays an existingidempotency_key.get_simulation_run(agents:read) returns status, verdicts and pagination. Withoutrecordings:readit omits each attempt'stranscript,recording_refandfacts, assertionactualvalues, rubricrationaleand linked-evidencenote, because each can quote the conversation.
Content-bearing webhook subscriptions
Creating or changing a webhook subscription for sms.received requires sms:read. Subscribing to call.extraction.ready requires recordings:read, because extracted results can quote the conversation. Changing any existing webhook destination requires both sms:read and recordings:read: queued deliveries and concurrent subscription changes can contain either kind of content. Removing a subscription does not make its queued content safe to redirect. Agent names and lifecycle-only subscriptions remain editable with agents:write. Over MCP, a call lacking one of these content scopes receives a refused tool result naming the missing scope, before anything is written.
[
Post-call results
Verify signed lifecycle and artifact events, then optionally read a bounded advisory summary from a completed call.
](https://skysay.ai/docs/post-call-results)[
Tool reference
Every Skysay MCP tool with its required scope, generated from the server's TOOL_SCOPES.