MCP App selection¶
When a Hadron account is a member of 2 or more Apps, MCP sessions
that authenticate as the user (OAuth hdr_user_… tokens) must choose
which App is the active scope for the session. Two MCP tools handle
this:
h-list-apps— enumerate accessible Apps.h-set-active-app— pin one for the session.
Both tools are always present in tools/list for any authenticated MCP
session, regardless of whether the caller has 0, 1, or many Apps. For
single-App callers they're effectively no-ops (Hadron's single-App
default already resolves the App at session open). For multi-App
callers they're how you select.
App-Key callers (server-to-server, hdr_app_… tokens) carry their App
identity in the credential itself and don't need these tools. The
tools return helpful messages in that case rather than silently doing
nothing.
h-list-apps¶
Enumerate the Hadron Apps the caller can access. Callable any time the MCP session is authenticated, including before any selection has been made.
Parameters¶
None.
Return shape¶
A bulleted Markdown list, one App per line:
3 accessible apps:
- **hrn:app:acme-corp::mealplan** — Acme Mealplan (role: owner)
- **hrn:app:mentor-co::juno** — Mentor Co Juno (role: principal)
- **hrn:app:client-co::juno** — Client Co Juno (role: principal)
Order is deterministic — App.createdAt ascending. Each row shows the
App's canonical URN, display name, and the caller's AppMember.role
on it.
Special cases¶
- No accessible Apps. Returns:
- Exactly one accessible App. Returns the single-row list plus a
helpful tail noting that
h-set-active-appisn't required (the App is the implicit default). - App-Key caller. Returns the single App the key is scoped to,
labeled
(via App Key).
Filtering¶
Apps are filtered to active membership only:
App.deletedAt IS NULL— soft-deleted Apps are hidden.App.uninstalledAt IS NULL— soft-uninstalled Apps are hidden.AppMemberrow must exist for the caller (no orphaned access).
A user who was once a member but had their AppMember row removed
will not see that App in the list.
h-set-active-app¶
Pin a Hadron App as the active scope for the rest of the MCP session.
Subsequent App-scoped tool calls (h-list-memories, h-find-nodes,
h-add-node, etc.) resolve to this App until the session ends or the
tool is called again with a different identifier.
Parameters¶
| Name | Type | Required | Description |
|---|---|---|---|
app |
string | yes | Canonical App URN (e.g. hrn:app:acme-corp::mealplan) or a display name that matches exactly one accessible App. Trimmed; case-insensitive on the short-form path. |
Identifier resolution¶
The tool accepts two forms:
- Canonical URN — preferred form. Either bare
(
acme-corp:mealplan) or prefixed (hrn:app:acme-corp::mealplan). Matched againstApp.urndirectly; lookup includes the lifecycle filter (soft-deleted / soft-uninstalled Apps are reported asapp_unavailable). - Short form — App display name, case-insensitive, with
surrounding whitespace trimmed. Matched against the caller's
accessible Apps' display names (the same set
h-list-appsreturns). If exactly one matches, resolved. If two or more match (e.g. two orgs both have an App namedJuno), returns the typed error[app_identifier_ambiguous]with the URN candidates so the caller can disambiguate.
The matcher does not do slug-style normalization (no lowercase-and-dash). Pass the URN if your input has unusual punctuation or whitespace.
Behavior on success¶
- Writes the selection into the in-memory per-session map keyed by the
MCP transport
sessionId. - Returns a success message naming the URN + display name.
- A subsequent invocation replaces the selection atomically — the next App-scoped tool call sees the new App.
The selection lifecycle is per-session: when the MCP transport closes (Claude Desktop disconnects the connector, the session is DELETEd, the server restarts), the selection is cleared. A new session starts unselected.
Error envelopes¶
All errors are returned as MCP tool-error envelopes
({ isError: true, content: [{ type: 'text', text: '[<code>] …' }] })
— not as HTTP errors. The [<code>] prefix carries the
machine-readable code.
| Code | When | Recovery |
|---|---|---|
app_identifier_ambiguous |
Short form matches 2+ accessible Apps. | Retry with the URN form. The error message lists the matching URN candidates. |
app_not_found |
URN or short form matches zero accessible Apps. | Use h-list-apps to see available Apps. May indicate the user isn't an AppMember of the named App. |
app_unavailable |
The matched App is soft-deleted or soft-uninstalled. | Ask the App owner to reinstall, or pick a different App. |
app_member_revoked |
Caller's AppMember row was removed (rare race; mostly surfaces in mid-session revocation handling for App-scoped tool calls, not at selection time). |
Use h-list-apps to see your current accessible set. |
On any error, the previously-active selection (if any) is unchanged
— a failed h-set-active-app call doesn't clear what you already had.
Tool error vocabulary (for strict-list tools after the new regimes)¶
Per spec 026 D-2026-05-21-003, tools split into two classes:
- Advisory tools (
h-list-memories,h-find-nodes,h-list-nodes,h-read-next-node, and all URN-input tools likeh-read-node,h-update-node,h-add-node, etc.) — work without an active App. When no App is selected,h-list-memoriesreturns the un-narrowed set across every accessible App; URN-input tools use the URN's embedded App identity. App identity is a focusing concern, not access control (constitution Article V — Zero-Trust Apps). - Strict tools — a narrow set that genuinely needs App context to
function and has no per-resource URN to fall back on:
h-start-session,h-end-session, allh-chat-*tools, and anyh-run-actionwhose action declares App-scope. These return a tool error when no App is active.
When a strict tool runs without an active selection, the server returns one of these tool errors:
| Code | When |
|---|---|
no_active_app |
The session has already engaged with the selection surface (called h-list-apps or h-set-active-app, OR sent a directory-aware initialize parameter) but no active App is set. The message names h-list-apps + h-set-active-app as the recovery path. |
multiple_apps_resolved |
FR-016 fall-through. The session has NOT engaged with the new selection surface (legacy client behavior). Carries the literal multiple_apps_resolved token in the [<code>] prefix verbatim so production-log greps continue to match (SC-003 adoption signal). The message text starts with User has more than one Hadron App; this MCP client does not support App selection. Recovery is the same as no_active_app. |
The split exists so production-log telemetry can distinguish "un-engaged client" (FR-016 fall-through) from "engaged client but caller skipped selection" (new code). Both surfaces are valid recovery paths.
Related¶
- Install Hadron in Claude Desktop — the how-to that uses these tools.
- MCP authentication — explanation of the OAuth dance and credential types these tools assume.
- URN composition — the URN shape
App.urntakes.