Coding agents keep hitting the same wall humans do: the frontend they're writing needs an API that doesn't exist yet. The usual agent workarounds are all bad β hardcode JSONPlaceholder (fixed schema, fake writes), generate an MSW handler file (more code to maintain, only exists inside the test process), or scaffold an Express server (now your "mock" has a package.json, a port, and a lifecycle).
Mockbird is a hosted mock REST API service, and it ships a hosted MCP server. Add one URL to your MCP client config and your agent gets eighteen tools that create and drive real, live mock backends: seeded multi-resource projects, OpenAPI/db.json/Postman/CSV import, record CRUD, custom routes, snapshots. No signup, no API key, no OAuth dance β the connection just works.
# Claude Code
claude mcp add --transport http mockbird https://mockbird.mockbird.workers.dev/mcp
# Cursor / Windsurf / any client that reads mcp.json
{ "mcpServers": { "mockbird": { "url": "https://mockbird.mockbird.workers.dev/mcp" } } }
# VS Code
code --add-mcp '{"name":"mockbird","type":"http","url":"https://mockbird.mockbird.workers.dev/mcp"}'
The transport is stateless Streamable HTTP (spec 2025-06-18; older
2025-03-26 and 2024-11-05 clients work too). No session juggling, no SSE requirement, no
server to install β it's the same Cloudflare Worker that serves the mocks. Mockbird is also
listed in the official MCP Registry as
dev.workers.mockbird.mockbird/mockbird.
| Tool | What it does | Needs adminKey? |
|---|---|---|
create_project | New mock API β blog / ecommerce / saas preset or blank. Returns {id, adminKey, baseUrl}. | β |
import_data | OpenAPI 3.x / Swagger 2.0, json-server db.json, Postman Collection v2.x, DevTools HAR, VCR cassette, bare JSON array, or CSV β live seeded API. Auto-detected. OpenAPI non-CRUD paths (login, search, RPC verbs) round-trip as custom routes serving the spec's own examples. | β |
fork_project | Copy a whole project (records verbatim, custom routes, settings) into a fresh one with its own id + adminKey. Pass ttl for a self-expiring fork (60 s β 7 days) β crashed eval/CI runs can't leak sandboxes. withSnapshots:true carries the template's answer-key snapshots along. {"project":"demo"} works with no key. | source's (not for demo) |
add_resource | Add a collection from a template (users, products, β¦) or explicit typed fields; seeds realistic fake records. | yes |
project_info | Root index: resources, record counts, URLs, export links. Works on demo. | no |
query_records | GET with the full query toolkit: filters, _gte-style operators, search, sort, pagination, select, relations, and failure simulation (mock_status, mock_delay, mock_chaosβ¦). | no |
write_record | POST / PUT / PATCH / DELETE β writes persist. | no |
generate_fake_data | Instant realistic fake data, stateless β ready-made shapes (persons, products, credit_cardsβ¦) or a custom {key: type} field map; pass seed for deterministic rows. No project needed. | no |
custom_route | Define /health, /config/:key, catch-all /webhooks/* bins, templated bodies. | yes |
snapshots | Save / restore / list / delete full-dataset snapshots β deterministic fixtures for the tests your agent writes. action:"diff" grades a run: compare an expected snapshot against live data (or another snapshot) and assert .identical. | yes |
verdict | The whole eval grade in one call: state check (snapshot diff vs live) + trajectory constraints on the request log → {pass, checks[]}. E.g. {"snapshot":"expected","trajectory":[{"method":"DELETE","count":0}]} β assert .pass. | yes |
inspect_requests | Read the request inspector: what your app / tests / webhook sender actually sent (method, path, headers, body snippet). Public on demo. | yes* |
share_project | Mint / rotate / revoke a read-only share link β a browser URL your human reviewer opens to browse the sandboxβs data, endpoints, snapshots and live request traffic. No writes, adminKey never exposed. | yes |
delete_project | Delete a project and all its data β clean up short-lived test projects when the session is done. | yes |
check_api_status | Live health of the ~37 public mock/testing APIs on the status tracker (httpbin, JSONPlaceholder, ReqResβ¦): summary of everything failing, or per-service detail with 24h/7d uptime and recent checks. Down services link the migration guide. | no |
uptime_monitor | Free downtime alerts for any public URL β checked every 30 minutes from Cloudflare's network; your webhook gets one message on down, one on recovery (debounced, so blips never fire). Includes a public status page + badge + Atom feed. | no (returns its own secret) |
heartbeat | Dead man's switch for cron jobs and recurring agent runs: the job pings Mockbird (a returned URL or the tool's ping action); a missed ping fires the alert webhook. Arm one for your own scheduled runs so a human hears when you stop running. | no (returns its own secret) |
watch_service_status | Subscribe a webhook to down / recovered events for any API tracked by check_api_status β or "*" for all of them. | no (returns its own secret) |
Every tool dispatches through the same code paths as the public HTTP API, so the
request inspector, daily caps, and anonymous per-IP limits apply
identically. The adminKey returned by create_project is shown once β
well-behaved agents save it into the project's .env.
The server also publishes MCP prompts β ready-made workflows your client
surfaces as slash commands (in Claude Code they appear in the / picker as
/mockbird:<name> (MCP)):
| Prompt | Argument | What it does |
|---|---|---|
mock_an_api | a plain-English description | creates the project, adds matching resources with realistic field types, verifies with real reads, hands you baseUrl + dashboard + a working curl |
mock_from_spec | an OpenAPI spec, db.json, Postman collection, HAR, CSV β or a URL to one | imports it as a live mock, reports warnings, verifies records survived |
simulate_failures | optional scenario ("retries on 503", "rate limiting"β¦) | builds the exact mock_status/mock_chaos/mock_seq/mock_ratelimit URLs for your test and demonstrates each failing response for real |
monitor_uptime | a URL (or a cron-job description) + a webhook | picks uptime_monitor or heartbeat, arms it, stores the credentials, and hands you the status page + badge + (for cron jobs) the ping line to append |
is_it_down | a public API name ("httpbin", "reqres.in"β¦) | reads the live status tracker, and if the service is failing, stands up a drop-in replacement and tells you what to change |
They're plain prompts/list + prompts/get under the hood β no client
lock-in, any MCP client that supports prompts gets them.
Prompt your agent with something like:
"Create an ecommerce mock API with Mockbird and point this app's
.env at it. Then write a Playwright test that checks the empty-cart
state using a snapshot."
A capable agent will: call create_project with preset: "ecommerce"
(one call β products, orders, customers, reviews, all seeded), write
VITE_API_URL=<baseUrl> into .env, call snapshots
with action: "save" after emptying the fixture data it needs, and pin that
scenario in tests via mock_snapshot=<name> in query_records
params β the same snapshot pinning humans use,
no restore races between parallel workers.
The important part: the mock itself stays plain HTTP. The code your agent writes ships with a working URL β you can curl it, open it in a browser, hand it to a teammate, or run CI against it after the agent session ends. The mock isn't trapped inside the agent's tool sandbox.
You can drive the whole thing from curl β useful for debugging what your agent sees:
# list the tools
curl -s -X POST https://mockbird.mockbird.workers.dev/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# call one: the shared demo project's index
curl -s -X POST https://mockbird.mockbird.workers.dev/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
"name":"project_info","arguments":{"project":"demo"}}}'
# query with projection + pagination
curl -s -X POST https://mockbird.mockbird.workers.dev/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{
"name":"query_records","arguments":{"project":"demo",
"resource":"products","params":{"_limit":2,"select":"name,price"}}}}'
All three run against the live server right now β the last one returns two products with
just id, name, price.
Honest answer: agents can already use Mockbird with plain HTTP β that's why
/llms.txt exists, and agent traffic does arrive that way. MCP adds
three things: discovery (the agent finds typed tools with descriptions instead
of reading docs into context), fewer tokens (tool results are trimmed and
capped at 50 KB, with a hint to use select/_limit when truncated), and
fewer mistakes (input schemas encode the gotchas β field types, which calls
need the adminKey β so the agent doesn't learn them by 400ing). If your agent runs fine on raw
HTTP, nothing forces the switch.
Limits, honestly: tool calls share the project's 10,000 requests/day cap and anonymous project creation is limited to 30/IP/day (the MCP server forwards your real client IP for caps β one shared egress IP for a big agent fleet will hit it). Responses are JSON only, no streaming. The server is stateless, so clients that require session-id handshakes fall back to sessionless mode per spec. And the data is mock-grade: this is for building against an API shape, not for storing anything you care about. Full reference in the docs.
More guides: using the sandbox for agent evals (snapshot episodes, inspector ground truth, chaos drills) Β· deterministic test data Β· mock server from an OpenAPI spec Β· testing loading & error states Β· free mock API tools compared. Create your API β