[UI-REWRITE] Add a shared MCP server status indicator - #130
Conversation
Adds one availability derivation and one indicator for MCP server health, starting with the servers page. The "Authorization needed" state is new. OAuth tokens are held per user per gateway, so an authorization_code server that a colleague authorized is still unusable for everyone else. The health check treats the resulting 401 as healthy on purpose, so those rows read Active with zero components today. GET /oauth/status reports the caller's own token state, and the indicator maps a missing or expired token to that state. Retires the "warning" status. Two conflicting definitions existed: unreachable but seen before, and reachable but stale over five minutes. The first is Offline by another name; the second fires on any server the health loop has not reached yet. Unreachable now splits into Offline and Connecting on whether the server has ever responded. Deletes ServerStatusBadge, which nothing rendered. Closes #6464 Closes #6465 Signed-off-by: Anna Effort <anna.effort@ibm.com>
States with nothing to resolve open a popover rather than a modal, matching the visibility info affordance. Authorization needed starts the OAuth flow on click instead of describing it behind a dialog, and falls back to the popover where the caller has no way to run it. Turn on goes, since Activate is already in the row menu. Signed-off-by: Anna Effort <anna.effort@ibm.com>
Recast the status explanations around the server rather than ContextForge, and stop showing the last error on inactive servers, where the health loop leaves it behind from an earlier outage. Narrow the popover to max-w-xs and anchor it to the end of the status label. Shorten the compact label to Auth, keeping the full word for screen readers. Signed-off-by: Anna Effort <anna.effort@ibm.com>
Signed-off-by: Anna Effort <anna.effort@ibm.com>
There was a problem hiding this comment.
🟡 Changes recommended
OAuth status synchronization and availability presentation still have correctness issues.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds a shared MCP server availability indicator, initially integrated into the servers page.
Changes:
- Adds centralized availability classification and status details.
- Integrates per-user OAuth authorization status and actions.
- Adds translations and tests while removing the unused badge.
File summaries
| File | Description |
|---|---|
| src/types/server.ts | Adds health and OAuth status types. |
| src/pages/Servers.tsx | Loads OAuth states and handles authorization. |
| src/pages/Servers.test.tsx | Tightens Connect button assertions. |
| src/lib/serverStatus.ts | Defines shared availability logic. |
| src/lib/serverStatus.test.ts | Tests availability classification. |
| src/i18n/locales/pt-BR/mcpServer.json | Adds Portuguese status messages. |
| src/i18n/locales/es-ES/mcpServer.json | Adds Spanish status messages. |
| src/i18n/locales/en-US/mcpServer.json | Adds English status messages. |
| src/components/servers/ServerStatusIndicator.tsx | Implements the shared status control. |
| src/components/servers/ServerStatusIndicator.test.tsx | Tests indicator behavior and accessibility. |
| src/components/servers/ServerStatusDetail.tsx | Renders status explanations and diagnostics. |
| src/components/servers/ServerStatusBadge.tsx | Removes the unused legacy badge. |
| src/components/servers/ServerStatusBadge.test.tsx | Removes obsolete badge tests. |
| src/components/servers/ServersTable.tsx | Integrates the new status indicator. |
| src/components/servers/ServersTable.test.tsx | Tests updated table statuses and actions. |
| src/api/servers.ts | Adds OAuth status retrieval and cancellation typing. |
Review details
- Files reviewed: 16/16 changed files
- Comments generated: 5
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The /oauth/status route rejects more than 100 ids, and a paged-through server list can exceed that, so getOAuthStatus splits and merges. A rejected refetch after authorization skipped the status reload and surfaced as an unhandled rejection at the click handler. Signed-off-by: Anna Effort <anna.effort@ibm.com>
45a7d1d to
9af64f3
Compare
|
LLM review feedback:
|
|
@a-effort - please resolve the conflicts |
marekdano
left a comment
There was a problem hiding this comment.
Status taxonomy only partially migrated - Minor
File: src/components/gateways/SourceSelection.tsx:63 (also CreateServer.tsx)
These still use local getServerStatus/getStatusConfig with the old draft/warning/offline/active model instead of the new shared serverStatus.ts. The "warning" status the PR description says is retired is still alive here, so the same server can show inconsistent status wording across views.
Suggested fix: migrate these call sites to getServerAvailability/getAvailabilityPresentation in the same PR, or file a fast-follow if scope is intentionally limited.
| const oauthServerIds = useMemo( | ||
| () => allServers.filter((server) => server.authType === "oauth").map((server) => server.id), | ||
| [allServers], | ||
| ); |
There was a problem hiding this comment.
oauthServerIds is a new array on every allServers change, so the full batched /oauth/status call re-fires on any unrelated refresh (delete, toggle, tag edit, "Load More") — not just OAuth-relevant changes. Per the backend, a non-DB token store serves this via up to 100 sequential per-id Vault lookups with retry/backoff, so this is real latency, not just a wasted round trip.
Suggested fix: memoize more narrowly (e.g. by id set content, not allServers reference) or debounce.
There was a problem hiding this comment.
Fixed in #131, which moves this into a useOAuthTokenStatuses hook. The memo keys on the joined id string rather than the allServers reference, so the batch call follows which servers are in the list and an unrelated refresh no longer re-fires it.
Signed-off-by: Anna Effort <anna.effort@ibm.com>
The guard tested the availability state, but auth outranks inactive, so a disabled server whose token had also expired kept rendering the error the health loop left behind before it was turned off. Signed-off-by: Anna Effort <anna.effort@ibm.com>
|
You are right that That migration is in #131, which is stacked on this branch. Both call sites move to |
Goal: enable users to be informed of their MCP server health.
Status is shown at the server level and the user can click it to trigger a popover that provides more info. Clicking the authorization needed option starts the OAuth flow instead.
Note: OAuth tokens are held per user per server, so an authorization_code server that a colleague authorized is still unusable for everyone else. GET /oauth/status reports the caller's own token state, and the indicator maps a missing or expired token to that state.
130.mp4
This retires the "warning" status and deletes ServerStatusBadge, which was a placeholder this approach replaces.
Closes IBM/mcp-context-forge#6462
Closes IBM/mcp-context-forge#6464
IBM/mcp-context-forge#6465 stays open: it covers catalog cards, which will be a follow up.