Docs / Decisions
ADR 0020: An MCP server in the binary, as a client of the public API
- Status: accepted; built (sign-in for hosted assistants later)
- Date: 2026-10-02
Context
Callers bring the content (ADR 0001), and more and more of them are AI agents: someone asks an assistant to announce a release, and the assistant should be able to see the brands and channels, draft the post, check it against every platform's rules, fix it, schedule it, and later see how it did. The Model Context Protocol (MCP) is how assistants such as Claude Code and Claude Desktop reach tools like these.
Decision
araldo mcpis an MCP server over stdio (JSON-RPC 2.0, one message per line). An assistant runs it as a local command, withARALDO_URL(the Araldo to talk to) andARALDO_API_KEYin its environment.- It is a client of the public API, never the database: whatever the key may do, the tools may do, and nothing more. A test key reaches only sandbox channels (ADR 0006); scopes, brand limits and rate limits apply unchanged (ADR 0019). It works against any install, local or remote.
- The tools follow how an agent works: discover (
list_platforms,list_brands,list_channels,list_templates,get_template), prepare (upload_media_from_url), draft and check (preview_post, whose rule violations are data, not errors), act (create_post,reschedule_post,cancel_post), follow up (list_posts,get_post,engagement_summary,ads_summary,analytics_summary,brand_report), and draft newsletters (preview_newsletter,draft_newsletter,list_newsletters). Each declares whether it only reads, andcancel_postthat it is destructive, so the assistant can ask first. - Errors are the API's problem details, returned as a tool error, so
the agent reads the stable
codeandparamand corrects itself. create_posttakes an idempotency key (generated when the agent gives none), so an assistant that retries does not post twice.- No MCP library. The protocol subset a tools-only server needs (initialize, ping, tools/list, tools/call) is a few hundred lines on the standard library, which keeps ADR 0002's rule on dependencies.
- The server also serves MCP over HTTP at
POST /v1/mcp(the Streamable HTTP transport, stateless, one JSON response per request), so an assistant can connect without running a binary. It is authenticated by the same API key as the rest of/v1, sent as a bearer token, and runs the same tools, calling the API handler in-process with that key: nothing an HTTP caller could not do with the key directly. Hosted assistants that require an OAuth sign-in are a later step.
Alternatives considered
- Only stdio. Every API-first competitor offers a hosted MCP endpoint, and many assistants connect to a URL with a key; requiring a local binary would be a reason to pick them instead.
- Calling
coredirectly from the MCP server. Faster, but it would need the database and master keys, and would bypass the scopes and limits an API key carries.
Consequences
- The tools are a second, small interface to keep in step with the API; their tests run against the real API handler.
- An assistant needs a key: a test key to try things, a live key (perhaps limited to one brand) to publish.