A working demo MCP server that lets an AI agent look up customer order shipment status in natural language. It accompanies the NimblePros post Building Your Own MCP Server in .NET.
The whole point: an MCP server is just another delivery mechanism — the same as a controller. Protocol concerns stay at the presentation layer; the real work lives in testable application handlers.
src/
ShippingStatusMcpServer.Domain Shipment entity, ShipmentStatus, CarrierServiceLevel
ShippingStatusMcpServer.Application Queries, DTOs, MediatR handlers, repository interfaces
ShippingStatusMcpServer.Infrastructure In-memory repository + seed data (swap for EF Core)
ShippingStatusMcpServer The MCP host: Tools, Resources, Prompts, Result->MCP mapping
tests/
ShippingStatusMcpServer.Tests Handler tests + translation-layer tests (xUnit/NSubstitute/Shouldly)
The MCP layer exposes three flavors of the same delegation pattern:
- Tool
GetShipmentStatus(orderNumber) - Resource
shipping://carriers/service-levels - Prompt
DraftDelayNotification(orderNumber)
It ships with in-memory seed data, so it runs with zero database setup. Try
these order numbers: ORD-10432 (in transit), ORD-10500 (delivered),
ORD-10600 (delayed), ORD-10700 (created), and any other value to see the
NotFound path.
- .NET 10 SDK (needed for the
dnxlauncher; the libraries themselves target .NET 8+) - Node.js (only for the MCP Inspector end-to-end test)
dotnet build
dotnet testIMPORTANT: always
dotnet buildfirst, then run with--no-build. A colddotnet runprints build output to stdout, which corrupts the JSON-RPC handshake and gives you a server that silently won't connect.
dotnet build
npx @modelcontextprotocol/inspector dotnet run --project src/ShippingStatusMcpServer --no-buildOpen the printed URL, click List Tools, call GetShipmentStatus with
ORD-10432, and confirm the structured content plus the IsError behavior on a
bad order number.
dotnet build
claude mcp add shipping-status -- dotnet run --project ./src/ShippingStatusMcpServer --no-buildThen ask: "What is the status of order ORD-10432?"
A ready-to-use .vscode/mcp.json is included. Open Copilot Chat in Agent
mode and the shippingStatus tool appears in the tools picker.
The host .csproj is already marked PackAsTool with PackageType=McpServer
and a .mcp/server.json manifest.
dotnet pack -c Release
dotnet nuget push bin/Release/YourCompany.ShippingStatusMcp.1.0.0.nupkg \
--api-key <your-api-key> --source https://api.nuget.org/v3/index.jsonVersions are centralized in Directory.Packages.props. They were current at the
time of writing (mid-2026, .NET 10); the ModelContextProtocol SDK is still
pre-release and moves quickly, so run dotnet restore and bump anything that has
shifted. If a type name in the ModelContextProtocol.Protocol namespace changed
(e.g. CallToolResult, TextContentBlock, StructuredContent), align it with
the installed SDK version.