Kronos AI

Kronos AI MCP

Plug Kronos AI into Claude Desktop, ChatGPT, n8n, or any MCP-compatible client. Send messages, look up conversations, and fetch your WhatsApp templates directly from inside the client's chat or workflow — no glue code, no custom integrations.

Endpoint: https://mcp.kronos.com.mx/v1Transport: streamable-httpVersion: v1 (beta)

What is MCP?

The Model Context Protocol (MCP) is an open standard for connecting AI clients to tool servers. A client speaks MCP, a server exposes tools, and the client's underlying model decides when to call them. It is what lets Claude Desktop's chat send a real message, or an n8n workflow call into your CRM without you writing the glue yourself.

Kronos AI MCP is the server side of that protocol for the Kronos AI inbox. Once you plug it into a client like Claude Desktop, ChatGPT, or n8n, the model can ask Kronos AI to send a WhatsApp message, look up a sent message, list your conversations, or pick a template — using the exact same account credentials that power the Kronos AI dashboard. No glue code, no scopes you can't see.

Setup in Claude Desktop

  1. Open Claude Desktop → Settings → Developer → Edit Config. This opens claude_desktop_config.json.
  2. Add Kronos AI under mcpServers (snippet below). Replace kronos_sk_live_xxx with a real key created from Settings → API Keys.
  3. Restart Claude Desktop. The Kronos AI tools appear in the chat composer under the tools menu.

Config snippet

{
  "mcpServers": {
    "kronos": {
      "url": "https://mcp.kronos.com.mx/v1",
      "headers": { "Authorization": "Bearer kronos_sk_live_xxx" }
    }
  }
}

Other clients

Any client that speaks MCP's streamable-HTTP transport can use Kronos AI with the same URL + Bearer header. ChatGPT (with custom connectors) and n8n are common examples — point them at https://mcp.kronos.com.mx/v1 and include the same Authorization: Bearer … header.

Discovery manifest

For tooling that auto-discovers servers, the discovery manifest lives at:

curl https://mcp.kronos.com.mx/.well-known/mcp.json

Authentication

Kronos AI MCP uses the same API keys as the REST API. Create one from Settings → API Keys. The plaintext key is shown ONCE at creation — store it in your password manager or secrets store immediately. Server-side only: never embed it in a browser bundle or commit it to a repo.

Header format

Authorization: Bearer kronos_sk_live_<random>

Available scopes

Each key carries one or more scopes. Tools the key doesn't have a scope for never appear in tools/list and calling them returns the same generic -32001 as any other auth failure — we never reveal which scope is missing.

account:readOpt-in

Read account setup, aggregate metrics, agents, and connected inbox metadata.

messages:send

Send messages, including templates.

messages:read

Look up a message by id.

conversations:read

List conversations and metadata.

templates:read

List approved WhatsApp templates.

calls:initiateOpt-in · costs money

Place outbound voice calls with one of your AI agents.

calls:read

List the voice numbers connected to your account.

integrations:connectOpt-in

Start safe integration connection flows.

agents:readOpt-in

Read agent settings and full prompts; list knowledge and resources.

agents:writeOpt-in

Create, activate and edit agents; link, unlink or delete knowledge and resources.

agents:assignOpt-in

Assign agents to inboxes or conversations.

Scopes & tools matrix

ToolScope requiredPurpose
get_account_overviewaccount:readRead safe account setup, aggregate metrics, the credit balance, agents, and inbox metadata.
start_integration_connectionintegrations:connectReturn a safe URL to start an integration login flow.
get_agent_detailsagents:readRead an agent's settings and its prompt, in pages for long prompts.
create_draft_agentagents:writeCreate an AI agent. It is inactive unless is_active is true.
update_agent_configurationagents:writeUpdate editable fields on an account-owned agent, activate or deactivate it, or edit part of its prompt.
reassign_agentagents:assignAssign an agent to an inbox or specific conversations.
list_knowledge_and_resourcesagents:readList knowledge items and resources with their status and linked agents.
set_library_item_agent_linkagents:writeLink or unlink a knowledge item or resource to an agent.
delete_library_itemagents:writePermanently delete a knowledge item or resource.
send_messagemessages:sendSend a text / template / media message.
send_templatemessages:sendConvenience wrapper for an approved WhatsApp template.
get_messagemessages:readLook up an outbound message by id.
list_conversationsconversations:readPaginate conversation metadata (no message bodies).
list_templatestemplates:readList approved WhatsApp templates for a WABA.
initiate_callcalls:initiatePlace an outbound voice call with one of your AI agents.
list_voice_numberscalls:readList the voice numbers connected to your account.
search_docsdocs:readSemantic search over the public Kronos AI docs (RAG). Auto-included on every key.

Issue keys with the minimum scopes the client needs. A key with only conversations:read cannot send messages or read message bodies — the inbox stays read-only and metadata-only.

Tool reference

Every tool is invoked through the JSON-RPC tools/call method. The wire envelope:

{
  "jsonrpc": "2.0",
  "id":      1,
  "method":  "tools/call",
  "params":  { "name": "<tool>", "arguments": { /* per-tool */ } }
}

On success, the response carries result.content[0].text as a JSON-encoded string — parse it client-side. Errors carry the standard JSON-RPC error.code / error.message shape (see Errors).

get_account_overviewscope: account:read

Read the current account's onboarding state, aggregate counts, credit balance (included and purchased credits, renewal, rate card), agents, and connected inbox metadata. This is the safe discovery tool for AI-native clients — use it to answer "how many credits do I have left?" — and does not return message bodies, prompts, access tokens, API keys, or platform account ids.

credits is { enabled: false } while credits are not active on the account, and { enabled: false, unavailable: true } when the balance could not be read right now (the rest of the overview is still valid; retry later). Only operations that run your agent or place a call spend credits; every other tool is free.

Arguments

{}

Success payload shape

// JSON.parsed from result.content[0].text
{
  account: {
    user_id: string,
    display_name: string | null,
    company_name: string | null,
    onboarding_state: "onboarding" | "dashboard",
    onboarding_completed_at: string | null
  },
  counts: {
    agents_total: number,
    agents_active: number,
    integrations_total: number,
    connected_channels: string[],
    conversations_total: number,
    messages_7d: number,
    contacts_total: number,
    open_followups: number,
    pending_kron_cards: number,
    voice_calls_inbound_30d: number,
    voice_calls_outbound_30d: number
  },
  credits:
    | { enabled: false }                      // credits are not active on this account
    | { enabled: false, unavailable: true }   // balance could not be read right now — retry later
    | {
        enabled: true,
        balance_total: number,
        included_balance: number,
        purchased_balance: number,
        included_allowance: number,
        included_renews_with_next_payment: boolean,
        included_expires_at: string | null,
        purchased_expires_at: string | null,
        low_balance: boolean,
        depleted: boolean,                    // agents are paused until credits are added
        rate_card: {
          reply: number,
          integration_call_surcharge: number,
          integration_surcharge_cap: number,
          voice_inbound_per_minute: number,
          voice_outbound_per_minute: number,
          reply_multiplier: number
        }
      },
  onboarding: { exists: boolean, is_first_onboarding: boolean, use_cases: string[] },
  agents: Array<{
    id: string,
    name: string,
    is_active: boolean,
    model_id: string | null,
    credits_per_reply: number | null          // null unless credits are enabled
  }>,
  integrations: Array<{ id: string, platform: string, account_name: string | null }>
}

Account action toolsscopes: integrations:connect · agents:read · agents:write · agents:assign

These tools expose the same Tool Kernel actions used by Kron and the REST API. They always run against the authenticated account. User-mode API keys must not pass user_id; admin MCP calls require user_id at the dispatcher layer.

start_integration_connection

Scope: integrations:connect

{
  provider: "instagram" | "facebook" | "messenger" | "whatsapp" | "gmail" | "shopify" | "telegram" | "mcp",
  return_to?: string
}

get_agent_details

Scope: agents:read

{
  agent_id: string,
  prompt_offset?: number, // default 0
  prompt_limit?: number   // default 12000, max 50000
}

Returns the agent's settings and prompt.text from prompt_offset. Long prompts come in pages: when prompt.has_more is true, call again with prompt_offset = prompt.next_offset.

create_draft_agent

Scope: agents:write

{
  name: string,
  description: string, // required, trimmed, 10-280 characters
  prompt?: string,
  is_active?: boolean  // default false: the agent is created inactive
}

update_agent_configuration

Scope: agents:write

{
  agent_id: string,
  name?: string,
  description?: string, // when supplied: trimmed, 10-280 characters
  prompt?: string, // replaces the whole prompt
  prompt_edits?: { find: string, replace: string }[], // 1-20 pairs
  is_active?: boolean, // true activates the agent, false deactivates it
  followup_mode?: "disabled" | "classic" | "agentic" | "guided",
  temperature?: number
}

Use prompt_edits to change part of a long prompt without resending it. Each find must match exactly one place in the current prompt; if any edit does not, nothing is changed. The edited prompt can have at most 200,000 characters. Send prompt or prompt_edits, not both.

reassign_agent

Scope: agents:assign

{
  target_type: "inbox",
  inbox_id: string,
  agent_id: string
}
// or
{
  target_type: "conversations",
  conversation_ids: string[],
  agent_id: string
}

list_knowledge_and_resources

Scope: agents:read

{
  kind?: "knowledge" | "resource" | "all", // default all
  agent_id?: string, // only items linked to this agent
  limit?: number     // per kind, default 50, max 100
}

Knowledge items are documents an agent searches to answer. Resources are files an agent can send to a contact. Each item comes with its processing status, a stalled flag (true when processing stopped and the item must be reprocessed or uploaded again), and the agents it is linked to.

set_library_item_agent_link

Scope: agents:write

{
  kind: "knowledge" | "resource",
  item_id: string,
  agent_id: string,
  linked: boolean // true links, false unlinks
}

delete_library_item

Scope: agents:write

{
  kind: "knowledge" | "resource",
  item_id: string
}

Deletes the item, its file and its search index. Every linked agent loses it. Cannot be undone.

send_messagescope: messages:send

Send a text, template, or media message via Meta Cloud API for any of your connected channels.

Arguments

{
  channel:         "whatsapp" | "instagram" | "messenger" | "telegram",
  integration_id?: string,        // UUID — required if you have >1 inbox on this channel
  recipient:       string | { chat_id: string },
                                  // Meta channels: plain string (wa_id | PSID)
                                  // Telegram: { chat_id: string } (int64 as decimal)
  message: {
    type: "text";
    text: string                  // max 4096 chars
  } | {
    type: "template";             // WhatsApp only
    template: {
      name:     string,
      language: string,           // e.g. "en_US"
      components?: Array<{ type, parameters?: object[] }>
    }
  } | {
    type: "media";
    media: {
      url:       string,
      mediaType: "image" | "video" | "audio" | "document",
      caption?:  string           // max 1024 chars
    }
  },
  tag?:             "CONFIRMED_EVENT_UPDATE" | "POST_PURCHASE_UPDATE"
                  | "ACCOUNT_UPDATE" | "HUMAN_AGENT",   // IG / Messenger >24h
  idempotency_key?: string        // 8..128 chars
}

Success result

{
  "content": [{
    "type": "text",
    "text": "{\"id\":\"wamid.HBgN...\",\"channel\":\"whatsapp\",\"status\":\"sent\",\"created_at\":\"2026-05-12T07:42:27.852Z\"}"
  }]
}

Idempotent replays carry an extra idempotent_replay: true inside the JSON payload of content[0].text.

Example — curl

curl -X POST https://mcp.kronos.com.mx/v1 \
  -H "Authorization: Bearer $KRONOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      1,
    "method":  "tools/call",
    "params": {
      "name": "send_message",
      "arguments": {
        "channel":   "whatsapp",
        "recipient": "5215555555555",
        "message":   { "type": "text", "text": "Hi from MCP!" }
      }
    }
  }'

send_templatescope: messages:send

Convenience wrapper for an approved WhatsApp template. Internally constructs a send_message call with message.type="template". WhatsApp only — Messenger / Instagram do not support templates.

Arguments

{
  channel?:        "whatsapp",      // implicit
  integration_id?: string,
  recipient:       string,
  template_name:   string,
  language:        string,          // e.g. "en_US"
  components?:     Array<{ type, parameters?: object[] }>,
  tag?:            "CONFIRMED_EVENT_UPDATE" | "POST_PURCHASE_UPDATE"
                 | "ACCOUNT_UPDATE" | "HUMAN_AGENT",
  idempotency_key?: string          // 8..128 chars
}

Example — curl

curl -X POST https://mcp.kronos.com.mx/v1 \
  -H "Authorization: Bearer $KRONOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      2,
    "method":  "tools/call",
    "params": {
      "name": "send_template",
      "arguments": {
        "recipient":     "5215555555555",
        "template_name": "appointment_reminder",
        "language":      "en_US",
        "components": [{
          "type": "body",
          "parameters": [
            { "type": "text", "text": "Maria" },
            { "type": "text", "text": "Tuesday at 10:00 AM" }
          ]
        }]
      }
    }
  }'

get_messagescope: messages:read

Look up an outbound message by its platform_message_id — the same id returned from send_message and from Meta's delivery webhooks.

Arguments

{ id: string }

Not-found behavior

A missing id (or a message that doesn't belong to your account) is returned as a result.isError = true tool result — NOT a JSON-RPC error code. This lets MCP clients display the "not found" text directly to the model without branching on protocol-level error handling.

Example

curl -X POST https://mcp.kronos.com.mx/v1 \
  -H "Authorization: Bearer $KRONOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      3,
    "method":  "tools/call",
    "params":  { "name": "get_message", "arguments": { "id": "wamid.HBgN..." } }
  }'

list_conversationsscope: conversations:read

List conversation metadata across your inboxes, most-recent first. Returns the conversation id, channel, contact name / handle, and timestamps. Message bodies are NOT included — reading bodies requires the separate messages:read scope and a future per-conversation tool.

Arguments

{
  integration_id?: string,        // UUID — filter to a single inbox
  limit?:          number,        // 1..100, default 25
  cursor?:         string         // opaque, from prior response next_cursor
}

Success payload shape

// JSON.parsed from result.content[0].text
{
  items: Array<{
    id:               string,
    integration_id:   string,
    channel:          "whatsapp" | "instagram" | "messenger" | "telegram",
    contact_name:     string | null,
    contact_handle:   string,            // wa_id | PSID | telegram chat_id
    last_message_at:  string | null,     // ISO timestamp
    created_at:       string
  }>,
  next_cursor: string | null              // null when no more pages
}

Example

curl -X POST https://mcp.kronos.com.mx/v1 \
  -H "Authorization: Bearer $KRONOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      4,
    "method":  "tools/call",
    "params":  { "name": "list_conversations", "arguments": { "limit": 25 } }
  }'

list_templatesscope: templates:read

List WhatsApp message templates for a WABA. Resolves the WhatsApp integration the same way send_message does — single-inbox auto-picks, multi-inbox requires an explicit integration_id.

Arguments

{
  integration_id?: string,        // UUID — required if you have multiple WA inboxes
  status?:         "APPROVED" | "PENDING" | "REJECTED" | "PAUSED"
}

Example — only approved templates

curl -X POST https://mcp.kronos.com.mx/v1 \
  -H "Authorization: Bearer $KRONOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      5,
    "method":  "tools/call",
    "params":  { "name": "list_templates", "arguments": { "status": "APPROVED" } }
  }'

search_docsscope: docs:read

Semantic search over the public Kronos AI documentation. Backed by a gemini-embedding-001 vector index (768d, cosine). Returns the top-K matching chunks with their doc slug, section heading, full chunk content, and similarity score in [0, 1] (higher = closer).

The docs:read scope is auto-included on every newly emitted API key — no rotation needed. The same surface is reachable without a Bearer at POST https://api.kronos.com.mx/v1/docs/search (rate-limited 60 req/min/IP).

Arguments

{
  query:    string,         // 1..500 chars, trimmed server-side
  limit?:   number,         // 1..20, default 5
  doc_slug?: string         // restrict to one doc; ^[a-z][a-z0-9-]*$
}

Response shape

{
  items: Array<{
    doc_slug:     string,
    doc_title:    string,
    doc_category: "getting-started" | "products" | "integrations"
                | "billing" | "security" | "developer",
    section:      string | null,    // H2/H3 heading, null for preamble
    content:      string,           // chunk text as embedded
    score:        number            // 1 - cosine_distance, ~[0, 1]
  }>
}

Example — natural-language query

curl -X POST https://mcp.kronos.com.mx/v1 \
  -H "Authorization: Bearer $KRONOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      6,
    "method":  "tools/call",
    "params":  {
      "name": "search_docs",
      "arguments": {
        "query": "how do I connect a WhatsApp business inbox",
        "limit": 3
      }
    }
  }'

Example — public REST mirror (no Bearer)

curl -X POST https://api.kronos.com.mx/v1/docs/search \
  -H "Content-Type: application/json" \
  -d '{ "query": "send a template message", "limit": 5 }'

initiate_call

Scope: calls:initiate Opt-in · costs money

Place an outbound voice call. The recipient picks up and hears your AI agent — the model initiates the dial; the agent has the conversation. Mirrors the REST endpoint POST /v1/calls/initiate exactly.

Arguments

{
  to:              string,           // international format, "+" optional
  agent_id:        string,           // UUID; agent must have Voice channel enabled
  context?:        string,           // optional briefing for the agent (background,
                                     // not instructions). Max 2000 chars.
  integration_id?: string,           // UUID; required only if you have >1 voice number
  tag?:            string,           // optional free-form correlation id, max 100
  idempotency_key?: string           // 8..128 chars
}

Success result

{
  "content": [{
    "type": "text",
    "text": "{\"call_id\":\"7d63af24-...\",\"twilio_call_sid\":\"CA159e...\",\"from\":\"+15187329372\",\"to\":\"+5215555555555\",\"status\":\"initiated\",\"agent_id\":\"547ce9ba-...\"}"
  }]
}

Idempotent replays carry an extra idempotent_replay: true inside the JSON payload of content[0].text. Failed dials are NOT cached — retrying with the same key after a failure re-attempts.

Example — curl

curl -X POST https://mcp.kronos.com.mx/v1 \
  -H "Authorization: Bearer $KRONOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      1,
    "method":  "tools/call",
    "params": {
      "name": "initiate_call",
      "arguments": {
        "to":       "+5215555555555",
        "agent_id": "547ce9ba-55b5-4992-baaa-bdfb232310aa",
        "context":  "Lead asked about onboarding hours. Speak Spanish."
      }
    }
  }'

Error semantics: validation issues, missing / wrong agent, no voice number, multi voice numbers without integration_id, or a call that can't be paid for → -32602 invalid_params with a human-readable message. For the last case the message names the reason: not enough credits (outbound calls cost 10 credits per minute), the outbound minutes of the period are used up (accounts not yet on credits), or the plan is not active. The REST surface uses distinct HTTP codes for each (see REST errors); MCP collapses them to invalid_params since JSON-RPC has no dedicated quota code. Carrier-side dial refusals → -32003 upstream_failed with the reason code embedded in the message text.

list_voice_numbers

Scope: calls:read

List the voice numbers connected to your account. Useful for picking the right integration_id for initiate_call when you have multiple. Mirrors the REST endpoint GET /v1/voice/numbers.

Arguments

None. The schema is { } strict — extra keys are rejected.

Success result

{
  "content": [{
    "type": "text",
    "text": "{\"numbers\":[{\"integration_id\":\"...\",\"phone_number\":\"+15187329372\",\"inbox_name\":\"Support\",\"iso_country\":\"US\",\"default_agent_id\":\"...\"}]}"
  }]
}

Example — curl

curl -X POST https://mcp.kronos.com.mx/v1 \
  -H "Authorization: Bearer $KRONOS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      2,
    "method":  "tools/call",
    "params":  { "name": "list_voice_numbers", "arguments": {} }
  }'

Workflows

The public MCP server does not expose tools to create, publish, execute, pause, or list dashboard Workflows. Its tool registry is limited to the tools listed in this page, such as messages, conversations, templates, account actions, voice, and documentation search.

The mcp node inside the dashboard Workflow editor is a different surface. It calls a server and tool associated with the Workflow's agent, rechecks the agent's read/write permissions in the server, and applies Workflow timeouts and output limits. Connecting to this public MCP endpoint does not grant a client access to another agent's Workflow tools.

Read the complete graph and node contract in Workflows documentation.

Errors

Protocol-level failures (auth, validation, missing methods) are returned INSIDE the JSON-RPC envelope with HTTP 200 per the JSON-RPC 2.0 spec. Transport-level failures (body too large, method not allowed on the endpoint) use real HTTP codes.

{
  "jsonrpc": "2.0",
  "id":     1,
  "error":  { "code": -32602, "message": "..." }
}

JSON-RPC error codes

CodeMeaningWhen
-32700Parse errorBody is not valid JSON.
-32600Invalid requestEnvelope is shaped wrong, or notification (missing id) — notifications are not supported.
-32601Method not foundUnknown JSON-RPC method (not the same as unknown tool name — that returns -32001).
-32602Invalid paramsArguments failed validation (wrong shape, missing required field, value out of range).
-32603Internal errorUnexpected Kronos AI-side error.
-32001UnauthorizedMissing / invalid / expired / revoked key, OR your key lacks the required scope, OR the tool name doesn't exist. The envelope is byte-identical across all auth failure modes — we never reveal which one happened.
-32002Idempotency conflictSame idempotency_key reused with a different request body.
-32003Upstream failedMeta rejected the call (rate limit, ban, template rejection). Distinct code so clients can retry differently than on Kronos AI-internal errors.
-32004Rate limitedYour key exceeded its per-minute budget. Back off and retry.

Transport-level (HTTP)

StatusWhen
405GET on /v1. The endpoint accepts POST (and OPTIONS for CORS preflight) only.
413Body exceeds 32 KB.

Rate limits

Each API key is capped at 60 requests / minute. Crossing the cap returns -32004 with a short backoff. The bucket is per-key — separate keys (e.g. one per environment) get separate budgets.

Meta's own per-channel limits still apply on top (WhatsApp Business tiers, Messenger rate caps). If you need higher bursts (e.g. backfilling a campaign), reach out via in-app support so we can whitelist your account.

Versioning

MCP protocol
2025-03-26

Returned by initialize as protocolVersion.

Server version
1.0.0

Returned by initialize as serverInfo.version.

Breaking changes to tool schemas or error envelopes will bump the server version's major component and ship a parallel v2 endpoint — your existing integration continues working at https://mcp.kronos.com.mx/v1 until you migrate.

MCP — Kronos AI | Kronos AI