Skip to content

Commit bf23882

Browse files
Simplify basic-server-* examples
- Clarify comments - Return plain text from `get-time` tool instead of JSON - Remove simulated cleanup delay from `onteardown` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 2df8bb1 commit bf23882

File tree

4 files changed

+28
-42
lines changed

4 files changed

+28
-42
lines changed

examples/basic-server-react/server.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE, RESOURCE_URI_
66
import { startServer } from "./src/server-utils.js";
77

88
const DIST_DIR = path.join(import.meta.dirname, "dist");
9-
const RESOURCE_URI = "ui://get-time/mcp-app.html";
109

1110
/**
1211
* Creates a new MCP server instance with tools and resources registered.
@@ -17,37 +16,37 @@ function createServer(): McpServer {
1716
version: "1.0.0",
1817
});
1918

20-
// MCP Apps require two-part registration: a tool (what the LLM calls) and a
21-
// resource (the UI it renders). The `_meta` field on the tool links to the
22-
// resource URI, telling hosts which UI to display when the tool executes.
19+
// Two-part registration: tool + resource, tied together by the resource URI.
20+
const resourceUri = "ui://get-time/mcp-app.html";
21+
22+
// Register a tool with UI metadata. When the host calls this tool, it reads
23+
// `_meta[RESOURCE_URI_META_KEY]` to know which resource to fetch and render
24+
// as an interactive UI.
2325
registerAppTool(server,
2426
"get-time",
2527
{
2628
title: "Get Time",
2729
description: "Returns the current server time as an ISO 8601 string.",
2830
inputSchema: {},
29-
_meta: { [RESOURCE_URI_META_KEY]: RESOURCE_URI },
31+
_meta: { [RESOURCE_URI_META_KEY]: resourceUri },
3032
},
3133
async (): Promise<CallToolResult> => {
3234
const time = new Date().toISOString();
33-
return {
34-
content: [{ type: "text", text: JSON.stringify({ time }) }],
35-
};
35+
return { content: [{ type: "text", text: time }] };
3636
},
3737
);
3838

39+
// Register the resource, which returns the bundled HTML/JavaScript for the UI.
3940
registerAppResource(server,
40-
RESOURCE_URI,
41-
RESOURCE_URI,
41+
resourceUri,
42+
resourceUri,
4243
{ mimeType: RESOURCE_MIME_TYPE },
4344
async (): Promise<ReadResourceResult> => {
4445
const html = await fs.readFile(path.join(DIST_DIR, "mcp-app.html"), "utf-8");
4546

4647
return {
4748
contents: [
48-
// Per the MCP App specification, "text/html;profile=mcp-app" signals
49-
// to the Host that this resource is indeed for an MCP App UI.
50-
{ uri: RESOURCE_URI, mimeType: RESOURCE_MIME_TYPE, text: html },
49+
{ uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html },
5150
],
5251
};
5352
},

examples/basic-server-react/src/mcp-app.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,8 @@ const log = {
2020

2121

2222
function extractTime(callToolResult: CallToolResult): string {
23-
const text = callToolResult.content!
24-
.filter((c): c is { type: "text"; text: string } => c.type === "text")
25-
.map((c) => c.text)
26-
.join("");
27-
const { time } = JSON.parse(text) as { time: string };
28-
return time;
23+
const { text } = callToolResult.content?.find((c) => c.type === "text")!;
24+
return text;
2925
}
3026

3127

@@ -37,8 +33,6 @@ function GetTimeApp() {
3733
onAppCreated: (app) => {
3834
app.onteardown = async () => {
3935
log.info("App is being torn down");
40-
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulate cleanup work
41-
log.info("App teardown complete");
4236
return {};
4337
};
4438
app.ontoolinput = async (input) => {

examples/basic-server-vanillajs/server.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE, RESOURCE_URI_
66
import { startServer } from "./src/server-utils.js";
77

88
const DIST_DIR = path.join(import.meta.dirname, "dist");
9-
const RESOURCE_URI = "ui://get-time/mcp-app.html";
109

1110
/**
1211
* Creates a new MCP server instance with tools and resources registered.
@@ -17,37 +16,37 @@ function createServer(): McpServer {
1716
version: "1.0.0",
1817
});
1918

20-
// MCP Apps require two-part registration: a tool (what the LLM calls) and a
21-
// resource (the UI it renders). The `_meta` field on the tool links to the
22-
// resource URI, telling hosts which UI to display when the tool executes.
19+
// Two-part registration: tool + resource, tied together by the resource URI.
20+
const resourceUri = "ui://get-time/mcp-app.html";
21+
22+
// Register a tool with UI metadata. When the host calls this tool, it reads
23+
// `_meta[RESOURCE_URI_META_KEY]` to know which resource to fetch and render
24+
// as an interactive UI.
2325
registerAppTool(server,
2426
"get-time",
2527
{
2628
title: "Get Time",
2729
description: "Returns the current server time as an ISO 8601 string.",
2830
inputSchema: {},
29-
_meta: { [RESOURCE_URI_META_KEY]: RESOURCE_URI },
31+
_meta: { [RESOURCE_URI_META_KEY]: resourceUri },
3032
},
3133
async (): Promise<CallToolResult> => {
3234
const time = new Date().toISOString();
33-
return {
34-
content: [{ type: "text", text: JSON.stringify({ time }) }],
35-
};
35+
return { content: [{ type: "text", text: time }] };
3636
},
3737
);
3838

39+
// Register the resource, which returns the bundled HTML/JavaScript for the UI.
3940
registerAppResource(server,
40-
RESOURCE_URI,
41-
RESOURCE_URI,
41+
resourceUri,
42+
resourceUri,
4243
{ mimeType: RESOURCE_MIME_TYPE },
4344
async (): Promise<ReadResourceResult> => {
4445
const html = await fs.readFile(path.join(DIST_DIR, "mcp-app.html"), "utf-8");
4546

4647
return {
4748
contents: [
48-
// Per the MCP App specification, "text/html;profile=mcp-app" signals
49-
// to the Host that this resource is indeed for an MCP App UI.
50-
{ uri: RESOURCE_URI, mimeType: RESOURCE_MIME_TYPE, text: html },
49+
{ uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html },
5150
],
5251
};
5352
},

examples/basic-server-vanillajs/src/mcp-app.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,8 @@ const log = {
1515

1616

1717
function extractTime(result: CallToolResult): string {
18-
const text = result.content!
19-
.filter((c): c is { type: "text"; text: string } => c.type === "text")
20-
.map((c) => c.text)
21-
.join("");
22-
const { time } = JSON.parse(text) as { time: string };
23-
return time;
18+
const { text } = result.content?.find((c) => c.type === "text")!;
19+
return text;
2420
}
2521

2622

@@ -40,8 +36,6 @@ const app = new App({ name: "Get Time App", version: "1.0.0" });
4036

4137
app.onteardown = async () => {
4238
log.info("App is being torn down");
43-
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulate cleanup work
44-
log.info("App teardown complete");
4539
return {};
4640
};
4741

0 commit comments

Comments
 (0)