Skip to content

Conversation

@ochafik
Copy link
Collaborator

@ochafik ochafik commented Jan 9, 2026

Summary

Update all example servers to use structuredContent for typed tool outputs, with corresponding outputSchema declarations.

Changes:

  1. Add structuredContent to tool results - All servers now return structured data directly instead of requiring JSON.parse on the client side

  2. Add outputSchema to tool definitions - Each tool now declares its output schema using Zod, enabling validation and documentation

  3. Simplify mcp-app clients - Clients now read result.structuredContent directly instead of parsing JSON from text content

Updated servers (10):

  • basic-server-vanillajs - { time: string }
  • budget-allocator-server - BudgetDataResponseSchema
  • cohort-heatmap-server - CohortDataSchema
  • customer-segmentation-server - { customers, segments }
  • integration-server - { time: string }
  • scenario-modeler-server - { templates, defaultInputs, ... }
  • system-monitor-server - SystemStatsSchema
  • threejs-server - { code, height }
  • video-resource-server - { videoUri, description }
  • wiki-explorer-server - { page, links, error }

Test plan

  • All examples build successfully
  • Manual testing of each example server

🤖 Generated with Claude Code

All servers now return structuredContent alongside JSON text content.
All mcp-apps now read structuredContent directly (no JSON.parse fallback).

Updated servers:
- basic-server-vanillajs
- budget-allocator-server
- cohort-heatmap-server
- customer-segmentation-server
- integration-server
- scenario-modeler-server
- system-monitor-server
- threejs-server
- video-resource-server
- wiki-explorer-server
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 }
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 9, 2026

Open in StackBlitz

@modelcontextprotocol/ext-apps

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/ext-apps@220

@modelcontextprotocol/server-basic-react

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-react@220

@modelcontextprotocol/server-basic-vanillajs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-basic-vanillajs@220

@modelcontextprotocol/server-budget-allocator

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-budget-allocator@220

@modelcontextprotocol/server-cohort-heatmap

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-cohort-heatmap@220

@modelcontextprotocol/server-customer-segmentation

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-customer-segmentation@220

@modelcontextprotocol/server-scenario-modeler

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-scenario-modeler@220

@modelcontextprotocol/server-system-monitor

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-system-monitor@220

@modelcontextprotocol/server-threejs

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-threejs@220

@modelcontextprotocol/server-wiki-explorer

npm i https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/server-wiki-explorer@220

commit: af88f60

All servers now return structuredContent alongside JSON text content.
All mcp-apps now read structuredContent directly (no JSON.parse fallback).

Updated servers:
- basic-server-vanillajs
- budget-allocator-server
- cohort-heatmap-server
- customer-segmentation-server
- integration-server
- scenario-modeler-server
- system-monitor-server
- threejs-server
- video-resource-server
- wiki-explorer-server
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 }
@ochafik ochafik force-pushed the ochafik/structured-content branch from c999ada to a6c34d7 Compare January 9, 2026 01:17
@ochafik ochafik marked this pull request as ready for review January 9, 2026 22:39
jonathanhefner
jonathanhefner previously approved these changes Jan 9, 2026
Comment on lines 38 to 43
const time = new Date().toISOString();
const data = { time };
return {
content: [{ type: "text", text: JSON.stringify({ time }) }],
content: [{ type: "text", text: JSON.stringify(data) }],
structuredContent: data,
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm inclined to write this as either:

      const data = { time: new Date().toISOString() };
      return {
        content: [{ type: "text", text: JSON.stringify(data) }],
        structuredContent: data,
      };  

Or as:

      const time = new Date().toISOString();
      return {
        content: [{ type: "text", text: time }],
        structuredContent: { time },
      };  

depending on how strict we want to be about content vs structuredContent equivalence.

I also think we should update the Quickstart guide to match whatever basic-server-vanillajs does, because it links to it as the full example.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Updated to match the quickstart pattern:

const time = new Date().toISOString();
return {
  content: [{ type: "text", text: time }],
  structuredContent: { time },
};

The quickstart guide already uses this pattern (lines 127-132), so no changes needed there.

Comment on lines 18 to 19
const data = result.structuredContent as { time: string };
return data.time;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally, I wrote this as:

  const { time } = (result.structuredContent as { time?: string }) ?? {};
  return time ?? "[ERROR]";

to handle potential type desync, though I don't feel too strongly about it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Updated to use the defensive pattern:

const { time } = (result.structuredContent as { time?: string }) ?? {};
return time ?? "[ERROR]";

This also matches what the quickstart guide shows (lines 223-224).

content: [
{
type: "text",
text: JSON.stringify(response),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally, this was richly formatted text — see 61cd4ed#diff-4360a472ed891e48c204f1cf177aec8fb637d96bff5047cba6a1e4a899971b1aL224-R270.

Not sure whether we care about restoring that for these examples.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored! Added formatBudgetSummary that produces human-readable output like:

Budget Allocator Configuration
==============================

Default Budget: $100,000
Available Presets: $50,000, $100,000, $250,000, $500,000

Categories:
  - Marketing: 25% default
  - Engineering: 35% default
  ...

The structuredContent still contains the full data for the UI.

);

return {
content: [{ type: "text", text: JSON.stringify(data) }],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored! Added formatCohortSummary that produces:

Cohort Analysis: 12 cohorts, 12 periods
Average retention: 45.2%
Metric: retention, Period: monthly

customProjections: customScenario?.projections,
customSummary: customScenario?.summary,
}),
text: JSON.stringify(data),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored! Added formatCurrency and formatScenarioSummary that produce:

SaaS Scenario Modeler
========================================

Available Templates:
  🌱 Bootstrapped Growth: Low burn, steady growth, path to profitability
  🚀 VC Rocketship: High burn, explosive growth, raise more later
  ...

Custom Scenario:
  Ending MRR: $62.5K
  ARR: $750.0K
  Total Revenue: $678.2K
  ...

- Simplify server.ts to return plain time string in text content (not JSON),
  matching the quickstart guide pattern
- Add defensive coding in mcp-app.ts with optional chaining and fallback
  to handle potential type mismatches gracefully
Restore the human-readable text formatting functions that were removed,
providing meaningful summaries in the text content while keeping
structuredContent for programmatic UI consumption:

- budget-allocator-server: formatBudgetSummary with config overview
- cohort-heatmap-server: formatCohortSummary with retention stats
- scenario-modeler-server: formatScenarioSummary with financial metrics
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants