Skip to content

Accounts: each account's MCP servers, connectors and plugins (--mcp) - #51

Merged
JOsacky merged 1 commit into
mainfrom
claude/blissful-greider-52596b
Oct 23, 2026
Merged

JOsacky merged 1 commit into
mainfrom
claude/blissful-greider-52596b

Conversation

@JOsacky

@JOsacky JOsacky commented Oct 23, 2026

Copy link
Copy Markdown
Member

Follow-up to #50. Each named account has its own CLAUDE_CONFIG_DIR / CODEX_HOME, so its MCP servers, claude.ai / ChatGPT connectors and plugins can differ from the machine's own login, and each needs authenticating separately. skillhook health only probed the default login.

What it does

--mcp asks each usable login/token account's own CLI, with withAccountEnv, which servers its runs get and whether each connects:

  • Claude Code: the control protocol's mcp_status request (claude -p --input-format stream-json, hooks off, no session saved, without --strict-mcp-config / ENABLE_CLAUDEAI_MCP_SERVERS=false, so connectors and plugin servers are included). It asks again every 500 ms until no server is pending, waiting at least 3 s so the background connector fetch lands. Plus claude plugin list --json. A CLI without mcp_status falls back to claude mcp list.
  • Codex: codex mcp list --json (configured/enabled) merged with codex app-server's mcpServerStatus/list, which connects and reports tool counts and errors; OAuth "authorization required" → needs_auth. Servers not in the config are plugins' or codex_apps (ChatGPT apps, source: connector). Plus codex plugin list.
  • Both CLIs return server headers and env (tokens) in these answers. Only the URL or command line is kept, collapsed to one line. Tests assert that no secret survives parsing.

I picked the control protocol over claude mcp list because it's one process, reports connectors (scope: claudeai) that mcp list omits, and gives structured error / error_code and tool counts.

Surfaces

  • AccountView.mcp = {servers: [{name, target, transport?, state: connected|needs_auth|failed|disabled|unknown, detail?, source?, plugin?, tools?}], plugins?, via?, error?, checked_at}, only when asked; each probe is bounded by health.probe_timeout_seconds.
  • skillhook accounts show <name> --mcp (server table + plugins), accounts --mcp (an mcp column, e.g. 8/19 (3 need auth, 8 failed)), accounts check --mcp, GET /accounts?mcp=1, MCP list_accounts {mcp: true}.
  • Attention: mcp_needs_auth (warn; fix skillhook accounts exec <name> -- claude then /mcp, or … -- codex mcp login <server>), mcp_failed (warn; … mcp get <server>, or skillhook secret set VAR when the CLI says an environment variable is missing), mcp_missing (info; servers the machine's own login has and the account lacks, connectors excluded; that login is probed once per runner).
  • skillhook health deep mode: account <name> mcp <server> rows in the tools group (accounts using the machine's own directory are already covered by the claude mcp / codex mcp rows).
  • Fixtures: fake-claude answers mcp_status (first answer still pending, header/env secrets planted, no-mcp-status for the fallback); fake-codex answers mcpServerStatus/list and plugin list.
  • Docs: new section in docs/accounts.md, plus docs/api.md, docs/mcp.md, docs/operations.md, README, llms.txt, CHANGELOG.

No new outbound requests from skillhook itself. Only the account's own CLI is spawned, with argv only.

Verified

  • pnpm run check is green (418 tests).
  • Ran against the real CLIs (Claude Code 2.1.305, codex-cli 0.163.0) with accounts pointed at ~/.claude / ~/.codex, in a scratch skillhook home:
    • Codex: accounts show cdx --mcp took 9.9 s for 19 active servers: 3 need auth, 8 fail on a variable the job environment lacks, 8 connected, 6 disabled.
    • Claude: probeClaudeMcp against the real CLI took 3.5 s for 10 servers, correct states and tool counts, no header values kept.
    • Not covered: the accounts show mine --mcp path for Claude said "not probed: login expired", because ~/.claude's own keychain login is expired on this machine (the desktop app authenticates its own way).
    • Not covered: no claude.ai connectors showed up here (that CLI reported "API-key auth precedence"), so the connector row follows the CLI's schema rather than a captured answer.

🤖 Generated with Claude Code

Every account has its own configuration directory, so its MCP servers,
claude.ai / ChatGPT connectors and plugins can differ from the machine's
own login and need authenticating separately. `--mcp` asks each usable
account's CLI with the account's environment:

- Claude Code: the control protocol's `mcp_status` (connectors and
  plugin servers included, asked again until nothing is pending), plus
  `claude plugin list --json`; falls back to `claude mcp list`.
- Codex: `codex mcp list --json` merged with app-server's
  `mcpServerStatus/list` (connection state, tool counts, errors), plus
  `codex plugin list`.

Only URLs and command lines are kept, never headers or env values.
Surfaces: `accounts show <name> --mcp`, `accounts --mcp` (7/9 column),
`accounts check --mcp`, `GET /accounts?mcp=1`, MCP `list_accounts
{mcp: true}`, and `account <name> mcp <server>` rows in deep health.
Attention codes mcp_needs_auth, mcp_failed and mcp_missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JOsacky
JOsacky merged commit 3612cf6 into main Oct 23, 2026
6 checks passed
@JOsacky
JOsacky deleted the claude/blissful-greider-52596b branch October 23, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant