Skip to content

Commit 075e14d

Browse files
committed
feat: add outputSchema to all example servers
Define output schemas for structuredContent validation: - basic-server-vanillajs: { time: string } - budget-allocator-server: BudgetDataResponseSchema - cohort-heatmap-server: CohortDataSchema - customer-segmentation-server: customers/segments schema - integration-server: { time: string } - scenario-modeler-server: templates/defaultInputs schema - system-monitor-server: SystemStatsSchema - threejs-server: { code, height } - video-resource-server: { videoUri, description } - wiki-explorer-server: { page, links, error }
1 parent 8ad706e commit 075e14d

File tree

15 files changed

+69
-5
lines changed

15 files changed

+69
-5
lines changed

examples/basic-server-vanillajs/server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
33
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
44
import fs from "node:fs/promises";
55
import path from "node:path";
6+
import { z } from "zod";
67
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE, RESOURCE_URI_META_KEY } from "@modelcontextprotocol/ext-apps/server";
78
import { startServer } from "./server-utils.js";
89

@@ -28,6 +29,9 @@ export function createServer(): McpServer {
2829
title: "Get Time",
2930
description: "Returns the current server time as an ISO 8601 string.",
3031
inputSchema: {},
32+
outputSchema: z.object({
33+
time: z.string(),
34+
}),
3135
_meta: { [RESOURCE_URI_META_KEY]: RESOURCE_URI },
3236
},
3337
async (): Promise<CallToolResult> => {

examples/budget-allocator-server/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ export function createServer(): McpServer {
248248
description:
249249
"Returns budget configuration with 24 months of historical allocations and industry benchmarks by company stage",
250250
inputSchema: {},
251+
outputSchema: BudgetDataResponseSchema,
251252
_meta: { [RESOURCE_URI_META_KEY]: resourceUri },
252253
},
253254
async (): Promise<CallToolResult> => {

examples/budget-allocator-server/src/mcp-app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ const app = new App({ name: "Budget Allocator", version: "1.0.0" });
607607

608608
app.ontoolresult = (result) => {
609609
log.info("Received tool result:", result);
610-
const data = result.structuredContent as BudgetDataResponse;
610+
const data = result.structuredContent as unknown as BudgetDataResponse;
611611
if (data?.config && data?.analytics) {
612612
initializeUI(data.config, data.analytics);
613613
}

examples/cohort-heatmap-server/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ export function createServer(): McpServer {
169169
description:
170170
"Returns cohort retention heatmap data showing customer retention over time by signup month",
171171
inputSchema: GetCohortDataInputSchema.shape,
172+
outputSchema: CohortDataSchema.shape,
172173
_meta: { [RESOURCE_URI_META_KEY]: resourceUri },
173174
},
174175
async ({ metric, periodType, cohortCount, maxPeriods }) => {

examples/cohort-heatmap-server/src/mcp-app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ function CohortHeatmapInner({
123123
maxPeriods: 12,
124124
},
125125
});
126-
setData(result.structuredContent as CohortData);
126+
setData(result.structuredContent as unknown as CohortData);
127127
} catch (e) {
128128
console.error("Failed to fetch cohort data:", e);
129129
} finally {

examples/customer-segmentation-server/server.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,29 @@ const GetCustomerDataInputSchema = z.object({
3030
.describe("Filter by segment (default: All)"),
3131
});
3232

33+
const CustomerSchema = z.object({
34+
id: z.string(),
35+
name: z.string(),
36+
segment: z.string(),
37+
annualRevenue: z.number(),
38+
employeeCount: z.number(),
39+
accountAge: z.number(),
40+
engagementScore: z.number(),
41+
supportTickets: z.number(),
42+
nps: z.number(),
43+
});
44+
45+
const SegmentSummarySchema = z.object({
46+
name: z.string(),
47+
count: z.number(),
48+
color: z.string(),
49+
});
50+
51+
const GetCustomerDataOutputSchema = z.object({
52+
customers: z.array(CustomerSchema),
53+
segments: z.array(SegmentSummarySchema),
54+
});
55+
3356
// Cache generated data for session consistency
3457
let cachedCustomers: Customer[] | null = null;
3558
let cachedSegments: SegmentSummary[] | null = null;
@@ -78,6 +101,7 @@ export function createServer(): McpServer {
78101
description:
79102
"Returns customer data with segment information for visualization. Optionally filter by segment.",
80103
inputSchema: GetCustomerDataInputSchema.shape,
104+
outputSchema: GetCustomerDataOutputSchema.shape,
81105
_meta: { [RESOURCE_URI_META_KEY]: resourceUri },
82106
},
83107
async ({ segment }): Promise<CallToolResult> => {

examples/integration-server/server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
} from "@modelcontextprotocol/sdk/types.js";
77
import fs from "node:fs/promises";
88
import path from "node:path";
9+
import { z } from "zod";
910
import {
1011
registerAppTool,
1112
registerAppResource,
@@ -33,6 +34,9 @@ export function createServer(): McpServer {
3334
title: "Get Time",
3435
description: "Returns the current server time.",
3536
inputSchema: {},
37+
outputSchema: z.object({
38+
time: z.string(),
39+
}),
3640
_meta: { [RESOURCE_URI_META_KEY]: RESOURCE_URI },
3741
},
3842
async (): Promise<CallToolResult> => {

examples/scenario-modeler-server/server.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ const GetScenarioDataInputSchema = z.object({
6464
),
6565
});
6666

67+
const GetScenarioDataOutputSchema = z.object({
68+
templates: z.array(ScenarioTemplateSchema),
69+
defaultInputs: ScenarioInputsSchema,
70+
customProjections: z.array(MonthlyProjectionSchema).optional(),
71+
customSummary: ScenarioSummarySchema.optional(),
72+
});
73+
6774
// Types derived from schemas
6875
type ScenarioInputs = z.infer<typeof ScenarioInputsSchema>;
6976
type MonthlyProjection = z.infer<typeof MonthlyProjectionSchema>;
@@ -269,6 +276,7 @@ export function createServer(): McpServer {
269276
description:
270277
"Returns SaaS scenario templates and optionally computes custom projections for given inputs",
271278
inputSchema: GetScenarioDataInputSchema.shape,
279+
outputSchema: GetScenarioDataOutputSchema.shape,
272280
_meta: { [RESOURCE_URI_META_KEY]: resourceUri },
273281
},
274282
async (args: {

examples/scenario-modeler-server/src/mcp-app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function ScenarioModeler() {
5858
onAppCreated: (app) => {
5959
app.ontoolresult = async (result) => {
6060
const { templates, defaultInputs } =
61-
result.structuredContent as CallToolResultData;
61+
result.structuredContent as unknown as CallToolResultData;
6262
if (templates) setTemplates(templates);
6363
if (defaultInputs) setDefaultInputs(defaultInputs);
6464
};

examples/system-monitor-server/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export function createServer(): McpServer {
124124
description:
125125
"Returns current system statistics including per-core CPU usage, memory, and system info.",
126126
inputSchema: {},
127+
outputSchema: SystemStatsSchema.shape,
127128
_meta: { [RESOURCE_URI_META_KEY]: resourceUri },
128129
},
129130
async (): Promise<CallToolResult> => {

0 commit comments

Comments
 (0)