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

SettingValue
MCP resourcehttps://api.skysay.ai/mcp
Authorization serverhttps://api.skysay.ai
Resource discoveryhttps://api.skysay.ai/.well-known/oauth-protected-resource/mcp
Authorization server discoveryhttps://api.skysay.ai/.well-known/oauth-authorization-server
Authorization endpointhttps://api.skysay.ai/oauth/authorize
Token endpointhttps://api.skysay.ai/oauth/token
Dynamic registration endpointhttps://api.skysay.ai/oauth/register
Revocation endpointhttps://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:

  1. Call get_agent_catalog to discover selectable STT, LLM, and TTS options plus conversation engines. It accepts either agents:read or coverage:read; use metered_only: true when you need only component-metered choices. Pass voice_frontend: "gpt_live" on create_agent or set_agent_voice_stack to select GPT-Live 1; omit it to keep Standard.
  2. Call create_agent, then use list_agents for a bounded newest-first page or get_agent for one current safe agent projection.
  3. Use update_agent for the ordinary mutable fields and set_agent_voice_stack to publish a selected stack. Read the published configuration back with get_agent_voice_stack.
  4. Use preview_voice only 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's body, metadata, error and idempotency_key without sms:read.
  • send_sms (sms:send) and send_agent_template_message (sms:send + agents:read) return the message ID and delivery status; body, metadata, error and idempotency_key come back only with sms:read. This includes a retry that replays an existing idempotency_key.
  • get_simulation_run (agents:read) returns status, verdicts and pagination. Without recordings:read it omits each attempt's transcript, recording_ref and facts, assertion actual values, rubric rationale and linked-evidence note, 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.

](https://skysay.ai/docs/tool-reference)