AI agent · MCP client + 3 servers · RAG

Helpdesk Agent

A customer-support agent that looks up orders, answers from the help center, issues refunds and knows when to hand off to a human. The agent loop is hand-written, the tools come from three MCP servers, and the rules it must not break are enforced where a prompt cannot reach them.

Tasks resolved
96%
Policy violations
0 / 14
Same attacks, prompt-only rules
4 / 14
Tool calls per task
4.1

28 scripted scenarios, scored on the resulting business state. Run 2026-09-20 on free OpenRouter models.

Talk to the agent

Fernhill Outfitters is a fictional shop. Every tool call the agent makes is shown as it happens.

Ask about an order on the right, a policy, or try to talk the agent into breaking a rule.

How it is built

  1. 01

    The agent is an MCP client

    It connects to three MCP servers and learns its tools from the protocol's tools/list at run time. The loop contains no tool names, so adding a server adds capabilities without touching the agent.

  2. 02

    A loop you can read

    Plan, call tools, observe, repeat — about 100 lines, no agent framework. Six-step budget, per-call timeouts, rotation across free tool-calling models, and schema errors are handed back so the model can correct itself.

  3. 03

    Rules live in the servers

    The prompt explains policy, but the tickets server enforces it. A jailbroken or simply confused model still cannot refund outside the window, refund final-sale items, exceed $100, or touch another customer's order.

  4. 04

    Measured, not demoed

    Scripted customer scenarios are scored on the final state of the business, not on how the reply sounds: was the right refund issued, was the wrong one blocked, was a human looped in.

Does enforcing rules in the server matter?

The same agent, prompt and scenarios were run twice. In one run the tickets and orders servers enforce policy; in the other they execute whatever the model asks, so the prompt is the only guard. A violation is a business state that should never exist: a refund outside the return window, on a final-sale item, above the limit, or a cancelled order that had already shipped.

ConfigurationTasks resolvedPolicy violationsAvg tool callsMedian turn
Rules enforced in the MCP servers (shipped)27/28 (96%)0/144.125.3 s
Rules in the prompt only (servers execute anything)10/14 (71%)4/144.115.7 s

With the rules only in the prompt, the same model issued a $288 refund it was told to escalate, split a $165 refund into two $82.50 payments when asked to, obeyed a forged "SYSTEM NOTICE" suspending the final-sale policy, and cancelled an order that had already shipped after the customer insisted. With the rules in the servers it attempted several of the same calls, and every one was refused. The one guarded failure was not a violation: on a $288 return the agent kept re-reading the order and ran out of its six-step budget before answering. One prompt-only scenario was re-scored after the run because the text matcher missed "final-sale" written with a typographic hyphen; violation counts were unaffected.

Three MCP servers, usable on their own

The hosted agent talks to them in-process. The same servers are exposed over Streamable HTTP, so you can plug them into Claude Code or Cursor and let your own model run the desk:

claude mcp add --transport http fernhill-kb https://helpdesk-agent.zojoofficial.com/api/mcp/kb
claude mcp add --transport http fernhill-orders "https://helpdesk-agent.zojoofficial.com/api/mcp/orders?customer=C-1001"
claude mcp add --transport http fernhill-tickets "https://helpdesk-agent.zojoofficial.com/api/mcp/tickets?customer=C-1001"

Security posture