Skip to main content

Overview

Simulations define test scenarios for your resources—combining tool definitions, mock data, and platform state. They can be used with the ChatGPTSimulator for local development or runMCPServer for platform testing.
In the sunpeak framework, simulations are JSON files with auto-discovery. The resource component and metadata are automatically linked based on filename prefix.

File Naming Convention

Simulation files follow the pattern:
src/simulations/{resource}-{scenario}-simulation.json
For example:
  • albums-show-simulation.json - linked to albums-resource.tsx
  • review-diff-simulation.json - linked to review-resource.tsx
  • review-post-simulation.json - linked to review-resource.tsx
The {resource} prefix determines which resource files are automatically linked:
  • Component: src/resources/{resource}-resource.tsx
  • Metadata: src/resources/{resource}-resource.json
You can have multiple simulations per resource (e.g., albums-show-simulation.json and albums-empty-simulation.json).

JSON Schema

Each simulation JSON file contains:
// src/simulations/example-show-simulation.json
{
  "userMessage": "Show me an example",
  "tool": {
    "name": "show-example",
    "description": "Show an example",
    "inputSchema": { "type": "object", "properties": {}, "additionalProperties": false },
    "title": "Show Example",
    "annotations": { "readOnlyHint": true },
    "_meta": {
      "openai/toolInvocation/invoking": "Loading example",
      "openai/toolInvocation/invoked": "Example loaded",
      "openai/widgetAccessible": true,
      "openai/resultCanProduceWidget": true
    }
  },
  "callToolResult": {
    "structuredContent": {
      "items": ["item1", "item2"]
    },
    "_meta": {}
  }
}

Auto-Discovery

The framework automatically discovers and links simulations:
  1. Discovery: Glob pattern src/simulations/*-simulation.json
  2. Matching: Longest prefix match links to resources (e.g., albums-show matches albums-resource.tsx)
  3. No imports needed: Everything is wired automatically
This means you never need to:
  • Import resource metadata into simulations
  • Specify resource in the simulation JSON
  • Maintain an index file of simulations

Multiple Scenarios

Create multiple simulations per resource to test different scenarios:
src/simulations/
  albums-show-simulation.json      # Default view
  albums-empty-simulation.json     # Empty state
  albums-error-simulation.json     # Error state
Each simulation can have different callToolResult.structuredContent to test various data scenarios.

Properties

name
string
required
Unique identifier for the simulation. Used to select simulations in the UI and URL parameters. (Library only - auto-generated from filename in framework)
resourceComponent
React.ComponentType
required
The React component to render for this simulation. (Library only - auto-linked in framework)
userMessage
string
A decorative message shown in the simulator interface. Has no functional purpose.
tool
Tool
required
MCP Tool definition from @modelcontextprotocol/sdk. Defines the tool’s name, description, input schema, and metadata.
import type { Tool } from '@modelcontextprotocol/sdk/types.js';
resource
Resource
required
MCP Resource definition from @modelcontextprotocol/sdk. Defines the resource’s name, URI, MIME type, and metadata. (Library only - auto-linked in framework)
import type { Resource } from '@modelcontextprotocol/sdk/types.js';
callToolResult
CallToolResult
Mock data for the MCP CallTool response. The structuredContent property is passed to your component via useWidgetProps().
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
callToolRequestParams
CallToolRequestParams
Mock input parameters for the tool call. The arguments property is accessible via useToolInput().
import type { CallToolRequest } from '@modelcontextprotocol/sdk/types.js';
type CallToolRequestParams = CallToolRequest['params'];
widgetState
Record<string, unknown> | null
Initial widget state for the simulation. Accessible via useWidgetState().

MCP SDK Types

The simulation interface uses official types from @modelcontextprotocol/sdk:

Tool

interface Tool {
  name: string;
  description?: string;
  inputSchema: JSONSchema;
  title?: string;
  annotations?: {
    readOnlyHint?: boolean;
    destructiveHint?: boolean;
    idempotentHint?: boolean;
    openWorldHint?: boolean;
  };
  _meta?: Record<string, unknown>;
}

Resource

interface Resource {
  name: string;
  uri: string;
  title?: string;
  description?: string;
  mimeType?: string;
  _meta?: Record<string, unknown>;
}

CallToolResult

interface CallToolResult {
  content?: Array<TextContent | ImageContent | AudioContent | EmbeddedResource>;
  structuredContent?: Record<string, unknown>;
  isError?: boolean;
  _meta?: Record<string, unknown>;
}

OpenAI-Specific Metadata

When targeting ChatGPT, include OpenAI-specific metadata in the _meta fields:

Tool _meta

{
  _meta: {
    'openai/toolInvocation/invoking': 'Loading albums...',
    'openai/toolInvocation/invoked': 'Albums loaded',
    'openai/widgetAccessible': true,
    'openai/resultCanProduceWidget': true,
  }
}

Resource _meta

{
  _meta: {
    'openai/widgetDomain': 'https://example.com',
    'openai/widgetCSP': {
      connect_domains: [],
      resource_domains: ['https://*.oaistatic.com'],
    },
  }
}

See Also

ChatGPTSimulator

Component API reference.

runMCPServer

MCP server API reference.