publ betaReference (MCP guide)
Open publ console

Shared console navigation contract

# Shared console navigation contract

It adds console navigation to MCP application results while preserving existing screen workflows. It does not implement capability search, nickname resolution, multi-channel orchestration or native chat.

## Target-path requirement

The user clarified that a navigation link must open the console screen corresponding to the operation and selected target. Mapping is at the screen-workflow level: one MCP tool can compose several APIs, and its resulting operation and target determine the path. Each MCP call returns exactly one corresponding console address. A generic console-home link or a list of alternate screens does not satisfy this requirement.

Examples: membership metadata uses the selected channel and membership `mid` editor path; Channel Point policy uses that channel's policy path; channel creation links to the created channel's console; deletion links to the surviving parent/list. Each path comes from source routers and central configuration, not LLM-generated strings. Authentication, unsupported routes, general discovery/development messages and task status without freshly established target context do not receive a substitute home URL.

## Result shape

Every ordinary application result passing through `createServer` receives a required `navigation` object in `structuredContent` and its text JSON representation. Existing status, task, revision, outcome and verification fields retain their meaning. For live/configured results, the legacy top-level `consoleUrl` is derived from `navigation.primaryUrl`.

| Field | Meaning |
| --- | --- |
| `status` | `available` or `unavailable` |
| `primaryUrl` | One of the returned link URLs; null when unavailable |
| `links` | Exactly one named destination when available, with `label`, `url`, `screenId`, `relation`, and an optional authorized `channelName`; empty when unavailable |
| `relation` | `target` for the supported screen or `parent` after deletion. The legacy enum value `fallback` remains schema-compatible but is no longer generated |
| `environment` | The API/runtime environment label; it does not itself select the process console profile |
| `notice` | Available links may require browser login and do not prove the result or matching environment |

It now explicitly returns unavailable navigation with an empty link list, rather than fabricating a live screen for a demo entity. Invalid console configuration is also unavailable. Actual credentials and browser sessions are never embedded in URLs.

The host selects `PUBL_CONSOLE_ENVIRONMENT=dev` for the user-confirmed
`https://console.dev.publ.biz`, or `prod` for `https://console.publ.biz`.
Without an explicit selection, an exact registered DEV/production API profile
selects its corresponding console; an absent or custom API profile defaults to
`prod`. A contradictory explicit selection for a registered API is rejected.
Both addresses are centrally registered in
`config/public-origins.json`; arbitrary URL overrides and MCP-input host selection
are unsupported.

## Registration and integration

`src/mcp-results.ts` installs a shared tool-registration wrapper before `restrictTools`. The hosted guard is therefore inside the result finalizer: application-level scope rejections and authorization callback failures receive the same navigation contract without invoking the business handler. The existing allow lists, channel checks and current-grant check remain in place.

The wrapper publishes a required navigation output schema for current tools. Existing Zod object output schemas are extended while retaining their fields; strict object schemas also admit the derived legacy URL. Other schema implementations require explicit composition before registration. Navigation is validated by application code for both success and error results; the MCP SDK skips its ordinary output-schema validation for error results.

`src/console-navigation.ts` reuses existing route builders and validates supported destinations against a route catalog derived from the publ console source. It never consumes raw tool arguments. Returned URLs must use the central console origin, recognized paths and supported query parameters. Channel-bound contexts cannot return another channel's navigation or account-specific routes. When the corresponding supported destination cannot be established, navigation is unavailable with no links or legacy consoleUrl. Never substitute console home.

Deletion uses a surviving parent/list route. The workflow destination takes precedence over required-action or other handoff candidates. The finalizer keeps action purposes and business fields, removes competing consoleUrl fields from known handoff containers, membership list rows, subscription-product action metadata and direct saved TASK_STATUS results, and exposes one link plus the identical legacy top-level consoleUrl alias. It does not mutate the original workflow result or execute a human action.

New business tools registered after the wrapper automatically inherit the result schema and finalization. Their owner continues supplying authoritative screen/target metadata through existing workflow results. Add newly supported console routes to the navigation catalog with source evidence; unknown paths remain unavailable until that mapping is added. A task-status response without freshly established target metadata remains unavailable rather than trusting a stale `lastResult` URL.

The subsequent target-path correction updates the shared URL helper, result finalizer, server guidance and authored contracts without changing business API requests. These checks remain separate from browser destination verification.

## Outcome and presentation limits

Link construction does not retry a workflow. An unsupported or invalid destination produces unavailable navigation while preserving an already returned business outcome and task reference. Unexpected callback exceptions are sanitized; an unknown write outcome is not mislabeled as unsent. A known Bridge error retains its existing outcome classification.

Invalid inputs rejected by the SDK before application dispatch, unknown tool/protocol errors, HTTP authentication failure, disconnected transport and protocol-level input-required replies are outside this application-result contract.

Server instructions ask external agents to display the returned labeled links only when reporting the relevant publ result. They must not append a console home footer to unrelated conversation or development status. This does not force their final answer formatting. Native chat can later render a control independently of model prose; no native chat UI is delivered here. A console URL is navigation, not evidence that its screen was loaded, that the browser can access it, or that a mutation succeeded.

## Existing-tool path corrections

Member list filters now retain their original registered, membership or banned
screen. Selected member detail and moderation outputs link to the observed
numeric profile at members/registered-users/{profileId}; distinctId is never
substituted. Mismatched/unobserved targets remain unavailable.

An authorized point withdrawal handoff can return its exact request screen when
financial prerequisite reads are unavailable, after a fresh context check. Its
status is action_required and eligibility remains not-observed; authentication,
permission/context failures and selected-target checks are not bypassed. See the
[channel point handoff reference](tools/publ_channel_points_handoff.md).

Member visitor access and financial completion are separate.

The wrapper requires serialKeysRead:true and equality with serialKeyPagination; page is 1–1,000,000 and limit is 15/30/50/100. Unknown/additional query fields or mismatched values are not approved destinations. The original UI keeps status in local screen state, so the route does not preserve that filter. A selected manage-coupons action may accompany the read; ordinary coupon guidance without serialKeys keeps its existing no-query route. One consoleUrl/primaryUrl destination remains, with no generic home fallback. See the [workflow](guides/membership-serial-keys.md#one-exact-console-destination).

## Membership product-list page and filter

The wrapper requires productsRead:true, exactly those three query fields, canonical page 1–1,000,000, limit 15/30/50/100 and literal true/false matching productPagination/productFilter. Extra, duplicate or mismatched fields fail destination validation. Plain list-page reads and manage-products with products use this rule; an ordinary selected detail keeps the editor route and serialKeys keeps its separate two-field coupons query. [Extension/selling-state actions](guides/membership-product-actions.md) require manual row selection at this exact list. No modal URL, selected checkbox or automatic bulk submission is claimed.

## Selected member-history tabs

[member_get history](tools/publ_member_get.md#history-results-stability-and-recovery) uses /channels/{channelCode}/members/membership-users/{profileId}/membership-history, optionally followed by /{membershipMid}/{subscriptionProductId}?page={page}&limit={limit}. The observed profile id, parent mid/product and returned purchase selection/pagination must agree. Exactly page/limit are admitted on a purchase destination; the unpaginated history destination has no query. The basic/include registered-users detail path remains separate. A current destination does not prove browser access, the rendered state or completed financial work.

## Channel administration app

channel_admin_app_get and initial-release observations use
/channels/{channelCode}/preferences/ch-admin-app. Missing address and source
plan prerequisites use publish/settings and plan/home respectively for the
same channel. The release modal has no independent URL. Each result chooses
one destination; installationUri is not exposed as an additional link.
Historical completion has no fresh destination; get rechecks current state.