A C# MCP Server with Single-Use Order Approvals
Martin Pisacreta built a small .NET 8 MCP server where the order cancellation tool requires a separately recorded, single-use, expiring approval instead of trusting the model's confirmation. The article walks through the claim-before-use approval store, the tool contract and the limits of the design, backed by 12 passing tests.
Key points
- cancel_order takes only orderId; there is no approved parameter and no tool that creates approvals.
- An approval file is valid for one action and one exact order ID, and expires five minutes after it is written.
- The store renames the approval file before validation, so two concurrent requests cannot consume the same permission.
- Stdout is reserved for MCP protocol messages in stdio transport, so application logs go to stderr.
- The approval directory must stay outside the model's writable filesystem and shell access to matter.
- Orders reset on restart while unused approval files can survive, so the author recommends clearing them before restarting.
The author argues that reading orders through an MCP tool is simple, but a cancellation tool forces a harder question: who authorizes the change? In dotnet-mcp-orders-server, a .NET 8 sample over stdio, cancel_order accepts only an order ID and cannot create approvals. Instead, an operator records a JSON approval for one action and one order, valid for five minutes, using a separate command. The server checks that file before changing anything.
The store renames the approval file before reading it, so two callers cannot consume the same permission. Action, order ID and expiry are validated, and the file is deleted even when validation fails. Order status is checked under a lock. The 12 tests call the tool class directly and do not establish a live Claude connection. The author notes that an agent with shell access as the same user is not blocked, and that a crash between consuming approval and cancelling can lose permission.
Real-world use
- An internal support tool where an AI agent can look up orders but only an operator-approved cancellation can change them.
- An MCP server for finance or inventory actions where the model must not be able to create its own permission.
- A team writing xUnit tests for approval and authorization rules in an agent-facing API before moving to production.
Why it matters
A confirmation generated by the model is not permission; authorization has to live outside the tool call, in a separately recorded, short-lived approval the server checks. The sample shows how to build that boundary, but production use still needs authenticated approval, durable state and audit records.