Replace deprecated RESOURCE_URI_META_KEY usage with modern format (#457)
This commit is contained in:
parent
ef8fc6e2f0
commit
19fe73a08a
4 changed files with 80 additions and 28 deletions
|
|
@ -17,7 +17,6 @@ import {
|
|||
registerAppTool,
|
||||
registerAppResource,
|
||||
RESOURCE_MIME_TYPE,
|
||||
RESOURCE_URI_META_KEY,
|
||||
} from "@modelcontextprotocol/ext-apps/server";
|
||||
import { randomUUID } from "crypto";
|
||||
|
||||
|
|
@ -25,7 +24,7 @@ import { randomUUID } from "crypto";
|
|||
const DIST_DIR = import.meta.filename.endsWith(".ts")
|
||||
? path.join(import.meta.dirname, "dist")
|
||||
: import.meta.dirname;
|
||||
const RESOURCE_URI = "ui://cesium-map/mcp-app.html";
|
||||
const resourceUri = "ui://cesium-map/mcp-app.html";
|
||||
|
||||
// Nominatim API response type
|
||||
interface NominatimResult {
|
||||
|
|
@ -118,8 +117,8 @@ export function createServer(): McpServer {
|
|||
// Register the CesiumJS map resource with CSP for external tile sources
|
||||
registerAppResource(
|
||||
server,
|
||||
RESOURCE_URI,
|
||||
RESOURCE_URI,
|
||||
resourceUri,
|
||||
resourceUri,
|
||||
{ mimeType: RESOURCE_MIME_TYPE },
|
||||
async (): Promise<ReadResourceResult> => {
|
||||
const html = await fs.readFile(
|
||||
|
|
@ -130,7 +129,7 @@ export function createServer(): McpServer {
|
|||
contents: [
|
||||
// CSP metadata on the content item takes precedence over listing-level _meta
|
||||
{
|
||||
uri: RESOURCE_URI,
|
||||
uri: resourceUri,
|
||||
mimeType: RESOURCE_MIME_TYPE,
|
||||
text: html,
|
||||
_meta: cspMeta,
|
||||
|
|
@ -175,7 +174,7 @@ export function createServer(): McpServer {
|
|||
.optional()
|
||||
.describe("Optional label to display on the map"),
|
||||
},
|
||||
_meta: { [RESOURCE_URI_META_KEY]: RESOURCE_URI },
|
||||
_meta: { ui: { resourceUri } },
|
||||
},
|
||||
async ({ west, south, east, north, label }): Promise<CallToolResult> => ({
|
||||
content: [
|
||||
|
|
|
|||
|
|
@ -9,13 +9,12 @@ import {
|
|||
registerAppTool,
|
||||
registerAppResource,
|
||||
RESOURCE_MIME_TYPE,
|
||||
RESOURCE_URI_META_KEY,
|
||||
} from "@modelcontextprotocol/ext-apps/server";
|
||||
// Works both from source (server.ts) and compiled (dist/server.js)
|
||||
const DIST_DIR = import.meta.filename.endsWith(".ts")
|
||||
? path.join(import.meta.dirname, "dist")
|
||||
: import.meta.dirname;
|
||||
const RESOURCE_URI = "ui://transcript/mcp-app.html";
|
||||
const resourceUri = "ui://transcript/mcp-app.html";
|
||||
|
||||
/**
|
||||
* Creates a new MCP server instance with tools and resources registered.
|
||||
|
|
@ -35,7 +34,7 @@ export function createServer(): McpServer {
|
|||
description:
|
||||
"Opens a live speech transcription interface using the Web Speech API.",
|
||||
inputSchema: {},
|
||||
_meta: { [RESOURCE_URI_META_KEY]: RESOURCE_URI },
|
||||
_meta: { ui: { resourceUri } },
|
||||
},
|
||||
async (): Promise<CallToolResult> => {
|
||||
return {
|
||||
|
|
@ -55,8 +54,8 @@ export function createServer(): McpServer {
|
|||
// Register the UI resource
|
||||
registerAppResource(
|
||||
server,
|
||||
RESOURCE_URI,
|
||||
RESOURCE_URI,
|
||||
resourceUri,
|
||||
resourceUri,
|
||||
{ mimeType: RESOURCE_MIME_TYPE, description: "Transcript UI" },
|
||||
async (): Promise<ReadResourceResult> => {
|
||||
const html = await fs.readFile(
|
||||
|
|
@ -67,7 +66,7 @@ export function createServer(): McpServer {
|
|||
return {
|
||||
contents: [
|
||||
{
|
||||
uri: RESOURCE_URI,
|
||||
uri: resourceUri,
|
||||
mimeType: RESOURCE_MIME_TYPE,
|
||||
text: html,
|
||||
_meta: {
|
||||
|
|
|
|||
|
|
@ -12,16 +12,46 @@ import type {
|
|||
McpServer,
|
||||
ToolCallback,
|
||||
} from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { App, PostMessageTransport, RESOURCE_URI_META_KEY } from "./app.js";
|
||||
import {
|
||||
App,
|
||||
PostMessageTransport,
|
||||
RESOURCE_URI_META_KEY,
|
||||
McpUiToolMeta,
|
||||
} from "./app.js";
|
||||
import { registerAppTool } from "./server/index.js";
|
||||
|
||||
/**
|
||||
* Example: How MCP servers use RESOURCE_URI_META_KEY (server-side, not in Apps).
|
||||
* Example: Modern format for registering tools with UI (recommended).
|
||||
*/
|
||||
function RESOURCE_URI_META_KEY_serverSide(
|
||||
function RESOURCE_URI_META_KEY_modernFormat(
|
||||
server: McpServer,
|
||||
handler: ToolCallback,
|
||||
) {
|
||||
//#region RESOURCE_URI_META_KEY_serverSide
|
||||
//#region RESOURCE_URI_META_KEY_modernFormat
|
||||
// Preferred: Use registerAppTool with nested ui.resourceUri
|
||||
registerAppTool(
|
||||
server,
|
||||
"weather",
|
||||
{
|
||||
description: "Get weather forecast",
|
||||
_meta: {
|
||||
ui: { resourceUri: "ui://weather/forecast" },
|
||||
},
|
||||
},
|
||||
handler,
|
||||
);
|
||||
//#endregion RESOURCE_URI_META_KEY_modernFormat
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: Legacy format using RESOURCE_URI_META_KEY (deprecated).
|
||||
*/
|
||||
function RESOURCE_URI_META_KEY_legacyFormat(
|
||||
server: McpServer,
|
||||
handler: ToolCallback,
|
||||
) {
|
||||
//#region RESOURCE_URI_META_KEY_legacyFormat
|
||||
// Deprecated: Direct use of RESOURCE_URI_META_KEY
|
||||
server.registerTool(
|
||||
"weather",
|
||||
{
|
||||
|
|
@ -32,16 +62,19 @@ function RESOURCE_URI_META_KEY_serverSide(
|
|||
},
|
||||
handler,
|
||||
);
|
||||
//#endregion RESOURCE_URI_META_KEY_serverSide
|
||||
//#endregion RESOURCE_URI_META_KEY_legacyFormat
|
||||
}
|
||||
|
||||
/**
|
||||
* Example: How hosts check for RESOURCE_URI_META_KEY metadata (host-side).
|
||||
* Example: How hosts check for RESOURCE_URI_META_KEY metadata (must support both formats).
|
||||
*/
|
||||
function RESOURCE_URI_META_KEY_hostSide(tool: Tool) {
|
||||
//#region RESOURCE_URI_META_KEY_hostSide
|
||||
// Check tool definition metadata (from tools/list response):
|
||||
const uiUri = tool._meta?.[RESOURCE_URI_META_KEY];
|
||||
// Hosts should check both modern and legacy formats
|
||||
const meta = tool._meta;
|
||||
const uiMeta = meta?.ui as McpUiToolMeta | undefined;
|
||||
const legacyUri = meta?.[RESOURCE_URI_META_KEY] as string | undefined;
|
||||
const uiUri = uiMeta?.resourceUri ?? legacyUri;
|
||||
if (typeof uiUri === "string" && uiUri.startsWith("ui://")) {
|
||||
// Fetch the resource and display the UI
|
||||
}
|
||||
|
|
|
|||
37
src/app.ts
37
src/app.ts
|
|
@ -75,12 +75,30 @@ export {
|
|||
* When hosts see a tool with this metadata, they fetch and render the
|
||||
* corresponding {@link App `App`}.
|
||||
*
|
||||
* **Note**: This constant is provided for reference. App developers typically
|
||||
* don't need to use it directly. Prefer using {@link server-helpers!registerAppTool `registerAppTool`}
|
||||
* with the `_meta.ui.resourceUri` format instead.
|
||||
* **Note**: This constant is provided for reference and backwards compatibility.
|
||||
* Server developers should use {@link server-helpers!registerAppTool `registerAppTool`}
|
||||
* with the `_meta.ui.resourceUri` format instead. Host developers must check both
|
||||
* formats for compatibility.
|
||||
*
|
||||
* @example How MCP servers use this key (server-side, not in Apps)
|
||||
* ```ts source="./app.examples.ts#RESOURCE_URI_META_KEY_serverSide"
|
||||
* @example Modern format (server-side, not in Apps)
|
||||
* ```ts source="./app.examples.ts#RESOURCE_URI_META_KEY_modernFormat"
|
||||
* // Preferred: Use registerAppTool with nested ui.resourceUri
|
||||
* registerAppTool(
|
||||
* server,
|
||||
* "weather",
|
||||
* {
|
||||
* description: "Get weather forecast",
|
||||
* _meta: {
|
||||
* ui: { resourceUri: "ui://weather/forecast" },
|
||||
* },
|
||||
* },
|
||||
* handler,
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* @example Legacy format (deprecated, for backwards compatibility)
|
||||
* ```ts source="./app.examples.ts#RESOURCE_URI_META_KEY_legacyFormat"
|
||||
* // Deprecated: Direct use of RESOURCE_URI_META_KEY
|
||||
* server.registerTool(
|
||||
* "weather",
|
||||
* {
|
||||
|
|
@ -93,10 +111,13 @@ export {
|
|||
* );
|
||||
* ```
|
||||
*
|
||||
* @example How hosts check for this metadata (host-side)
|
||||
* @example How hosts check for this metadata (must support both formats)
|
||||
* ```ts source="./app.examples.ts#RESOURCE_URI_META_KEY_hostSide"
|
||||
* // Check tool definition metadata (from tools/list response):
|
||||
* const uiUri = tool._meta?.[RESOURCE_URI_META_KEY];
|
||||
* // Hosts should check both modern and legacy formats
|
||||
* const meta = tool._meta;
|
||||
* const uiMeta = meta?.ui as McpUiToolMeta | undefined;
|
||||
* const legacyUri = meta?.[RESOURCE_URI_META_KEY] as string | undefined;
|
||||
* const uiUri = uiMeta?.resourceUri ?? legacyUri;
|
||||
* if (typeof uiUri === "string" && uiUri.startsWith("ui://")) {
|
||||
* // Fetch the resource and display the UI
|
||||
* }
|
||||
|
|
|
|||
Loading…
Reference in a new issue