docs: add tool visibility and restructure _meta.ui (#131)
* docs: add tool visibility and restructure _meta.ui - Restructure tool metadata: `_meta["ui/resourceUri"]` → `_meta.ui.resourceUri` - Add `visibility` array field: ["model"], ["apps"], or ["model", "apps"] - Default ["model"] preserves standard MCP behavior - ["apps"] enables widget-only tools hidden from agent - Add McpUiToolMeta interface for type safety - Add Design Decision #4 explaining approach vs OpenAI's two-field model 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * address PR review comments - Change default visibility to ["model", "apps"] - Add deprecation notice for flat ui/resourceUri format - Add McpUiToolMeta and McpUiToolVisibility to spec.types.ts - Improve tools/list and tools/call behavior wording 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: regenerate schemas for McpUiToolMeta types 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: tool visibility and nested _meta.ui format - Rename visibility "apps" → "app" in McpUiToolVisibility type - Add _meta.ui.resourceUri nested format (deprecate flat format) - Add getToolUiResourceUri() utility with backward compatibility - Add visibility demo to system-monitor-server: - get-system-stats: visibility ["model"] with resourceUri - refresh-stats: visibility ["app"] (app-only polling) - Update all example servers to use new _meta.ui format - Add 11 unit tests for getToolUiResourceUri() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: regenerate schemas with updated dependencies * feat: export McpUiToolMeta type and add type annotations - Export McpUiToolMeta and McpUiToolVisibility types from types.ts - Export corresponding Zod schemas (McpUiToolMetaSchema, McpUiToolVisibilitySchema) - Add `as McpUiToolMeta` type annotations to all example servers - Update docs/quickstart.md with proper typing Ensures type safety for `_meta.ui` tool metadata across the codebase. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add server helpers and optional connect() transport Add `src/server/` with convenience functions for registering MCP App tools and resources: - `registerAppTool(server, name, config, handler)` - `registerAppResource(server, name, uri, config, callback)` The `transport` parameter in `App.connect()` is now optional, defaulting to `PostMessageTransport(window.parent)`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Update src/server/index.ts Co-authored-by: Jonathan Hefner <jonathan@hefner.pro> * feat: update McpUiAppToolConfig to support both _meta.ui and flat formats * refactor: simplify server helper imports * docs: add deprecation notice and improve resourceUri documentation * feat: add backward compat normalization in registerAppTool - If _meta.ui.resourceUri is set, also set legacy flat key - If legacy flat key is set, also set _meta.ui.resourceUri - Preserves existing visibility when merging - Does not overwrite if both formats already set * refactor: avoid mutating config arg in registerAppTool * style: format with prettier --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Olivier Chafik <ochafik@anthropic.com> Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
This commit is contained in:
parent
bea0ae27f5
commit
37aab03de0
6 changed files with 530 additions and 43 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { RESOURCE_MIME_TYPE, RESOURCE_URI_META_KEY, type McpUiSandboxProxyReadyNotification, AppBridge, PostMessageTransport } from "@modelcontextprotocol/ext-apps/app-bridge";
|
||||
import { RESOURCE_MIME_TYPE, getToolUiResourceUri, type McpUiSandboxProxyReadyNotification, AppBridge, PostMessageTransport } from "@modelcontextprotocol/ext-apps/app-bridge";
|
||||
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
||||
import type { CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
||||
|
|
@ -77,7 +77,7 @@ export function callTool(
|
|||
|
||||
const toolCallInfo: ToolCallInfo = { serverInfo, tool, input, resultPromise };
|
||||
|
||||
const uiResourceUri = getUiResourceUri(tool);
|
||||
const uiResourceUri = getToolUiResourceUri(tool);
|
||||
if (uiResourceUri) {
|
||||
toolCallInfo.appResourcePromise = getUiResource(serverInfo, uiResourceUri);
|
||||
}
|
||||
|
|
@ -86,16 +86,6 @@ export function callTool(
|
|||
}
|
||||
|
||||
|
||||
function getUiResourceUri(tool: Tool): string | undefined {
|
||||
const uri = tool._meta?.[RESOURCE_URI_META_KEY];
|
||||
if (typeof uri === "string" && uri.startsWith("ui://")) {
|
||||
return uri;
|
||||
} else if (uri !== undefined) {
|
||||
throw new Error(`Invalid UI resource URI: ${JSON.stringify(uri)}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function getUiResource(serverInfo: ServerInfo, uri: string): Promise<UiResourceData> {
|
||||
log.info("Reading UI resource:", uri);
|
||||
const resource = await serverInfo.client.readResource({ uri });
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ Exposes a single `get-budget-data` tool that returns:
|
|||
- Historical data (~120 data points) - 24 months of allocation history per category
|
||||
- Industry benchmarks (~60 data points) - Aggregated percentile data by company stage
|
||||
|
||||
The tool is linked to a UI resource via `_meta[RESOURCE_URI_META_KEY]`.
|
||||
The tool is linked to a UI resource via `_meta.ui.resourceUri`.
|
||||
|
||||
### App (`src/mcp-app.ts`)
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ Exposes a single `get-customer-data` tool that returns:
|
|||
- Segment summary with counts and colors for each group
|
||||
- Optional segment filter parameter
|
||||
|
||||
The tool is linked to a UI resource via `_meta[RESOURCE_URI_META_KEY]`.
|
||||
The tool is linked to a UI resource via `_meta.ui.resourceUri`.
|
||||
|
||||
### App (`src/mcp-app.ts`)
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ Exposes a single `get-scenario-data` tool that returns:
|
|||
- Default input values for the sliders
|
||||
- Optionally computes custom projections when `customInputs` are provided
|
||||
|
||||
The tool is linked to a UI resource via `_meta[RESOURCE_URI_META_KEY]`.
|
||||
The tool is linked to a UI resource via `_meta.ui.resourceUri`.
|
||||
|
||||
### App (`src/`)
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Exposes a single `get-system-stats` tool that returns:
|
|||
- Memory usage (used/total/percentage)
|
||||
- System info (hostname, platform, uptime)
|
||||
|
||||
The tool is linked to a UI resource via `_meta[RESOURCE_URI_META_KEY]`.
|
||||
The tool is linked to a UI resource via `_meta.ui.resourceUri`.
|
||||
|
||||
### App (`src/mcp-app.ts`)
|
||||
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ const app = new App({ name: "System Monitor", version: "1.0.0" });
|
|||
async function fetchStats(): Promise<void> {
|
||||
try {
|
||||
const result = await app.callServerTool({
|
||||
name: "get-system-stats",
|
||||
name: "refresh-stats", // Use app-only tool for polling
|
||||
arguments: {},
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue