What the node command does
An entry such as {"command": "node", "args": ["server.js"]} in Claude's MCP config is an instruction to start a program on your machine. Here is everything that follows, message by message.
By the end of this lesson you can
- describe the lifecycle of a local server from spawn to shutdown;
- say what travels on stdin, stdout and stderr, and the one rule about stdout;
- explain how a tool definition ends up in the model's prompt and how a call comes back;
- explain why adding a local server is a supply-chain decision.
A config entry is a command
This is all a host needs to run a local server. There is no URL and no token: the host simply starts the program as a child process.
You picked Remote, so here is the other kind of entry first, for contrast. A remote server is a url, not a command: nothing starts on your machine, and the token comes from OAuth instead of env. The rest of this lesson is about the command kind; the remote side is covered in stdio and Streamable HTTP and The OAuth flow for remote servers.
// a remote entry: the host connects, it does not spawn anything { "mcpServers": { "deployer": { "type": "http", "url": "https://deploy.example.com/mcp" // OAuth on first use; a bearer token on every POST } } }
// an MCP config file (Claude Desktop, Claude Code and others use this shape) { "mcpServers": { "deployer": { "command": "node", "args": ["server.js"], "env": { "DEPLOY_TOKEN": "…" } // stdio servers get credentials from the environment, never OAuth } } }
A parent, a child and three pipes
- The host reads the config and creates an MCP client for this server.
- It spawns
node server.jsas a child process, with the working directory and environment from the config. The child runs as you. - The host writes requests to the child's stdin: one JSON-RPC message per line, no embedded newlines.
- The server writes responses to its stdout. Each line is one JSON-RPC message, and nothing else may appear there.
- Logs go to stderr. The host may capture them, but never parses them as protocol.
- A stray
console.logon stdout is a line that is not JSON-RPC: the client's parser chokes. This is the classic first bug in a hand-written stdio server. - To stop the server, the host closes stdin. End-of-file is the goodbye; the server should exit, and the host escalates to SIGTERM and SIGKILL only if it lingers.
Spec rule
A server MUST NOT write anything to stdout that is not a valid MCP message. Servers SHOULD exit promptly when stdin is closed.
Step through a local server's life
Three lanes: the model, the host with its client, and the server process. Use Next, Play or the arrow keys, or click any message in the diagram.
From tool list to the model's prompt
Notice where the model appears in the stepper: only at steps 6, 7 and 10. Everything else is the host and the server talking. What the model receives is not JSON-RPC but a tool definition in its own API format, usually renamed to mcp__deployer__deploy so two servers can both offer a tool called deploy.
- Tool definitions are what the model will read. Their size is the context cost of the server, paid on every turn (lesson 14 does the arithmetic).
- Text from a server is text in your prompt. The
instructionsfield of the discover result and every tool description land in front of the model. - The host decides before anything runs. The model emits a
tool_useblock; the host may ask you to approve it, then routes it to the right client.
Spec principle
Hosts must obtain explicit user consent before invoking any tool.
It runs as you
Key idea
Adding a local server means running that program with your permissions. It can read what you can read and call what you can call. That is why a local server is a supply-chain decision, not a settings change.
Common misconception
“The model only calls the tools it is given, so a local server is sandboxed by MCP.” MCP does not sandbox anything. The process can do whatever your account can do, whether or not the model ever calls a tool. Sandboxing, if you want it, is the host's or your operating system's job.
Quick check
Your stdio server needs to print debugging output. Where should it go?
How does a host ask a stdio server to shut down gracefully?
What does the model produce when it wants to use the deploy tool?
Recap
- A
commandentry makes the host spawn a child process and talk to it over its pipes. - stdin carries requests, stdout carries only protocol, stderr carries logs.
- Discover, list, add tools to the prompt, model emits
tool_use, consent,tools/call, result back to the model. - Shutdown is closing stdin. The server runs with your permissions the whole time.