Skip to main content
Glama
pugazece

hello-mcp-server

by pugazece

hello-mcp-server

Simple MCP server — TypeScript ESM ("type": "module"), tsx, Express + Streamable HTTP transport.

Streamable HTTP (POST/GET/DELETE /mcp) was picked for scale / larger audience. It is the current MCP standard; legacy SSE (/sse + /messages) is deprecated.

Prereqs

Node >= 22.5 (uses built-in node:sqlite, no extra DB deps)

Related MCP server: http-mcp-server

Setup

npm install
cp .env.example .env   # optional, default PORT=3081

Run

npm run dev        # tsx watch src/index.ts
npm start          # tsx src/index.ts
npm run build && npm run start:prod  # compiled dist/

Server:

  • POST/GET/DELETE http://localhost:3081/mcp

  • GET http://localhost:3081/health

  • GET http://localhost:3081/metrics — counts, avg latency, per-tool stats

  • GET http://localhost:3081/traces?limit=50 — recent HTTP traces

  • GET http://localhost:3081/traces/:traceId — HTTP + tool calls for one trace

Try it

Health:

curl http://localhost:3081/health

MCP Inspector:

npx @modelcontextprotocol/inspector
# Transport: Streamable HTTP, URL: http://localhost:3081/mcp
# Call tool `hello` with { "name": "pugazh" }

Structure

src/
  index.ts                  # bootstrap only (config, listen, graceful shutdown)
  config.ts                 # env: PORT, SQLITE_PATH, LOG_LEVEL, LOG_PRETTY
  logger.ts                 # pino (pretty in dev, JSON in prod)
  observability/
    trace.ts                # AsyncLocalStorage trace context
    db.ts                   # node:sqlite init + schema
    repository.ts           # logHttp/logTool/getMetrics/listRecentTraces/getTraceDetail
    index.ts                # barrel
  mcp/
    server.ts               # createMcpServer() - registers all tools
    sessions.ts             # McpSessionStore (sessionId -> transport map)
    tools/
      withTracing.ts        # runTracedTool() shared wrapper
      hello.ts              # hello tool
      observability.ts      # get_metrics / list_traces / get_trace tools
  http/
    app.ts                  # createApp() - middleware + route wiring
    middleware/             # trace.ts (X-Trace-Id), requestLogger.ts (pino-http)
    routes/                 # health.ts, observability.ts, mcp.ts

Rules: HTTP layer never touches SQLite directly (via observability/); MCP tools never touch Express (via runTracedTool); index.ts only bootstraps. Add a tool = new file in mcp/tools/ + one line in mcp/server.ts.

MCP tools

Tool

Input

Returns

hello

{ name? }

Hello, {name or world}!

get_metrics

HTTP + tool-call stats, per-tool / per-route breakdowns

list_traces

{ limit? }

Recent HTTP traces, newest first

get_trace

{ trace_id }

HTTP + tool calls for one trace

From VS Code Copilot (Agent mode): What do the server metrics say? or Show me the trace for <traceId>. From the Inspector: call them like any tool. Plain-HTTP mirrors: GET /metrics, /traces, /traces/:id.

Logs (pino + pino-pretty)

Every request prints a pretty line to the terminal in dev (src/logger.ts, via pino-http; req.id is the X-Trace-Id, so terminal lines join to the SQLite traces below). Tool calls log a tool called line, session init/close and bad-session warnings are logged too.

LOG_LEVEL=debug npm run dev   # trace/debug lines
LOG_PRETTY=false npm start    # JSON lines (production style)

Dual sink: the terminal stays pretty in dev, and every line is also appended as JSON to LOG_FILE (default logs/app.log, auto-created, git-ignored) — same events, grep-able and tail-able:

tail -f logs/app.log
cat logs/app.log | python3 -c "import sys,json; [print(json.loads(l)['msg'], json.loads(l).get('traceId')) for l in sys.stdin]"
LOG_FILE=false npm run dev      # terminal only
LOG_FILE=/tmp/mcp.jsonl npm start  # custom path

Rotation is built in (pino-roll, no logrotate needed): the file rolls daily or at 10m, keeping 14 rotated files + the active one (logs/app.1.log, app.2.log, …). Tune via LOG_ROTATE_FREQUENCY (daily|hourly|<ms>), LOG_ROTATE_SIZE (10m, 500k, 1g), LOG_ROTATE_KEEP. Shutdown flushes the file transport first, so no trailing lines are lost.

Note: GET /mcp holds an SSE stream open, so its request line prints when the stream closes — that is expected.

Why you saw nothing before: telemetry only went to SQLite; stdout only had startup lines. Now both exist: stdout (pino) + SQLite (/metrics, /traces).

Observability & traceability (node:sqlite)

Zero-dependency SQLite via node:sqlite (src/observability/, DB at SQLITE_PATH, default data/mcp.db, WAL mode). Every request gets X-Trace-Id (pass your own or one is generated); it propagates via AsyncLocalStorage into MCP tool handlers, so HTTP + tool calls share one trace_id.

Tables: http_requests, tool_calls. New tools stay traceable via the shared wrapper (src/mcp/tools/withTracing.ts):

const text = await runTracedTool("my_tool", { arg }, async () => {
  return "result";
});
curl http://localhost:3081/metrics
curl http://localhost:3081/traces?limit=20
curl http://localhost:3081/traces/<traceId>

Add tools

New file in src/mcp/tools/ (see hello.ts) → register it in src/mcp/server.ts. Zod defines the input schema. Always go through runTracedTool so stdout + SQLite tracing stay automatic.

Scale note

Stateful by default via McpSessionStore (src/mcp/sessions.ts). For horizontal scale without sticky sessions, switch to stateless mode (sessionIdGenerator: undefined, no store) — see comment there.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    Not graded
    maintenance
    A minimal reference implementation of an MCP server that responds with "Hello, World" via Streamable HTTP. Serves as a baseline for integration testing and MCP client development with production-ready features including health checks, metrics, and containerized deployment.
    3
    27,117
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Mock HTTP server implementing MCP (Model Context Protocol) with streamable HTTP transport, health endpoint, and example tools like echo and time.
    152
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    A minimal MCP server offering a hello_world tool that returns a greeting and current UTC time via streamable HTTP.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables per-profile tool filtering and enforcement for one or more upstream MCP servers, exposing only allowed tools and rejecting blocked calls, with Streamable HTTP serving and observability.
    863,678
    MIT