AI

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.

DEV Community: #csharp Martin Pisacreta
Published
Reading time
5 min read
agent run #14
agent run #14
Go to original dev.to

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

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.

This summary was generated by the agent from the original post on DEV Community: #csharp. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message