{"slug": "show-hn-language-for-api-calls-load-tests-and-mcp-server", "title": "Show HN: Language for API calls, load tests and MCP server", "summary": "Stampdrill released a plain-text API testing language in which requests, assertions, test plans, load tests and race tests are stored as reviewable `.stamp` files that run identically in the macOS app, in CI and from the open-source `stampdrill` command. The macOS 14+ app costs $49.99 on the Mac App Store, while the engine and CLI are free and open source; the tool covers HTTP, GraphQL, WebSockets and MCP servers, and imports Postman, Insomnia and Bruno collections, HAR files, curl commands and OpenAPI documents. Stampdrill replaces per-environment copies with named dimensions (for example `env` and `region`) whose variable sets apply by specificity, and adds load testing with virtual users, ramp-up, think time and pass/fail thresholds on percentiles, error rate and throughput.", "body_md": "### Plain text, always\n\nRequests are `.stamp` files: readable in any editor, reviewable in a pull request, and never locked inside an app.\n\nOne `.stamp` file holds the request, the assertions, the test plan, the load test and the race test. It diffs in a pull request, merges like code, and runs the same way for a person, for CI, and for an agent. HTTP, GraphQL, WebSockets and MCP servers; no account, no cloud workspace, nothing leaving your Mac but the requests you send.\n\n[Get Stampdrill](#get-it)\n[Read the language](language/)\n\nFor macOS 14 or later. $49.99 on the Mac App Store. The engine and the `stampdrill` command are free and open source.\n\nA request file is short enough to read at a glance. Open it in Stampdrill to send it with a click, or run it from a shell with the same dimensions selected.\n\napi/orders.stamp\n\n```\n@base = {{host}}/api\n\n### Log in\nPOST {{base}}/login\nContent-Type: application/json\n\n{ \"username\": \"{{username}}\", \"password\": \"{{password}}\" }\n\n> assert status == 200\n> set token = body.token\n\n### Orders\n@needs logIn\n@auth bearer {{token}}\nGET {{base}}/orders?limit=20\n\n> assert all(body.items, o => o.total > 0)\n> print length(body.items) + \" orders\"\n```\n\nTerminal\n\n``` bash\n$ stamp run api/orders.stamp env=staging region=latam\n→ POST https://api.staging.latam.example.com/api/login  orders.stamp › logIn\n  200 OK  142 ms  612 bytes\n  ✓ status == 200\n\n→ GET https://api.staging.latam.example.com/api/orders?limit=20  orders.stamp › orders\n  200 OK  88 ms  4 KB\n  ✓ all(body.items, o => o.total > 0)\n  │ 20 orders\n\n✓ 2 requests, 2 assertions\n```\n\nMost tools give you a list of environments, so *staging-latam*, *staging-mena* and *prod-latam* each become a copy to keep in step. Stampdrill lets you name the axes instead. Variable sets say where they apply, the most specific one wins, and `*` means any value.\n\nenvironment.stamp\n\n```\ndimension env = test, staging, prod\ndimension region = latam, mena, apac, dach\n\nvars {\n  host = localhost(8080)\n}\n\nvars env=staging|prod {\n  host = \"api.\" + env + \".\" + region + \".example.com\"\n}\n\nvars env=prod {\n  password = secret(getenv(\"PROD_PASSWORD\"))\n}\n```\n\nSwiftUI and AppKit, fast to launch and quiet in use. Form or source editing on the same file, with the file watched for changes, and an [editor extension](https://marketplace.visualstudio.com/items?itemName=StampDrill.stampdrill) when you would rather stay in VS Code.\n\n`stamp run`, `test` and `load` read exactly what the app reads, with exit codes and JUnit, HTML or JSON reports for CI.\n\nA dimension is one axis your API varies along: the environment, the region, the kind of account. Name the axes once, pick a value for each or leave one on any, and the matching variables follow.\n\nCheck responses, pass values between requests with `set`, keep personal ones with `save`, and write your own functions and lambdas.\n\nSteps, loops, conditions, retries and timeouts, run over a matrix of dimensions and CSV or JSON data, in parallel.\n\nVirtual users with ramp-up, think time and pass or fail thresholds on percentiles, error rate and throughput, drawn live.\n\n`concurrently` starts actors together and `sync` lines them up on the same instant, to catch double spends and lost updates.\n\nRealistic names, addresses and companies, related records that belong together, and bodies generated from JSON Schema. Same seed, same data.\n\nScript a socket conversation, send GraphQL operations, check STUN and TURN servers, and test the MCP servers you build for AI assistants.\n\nBearer, JWT, Basic, API keys in headers or queries, and OAuth 2 tokens fetched and reused until they expire. Tokens and passwords in responses stay blurred until you click them.\n\nCompare a run against an earlier one: status, timing and size, the headers that moved, the tests that started failing, and a line diff of the body with the noise filtered out.\n\nImport Postman, Insomnia and Bruno collections with their environments, HAR files, curl commands and OpenAPI documents. Tokens found along the way go to a file git ignores. Side by side: [Postman](compare/postman/) and [Bruno](compare/bruno/).\n\nA workspace is a folder of text files that sits in the repository next to your code. Personal values go to a file Stampdrill keeps out of git.\n\nUnknown variables, broken expressions and missing dependencies are flagged as you type, and `stamp check` finds them before CI sends anything.\n\nDouble-click a `.stamp` file to open its workspace with that file selected. Existing `.http` files are read too.\n\nJSON as text, a tree or a sortable table, CSV as a table, images, PDFs, HTML, XML and hex. Save a body, or the whole exchange as a readable transcript.\n\nPlans sit next to the requests they run. A matrix repeats a plan for every combination of dimensions, data files add rows, and every iteration gets its own session so tokens never leak between them.\n\n`concurrently` starts actors at the same moment and `sync` holds them until all have arrived, so a coupon redeemed ten times at once shows whether only one of them wins. Reports come out as JUnit for CI or HTML for people.\n\n```\nplan Checkout {\n  matrix env = staging|prod, region = *\n  parallel 4\n  retry 2 every 500ms\n\n  setup { run logIn }\n\n  step \"Browse\" {\n    run listProducts with limit = 5\n    expect status == 200\n    expect time < 800\n    set productId = body[0].id\n  }\n\n  concurrently 10 {\n    sync \"go\"\n    run redeemCoupon with code = \"WELCOME\"\n  }\n  expect count(results, r => r.status == 200) == 1\n}\n```\n\nVirtual users start over a ramp and the run is judged against thresholds on percentiles, errors and throughput, charted while it happens.\n\nWith a seed, every scenario run gets its own repeatable random data, and keyed values like `uuid(\"order\")` tie the create and the lookup of one run together. `share` hands ids from one virtual user to the others.\n\n```\nload Checkout {\n  users 50\n  ramp 30s\n  duration 5m\n  seed checkout-load\n  threshold p95 < 800ms\n  threshold errors < 1%\n\n  scenario {\n    run createOrder with orderId = uuid(\"order\")\n    run getOrder with orderId = uuid(\"order\")\n    share lastOrder = body.id\n  }\n}\n```\n\n`fake` gives names, emails, addresses, companies, prices and dates. `person(7)` is the same person everywhere you use it, with an email made from their name. `mock(schema)` builds a body from JSON Schema, honouring formats, enums and bounds.\n\nSet a seed and every run sends exactly the same data, so a failure today can be replayed tomorrow.\n\n```\n@seed = checkout-tests\n\n### Sign up\nPOST {{base}}/users\n\n{\n  \"id\": \"{{uuid(\"user\")}}\",\n  \"name\": \"{{person(7).name}}\",\n  \"email\": \"{{person(7).email}}\",\n  \"company\": \"{{fake.company}}\",\n  \"profile\": {{ json(mock(readJson(\"./schemas/profile.json\"), \"user-7\")) }}\n}\n```\n\nScript a WebSocket conversation with `send` and `receive` and read it back as a timeline. Send GraphQL operations with their variables.\n\nCheck that STUN and TURN servers answer, and that they accept your credentials, before a video call depends on them.\n\n```\n### Chat\nWS wss://chat.example.com/socket\n\n> send json({ type: \"hello\" })\n> receive 5s\n> assert data.type == \"welcome\"\n\n### Countries\nGRAPHQL https://countries.trevorblades.com/graphql\n\nquery { country(code: \"IQ\") { name capital } }\n\n### Can calls connect?\nSTUN stun:stun.l.google.com:19302\n\n> assert body.rtt < 200\n```\n\n`MCP` connects to a Model Context Protocol server the way an AI assistant would, over Streamable HTTP or by starting it with `stdio:`. After the handshake, a script calls tools, reads resources and gets prompts, and asserts on what comes back, including the errors a well-behaved server should return.\n\nWhen the server asks the client for something, `@sampling`, `@elicitation` and `@roots` answer, so those paths get tested too. In the app, every tool gets a form built from its input schema, and **Save as Test** turns a call and its answer into lines of the script.\n\n```\n### Weather server\n@sampling reply Sunny, 24°C\nMCP stdio: node build/index.js\n\n> assert toolNames contains \"forecast\"\n> let paris = call(\"forecast\", { city: \"Paris\" })\n> assert !paris.isError\n> assert paris.text contains \"°C\"\n> assert read(\"weather://cities\").text != \"\"\n> assert request(\"no/such\").error.code == -32601\n```\n\n`stampdrill` is free. It runs requests, test plans, load tests and MCP server tests from the same workspace as the app, exits with 1 when a check fails and 2 when a file has errors, prints secrets masked, and writes reports your CI already understands. There are builds for macOS and fully static builds for Linux on x86_64 and arm64.\n\nInstall\n\n```\nbrew install stampdrill/tap/stampdrill\n```\n\nGitHub Actions\n\n```\n- name: API tests\n  run: |\n    curl -sL https://github.com/stampdrill/stampdrill/releases/latest/download/stampdrill-linux-x86_64.tar.gz | tar xz\n    ./stamp test api --junit reports/junit.xml\n```\n\nIn a pipeline\n\n```\nstamp check .\nstamp test . --tags smoke \\\n  --junit reports/junit.xml --html reports/plans.html\nstamp load . --json reports/load.json\n```\n\n| `stamp run` | send requests, and test MCP servers, from a file or a folder | \n| `stamp test` | run test plans, with JUnit and HTML reports | \n| `stamp load` | run load tests and check their thresholds | \n| `stamp list` | show the requests a file or folder contains | \n| `stamp check` | find problems without sending anything | \n| `stamp env` | show dimensions and what variables resolve to | \n| `stamp import` | bring in Postman, Insomnia, Bruno, HAR, curl and OpenAPI files | \n\nThe Stamp language, the runner, every transport and the `stampdrill` command are on [GitHub](https://github.com/stampdrill/stampdrill) under the Mozilla Public License, with the language reference, examples, a VS Code grammar and an agent skill under MIT. Build it yourself, read what it sends, keep using it if this app disappears.\n\nThe skill teaches an agent the conventions, dimensions instead of copied environments, secrets out of shared files, and `stamp check` gives it an exit code to verify its own work against. The app is where you read what it wrote.\n\nClaude Code\n\n```\n/plugin marketplace add stampdrill/stampdrill\n/plugin install stampdrill@stampdrill\n```\n\nStampdrill is $49.99 on the Mac App Store, for macOS 14 or later. It opens with an example workspace that talks to public test APIs, so there is something to send right away.", "url": "https://wpnews.pro/news/show-hn-language-for-api-calls-load-tests-and-mcp-server", "canonical_source": "https://stampdrill.com/", "published_at": "2026-11-14 08:05:20+00:00", "updated_at": "2026-11-14 08:19:55.623947+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "agent-protocols", "ai-tools"], "entities": ["Stampdrill", "Mac App Store", "Postman", "Insomnia", "Bruno", "Visual Studio Code", "GraphQL", "OpenAPI"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-language-for-api-calls-load-tests-and-mcp-server", "markdown": "https://wpnews.pro/news/show-hn-language-for-api-calls-load-tests-and-mcp-server.md", "text": "https://wpnews.pro/news/show-hn-language-for-api-calls-load-tests-and-mcp-server.txt", "jsonld": "https://wpnews.pro/news/show-hn-language-for-api-calls-load-tests-and-mcp-server.jsonld"}}