Sobmit as an MCP server
Sobmit is not just an MCP client — it can be consumed as an MCP server. An external agent (Claude Desktop, Cursor, or any MCP 2026-07-28 client) can discover Sobmit as a protected resource, authenticate with OAuth 2.1, and then build, read and validate flows on your behalf.
Endpoint
The MCP server is served over a stateless JSON-RPC POST endpoint:
POST /api/mcp It implements the MCP 2026-07-28 protocol (createMcpHandler from the official
SDK v2), constructing a fresh server per request so tool definitions are always
backed by the current authenticated user.
Discovery (RFC 9728)
An MCP client discovers the server through its protected-resource metadata, served at the well-known root:
GET /.well-known/oauth-protected-resource This document is what the 401 WWW-Authenticate challenge points to via its resource_metadata field, so a standards-compliant client finds the
authorization server and token endpoint without manual configuration.
Authentication — OAuth 2.1 authorization-code flow + PKCE
Access is granted with the standard OAuth 2.1 authorization-code flow with PKCE (RFC 7636). The flow:
- Authorization request — the client redirects the user to
/oauth2/authorizewithclient_id,scope,redirect_uriand the PKCEcode_challenge. - Consent — if the user has not already consented, Sobmit shows a consent
screen at
/consentnaming the requesting client and the scopes it asks for. The user approves or denies. - Authorization code — on approval, the browser is redirected back to the
client’s
redirect_uriwith a one-timecode. - Token exchange — the client exchanges the code (plus its PKCE
code_verifier) for an access token at the token endpoint. - Access — the client calls
POST /api/mcpwith the bearer access token.requireMcpAuthverifies the token (issuer, audience, expiry) against the authorization server’s JWKS and maps it to the authenticated user.
The signing key is published at:
GET /jwks Access tokens are audience-bound to the /api/mcp resource and scoped to
the specific user who consented — a client can only act on that user’s flows.
Static token (for clients without OAuth)
Not every client speaks OAuth 2.1 with PKCE. For those, Sobmit issues a personal access token (PAT) — a static bearer token scoped to your account that you paste into the client once:
Open Account → API in Sobmit and create a token (give it a name, e.g.
vryne.com) and choose its permissions:- Run only (default, recommended) — trigger your flows and read their results, but cannot create, edit or delete flows.
- Full access — everything, including creating/editing flows.
The full token is shown exactly once — copy it then.
In the client, configure Sobmit as a remote MCP server with:
Endpoint: https://www.sobm.it/api/mcp Authorization: Bearer <token>The client sends
Authorization: Bearer <token>on every request. Sobmit maps the token to its owning account (hashed at rest) and enforces the token’s permission level — a “run only” token can start your flows and read results, but has no way to change them.
The PAT path speaks the stateless MCP profile: plain JSON-RPC POSTs
(initialize → tools/list → tools/call) with application/json / text/event-stream responses, and accepts an optional mcp-session-id header. Protocol 2025-06-18 and the 2025-era revisions are negotiated
automatically, so older streamable-HTTP clients work without extra setup.
Available tools
The server exposes these tools, all scoped to the authenticated user. Tools
marked edit are only available to a full-access token (or an OAuth
login); a run-only token sees only the read/trigger tools.
| Tool | Purpose | Requires |
|---|---|---|
list_node_kinds | Every addable node kind and its default data shape | run |
list_flows | The user’s flows (id, name, updated) | run |
get_flow | A flow’s full project graph by id | run |
validate_flow | Validate a flow and return any problems | run |
run_flow | Run a stored flow and wait for its output | run |
get_run | Poll a running flow’s status/result by run id | run |
get_flow_guide | The flow-building manual (see below) | run |
create_flow | Create a new flow from a name | full (edit) |
create_flow_from_project | Create a flow from a whole project document | full (edit) |
add_node | Add a node to a flow | full (edit) |
update_node | Update a node’s data in a flow | full (edit) |
remove_node | Remove a node from a flow | full (edit) |
add_edge | Connect two nodes | full (edit) |
remove_edge | Disconnect two nodes | full (edit) |
set_variables | Replace a flow’s [NAME] user inputs | full (edit) |
add_canvas_note | Write a heading or paragraph on the board | full (edit) |
add_comment | Pin a review note to a node | full (edit) |
Start with get_flow_guide
Building a flow from list_node_kinds alone produces something that runs but is
subtly wrong — the node shapes are there, the conventions are not. The guide
tool returns the same manual the in-app “Generate with AI” uses: every kind
with its exact data shape, the rules and three complete worked examples.
Call it once, before you design anything, and follow it:
- searching the web is a
websearchnode (orresearchfor a cited report), never anhttpnode pointed at a search API; - a router’s last edge carries no condition — it is the else branch;
- a node’s main-line payload carries only one upstream result, so a node
that must read several uses
{outputs.<nodeId>}templates in its own instructions; - a file input is an
uploadnode with empty data (the person running the flow picks the file), wired onto the reading node’sfilehandle; - a flow’s user inputs are
[NAME]tokens in a Prompt node plus a matchingvariablesentry — set them withset_variables; - finally set its description and add canvas notes, so the flow explains itself.
Two ways to create a flow
- Step by step —
create_flow, thenadd_node/add_edge, thenvalidate_flow. Good for a small flow, or when you want the user to watch it grow. - In one shot —
create_flow_from_projecttakes a complete project document (the same JSON the app exports and imports:type,version,name,description,graph,canvas) and creates the flow from it. It runs the app’s real importer, so a document that works when imported by hand works here, and it needs one call instead of dozens. Ask the user for an exported.flow.json, or build the document yourself from the guide.
run_flow is the tool for triggering a flow from another app and reading its
result: it starts a durable run of a flow you own (or edit), waits up to waitMs (default 120 000 ms), and returns { runId, status, output, executions, outputs } — where output is the final output node’s payload. If
the flow is still running after the wait, status is "running"; poll with get_run until it reaches "completed".
Each tool re-uses the same permission checks, header-sanitization and version snapshotting as the web app, so an agent gets exactly the behaviour (and the same safety) as a signed-in user in the browser.
Example — connect Claude Desktop
Add Sobmit as a remote MCP server in Claude Desktop, authenticating with OAuth. After consent, Claude can list your flows and build new ones:
"sobm.it" is an MCP server over OAuth — ask it to list_node_kinds first,
then create_flow + add_node to sketch a new automation. Related
- MCP servers — the reverse direction: calling external MCP tools from a Sobmit flow.
- Core concepts — flows, nodes and edges.