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/v1Today 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.