The examples all wrap one upstream: a zero-dependency Node server with an OpenAPI 3.1 description, in sample-api/ of the examples repository. It is small on purpose. Five operations are enough to exercise every decision a real integration has to make.
Files in the repository
Every snippet on this page comes from these files; open them to see the whole thing.
Run it
git clone https://github.com/apitoagents/mcp-examples
cd mcp-examples
node sample-api/server.mjs
It listens on 127.0.0.1:4010, serves its own description at /openapi.json, answers /health, and requires the header X-API-Key: demo-key on everything else. Data lives in memory and resets on restart.
The operations
GET /products?q&category&limit&cursor: full-text search over ten products in three categories, paginated with an opaque cursor.limitmust be 1 to 20.GET /products/{productId}: one product.POST /orderswith anIdempotency-Keyheader: creates an order for one product. The same key with the same payload returns the original order with200instead of201; the same key with a different payload is a409.GET /orders/{orderId}: one order.POST /orders/{orderId}/cancel: cancels an order that has not shipped. Irreversible;409if it already is.
Errors are JSON with a code (invalid_input, unauthorized, not_found, idempotency_conflict, order_not_cancellable) and a message.
Why five operations become four tools
searchProductsandgetProductbecome the read toolssearch_productsandget_product.createOrderbecomescreate_order. TheIdempotency-Keyheader is the interesting part: a generator will expose it as a raw input calledIdempotency-Key, while the examples name itidempotencyKeyand explain in the description that the assistant should generate one per user request and reuse it on retry.cancelOrderbecomescancel_order, a guarded tool that refuses to act until the assistant has shown the user the order and received an explicit confirmation.getOrderis not exposed at all. It is called internally bycancel_orderto show the user what will be cancelled. Exposing it would add nothing for the user and one more thing for the assistant to choose between.
That last point is the general rule: the tool list is designed from what a customer wants to get done, then mapped onto the API, not the other way round. The generator comparison shows what happens when it is done the other way round.
Try it with curl
curl -H "X-API-Key: demo-key" "http://127.0.0.1:4010/products?q=lamp&limit=2"
curl -H "X-API-Key: demo-key" -H "Idempotency-Key: demo-0001" \
-H "Content-Type: application/json" \
-d '{"productId":"p-1002","quantity":2}' http://127.0.0.1:4010/orders
# Repeat the exact request: same order back, status 200, no duplicate.
Next: build the server that wraps it in TypeScript, Python, C# or PHP.