DEV Community

Cover image for How to run a local MCP server in typeScript with node 23 without a build step
Yves Jutard
Yves Jutard

Posted on

How to run a local MCP server in typeScript with node 23 without a build step

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"
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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

It works!
Claude Settings showing the valid active MCP

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)

Collapse
 
offirmo profile image
Offirmo

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...