MCP server
The remote Deliverd MCP server: connect Claude Code, Codex, Cursor and other clients with OAuth, and the 101 tools an agent can call.
Deliverd runs a hosted Model Context Protocol server at /api/mcp on your Deliverd address, over Streamable HTTP. Any agent that speaks MCP can use it to ask a person — for an approval, a decision, an answer or a review — check an action against policy before it acts, keep a task's objective, and publish what it made, with no code of yours in between. The server is the same service as the REST API: the same scopes, the same refusals and the same audit trail.
Connect
Authentication is OAuth, not a pasted token. The server implements the MCP authorisation specification, so your client registers itself and you approve it in a browser, choosing the organisation as you do. In Claude Code, for example (every other client is below):
claude mcp add --transport http deliverd https://deliverd.dev/api/mcp
The first time a Deliverd tool runs, a browser window asks you to approve the connection. That approval is the credential. See Authentication for what it grants and how long it lasts.
Clients that cannot do OAuth can send an API key as a bearer token instead. It works, but it is a secret on disk; prefer OAuth where the client supports it.
Set up everything in one paste
Paste this into Claude Code, Codex, Cursor or Claude Desktop. It runs the installer from the CLI, tells you what it connected, and proves the connection with one call you see land.
Set up Deliverd so you can ask me for approval and publish work for me. 1. Run: npx deliverd setup --url https://deliverd.dev It looks for Claude Code, Codex, Claude Desktop, Cursor and Muse Code on this machine and adds the Deliverd MCP server to each one it finds. There is no API key to paste. 2. Tell me exactly what it connected and what it says to do next. Some tools need a restart, Codex needs "codex mcp login deliverd" and Muse Code needs "muse mcp login deliverd" before the connection is live. 3. Once you can see the Deliverd tools, prove the connection by asking me for an approval with the request_approval tool. Title it "Hello from Deliverd", say in the description that it is a test of the connection, and leave the approvers out so it comes to me. 4. Give me the URL it returns, then poll get_approval until I have decided and tell me what I said. From then on, ask me the same way before anything consequential; when there is a report to share, publish it with publish_report. 5. List the consequential things you can do for me here (payments, deploys, emails outside the organisation, data exports, deletions) and send them with propose_setup. Give me the URL it returns: it is a draft of rules for me to review, and nothing is enforced until I add it. If npx is unavailable, install the CLI first with: npm install -g deliverd
Each client
The same instructions as the Connect screen in the app, for every client that speaks MCP. Where a client can add a server from a link, the link comes first; the steps are the fallback.
Claude Code
claude mcp add --transport http deliverd https://deliverd.dev/api/mcp
Add the server
claude mcp add --transport http deliverd https://deliverd.dev/api/mcp
Claude Code opens a browser the first time it is used, so you can pick the organisation and approve access.
Codex
codex mcp add deliverd --url https://deliverd.dev/api/mcp
Add the server
codex mcp add deliverd --url https://deliverd.dev/api/mcp
Approve it in your browser
codex mcp login deliverd
Codex needs this second step — it does not begin the approval flow on its own.
On an older Codex
Streamable HTTP servers are only picked up when the rmcp client is on. If the server does not appear, upgrade Codex, or add [features] experimental_use_rmcp_client = true to ~/.codex/config.toml above the server entry.
Cursor
Opens Cursor and asks you to add the server; you approve the connection in your browser. If nothing happens, follow the steps below.
Or add it to ~/.cursor/mcp.json
{ "mcpServers": { "deliverd": { "type": "http", "url": "https://deliverd.dev/api/mcp" } } }Keep any servers already listed there — replacing the file removes them.
Reload Cursor
Then approve the connection in your browser.
VS Code
Opens VS Code and asks you to add the server; you approve the connection in your browser. If nothing happens, follow the steps below.
Or add it to .vscode/mcp.json
{ "servers": { "deliverd": { "type": "http", "url": "https://deliverd.dev/api/mcp" } } }In the project for one repository, or in your user settings for all of them. The key is “servers” — VS Code ignores an “mcpServers” block.
Start it
Run “MCP: List Servers” from the command palette, start the server, and approve the connection in your browser.
ChatGPT
Turn on developer mode
Settings → Apps → Advanced settings → Developer mode. Custom connectors need a paid ChatGPT plan.
Add a custom connector with this address
https://deliverd.dev/api/mcp
The connector registers itself and sends you to a screen where you choose the organisation and approve access.
Claude desktop & web
Settings → Connectors → Add custom connector
https://deliverd.dev/api/mcp
Windsurf
Add it to ~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "deliverd": { "serverUrl": "https://deliverd.dev/api/mcp" } } }Keep any servers already listed there. The key is “serverUrl” — a plain “url” is ignored.
Refresh the servers
In Cascade's MCP panel, refresh, then approve the connection in your browser.
Gemini CLI
gemini mcp add --transport http deliverd https://deliverd.dev/api/mcp
Add the server
gemini mcp add --transport http deliverd https://deliverd.dev/api/mcp
Approve it
/mcp auth deliverd
Inside Gemini, if it has not already opened a browser for you.
Muse Code
npx deliverd setup --agent muse-code --url https://deliverd.dev
Add the server
npx deliverd setup --agent muse-code --url https://deliverd.dev
Writes the entry below into Muse Code's settings, keeping every server already there and a backup of the file.
Or add it to ~/.config/muse/settings.json
{ "schema_version": 1, "mcp_servers": { "deliverd": { "transport": "streamable_http", "url": "https://deliverd.dev/api/mcp", "mode": "optional" } } }Keep schema_version and any servers already there. If your file says “mcpServers” rather than “mcp_servers”, add it under that key instead: a file with both turns every server off.
Approve it in your browser
muse mcp login deliverd
Then start a new session; /mcp lists the server and its tools.
Microsoft Foundry
Issue a key for the agent
Agents → Agents → the agent → Credentials → Issue new key. Its requests are then the agent's, under the permissions you gave it. Agent identities are on Team and above.
Keep it in a key-based connection in your Foundry project
Authorization: Bearer dlv_…
One key named Authorization whose value is the word Bearer, a space, and the key. Foundry sends it as a header on every call to the server.
Add the MCP tool to the agent
from azure.ai.projects.models import MCPTool MCPTool( server_label="deliverd", server_url="https://deliverd.dev/api/mcp", require_approval="always", project_connection_id=connection.id, )With require_approval "always", Foundry pauses before each call with an mcp_approval_request. run_with_deliverd_approvals from deliverd.adapters.foundry (the Python SDK, from 0.11.0) asks a person in Deliverd and answers it.
Amazon Bedrock
Issue a key for the agent
Agents → Agents → the agent → Credentials → Issue new key. Its requests are then the agent's, under the permissions you gave it. Agent identities are on Team and above.
Keep it in AWS Secrets Manager
Read it into the agent's environment at start-up, as DELIVERD_KEY in the code below. The agent's execution role needs secretsmanager:GetSecretValue on that one secret.
On AgentCore, or anywhere Strands runs: add the MCP server
from mcp.client.streamable_http import streamablehttp_client from strands import Agent from strands.tools.mcp import MCPClient deliverd_mcp = MCPClient(lambda: streamablehttp_client( "https://deliverd.dev/api/mcp", headers={"Authorization": f"Bearer {DELIVERD_KEY}"}, )) with deliverd_mcp: agent = Agent(tools=deliverd_mcp.list_tools_sync())The agent can now call request_approval before it acts, and wait for the answer. To have a person decide the agent's own tool calls instead, add DeliverdApprovals from deliverd.adapters.strands to its hooks (the Python SDK, from 0.19.0).
On Bedrock Agents: confirm action group calls
from deliverd.adapters.bedrock import invoke_with_deliverd_approvals
Turn on user confirmation for the functions that matter, and Bedrock hands control back before each call. invoke_with_deliverd_approvals invokes the agent, asks a person in Deliverd about each call, and sends CONFIRM or DENY, with their reason, on the same session (from 0.19.0).
Google Vertex AI
Issue a key for the agent
Agents → Agents → the agent → Credentials → Issue new key. Its requests are then the agent's, under the permissions you gave it. Agent identities are on Team and above.
Keep it in Secret Manager
Pass it to the agent as DELIVERD_KEY when you deploy it to Agent Engine, from Secret Manager rather than as plain text.
Add the MCP server to the agent
from google.adk.agents import LlmAgent from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams from google.adk.tools.mcp_tool.mcp_toolset import McpToolset deliverd_mcp = McpToolset(connection_params=StreamableHTTPConnectionParams( url="https://deliverd.dev/api/mcp", headers={"Authorization": f"Bearer {DELIVERD_KEY}"}, )) agent = LlmAgent(model="gemini-2.5-flash", name="ops", tools=[deliverd_mcp])The agent can now call request_approval before it acts, and wait for the answer. Deploy it to Agent Engine as you would any ADK agent.
Or have a person decide the agent's tool calls
from deliverd import Deliverd from deliverd.adapters.adk import deliverd_before_tool_callback agent = LlmAgent(..., before_tool_callback=deliverd_before_tool_callback(Deliverd()))
Each tool call waits for a person in Deliverd; a declined call does not run, and the model reads why. For tools built with require_confirmation, run_with_deliverd_confirmations answers ADK's confirmation from your client instead (the Python SDK, from 0.19.0).
For any other client, give it the server address and let it register itself:
https://deliverd.dev/api/mcp
Tools
The server carries 101 tools. Each requires the scope beside it, from the same list API keys use; a call without it is refused with a message naming the scope it needed. The list below is the one the server publishes for directories, so it is always the server's own; it leaves out find_report, a deprecated alias of find_reports kept for older clients.
Asking a person, and the record
Asking before acting comes first. check_gate asks your organisation's policy whether to perform a registered action — see the gate — and the rest ask a named person for an approval, a review or information, or tie them together in a flow. See Approvals, reviews and requests for the fields.
| Tool | What it does | Scope |
|---|---|---|
check_gate | Ask whether you may perform a registered action before you perform it; policy answers allow, refuse, or a person decides. | gates:write |
get_gate | The state of a gate decision you raised, once a person has answered it. | gates:read |
request_approval | Ask named people to authorise an action before you take it; returns the request and its page. | approvals:write |
get_approval | The status of an approval — pending, approved, rejected or expired — with any questions the approver asked. | approvals:read |
answer_approval_question | Answer a question an approver asked about your request, on the approval page. | approvals:write |
cancel_approval | Withdraw an approval you asked for, while it is still undecided. | approvals:write |
request_review | Ask named people to read work and say whether it is right; returns the request and its page. | reviews:write |
get_review | The outcome of a review — pending, approved or changes requested — with each reviewer's verdict and note. | reviews:read |
cancel_review | Withdraw a review you asked for, while it is still unanswered. | reviews:write |
request_information | Ask named people typed questions and get structured answers back; returns the request and its page. | collections:write |
get_collection | The answers to a request for information, with who replied and what they said. | collections:read |
cancel_collection | Withdraw a request for information you made, while it is still open. | collections:write |
cancel_gate | Withdraw your own gate request, or a permission you have not used yet. | gates:write |
record_execution | Report what you did with a gate's permission; a different artifact or destination is refused. | gates:execute |
release_version | Have Deliverd make the staged report version a gate authorised live, and record it as verified. | gates:execute |
create_flow | Start a flow: the thread tying one job's approvals, reviews, requests and publishes together. | flows:write |
find_flow | Find the flow you started with an externalId, or null, so a restarted job extends it rather than starting a second. | flows:read |
get_flow | A flow with everything in it and the timeline of what happened across all of them, in order. | flows:read |
complete_flow | Say the work a flow covers is done. Only whoever started it, and it takes no new members afterwards. | flows:write |
cancel_flow | Close a flow as abandoned rather than done, so the history says which of the two happened. | flows:write |
create_task | Start an objective: what the work is ultimately for, kept apart from the conversation and returned at the top of every context. | tasks:write |
get_task_context | The objective, where a task stands, its decisions, open questions, side-task results, reports and next action — read instead of the history. | tasks:read |
list_tasks | The objectives you can see, with status, next action and side-task counts — find work already under way before starting more. | tasks:read |
get_task | One task in full: objective, state, result, findings, decisions, where it sits and its side tasks. | tasks:read |
get_task_graph | Every side task under an objective, with its status and one-line result, and the links between them. | tasks:read |
update_task | Update a task's working state — where it stands, open questions, what blocks it, the next action — or its status. | tasks:write |
create_side_task | Branch a problem out of the main task so the main thread stays on its goal. It starts with a chosen snapshot of the parent. | tasks:write |
add_finding | Record a work product on a task: hypothesis, test, evidence, conclusion, recommendation or a decision you suggest. | tasks:write |
complete_task | Finish a task with a structured result: summary, findings, proposed decisions, open questions and the next action. | tasks:write |
apply_side_task | Carry a finished side task's result into its parent, or keep or discard it, and return to the objective. | tasks:write |
reopen_task | Reopen a finished task when there is more to do. What it found the first time is kept. | tasks:write |
cancel_task | Call a task off as abandoned rather than finished. Cancelling an objective cancels its open side tasks. | tasks:write |
request_decision_approval | Put a decision you suggested to the organisation's approval process; approved confirms it, rejected rejects it. | approvals:write |
create_governed_task | Start an objective under Compliance Mode: the AI system, purpose, owners, risk, data and oversight, held to the controls they require. | tasks:write |
govern_task | Put an existing objective under Compliance Mode, with what is known of its governance profile. | tasks:write |
get_governance_context | A governed task's profile, AI system, controls and their state, evidence, readiness and gate answer. | tasks:read |
update_governance_profile | Record what was learnt about a governed task. An agent may raise risk or add facts; only a person lowers or clears them. | tasks:write |
get_required_controls | The governance controls a governed task must satisfy, and what satisfies each. | tasks:read |
submit_evidence | Record evidence for a governed task and the controls it speaks to, with the scores a run measured or the tool's own report. | tasks:write |
request_control_approval | Put a compliance or deployment approval control to a person through the organisation's approval process. | approvals:write |
check_governance_gate | Whether governed work may proceed, naming the controls still outstanding. Recorded. | tasks:read |
get_evidence_pack | The AI governance evidence pack of a governed task, with a digest. Assists audit; certifies nothing. | tasks:read |
register_ai_system | Add an AI system to the organisation's register so governed tasks can name it. | tasks:write |
update_ai_system | Change an AI system's register entry. An agent cannot lower its risk or set its status. | tasks:write |
move_ai_system | Put an AI system's register entry forward for assessment, or withdraw it. Decisions on it are a person's. | tasks:write |
list_ai_systems | The organisation's register of AI systems. | tasks:read |
get_ai_system | One AI system's register entry: its lifecycle status and steps, who answers for it, and the governed tasks that name it. | tasks:read |
get_ict_register | The ICT third-party register: providers, contracts, the AI systems under each, what entries lack, and concentration per provider. | tasks:read |
get_framework_mapping | How framework requirements map onto governance controls, and how far a governed task's completed controls cover them. Not a compliance verdict. | tasks:read |
create_custom_framework | Draft the organisation's own governance framework. Applies only once a person publishes and adopts it. | tasks:write |
check_agent_authority | Whether this agent may take a kind of action on its own, only with a person's approval, or not at all. | tasks:read |
screen_data | Before sending text to an AI model, find the personal data, secrets and confidential terms in it, and whether that model may receive them. | approvals:write |
record_model_change | Record a new provider, model or version for an AI system; every governed task using it is reassessed. | tasks:write |
search_knowledge | Search the organisation's confirmed knowledge — facts, conventions, decisions, who to ask — before you start or when unsure. | tasks:read |
get_knowledge | One knowledge entry in full: its words, who confirmed it, when it is due for review, and the versions it replaced. | tasks:read |
propose_knowledge | Propose something you learned as organisation knowledge, for any agent to rely on once a person confirms it. | tasks:write |
list_playbooks | The organisation's playbooks and approved prompts: how a kind of job is done, with which version is in force. | tasks:read |
get_playbook | One playbook: its purpose, its inputs and each step with the rule that applies — a gate check, an approval or a review. | tasks:read |
draft_playbook | Write down a procedure as a playbook draft. A person puts it in force; nobody runs a draft. | tasks:write |
start_playbook | Run the playbook in force: an objective with a side task per step, each holding its instruction and its rule. | tasks:write |
use_prompt | Take one of the organisation's approved prompts, filled in with your inputs: the version in force, with its limitations. | tasks:read |
propose_setup | Describe the consequential things you can do here, and get rules for them drafted for an administrator to review and add. | tasks:write |
trigger_reassessment | Ask for a governed task to be reassessed. Its gate stays closed until a person completes it. | tasks:write |
report_ai_incident | Report an AI incident against a governed task or AI system. High or critical closes the gate until a person resolves it. | tasks:write |
get_ai_incident | One incident with its DORA classification, its reports and which report is due next, by when. | tasks:read |
get_risk_indicators | The AI risk scorecard for a month: each indicator against its green, amber and red limits, the trend and the actions open. | tasks:read |
submit_risk_indicator_reading | Give a month's figure for an AI risk indicator Deliverd cannot measure itself, with where it comes from. | tasks:write |
draft_incident_report | Draft the next DORA report on a major incident and put it to a person to sign off. | approvals:write |
get_evidence | An evidence pack for a flow or a report: every step, who decided what, and the full timeline. | every read scope |
Publishing and reading
Publishing, sharing, datasets, comments and analytics. See Publishing reports.
| Tool | What it does | Scope |
|---|---|---|
show_library | Your library as tiles: the prompts and reports made available to you, pinned and recent first. | reports:read |
get_profile | Who this connection belongs to, to tell connected accounts apart. | workspaces:read |
resolve_audience | Turn natural-language audience phrases into concrete principals. | audiences:read |
list_workspaces | List workspaces, with who can already open a given report. | workspaces:read |
publish_report | Publish HTML to a persistent secure URL, with an audience named in plain English. | reports:write |
update_report | Publish a new version of an existing report, keeping its URL and audience. | reports:write |
rename_report | Change a report's title or address; the old address keeps working. | reports:write |
move_report | File a report into a workspace. | reports:write |
archive_report | Stop a report's URL serving. Reversible; nothing is deleted. | reports:write |
unarchive_report | Put an archived report back, at the same URL and audience. | reports:write |
rollback_report | Serve an earlier version again, without republishing it. | reports:write |
get_report | Fetch a report's metadata, URL and current version. | reports:read |
find_reports | Search reports by title or slug. | reports:read |
list_templates | Reports the organisation offers as starting points. | reports:read |
share_report | Grant people, teams or groups access to a report. | reports:share |
revoke_access | Take a report's access away again, from the same audience phrase that granted it. | reports:share |
send_report | Email a report to a list of addresses, with a covering note. Each gets their own link. | reports:share |
list_due_schedules | Recurring reports waiting on this agent. | schedules:read |
create_schedule | Ask an agent for a recurring publish, on a cron cadence. | schedules:write |
update_schedule | Change a schedule's cadence, or turn it on or off. | schedules:write |
delete_schedule | Stop asking for a recurring publish. | schedules:write |
list_report_data | List the datasets a report reads when it is opened. | reports:read |
update_report_data | Replace a report's live data without publishing a new version. | reports:write |
delete_report_data | Remove a dataset from a report. | reports:write |
list_comments | Read reader feedback, with the quoted passage and context. | comments:read |
list_open_comments | Every open comment thread across the organisation's reports — what needs attention. | comments:read |
get_report_analytics | Who read a report and when: views, readers, by day and by version. | reports:read |
get_org_analytics | Readership across every report, including the ones nobody has opened. | reports:read |
get_revision_brief | The open feedback on a report as one revision prompt, with the readers' screenshots. | comments:read |
comment_on_report | Comment on a report, anchored to a quoted passage. | comments:write |
retract_comment | Take back a comment nobody has answered yet. | comments:write |
resolve_comment | Mark a comment thread resolved. | comments:write |
Behaviour worth knowing
- Audience parameters take plain language — "Finance team", "Sarah Jones", "everyone". When a phrase is ambiguous the tool returns candidates for the agent to confirm with you, then retry.
resolve_audiencechecks a phrase without sharing anything. - A connection made with OAuth acts as the person who approved it. Their membership is checked on every call, so removing someone from the organisation cuts their agent off at once.
- A refusal comes back as a tool result marked as an error. Most carry the same
errorcode and message the REST API sends; see Errors and limits. tools/listneeds a credential like every other call. A directory reads the public server card at/.well-known/mcp/server-card.jsoninstead.
Try it on your own agent.
Free to start, no card. Sign up with Google, Microsoft or GitHub, and the first page after hands you an API key.