MCP Tool Registry
ProRegistry for the tools and MCP servers an agent is connected to. Connection lifecycle and health, credential expiry, per-tool parameter schemas, usage and error rates, a scope permission matrix and a recent call log. Four variants — grid, table, permissions and detail.
import { SvMcpToolRegistryComponent } from '@styloviz-pro/mcp-tool-registry';Demo & usage
Basic usage
ProUsage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Scope matrix
ProScopes are ordered, so a policy is a threshold rather than a set.
Audit the transition, not just the result
ProEvery scope change reports the value it replaced.
Diagnose a failing connection
ProThe schema says what the tool expects; the call log says what happened.
Read-only audit view
ProKeeps the information, removes every control.
When to use
- Building the integrations page for an agent product — what is connected, what is healthy, what expires soon.
- Letting an operator narrow what an agent may do, per tool, without editing a config file.
- Diagnosing why a tool call keeps failing, with the declared schema and the recent call log side by side.
- Giving a compliance reviewer a read-only view of every connection and granted scope.
Async states
- loading
- error
- retry
Item identity & owned state
- Restorable state
- expandedIds
- paramsExpandedKeys
Bind these to put a saved view back — the open sections, the hidden columns, the selected rows — and read their
Changeevents to store what the user does.
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the data is being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| servers | readonly McpServer[] | [] | The connected servers. |
| selectedId | string | null | null | Which server the `detail` and `permissions` variants show. Defaults to the first. |
| variant | McpRegistryVariant | 'grid' | Presentation preset. |
| showHealth | boolean | true | Show the roll-up counts above the list. |
| showUsage | boolean | true | Show per-tool call counts, error rate and latency. |
| editable | boolean | true | Let the reader flip servers and tools on and off. |
| logLimit | number | 8 | How many call-log entries the `detail` variant shows per page. `0` hides the log. When the log is longer, a notice says how many are hidden and a "Show more" control reveals the next page. |
| ariaLabel | string | 'Connected tools' | Accessible label for the registry. |
| now | number | Date.now() | Clock used for credential expiry, injectable so a test is not at the mercy of the wall clock. |
| expandedIds | ReadonlySet<string> (two-way) | new Set() | Server ids whose tool list the viewer expanded (two-way). A `model` so a host can restore or persist which servers were open. |
| maxServers | number | 100 | How many servers the registry lists at once. `0` = no ceiling. A REGISTRY IS A CATALOGUE, AND CATALOGUES GROW MONOTONICALLY. Nobody removes an MCP server; a platform team's registry passes a hundred entries in its first year and nothing in this component was bounded. |
| maxToolsPerServer | number | 50 | How many of one server's tools are listed when it is expanded. `0` = none. THIS IS THE CEILING THAT ACTUALLY BITES, and it is per SERVER rather than per page. One server exposing a generated API can carry several hundred tools, each with a parameter table — so a registry of six servers renders thousands of rows the moment somebody expands the wrong one, and the count beside the name gave no warning because it is the number the ceiling hides. |
| maxParamsPerTool | number | 8 | How many of one tool's schema parameters are listed before "Show all". `0` = no ceiling. A GENERATED SCHEMA CAN CARRY A HUNDRED PARAMETERS, and the tool ceiling alone does not bound the page: fifty tools × a hundred rows is still five thousand. The table stops at the ceiling, says how many are hidden, and expands on demand for the one tool being inspected. |
| paramsExpandedKeys | ReadonlySet<string> (two-way) | new Set() | `server::tool` keys whose full parameter table the viewer expanded (two-way). A `model` so a host can restore or persist it. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
| serverToggled | McpServerToggle | A server's master switch was flipped. |
| toolToggled | McpToolToggle | A single tool was enabled or disabled. |
| scopeChanged | McpScopeChange | A tool's granted scope changed, with the value it replaced. |
| reconnect | McpServer | The reader asked to reconnect a server. |
| credentialAction | McpCredentialAction | A credential needs re-authorising or revoking — the host does the work. |
| serverSelected | McpServer | A server row or card was activated. |
| revealChanged | McpRevealChange | A viewer revealed or re-hid a server's masked values. Only fires when the privacy policy allows reveal (`provideSvAiPrivacy({ reveal: true })`) — log it to keep an audit trail of who looked at what. |
| expandedIdsChange | ReadonlySet<string> | Emits the new `expandedIds` whenever it changes — the output half of `[(expandedIds)]`. |
| paramsExpandedKeysChange | ReadonlySet<string> | Emits the new `paramsExpandedKeys` whenever it changes — the output half of `[(paramsExpandedKeys)]`. |
Wire it to your API
This component is headless about transport: it renders what you give it and reports what the user asks for. Nothing below requires @styloviz/data — drive it from whatever you already use.
Template
ProBound to the names this component actually exposes.
Host class
ProDrive the three async inputs from your own fetch.
- This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `servers`, `loading` and `error`.
- Normalize failures with `toSvDataError()` from `@styloviz/core`. It derives `retryable` from the status, so a 404 does not get a "Try again" button that can only fail again.
Full walkthrough: Connecting to a backend.
Customization & theming
- Redaction, from the pack-wide policy (`X-2`): the credential LABEL, the server URL, the server error and every call-log error are masked per `provideSvAiPrivacy({ patterns })`. A URL carries a credential without looking like one (`https://user:pass@…`, `…?token=…`) and a failing client echoes it into its error; `SV_AI_COMMON_PATTERNS` includes `url-credentials` and `url-secret-param` for exactly this.
- Role-gated reveal: with `provideSvAiPrivacy({ reveal: true })` — provided only for the roles allowed to see secrets — each server with something masked on screen gets a Reveal / Hide control, and `(revealChanged)` reports `{ server, revealed }` so you can log who looked. `reveal` is false by default, and it never switches masking off: values stay masked until a viewer asks.
- `variant` chooses the shape: `grid` for a landing page, `table` when there are more servers than fit, `permissions` for the scope matrix, `detail` for one connection in full.
- `editable` false turns the whole component into an audit view — switches, radios and actions all disappear.
- `showHealth` and `showUsage` drop the roll-up counts and the per-tool metrics independently.
- `logLimit` is the call-log page size: a longer log says how many calls are hidden and offers "Show N more". `0` hides the log. `selectedId` drives which server the single-server variants show.
- `maxParamsPerTool` (8) bounds a tool's parameter table: a generated schema can carry a hundred parameters, so the table stops at the ceiling, says what it hid, and "Show all N parameters" expands it for the one tool being inspected. `0` turns it off.
- The `SCOPE_ORDER`, `scopeAtLeast`, `registryHealth` and `credentialExpiry` helpers are exported, so a policy layer can threshold scopes and compute its own roll-ups.
- Scale ceilings: `[maxServers]` (100) bounds the catalogue and `[maxToolsPerServer]` (50) bounds one server's tool list — the second is the one that bites, because a single server exposing a generated API can carry several hundred tools, each with a parameter table. Both disclose what they left out, and the tool count beside a server name stays the SERVER's count, so the warning does not vanish exactly when it is earned. `0` turns either off.
Best practices
- Do: Set `risk` on each tool to match the risk you pass to Agent Approval, so the registry and the approval gate agree on severity.
- Do: Record `previous` from `scopeChanged` in your audit log — knowing a scope became `admin` matters far less than knowing it was `read` an hour ago.
- Do: Fill in `params` for every tool. The schema is what turns a failing call into a fixable one.
- Do: Pass `now` in tests so credential-expiry assertions are not at the mercy of the wall clock.
- Don't: Do not put secrets in `credential`. It carries a kind, a display label and an expiry — `credentialAction` asks the host to do the actual work.
- Don't: Do not set `expiresAt` on a credential that does not expire. A static key flagged as expiring is how a registry cries wolf until nobody reads it.
- Don't: Do not reach for this to pick a model — that is AI Model Selector. This manages many stateful connections, not one choice.
Accessibility
- The permission matrix is a real table: scope columns are `th[scope="col"]`, each tool row is `th[scope="row"]`, and a visually-hidden `caption` names the server.
- Each radio carries an explicit label ("merge_pull_request: write"), so the cell is meaningful without reading the row and column headers separately.
- The connected count is `role="status"`, so a connection dropping while the operator is elsewhere is announced.
- Table rows use proper `aria-expanded` / `aria-controls` disclosures pointing at the revealed tool list.
- Status is never colour-only — each state carries a text label beside its dot, and a connecting server animates rather than relying on hue alone.
- Every switch has an explicit `aria-label` naming what it enables, since the visible text belongs to the row rather than the control.
- The Reveal control is a toggle button with `aria-pressed` and a label naming the server; the parameter "Show all" control carries `aria-expanded` / `aria-controls` pointing at the parameter list.
Feedback on MCP Tool Registry
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.