Documentation/Under the hood/Building an app over MCP: the 33 tools, in the order they run
Building an app over MCP: the 33 tools, in the order they run
An MCP server with 64 tools, 33 of them for building and deploying an app. The full catalogue is readable without an account. Here is what each phase does.
- mcp
- developer-tools
- api-keys
- deployment
- agents
Overview
You can read the entire tool surface before you have an account. Start there.
---
Run this. It needs no key and no client library:
bash
curl -s https://api.supero.dev/mcp/v1/messages \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'You get 64 tools back. Names, descriptions, argument schemas, all of it.
That is the whole surface.
Most vendors in this category will not let you see what their agent integration can do until you have signed up, and by then you have spent the afternoon. This article is the guided version of that response: what the 64 are, which 33 of them build an application, and the order they are meant to run in.
What the 64 break down into
The catalogue splits into two halves that do genuinely different jobs.
| Family | Count | What it is for |
|---|---|---|
| `build_` | 33 | Author, validate, publish, deploy and test a whole application |
| `connector_` | 11 | Drive external data sources: discovery, sync runs, connectivity tests |
| `schema_` | 7 | List, validate, save and update object types |
| `crud_` | 5 | Read and write records of any type |
| `sdk_` | 4 | Generate and download client SDKs |
| `rbac_` | 2 | Ask what the current credential may do |
| `apikey_` | 1 | Scope summary for the key making the call |
| `project_` | 1 | Link schemas into a project |
The 31 non-`build_` tools are for an application that already exists. You reach for them while operating one: reading records, checking what a credential may do, kicking off a connector sync, regenerating a client library after a schema change.
The 33 `build_` tools are what get an application to exist in the first place. A session that uses them tends to use them in one burst and then not again until the next version.
Different jobs, one endpoint.
The order
The server tells a connecting client what order to use, so in practice your editor already knows this. Knowing it yourself matters when a build goes sideways and you need to say which step lied.
Six phases.
**Find out who you are.** `build_whoami` resolves your key to a domain and a project, then reports the role and plan it landed on. Call it first.
A key has no permission level you set after the fact. Its reach is decided by where it was created — which domain, which project, which tenant — so the answer to "why can this key not see that project" is nearly always that it was created somewhere else.
**Learn the shape.** `build_get_skills` returns the spec. `build_get_examples` returns a complete reference application you can copy rather than invent. `build_plan` turns one line of intent into a checklist of pages and object types. `build_get_service_contract` hands back the authoritative state machine for a transactional service, with its operations and required fields set out. That is the same declaration that produces the error contract in A 409 should tell you what to do next. That is the difference between an agent guessing at an order lifecycle and reading it.
**Write seven files.** The validator looks for `schemas.py`, `config.py`, `setup.py`, `__main__.py`, `requirements.txt`, `run.sh` and `ui/app.js`. The first two are hard requirements and the rest are warnings, so a bundle can carry more and still pass. Your object types go in the first. Project identity and the services you import go in the second. Provisioning, seed data and workflow definitions go in the third, and `ui/app.js` is the shell resolver.
**Check before you ship.** `build_validate` runs the bundle against the live platform: manifest, syntax, imports. `build_doctor` looks for the class of problem validation does not catch. Then `build_publish` packages it and records a version. A bundle too large to send inline goes through `build_stage_bundle` and an out-of-band URL.
**Put it somewhere.** `build_deploy` for an ephemeral preview, `build_go_live` for a permanent public URL. Both return a poll URL rather than a finished deployment, and `build_deploy_status` is how you wait.
**Prove it works.** `build_smoke_test` checks the page loads, has a title, and is serving your `app.js` rather than a default. `build_e2e_test` runs a behavioural suite against the deployed thing — auth and RBAC, CRUD round-trips, workflows — and `build_e2e_test_status` returns a verdict with per-suite findings.
That last pair is the part that surprises people. The agent that wrote the application can run an authorisation test suite against the deployed result and read the failures, in the same session, without a human opening a browser.
Be careful with that rather than impressed by it. A suite written by the same system that wrote the code is not an independent check, and `build_e2e_test` is not that: it runs the platform's own behavioural contracts against your deployment, so it is testing whether your application honours the platform's rules, not whether it does what you meant. Those are different questions and only one of them is answered here. An agent that reports a green e2e run has established that auth works, that a create followed by a read returns the thing you created, and that a workflow you declared actually transitions. It has established nothing at all about whether the invoice total is right.
Three things that will surprise you
1. The catalogue is open. The data is not.
`tools/list` answers 200 to an anonymous caller. `tools/call` does not:
text
POST /mcp/v1/messages {"method":"tools/call","params":{"name":"rbac_get_my_access"}}
→ 401
{"error":{"code":-32001,"message":"Authentication required. Send an API key as
X-API-Key, or a JWT as Authorization: Bearer. See
https://docs.supero.dev/developers/mcp/overview."}}Discovery before authentication, invocation after it.
We think that is the right split for MCP, and it is why the `curl` at the top of this article works at all. An agent deciding whether a server is worth connecting to should be able to read what that server offers without first being issued a credential by a human, because the alternative is that every evaluation of every MCP server starts with a signup form and most of them never get evaluated.
The anonymous listing is filtered rather than raw: a prefix allow-list decides what an unauthenticated caller may see, and everything outside the customer-facing families is withheld from it regardless of any other setting. All 64 of the tools above sit inside the allow-list. That is why you see all 64.
2. A key's reach is fixed when it is created
There is no permission level on a key that you adjust afterwards. A key minted under a project reaches that project, and the only way to change what it reaches is to mint a different one.
This catches people out in a specific way. You create a key, the project gets renamed or recreated, and the key now carries a label that no longer matches anything. `build_whoami` reports whether that binding still resolves rather than echoing a project name that has stopped existing, which it used to do — and the old behaviour sent people off to re-mint keys that were authenticating perfectly well.
3. A slow deploy is usually not a failed deploy
`build_deploy_status` answers `launching` while a deployment settles, and the temptation is to put a short deadline on that and declare failure.
We tried exactly that, with a five-minute clock, and it tore down healthy applications. Cloud IAM propagation on its own can take six minutes, so a deployment that is entirely fine legitimately sits in `launching` past the five-minute mark. The ceiling is ten minutes now, and the rule is to **probe before concluding failure** instead of trusting the clock.
If you are driving this from an unattended loop, that distinction is the difference between a retry and an outage you caused yourself.
What this does not do for you
Permanent hosting depends on your plan, and `build_whoami` reports whether yours includes it. Check at the start rather than at the deploy step.
`build_replace_project` wipes a project's data and rebuilds in place. It is domain-admin only and refused on a project in live mode. Three things have to line up before that call runs at all: a domain-admin role, a project that is not in live mode, and a typed confirmation of the project name. That is deliberate, and it is what stands between a confused agent and a customer's production application.
And the generic tools are generic. `crud_search` reaches whatever the calling key's address reaches. It is the same boundary the REST API applies, evaluated in the same place. MCP is a transport onto the platform's existing authorisation, not a second one. If a key can read a record through the API it can read it through a tool, and if it cannot, the tool returns the same refusal.
Run the `tools/list` call at the top and read the four `sdk_` tool definitions for yourself.
One thing to know before you do: `sdk_generate` advertises a `languages` enum of python, javascript, java, go and cpp, and only the first two are implemented. Ask for Go and you get a `NotImplementedError`. That enum is wrong and it is ours to fix, and you would have found it in about ninety seconds, so you may as well hear it here first.
Then, if you want the other half, mint a key scoped to a project and ask your editor to call `build_whoami`. The answer it gives you is the answer to every scoping question you are going to have afterwards.
*(Disclosure: I work on Supero. The `curl` at the top runs against our production server and needs no account, so the first claim above is the one you are least required to take on trust.)*
On this page