mcp-local-gateway

mcp-local-gateway

Minimal MCP server exposing a single tool, run_date, to execute the local date command via a Streamable HTTP endpoint.

Category
Visit Server

README

mcp-local-gateway

P0 goal: run a minimal local MCP server that exposes exactly one tool, run_date, through a Streamable HTTP /mcp endpoint.

This project is intentionally small. It does not expose arbitrary Bash. It does not use an OpenAI API key. It is designed for this validation chain:

ChatGPT Web
  -> HTTPS /mcp
  -> Cloudflare Tunnel or another HTTPS tunnel
  -> 127.0.0.1:8787
  -> Hono
  -> MCP Server
  -> policy layer
  -> fixed date command

Terms

  • MCP: Model Context Protocol, 模型上下文协议,用来让 AI Host 通过标准协议发现并调用外部工具。
  • Streamable HTTP: 可流式 HTTP 传输,适合远程 MCP server。
  • Hono: 轻量 HTTP framework,HTTP 框架。
  • OAuth: Open Authorization,开放授权。P0 只预留结构,不实现完整授权码流程。
  • Policy layer: 策略层,本项目中用于拒绝任意命令,只允许 run_date -> date

Requirements

  • Node.js >= 20.11
  • npm
  • Linux / WSL recommended

Install

cd ~/project/mcp-local-gateway
npm install
cp .env.example .env

Start

npm run dev

Expected startup lines:

mcp-local-gateway listening on http://127.0.0.1:8787
health: http://127.0.0.1:8787/healthz
mcp:    http://127.0.0.1:8787/mcp
auth:   off

Local validation

In another terminal:

cd ~/project/mcp-local-gateway
npm run typecheck
npm run build
npm test
npm run test:local

The tools/list response should include run_date. The tools/call response should include JSON text containing stdout from the local date command.

Persistent user service / 用户级常驻服务

Use the user-level systemd service when you want the gateway to keep running after the terminal closes.

npm run service:install
npm run service:status
npm run service:logs
npm run service:uninstall

service:install runs npm run build and starts dist/index.js; it does not use npm run dev. The service keeps running after the terminal exits. Cloudflare Tunnel access to mcp.songlei.me depends on this service listening on 127.0.0.1:8787.

Persistent OpenAI Tunnel / OpenAI Tunnel 常驻运行

Use the user-level systemd service when you want tunnel-client to keep the OpenAI Tunnel process running after the terminal closes.

npm run tunnel:install
npm run tunnel:status
npm run tunnel:logs
npm run tunnel:uninstall

tunnel:install runs npm ci and npm run build, checks tunnel-client, ~/.config/homelab-mcp/openai-tunnel.env, and ~/.config/tunnel-client/homelab-stdio.yaml, then installs openai-tunnel-client.service. The service uses WorkingDirectory at the repository root, loads ~/.config/homelab-mcp/openai-tunnel.env, and runs:

tunnel-client run --profile homelab-stdio --health.listen-addr 127.0.0.1:18080 --health.url-file /tmp/homelab-openai-tunnel-stdio-health.url --log.file /tmp/homelab-openai-tunnel-stdio.log

After install, the script runs systemctl --user daemon-reload, enable, restart, and status for openai-tunnel-client.service, then waits for both /healthz and /readyz to succeed through the URL written to /tmp/homelab-openai-tunnel-stdio-health.url.

Static bearer mode

Use this before exposing through a tunnel if you are not using OAuth yet.

cat > .env <<'ENDENV'
HOST=127.0.0.1
PORT=8787
MCP_AUTH_MODE=static_bearer
MCP_STATIC_BEARER_TOKEN=replace-this-with-a-long-random-token
MCP_ALLOWED_ORIGINS=http://127.0.0.1:8787,http://localhost:8787,https://chatgpt.com
AUDIT_TO_STDOUT=true
AUDIT_LOG_FILE=logs/audit.jsonl
ENDENV

npm run dev

Validation with token:

MCP_STATIC_BEARER_TOKEN='replace-this-with-a-long-random-token' npm run test:local

Cloudflare Tunnel sketch

Do not bind this server to 0.0.0.0. Keep HOST=127.0.0.1 and publish it with a tunnel.

Example target mapping:

https://mcp.songlei.me/mcp -> http://127.0.0.1:8787/mcp

After that, create a ChatGPT connector and set Connector URL to:

https://mcp.songlei.me/mcp

P0 recommendation: use static bearer only for a private short-lived test. P1 should implement OAuth / OIDC token validation or put the MCP server behind a compatible identity-aware proxy.

Security constraints in P0

  • No arbitrary Bash.
  • run_date accepts no arguments.
  • Command execution uses spawn with shell: false.
  • Server refuses HOST=0.0.0.0.
  • /mcp checks Origin when Origin is present.
  • /mcp can enforce static Bearer token.
  • Each tool call writes JSONL audit records.

File map

src/index.ts              entry point
src/config.ts             environment config and startup safety checks
src/http/app.ts           Hono app, health endpoint, /mcp route
src/http/origin.ts        Origin allowlist guard
src/auth/auth.ts          off/static_bearer/oauth_placeholder auth middleware
src/mcp/server.ts         MCP server creation and tool registration
src/mcp/transport.ts      Streamable HTTP transport creation
src/tools/run-date.ts     run_date MCP tool
src/policy/policy.ts      P0 allow/deny logic
src/shell/exec-fixed.ts   fixed date command execution
src/audit/audit.ts        JSONL audit logger
scripts/local-validate.sh curl-based validation script
test/*.test.ts            minimal unit tests

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