MCP
MCP server
Connect Claude Code, Cursor or any MCP client to your Seegnals workspace with one URL and your API token. Tools, errors, limits and the exact client configs.
Updated 4 September 2026
Seegnals runs a remote Model Context Protocol server. An assistant that speaks MCP over Streamable HTTP can read your campaigns, companies, replies, offers and mailboxes, add prospects, enrol them in a campaign, exclude addresses and manage event subscriptions, with the same rules and the same permissions as the REST API.
| Endpoint | https://app.seegnals.com/api/mcp |
| Transport | Streamable HTTP, stateless: JSON responses, no sessions |
| Methods | POST (JSON-RPC). GET answers 405. |
| Authentication | Authorization: Bearer <token>, the same workspace API token as the REST API |
| Token | Settings → Integrations → API keys; shown once |
Every tool is a thin proxy over one REST endpoint on the same origin, called with the token you connected with. The server can do exactly what the REST API allows and nothing more: same validation, same workspace isolation, same rate limit.
Connecting
Claude Code
claude mcp add --transport http seegnals https://app.seegnals.com/api/mcp \
--header "Authorization: Bearer sgn_your_token_here"
/mcp inside Claude Code then lists seegnals as connected with its tools.
Cursor
.cursor/mcp.json in the project, or ~/.cursor/mcp.json globally:
{
"mcpServers": {
"seegnals": {
"url": "https://app.seegnals.com/api/mcp",
"headers": { "Authorization": "Bearer sgn_your_token_here" }
}
}
}
Claude Desktop
The custom connector dialog in Claude Desktop expects OAuth. This server uses a bearer token, so bridge it with mcp-remote in claude_desktop_config.json:
{
"mcpServers": {
"seegnals": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://app.seegnals.com/api/mcp",
"--header", "Authorization: Bearer sgn_your_token_here"
]
}
}
}
Any other client
{
"mcpServers": {
"seegnals": {
"type": "http",
"url": "https://app.seegnals.com/api/mcp",
"headers": { "Authorization": "Bearer sgn_your_token_here" }
}
}
}
Raw protocol, for debugging. The Accept header is required by the transport:
curl -s https://app.seegnals.com/api/mcp \
-H "Authorization: Bearer sgn_your_token_here" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
const res = await fetch("https://app.seegnals.com/api/mcp", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.SEEGNALS_TOKEN}`,
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream"
},
body: JSON.stringify({
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
})
});
const json = await res.json().catch(() => null);
console.log(res.status, json);
import os, requests
res = requests.get(
"https://app.seegnals.com/api/mcp",
headers={"Authorization": f"Bearer {os.environ['SEEGNALS_TOKEN']}", "Accept": "application/json, text/event-stream"}, json={
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
},
timeout=20,
)
print(res.status_code, res.json() if res.content else None)
Because the server is stateless, initialize is not required before other calls and no Mcp-Session-Id is ever issued. Each request stands on its own.
Tools
Tools return the REST API’s JSON as text in content[0].text and, for objects, as structuredContent. Arguments are validated before any HTTP call is made.
| Tool | Proxies | Inputs |
|---|---|---|
create_prospect |
POST /api/v1/prospects (?campaign= when campaign_id is given) |
email (required), first_name, last_name, timezone, company_name, custom_fields, campaign_id |
update_prospect |
PATCH /api/v1/prospects/{id} |
id and email (required), plus the full desired state of the other fields; see Prospects |
list_prospects |
GET /api/v1/prospects |
email, company_id, status, created_since, limit, cursor |
get_prospect |
GET /api/v1/prospects/{id} |
id |
list_campaigns |
GET /api/v1/campaigns |
status, folder_id, archived, limit, cursor |
get_campaign |
GET /api/v1/campaigns/{id} |
id |
list_campaign_prospects |
GET /api/v1/campaigns/{id}/prospects |
id, status, limit, cursor |
list_companies |
GET /api/v1/companies |
search, temperature, limit, cursor |
get_company |
GET /api/v1/companies/{id} |
id |
list_replies |
GET /api/v1/replies |
classification, since, campaign_id, prospect_id, limit, cursor |
list_offers |
GET /api/v1/offers |
status, prospect_id, campaign_id, limit, cursor |
get_offer |
GET /api/v1/offers/{id} |
id |
add_suppression |
POST /api/v1/suppressions |
target (required) |
list_suppressions |
GET /api/v1/suppressions |
kind, limit, cursor |
create_webhook |
POST /api/v1/hooks |
event, target_url (both required) |
list_webhooks |
GET /api/v1/hooks |
limit, cursor |
delete_webhook |
DELETE /api/v1/hooks/{id} |
id |
list_mailboxes |
GET /api/v1/mailboxes |
none |
enrol_prospects |
POST /api/v1/campaigns/{id}/prospects |
id, one of prospect_ids / emails (1 to 200) |
pause_campaign |
POST /api/v1/campaigns/{id}/pause |
id |
resume_campaign |
POST /api/v1/campaigns/{id}/resume |
id |
classify_reply |
PATCH /api/v1/replies/{id} |
id, classification |
delete_suppression |
DELETE /api/v1/suppressions/{id} |
id |
Read tools are marked read-only in their annotations, so a client that asks before running write tools can run these without asking. Every tool mirrors the matching page in the REST reference; the parameters, filters and pagination are identical. The server never exposes more than the REST API does; when an endpoint ships, its tool is added the same day and listed in the changelog.
Errors
| Situation | What the client sees |
|---|---|
| Missing, malformed or revoked token | HTTP 401 with { "error": "…" } and WWW-Authenticate: Bearer realm="Seegnals API". Never 500. |
| Rate limit exceeded | HTTP 429 with Retry-After in seconds; every authenticated response also carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset |
| Token check impossible (database outage) | HTTP 500 { "error": "Authentication is temporarily unavailable." } |
GET /api/mcp |
HTTP 405, Allow: POST, DELETE |
| Invalid tool arguments | Tool result with isError: true explaining the validation failure; no HTTP call is made |
REST API answers 4xx or 5xx |
Tool result with isError: true and HTTP <status> from <METHOD> <path>: <message> (code: <code>); for 429 also Retry after N seconds. |
| REST API unreachable | Tool result with isError: true: Could not reach the Seegnals API … |
Tool failures are always tool results, never JSON-RPC protocol errors, so the model can read the message and correct its input.
Limits
- Rate limit. The REST budget is 60 requests a minute per token. One tool call spends two of them (the MCP request and the proxied REST call), so plan on about 30 tool calls a minute per token.
tools/listcosts one. - Bodies. Prospects up to 64 KiB, suppressions and subscriptions up to 4 KiB, as in the REST API.
- Timeout. A proxied call is aborted after 20 seconds and reported as a tool error.
- Stateless. No sessions, no resumability, no server-initiated notifications, no
resourcesorpromptscapabilities.
Security notes
The token in your client configuration is a full-access workspace token. Keep the config file out of version control, give the assistant its own token so you can revoke it independently, and remember that an assistant with this server can create prospects and subscriptions in your workspace on its own initiative. Review what it did in Settings → Integrations → History and in the prospects list, where API-created prospects carry source = API.