@modelcontextprotocol/ext-apps 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/LICENSE +196 -1
  2. package/README.md +274 -25
  3. package/dist/docs/patterns.d.ts +9 -0
  4. package/dist/src/app-bridge.d.ts +253 -247
  5. package/dist/src/app-bridge.examples.d.ts +9 -0
  6. package/dist/src/app-bridge.js +17 -17
  7. package/dist/src/app-with-deps.js +9 -9
  8. package/dist/src/app.d.ts +246 -209
  9. package/dist/src/app.examples.d.ts +9 -0
  10. package/dist/src/app.js +10 -10
  11. package/dist/src/generated/schema.d.ts +45 -33
  12. package/dist/src/generated/schema.test.d.ts +1 -0
  13. package/dist/src/message-transport.d.ts +30 -32
  14. package/dist/src/message-transport.examples.d.ts +9 -0
  15. package/dist/src/react/index.d.ts +8 -10
  16. package/dist/src/react/index.examples.d.ts +6 -0
  17. package/dist/src/react/index.js +8 -8
  18. package/dist/src/react/react-with-deps.js +8 -8
  19. package/dist/src/react/useApp.d.ts +58 -44
  20. package/dist/src/react/useApp.examples.d.ts +6 -0
  21. package/dist/src/react/useAutoResize.d.ts +14 -11
  22. package/dist/src/react/useAutoResize.examples.d.ts +6 -0
  23. package/dist/src/react/useDocumentTheme.d.ts +14 -16
  24. package/dist/src/react/useDocumentTheme.examples.d.ts +6 -0
  25. package/dist/src/react/useHostStyles.d.ts +45 -53
  26. package/dist/src/react/useHostStyles.examples.d.ts +6 -0
  27. package/dist/src/server/index.d.ts +215 -41
  28. package/dist/src/server/index.examples.d.ts +9 -0
  29. package/dist/src/server/index.js +10 -10
  30. package/dist/src/spec.types.d.ts +56 -40
  31. package/dist/src/styles.d.ts +75 -32
  32. package/dist/src/styles.examples.d.ts +9 -0
  33. package/dist/src/types.d.ts +8 -7
  34. package/package.json +26 -7
@@ -1,16 +1,44 @@
1
1
  /**
2
- * Server Helpers for MCP Apps.
2
+ * Utilities for MCP servers to register tools and resources that display interactive UIs.
3
+ *
4
+ * Use these helpers instead of the base SDK's `registerTool` and `registerResource` when
5
+ * your tool should render an {@link app!App `App`} in the client. They handle UI metadata normalization
6
+ * and provide sensible defaults for the MCP Apps MIME type ({@link RESOURCE_MIME_TYPE `RESOURCE_MIME_TYPE`}).
3
7
  *
4
8
  * @module server-helpers
9
+ *
10
+ * @example
11
+ * ```ts source="./index.examples.ts#index_overview"
12
+ * // Register a tool that displays a view
13
+ * registerAppTool(
14
+ * server,
15
+ * "weather",
16
+ * {
17
+ * description: "Get weather forecast",
18
+ * _meta: { ui: { resourceUri: "ui://weather/view.html" } },
19
+ * },
20
+ * toolCallback,
21
+ * );
22
+ *
23
+ * // Register the HTML resource the tool references
24
+ * registerAppResource(
25
+ * server,
26
+ * "Weather View",
27
+ * "ui://weather/view.html",
28
+ * {},
29
+ * readCallback,
30
+ * );
31
+ * ```
5
32
  */
6
- import { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE, McpUiResourceMeta, McpUiToolMeta } from "../app.js";
33
+ import { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE, McpUiResourceMeta, McpUiToolMeta, McpUiClientCapabilities } from "../app.js";
7
34
  import type { McpServer, RegisteredTool, ResourceMetadata, ToolCallback, ReadResourceCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
8
35
  import type { AnySchema, ZodRawShapeCompat } from "@modelcontextprotocol/sdk/server/zod-compat.js";
9
- import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
36
+ import type { ClientCapabilities, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
10
37
  export { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE };
11
38
  export type { ResourceMetadata, ToolCallback, ReadResourceCallback };
12
39
  /**
13
- * Tool configuration (same as McpServer.registerTool).
40
+ * Base tool configuration matching the standard MCP server tool options.
41
+ * Extended by {@link McpUiAppToolConfig `McpUiAppToolConfig`} to add UI metadata requirements.
14
42
  */
15
43
  export interface ToolConfig {
16
44
  title?: string;
@@ -21,7 +49,14 @@ export interface ToolConfig {
21
49
  _meta?: Record<string, unknown>;
22
50
  }
23
51
  /**
24
- * MCP App Tool configuration for `registerAppTool`.
52
+ * Configuration for tools that render an interactive UI.
53
+ *
54
+ * Extends {@link ToolConfig `ToolConfig`} with a required `_meta` field that specifies UI metadata.
55
+ * The UI resource can be specified in two ways:
56
+ * - `_meta.ui.resourceUri` (preferred)
57
+ * - `_meta["ui/resourceUri"]` (deprecated, for backward compatibility)
58
+ *
59
+ * @see {@link registerAppTool `registerAppTool`} for the recommended way to register app tools
25
60
  */
26
61
  export interface McpUiAppToolConfig extends ToolConfig {
27
62
  _meta: {
@@ -33,7 +68,7 @@ export interface McpUiAppToolConfig extends ToolConfig {
33
68
  * URI of the UI resource to display for this tool.
34
69
  * This is converted to `_meta["ui/resourceUri"]`.
35
70
  *
36
- * @example "ui://weather/widget.html"
71
+ * @example "ui://weather/view.html"
37
72
  *
38
73
  * @deprecated Use `_meta.ui.resourceUri` instead.
39
74
  */
@@ -41,10 +76,22 @@ export interface McpUiAppToolConfig extends ToolConfig {
41
76
  });
42
77
  }
43
78
  /**
44
- * MCP App Resource configuration for `registerAppResource`.
79
+ * MCP App Resource configuration for {@link registerAppResource `registerAppResource`}.
80
+ *
81
+ * Extends the base MCP SDK `ResourceMetadata` with optional UI metadata
82
+ * for configuring security policies and rendering preferences.
83
+ *
84
+ * @see {@link registerAppResource `registerAppResource`} for usage
45
85
  */
46
86
  export interface McpUiAppResourceConfig extends ResourceMetadata {
87
+ /**
88
+ * Optional UI metadata for the resource.
89
+ * Used to configure security policies (CSP) and rendering preferences.
90
+ */
47
91
  _meta?: {
92
+ /**
93
+ * UI-specific metadata including CSP configuration and rendering preferences.
94
+ */
48
95
  ui?: McpUiResourceMeta;
49
96
  [key: string]: unknown;
50
97
  };
@@ -52,30 +99,79 @@ export interface McpUiAppResourceConfig extends ResourceMetadata {
52
99
  /**
53
100
  * Register an app tool with the MCP server.
54
101
  *
55
- * This is a convenience wrapper around `server.registerTool` that will allow more backwards-compatibility.
102
+ * This is a convenience wrapper around `server.registerTool` that normalizes
103
+ * UI metadata: if `_meta.ui.resourceUri` is set, the legacy `_meta["ui/resourceUri"]`
104
+ * key is also populated (and vice versa) for compatibility with older hosts.
56
105
  *
57
106
  * @param server - The MCP server instance
58
107
  * @param name - Tool name/identifier
59
- * @param config - Tool configuration with required `ui` field
60
- * @param handler - Tool handler function
108
+ * @param config - Tool configuration with `_meta` field containing UI metadata
109
+ * @param cb - Tool handler function
61
110
  *
62
- * @example
63
- * ```typescript
64
- * import { registerAppTool } from '@modelcontextprotocol/ext-apps/server';
65
- * import { z } from 'zod';
66
- *
67
- * registerAppTool(server, "get-weather", {
68
- * title: "Get Weather",
69
- * description: "Get current weather for a location",
70
- * inputSchema: { location: z.string() },
71
- * _meta: {
72
- * [RESOURCE_URI_META_KEY]: "ui://weather/widget.html",
111
+ * @example Basic usage
112
+ * ```ts source="./index.examples.ts#registerAppTool_basicUsage"
113
+ * registerAppTool(
114
+ * server,
115
+ * "get-weather",
116
+ * {
117
+ * title: "Get Weather",
118
+ * description: "Get current weather for a location",
119
+ * inputSchema: { location: z.string() },
120
+ * _meta: {
121
+ * ui: { resourceUri: "ui://weather/view.html" },
122
+ * },
73
123
  * },
74
- * }, async (args) => {
75
- * const weather = await fetchWeather(args.location);
76
- * return { content: [{ type: "text", text: JSON.stringify(weather) }] };
77
- * });
124
+ * async (args) => {
125
+ * const weather = await fetchWeather(args.location);
126
+ * return { content: [{ type: "text", text: JSON.stringify(weather) }] };
127
+ * },
128
+ * );
78
129
  * ```
130
+ *
131
+ * @example Tool visible to model but not callable by UI
132
+ * ```ts source="./index.examples.ts#registerAppTool_modelOnlyVisibility"
133
+ * registerAppTool(
134
+ * server,
135
+ * "show-cart",
136
+ * {
137
+ * description: "Display the user's shopping cart",
138
+ * _meta: {
139
+ * ui: {
140
+ * resourceUri: "ui://shop/cart.html",
141
+ * visibility: ["model"],
142
+ * },
143
+ * },
144
+ * },
145
+ * async () => {
146
+ * const cart = await getCart();
147
+ * return { content: [{ type: "text", text: JSON.stringify(cart) }] };
148
+ * },
149
+ * );
150
+ * ```
151
+ *
152
+ * @example Tool hidden from model, only callable by UI
153
+ * ```ts source="./index.examples.ts#registerAppTool_appOnlyVisibility"
154
+ * registerAppTool(
155
+ * server,
156
+ * "update-quantity",
157
+ * {
158
+ * description: "Update item quantity in cart",
159
+ * inputSchema: { itemId: z.string(), quantity: z.number() },
160
+ * _meta: {
161
+ * ui: {
162
+ * resourceUri: "ui://shop/cart.html",
163
+ * visibility: ["app"],
164
+ * },
165
+ * },
166
+ * },
167
+ * async ({ itemId, quantity }) => {
168
+ * const cart = await updateCartItem(itemId, quantity);
169
+ * return { content: [{ type: "text", text: JSON.stringify(cart) }] };
170
+ * },
171
+ * );
172
+ * ```
173
+ *
174
+ * @see {@link registerAppResource `registerAppResource`} to register the HTML resource referenced by the tool
79
175
  */
80
176
  export declare function registerAppTool<OutputArgs extends ZodRawShapeCompat | AnySchema, InputArgs extends undefined | ZodRawShapeCompat | AnySchema = undefined>(server: Pick<McpServer, "registerTool">, name: string, config: McpUiAppToolConfig & {
81
177
  inputSchema?: InputArgs;
@@ -85,29 +181,107 @@ export declare function registerAppTool<OutputArgs extends ZodRawShapeCompat | A
85
181
  * Register an app resource with the MCP server.
86
182
  *
87
183
  * This is a convenience wrapper around `server.registerResource` that:
88
- * - Defaults the MIME type to "text/html;profile=mcp-app"
184
+ * - Defaults the MIME type to {@link RESOURCE_MIME_TYPE `RESOURCE_MIME_TYPE`} (`"text/html;profile=mcp-app"`)
89
185
  * - Provides a cleaner API matching the SDK's callback signature
90
186
  *
91
187
  * @param server - The MCP server instance
92
188
  * @param name - Human-readable resource name
93
- * @param uri - Resource URI (should match the `ui` field in tool config)
189
+ * @param uri - Resource URI (should match the `_meta.ui` field in tool config)
94
190
  * @param config - Resource configuration
95
191
  * @param readCallback - Callback that returns the resource contents
96
192
  *
97
- * @example
98
- * ```typescript
99
- * import { registerAppResource } from '@modelcontextprotocol/ext-apps/server';
100
- *
101
- * registerAppResource(server, "Weather Widget", "ui://weather/widget.html", {
102
- * description: "Interactive weather display",
103
- * mimeType: RESOURCE_MIME_TYPE,
104
- * }, async () => ({
105
- * contents: [{
106
- * uri: "ui://weather/widget.html",
107
- * mimeType: RESOURCE_MIME_TYPE,
108
- * text: await fs.readFile("dist/widget.html", "utf-8"),
109
- * }],
110
- * }));
193
+ * @example Basic usage
194
+ * ```ts source="./index.examples.ts#registerAppResource_basicUsage"
195
+ * registerAppResource(
196
+ * server,
197
+ * "Weather View",
198
+ * "ui://weather/view.html",
199
+ * {
200
+ * description: "Interactive weather display",
201
+ * },
202
+ * async () => ({
203
+ * contents: [
204
+ * {
205
+ * uri: "ui://weather/view.html",
206
+ * mimeType: RESOURCE_MIME_TYPE,
207
+ * text: await fs.readFile("dist/view.html", "utf-8"),
208
+ * },
209
+ * ],
210
+ * }),
211
+ * );
111
212
  * ```
213
+ *
214
+ * @example With CSP configuration for external domains
215
+ * ```ts source="./index.examples.ts#registerAppResource_withCsp"
216
+ * registerAppResource(
217
+ * server,
218
+ * "Music Player",
219
+ * "ui://music/player.html",
220
+ * {
221
+ * description: "Audio player with external soundfonts",
222
+ * },
223
+ * async () => ({
224
+ * contents: [
225
+ * {
226
+ * uri: "ui://music/player.html",
227
+ * mimeType: RESOURCE_MIME_TYPE,
228
+ * text: musicPlayerHtml,
229
+ * _meta: {
230
+ * ui: {
231
+ * csp: {
232
+ * resourceDomains: ["https://cdn.example.com"], // For scripts/styles/images
233
+ * connectDomains: ["https://api.example.com"], // For fetch/WebSocket
234
+ * },
235
+ * },
236
+ * },
237
+ * },
238
+ * ],
239
+ * }),
240
+ * );
241
+ * ```
242
+ *
243
+ * @see {@link registerAppTool `registerAppTool`} to register tools that reference this resource
112
244
  */
113
245
  export declare function registerAppResource(server: Pick<McpServer, "registerResource">, name: string, uri: string, config: McpUiAppResourceConfig, readCallback: ReadResourceCallback): void;
246
+ /**
247
+ * Extension identifier for MCP Apps capability negotiation.
248
+ *
249
+ * Used as the key in `extensions` to advertise MCP Apps support.
250
+ */
251
+ export declare const EXTENSION_ID = "io.modelcontextprotocol/ui";
252
+ /**
253
+ * Get MCP Apps capability settings from client capabilities.
254
+ *
255
+ * This helper retrieves the capability object from the `extensions` field
256
+ * where MCP Apps advertises its support.
257
+ *
258
+ * Note: The `clientCapabilities` parameter extends the SDK's `ClientCapabilities`
259
+ * type with an `extensions` field (pending SEP-1724). Once `extensions` is added
260
+ * to the SDK, this can use `ClientCapabilities` directly.
261
+ *
262
+ * @param clientCapabilities - The client capabilities from the initialize response
263
+ * @returns The MCP Apps capability settings, or `undefined` if not supported
264
+ *
265
+ * @example Check for MCP Apps support in server initialization
266
+ * ```typescript
267
+ * import { getUiCapability, RESOURCE_MIME_TYPE, registerAppTool } from "@modelcontextprotocol/ext-apps/server";
268
+ *
269
+ * server.oninitialized = ({ clientCapabilities }) => {
270
+ * const uiCap = getUiCapability(clientCapabilities);
271
+ * if (uiCap?.mimeTypes?.includes(RESOURCE_MIME_TYPE)) {
272
+ * registerAppTool(server, "weather", {
273
+ * description: "Get weather with interactive dashboard",
274
+ * _meta: { ui: { resourceUri: "ui://weather/dashboard" } },
275
+ * }, weatherHandler);
276
+ * } else {
277
+ * // Register text-only fallback
278
+ * server.registerTool("weather", {
279
+ * description: "Get weather as text",
280
+ * }, textWeatherHandler);
281
+ * }
282
+ * };
283
+ * ```
284
+ */
285
+ export declare function getUiCapability(clientCapabilities: (ClientCapabilities & {
286
+ extensions?: Record<string, unknown>;
287
+ }) | null | undefined): McpUiClientCapabilities | undefined;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Type-checked examples for {@link registerAppTool `registerAppTool`} and {@link registerAppResource `registerAppResource`}.
3
+ *
4
+ * These examples are included in the API documentation via `@includeCode` tags.
5
+ * Each function's region markers define the code snippet that appears in the docs.
6
+ *
7
+ * @module
8
+ */
9
+ export {};