JanusMCP
About
Local, open-source multi-account MCP broker — one endpoint, every account. Add credentials once and switch identity without reconnecting, from any LLM client.
Details
- License
- MIT
Explore
| | |
|---|---|
| Multi-account, one endpoint | N identities for the same service, no reconnecting |
| Identity scoping | per-call → per-session (Mcp-Session-Id) → global, via bindingMode: global \| session \| locked |
| Dual transport | stdio (local-first clients) + Streamable HTTP (remote-first clients), same process |
| Secure vault | OS keychain (macOS/Windows/Linux) + encrypted-file fallback; secrets as vault:<name> |
| OAuth loopback | janusmcp login (PKCE), tokens stored in the vault, auto-refresh, oauth:<name> |
| Context-safe | only the active account's tools are exposed; switching emits tools/list_changed |
Setting up with Highlight
This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:
- Download and install Highlight from highlightai.com/download
- Navigate to the plugins tab and select "Add Custom Plugin"
-
Configure the plugin with the settings below
Plugin Name
JanusMCPCommand (node, npx, python, etc.)Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.
- Enable "Start Automatically" if you want the plugin to start when Highlight launches
From the repository
Once released, install via your favorite channel (all published automatically on each
tag — see RELEASING.md):
npx @bayway/janusmcp serve # npm (works inside MCP/npx setups)
brew install bayway/janusmcp/janusmcp # Homebrew (macOS/Linux)
scoop install janusmcp # Windows
docker run --rm -p 7332:7332 ghcr.io/bayway/janusmcp:latest
…or download a prebuilt binary from Releases.
git clone https://github.com/bayway/janusmcp
cd janusmcp/go
make build # produces ./bin/janusmcp
cp config.example.json config.json # edit with your accounts
./bin/janusmcp serve # stdio, for Claude Desktop/Code
Two Supabase clients, PATs kept in your OS keychain (never in the config):
./bin/janusmcp vault set supabase_client_a # paste the PAT
./bin/janusmcp vault set supabase_client_b
// config.json
{
"bindingMode": "session",
"accounts": [
{ "id": "client_a", "service": "supabase", "command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase@latest", "--read-only", "--project-ref=REF_A"],
"env": { "SUPABASE_ACCESS_TOKEN": "vault:supabase_client_a" } },
{ "id": "client_b", "service": "supabase", "command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase@latest", "--read-only", "--project-ref=REF_B"],
"env": { "SUPABASE_ACCESS_TOKEN": "vault:supabase_client_b" } }
]
}
Add it to Claude Desktop:
{ "mcpServers": { "janusmcp": {
"command": "/abs/path/janusmcp/go/bin/janusmcp", "args": ["serve"],
"env": { "JANUS_CONFIG": "/abs/path/janusmcp/go/config.json" } } } }
For ChatGPT / Gemini / Cursor / Copilot, run HTTP and point them at the URL:
```bash
JANUS_TRANSPORT=http JANUS_HTTP_PORT=7332 ./bin/janusmcp serve
Loading every MCP tool definition into an LLM context is expensive. In code-execution
mode an agent (or you) invokes tools on demand from the shell instead — à la
"code execution with MCP" —
so the context holds only the results it actually asked for:
janusmcp tools # compact list for the active account/profile
janusmcp tools client_a # ...or any account/profile explicitly
janusmcp schema list_tables # full input schema of ONE tool, only when needed
janusmcp call list_tables --args '{"schemas":["public"]}'
janusmcp call ping --account azienda_b # cross-account without switching
echo '{"sql":"select 1"}' | janusmcp call db_query # JSON args via stdin too
call prints the tool's text content to stdout and exits non-zero on a tool error, so
it composes with pipes and scripts. Selectors resolve exactly like in the broker: the
persisted active account by default, or any account id / profile name; a name that
collides across a profile's accounts must be disambiguated with --account. Secrets
resolve through the same vault/OAuth stack as serve — nothing extra to configure.
Claude Desktop / Cursor
Paste into your MCP client config file to install this server.
{
"mcpServers": {
"janusmcp": {
"janusmcp": {
"command": "npx",
"args": [
"@bayway/janusmcp",
"serve",
"#",
"npm",
"(works",
"inside",
"MCP/npx",
"setups)"
]
}
}
}
}
McpServers
{
"janusmcp": {
"command": "npx",
"args": [
"@bayway/janusmcp",
"serve",
"#",
"npm",
"(works",
"inside",
"MCP/npx",
"setups)"
]
}
}
One MCP endpoint, every account.
Add your credentials once, switch identity without reconnecting — from any LLM.
<br/>
<sub>One-click buttons require the npm package to be published. See <a href="RELEASING.md">RELEASING.md</a>.</sub>
</div>
The problem
If you work with more than one company, you use the same MCP server (Supabase, GitHub,
Slack…) with different identities — a different account, email and token per client.
Today most LLM clients hold one account at a time per connector: to switch client you
disconnect, reconnect, and redo the OAuth login. Every time.
The MCP protocol has no notion of "account": one session = one identity = one set of
credentials. JanusMCP fills that gap.
What it does
JanusMCP is a local broker that sits between your LLM client and the real MCP servers:
- Add N accounts once for the same service and keep them all available.
- Switch identity without reconnecting — no re-login, no fiddling with config.
- Works with any LLM client — it just speaks standard MCP (stdio + Streamable HTTP).
- Runs locally — your machine, your keychain, your control.
- Keeps the context clean — it exposes only the active account's tools, not N×tools.
┌─────────────────────────────┐ ┌─ Supabase (Client A)
LLM client ─MCP─▶│ JanusMCP broker │─▶ ├─ Supabase (Client B)
(Claude/GPT/ │ active-account · vault · │ ├─ GitHub (Client A)
Gemini/…) │ per-session scoping │ └─ …
└─────────────────────────────┘
You drive it with three control tools that appear in any client:
janus_list_accounts, janus_use_account, janus_whoami.
Install
Once released, install via your favorite channel (all published automatically on each
tag — see RELEASING.md):
npx @bayway/janusmcp serve # npm (works inside MCP/npx setups)
brew install bayway/janusmcp/janusmcp # Homebrew (macOS/Linux)
scoop install janusmcp # Windows
docker run --rm -p 7332:7332 ghcr.io/bayway/janusmcp:latest
…or download a prebuilt binary from Releases.
Build from source (60-second quickstart)
git clone https://github.com/bayway/janusmcp
cd janusmcp/go
make build # produces ./bin/janusmcp
cp config.example.json config.json # edit with your accounts
./bin/janusmcp serve # stdio, for Claude Desktop/Code
Two Supabase clients, PATs kept in your OS keychain (never in the config):
./bin/janusmcp vault set supabase_client_a # paste the PAT
./bin/janusmcp vault set supabase_client_b
// config.json
{
"bindingMode": "session",
"accounts": [
{ "id": "client_a", "service": "supabase", "command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase@latest", "--read-only", "--project-ref=REF_A"],
"env": { "SUPABASE_ACCESS_TOKEN": "vault:supabase_client_a" } },
{ "id": "client_b", "service": "supabase", "command": "npx",
"args": ["-y", "@supabase/mcp-server-supabase@latest", "--read-only", "--project-ref=REF_B"],
"env": { "SUPABASE_ACCESS_TOKEN": "vault:supabase_client_b" } }
]
}
Add it to Claude Desktop:
{ "mcpServers": { "janusmcp": {
"command": "/abs/path/janusmcp/go/bin/janusmcp", "args": ["serve"],
"env": { "JANUS_CONFIG": "/abs/path/janusmcp/go/config.json" } } } }
For ChatGPT / Gemini / Cursor / Copilot, run HTTP and point them at the URL:
```bash
JANUS_TRANSPORT=http JANUS_HTTP_PORT=7332 ./bin/janusmcp serve
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.



