Skip to main content

Documentation Index

Fetch the complete documentation index at: https://sunpeak.ai/docs/llms.txt

Use this file to discover all available pages before exploring further.

Blank page in the inspector

If the inspector loads but the resource iframe is blank:
  1. Check the browser console for errors (especially CSP or CORS issues)
  2. Make sure your resource component is the default export from src/resources/{name}/{name}.tsx
  3. Verify you have at least one simulation in tests/simulations/ that references your tool
For standalone usage (sunpeak inspect --server), verify your MCP server is running and reachable at the URL you provided.

Stdio server fails to start

When a stdio MCP server fails to start, sunpeak captures and displays the server’s stderr output. This includes Python tracebacks, import errors, missing dependencies, and other startup failures. Check the error message for the specific cause. Common fixes:
  • Python ModuleNotFoundError: Install missing dependencies or set PYTHONPATH via the env option in your config or --env on the CLI.
  • Wrong working directory: Set cwd in your config or --cwd on the CLI so the server resolves relative imports correctly.
  • Missing environment variables: Pass them with server.env in defineConfig() or --env KEY=VALUE on the CLI.
// Example: fixing a Python server that needs a specific working directory and env
export default defineConfig({
  server: {
    command: 'python', args: ['server.py'],
    cwd: './backend',
    env: { PYTHONPATH: './src' },
  },
});

Tests failing with iframe errors

E2E tests must use the double-iframe locator pattern because resource content renders inside a nested sandbox:
// Wrong - this looks at the inspector chrome, not the app
page.locator('.my-element')

// Correct - drill through both iframe layers
page.frameLocator('iframe').frameLocator('iframe').locator('.my-element')
When using the inspector fixture from sunpeak/test, result.app() returns a locator already scoped to the inner iframe, so you don’t need to chain frameLocator manually:
const result = await inspector.renderTool('show-albums');
const app = result.app();
await expect(app.locator('.my-element')).toBeVisible();
See the Inspector architecture for details on the double-iframe sandbox.

MCP server requires authentication (OAuth)

sunpeak auto-negotiates OAuth when connecting to MCP servers that require it. If your server returns a 401 response, sunpeak will:
  1. Discover the server’s OAuth metadata
  2. Register a client dynamically
  3. Complete the authorization flow
For servers with auto-approved (anonymous) OAuth, this happens automatically with no user interaction. For servers that require interactive login, sunpeak opens the authorization URL in your browser and waits for the callback. If OAuth negotiation fails, check that your server’s OAuth endpoints are accessible and return standard MCP OAuth responses (/.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server).

Server startup timeout

If your MCP server takes a long time to start (compiling, loading large models, etc.), you may see a timeout error. Increase the startup timeout in your config:
export default defineConfig({
  server: { command: 'python', args: ['server.py'] },
  timeout: 120_000, // 120 seconds (default: 60000)
});

Flaky E2E tests

The double-iframe sandbox proxy can be overwhelmed by too many concurrent Playwright workers. If you see PostMessage relay timeouts or intermittent failures:
  • Limit workers to 2 locally (workers: 2 in your Playwright config)
  • In CI, use 1 worker (workers: process.env.CI ? 1 : 2)
The defineConfig() from sunpeak/test/config sets these defaults automatically.

Live test authentication

On first run, a browser window opens for you to log in to ChatGPT. The session is saved to .auth/chatgpt.json but typically only lasts a few hours because Cloudflare’s cf_clearance cookie is HttpOnly and cannot be persisted across runs. When you see this error, just re-authenticate in the browser window that opens. If it keeps failing, delete the .auth/ directory and run pnpm test:live again.
Verify your tunnel is running and the URL is correct. The test checks the tunnel’s /health endpoint before proceeding.
ChatGPT occasionally updates their UI. The ChatGPTPage class checks selector health at startup. If selectors are stale, update the SELECTORS constant in chatgpt-page.mjs.
Live tests use specific prompts like “Use the show-albums tool to…” to reliably trigger tool calls. If a tool isn’t called, the test retries once. Persistent failures may indicate the tool isn’t properly connected — check ChatGPT settings.
For dev server, tunnel, and build-related troubleshooting, see App Framework Troubleshooting.