janusmcp
JanusMCP
One credential broker. Every account. From the CLI or MCP. Multi-account tool access for AI agents, with credentials kept local.
One-click buttons require the npm package to be published. See RELEASING.md.
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.
Related MCP server: qiaomu-llm-mcp
What it does
JanusMCP is a local multi-account tool broker for AI agents. It can be used directly from the CLI or as an MCP server in front of the real upstream 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).
Works without an MCP session too — agents can drive it directly from the CLI (code-execution mode):
janusmcp tools/schema/callinvoke tools on demand, with no bulk tool definitions loaded upfront.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.
Choose your mode
Use from the CLI — Claude Code, Codex, Cursor, scripts
npm install -g @bayway/janusmcp
janusmcp tools
janusmcp schema list_tables
janusmcp call list_tables --args '{"schemas":["public"]}' --json --timeout 30sThe CLI discovers schemas only when needed, accepts JSON through --args or stdin,
supports explicit accounts/profiles, and provides stable exit codes. See the
CLI guide and copyable agent instructions.
Connect over MCP — desktop and chat clients
npx @bayway/janusmcp serve
# or configure a supported client automatically:
janusmcp install claude-desktopBoth modes share the same config, OS-keychain vault, OAuth tokens and persisted active
account. Use janusmcp daemon start to keep upstream sessions warm across repeated CLI calls.
Install
Once released, install via your favorite channel (all published automatically on each tag — see RELEASING.md):
npx @bayway/janusmcp serve # npm / MCP mode
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/CodeTwo 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:
JANUS_TRANSPORT=http JANUS_HTTP_PORT=7332 ./bin/janusmcp serve
# → http://127.0.0.1:7332/mcpCommands
Run janusmcp help for the full reference. The essentials:
Command | What it does |
| Run the broker (default). Transports via env: |
| Compact tool list for the active (or given) account/profile. |
| Full JSON definition of one tool. |
| Invoke a tool. Supports |
| Persist the active selector for future CLI commands and new MCP sessions. |
| Manage the optional loopback-only daemon that reuses upstream sessions. |
| Open the local control panel — add accounts, log in, set secrets. |
| Add an account from a template ( |
| List the built-in account templates. |
| Connect an account; for remote OAuth, opens the browser. |
| Show each account's login/secret status (no secret values). |
| Store / remove a secret in the OS keychain. |
| OAuth loopback login; token referenced as |
| List built-in OAuth providers. |
| Configure an LLM client to launch JanusMCP. |
| Remove JanusMCP from an LLM client's config. |
| Version · this reference. |
Supported <client> values for install / uninstall: claude-desktop, claude-code,
cursor, vscode, gemini, codex, chatgpt, print. Run janusmcp install list
(or uninstall list) to see each target and whether it's already configured.
janusmcp install claude-desktop # one-command setup
janusmcp uninstall claude-desktop # clean removal (restart the client afterwards)Inside any connected client you also get the control tools janus_list_accounts,
janus_use_account, janus_whoami, janus_login, janus_use_profile, and
janus_with_account.
Profiles — a whole client's stack at once
A profile groups accounts of the same client across different services. Activating it exposes the tools of all its accounts together, and each call is routed to the right upstream:
// config.json
{
"accounts": [
{ "id": "supabase_a", "service": "supabase", "transport": "http", "url": "https://mcp.supabase.com/mcp", "auth": "oauth" },
{ "id": "github_a", "service": "github", "transport": "http", "url": "https://api.githubcopilot.com/mcp/", "auth": "oauth" }
],
"profiles": {
"client_a": ["supabase_a", "github_a"]
}
}Then in chat: janus_use_profile with { "profile": "client_a" } → Supabase and
GitHub tools for Client A are available simultaneously. Colliding tool names across
accounts are namespaced (<account>_<tool>).
One-shot cross-account calls
janus_with_account runs a single call on another account without changing the
active one — e.g. { "account_id": "client_b", "tool": "list_tables" }. Omit tool
to list that account's available tools first.
Code-execution mode — context-efficient tools from the terminal
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
janusmcp call ping --json --timeout 30s # stable envelope for agentscall 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.
This makes JanusMCP a first-class citizen for CLI-driven agents (Claude Code,
Codex, Cursor agents, or any agent with shell access): instead of registering it as
an MCP server, just tell the agent that janusmcp tools / schema / call exist.
Discovery, schemas and invocation happen on demand, credentials stay in the keychain,
and multi-account switching works the same as over MCP. Both modes share the config
and the persisted active account, so you can mix them freely.
For repeated calls, janusmcp daemon start launches an authenticated loopback-only
broker. tools, schema, and call auto-detect it and reuse its upstream sessions;
--direct bypasses it and --daemon requires it. Set JANUS_DAEMON=auto|require|off
to choose a default policy.
Key features
Multi-account, one endpoint | N identities for the same service, no reconnecting |
Identity scoping | per-call → per-session → global, via |
Dual transport | stdio (local-first clients) + Streamable HTTP (remote-first clients), same process. HTTP serves MCP 2026-07-28 and every earlier revision, each on the transport it requires |
Secure vault | OS keychain (macOS/Windows/Linux) + encrypted-file fallback; secrets as |
OAuth loopback |
|
Context-safe | only the active account's tools are exposed; switching emits |
MCP and CLI | same broker as an MCP server or via |
How it's different
The MCP gateway space (MetaMCP, mcp-proxy, IBM ContextForge, …) aggregates different servers behind one endpoint. JanusMCP solves the orthogonal, under-served problem: many identities for the same service, without saturating the model's context, from any LLM, fully local. It's a credential-aware broker, not a flat aggregator.
Built-in connectors
Scaffold an account from a ready-made template with janusmcp add <template> (run
janusmcp catalog for the full, up-to-date list). Most use browser OAuth (dynamic client
registration); a few need extra setup, noted below.
Remote, browser login (OAuth):
supabase,github,notion,sentry,stripe,hubspot,paypal,linear,vercel,canva,neon,netlify,zapier.SSE transport (legacy):
asana,monday,intercom,webflow,wix,square,globalping.Cloudflare (Streamable HTTP):
cloudflare-bindings,cloudflare-observability,cloudflare-radar,cloudflare-builds,cloudflare-browser.Google Workspace (bring-your-own OAuth client):
gmail,google-drive,google-calendar,google-chat— seego/docs/google-workspace.md.Per-account URL:
activecampaign(paste your Remote MCP URL).Figma:
figma-desktop(local, recommended) andfigma(remote, restricted — see below).Generic building blocks:
http-oauth,sse-oauth,supabase-pat,stdio.
Missing one? Add any remote server with http-oauth / sse-oauth, any local one with
stdio, or define your own template in ~/.config/janusmcp/templates.json.
Provider notes
ActiveCampaign
ActiveCampaign ships an official remote MCP server with a unique URL per account (ActiveCampaign → Settings → Developer → Remote MCP URL) and browser-based OAuth — a natural fit for the multi-account broker. Add one account per client:
janusmcp add activecampaign ac_clientA # then paste that client's Remote MCP URL in config.json
janusmcp connect ac_clientA # browser loginBecause the URL is per-account, the template seeds a REPLACE_ACTIVECAMPAIGN_MCP_URL
placeholder you must replace with your own URL. Login uses dynamic client registration, so
no client ID/secret is needed.
Google Workspace (Gmail / Drive / Calendar / Chat)
Google offers remote MCP servers for Gmail, Drive, Calendar and Chat, but — unlike most
providers here — they require your own OAuth client (created in the Google Cloud
Console); they don't support dynamic client registration. JanusMCP supports this via the
oauthClientId / oauthClientSecret / scopes fields, preset by the gmail,
google-drive, google-calendar and google-chat templates:
export GOOGLE_OAUTH_CLIENT_ID=... GOOGLE_OAUTH_CLIENT_SECRET=...
janusmcp add gmail gmail_clientA
janusmcp connect gmail_clientA # browser login as client AFull one-time Google Cloud setup (enable MCP APIs, consent screen, Desktop OAuth client)
and scope details are in go/docs/google-workspace.md.
Figma
Figma offers two MCP servers, handled differently here:
Local Dev Mode server (recommended). Figma's desktop app hosts an MCP server on
http://127.0.0.1:3845/mcp. It's local, needs no OAuth, and works out of the box: enable it in the desktop app (Dev Mode → Inspect → Enable desktop MCP server) and add it withjanusmcp add figma-desktop figma_work. Requires a Dev/Full seat on a paid Figma plan.Remote server (
https://mcp.figma.com/mcp) — restricted. Figma allowlists the OAuthclient_nameduring dynamic client registration and returns 403 Forbidden to any client that isn't in its MCP catalog (VS Code, Cursor, Claude Code, …). JanusMCP is not (yet) an approved client.⚠️ Workaround — opt-in, use at your own risk. You can make JanusMCP register under an approved name by setting
"clientName": "Claude Code"on a remotefigmaaccount in yourconfig.json. This impersonates an approved client and may violate Figma's Terms of Service; it can also break whenever Figma updates its allowlist. It is not enabled by default. Prefer the local Dev Mode server above for real work.The proper long-term fix is for JanusMCP to be submitted to and approved for Figma's MCP catalog, so no
client_nameoverride is needed. This is planned.
Status & roadmap
Alpha — the core is implemented and tested in Go.
Active-account model, per-session / global / locked scoping
stdio + Streamable HTTP transports
MCP 2026-07-28 (stateless core) on both transports, legacy revisions unchanged
OS-keychain vault + encrypted-file fallback
OAuth loopback (PKCE) with auto-refresh and per-spawn token resolution
One-command client install (
janusmcp install …), Claude Desktop.mcpb, registryserver.jsonMulti-server "profiles" per client (Supabase + GitHub + Slack of Client A at once)
with_accountone-shot cross-account callsCLI / code-execution mode (
janusmcp tools/schema/call) — invoke tools on demand instead of loading all definitions, to cut token usageSSE upstream transport (in addition to Streamable HTTP + stdio) for SSE-only servers
Pre-registered OAuth clients (bring-your-own client for servers without dynamic client registration, e.g. Google Workspace)
Built-in connector catalog (25+ services) via
janusmcp catalog/addSigned, per-OS release binaries & registry auto-publish in CI
See design-broker-mcp-multi-account.md for the full design.
Repository layout
go/— the broker (Go). This is the real implementation. Build & docs →spike/— the original TypeScript spike, kept as a verified reference of behavior.design-broker-mcp-multi-account.md— architecture & rationale.docs/— current architecture, compatibility contract, testing, ADRs, and operations.
Project documentation
Privacy Policy
JanusMCP runs entirely on your machine. It has no backend servers, collects no data, and
contains no analytics or telemetry — the developers receive nothing about you or your usage.
Credentials and tokens are stored in your OS keychain (or, if you opt in, an encrypted local
file) and are used only to authenticate to the services you configure; they never pass through
the model context. Network connections are made only to the MCP servers and OAuth providers you
configure. Because everything is local, data is retained only on your own device for as long as
you keep it, and removing it (janusmcp vault delete <name>, or uninstalling) removes it
entirely.
Full policy: https://janusmcp.dev/privacy.
Contributing
Contributions are very welcome — see CONTRIBUTING.md. New connector presets, client integration guides, and packaging help are especially appreciated.
License
MIT — see LICENSE.
Available Tools
5 toolsjanus_list_accountsARead-only
List configured accounts/services and which is active for this session.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description usefully discloses that the result is session-scoped ('active for this session'), which the annotations do not convey, but it says nothing about the idempotentHint=false oddity, pagination, or result shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with zero waste, front-loading the action ('List') and then the two pieces of information returned. Nothing could be trimmed without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless read tool with readOnlyHint, the description covers what is listed and which account is flagged active, which is most of what an agent needs. With no output schema, a brief note on the result shape or ordering would make it fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter semantics to document; the baseline for a parameterless schema is 4. Nothing in the description is needed to clarify inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb 'List' plus resource 'configured accounts/services', and it adds the active-session detail. It does not name or contrast with siblings like janus_use_account or janus_whoami, but the scope is clear enough to distinguish a listing tool from a switching/identity tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implicit usage only: listing accounts naturally precedes janus_use_account, and the 'which is active for this session' phrasing hints at session-awareness. There is no explicit when-to-use, no exclusions, and no routing to alternatives such as janus_whoami.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
janus_loginA
Start an OAuth login for in your browser and store the token as . The token is captured locally and saved to the OS keychain — it never passes through this chat. Afterwards reference it from an account env as "oauth:". Built-in providers: github, google, supabase.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name to store the token under (used as oauth:<name>). | |
| provider | Yes | OAuth provider preset, e.g. github, google. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover safety hints (readOnly=false, openWorld=true, destructive=false, idempotent=false). The description adds material behavior beyond that: a browser window opens, the token is captured locally and saved to the OS keychain, and it never passes through the chat. This is exactly the security-relevant context an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: action first, token-handling detail second, provider list last. No filler, and the most decision-relevant information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-value burden, which it does by explaining the token is saved locally and how to reference it afterwards. Combined with 100% schema coverage, an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameter descriptions already explain 'name' (used as oauth:<name>) and 'provider' (preset, e.g. github, google). The description largely restates this convention rather than adding new syntax or constraints, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (start OAuth login for a provider) and the side effect (store token as <name>). It is clearly distinguishable from siblings like janus_list_accounts or janus_whoami, which do not initiate auth flows.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Tells the agent the follow-up step: reference the token via an account env as "oauth:<name>", and lists built-in providers (github, google, supabase). It gives clear context for when this tool is the right one, but doesn't explicitly state when not to use it or prerequisites (e.g., whether a browser must be available).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
janus_use_accountAIdempotent
Set the active account/identity. Reloads upstream tools and notifies the client. scope: 'session' or 'global' (defaults to the broker bindingMode).
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | ||
| account_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, so the safety profile is already structured. The description adds genuinely useful side-effect context beyond that: the call reloads upstream tools and notifies the client, which tells an agent the tool list may change after invocation. It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short clauses, front-loaded with the core action before the side effects and the scope note. No filler or restatement of the name. The parenthetical default could be phrased more tightly, but nothing is wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter state setter with no output schema, the description covers purpose, side effects, and the scope default. Annotations carry the safety profile. The remaining gap is account_id semantics and any failure behavior for an invalid account, which keeps it short of fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for two parameters, so the description must compensate. It does explain the scope enum values and its default ('defaults to the broker bindingMode'), which is real added value. The required account_id gets no semantics at all – no format, no hint that it should come from janus_list_accounts – leaving half the surface undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Set the active account/identity.' That is unambiguous and an agent can distinguish it from janus_whoami (read current identity) or janus_list_accounts. It does not explicitly contrast itself with the closest sibling, janus_with_account, which is a scoped variant of the same idea.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the name and by 'Set the active account/identity' – an agent can infer this is the tool to call when switching identity. However, there is no explicit when-to-use guidance, no statement of when to prefer janus_with_account or janus_login instead, and no mention of prerequisites such as needing an existing authenticated session.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
janus_whoamiBRead-only
Return the active account for this session and how it was resolved.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so safety is covered. The description adds real value by signaling that resolution provenance is returned ('how it was resolved'), but it does not explain the odd non-idempotent hint or the shape of the resolution detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with the subject front-loaded and no wasted words. Appropriate size for a no-arg query tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-param read tool with annotations covering safety, this is nearly adequate, but with no output schema the description should hint at the returned fields (account identity, resolution source) to fully prepare the agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Return') and resource ('the active account for this session'), plus the extra dimension of 'how it was resolved'. This is clearly distinct from siblings like janus_login or janus_use_account, though it never explicitly names or contrasts with them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to call this versus janus_list_accounts or the other session tools. The phrase 'for this session' implies a diagnostic/context-check use case, but the agent must infer that entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
janus_with_accountA
Run a single tool call on another account WITHOUT changing the active account. Omit 'tool' to first list that account's available tools.
| Name | Required | Description | Default |
|---|---|---|---|
| tool | No | Tool to call; omit to list the account's tools. | |
| arguments | No | Arguments object for the tool. | |
| account_id | Yes | Target account id. | |
| full_schema | No | When listing, include complete tool definitions. Intended for CLI discovery. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, openWorldHint=true, and idempotentHint=false, so the safety posture is partly covered. The description adds the key non-obvious behavior that the active account is left untouched, but does not disclose side effects, auth requirements, or what happens to the invoked tool's writes. Adequate, not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences with the primary behavior and its distinguishing constraint front-loaded, followed by the discovery fallback. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an open-world meta-tool with no output schema, the description covers the core modes (invoke vs. list) and the account-scoping behavior well. It omits behavioral detail on the arbitrary tools it may invoke, which is a minor gap given annotations carry the safety profile.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the schema. The description's mention of omitting 'tool' to list tools duplicates what the schema already states about the tool parameter, adding no syntax or format detail beyond it. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Run a single tool call on another account') plus a critical scope constraint ('WITHOUT changing the active account') that implicitly separates it from the sibling janus_use_account. An agent can tell what this does and what it is not without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'WITHOUT changing the active account' clause establishes clear context for when to use this over janus_use_account, and the description instructs how to discover tools ('Omit tool to first list that account's available tools'). It stops short of naming the alternative sibling explicitly or stating exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.6.2- First observed
janus_list_accounts - First observed
janus_login - First observed
janus_use_account - First observed
janus_whoami - First observed
janus_with_account
TDQS
Scored across 5 tools
Each tool has a distinct action: listing, logging in, switching active account, checking identity, and one-off account-scoped execution. There is minor overlap between janus_list_accounts and janus_whoami since both can reveal the active account, but their descriptions make the distinction workable.
All tools share the janus_ prefix and use consistent snake_case naming. The verb-based patterns (list_accounts, login, use_account, whoami, with_account) are predictable and readable despite whoami being a conventional special case.
Five tools is well-scoped for an account/identity management server. Each tool earns its place, covering discovery, authentication, active-account control, identity inspection, and temporary account switching without unnecessary extras.
The core account lifecycle is covered: listing, OAuth login, setting active identity, checking identity, and running a one-off call under another account. A logout/forget-account operation is a minor gap, but agents can work around it and the essential workflows are present.
Maintenance
Related MCP Connectors
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
One MCP endpoint for Claude, GPT & Gemini: 100+ tools + no-code connectors + agent workers.
Connect MCP clients to 2,000+ AI models without managing provider API keys.
- 0bridgeOAuthdev.0bridge
Every service you connect, one MCP endpoint for all your AI tools. Sign in once.
Related MCP Servers
- AlicenseAqualityCmaintenanceAn MCP server that enables users to query, compare, and synthesize responses from multiple local and cloud LLMs simultaneously using existing subscriptions. It provides tools for parallel model evaluation, consensus polling with an LLM-as-judge, and response synthesis across different model providers.830 npm15MIT
- AlicenseAqualityCmaintenanceA local MCP gateway that unifies multiple LLM providers, API keys, routing, and multi-model discussions into a single tool surface.1346MIT
- AlicenseAqualityAmaintenanceOne local gateway for all your MCP servers — shared by every AI coding tool (Claude, Cursor, VS Code, Codex). Set up each server once; keys stay in the OS keychain; lazy discovery keeps agent context small. Local-first, open source.45 npm221MIT
- FlicenseNot gradedqualityCmaintenanceMulti-cloud MCP server that exposes cloud AI models as tools for AI CLI agents, supporting streaming, conversation history, parallel multi-model queries, and dynamic model discovery.2-