MCP server
Point an MCP client at one URL and the agent inside it can send and receive on real channels. Nothing is installed, nothing is written into your project except the config entry itself — the SDK, the tokens, and the platform calls all stay on Caspian's side.
Add the server
Cursor reads .cursor/mcp.json (per project) or ~/.cursor/mcp.json (everywhere). Claude Code and other MCP clients take the same shape. Start with no API key:
{
"mcpServers": {
"caspian": {
"url": "https://api.trycaspianai.com/mcp"
}
}
}Then ask the agent to get started. It calls get_started, which mints a free sandbox project with no signup and returns the key plus the exact config block to write back:
{
"mcpServers": {
"caspian": {
"url": "https://api.trycaspianai.com/mcp",
"headers": { "Authorization": "Bearer comm_..." }
}
}
}Reconnect the server after adding the header — MCP clients read headers when the connection opens, so the key applies on the next connect, not the next call. An existing key from the dashboard works here too; get_started is only for going from nothing to working without leaving the editor.
Tools
| Tool | |
|---|---|
get_started | Mint a sandbox key — the one tool that needs no key |
connect_channel | Connect email (instant), Slack or Discord (returns an install link), Telegram (bot token) |
list_channels | What this account can send and receive on |
list_connections | The addresses it owns — an inbox, a Slack workspace |
inbox | Read what people sent: @mentions, DMs, email. Each entry carries a message_id |
read_conversation | The full thread, for context before answering a follow-up |
reply | Answer in the same thread and channel it arrived on |
send_message | Start a new conversation with someone who has not written in |
The tool descriptions are the documentation. On connect the client fetches them along with the server's instructions and hands them to the model, so the agent knows the surface without being told — there is no SKILL file to install for MCP.
Connecting a channel
Email needs no credentials and is live immediately. Slack and Discord return an authorize_url: the agent shows it as a link, you approve it in your own workspace, and the connection goes active.
For Slack there is a second step that is easy to miss — installing the app to the workspace is not enough. The bot must also be in a channel. Run /invite @<app name> in the channel it should watch, or DM the app. Until then it receives nothing, and inbox will say so rather than returning an empty list.
Receiving is a pull
Inbound messages are stored the moment they arrive — Slack posts to Caspian's webhook whether or not your editor is open. But nothing wakes the agent: it sees them when it calls inbox. Ask it what came in, or tell it you have sent something, and it will look.
That is the honest limit of the MCP path. An agent that answers unprompted at 3am needs the SDK, which owns its own inbound loop.
How it compares
| MCP | CLI | SDK | |
|---|---|---|---|
| To install | a URL | the caspian binary | the package + your handler |
| Code in your project | none | none (unless you scaffold) | yes — you write the bot |
| Who calls Slack | Caspian | Caspian | Caspian, or you with via="self-host" |
| Runs unattended | no | yes — scriptable | yes |
| Best for | "answer this thread" inside an editor | scripts, cron, non-MCP agents | an always-on bot |
All three speak to the same gateway with the same key, so they compose: connect Slack through MCP in Cursor, then caspian channels ls shows that workspace.
Notes
- The server is stateless (MCP 2026-07-28): no sessions, no handshake. Your key travels in the
Authorizationheader on every request, so any instance can serve it. - Discovery is unauthenticated —
tools/listandget_startedwork without a key so a fresh agent can bootstrap. Every tool that touches data requires one. - Transport is Streamable HTTP at
/mcp, mounted on the same gateway that serves the REST API.