Skip to content

Make vite work out-of-the-box for simple-host - #33

Merged
ochafik merged 1 commit into
modelcontextprotocol:mainfrom
hybrist:simpler-simple-host
Dec 1, 2025
Merged

Make vite work out-of-the-box for simple-host#33
ochafik merged 1 commit into
modelcontextprotocol:mainfrom
hybrist:simpler-simple-host

Conversation

@hybrist

@hybrist hybrist commented Nov 26, 2025

Copy link
Copy Markdown
Contributor

This removes some of the workarounds to make the sandboxing work to allow for a more straight-forward vite dev experience when looking at the host.

Downside: It no longer inlines the sandbox script in sandbox.html for the output. But that seems less relevant for the host than it is for the tool UIs. It's likely possible to bring that back but for a simple demo it might be fine to leave as is?

@hybrist
hybrist force-pushed the simpler-simple-host branch from fde9bf2 to 643fd8f Compare November 26, 2025 17:50

@ochafik ochafik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @hybrist, thanks for this, looks neater, but I wonder if there's a way to keep serving CSP dynamically?

Ideally would need to show how to pass down the various CSP settings defined in the resource's _meta.ui.csp and the only safe way to do so is as query params on the sandbox GET handler so they're returned as http headers.

I was incubating the following change for serve.ts:

// CSP for sandbox content, with customizable script-src and connect-src via query params
sandboxApp.get(["/", "/sandbox.html"], (req, res) => {
  // Allow customizing script-src and connect-src via query params
  const scriptSrc = req.query["script-src"] as string | undefined;
  const connectSrc = req.query["connect-src"] as string | undefined;

  // Build CSP with defaults, allowing query param overrides
  const csp = [
    "default-src 'self'",
    "img-src * data: blob: 'unsafe-inline'",
    "style-src * blob: data: 'unsafe-inline'",
    `script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval' blob: data:${scriptSrc ? ` ${scriptSrc}` : ""}`,
    `connect-src 'self'${connectSrc ? ` ${connectSrc}` : " 'self'"}`,
    "font-src * blob: data:",
    "media-src * blob: data:",
    `frame-src 'self' blob: data:`,
    "base-uri 'self'",
  ].join("; ");

  res.setHeader("Content-Security-Policy", csp);
  res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
  res.setHeader("Pragma", "no-cache");
  res.setHeader("Expires", "0");
  res.sendFile(join(DIRECTORY, "sandbox.html"));
});

ochafik added a commit that referenced this pull request Dec 1, 2025
Replace dual-server Express setup with Vite-only approach:
- Add vite-plugin-sandbox-csp for dynamic CSP headers via query params
  (supports script-src and connect-src customization for _meta.ui.csp)
- Use [::1] vs localhost for cross-origin sandbox isolation
- Simplify package.json scripts (dev, start, preview, build)
- Remove serve.ts, express, cors, concurrently, bun deps
- Add index.html redirect to example-host-react.html

Based on PR #33 approach but preserves dynamic CSP header capability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

@ochafik ochafik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a way to do the CSP as a vite plugin, will merge this PR then introduce the csp stuff.

@ochafik
ochafik merged commit a7d73c7 into modelcontextprotocol:main Dec 1, 2025
1 check failed
@hybrist

hybrist commented Dec 1, 2025

Copy link
Copy Markdown
Contributor Author

Thanks! Sorry for the lack of follow-up. I think there's also some neat opportunity to leverage vite environments for the widget setup. But I still have to try it out to see if it makes things easier or just more convoluted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants