MCP
Who can use this feature?
- You need the Pro or Plus plan to create and manage API keys.
- Setting this up needs a developer. You create the key yourself in Settings → General → Manage keys, then someone who writes code connects the bot to it.
Overview
MCP lets an AI assistant you run yourself work inside your Chatty inbox: read a conversation, look up a product, an order, or an FAQ, and post its reply where the customer sees it. That assistant can be a bot your team builds, or a tool such as Claude.
Chatty exposes your store's chat capabilities as an MCP (opens in a new tab) server. An external bot connects once, discovers the tools your store has enabled, calls them to gather what it needs, and posts its answer back into the conversation.
A typical loop:
- A customer sends a message.
- Chatty fires a
message.createdwebhook to your bot. ReadsenderTypeand act oncustomeronly. - Your bot calls Chatty's MCP tools: look up a product, search FAQs, check an order.
- Your bot calls
send_messageto reply. The answer appears in the conversation.
Use it to run your own model, apply your own logic before answering, or plug Chatty into an agent framework you already have.
Every parameter, type, and return value is listed in the Tool Reference.
Connect
| Endpoint | POST https://app.chatty.net/mcp |
| Server name | chatty-mcp, version 1.0.0 |
| Protocol | JSON-RPC 2.0 over Streamable HTTP |
| Mode | Stateless, so every request is self-contained. Only POST is accepted. |
Headers
| Header | Required | Value |
|---|---|---|
X-App-Id | Yes | Your App ID, the field at the top of Settings → General → Manage keys. Some clients call it a Client ID. |
Authorization | Yes | Bearer sk_..., an API key from the same panel. |
X-Chatty-Convo-Id | No | The conversation the bot is acting in. add_note, update_tags, and assign_member read convoId from this header when you omit the parameter. |
Both credentials sit in the same place, and the key is the same one the Chat Conversations API uses. The two APIs read it from different headers: MCP wants Authorization: Bearer sk_..., the Chat Conversations API wants X-Api-Key: sk_.... Sending it the wrong way returns 401 on either side.
Each store can hold up to 5 active keys. See the API reference for how to create one.
Check the connection
List the tools your store exposes
curl -s -X POST "https://app.chatty.net/mcp" \
-H "X-App-Id: $CHATTY_APP_ID" \
-H "Authorization: Bearer $CHATTY_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'Call tools/list after connecting rather than hard-coding a list. The tool set is rebuilt on every request from your store's AI agent settings, so it changes the moment you flip a switch in the app.
Connect from an MCP client
Clients that speak Streamable HTTP take the URL and the two headers as they are. Clients that expect a local command need the mcp-remote bridge.
Claude Desktop
Add this to claude_desktop_config.json, then restart the app.
{
"mcpServers": {
"chatty": {
"command": "npx",
"args": [
"-y", "mcp-remote", "https://app.chatty.net/mcp",
"--header", "X-App-Id:${CHATTY_APP_ID}",
"--header", "Authorization:Bearer ${CHATTY_API_KEY}"
],
"env": {
"CHATTY_APP_ID": "YOUR_APP_ID",
"CHATTY_API_KEY": "sk_..."
}
}
}
}Cursor
Add this to .cursor/mcp.json in your project, or to ~/.cursor/mcp.json for every project. Cursor speaks Streamable HTTP directly, so no bridge is needed.
{
"mcpServers": {
"chatty": {
"url": "https://app.chatty.net/mcp",
"headers": {
"X-App-Id": "YOUR_APP_ID",
"Authorization": "Bearer sk_..."
}
}
}
}Your API key grants full access to your inbox, including sending messages as your store. Keep these files out of version control and off shared machines.
Which tools your store gets
Chatty exposes 17 tools. Eight are always registered. Nine more depend on switches in your AI agent settings, and Chatty reads those switches on every single request.
Three tools share one switch. Turning on AI agent > Training data > Products registers product_lookup, product_faq_lookup, and manage_cart together. There is no separate switch for the cart — if the AI can read products, it can also edit the cart.
Four switches are off until you turn them on. Products, Collections, Discounts, and Size guide all default to off. A store that has never touched its AI agent settings exposes 11 tools: the 8 always-on ones plus order tracking, after-sale support, and human handover, which are on by default.
| Switch in the app | Tools it registers | Default |
|---|---|---|
| AI agent > Training data > Products | product_lookup, product_faq_lookup, manage_cart | Off |
| AI agent > Training data > Collections | collection_lookup | Off |
| AI agent > Training data > Discounts | discount_lookup | Off |
| AI agent > Instructions > Assistant skills > Size guide | size_guide_lookup | Off |
| AI agent > Instructions > Assistant skills > Order tracking | check_order_status | On |
| AI agent > Instructions > Assistant skills > After-sale support | customer_support | On |
| AI agent > Instructions > Assistant skills > Human handover | human_agent_transfer | On |
No tool is plan-gated at the MCP layer. The plan check happens earlier, on the switch itself and on the API key: order tracking needs the Basic plan or higher, size guide needs Pro, and creating any key at all needs Pro or Plus.
Rules for your bot
Six rules cover the mistakes that break a Chatty bot in production.
- Ask before you assume. Call
tools/listafter connecting. The tool set is rebuilt from your settings on every request, so a hard-coded list goes stale the moment someone flips a switch. - Answer customers, not yourself.
message.createdfires for every message, including the ones your bot sends. Act only whensenderTypeiscustomer. - Copy ids verbatim. Every id comes from an earlier call. Never build, shorten, or reformat one. See Identifiers.
- Read before you replace.
update_tagsoverwrites the whole tag list rather than merging. Read the current tags first if you mean to add one. - Confirm before you escalate.
customer_supportandhuman_agent_transfertake two calls. The first asks the customer; the second sendsisConfirmed: true. Send it only after the customer has actually agreed. - Nothing reaches the customer until you send it. Every tool returns text to your bot.
send_messageis the only one that posts into the conversation.
Receive customer messages
Your bot needs to know when to act. Register a webhook, either with the register_webhook tool or with POST /chat/webhooks on the Chat Conversations API:
curl -s -X POST "https://app.chatty.net/chat/webhooks" \
-H "X-Api-Key: $CHATTY_KEY" -H "Content-Type: application/json" \
-d '{
"url": "https://your-bot.example.com/hooks/chatty",
"events": ["message.created"]
}'Events you can subscribe to
| Event | Fires when |
|---|---|
message.created | A message is added to a conversation. |
message.updated | A message is edited. |
message.removed | A message is deleted. |
conversation.created | A conversation starts. |
conversation.state_changed | The conversation status changes. |
conversation.assigned | The conversation is assigned to a member. |
conversation.tags_updated | The tags on a conversation change. |
conversation.removed | A conversation is deleted. |
customer.created | A customer record is created. |
message.created fires for every message added to a conversation, whichever side added it. The payload carries senderType. Act only when it is customer, so your bot never answers itself.
Do not set your own signing secret. Chatty generates it and ignores any secret you send. The generated value comes back in the register_webhook result, and in the response body of POST /chat/webhooks. It looks like whsec_ plus 48 hex characters. Store it when you register, and verify every payload with it.
Verify every delivery before acting on it. See Webhooks for the payload shape and signature check.
Rate limits
| Limit | Value |
|---|---|
Requests to /mcp | No limit today. Chatty counts nothing on this endpoint. |
Requests to /chat/* with the same key | 120 per minute per key, 300 per minute per IP |
The absence of an MCP limit is not a licence to hammer it. Your bot almost always calls the Chat Conversations API with the same key for reading live conversations, and those calls are counted. A tool-call loop that also polls /chat/conversations will hit 429 on the REST side long before anything complains on the MCP side. See Errors and rate limits.
Errors
Authentication is checked before anything else, and it answers with a plain object rather than JSON-RPC:
{ "error": "Invalid or revoked API key." }Everything after that comes back in JSON-RPC form:
{ "jsonrpc": "2.0", "error": { "code": -32000, "message": "Shop not found." }, "id": null }| Situation | Status | Response |
|---|---|---|
X-App-Id missing, or Authorization missing or not starting with Bearer | 401 | { "error": "Missing required headers: X-App-Id and Authorization (Bearer sk_...)" } |
Key sent in X-Api-Key instead of Authorization | 401 | Same missing-headers message. The header check runs first and never sees the key. |
| Key unknown, revoked, or belonging to another store | 401 | { "error": "Invalid or revoked API key." } |
Any method other than POST | 405 | { "jsonrpc": "2.0", "error": { "code": -32000, "message": "Method not allowed. Only POST is supported in stateless mode." }, "id": null } |
| App ID resolves to a store that no longer exists | 404 | { "jsonrpc": "2.0", "error": { "code": -32000, "message": "Shop not found." }, "id": null } |
| Calling a tool the store has not turned on | 200 | A JSON-RPC error from the MCP layer reporting that the tool does not exist. Chatty never registered it, so tools/list never listed it either. Compare against tools/list before you call. |
Because the header check runs first, an unauthenticated GET returns 401 rather than 405. Test for a top-level error string before parsing a JSON-RPC response.
Tool-level failures are not protocol errors. A tool that cannot do its job returns 200 with an ordinary result whose text is {"error": "..."} — for example Conversation abc not found or Member is not active. Parse the result text and check for an error key.
Security
An API key is all-or-nothing. There is no way to limit a key to read-only, to one conversation, or to a subset of tools. A key that can search your FAQs can also send messages as your store, reassign conversations, and register webhooks that forward every message to an outside URL.
What that means when you hand a key to a bot:
- A leaked key is a leaked inbox. Treat it like a password to your storefront, not like a public app token.
- Give each bot its own key. You get 5 per store. One key per bot means you can revoke one without taking the others down.
- Never ship it to the browser. The key belongs on your server. Anything in storefront JavaScript is public.
- Rotate on suspicion, not on schedule. Delete the key in Settings → General → Manage keys and generate a replacement. MCP verifies the key against the database on every request, with no cache, so deletion stops MCP traffic immediately. The Chat Conversations API caches for 5 minutes, so REST calls with the same key can survive that long.
- Watch the webhooks.
register_webhookis available to every key. A stolen key can quietly point a copy of your message stream at someone else's server, so audit your subscriptions withGET /chat/webhooksafter any incident.
Store the key outside your code
Read it from an environment variable or a secret manager. Never commit it, and keep client config files out of version control.
Scope the bot yourself
Chatty cannot restrict what a key can do, so restrict what your bot does. If it only needs to answer questions, let it call faq_retrieval and send_message and drop the rest.
Log every write
Record each send_message, update_tags, and assign_member your bot makes. Chatty marks bot messages as automated, but only your logs tell you which bot sent what.
Need help?
Contact the Chatty support team from your dashboard. Include the tool name, the timestamp of a failing call, and the returned error message.
For parameters and return values, see the Tool Reference. For reading live conversations over REST, see the Chat Conversations API.
Chatty Help Center