Make your API usable by every AI assistant, safely.
Your customers are starting to work through AI assistants. MCPcast turns the OpenAPI document you already have into a reviewed MCP server in one command: a small set of tools an agent can actually use, human approval on anything that changes data, and a score that tells you it works before you ship it.
Your users have AI assistants. Your API is not ready for them yet.
An OpenAPI document describes everything your API can do: hundreds of operations, developer prose, parameters nobody sets. Hand that to a model and it picks the wrong call, invents identifiers, and deletes something on a Tuesday.
Any MCP client
Claude Desktop, Claude Code, Cursor, or your own build_agent(). Stdio and HTTP/SSE, nothing bespoke.
Safe by default
Read-only unless you opt in, and every non-read tool waits for a human, enforced by the server rather than by a prompt.
Code you own
An installable package with its own tests, Dockerfile and README. No runtime dependency on a hosted service.
Designed, gated, and yours
MCPcast designs the small surface an agent needs, gates everything that changes data behind a human, and writes it as a project you can read, edit and ship. The plan file is yours; the server is generated from it, every time.
Automation where it is safe, your judgement where it counts.
Code does the deterministic work. A model designs the surface under rules code enforces. You review the plan before a single file is written.
Every operation, with where each value travels
A file, a URL, or an API running on your machine. OpenAPI 3.x and Swagger 2. Local $refs inlined (cycle- and depth-guarded), parameters resolved to their wire location — path, query, body — security schemes read, deprecations kept. Hostile documents fail with one actionable error, never a traceback: alias bombs, 300-level nesting and 20 MiB specs are refused before they cost you anything.Done by: code
promptise mcpcast https://api.acme.com/openapi.json
promptise mcpcast ./openapi.yaml
promptise mcpcast # detects an API running locallyReview every tool before a customer’s agent can call it.
A model designed this surface, so it will misread something. In our own documented run it wrote “use delete_ticket instead” into the description of a tool the safety profile had excluded, and hid a parameter users need behind a default.
The warnings are computed, not guessed
A description that names a tool this plan does not expose, parameters sent as fixed defaults, examples that teach the wrong identifiers. Each is a one-line fix in mcpcast.plan.yaml, after a human has read it.
- --review on the command line
- the guided setup’s review workspace
- the plan file in your editor
! find_ticket: the description names delete_ticket,
refund_ticket — not exposed by this plan, so the agent
will look for a tool that does not exist
! open_ticket: hides priority (sent as a default) —
fine unless your users need to set it
! get_customer: the example uses cust_123, which your
API does not recognise
→ fix in mcpcast.plan.yaml, then regenerateWhat an agent may do is your decision, not an accident.
The safety profile decides which risk classes become tools at all. Everything that is not a read waits for a human, enforced inside the server for every MCP client.
--profile read-only
Only reads are generated. Writes, deletes and anything financial are left out of the server entirely — an agent cannot call what does not exist.
--profile standard
Writes are generated and every one of them is approval-gated, enforced by the server for any MCP client. Destructive and financial operations stay out.
--profile full
Destructive and financial operations too — each one gated. You opt in explicitly, and the plan records the risk class next to every tool.
Tool counts are from an example helpdesk API.
A gate in the request pipeline
The gate is middleware in the server’s own request pipeline, so it applies to every client, not only to agents you built. Over stdio the client asks its user through MCP elicitation. In a multi-tenant deployment a second person of the same tenant decides, four-eyes.
Fail closed
A client that cannot ask, a reviewer who declines, a decision that never comes: all end the same way with APPROVAL_DENIED, and nothing is sent upstream.
agent → close_ticket(ticket_id=2)
│
gate → "Approve close_ticket(ticket_id=2)?"
│
declined → APPROVAL_DENIED · 0 requests upstream
approved → POST /tickets/2/close · 200Control whose credentials reach your API.
Four deployments, one flag. The generated server presents the credential where your spec’s security scheme puts it: an Authorization header, a custom header, or a query key.
Personal — a desktop client
One credential from MCPCAST_UPSTREAM_TOKEN, presented where the spec’s security scheme puts it: the Authorization header, or the custom header or query parameter an apiKey scheme names. Claude Desktop, Claude Code and Cursor launch it over stdio. Because it carries one shared secret and authenticates nobody, it binds loopback only unless you pass --public behind a gateway.
Nothing is echoed
A credential is validated when read and never appears in an error message, not even when the upstream quotes it back in a 401 body.
No accidental exposure
Modes that carry one shared secret bind loopback only. Publishing one takes an explicit --public behind a gateway.
Bounded by default
Response size caps, a wall-clock deadline per call, retryable 408/425/429 with Retry-After, and structured UPSTREAM_* errors an agent can act on.
No plain-http leaks
A credentialed call to a non-loopback http:// host is refused unless you say you mean it.
From spec to server in one guided session.
A full-screen terminal wizard finds the API already running on your machine, explains each decision next to the choice, shows how many tools each profile would produce, opens a review workspace before anything is written, and ends by printing the exact non-interactive command, so the second run is a script.
API spec
A file, a URL, or an API detected on this machine.
Model
A model designs the tools, or run fully offline.
Safety
Read-only, standard or full, with live tool counts.
Auth
Personal, shared, multi-tenant or local demo.
Project
Name, folder, tool budget, evaluation.
Review
Every tool, with warnings computed from the plan.
Write
The project, and the command that reproduces it.
3 · What may an agent do?
▸ read-only 5 tools · reads only
standard 8 tools · 3 require human approval
full 11 tools · 6 require human approval
── Explain ─────────────────────────────────────
Counted from your spec, not from a brochure.
Anything that changes data is generated only if
you ask for it — and then it is approval-gated.
↑↓ choose · enter continue · esc back · f1 helpKnow an agent can use it before you launch.
--eval writes tasks from your plan, runs a real agent against the full server pipeline and grades the run A to F: the right tool first, valid arguments, tools no task could reach, examples the API does not recognise.
The report names the fix, not the symptom
Edit the plan, regenerate, run it again, and watch the number move. That is the loop: review, fix, measure.
Agent Readiness: B (6/8 tasks succeeded)
correct tool first: 88% · parameter errors: 12%
t1 find_ticket ✓
t2 get_customer ✗
t3 list_orders ✓
t4 create_ticket ✓
✗ find_ticket, get_customer called the API with
identifiers it does not recognise — replace the
example values in the plan with ones that existWhat lands on disk
A package you could have written by hand. It depends on promptise and httpx, nothing else.
helpdesk-mcp/
├── mcpcast.plan.yaml the source of truth — you edit this
├── server.py python server.py · promptise serve
├── helpdesk_mcp/
│ ├── __init__.py build_server()
│ ├── __main__.py --transport stdio | http | sse
│ ├── config.py the plan's constants + MCPCAST_* env
│ ├── upstream.py the HTTP client: routes, credentials
│ ├── approval.py the human approval gate
│ ├── server.py where the pieces meet
│ └── tools/
│ ├── tickets.py @server.tool per resource, with ROUTES
│ └── customers.py
├── tests/ a pytest suite: listed · routed · gated
├── pyproject.toml pip install -e . → the helpdesk-mcp command
├── Dockerfile non-root, slim, no baked-in config
├── .env.example every variable, with what it does
└── README.md install snippets for each MCP clientRegeneration is safe
Everything derived is rewritten from the plan. A module you wrote by hand is never overwritten: regeneration refuses and names the file.
Tests that mean something
Every tool is listed, every route reaches the right method and path against a fake upstream, and every gated tool is denied when the human says no.
Clean under your tools
ruff, ruff format and mypy pass on the generated tree, with its own pinned lint rules.
Ship it anywhere
stdio for desktop clients, HTTP for shared deployments, a Dockerfile for your cluster, and promptise serve when you want the framework to host it.
From OpenAPI to an agent using your API.
pip install promptise, then run promptise mcpcast. Point it at a spec, read what it decided, fix what it got wrong, and hand the result to Claude Desktop. The plan stays yours.