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
  1. 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
  1. Add the server

    codex mcp add deliverd --url https://deliverd.dev/api/mcp
  2. Approve it in your browser

    codex mcp login deliverd

    Codex needs this second step — it does not begin the approval flow on its own.

  3. 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.

  1. 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.

  2. 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.

  1. 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.

  2. Start it

    Run “MCP: List Servers” from the command palette, start the server, and approve the connection in your browser.

ChatGPT

  1. Turn on developer mode

    Settings → Apps → Advanced settings → Developer mode. Custom connectors need a paid ChatGPT plan.

  2. 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

  1. Settings → Connectors → Add custom connector

    https://deliverd.dev/api/mcp

Windsurf

  1. 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.

  2. 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
  1. Add the server

    gemini mcp add --transport http deliverd https://deliverd.dev/api/mcp
  2. 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
  1. 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.

  2. 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.

  3. Approve it in your browser

    muse mcp login deliverd

    Then start a new session; /mcp lists the server and its tools.

Microsoft Foundry

  1. 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.

  2. 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.

  3. 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

  1. 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.

  2. 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.

  3. 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).

  4. 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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

ToolWhat it doesScope
check_gateAsk whether you may perform a registered action before you perform it; policy answers allow, refuse, or a person decides.gates:write
get_gateThe state of a gate decision you raised, once a person has answered it.gates:read
request_approvalAsk named people to authorise an action before you take it; returns the request and its page.approvals:write
get_approvalThe status of an approval — pending, approved, rejected or expired — with any questions the approver asked.approvals:read
answer_approval_questionAnswer a question an approver asked about your request, on the approval page.approvals:write
cancel_approvalWithdraw an approval you asked for, while it is still undecided.approvals:write
request_reviewAsk named people to read work and say whether it is right; returns the request and its page.reviews:write
get_reviewThe outcome of a review — pending, approved or changes requested — with each reviewer's verdict and note.reviews:read
cancel_reviewWithdraw a review you asked for, while it is still unanswered.reviews:write
request_informationAsk named people typed questions and get structured answers back; returns the request and its page.collections:write
get_collectionThe answers to a request for information, with who replied and what they said.collections:read
cancel_collectionWithdraw a request for information you made, while it is still open.collections:write
cancel_gateWithdraw your own gate request, or a permission you have not used yet.gates:write
record_executionReport what you did with a gate's permission; a different artifact or destination is refused.gates:execute
release_versionHave Deliverd make the staged report version a gate authorised live, and record it as verified.gates:execute
create_flowStart a flow: the thread tying one job's approvals, reviews, requests and publishes together.flows:write
find_flowFind the flow you started with an externalId, or null, so a restarted job extends it rather than starting a second.flows:read
get_flowA flow with everything in it and the timeline of what happened across all of them, in order.flows:read
complete_flowSay the work a flow covers is done. Only whoever started it, and it takes no new members afterwards.flows:write
cancel_flowClose a flow as abandoned rather than done, so the history says which of the two happened.flows:write
create_taskStart 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_contextThe objective, where a task stands, its decisions, open questions, side-task results, reports and next action — read instead of the history.tasks:read
list_tasksThe objectives you can see, with status, next action and side-task counts — find work already under way before starting more.tasks:read
get_taskOne task in full: objective, state, result, findings, decisions, where it sits and its side tasks.tasks:read
get_task_graphEvery side task under an objective, with its status and one-line result, and the links between them.tasks:read
update_taskUpdate a task's working state — where it stands, open questions, what blocks it, the next action — or its status.tasks:write
create_side_taskBranch 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_findingRecord a work product on a task: hypothesis, test, evidence, conclusion, recommendation or a decision you suggest.tasks:write
complete_taskFinish a task with a structured result: summary, findings, proposed decisions, open questions and the next action.tasks:write
apply_side_taskCarry a finished side task's result into its parent, or keep or discard it, and return to the objective.tasks:write
reopen_taskReopen a finished task when there is more to do. What it found the first time is kept.tasks:write
cancel_taskCall a task off as abandoned rather than finished. Cancelling an objective cancels its open side tasks.tasks:write
request_decision_approvalPut a decision you suggested to the organisation's approval process; approved confirms it, rejected rejects it.approvals:write
create_governed_taskStart an objective under Compliance Mode: the AI system, purpose, owners, risk, data and oversight, held to the controls they require.tasks:write
govern_taskPut an existing objective under Compliance Mode, with what is known of its governance profile.tasks:write
get_governance_contextA governed task's profile, AI system, controls and their state, evidence, readiness and gate answer.tasks:read
update_governance_profileRecord 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_controlsThe governance controls a governed task must satisfy, and what satisfies each.tasks:read
submit_evidenceRecord 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_approvalPut a compliance or deployment approval control to a person through the organisation's approval process.approvals:write
check_governance_gateWhether governed work may proceed, naming the controls still outstanding. Recorded.tasks:read
get_evidence_packThe AI governance evidence pack of a governed task, with a digest. Assists audit; certifies nothing.tasks:read
register_ai_systemAdd an AI system to the organisation's register so governed tasks can name it.tasks:write
update_ai_systemChange an AI system's register entry. An agent cannot lower its risk or set its status.tasks:write
move_ai_systemPut an AI system's register entry forward for assessment, or withdraw it. Decisions on it are a person's.tasks:write
list_ai_systemsThe organisation's register of AI systems.tasks:read
get_ai_systemOne 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_registerThe ICT third-party register: providers, contracts, the AI systems under each, what entries lack, and concentration per provider.tasks:read
get_framework_mappingHow 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_frameworkDraft the organisation's own governance framework. Applies only once a person publishes and adopts it.tasks:write
check_agent_authorityWhether this agent may take a kind of action on its own, only with a person's approval, or not at all.tasks:read
screen_dataBefore 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_changeRecord a new provider, model or version for an AI system; every governed task using it is reassessed.tasks:write
search_knowledgeSearch the organisation's confirmed knowledge — facts, conventions, decisions, who to ask — before you start or when unsure.tasks:read
get_knowledgeOne knowledge entry in full: its words, who confirmed it, when it is due for review, and the versions it replaced.tasks:read
propose_knowledgePropose something you learned as organisation knowledge, for any agent to rely on once a person confirms it.tasks:write
list_playbooksThe organisation's playbooks and approved prompts: how a kind of job is done, with which version is in force.tasks:read
get_playbookOne playbook: its purpose, its inputs and each step with the rule that applies — a gate check, an approval or a review.tasks:read
draft_playbookWrite down a procedure as a playbook draft. A person puts it in force; nobody runs a draft.tasks:write
start_playbookRun the playbook in force: an objective with a side task per step, each holding its instruction and its rule.tasks:write
use_promptTake one of the organisation's approved prompts, filled in with your inputs: the version in force, with its limitations.tasks:read
propose_setupDescribe the consequential things you can do here, and get rules for them drafted for an administrator to review and add.tasks:write
trigger_reassessmentAsk for a governed task to be reassessed. Its gate stays closed until a person completes it.tasks:write
report_ai_incidentReport 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_incidentOne incident with its DORA classification, its reports and which report is due next, by when.tasks:read
get_risk_indicatorsThe 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_readingGive a month's figure for an AI risk indicator Deliverd cannot measure itself, with where it comes from.tasks:write
draft_incident_reportDraft the next DORA report on a major incident and put it to a person to sign off.approvals:write
get_evidenceAn 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.

ToolWhat it doesScope
show_libraryYour library as tiles: the prompts and reports made available to you, pinned and recent first.reports:read
get_profileWho this connection belongs to, to tell connected accounts apart.workspaces:read
resolve_audienceTurn natural-language audience phrases into concrete principals.audiences:read
list_workspacesList workspaces, with who can already open a given report.workspaces:read
publish_reportPublish HTML to a persistent secure URL, with an audience named in plain English.reports:write
update_reportPublish a new version of an existing report, keeping its URL and audience.reports:write
rename_reportChange a report's title or address; the old address keeps working.reports:write
move_reportFile a report into a workspace.reports:write
archive_reportStop a report's URL serving. Reversible; nothing is deleted.reports:write
unarchive_reportPut an archived report back, at the same URL and audience.reports:write
rollback_reportServe an earlier version again, without republishing it.reports:write
get_reportFetch a report's metadata, URL and current version.reports:read
find_reportsSearch reports by title or slug.reports:read
list_templatesReports the organisation offers as starting points.reports:read
share_reportGrant people, teams or groups access to a report.reports:share
revoke_accessTake a report's access away again, from the same audience phrase that granted it.reports:share
send_reportEmail a report to a list of addresses, with a covering note. Each gets their own link.reports:share
list_due_schedulesRecurring reports waiting on this agent.schedules:read
create_scheduleAsk an agent for a recurring publish, on a cron cadence.schedules:write
update_scheduleChange a schedule's cadence, or turn it on or off.schedules:write
delete_scheduleStop asking for a recurring publish.schedules:write
list_report_dataList the datasets a report reads when it is opened.reports:read
update_report_dataReplace a report's live data without publishing a new version.reports:write
delete_report_dataRemove a dataset from a report.reports:write
list_commentsRead reader feedback, with the quoted passage and context.comments:read
list_open_commentsEvery open comment thread across the organisation's reports — what needs attention.comments:read
get_report_analyticsWho read a report and when: views, readers, by day and by version.reports:read
get_org_analyticsReadership across every report, including the ones nobody has opened.reports:read
get_revision_briefThe open feedback on a report as one revision prompt, with the readers' screenshots.comments:read
comment_on_reportComment on a report, anchored to a quoted passage.comments:write
retract_commentTake back a comment nobody has answered yet.comments:write
resolve_commentMark 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_audience checks 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 error code and message the REST API sends; see Errors and limits.
  • tools/list needs a credential like every other call. A directory reads the public server card at /.well-known/mcp/server-card.json instead.

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.