ops-copilot

An MCP server for delivery exceptions

Connect any MCP-compatible AI client, then follow the five-step walkthrough below. About ten minutes. All data here is synthetic.

Connect

claude.ai — Settings → Connectors → Add custom connector. Paste this as the URL and leave the OAuth fields empty (claude.ai cannot send a custom header, so the token rides in the URL).

https://ops-copilot-musharraf008s-projects.vercel.app/api/mcp/t/ops-demo-12dc8b077e028dcc71526cb8

Claude Code

claude mcp add --transport http ops-copilot https://ops-copilot-musharraf008s-projects.vercel.app/api/mcp \
  --header "Authorization: Bearer ops-demo-12dc8b077e028dcc71526cb8"
Other clients — MCP Inspector, plain URL + token, .mcp.json

MCP Inspector — transport “Streamable HTTP”, then paste the URL and header below

npx @modelcontextprotocol/inspector

URL and token on their own

https://ops-copilot-musharraf008s-projects.vercel.app/api/mcp
Authorization: Bearer ops-demo-12dc8b077e028dcc71526cb8

Anything that reads .mcp.json

{
  "mcpServers": {
    "ops-copilot": {
      "type": "http",
      "url": "https://ops-copilot-musharraf008s-projects.vercel.app/api/mcp",
      "headers": { "Authorization": "Bearer ops-demo-12dc8b077e028dcc71526cb8" }
    }
  }
}

You should see 5 tools, 3 resources and 1 prompt. The token is a demo credential guarding synthetic data — it is published here on purpose.

What this is

An operations specialist can see the storefront admin but not the payment ledger or the carrier’s scan history, so “where did the parcel go, and do we owe this person money?” becomes a message to an engineer who hand-writes queries and performs the refund himself. This removes that dependency for one workflow — a delayed, lost or disputed delivery, and the refund decision that follows.

The design rule: the server decides, the model narrates. Detection, diagnosis, the refund amount and the policy verdict are all deterministic server-side code. The model reads a verdict — it never authors one. There is no field on any tool where a model can type a dollar amount.

detect       ops_list_delayed_shipments           what needs attention
investigate  ops_investigate_delivery_exception   what happened, and how sure are we
verify       ops_verify_carrier_exception         what does the CARRIER say
preview      ops_preview_refund                   the server computes the amount
act          ops_issue_refund                     execute the plan by id
confirm      ops_investigate_delivery_exception   re-run to check the outcome

The walkthrough

Five steps, in order. Each shows something different — they are not variations on one trick. If someone has been here before you, hit Reset demo data at the bottom first.

01

It finds the work, and resolves what it can

What delivery exceptions are open right now?

Expect: 7 of 28 orders, ranked worst-first, each with a one-line reason. The other 21 are healthy and correctly ignored.

Work ORD-1001 through to a resolution.

Expect: It investigates, asks the carrier, previews, and refunds $87.08 on its own authority — verified lost, under the $150 ceiling, no human involved.

Ask it to show you the root cause and the evidence. Every fact cites a real event id you can trace. None of that reasoning happened in the chat — it came back from the server already decided.

02

It knows the difference between lost and late

ORD-1006 is late too. Should we refund that one as well?

Expect: Refused as premature. The carrier reports the parcel located and moving, with a revised ETA.

This is the important one. ORD-1006 is indistinguishable from ORD-1001 in our own data — same scan gap, same breached promise date, same diagnosis at the same confidence. Only calling the carrier separates them, which is why a fresh carrier verification is a hard precondition for any refund rather than a box to tick.

Try again, it has been long enough now.

Expect: It declines to retry rather than reshaping the request into something that might slip through.

03

Above a threshold, a human decides

ORD-1002 is lost as well. Refund it.

Expect: Queued for approval, not executed — $219.92 is over the ceiling — with zero money moved and a link to the approval.

Open the approvals queue and click into it. You get the computed amount and where it came from, all nine policy rules with their verdicts, the ranked causes, and the customer and carrier text kept visibly fenced. Approve it with a note.

Expect: Executed, your name and note recorded, and the form replaced by “Decisions are single-use”. Ask the agent to check the order again — it now reports the refund settled.

No tool can approve anything. The agent raised the request and can read its status, but a decision exists only here, as a human action. That omission is the entire gate.

04

It says when it does not know

The customer on ORD-1003 says their parcel never arrived. Refund them.

Expect: Low confidence, and no recommendation. Two competing explanations, each carrying evidence that argues against it, and an escalation to a human.

The carrier’s GPS puts the delivery 28 metres from the door; the customer says it never came. Both stories hold up. It also surfaces that this customer made an identical claim 71 days ago — as a note for the human, deliberately not folded into the ranking, because a customer’s history is not evidence about where this parcel went.

05

Try to break it

Refund ORD-1004.

Expect: Refused. The payment ledger shows it was already refunded in full — even though the order status still reads “open”. The ledger wins.

Refund $5,000 on ORD-1005.

Expect: The amount is ignored entirely — there is no field to put it in. The server computes $121.64, then escalates anyway because the customer’s card is closed.

Issue that same refund plan again.

Expect: replayed: true and one refund transaction, not two.

Finally, open the audit log. Every attempt is there including the refused ones, with who asked, which rules fired, and the amount.

What it will never do

Each of those is backed by a test. There are 93 assertions plus 75 more run over the wire against this deployment.

If something looks wrong

A timed-out call is the free-tier database waking up — retry once. An already-resolved scenario or an empty approvals queue means someone got here before you — reset below.

Restores all 28 synthetic orders. Safe to run at any time.