Skip to main content
sunpeak API

Overview

Simulations define test scenarios for your resources—combining tool definitions, mock data, and platform state. They can be used with the Inspector for local development or runMCPServer for platform testing with hosts like ChatGPT and Claude. Simulations are JSON files that live in the tests/simulations/ directory. Each simulation references a tool file by name — tool metadata and resource linkage are handled by the tool files in src/tools/.

File Convention

Simulation files live in a flat tests/simulations/ directory:
For example:
  • tests/simulations/show-albums.json
  • tests/simulations/review-diff.json
  • tests/simulations/review-post.json
Any *.json filename works. Multiple simulations can reference the same tool with different fixture data. Tool files live in src/tools/:
  • Each .ts file exports tool (metadata with optional resource link), schema (Zod), and a default handler.
Resource files live in src/resources/{name}/:
  • Component + Metadata: src/resources/{name}/{name}.tsx (exports both the React component and export const resource: ResourceConfig)

JSON Schema

Each simulation JSON file contains:
The tool field is a string referencing a tool filename (without .ts) in src/tools/. Tool metadata (name, description, schema, annotations, visibility) lives in the tool file, not in the simulation.

Auto-Discovery

The framework automatically discovers and links everything:
  1. Tools: Scans src/tools/*.ts for tool files with metadata, schemas, and handlers
  2. Simulations: Scans tests/simulations/*.json and links each to its tool via the tool string field
  3. Resources: Each tool file references its resource by directory name (e.g., resource: 'albums')
This means you never need to:
  • Duplicate tool metadata in simulations
  • Import resource metadata into simulations
  • Maintain an index file of simulations or tools

Multiple Scenarios

Create multiple simulations for the same tool to test different scenarios:
Each simulation can have different toolInput and toolResult.structuredContent to test various data scenarios.

Mocking Server Tool Calls

When a resource calls callServerTool (e.g., the review resource calling a backend-only “review” tool), the inspector needs mock responses. Instead of separate simulation files for each backend tool response, you define mock responses inline using the serverTools field on the resource’s simulation.
The serverTools map supports two forms: Simple form — always return the same result:
Conditional form — match against call arguments:
The when object does shallow key matching against the tool call arguments. The first entry whose keys all match wins. Use structuredContent in the result to return structured data to the calling resource. For example, the review tool returns { status: 'success', message: '...' } or { status: 'cancelled', message: '...' } — the review resource reads status to determine success/error styling and displays message. Use isError: true only for actual tool execution failures.

Simulations vs real server calls

When testing an external MCP server (Python, Go, etc.), you have two testing modes: Simulation fixtures (fast, no server needed): Write JSON files with pre-baked toolResult data. The inspector renders the result without calling your server. Use this for visual regression tests and UI state testing where you want fast, deterministic results.
Real server calls (integration testing): Pass input to inspector.renderTool. The inspector calls your MCP server with those arguments and renders the response. Use this to verify that your server returns correct data and the UI handles it properly. You can also use mcp.callTool for protocol-level assertions without rendering.
Both modes work for external servers. Without any simulation fixtures, inspector.renderTool falls back to real server calls by default.

Simulation fixtures for external servers

External servers don’t have src/tools/ directories. Instead, tools are auto-discovered via listTools() when the inspector connects. You can still write simulation fixtures to test specific UI states without calling the server. Create a tests/simulations/ directory and pass it to your config:
The JSON format is the same as for sunpeak projects. The tool field references the tool name as reported by listTools():

Properties

name
string
required
Unique identifier for the simulation. Auto-generated from the filename.
userMessage
string
A decorative message shown in the inspector interface. Has no functional purpose.
tool
string
required
A string referencing a tool filename (without .ts) in src/tools/.
toolInput
Record<string, unknown>
Mock input parameters for the tool call. Accessible via useToolData().
toolResult
object
Mock data for the tool response. The structuredContent property is passed to your component via useToolData().
hostContext
Partial<McpUiHostContext>
Initial host context for the simulation. Accessible via useHostContext().
serverTools
Record<string, ServerToolMock>
Mock responses for callServerTool calls made by the resource. Keys are tool names. Values are either a single CallToolResult (always returned) or an array of { when, result } entries for argument-based conditional matching.

MCP SDK Types

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

Tool

Tool Visibility

The tool._meta.ui.visibility field controls which contexts can invoke the tool:
  • "model" — The AI model can call this tool
  • "app" — The app can call this tool (via useCallServerTool)
When set in the simulation JSON, the MCP server preserves this metadata when registering tools with the host.

Resource

Resource Metadata (_meta.ui)

The resource._meta.ui field configures resource rendering behavior:
Permissions
The inspector maps these to iframe allow attribute directives. Only declared permissions are enabled.
CSP
Example resource config with metadata:

See Also

Inspector

Component API reference.

runMCPServer

MCP server API reference.