Unified MCP Hub for managing multiple Model Context Protocol servers
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.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @himorishige/hatago-mcp-hubMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-himorishige-hatago-mcp-hub": {
"command": "npx",
"args": [
"-y",
"@himorishige/hatago-mcp-hub"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceio.github.himorishige/hatago-mcp-hub works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.