If you're juggling multiple MCP servers across Claude Desktop, Cursor, or VS Code, this hub consolidates them into a single endpoint. It supports stdio, HTTP, and SSE transports, proxies remote MCP servers, and manages npx-based servers on the fly. You configure all your servers once in hatago.config.json, including filesystem, GitHub, or custom APIs, then point your client at the hub instead of wiring each server individually. The v0.0.14 release cut startup time by 8x and added tag-based filtering so you can load different server groups per environment. It forwards progress notifications, expands environment variables Claude-style, and exposes a hatago://servers resource for introspection. Helpful if you maintain a stable toolchain across multiple AI coding assistants without duplicating configuration.
English | 日本語
Hatago (旅籠) — A relay point connecting modern AI tools with MCP servers.
Hatago MCP Hub is a lightweight hub that unifies access to multiple MCP (Model Context Protocol) servers from tools like Claude Code, Codex CLI, Cursor, Windsurf, and VS Code.
docs/README.mdpackages/mcp-hub/README.mdDev.to: Getting Started with Multi-MCP Using Hatago MCP Hub — One Config to Connect Them All
npx @himorishige/hatago-mcp-hub serve --httpnodemon --exec "hatago serve --http" --watch hatago.config.jsonpm2 start "hatago serve" --watch hatago.config.jsonnotifications/tools/list_changed notificationnotifications/progresshatago://servers - JSON snapshot of currently connected servers (id, status, type, tools, resources, prompts)${VAR} and ${VAR:-default} syntaxextends field for DRY principleExternal packages (server/test-utils) use a thin IHub interface to avoid tight coupling with the concrete class.
import type { IHub } from '@himorishige/hatago-hub';
import { createHub } from '@himorishige/hatago-hub/node';
const hub: IHub = createHub({
preloadedConfig: { data: { version: 1, mcpServers: {} } }
}) as IHub;
await hub.start();
hub.on('tool:called', (evt) => {
/* metrics, logs */
});
await hub.stop();
Extracted modules for thin hub:
packages/hub/src/rpc/handlers.tspackages/hub/src/http/handler.tspackages/
├── mcp-hub/ # Main npm package (@himorishige/hatago-mcp-hub)
├── server/ # Server implementation (@himorishige/hatago-server)
├── hub/ # Hub core (@himorishige/hatago-hub)
├── core/ # Shared types (@himorishige/hatago-core)
├── runtime/ # Runtime components (@himorishige/hatago-runtime)
├── transport/ # Transport layer (@himorishige/hatago-transport)
├── cli/ # CLI tools (@himorishige/hatago-cli)
├── hub-management/ # Management components (@himorishige/hatago-hub-management)
└── test-fixtures/ # Test utilities
# Initialize configuration
npx @himorishige/hatago-mcp-hub init
# Start in STDIO mode (for Claude Code)
# NOTE: STDIO requires a config file path
npx @himorishige/hatago-mcp-hub serve --stdio --config ./hatago.config.json
# Or start in HTTP mode without a config (demo/dev)
npx @himorishige/hatago-mcp-hub serve --http
# Install globally
npm install -g @himorishige/hatago-mcp-hub
# Use with hatago command
hatago init
hatago serve
# Install as dependency
npm install @himorishige/hatago-mcp-hub
# Add to package.json scripts
{
"scripts": {
"mcp": "hatago serve"
}
}
Add to .mcp.json:
{
"mcpServers": {
"hatago": {
"command": "npx",
"args": [
"@himorishige/hatago-mcp-hub",
"serve",
"--stdio",
"--config",
"./hatago.config.json"
]
}
}
}
Add to ~/.codex/config.toml:
[mcp_servers.hatago]
command = "npx"
args = ["-y", "@himorishige/hatago-mcp-hub", "serve", "--stdio", "--config", "./hatago.config.json"]
Add to .mcp.json:
{
"mcpServers": {
"hatago": {
"url": "http://localhost:3535/mcp"
}
}
}
Add to ~/.codex/config.toml:
[mcp_servers.hatago]
command = "npx"
args = ["-y", "mcp-remote", "http://localhost:3535/mcp"]
For testing and debugging:
# Start in HTTP mode
hatago serve --http --port 3535
# Connect with MCP Inspector
# Endpoint: http://localhost:3535/mcp
Visit MCP Inspector
Enable lightweight in-memory metrics and expose an HTTP endpoint:
HATAGO_METRICS=1 hatago serve --http --port 3535
# Then visit: http://localhost:3535/metrics
Notes:
HATAGO_LOG=json (respecting HATAGO_LOG_LEVEL).Create hatago.config.json:
{
"$schema": "https://raw.githubusercontent.com/himorishige/hatago-mcp-hub/main/schemas/config.schema.json",
"version": 1,
"logLevel": "info",
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
{
"mcpServers": {
"deepwiki": {
"url": "https://mcp.deepwiki.com/sse",
"type": "sse"
},
"custom-api": {
"url": "https://api.example.com/mcp",
"type": "http",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
}
}
}
Group servers with tags in a single configuration file:
{
"mcpServers": {
"filesystem-dev": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
"tags": ["dev", "local"]
},
"github-prod": {
"url": "https://api.github.com/mcp",
"type": "http",
"tags": ["production", "github"]
},
"database": {
"command": "mcp-server-postgres",
"tags": ["dev", "production", "database"]
}
}
}
Start with specific tags:
# Only start servers tagged as "dev"
hatago serve --tags dev
# Start servers with either "dev" or "test" tags
hatago serve --tags dev,test
# Japanese tags are supported
hatago serve --tags 開発,テスト
Split configurations by environment using the extends field:
Base configuration (~/.hatago/base.config.json):
{
"version": 1,
"logLevel": "info",
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
}
}
}
Work configuration (./work.config.json):
{
"extends": "~/.hatago/base.config.json",
"logLevel": "debug",
"mcpServers": {
"github": {
"env": {
"GITHUB_TOKEN": "${WORK_GITHUB_TOKEN}",
"DEBUG": null
}
},
"internal-tools": {
"url": "https://internal.company.com/mcp",
"type": "http",
"headers": {
"Authorization": "Bearer ${INTERNAL_TOKEN}"
}
}
}
}
Features:
"extends": ["./base1.json", "./base2.json"]~, relative, and absolute pathsnull to remove inherited env vars| Strategy | Tag-based | Inheritance-based |
|---|---|---|
| Files | Single config | Multiple configs |
| Switch | --tags option | --config option |
| Management | Centralized | Distributed |
| Best for | Team sharing, Simple setups | Complex environments, Personal customization |
Supports Claude Code compatible syntax:
${VAR} - Expands to the value of VAR (error if undefined)${VAR:-default} - Uses default value if VAR is undefinedhatago initCreate configuration file with interactive setup:
hatago init # Interactive mode
hatago init --mode stdio # STDIO mode config
hatago init --mode http # HTTP mode config
hatago init --force # Overwrite existing
hatago serveStart MCP Hub server:
hatago serve --stdio --config ./hatago.config.json # STDIO mode (default, requires config)
hatago serve --http # HTTP mode (config optional)
hatago serve --config custom.json # Custom config
hatago serve --verbose # Debug logging
hatago serve --tags dev,test # Filter servers by tags
hatago serve --env-file ./.env # Load variables from .env before start (repeatable)
hatago serve --env-override # Override existing env vars when using --env-file
Use --env-file <path...> to load variables before config parsing. This helps resolve ${VAR} and ${VAR:-default} placeholders without exporting variables globally.
KEY=VALUE, export KEY=VALUE, # comments, blank lines.\n, \r, \t.~/ expanded to home.process.env keys are preserved unless --env-override is provided.import { startServer } from '@himorishige/hatago-mcp-hub';
// Start server programmatically
await startServer({
mode: 'stdio',
config: './hatago.config.json',
logLevel: 'info'
});
import { createHub } from '@himorishige/hatago-mcp-hub';
const hub = createHub({
mcpServers: {
memory: {
command: 'npx',
args: ['@modelcontextprotocol/server-memory']
}
}
});
// Use hub directly in your application
const tools = await hub.listTools();
Client (Claude Code, etc.)
↓
Hatago Hub (Router + Registry)
↓
MCP Servers (Local, NPX, Remote)
@modelcontextprotocol/server-filesystem@modelcontextprotocol/server-github@modelcontextprotocol/server-memoryhttps://mcp.deepwiki.com/sse)"No onNotification handler set" warning
Server connection failures
--verbose flag for detailed logsTool name collisions
# Enable verbose logging
hatago serve --verbose
# Check server status
hatago status
Contributions are welcome! Please see our GitHub repository for more information.
MIT License
Built with the Hono and the Model Context Protocol SDK by Anthropic.