Dual-Protocol Support: The inspector supports both widget protocols:
- MCP Apps - Standard MCP protocol (SEP-1865) with JSON-RPC communication
- ChatGPT Apps SDK - OpenAI’s protocol with
window.openaiAPI emulation
Overview
What are Widget Protocols?
MCP servers can provide interactive widgets using two protocols:| Protocol | Standard | Clients | Communication |
|---|---|---|---|
| MCP Apps | SEP-1865 (MCP standard) | Claude, Goose, MCP clients | JSON-RPC over postMessage |
| ChatGPT Apps SDK | OpenAI proprietary | ChatGPT | window.openai API |
type: "mcpApps".
How the Inspector Helps
The inspector provides:- Dual-Protocol Testing: Switch between MCP Apps and ChatGPT protocols
- Protocol Toggle: Test cross-compatibility with one click
- Widget Rendering: Preview widgets in both protocols
- Debug Controls: Test different devices, locales, CSP modes
- Display Modes: Test inline, picture-in-picture, fullscreen
- Interactive Debugging: Test widget interactions and tool calls
- Dev Mode Support: Hot reload for widget development
Protocol Toggle
For widgets that support both protocols (usingtype: "mcpApps"), the inspector shows a Protocol Toggle that lets you switch between:
- MCP Apps - Tests the SEP-1865 protocol with JSON-RPC communication
- ChatGPT Apps - Tests the Apps SDK protocol with window.openai emulation
type: "appsSdk") only render using ChatGPT protocol.
MCP Apps Debug Controls
When testing MCP Apps protocol widgets, the inspector provides comprehensive debug controls:Device Emulation
Switch between device types to test responsive behavior:- Desktop - Large viewport, hover support
- Mobile - Small viewport, touch support
- Tablet - Medium viewport, both touch and hover
Locale & Timezone
Test internationalization:- Locale Selector - Choose from 100+ locales (en-US, es-ES, ja-JP, etc.)
- Timezone Selector - Test timezone-specific behavior (MCP Apps only)
CSP Mode Toggle
Test Content Security Policy enforcement:- Permissive - Relaxed CSP for debugging
- Widget-Declared - Enforces widget’s declared CSP (production mode)
Capabilities Testing
Toggle device capabilities:- Touch - Enable/disable touch input simulation
- Hover - Enable/disable hover state detection
Safe Area Insets
Configure safe area insets for testing mobile layouts:- Top - Notch or status bar area
- Bottom - Home indicator area
- Left/Right - Display cutouts
Display Mode Controls
Test different display modes:- Inline - Default embedded view
- Picture-in-Picture - Floating window (click PiP button)
- Fullscreen - Full browser window (click fullscreen button)
Props Management
Test widgets with different inputs:- Use Tool Input - Use current tool call parameters
- Select Preset - Choose from saved prop configurations
- Create Preset - Save current props for reuse
- Edit Props - Manually modify prop values
ChatGPT Apps SDK: window.openai API Emulation
This section covers the ChatGPT Apps SDK protocol specifically. For MCP Apps protocol widgets, the inspector uses JSON-RPC over postMessage instead.Your widget code can work with both protocols by using the
useWidget() hook from mcp-use/react, which abstracts protocol differences.window.openai API. This API is automatically injected into widget iframes, allowing your components to work identically in the inspector and in ChatGPT.
API Overview
Thewindow.openai object provides:
- Global Properties: Theme, display mode, tool data, widget state
- Methods: Tool calls, follow-up messages, display mode requests
- Events: Global change notifications via
openai:set_globalsevents
Global Properties
These properties are available onwindow.openai and update reactively:
toolInput
The input parameters passed to the tool that triggered this widget.
toolOutput
The structured output from the tool execution. This is the primary data source for your widget.
toolResponseMetadata
Additional metadata from the tool response (currently null in inspector).
widgetState
Persistent state for this widget instance. State is scoped to the specific widget and conversation message.
Widget state persists in browser localStorage and is rehydrated when the
widget loads. State is scoped to the widget instance and doesn’t travel across
different widgets or conversation turns.
displayMode
Current display mode: "inline", "pip", or "fullscreen".
theme
Current theme: "light" or "dark". Automatically syncs with inspector theme.
maxHeight
Maximum height available for the widget container (in pixels).
locale
User’s locale setting.
safeArea
Safe area insets for mobile devices.
userAgent
User agent information including device type and capabilities.
API Methods
callTool(name, params)
Call an MCP tool directly from the widget. Returns a Promise with the tool result.
- Sends
postMessageto parent (inspector) - Inspector executes tool via MCP connection
- Result is formatted to match OpenAI’s expected format
- MCP
contentsarray is converted to OpenAIcontentformat - 30-second timeout for tool calls
sendFollowUpMessage(args)
Send a follow-up message to ChatGPT as if the user typed it.
- Dispatches custom event
mcp-inspector:widget-followup - Message appears in Chat tab
- Can be used to continue conversation from widget interactions
setWidgetState(state)
Persist widget state across interactions. State is visible to ChatGPT and can influence future tool calls.
- Stores state in browser localStorage
- Keyed by widget instance ID
- State is rehydrated on widget load
- Sent to parent via
postMessagefor inspector awareness
Keep widget state under 4k tokens for performance. State is sent to ChatGPT
and can influence model behavior.
requestDisplayMode(options)
Request a different display mode for the widget.
"inline"- Default embedded view"pip"- Picture-in-Picture floating window"fullscreen"- Full browser window
- Uses native Fullscreen API when available
- Falls back to CSS-based fullscreen
- On mobile, PiP may be coerced to fullscreen
- Updates
displayModeproperty and dispatches events
openExternal(payload)
Open an external link in a new window/tab.
- Uses
window.open()with security flags - Opens in new tab with
noopener,noreferrer
notifyIntrinsicHeight(height)
Notify OpenAI about intrinsic height changes for auto-sizing. This allows widgets to dynamically resize based on content.
- Sends
postMessagewith typeopenai:notifyIntrinsicHeight - Inspector updates iframe height accordingly
- Height is capped based on display mode (fullscreen/pip respect viewport)
- Used by
McpUseProviderwithautoSize={true}for automatic height updates
Console Proxy Toggle
The inspector provides a console proxy feature that allows you to forward iframe console logs to the page console for easier debugging.Enabling Console Proxy
- Open the Console panel in the inspector (click the terminal icon)
- Toggle “Proxy logs to page console” switch
- Console logs from the widget iframe will now appear in your browser’s developer console
Features
- Persistent Preference: Your preference is saved in
localStorageand persists across sessions - Formatted Output: Logs are prefixed with
[WIDGET CONSOLE]for easy identification - Log Level Preservation: Error, warn, info, debug, and trace levels are preserved
- JSON Formatting: Objects are automatically stringified for better readability
Use Cases
- Debugging Widget Issues: See all console logs in one place
- Development Workflow: Use browser DevTools features (filtering, searching)
- Error Tracking: Easier to spot errors and warnings
Widget State Inspection
The inspector provides built-in widget state inspection capabilities through theWidgetInspectorControls component.
Viewing Widget State
When a widget is rendered in the inspector, you can inspect:- Props: Current widget props from
toolInput - Output: Tool output data (
toolOutput) - Metadata: Response metadata (
toolResponseMetadata) - State: Persistent widget state (
widgetState) - Theme: Current theme (light/dark)
- Display Mode: Current display mode (inline/pip/fullscreen)
- Safe Area: Safe area insets for mobile
- User Agent: Device capabilities
- Locale: User locale
Debug Information Display
The inspector automatically displays debug information when widgets useMcpUseProvider with debugger={true} or when using WidgetControls component. This provides:
- Real-time state updates
- Interactive tool testing
- State modification capabilities
- Full widget context visibility
State Inspection API
Widgets can respond to state inspection requests:Events
openai:set_globals
Custom event dispatched when any global property changes. React components can listen to this for reactive updates.
- Initial widget load
- Display mode changes
- Theme changes
- Any global property update from parent
React Helper Hooks
The inspector’s API emulation is compatible with React hooks that useuseSyncExternalStore to subscribe to global changes. Here’s an example pattern:
Implementation Details
API Injection
Thewindow.openai API is injected into widget iframes via server-side HTML generation:
- Widget HTML is fetched from MCP server
- Inspector injects API script before widget content
- API object is attached to
window.openaiandwindow.webplus(for compatibility) - Initial globals event is dispatched
- Message listeners are set up for parent communication
Communication Protocol
Widget-to-inspector communication usespostMessage:
Widget → Inspector:
openai:callTool- Tool execution requestsopenai:sendFollowup- Follow-up messagesopenai:requestDisplayMode- Display mode changesopenai:setWidgetState- State updates
openai:callTool:response- Tool call resultsopenai:globalsChanged- Global property updatesopenai:displayModeChanged- Display mode changes (legacy)
State Persistence
Widget state is persisted in browser localStorage:- Key format:
mcp-inspector-widget-state-${toolId} - Storage: Browser localStorage (scoped to inspector domain)
- Lifetime: Persists across page reloads
- Scope: Per widget instance
Tool Result Formatting
MCP tool results are automatically converted to OpenAI’s expected format: MCP Format:Compatibility
The inspector maintains compatibility with:- OpenAI Apps SDK: Full API compatibility
- Legacy APIs:
sendFollowupTurn(aliased tosendFollowUpMessage) - React Router: URL normalization for routing
- Multiple display modes: Inline, PiP, Fullscreen
Differences from ChatGPT
While the inspector provides full API compatibility, there are some differences:- User Agent: Inspector provides mock user agent data
- Safe Area: Defaults to zero insets (not mobile-specific)
- Locale: Defaults to “en-US” (not user-specific)
- Tool Results: Converted from MCP format to OpenAI format
- Follow-ups: Appear in inspector Chat tab instead of ChatGPT
Testing Your Widget
To test widget compatibility:- Develop locally with inspector
- Test all API methods in your widget
- Verify state persistence across interactions
- Test display mode transitions
- Verify tool calls work correctly
- Check theme adaptation
- Test in ChatGPT for final verification
Official Documentation
For the complete OpenAI Apps SDK API reference, see:- OpenAI Apps SDK - Build a custom UX - Official API documentation
- OpenAI Apps SDK Reference - Complete API reference
Connecting Your ChatGPT App
Setting Up Your MCP Server
Your ChatGPT App needs an MCP server that exposes tools and optionally widgets:Connecting via Inspector
- Start your MCP server
- Open the inspector (local or hosted)
- Connect to your server URL:
- Local:
http://localhost:3000/mcp - Remote:
https://your-server.com/mcp
- Local:
- Server appears in Connected Servers list
Authentication Setup
If your ChatGPT App requires authentication:- Configure OAuth in connection settings
- Or add custom headers with API keys
- Complete authentication flow
- Inspector stores credentials securely
Testing Tools
Executing Tools
Test your ChatGPT App tools directly:- Navigate to Tools tab
- Find your tool in the list
- Click to select it
- Enter test parameters
- Click Execute
- View results in real-time
Viewing Tool Results
Tool results show:- Text Output: Plain text responses
- Structured Data: JSON responses
- Widget References: Links to OpenAI Apps SDK widgets
- Metadata: Tool execution metadata
Testing with Different Parameters
Test edge cases and variations:- Execute tool with different parameters
- Save successful requests for replay
- Test error handling
- Verify parameter validation
Use saved requests to quickly test the same tool with different parameters.
Widget/Component Testing
OpenAI Apps SDK Widget Support
The inspector fully supports OpenAI Apps SDK widgets:- Widget Rendering: Interactive widget display
- Dev Mode: Hot reload during development
- Display Modes: Inline, Picture-in-Picture, Fullscreen
- CSP Handling: Content Security Policy support
Rendering Widgets
When a tool returns a widget reference:- Tool executes successfully
- Inspector detects widget URI in metadata
- Widget automatically loads and renders
- Interactive components become available
- Looks for
openai/outputTemplatein tool metadata - Fetches widget resource from MCP server
- Renders in dedicated widget container
Widget Lifecycle Testing
Widgets render before tool execution completes, allowing them to show loading states. The mcp-use Inspector properly emulates this lifecycle:- Tool Called → Widget iframe created immediately
- Widget Renders →
isPending=true, shows loading state - Tool Completes → Widget receives result via
window.openaiupdates - Widget Updates →
isPending=false, shows data
- Use a tool that takes >2 seconds to complete
- Widget should show loading state immediately (not after tool completes)
- Open browser DevTools console
- Look for logs showing
isPending: truethenisPending: false - Verify widget transitions from loading UI to data display
isPending behavior and implementation patterns.
Dev Mode for Widgets
Enable hot reload for widget development:- Set widget metadata with dev flag:
- Inspector uses dev server URL
- Changes reload automatically
- Console logs visible in inspector
Widget Display Modes
Widgets support three display modes: Inline:- Default mode
- Embedded in result panel
- Scrollable content
- Floating window
- Stays visible while scrolling
- Resizable and draggable
- Full browser window
- Maximum visibility
- Exit with ESC or close button
- Widget can request mode changes
- Inspector handles transitions
- State persists during session
Widget CSP Handling
Content Security Policy is automatically handled:- CSP metadata from tool results
- Applied to widget iframe
- Secure sandbox environment
- Script execution allowed
Interactive Widget Features
Tool Calls from Widgets
Widgets can call MCP tools:- Widget uses
window.openai.callTool() - Inspector intercepts the call
- Executes tool via MCP connection
- Returns result to widget
- Widget updates with response
Follow-up Messages
Widgets can send follow-up messages to ChatGPT:- Widget calls
window.openai.sendFollowup() - Inspector captures the message
- Message appears in Chat tab
- ChatGPT processes the follow-up
- Conversation continues
- User interactions in widget
- Dynamic conversation flow
- Context-aware responses
Widget State Management
Widget state is managed automatically:- Tool Input: Parameters passed to tool
- Tool Output: Results from tool execution
- Widget Data: Resource content for widget
- Display State: Current display mode
Console Logging from Widgets
View widget console output:- Widget console logs appear in inspector
- Access via console panel in widget container
- Filter by log level
- Debug widget issues
- Real-time log streaming
- Log level filtering
- Error highlighting
- Stack trace display
Debugging Workflow
Step-by-Step Process
-
Connect to Server
- Add your MCP server in inspector
- Verify connection status
-
Test Tools
- Execute each tool independently
- Verify parameters and responses
- Check for errors
-
Test Widgets
- Execute tools that return widgets
- Verify widget rendering
- Use Protocol Toggle to test both protocols (if dual-protocol)
- Test widget interactions and tool calls
- Test different display modes (inline, PiP, fullscreen)
-
Test Device Compatibility
- Use Device Emulation (Desktop/Mobile/Tablet)
- Test different locales and timezones
- Verify CSP compliance (Widget-Declared mode)
- Test touch and hover capabilities
-
Test Integration
- Use Chat tab with LLM
- Verify tool calls from AI
- Check widget rendering in context
-
Debug Issues
- Check console logs
- Review tool results
- Verify widget metadata
- Test error scenarios
Common Issues and Solutions
Widget Not Rendering:- MCP Apps: Check
_meta.ui.resourceUrior_meta["ui/resourceUri"]in metadata - ChatGPT: Check
openai/outputTemplatein metadata - Verify widget resource exists at the specified path
- Check CSP settings match widget’s network requirements
- Use Protocol Toggle to test if it works in the other protocol
- Review console for errors
- Verify tool name matches
- Check parameter schema
- Review authentication
- Check server logs
- ChatGPT: Verify
window.openaiAPI availability in widget - MCP Apps: Check JSON-RPC postMessage communication
- Check widget iframe sandbox permissions
- Review console for errors
- Test in different display modes
- Try switching protocols with Protocol Toggle
Testing Widget Interactions
- Render Widget: Execute tool to load widget
- Interact: Click buttons, fill forms in widget
- Monitor: Watch console for tool calls
- Verify: Check tool results and widget updates
- Iterate: Fix issues and retest
Verifying Tool Outputs
- Preview Mode: See formatted widget output
- JSON Mode: View raw tool response
- Metadata: Check widget references
- Structure: Verify data format
Best Practices
Development vs Production Widgets
Development:- Use dev mode for hot reload
- Enable console logging and verbose debugging
- Use Permissive CSP mode for easier debugging
- Test in all display modes and device types
- Test both protocols (MCP Apps and ChatGPT)
- Verify error handling and fallbacks
- Disable dev mode
- Use Widget-Declared CSP mode to catch violations
- Minimize console output
- Test with production CSP restrictions
- Verify performance across device types
- Test internationalization with different locales
Testing Widget Responsiveness
- Test in different display modes (inline, PiP, fullscreen)
- Use Device Emulation to test Desktop/Mobile/Tablet
- Verify mobile layouts with safe area insets
- Check resize behavior and auto-resize (MCP Apps)
- Test PiP mode transitions
- Test with different locales and timezones
Handling Widget Errors
- Implement error boundaries
- Show user-friendly messages
- Log errors to console
- Provide fallback UI
Performance Considerations
- Optimize widget loading
- Minimize initial bundle size
- Lazy load components
- Cache widget resources
Next Steps
- MCP Apps - Build widgets with the standard MCP protocol
- ChatGPT Apps SDK - Build ChatGPT-specific widgets
- Widget Components - React hooks and components
- Inspector Overview - Inspector features and usage
- Connection Settings - Advanced inspector configuration