MCP server
Connect Claude, Claude Code, Cursor or any MCP client to OrderLoop at /mcp, with the same tools as the assistant, limited by role.
OrderLoop serves its workspace tools to Model Context Protocol
clients at https://orderloop.app/mcp. They are the
tools of the assistant, so a client can check what needs attention, find and
read orders, and, with the right role, decide approvals or cancel orders. Each person is limited to
what their role allows.
The server is stateless: every request is answered by a fresh server that lists only the tools
the caller’s role can use. It speaks streamable HTTP, the draft 2026-07-28 revision of the
protocol and the 2025 stateless lane. Another agent that speaks Agent2Agent rather than MCP
connects at /a2a; see A2A endpoint.
Connecting
Section titled “Connecting”Claude and Claude Desktop
Section titled “Claude and Claude Desktop”Add a custom connector with the URL https://orderloop.app/mcp. The client discovers the
authorization server, registers itself and opens OrderLoop’s consent page in your browser:
- Sign in with your own account. Two-factor sign-in applies. The workspace password can’t connect an app, because an app’s actions must trace to a person.
- Check which app is asking and where access will be sent. An app that registered itself is marked as unverified; an app on your own computer gets an extra warning.
- Choose a role. You are offered your own role and the roles below it, lowest first, and the
lowest (
viewer) is selected. That role is the grant’s scope. - Select Connect. Cancel refuses the app.
Claude Code
Section titled “Claude Code”claude mcp add --transport http orderloop https://orderloop.app/mcpClaude Code runs the same browser flow the first time you use the server. To skip the browser, pass an API token:
claude mcp add --transport http orderloop https://orderloop.app/mcp \ --header "Authorization: Bearer ol_live_…"Cursor and other clients
Section titled “Cursor and other clients”A client that takes a URL and headers can send Authorization: Bearer ol_live_… with every
request. In Cursor’s mcp.json:
{ "mcpServers": { "orderloop": { "url": "https://orderloop.app/mcp", "headers": { "Authorization": "Bearer ol_live_…" } } }}A client that runs OAuth itself finds the authorization server from
/.well-known/oauth-protected-resource/mcp. It registers with dynamic client registration at
/oauth/register or with a Client ID Metadata Document (an https client_id), sends the person
to /oauth/authorize (authorization code with PKCE) and exchanges the code at /oauth/token.
A token carries the role it was created with and its expiry. /mcp accepts the same bearer
credentials as the REST API: ol_live_ tokens, and the workspace
password as a break-glass operator. These work on /a2a too. Wrong guesses are throttled (429 with Retry-After) and an expired token is
refused (401 with the reason), as there.
A client sees only the rows its role can use. Write tools are the ones the assistant stops to confirm; over MCP the client decides how to ask, using the annotations below.
| Tool | Role | Access | Does |
|---|---|---|---|
needs_attention | viewer (Viewer) | Read | What is waiting on people: open approvals (oldest first), orders that failed or rolled back in the last 3 days, and orders waiting on a business event for over a day. |
find_orders | viewer (Viewer) | Read | Search orders. Totals compare in USD. Returns the count and total of all matches plus up to `limit` rows. |
get_order | viewer (Viewer) | Read | One order: status, what it waits on (with where each decision leads), steps run so far and recent activity. |
assess_order | viewer (Viewer) | Read | Ask typed questions about one order and get a probability for every option: noul (yes/no, the probability of yes), choice (pick one of 2–255 options) or score (an ordered rubric of 2–10 levels, lowest first). Optionally pass up to 4 images (the order’s R2 document keys, https or data URLs; PNG, JPEG or WebP). |
find_products | viewer (Viewer) | Read | Products with stock, reserved and available quantities and reorder points. |
list_flows | viewer (Viewer) | Read | All flows and their published versions. |
get_flow | viewer (Viewer) | Read | A flow’s saved draft: its steps, connections and validation problems. |
propose_flow_change | operator (Operator) | Read | Draft a change to a flow from an instruction. Nothing is saved: a person reviews the proposal in the flow editor and applies it there. |
decide_approval | approver (Approver) | Write | Approve or reject an approval an order is waiting on. |
deliver_event | operator (Operator) | Write | Deliver a business event (e.g. payment.received) to the order waiting for it. |
cancel_order | operator (Operator) | Write | Cancel an order and undo what it did (release stock, void payment, cancel shipments). |
publish_flow | operator (Operator) | Write | Publish a flow’s saved draft as a new version. |
run_stock_review | operator (Operator) | Write | Run the daily stock review now; it starts reorders for SKUs at or below their reorder point. |
Each tool has a title, a description and a JSON input schema. Results come back as text and as
structuredContent. A refusal from live data (nothing is waiting on that event, the approval is
already decided, the order has finished) is returned as a tool error the model can read, not a
protocol error. A tool the role can’t use is not listed, and calling it by name fails as unknown.
Annotations tell a client when to confirm:
| Tools | Hints |
|---|---|
Reads and propose_flow_change |
readOnlyHint: true |
decide_approval, cancel_order, publish_flow |
destructiveHint: true; the first two are also idempotentHint: true |
deliver_event, run_stock_review |
writes, not destructive |
All tools set openWorldHint: false.
Who did it
Section titled “Who did it”A write made over MCP is attributed to the person who approved the connection, with the channel:
<email> via MCP. That string is the approval’s by or ends the cancel reason, as <email> via assistant does for the panel (see Who decided). A client
using an API token acts as token:<name>.
Disconnecting
Section titled “Disconnecting”Account lists Connected apps (MCP clients and A2A agents alike): the app’s name, whether it
connected over MCP or A2A, the address its access goes to, the role you granted and when it
connected.
Disconnect revokes the grant, and the app has to be connected again. Connecting and
disconnecting are recorded in the audit log as
oauth.app_connected and oauth.app_disconnected. Access tokens last one hour and refresh
tokens 30 days.
Security
Section titled “Security”- One endpoint per token.
/mcpand/a2aare separate OAuth resources of one authorization server. A client requestshttps://orderloop.app/mcp(a client that names no resource, and grants made before A2A existed, are for MCP), and the access token it gets is refused at/a2a; an A2A token is likewise refused here. Each endpoint publishes its own metadata at/.well-known/oauth-protected-resource/<path>. - Role cap. A grant is never higher than the role of the person who approved it, and the consent page offers no more. Pick the lowest role the client needs.
- Checked on every request. OrderLoop re-reads the person each time. A disabled or deleted
person’s grants stop working at once. The role is the lower of the one granted and the
person’s current role, so demoting someone narrows the apps they connected. A person whose role
must use two-factor sign-in and hasn’t set it up, or who is still on a temporary password, gets
403. - Credentials stay at the edge. OrderLoop resolves the caller before the request reaches the
tools;
Authorizationand cookies go no further, and the model never sees a token. - Origin. A request whose
Originis not anhttporhttpsorigin is refused with403. - Rate limits.
/oauth/registerallows 10 requests a minute and/oauth/token60, per address; over that it answers429 { "error": "slow_down" }withRetry-After: 60. - Tokens at rest. Tokens are stored hashed and grant data encrypted.