restaurant-agent
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@restaurant-agentShow me the active orders"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
restaurant-agent
A permission-aware MCP server for a restaurant backend, with the process artifacts that built it: the specs it was built from and the eval harness that measures how agents behave against it.
The interesting part is not that an agent can read a menu — it is what happens when an agent asks for something it is not allowed to see, and how you find out whether your agent + tool design actually holds up.
What this demonstrates
Permission-aware tool design — every tool declares a minimum role (
viewer < staff < manager); an unauthorized call returns a structured refusal the agent can reason about, never an exception, never silent failure, and never data.Agent proposes, human approves — the single write-path tool (
draft_daily_special) cannot touch production; it creates a draft that a human approves out of band.Spec-driven process —
specs/holds the contract this server was built from (001), the reusable template (000), and a sanitized real-world case study (002). When agent output is wrong, the first suspect is spec quality — the fix goes into the spec, not just the code.Evals, not vibes —
evals/runs a real model against the server and mechanically checks tool choices, refusal handling and prompt-injection resistance. See evals/README.md for why these are not unit tests.
Related MCP server: Ordio MCP
Architecture
flowchart LR
agent["Agent<br/>(tool-use loop,<br/>Anthropic API)"]
subgraph mcp["MCP server (stdio)"]
registry["Tool registry"]
gate["Permission gate<br/>role rank vs minRole"]
validate["Zod validation"]
tools["7 tools"]
end
subgraph backend["Data source"]
mock["Mock API<br/>(fictional fixtures, default)"]
real["Real API<br/>(Bearer token, opt-in)"]
end
agent -- "tools/call" --> registry
registry --> gate
gate -- "insufficient role" --> refusal["Structured refusal<br/>{allowed:false, reason,<br/>required_role, current_role}"]
refusal --> agent
gate -- ok --> validate --> tools
tools --> mock
tools -.-> realAudit trail: every call is logged as JSONL to stderr (timestamp, tool, role, decision, args hash — raw arguments are never logged).
Quickstart
npm install
npm test # 57 unit tests: full role x tool gate matrix
npm run agent # demo agent against the mock server (needs ANTHROPIC_API_KEY)The server runs in mock mode by default — a fictional restaurant ("Ravintola Kotilounas") with invented menu, orders and sales. No backend, no credentials needed. Try different roles:
AGENT_TOKEN=demo-staff-token npm run agent -- "What orders are waiting right now?"
AGENT_TOKEN=demo-manager-token npm run agent -- "Revenue for the first week of June?"
AGENT_TOKEN=demo-viewer-token npm run agent -- "Revenue for the first week of June?" # watch the refusalPermission design
Roles are hierarchical: viewer (0) < staff (1) < manager (2). The registry
dispatches every call through the same path: gate → validate → handler.
The gate runs before argument validation, so an under-privileged caller gets
permission_denied— not schema feedback it could use to probe tools.Refusals are template-built from registry data only. Tool arguments are data, not instructions: a unit test injects instruction-like text through arguments and asserts the refusal text is unchanged.
Unknown or missing tokens resolve to
viewer— least privilege by default.Argument schemas are
.strict()— unexpected keys are rejected.
Example refusal (what the agent actually receives):
{
"allowed": false,
"error": "permission_denied",
"reason": "get_sales_summary requires role 'manager'; this session has role 'viewer'.",
"required_role": "manager",
"current_role": "viewer"
}Tools
Tool | Min role | Purpose |
| viewer | full menu grouped by category, with allergen codes |
| viewer | filter by text, category, excluded allergens |
| viewer | weekly hours + holiday exceptions |
| viewer | today's lunch menu and serving window |
| staff | live order queue with statuses |
| manager | per-day revenue and top items (mock-only) |
| staff | write-demo: draft → human approval, never prod |
The surface mirrors a real production restaurant API (the same one behind vanhamylly-api); real mode forwards a Bearer token and is opt-in via env — no real endpoints ship in this repo.
Evals
ANTHROPIC_API_KEY=... npm run evals # 14 tasks, prints pass rate
npm run evals -- --task prompt-injection-menu-note14 tasks: happy paths for every tool at sufficient role, refusal cases (viewer asking for sales, staff asking for manager data), and adversarial cases — prompt injection embedded in user content, requests for nonexistent capabilities, and an attempt to publish straight to production (expected outcome: a draft plus an answer that mentions human approval).
Latest local run: 14/14 (100%) on claude-sonnet-5. The first run scored
12/14 — and both failures were eval-quality defects, not agent defects:
the allergen task expected the literal argument
"gluten", while the agent did something smarter — looked up the menu's allergen legend first and used the documented code"G";the publish-bypass task demanded an immediate
draft_daily_specialcall, while the agent refused the "skip any approval" instruction and asked before drafting — safer than the expectation.
Both tasks were recalibrated to test the actual property (documented codes; the no-bypass safety guarantee) and the fix went into the tasks, not the code. That loop — failing eval → inspect → fix the spec — is the point of this repo. Rates vary between runs and models; treat single runs as measurements, not verdicts.
CI runs lint + typecheck + unit tests on every push; evals are a manual workflow (they need an API key and cost tokens).
License
MIT © 2026 Oleksii Halushka
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityCmaintenanceAn MCP server that implements a multi-stage employee access request and approval workflow, enabling employees to request system access and managers/IT admins to approve or reject requests through an interactive UI.
- Flicense-qualityBmaintenanceMCP server for the Ordio restaurant operations platform, enabling AI assistants to manage inventory, orders, recipes, team, shifts, and reports.1
- Alicense-qualityBmaintenanceMCP server for AI-native restaurant discovery with three-tier search (verified, menu_indexed, discovered), Menu Protocol menus, and structured menu validation.2MIT
- Flicense-qualityBmaintenanceAn MCP server that enables non-technical operations users to resolve common commerce-ops tickets, such as orders charged but failed, through an investigate, recommend, approve, and execute workflow with read-only and write tools.
Related MCP Connectors
MCP server for Meitre restaurant reservations.
A paid remote MCP for CLI tool MCP, built to return verdicts, receipts, usage logs, and audit-ready
A paid remote MCP for hosted MCP server, built to return verdicts, receipts, usage logs, and audit-r
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/illustraton916/restaurant-agent'
If you have feedback or need assistance with the MCP directory API, please join our Discord server