I experimented with writing and running a local MCP server in TypeScript and I ran into difficulties having it properly called from Claude.
In this article, I'll share the working config and the issues I encountered.
Prerequisite: MCP server code
I copy/pasted the TypeScript example from Claude documentation.
Goal: Direct Local execution
Claude rightfully recommends using TypeScript and suggests a build step to convert .ts
to .js
. However node >23.6 now supports direct execution of TypeScript with type stripping, so the build step felt unnecessary ❌.
TL:DR; Here is the working config:
Final, working, Claude's local config.json
:
{
"mcpServers": {
"hello-world": {
"command": "/Users/sam/.nvm/nvm-exec",
"env": {
"NODE_VERSION": "23"
},
"args": [
"node",
"--disable-warning=ExperimentalWarning --experimental-strip-types",
"/Users/sam/work/src/mcp/module/src/index.ts"
]
}
}
}
Issues encountered and solutions
Everything path must be absolute
Claude's config doesn't perform any path interpolation or env inheritance, so everything has to be explicitly declared and all paths have to be absolute. No ~
or $HOME
or PATH
preset:
"command": "/Users/sam/.nvm/nvm-exec"
"/Users/sam/work/src/mcp/module/src/index.ts"
Calling the right node
I'm using nvm
to manage my node runtimes. Even after installing the latest node 23 with nvm install 23
, calling node
from Claude yielded another version. The solution is to use nvm-exec
with an env variable NODE_VERSION=23
, see the config above. Note that nvm-exec
must be referenced with an absolute path.
Stdout pollution
Since node 23's --experimental-strip-types
is considered experimental, there is a warning message displayed on invocation. Since the local MCP protocol relies on stdin/stdout, this warning message disrupted the protocol.
The solution is to silence this warning with --disable-warning=ExperimentalWarning
Conclusion
I hope you'll overcome those issues faster thanks to this post. Good luck experimenting with MCP! Comments and reactions are appreciated 😊
Top comments (1)
Thanks!
Running MCP servers locally is the first step. After that, running them on a remotely accessible server makes them easy to distribute: blog.cloudflare.com/remote-model-c...