How to Test an MCP Server: Vitest, In-Memory Transport, Streamable HTTP and the Inspector CLI A developer published a three-layer testing approach for Model Context Protocol (MCP) servers using Vitest and the official TypeScript SDK, covering pure tool functions, the MCP contract (tool lists, schemas, results and errors), and the transport layer, with the full suite running in about 300 ms. The writeup, drawn from work on the developer's Benchline browser-tools project, uses InMemoryTransport.createLinkedPair() with a real SDK Client to exercise tools without an AI client, plus MCP Inspector CLI commands for manual checks of Streamable HTTP behavior such as 200 on initialize, 406 on wrong Accept headers and 405 on GET for stateless servers. It was tested against @modelcontextprotocol/sdk 1.32.2, Vitest 5.0.5 and Node 22.20. Cross-posted from my blog. The original, with any updates, lives on fabwaseem.com https://fabwaseem.com/blog/test-mcp-server . Testing an MCP server means checking three layers: the pure functions behind your tools, the MCP contract tool list, schemas, results and errors , and the transport your clients actually use. You can cover all three with Vitest and the official TypeScript SDK, without starting an AI client, and the whole suite below runs in about 300 ms. I wrote this while building Benchline https://fabwaseem.com/projects/benchline , my set of browser tools that are also a stateless MCP server. Every tool there is a pure function first and an MCP tool second, and that split is what makes testing easy. Below is a small, complete example server you can copy, the tests I run against it, and the MCP Inspector CLI commands for manual checks. Everything was run with @modelcontextprotocol/sdk 1.32.2, Vitest 5.0.5 and Node 22.20, and I re-ran the full suite on October 31, 2026 1.32.2 is still the latest SDK release with the same result. InMemoryTransport.createLinkedPair and a real SDK Client : list tools, check schemas, call each tool, and assert on errors. initialize returns 200, wrong Accept headers get 406, GET gets 405 on a stateless server. npx @modelcontextprotocol/inspector --cli