MCP server
The MCP endpoint, in full
MCP (Model Context Protocol) lets an AI agent enumerate and call tools over a standard wire format. FounderReply exposes its agent at a single endpoint — POST /api/mcp — speaking JSON-RPC 2.0 over one HTTP request and one response.
- tools/list returns all 60 tools with their JSON Schema
- One key, one workspace — no tool takes a workspace id
- Social writes enqueue for approval; the endpoint has no way around that queue
The one surface an fr_live_ key opens — 78 of the 90 /api/v1 routes are session-only
Wire contract
The whole contract, transcribed from source
- Endpoint
- POST /api/mcp
- Protocol
- JSON-RPC 2.0 over one HTTP request/response
- Methods
- tools/list · tools/call
- Auth
- Authorization: Bearer fr_live_… — missing or revoked → HTTP 401
- Scope
- The key resolves to one workspace; params never carry a workspace id
- Key reach
- This endpoint, plus /api/v1/voice/mcpdial/numbers?workspace_id= and /api/v1/voice/mcpdial/numbers/{id}?workspace_id= and /api/v1/voice/mcpdial/numbers/available?workspace_id=&country=&type= and /api/v1/voice/mcpdial/numbers/requirements?workspace_id=&country=&type= and /api/v1/voice/mcpdial/verification/status?workspace_id= and /api/v1/voice/mcpdial/verification/profile?workspace_id= and /api/v1/voice/mcpdial/verification/addresses?workspace_id= and /api/v1/voice/mcpdial/verification/addresses/{id}?workspace_id= and /api/v1/voice/mcpdial/verification/documents?workspace_id= and /api/v1/voice/mcpdial/verification/documents/{id}?workspace_id= and /api/v1/brain and /api/v1/brain/proposalsThe other 78 /api/v1 routes are session-only and never read an Authorization header.
- Errors
- −32700 parse · −32600 request · −32601 method · −32602 params · −32603 internal — all at HTTP 200
- Not shipped
- SSE / streamable-HTTP transport: server-push, notifications, sessions
curl -s https://founderreply.com/api/mcp \
-H "Authorization: Bearer fr_live_…" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "set_autonomy",
"arguments": { "action": "reply", "mode": "approve" }
}
}{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{ "type": "text",
"text": "{\"ok\":true,\"action\":\"reply\",\"mode\":\"approve\"}" }
],
"structuredContent": {
"ok": true, "action": "reply", "mode": "approve"
},
"isError": false
}
}A key is bound to one workspace and the tools take no workspace id, so a key can only ever operate its own. Each key also carries scopes — read, draft, publish, admin — and tools/list shows only the tools they cover. set_autonomy over MCP can only lower a dial: raising one, like approving a queued item, is a human decision made in the dashboard, whatever scopes the key holds. And even a lowered dial changes nothing on this endpoint: send_reply and publish_content enqueue whatever the mode says, so the dial changes what the dashboard and the schedulers do with the queued item, not whether the tool call dispatched.
What this server does not do
- No SSE or streamable-HTTP transport — no server push, no notifications, no sessions. One request, one response.
- No workspace switching. A key is minted against one workspace and stays there; there is no parameter to change that.
- No way around the social approval queue. send_reply and publish_content enqueue and return { ok, queued: true, id } — they do not dispatch, on any plan and for any caller.
- One exception, in Digital PR and named rather than hidden: send_press_pitch dispatches without a queue stop once a workspace has earned auto-send, and then needs a key with the publish scope. No key can approve a queued item — decide_press_approval only rejects. See the guardrails section for what earning it takes.
Tool registry
Every MCP tool, and what it actually does
The whole registry — 60 tools, in the order tools/list returns them. Nothing below is a roadmap item.
| Tool | What it does |
|---|---|
| Persona & strategy · 3 | |
| create_persona | Generate and persist a brand persona / content strategy from a company-focus brief, and update the workspace brand voice. |
| bootstrap_focus | Infer that brief from a connected account’s own recent posts instead of typing it. |
| get_persona | The workspace’s latest persona, or null if none exists yet. |
| Content · 12 | |
| generate_content_plan | Build a rolling calendar of planned posts from the persona over the next horizonDays. |
| plan_news_posts | Find recent news in the brand’s field and schedule one planned post per item on the news template. |
| generate_blog_posts | Research SEO topics and generate finished, ready-to-publish articles in the brand voice. |
| list_blog_posts | Generated articles with bodies omitted, optionally filtered by status. |
| get_blog_post | One article by id, including its full markdown body. |
| list_syndication_targets | The workspace’s connected blog syndication platforms (Dev.to, Hashnode, Medium, Ghost) and whether each is enabled. |
| connect_syndication_target | Connect (or update) one platform’s API credentials for cross-posting published articles. Credentials are encrypted at rest. |
| disconnect_syndication_target | Disconnect a syndication platform, deleting its stored credentials. |
| get_post_syndications | Per-platform syndication state — pending, synced, or failed, with the external URL — for one article. |
| syndicate_blog_post | Cross-post an already-published article to every connected target now, with a canonical URL back to its home on your own site. |
| list_templates | The available post formats — news, release, personal-update, tip, story, question, announcement. |
| list_scheduled_posts | Scheduled posts, optionally filtered by status. |
| Autonomy & analytics · 2 | |
| set_autonomy | Lower the mode (auto → approve → off) for an action type. A key can only make a dial stricter; raising one is done in the dashboard. Needs the admin scope. |
| get_analytics | Engagement overview over a trailing window, with a per-content-pillar rollup. |
| Growth · 2 | |
| find_growth_opportunities | Discover public conversations the brand could add value to, and persist them. |
| list_opportunities | Engagement opportunities, optionally filtered by status. |
| Engagement — capability-gated per platform · 6 | |
| list_messages | Inbound DMs on one platform, normalised to { id, origin, sender, content, ts, threadId }. |
| list_mentions | Recent comments and mentions on the brand. |
| list_own_posts | The brand’s own recent posts, for persona and context. |
| draft_reply | Draft a reply in brand voice with cross-platform memory recall. Never sends. |
| send_reply | Enqueue a reply to the human approval queue. Does not dispatch. |
| publish_content | Enqueue an original post to the human approval queue. Does not publish. |
| SEO · 10 | |
| run_seo_audit | Fetch each page rendered, score it on discrete metrics plus PageSpeed Insights, and reconcile the issue register. |
| get_seo_overview | Site and page counts, average page score, open issues by severity, keyword coverage, average SERP position. |
| list_seo_issues | Open on-page issues across the workspace: error → warn → info. |
| track_keyword | Add or update a tracked keyword so its SERP position is sampled over time. |
| get_keyword_rankings | Sample current SERP positions and return the latest known position per keyword. |
| sync_search_console | Ingest Search Console’s authoritative impressions, clicks and average position. |
| add_seo_site | Register a website for SEO tracking. |
| generate_blog_from_seo_gaps | Find tracked keywords outside the top 10, read who outranks you, and write against the gap. |
| generate_conquest_posts | Mine a competitor’s surface and generate posts that capture the traffic it ranks for. |
| refresh_stale_blog_posts | Redraft published articles in place — same slug, honest updated_at, IndexNow ping when configured. |
| Browser · 6 | |
| browse_page | Read any page as markdown by driving a real browser. The cheapest read. |
| extract_from_page | Pull structured fields out of a page — pricing, contact details, a product list. |
| screenshot_page | Capture a page as a base64 image. Rides a stored session, so it can shoot logged-in pages. |
| list_browser_connections | Which sites this workspace has a usable sign-in for, and which are still waiting on the user. |
| connect_browser_account | Mint a one-time connect_url to hand the user. Never asks anyone to type a password to the agent. |
| run_on_page | Drive a goal in a real browser until a success condition holds. Not a posting path — those go through approvals. |
| Digital PR — journalist outreach · 7 | |
| discover_press_contacts | Find journalist and outlet contacts by searching with a real browser plus a semantic classifier — reading only the pages a publication put up for pitching, never a personal profile. Saves them as leads; makes no external contact. |
| generate_press_pitches | Research sourced, newsworthy angles about the workspace and draft them. Every citation is checked against what was actually scraped, never invented. Makes no external contact. |
| list_press_pitches | The generated pitch angles for the workspace. |
| send_press_pitch | Personalise a pitch for one or more journalist leads and queue each send to the press approval queue. Does not dispatch directly by default — a workspace that has earned auto-send sends immediately, and the response says which happened. |
| get_press_campaign_status | One campaign’s coverage status, reply disposition, coverage URL and running conversation summary. |
| list_press_approvals | Pending press approvals awaiting human review — both initial drafts and drafted replies to a journalist’s response. |
| decide_press_approval | Reject a pending press approval. Approving sends the email, so it is a human decision made in the dashboard — over MCP, approve returns an error with the link. |
| Phone numbers & verification — owner/admin key · 12 | |
| list_phone_numbers | The workspace’s numbers — live, in carrier review or suspended — with credits per month, plus recent approvals and rejections. |
| search_available_numbers | Numbers you can buy in a country, the monthly price, and what the carrier still needs. Buys nothing. |
| buy_phone_number | Buy one. Spends credits; idempotent on the key you send. Where the carrier verifies, it is reserved until approved, and refunded if not. |
| release_phone_number | Give a number back. Irreversible; needs confirm: true. |
| get_number_requirements | What a country’s carriers verify — fields, address rule, documents — and where the workspace stands. |
| get_verification_status | Carrier review per country: draft, in review, approved or rejected with the reason. |
| get_verification_details | The profile, addresses and documents on file. Files are never returned. |
| save_verification_profile | Who is behind the numbers — a business or an individual — and the legal fields. |
| save_verification_address | An address for verification, one per country. |
| delete_verification_address | Remove a saved address. |
| upload_verification_document | Upload a PDF, JPG or PNG (base64, up to 5 MB), checked to be what it says before it is sent. |
| delete_verification_document | Remove an uploaded document. |
Guardrails
The agent gets the same gate you do
An agent holding a key is not a privileged caller. It reaches the product through the controller the dashboard reaches it through, and the queues are the same queues.
A tools/call, in full
Enforced server-side at /api/mcp — not by a client library you could swap out.
Press pitches run on a separate queue, and a trust ladder
FAQ
What agent developers actually ask.
Agent-native
Point your agent at one endpoint.
60 tools, one workspace per key, and a queue that does not move because the caller was a model.
Free to start · Approval on by default · No card required