S
supero.docs
Developers/MCP/MCP Tools & Protocol Reference

MCP Tools & Protocol Reference

Every JSON-RPC method, resource, and tool the Supero MCP server exposes — generic CRUD, schema, SDK, RBAC, and connector tools, plus the full build_* App Builder family — with request/response shapes and the two most common failure modes.

Overview

For the catalog services reachable over MCP and what each one expects, see MCP Integration Services.
The Supero MCP server exposes the platform to any MCP-capable client (Claude Code, Cursor, GitHub Copilot, or a custom agent) over a single Streamable HTTP endpoint speaking JSON-RPC 2.0. This page is the tool-by-tool reference: every protocol method, the schema resource, and every tool family the server advertises in tools/list, grouped by prefix. For connecting an editor and a first walkthrough, see Connect Your AI Editor over MCP — this page assumes you're already connected and want the full surface.
DetailValue
TransportStreamable HTTP, single endpoint
EndpointPOST https://api.supero.dev/mcp/v1/messages
Unauthenticated checksGET /mcp/v1/health, GET /mcp/v1/info
Protocol version2025-03-26 (2024-11-05 still accepted)
serverInfo.namesupero
AuthAuthorization: Bearer <jwt> OR X-API-Key: <api_key>
bash
# Unauthenticated connectivity check
curl https://api.supero.dev/mcp/v1/info
json
{
  "name": "supero",
  "version": "2.0.0",
  "protocol_version": "2025-03-26",
  "supported_protocol_versions": ["2025-03-26", "2024-11-05"],
  "transport": "streamable-http",
  "endpoint": "/mcp/v1/messages",
  "authentication": {
    "methods": ["bearer", "api_key"],
    "bearer": { "header": "Authorization", "format": "Bearer <jwt_token>" },
    "api_key": { "header": "X-API-Key", "format": "<api_key>", "note": "Create API keys in Supero dashboard" }
  },
  "capabilities": { "tools": true, "resources": true, "prompts": true }
}

ℹ️ No domain in the URL

There is no domain segment anywhere in the MCP path. Every request is a POST to the same /mcp/v1/messages endpoint; domain, project, and tenant scope are derived entirely from the credential you send. A request with no resolvable domain is refused with a JSON-RPC error before any tool runs.
Requests are capped in size (a JSON-RPC body over roughly 12 MB is rejected before it's fully buffered) — this exists so build_publish and build_validate can carry a whole app bundle inline. Keep an authored bundle text and under about 8 MB; for anything larger, stage it out-of-band first (see Authoring & publishing a bundle below).

JSON-RPC Methods

Every request is a standard JSON-RPC 2.0 envelope: {jsonrpc:"2.0", id, method, params}. The server routes on method — these are the ones it implements.
MethodPurpose
initializeClient handshake. Returns protocolVersion, capabilities (tools, prompts, and resources when the schema reference is available), and serverInfo.
notifications/initializedClient → server notification after initialize. No response is sent (the server returns an empty body / HTTP 202).
tools/listReturns every tool advertised for your credential — generic CRUD, schema_*, sdk_*, rbac_*/apikey_*, connector_*, and (if App Builder is enabled) the build_* family.
tools/callInvoke one tool by name with an arguments object. Returns {content:[{type:"text", text:...}], isError}.
resources/listLists readable resources — currently the schema reference.
resources/readFetch a resource's content by URI.
prompts/listLists server-defined prompts — currently start-supero-build.
prompts/getFetch a named prompt's message content.
pingLightweight keep-alive inside an active session; returns an empty result.
json
// initialize request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "clientInfo": { "name": "my-agent", "version": "1.0.0" }
  }
}

// initialize response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": { "tools": {}, "prompts": {}, "resources": {} },
    "serverInfo": { "name": "supero", "version": "2.0.0" },
    "instructions": "You are connected to the Supero Platform MCP server. ..."
  }
}
json
// tools/call request
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "crud_search",
    "arguments": { "object_type": "customer", "filters": { "status": "active" }, "limit": 20 }
  }
}

// tools/call response
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [ { "type": "text", "text": "Found 3 results:\n[ ... ]" } ],
    "isError": false
  }
}

💡 isError, not HTTP status

A tool failure is not an HTTP error — the call still returns 200 with a JSON-RPC result. Check result.isError (true when the underlying call failed) rather than the transport status code.
The initialize response's instructions field carries the server's operating contract for your agent in plain text — work only through MCP tools and resources, never scan or infer from local project folders or a stale local SKILLS.md copy, treat the API key as the sole source of project scope, and deploy only through build_go_live (permanent) or build_deploy (a short-lived managed preview) — never by running the app on your machine and exposing it through a tunnel. Most editors surface this automatically; the start-supero-build prompt below exists for the ones that don't.

Resources & Prompts

Schema reference resource

resources/list returns a single resource — the Schema Definition Language reference — whenever the server has a schema model loaded. Read it before authoring any schema: it covers the field/reference/parent_type model, reserved names, and validation rules in full.
URImimeTypeContents
supero://schema/referenceapplication/jsonComplete SDL reference: architecture, parent_type decision guide, reserved names, system fields, validation rules, example schemas.
json
{ "jsonrpc": "2.0", "id": 3, "method": "resources/read", "params": { "uri": "supero://schema/reference" } }

start-supero-build prompt

prompts/list advertises one prompt, start-supero-build. It's a containment path for editors (some IDE integrations) that don't surface the initialize handshake's instructions to the model — calling prompts/get for it returns the same operating contract as a plain user-role message, so the agent gets it either way.
json
{ "jsonrpc": "2.0", "id": 4, "method": "prompts/get", "params": { "name": "start-supero-build" } }

Generic CRUD Tools

Five generic tools cover every object type in your domain instead of one tool per schema — this keeps tools/list small and fast. Each takes an object_type argument naming the schema (a domain type like customer, invoice, or vehicle, or a system type). Under the hood, crud_search maps to a search_{object_type} call and so on, so the semantics match the REST CRUD API exactly.
ToolRequired argsOptional argsWhat it does
crud_searchobject_typefilters, limit, offset, detail, tenantSearch/list objects of a type. detail (default true) includes full object data; set it false for a lighter listing.
crud_getobject_type, uuid—Get one object by UUID.
crud_createobject_type, nameparent_type, parent_fq_name, data, tenantCreate an object. fq_name is auto-constructed from session context when omitted.
crud_updateobject_type, uuid, datatenantUpdate an object's fields by UUID.
crud_deleteobject_type, uuidtenantDelete an object by UUID.
System object_type values available in any domain: project, tenant, user_account, api_key, connector, audit_log, schema_registry, client_sdk, connector_execution, connector_plugin. Domain (app) types vary per domain — call schema_list to discover yours.

💡 Seeding a specific tenant

Pass an explicit tenant name (not UUID) to crud_search/create/update/delete to target a named tenant in a multi-tenant app instead of the session's default tenant — useful for seeding or verifying one tenant's data from a domain- or project-scoped key. Omit it for single-tenant apps.

⚠️ Tenant-scoped search needs project scope

A tenant-scoped crud_search fails with a clear error on a domain-wide (unscoped) session — the tenant can't be resolved without a project in scope. Use a project-scoped API key, or omit tenant and let the session default apply.

Platform Tool Families

Beyond generic CRUD, tools/list advertises four more families, gated on by default. Names are always prefixed by family: schema_, sdk_, rbac_/apikey_, and connector_.

Schema tools (schema_*)

ToolRequired argsWhat it does
schema_list—List every schema registered in the domain.
schema_getschema_uuidFull definition of one schema, including all fields.
schema_validateschemas[]Validate schema definitions before saving — checks conflicts, circular dependencies, reserved names, and parent_type correctness.
schema_saveschemas[]Save flat schema objects (not wrapped in schema_content). Optionally pass project_uuid to auto-link the saved schemas.
schema_deleteschema_uuidDelete a schema. force_delete overrides dependency checks.
schema_list_project—List schemas linked to a project (defaults to the key's project when resolvable).
schema_updateschema_uuid, schema_contentUpdate an existing schema's definition.
project_link_schemasproject_uuidLink existing schemas (by UUID or by name) to a project.
json
{
  "schemas": [
    {
      "name": "product",
      "description": "Product catalog entry",
      "parent_type": "tenant",
      "prefix": "prd",
      "plural_name": "products",
      "namespace": "<project_schema_namespace>",
      "attributes": [
        { "name": "title", "type": "string", "required": true },
        { "name": "price", "type": "float" },
        { "name": "stock", "type": "integer" }
      ]
    }
  ]
}

SDK tools (sdk_*)

ToolRequired argsWhat it does
sdk_generate—Generate client SDKs for the domain's schemas. Python and JavaScript are the languages that actually build. Other values (java, go, cpp) are accepted and reported as queued, but produce no artifact — the build falls back to Python and JavaScript.
sdk_statusrequest_idPoll an SDK generation request started by sdk_generate.
sdk_list—List SDKs already generated for the domain, optionally filtered by language.
sdk_downloadsdk_uuidGet a signed download URL and filename for a generated SDK (wheel, source, or docs artifact).

RBAC & API-key tools

ToolRequired argsWhat it does
rbac_get_my_access—The current credential's role, permissions, and scope.
rbac_check_permissionpermissionCheck whether the caller holds a specific permission (e.g. schema:manage, data:write).
apikey_get_scope—Scope and permission summary of the API key used for this call.

Connector tools (connector_*)

These operate an already-configured connector — trigger it, watch it, or test it. They're the orchestration layer underneath a connector, distinct from the App Builder's build_connect_data_source / build_bind_data_source flow (below), which is how an app first wires up an external source.
ToolRequired argsWhat it does
connector_runconnector_idTrigger a manual sync execution.
connector_cancelconnector_id, execution_idCancel a running execution.
connector_statusconnector_idGet status and recent executions.
connector_enableconnector_idEnable a connector for scheduling.
connector_disableconnector_idDisable a connector.
connector_discoverconnector_idTrigger schema/metadata discovery.
connector_discover_statusconnector_id, execution_idPoll a discovery execution's status.
connector_discover_resultsconnector_id, execution_idFetch discovery results.
connector_test_configconfigTest a connector configuration before creating it.
connector_testconnector_idTest an existing connector's connectivity.
connector_plugins—List available connector plugins.

App Builder Tools (build_*)

The build_* family is the App Builder: author a Supero app with your own agent, then validate, publish, and deploy it entirely over MCP. It's enabled per deployment; when it is, tools/list includes it alongside the generic tools above. A domain-admin API key can create projects and build into any project in the domain; a project-admin key can build into that one project only; a tenant-scoped key cannot run build tools at all.

Identity, discovery & planning

ToolWhat it does
build_whoamiResolve your key's role, domain, plan, and what you're allowed to do. Call this first in every session.
build_list_projectsList projects you can build into: uuid, name, schema_namespace, live_url.
build_get_projectOne project's schema_namespace (use this exact value as every schema's namespace), last published version, and its captured project intent (brief, discovered data model, landing intent).
build_get_skillsFetch a build reference doc: skills (the spec, default), components, rubric, landing, integrations, web, transactional, workflows, mobile, services, e2e_testing, or connectors. Long docs are paginated — fetch the next offset rather than re-fetching from the start.
build_get_examplesFetch a complete reference app (schemas.py, config.py, setup.py, ui/app.js) to copy patterns from. archetype selects commerce-marketplace, service-booking, ops-dashboard, multitenant-portal, or saas-billing; index (default) lists them.
build_planTurn a one-line app idea into an explicit build checklist — page structure, which entities need a detail page, the multi-tenant login pattern, and seed guidance — before authoring anything.
build_get_service_contractThe authoritative state machine, operations, required fields, and default UI schemas for a transactional platform service (cart, order, booking, payment, membership, and more) your app extends. Call before authoring UI for any extended service.

Project lifecycle

ToolWhat it does
build_create_project(domain-admin) Create a new project. Mints its schema_namespace and an API key, returned once.
build_update_projectUpdate project metadata: display name, description, public listing, live_url.
build_set_project_modeSet a project's mode: dev (default; allows a full replace) or live (protected).
build_replace_projectDestructive, domain-admin only: wipe a dev-mode project's data (credentials, API keys, namespace, and tenant are retained) and optionally publish a fresh bundle after. Refused on a live-mode project; requires the project name as a confirmation.

Build, validate & publish

ToolWhat it does
build_validateValidate an authored bundle against the live platform: manifest, syntax, import-safety, config exports, schema validity, and that every schema's namespace matches the project's. AST-only — your code is never executed.
build_publishPackage and upload the bundle, recording a new version. Runs build_validate first unless force is set. Returns version_uuid, file_id, and download_url.
build_stage_bundleGet an out-of-band upload URL for a bundle too large to send inline; pass the resulting file_id as files_ref to build_validate / build_publish / build_doctor.
build_get_bundleFetch the current (or a given) published bundle's file list and download URL, or one file's content inline. Start any change request here rather than re-authoring from scratch, so hand-tuned files aren't dropped.

Deploy & operate

ToolWhat it does
build_deployDeploy a published version. target: local (default when cloud deploy isn't available) hands back run instructions using the project's own key; cloud_ephemeral is a short-lived managed preview.
build_deploy_statusPoll a deploy started by build_deploy or build_go_live using its poll_url. A launch still pending after roughly five minutes should be treated as failed.
build_logsFetch recent logs for a deployed app — the tool for diagnosing a stalled or crashing deploy. Read-only and rate-limited per domain.
build_go_livePromote a published version to a permanent public URL at <project>.supero.live. Returns public_url and a poll_url; poll with build_deploy_status, then run build_smoke_test against the public URL.
build_teardownTear down a project's live deployment (permanent or ephemeral) and free its URL. Idempotent.

Quality gates

ToolWhat it does
build_doctorPreflight a bundle before publish/deploy for issues build_validate doesn't catch: a missing loading-splash removal, a heavy startup seed that can blow a deploy's startup timeout, reserved field names, namespace collisions, and services that need elevated import permission.
build_smoke_testVerify a deployed app actually works: the page loads with a title, app.js is your bundle (not a stub) and dismisses the boot splash, config.js's namespace matches the project, and — optionally, given a test login — that data reads back correctly. Run after every deploy.
build_e2e_testRun the full behavioral test suite (auth/RBAC, CRUD round-trips, workflows and event emission, services, aggregates, real-browser UI) against a project's own deployed app. Write-safe: a dev project's write suites touch only their own test records; a live project auto-restricts to read-only suites. Async — returns a run_id.
build_e2e_test_statusPoll an e2e run for its report: verdict, per-suite pass/fail/warn/skip, findings with a fix hint, and what was and wasn't covered.

Integrations & services

ToolWhat it does
build_list_capabilitiesList the live services catalog (email, sms, payment, oauth, and more) with each entry's exact service_id, category, and your connection's permissions. Descriptive — what exists, not what to use.
build_recommend_integrationsGiven an app description and the platform services it uses, return tiered (required/recommended/optional) integration suggestions drawn only from the live catalog. Prescriptive complement to build_list_capabilities.
build_configure_servicesConfigure a service's keys for the project. Test/sandbox keys only — a key with a clear live marker is auto-refused; secret values are never echoed back.

External data sources

ToolWhat it does
build_list_data_sourcesList connectable external source types: your own database, a REST API, or a warehouse, plus a curated public-API catalog.
build_connect_data_sourceCreate a connector to an external source you control. Returns a connector_id. Credentials are sent to the platform and never echoed back.
build_discover_sourceDiscover a connector's schema: source streams (names, columns, primary keys), AI-inferred Supero schemas, field mappings, and a suggested namespace. Run before binding.
build_bind_data_sourceBind discovered streams to app schemas. mode: live_read (default, read-only), live_readwrite (domain-admin only), or sync (copy into Supero-managed storage).
build_run_data_sourceTrigger a sync run on a connector and return the run id.
build_list_bound_schemasClassify a project's schemas as app-authored vs. connector-backed, with each one's access mode (sync, live-read, live-readwrite, or warehouse).

Authoring & Publishing a Bundle

Send an app bundle as a flat {relative_path: content} map — a leading folder like myapp/ is stripped automatically. Author at least schemas.py, config.py, setup.py, __main__.py, requirements.txt, run.sh, and ui/app.js, per the skills doc from build_get_skills.

⚠️ Files the platform generates for you

Do not ship .env, ui/index.html, ui/config.js, ui/server.py, or a Dockerfile — the SDK CLI generates these, and they're dropped if you include them. Never inline an API key or a private key anywhere in the bundle.
  • •Set every schema's namespace to the project's exact schema_namespace from build_get_project — the platform registers schemas under that value, and a mismatch fails build_validate.
  • •build_validate and build_doctor are AST-only checks; your code is never executed on the platform.
  • •build_publish runs build_validate first unless you pass force:true.
  • •A bundle too large to send inline (or truncated by your model's own output-token cap) should go through build_stage_bundle: upload a compressed {path: content} blob to the returned URL with your own key, then pass the returned file_id as files_ref to build_validate / build_publish / build_doctor instead of files.
json
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "build_validate",
    "arguments": {
      "project_uuid": "<project_uuid>",
      "files": {
        "schemas.py": "...",
        "config.py": "...",
        "setup.py": "...",
        "__main__.py": "...",
        "requirements.txt": "...",
        "run.sh": "...",
        "ui/app.js": "..."
      }
    }
  }
}

💡 Updating an existing app

To change a published app, fetch its current files with build_get_bundle and edit those — don't re-author from scratch, which silently drops hand-tuned UI and prior fixes. The cycle is: edit locally → build_validate → build_publish (bumps the version) → build_deploy or build_go_live.

Troubleshooting

Key bound to a project that no longer exists

A project-admin API key is bound to the project it was minted for, and that binding is fixed at mint time — it does not follow a later rename or recreation of the project. If the project was renamed or recreated after the key was minted, every project-scoped call (build_get_project, build_get_bundle, build_publish, build_deploy) is denied even though the key itself is still valid.
build_whoami reports this directly via project_binding: ok means the key's project label matches a live project; unresolved means it doesn't — the key authenticates but every project-scoped call will fail; unknown means the check couldn't run (a transient read failure).
json
{
  "role": "project_admin",
  "project_scope": "project",
  "project_name": "acme-crm",
  "project_binding": "unresolved",
  "binding_error": "This key is scoped to project 'acme-crm', which does not exist in this domain. The project was renamed, recreated, or deleted after the key was minted."
}

⚠️ Don't rotate — mint a new key

Rotating a stranded key reproduces the exact same stale binding, because rotation rebuilds the key from the same stored project label. Mint a brand-new API key against a project that appears in build_list_projects (from the project's settings in the Supero dashboard) instead.

Named-tenant users get "User not found" on login

In a multi-tenant app, each user lives inside a named tenant. Login must resolve that tenant server-side rather than assume a fixed one — pass an empty string as the tenant argument so the server looks up the user's own tenant by email, and add a tenant/workspace picker in your UI if you want the user to choose explicitly.
javascript
// Correct — server resolves the user's own tenant by email
client.login(domainName, email, password, projectName, '')

// Wrong on a multi-tenant app — force-scopes login to one fixed tenant
client.login(domainName, email, password, projectName, cfg.tenant)

🚨 Why cfg.tenant breaks this

On a managed cloud deploy, a client-side cfg.tenant typically resolves to the single default tenant regardless of which named tenant a user actually belongs to. Passing it as the login tenant force-scopes every login to that one tenant, so any user who lives in a different named tenant gets a 401 "User not found" even with the correct password. Always default the login tenant argument to an empty string and let the server resolve it.

Next steps

  • •Connect Your AI Editor over MCP — connecting Claude Code, Cursor, or GitHub Copilot, and a guided first build session
  • •Authentication — how login, JWT refresh, and API keys work across the REST API and MCP
  • •Schema API — the fields/references/namespace model your agent authors schemas.py against
  • •CRUD Endpoints — the REST endpoints a deployed app's UI (and your own scripts) call directly, mirrored by the generic crud_* tools