Docs / Decisions

ADR 0020: An MCP server in the binary, as a client of the public API

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

  1. araldo mcp is an MCP server over stdio (JSON-RPC 2.0, one message per line). An assistant runs it as a local command, with ARALDO_URL (the Araldo to talk to) and ARALDO_API_KEY in its environment.
  2. 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.
  3. 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, and cancel_post that it is destructive, so the assistant can ask first.
  4. Errors are the API's problem details, returned as a tool error, so the agent reads the stable code and param and corrects itself.
  5. create_post takes an idempotency key (generated when the agent gives none), so an assistant that retries does not post twice.
  6. 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.
  7. 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

Consequences

Edit this page on GitHub