mcp-express-bolierplate

mcp-express-bolierplate

Enables creation of MCP servers with both stdio and HTTP transports, providing CRUD tools, resources, and prompts for user management, along with a CLI client for testing and integration.

Category
Visit Server

README

MCP Node.js Boilerplate

Boilerplate สำหรับสร้าง MCP server และ Gemini agent ด้วย Node.js + TypeScript โดยฝั่ง HTTP ใช้ Express รองรับทั้ง

  • stdio — client เปิด server เป็น child process เหมาะกับ MCP host ที่รันในเครื่อง
  • Streamable HTTP — endpoint อยู่ที่ /mcp และนำออกเป็น HTTPS ได้ด้วย Cloudflare Tunnel
  • mock tools สำหรับ CRUD users
  • static resource users://all และ resource template users://{id}
  • prompt summarize-users
  • MCP Inspector สำหรับ discovery, เรียก tool, อ่าน resource และขอ prompt
  • Gemini agent ที่รับภาษาธรรมชาติและเลือกเรียก MCP tools ผ่าน OpenAI-compatible API

ข้อมูลเริ่มต้นอยู่ที่ src/data/users.json และถูกโหลดเข้า memory เมื่อเปิด server การแก้ไขผ่าน CRUD จะไม่เขียนทับไฟล์ และจะ reset เมื่อ restart process

Requirements

  • Node.js 22.19 ขึ้นไป
  • npm
  • cloudflared เฉพาะกรณีต้องการ HTTPS tunnel
  • Gemini API key เฉพาะกรณีรัน Agent client

ติดตั้ง

npm install

ตรวจ build และ test:

npm run check

โครงสร้างสำคัญ

src/
├── agent/
│   ├── agent.ts           # Gemini tool-calling loop สำหรับภาษาธรรมชาติ
│   └── mcp-transport.ts   # MCP transport สำหรับ Agent
├── 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

Factory ใน mcp.ts ถูกใช้ร่วมกันทั้งสอง transport ทำให้ความสามารถของ server ไม่ต่างกัน โดย Tools, Resources และ Prompts เรียก UserService กลางแทนการผูกกับ repository โดยตรง

เรียก External API ด้วย Axios

โปรเจกต์มี shared Axios instance ที่ src/lib/api-client.ts พร้อม base URL, timeout และ optional Bearer token สามารถ import ไปใช้ใน tool หรือ service ได้:

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

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

กำหนดค่าตอนเปิด server:

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

ตัวอย่างนำไปใช้ใน 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 },
    };
  },
);

หากไม่กำหนด API_BASE_URL ยังสามารถส่ง absolute URL ให้ Axios ได้โดยตรง หลีกเลี่ยงการ log API_TOKEN และควรเก็บ token ใน secret manager เมื่อ deploy production

วิธีรันแบบ stdio

ปกติไม่ต้องเปิด stdio server แยก เพราะ Inspector, Agent หรือ MCP host จะ spawn process ให้เอง

เปิด MCP Inspector พร้อม stdio server:

npm run inspector:stdio

เปิด server ตรง ๆ เพื่อรอ MCP host:

npm run server:stdio

ข้อควรระวัง: stdio ใช้ stdout เป็นช่อง JSON-RPC ดังนั้น log ของ server ต้องเขียนผ่าน stderr เช่น console.error เท่านั้น

ตัวอย่าง config สำหรับ MCP host โดยเปลี่ยน /absolute/path/to/mcp-boilerplate เป็น path จริง:

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

หรือ build ก่อนแล้วใช้ JavaScript โดยไม่ต้องพึ่ง tsx ตอน runtime:

npm run build
npm run start:stdio

config หลัง build:

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

วิธีรันแบบ Express HTTP

Terminal 1 — เปิด server:

npm run server:http

ค่า default:

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

Terminal 2 — เปิด MCP Inspector และเชื่อมต่อ /mcp:

npm run inspector:http

เปลี่ยน port หรือ host ได้ด้วย environment variables:

HOST=127.0.0.1 PORT=4000 npm run server:http
npx @modelcontextprotocol/inspector --server-url http://127.0.0.1:4000/mcp --transport http

สำหรับ production build:

npm run build
npm run start:http

เปิด HTTPS ด้วย Cloudflare Tunnel

HTTPS ในตัวอย่างนี้ terminate ที่ Cloudflare ส่วน Express server ยังฟัง HTTP เฉพาะในเครื่อง

macOS ติดตั้ง cloudflared:

brew install cloudflared

Terminal 1 — เปิด MCP HTTP server:

npm run server:http

Terminal 2 — เปิด Quick Tunnel:

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

cloudflared จะแสดง URL ชั่วคราว เช่น:

https://random-words.trycloudflare.com

MCP endpoint ภายนอกจึงเป็น:

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

Terminal 3 — ทดสอบผ่าน HTTPS tunnel:

npx @modelcontextprotocol/inspector --server-url https://random-words.trycloudflare.com/mcp --transport http

Quick Tunnel เหมาะสำหรับ development เท่านั้น และ Cloudflare ระบุว่าไม่รองรับ SSE ดังนั้น boilerplate นี้ตั้ง response mode เป็น auto ซึ่งคำสั่ง CRUD/discovery ทั่วไปจะตอบ JSON ได้ แต่ไม่ควรใช้ Quick Tunnel ทดสอบฟีเจอร์ที่ต้อง stream เช่น subscription ระยะยาว สำหรับ production ให้ใช้ named tunnel, hostname ของตนเอง, authentication และ authorization

เมื่อใช้ custom hostname ให้เพิ่ม hostname ใน allowlist:

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

หลาย hostname คั่นด้วย comma:

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

localhost, 127.0.0.1, ::1 และ *.trycloudflare.com ถูกอนุญาตไว้สำหรับ development แล้ว

MCP Inspector

Inspector เป็นเครื่องมือหลักสำหรับตรวจ Server โดยไม่ผ่านโมเดล ใช้ดูและเรียก Tools, Resources และ Prompts ผ่าน Web UI

stdio — Inspector จะ spawn server ให้:

npm run inspector:stdio

HTTP — เปิด npm run server:http ก่อน แล้วรัน:

npm run inspector:http

สำหรับ remote URL:

npx @modelcontextprotocol/inspector --server-url https://mcp.example.com/mcp --transport http

Inspector v2 ต้องใช้ Node.js 22.19 ขึ้นไป ตัว server และ Agent จึงกำหนด Node.js requirement เดียวกันเพื่อลดความต่างระหว่าง development กับ production

Gemini MCP Agent

agent.ts มี MCP Client อยู่ภายในเพื่อเชื่อม Server, ส่ง MCP tool schemas ให้ Gemini, รัน tool calls และส่งผลกลับให้โมเดลจนได้คำตอบสุดท้าย

User prompt → Gemini → MCP tool call → MCP Server → tool result → Gemini → answer

สร้างไฟล์ .env และใส่ API key:

cp .env.example .env
GEMINI_API_KEY=your_real_key
GEMINI_MODEL=gemini-3.7-flash

รัน interactive agent ผ่าน stdio โดยไม่ต้องเปิด server แยก:

npm run agent:stdio

หรือส่งคำถามครั้งเดียว:

npm run agent:stdio -- "แสดงผู้ใช้ทั้งหมด"
npm run agent:stdio -- "สร้างผู้ใช้ชื่อ John อีเมล john@example.com role developer"

สำหรับ HTTP ให้เปิด server ใน Terminal 1:

npm run server:http

แล้วเปิด Agent ใน Terminal 2:

npm run agent:http

หรือ one-shot:

npm run agent:http -- "ดูรายละเอียด user ID 1"

Agent ใช้ OpenAI SDK กับ Gemini OpenAI-compatible endpoint ค่า GEMINI_BASE_URL จึงสามารถเปลี่ยนได้หากต้องการใช้ compatible gateway อื่น แต่ tool-calling compatibility ของแต่ละ provider อาจไม่เหมือนกันทั้งหมด

Model compatibility

Agent ใน boilerplate นี้ยังไม่ได้ model-agnostic 100% โดยผูกกับ OpenAI-compatible Chat Completions API, โครงสร้าง tool_calls และ OpenAI SDK แต่ไม่ได้ผูกกับ Gemini SDK โดยตรง

  • Gemini: ใช้ได้ทันทีผ่าน Gemini OpenAI-compatible endpoint ตามค่า default
  • OpenAI: ใช้ได้โดยตั้ง GEMINI_BASE_URL เป็น OpenAI API base URL และกำหนด API key/model ของ OpenAI ในตัวแปรเดิม
  • Anthropic native API: ยังใช้โดยตรงไม่ได้ เพราะ message และ tool-use schema ต่างจาก OpenAI-compatible API ต้องเพิ่ม Anthropic adapter หรือใช้ gateway ที่แปลงเป็น OpenAI-compatible API

ตัวแปรยังใช้ prefix GEMINI_ เพราะ Gemini เป็น provider ตัวอย่างของ boilerplate นี้ ตัวอย่างการชี้ไป OpenAI:

GEMINI_API_KEY=your_openai_api_key
GEMINI_MODEL=your_openai_model
GEMINI_BASE_URL=https://api.openai.com/v1/

หากต้องการรองรับหลาย provider ใน production ควรแยก interface เช่น ModelProvider แล้วสร้าง adapter สำหรับ Gemini/OpenAI/Anthropic โดยให้ MCP client และ tool execution loop ใช้ interface กลางร่วมกัน

Tools, resources และ prompt ที่มีให้

ชนิด ชื่อ หน้าที่
Tool list-users ดู users ทั้งหมด
Tool get-user ดู user ตาม ID
Tool create-user สร้าง user
Tool update-user แก้ไข user
Tool delete-user ลบ user
Resource users://all JSON snapshot ของ users ทั้งหมด
Resource template users://{id} JSON ของ user รายคน พร้อม ID completion
Prompt summarize-users สร้างข้อความให้โมเดลสรุปข้อมูล users

Environment variables

ตัวแปร Default ใช้กับ
HOST 127.0.0.1 Express server bind address
PORT 3000 Express server port
MCP_URL http://127.0.0.1:3000/mcp HTTP endpoint ที่ Agent เชื่อมต่อ
MCP_ACCESS_TOKEN ไม่กำหนด Bearer token สำหรับ remote MCP server
ALLOWED_HOSTS ว่าง เพิ่ม custom Host/Origin ที่ server ยอมรับ
GEMINI_API_KEY จำเป็นสำหรับ Agent Gemini API key
GEMINI_MODEL gemini-3.7-flash โมเดลที่ Agent ใช้
GEMINI_BASE_URL Gemini OpenAI-compatible URL Model API endpoint
AGENT_MAX_TOOL_STEPS 10 จำนวน tool-call rounds สูงสุดต่อคำถาม
API_BASE_URL ไม่กำหนด Base URL ของ upstream API ที่ Axios เรียก
API_TIMEOUT_MS 10000 Axios request timeout หน่วยมิลลิวินาที
API_TOKEN ไม่กำหนด Bearer token ที่ Axios แนบให้อัตโนมัติ

ตัวอย่างค่าอยู่ใน .env.example โดย Agent จะโหลด .env อัตโนมัติผ่าน dotenv ส่วน Server และ Inspector ให้ export ตัวแปรหรือใส่ไว้หน้าคำสั่งตามตัวอย่างด้านบน

Security notes

  • ตัวอย่างนี้ยังไม่มี authentication และ authorization ห้ามเปิด public endpoint ที่มีข้อมูลจริง
  • validation ของ Host และ Origin เปิดเฉพาะ localhost, TryCloudflare และค่าจาก ALLOWED_HOSTS
  • mock repository อยู่ใน memory และตั้งใจไม่ persist ข้อมูล
  • สำหรับ production ควรเพิ่ม auth, rate limiting, audit logging, persistent database และ TLS/trust-proxy configuration ที่เหมาะกับระบบจริง

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 agent:stdio
npm run agent:http
npm run inspector:stdio
npm run inspector:http  # ต้องเปิด server:http ก่อน
npm run build
npm run start:stdio     # รัน dist หลัง build
npm run start:http      # รัน dist หลัง build
npm run start:agent:stdio
npm run start:agent:http
npm test
npm run check

อ้างอิง: MCP TypeScript SDK, MCP Inspector, Gemini OpenAI compatibility, OpenAI Chat Completions, Cloudflare Quick Tunnels

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured