Build a local TypeScript server

Serve and inspect the local server

Connect the server factory to stdio and test discovery, validation, success, and errors with the official Inspector.

Time to run the server for real. We have a factory with two tools. Now we connect it to a transport and talk to it.

Replace the placeholder src/index.ts with this:

import { serveStdio } from '@modelcontextprotocol/server/stdio'
import { createServer } from './server.js'

void serveStdio(createServer)

Three lines. serveStdio() owns the transport. It reads the opening exchange, picks the protocol era the client speaks, creates one server from our factory, and pins it to that connection. We pass the factory, not a server instance, and the SDK decides when to call it.

The void tells TypeScript we know the promise is not awaited on purpose.

Open the Inspector

The Inspector is the official MCP debugging client. It launches our server, connects to it, and gives us a browser UI to poke at everything. Start it from the project folder:

npx @modelcontextprotocol/inspector npx tsx src/index.ts

Everything after inspector is the command that starts our server. The Inspector prints a local URL and opens it in the browser. Click Connect.

Discovery before execution

Don’t call anything yet. Open the tools list first and read it as a model would: names, descriptions, input schemas, annotations. Both tools should show readOnlyHint: true. If a description is unclear to you here, it will be unclear to a model too, and it will pick the wrong tool.

Now run the calls. search_notes with deploy returns one result, deploy-checklist. get_note with deploy-checklist returns the complete note. Check both the text content and the structured result on each.

Then the bad calls: an empty query, a limit of 20, and an unknown ID. The first two are rejected before the handler runs. The third returns isError: true. Save these four outcomes in TESTING.md. They’re the start of our test matrix.

Watch the terminal

While you click around, look at the terminal that launched the Inspector. Our server_start event may show up there, coming from stderr. That’s fine. What must never appear inside the protocol stream is ordinary log text. If the Inspector shows a JSON parse error right after connecting, something in the process wrote to stdout. Go back to the previous lesson.

Record the versions

Before closing, note the SDK version you tested against:

npm ls @modelcontextprotocol/server

Write it in TESTING.md next to the negotiated protocol revision the Inspector shows.

One caution. A green Inspector session proves the public MCP surface works. It says nothing about authorization, data safety, or production readiness. We’ll test each of those separately.

Lesson completed