sayintel
Docs

Tools and connections.

Every action sayintel can take is defined once, in one capability registry, and exposed three ways: as a tool Q can call, as an MCP tool, and as a REST endpoint. A parity test fails the build if a door falls behind, so the catalogue you read here is the catalogue that runs.

The three doors

             ┌─ Q (in the app, acting as the signed-in owner)
capability ──┼─ MCP tool   https://sayintel.com/api/public/mcp
             └─ REST       https://sayintel.com/api/public/v1

Today that is 34 capabilities: 18 read, 14 write and 2 send, and 34 MCP tools. Send-kind capabilities still require a human approval inside the product; a token with the send scope pushes an already-approved set, it does not approve one.

Scopes map to kinds

read   → every read capability
write  → creating campaigns, curating people, staging rewrites
send   → pushing an approved set to the sending tool

Full details, plus rate limits and idempotency, in authentication. The per-capability reference is the REST reference.

Your own outside tools

An account can connect its own MCP servers, and Q then reaches them in the same turn as sayintel's own abilities. Two rules make that safe.

The permission line. Q may read from an outside server, and may create or update items there. It may never do anything that reaches a person (send, email, DM, post, invite, comment, call) and never anything destructive (delete, purge, revoke, reset). The decision runs on the tool definitions before the model sees the catalogue, so a withheld tool does not exist for the turn rather than being refused at call time. Server-provided annotations are advisory — the tool name is checked too, and the stricter answer wins.

list_invoices     → allowed   (a read never reaches anyone)
create_issue      → allowed   (create and update are in bounds)
send_email        → withheld  (it would reach a person)
delete_workspace  → withheld  (it deletes something)

Namespacing. Outside tools are exposed to Q as ext__<connection>__<tool>, so two servers can both expose search without colliding, and every call in the activity stream names the server it went to.

Connections are owner-scoped: only the account that added a server can use it, and its credentials are never exposed to the model or to any other account.