Skip to main content
Glama
Pongsapat1035

mcp-express-bolierplate

MCP Node.js Boilerplate

Boilerplate for building an MCP client and MCP server with Node.js + TypeScript, using Express on the HTTP side. Supports both

  • stdio — the client launches the server as a child process, suitable for MCP hosts running locally

  • Streamable HTTP — endpoint at /mcp, exposed over HTTPS via Cloudflare Tunnel

  • mock tools for CRUD users

  • static resource users://all and resource template users://{id}

  • summarize-users prompt

  • CLI client for discovery, calling tools, reading resources, and requesting prompts

Initial data lives in src/data/users.json and is loaded into memory when the server starts. Changes made through CRUD do not overwrite the file and are reset when the process restarts.

Requirements

  • Node.js 20 or later

  • npm

  • cloudflared only if you need an HTTPS tunnel

Related MCP server: MCP TypeScript Starter

Install

npm install

Check the build and tests:

npm run check

Key structure

src/
├── client/
│   └── client.ts          # MCP CLI client ใช้ได้ทั้ง stdio และ HTTP
├── data/
│   └── users.json         # mock seed data
├── lib/
│   └── api-client.ts      # shared Axios instance สำหรับ upstream APIs
├── services/
│   └── user-service.ts    # business logic กลางสำหรับ MCP capabilities
└── server/
    ├── mcp.ts             # ประกอบ server และ capability registrations
    ├── tools/
    │   └── user-tools.ts
    ├── resources/
    │   └── user-resources.ts
    ├── prompts/
    │   └── user-prompts.ts
    ├── schemas/
    │   └── user.ts        # shared MCP output schema
    ├── repository.ts      # in-memory CRUD repository
    ├── stdio.ts           # stdio entry point
    └── http.ts            # Express + Streamable HTTP entry point
scripts/
└── build.mjs              # compile TypeScript และ copy mock JSON ไป dist

The factory in mcp.ts is shared by both transports, so the server's capabilities are identical. Tools, Resources, and Prompts call the shared UserService instead of binding directly to a repository.

Calling External APIs with Axios

The project includes a shared Axios instance at src/lib/api-client.ts with a base URL, timeout, and optional Bearer token. You can import it for use in a tool or service:

import { apiClient } from "../../lib/api-client.js";

const response = await apiClient.get("/users");
console.log(response.data);

Set the values when starting the server:

API_BASE_URL=https://api.example.com \
API_TIMEOUT_MS=10000 \
API_TOKEN=your-token \
npm run server:http

Example of using it in an MCP tool:

server.registerTool(
  "list-upstream-users",
  {
    description: "List users from the configured upstream API",
    inputSchema: z.object({}),
  },
  async () => {
    const { data } = await apiClient.get("/users");
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
      structuredContent: { users: data },
    };
  },
);

If API_BASE_URL is not set, you can still pass an absolute URL directly to Axios. Avoid logging API_TOKEN, and store the token in a secret manager when deploying to production.

Running with stdio

Normally you don't need to start the stdio server separately, because the client or MCP host spawns the process itself.

Run the demo client, which starts the server, discovers capabilities, calls tools, reads resources, and requests a prompt:

npm run client:stdio -- demo

Start the server directly to wait for an MCP host:

npm run server:stdio

Caution: stdio uses stdout as the JSON-RPC channel, so server logs must go through stderr, e.g. console.error only.

Example config for an MCP host, replacing /absolute/path/to/mcp-boilerplate with the actual path:

{
  "mcpServers": {
    "mock-users": {
      "command": "node",
      "args": [
        "--import",
        "tsx",
        "/absolute/path/to/mcp-boilerplate/src/server/stdio.ts"
      ],
      "cwd": "/absolute/path/to/mcp-boilerplate"
    }
  }
}

Or build first and use JavaScript without relying on tsx at runtime:

npm run build
npm run start:stdio

Config after the build:

{
  "mcpServers": {
    "mock-users": {
      "command": "node",
      "args": [
        "/absolute/path/to/mcp-boilerplate/dist/server/stdio.js"
      ],
      "cwd": "/absolute/path/to/mcp-boilerplate"
    }
  }
}

Running with Express HTTP

Terminal 1 — start the server:

npm run server:http

Defaults:

  • MCP endpoint: http://127.0.0.1:3000/mcp

  • health check: http://127.0.0.1:3000/health

Terminal 2 — run the HTTP client:

npm run client:http -- demo

Change the port or host with environment variables:

HOST=127.0.0.1 PORT=4000 npm run server:http
MCP_URL=http://127.0.0.1:4000/mcp npm run client:http -- demo

For a production build:

npm run build
npm run start:http

Exposing HTTPS with Cloudflare Tunnel

In this example HTTPS terminates at Cloudflare, while the Express server still listens on HTTP locally only.

Install cloudflared on macOS:

brew install cloudflared

Terminal 1 — start the MCP HTTP server:

npm run server:http

Terminal 2 — open a Quick Tunnel:

cloudflared tunnel --url http://127.0.0.1:3000

cloudflared will show a temporary URL, e.g.:

https://random-words.trycloudflare.com

The external MCP endpoint is therefore:

https://random-words.trycloudflare.com/mcp

Terminal 3 — test through the HTTPS tunnel:

MCP_URL=https://random-words.trycloudflare.com/mcp npm run client:http -- demo

Quick Tunnel is for development only, and Cloudflare states it does not support SSE, so this boilerplate sets the response mode to auto, which lets ordinary CRUD/discovery calls respond with JSON. However, you should not use Quick Tunnel to test streaming features such as long-lived subscriptions. For production, use a named tunnel, your own hostname, authentication, and authorization.

When using a custom hostname, add it to the allowlist:

ALLOWED_HOSTS=mcp.example.com npm run server:http

Multiple hostnames separated by commas:

ALLOWED_HOSTS=mcp.example.com,mcp-staging.example.com npm run server:http

localhost, 127.0.0.1, ::1, and *.trycloudflare.com are already allowed for development.

MCP client commands

Both client:stdio and client:http use the same format; only the script name changes.

List tools:

npm run client:stdio -- list-tools
npm run client:http -- list-tools

List resources or prompts:

npm run client:stdio -- list-resources
npm run client:stdio -- list-prompts

Call CRUD tools:

npm run client:stdio -- call list-users '{}'
npm run client:stdio -- call get-user '{"id":"1"}'
npm run client:stdio -- call create-user '{"name":"Margaret Hamilton","email":"margaret@example.com","role":"developer"}'
npm run client:stdio -- call update-user '{"id":"1","role":"viewer"}'
npm run client:stdio -- call delete-user '{"id":"3"}'

Read resources:

npm run client:stdio -- read users://all
npm run client:stdio -- read users://1

Request a prompt:

npm run client:stdio -- prompt summarize-users '{"tone":"detailed"}'

For a different HTTP URL, set MCP_URL:

MCP_URL=https://mcp.example.com/mcp npm run client:http -- call list-users '{}'

Note for stdio: each CLI command spawns a new server process, so it always starts from the original mock data. If you want CRUD operations to persist across calls, use an MCP host that keeps the same connection, or start the HTTP server and call it through client:http.

Available tools, resources, and prompts

Type

Name

Purpose

Tool

list-users

View all users

Tool

get-user

View a user by ID

Tool

create-user

Create a user

Tool

update-user

Update a user

Tool

delete-user

Delete a user

Resource

users://all

JSON snapshot of all users

Resource template

users://{id}

JSON of a single user, with ID completion

Prompt

summarize-users

Generate text for a model to summarize user data

Environment variables

Variable

Default

Used for

HOST

127.0.0.1

Express server bind address

PORT

3000

Express server port

MCP_URL

http://127.0.0.1:3000/mcp

HTTP client endpoint

ALLOWED_HOSTS

empty

Add custom Host/Origin values the server accepts

API_BASE_URL

unset

Base URL of the upstream API that Axios calls

API_TIMEOUT_MS

10000

Axios request timeout in milliseconds

API_TOKEN

unset

Bearer token that Axios attaches automatically

Example values are in .env.example. The project does not auto-load the .env file; export the variables or prefix them to the command as shown in the examples above.

Security notes

  • This example has no authentication or authorization; do not expose a public endpoint with real data.

  • Host and Origin validation only allows localhost, TryCloudflare, and values from ALLOWED_HOSTS.

  • The mock repository lives in memory and intentionally does not persist data.

  • For production, add auth, rate limiting, audit logging, a persistent database, and TLS/trust-proxy configuration suited to your real system.

All scripts

npm run dev:stdio       # stdio server พร้อม watch mode
npm run dev:http        # Express HTTP server พร้อม watch mode
npm run server:stdio    # stdio server จาก TypeScript
npm run server:http     # Express HTTP server จาก TypeScript
npm run client:stdio -- demo
npm run client:http -- demo
npm run build
npm run start:stdio     # รัน dist หลัง build
npm run start:http      # รัน dist หลัง build
npm test
npm run check

References: MCP TypeScript SDK, Cloudflare Quick Tunnels

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A simple MCP server that exposes a createUser tool to add users to a local JSON file via stdio transport.
    247
    1
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A sample MCP server that exposes tools, resources, and prompts for managing users and todos, supporting both stdio and Streamable HTTP transports.
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables creating MCP (Model Context Protocol) servers with zero boilerplate, full TypeScript support, and multiple transports (stdio and HTTP).
    10
    1
    MIT

View all related MCP servers

Related MCP Connectors

  • An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform

  • A basic MCP server to operate on the Postman API.

  • A MCP server built for developers enabling Git based project management with project and personal…

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Pongsapat1035/mcp-express-bolierplate'

If you have feedback or need assistance with the MCP directory API, please join our Discord server