Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/contributing/mcp-apps-architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,21 @@ Stores widget data for later retrieval by the iframe.

Fetches widget HTML from MCP resource and injects the client script.

**SEP-1865 MIME type validation**: This endpoint validates that the resource has the correct MIME type (`text/html;profile=mcp-app`). If the MIME type is missing or incorrect, the endpoint returns a warning in the response:

```typescript
{
html: string,
csp: string,
permissive: boolean,
mimeType: string | undefined,
mimeTypeValid: boolean,
mimeTypeWarning: string | null
}
```

The warning is displayed in the widget footer to help developers identify MIME type issues during development.

### GET /api/mcp/sandbox-proxy

Serves the sandbox proxy HTML that creates the double-iframe architecture.
Expand Down
81 changes: 77 additions & 4 deletions docs/contributing/playground-architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1000,13 +1000,14 @@ body: JSON.stringify({

- `client/src/components/ChatTabV2.tsx` - Main chat UI with resizable layout
- `client/src/components/ChatTab.tsx` - Legacy single-panel layout
- `client/src/components/logging/json-rpc-logger-view.tsx` - MCP protocol viewer
- `client/src/components/logging/json-rpc-logger-view.tsx` - MCP protocol viewer (renamed from `logger-view.tsx` in PR #1050)
- `client/src/components/ui/resizable.tsx` - Resizable panel components
- `client/src/hooks/use-chat.ts` - Chat state management
- `client/src/components/chat/message.tsx` - Message rendering
- `client/src/components/chat/chat-input.tsx` - Input component
- `client/src/components/ElicitationDialog.tsx` - Elicitation UI
- `client/src/lib/sse.ts` - SSE parsing utilities
- `client/src/stores/traffic-log-store.ts` - Unified traffic logging (replaces `ui-log-store.ts` in PR #1050)

### Backend

Expand Down Expand Up @@ -1266,7 +1267,7 @@ The UI Playground is a specialized testing environment for ChatGPT Apps and MCP

Located in `client/src/components/ui-playground/PlaygroundMain.tsx`, the playground header includes:

**Device Selector** - Toggle between mobile (430×932), tablet (820×1180), and desktop (1280×800) viewports to test responsive layouts.
**Device Selector** - Toggle between mobile (430×932), tablet (820×1180), desktop (1280×800), and custom viewports to test responsive layouts. Custom viewports allow you to specify exact width and height dimensions (100-2560px) which are persisted across sessions. The playground automatically switches to compact mode for narrow custom viewports (width < 500px).

**Locale Selector** - Choose from common BCP 47 locales for internationalization testing:

Expand Down Expand Up @@ -1342,10 +1343,10 @@ The debug UI uses local state to track which panel is active:

```typescript
const [activeDebugTab, setActiveDebugTab] = useState<
"data" | "state" | "globals" | null
"data" | "state" | "csp" | null
>(null);

const handleDebugClick = (tab: "data" | "state" | "globals") => {
const handleDebugClick = (tab: "data" | "state" | "csp") => {
if (activeDebugTab === tab) {
// Clicking active tab closes panel
setActiveDebugTab(null);
Expand All @@ -1359,6 +1360,78 @@ const handleDebugClick = (tab: "data" | "state" | "globals") => {

This provides a cleaner UX compared to the previous tabs-based approach, reducing visual clutter and improving mobile responsiveness.

### Display Mode and Debug Controls

As of PR #1050, the display mode controls and debug buttons are merged into a single toolbar in the thread header. The display mode selector appears as a dropdown menu (only in UI Playground), while debug buttons (Data, State, CSP) remain as icon buttons. This consolidation reduces visual clutter and provides a more compact interface, especially useful for narrow viewports.

### Keyboard Shortcuts and Chat Reset

**Clear Chat Shortcut** (`Cmd/Ctrl+Shift+K`): Added in PR #1050, this keyboard shortcut provides quick access to clear the conversation thread.

```typescript
// client/src/components/ui-playground/PlaygroundMain.tsx
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (
(e.metaKey || e.ctrlKey) &&
e.shiftKey &&
e.key.toLowerCase() === "k"
) {
e.preventDefault();
if (!isThreadEmpty) {
setShowClearConfirm(true);
}
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [isThreadEmpty]);
```

**Chat Reset Confirmation**: The confirmation dialog includes a "Don't show this again" checkbox that saves the preference to localStorage (`skipChatResetConfirmation` key). When enabled, future clear operations execute immediately without confirmation. The dialog also auto-confirms if the preference is already set, providing a seamless UX for users who prefer to skip confirmations.

**Log Clearing**: When chat is reset, the traffic log store is also cleared to provide a clean debugging state. This unified clearing behavior ensures that both conversation history and debug logs are synchronized.

## Unified Traffic Logging

As of PR #1050, the playground uses a unified traffic logging system (`traffic-log-store.ts`) that captures both UI Apps traffic and MCP Server RPC traffic in a single store. This replaces the previous `ui-log-store.ts` which only tracked UI Apps messages.

### Traffic Log Store

The store maintains two separate arrays for different traffic sources:

```typescript
interface TrafficLogState {
items: UiLogEvent[]; // UI Apps traffic (ChatGPT Apps, MCP Apps)
mcpServerItems: McpServerRpcItem[]; // MCP Server RPC traffic
addLog: (event: Omit<UiLogEvent, "id" | "timestamp">) => void;
addMcpServerLog: (item: Omit<McpServerRpcItem, "id">) => void;
clear: () => void;
}
```

**UI Apps Traffic** (`UiLogEvent`):
- Captures postMessage communication between host and widget iframes
- Includes protocol (OpenAI Apps SDK or MCP Apps), direction, method, and message payload
- Logged by `ChatGPTAppRenderer` and `MCPAppsRenderer` components

**MCP Server RPC Traffic** (`McpServerRpcItem`):
- Captures JSON-RPC messages between Inspector and MCP servers
- Includes serverId, direction (IN/OUT), method, and payload
- Streamed from backend via Server-Sent Events to `LoggerView`

### Logger View Integration

The `LoggerView` component (`client/src/components/logging/logger-view.tsx`) consumes both traffic sources:

1. **Server RPC Streaming**: Connects to `/api/mcp/rpc-stream` endpoint and receives real-time JSON-RPC messages
2. **UI Apps Logs**: Subscribes to `traffic-log-store` for UI Apps traffic
3. **Unified Display**: Combines and sorts all traffic by timestamp (newest first)
4. **Source Filtering**: Users can filter by traffic source (MCP Server, ChatGPT Apps, MCP Apps)
5. **Actions**: Clear all logs, copy logs to clipboard

This unified approach provides a complete view of all MCP-related traffic in a single interface, making it easier to debug complex interactions between the LLM, MCP servers, and custom UI widgets.

## Related Documentation

- [MCPClientManager](./mcp-client-manager) - MCP orchestration layer
Expand Down
7 changes: 6 additions & 1 deletion docs/inspector/debugging.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ MCPJam Inspector provides powerful debugging and monitoring capabilities to help

## Logs

View all messages being sent back and forth between MCPJam and your MCP server. We're working on building support to view all JSON-RPC messages. Tracing message levels are `ERROR`, `WARNING`, and `TRACE`.
View all messages being sent back and forth between MCPJam and your MCP server. The logger captures two types of traffic:

- **MCP Server RPC**: JSON-RPC messages between Inspector and your MCP servers (via STDIO/HTTP/SSE transports)
- **UI Apps Traffic**: Messages between the host and custom UI widgets (ChatGPT Apps and MCP Apps)

You can filter logs by source, clear all logs, or copy logs to clipboard. The logger streams server RPC traffic in real-time and displays up to 1000 recent messages. Tracing message levels are `ERROR`, `WARNING`, and `TRACE`.

## Widget debugging

Expand Down
21 changes: 16 additions & 5 deletions docs/inspector/llm-playground.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ You can resize the panels by dragging the divider between them. This layout help

When errors occur during playground interactions, you'll see an error message with a "Reset chat" button. For detailed debugging, click "More details" to expand additional error information, including JSON-formatted error responses when available. This helps you quickly identify and resolve issues with your MCP server or LLM configuration.

### Clearing chat

You can clear the chat conversation using:
- The "Clear chat" button in the toolbar
- Keyboard shortcut: `Cmd+Shift+K` (Mac) or `Ctrl+Shift+K` (Windows/Linux)

When clearing chat, you'll see a confirmation dialog. Check "Don't show this again" to skip future confirmations and clear immediately. This preference is saved locally and can be reset by clearing your browser's localStorage.

## Elicitation support

MCPJam has elicitation support in the LLM playground. Any elicitation requests will be shown as a popup modal.
Expand Down Expand Up @@ -195,7 +203,7 @@ OpenAI Apps can request different display modes to optimize their presentation:
- **Picture-in-Picture** - Widget floats at the top of the screen, staying visible while you scroll through the chat
- **Fullscreen** - Widget expands to fill the entire viewport for immersive experiences

Widgets can request display mode changes using `window.openai.requestDisplayMode({ mode: 'pip' })` or `window.openai.requestDisplayMode({ mode: 'fullscreen' })`. Users can exit PiP or fullscreen modes by clicking the close button in the top-left corner of the widget.
Widgets can request display mode changes using `window.openai.requestDisplayMode({ mode: 'pip' })` or `window.openai.requestDisplayMode({ mode: 'fullscreen' })`. Users can manually control display mode via the dropdown menu in the tool header (in the UI Playground). Exit PiP or fullscreen modes by clicking the close button in the top-left corner of the widget.

### Device and locale testing

Expand All @@ -209,13 +217,14 @@ These settings are automatically passed to widgets via the `window.openai` API,

### Widget debugging

When viewing tool results with custom UI components, you can access debugging information using the icon buttons in the tool header:
When viewing tool results with custom UI components, you can access debugging information using the controls in the tool header:

- **Display mode dropdown** - Switch between inline, picture-in-picture, and fullscreen modes (UI Playground only)
- **Data** (database icon) - View tool input, output, and error details
- **Widget State** (box icon) - Inspect the current widget state and see when it was last updated
- **Globals** (globe icon) - View global values passed to the widget (theme, display mode, locale, etc.)
- **CSP** (shield icon) - View Content Security Policy violations and suggested fixes (UI Playground only)

Click any icon to toggle the corresponding debug panel. Click again to close it.
Click any icon to toggle the corresponding debug panel. Click again to close it. The display mode and debug controls are grouped together in a single toolbar for compact access.

### Content Security Policy (CSP)

Expand Down Expand Up @@ -243,7 +252,9 @@ The UI Playground provides controls to simulate different device environments fo

### Device type

Select between mobile, tablet, or desktop device types. This affects the `window.openai.userAgent.device.type` value that widgets receive. The device type selector is located in the playground toolbar.
Select between mobile, tablet, desktop, or custom device types. This affects the `window.openai.userAgent.device.type` value that widgets receive. The device type selector is located in the playground toolbar.

**Custom device type**: When you select "Custom", you can specify exact width and height dimensions (100-2560px) for testing specific viewport sizes. Your custom dimensions are saved and persist across sessions. This is useful for testing specific device resolutions or edge cases not covered by the preset device types.

### Device capabilities

Expand Down