A SvelteKit library for building Model Context Protocol (MCP) servers with reactive Svelte widgets for ChatGPT.
This library provides three integrated parts that work together:
.mcp.svelte files into standalone widget bundlesgraph TD
A[.mcp.svelte files] --> B[Vite Plugin]
B --> C[Standalone JS bundles<br/>static/widgets/*.js]
B --> D[Auto-generates<br/>src/mcp/widgets.ts]
D --> E[MCP Handler]
C --> G
E --> F[Serves to ChatGPT<br/>as widget:// resources]
F --> G[ChatGPT loads bundle]
G --> H[Widget auto-mounts<br/>& renders]
H --> I[useOpenAI hook<br/>accesses context]
Compiles .mcp.svelte files into self-contained JavaScript bundles with inlined CSS.
What it does:
.mcp.svelte files in your projectstatic/widgets/src/mcp/widgets.ts with widget definitions that you can customize if necessarySetup:
// vite.config.ts
import { mcpSveltePlugin } from 'chat-app-kit/vite';
export default defineConfig({
plugins: [mcpSveltePlugin({ outputDir: 'widgets' })]
});
Reactive Svelte 5 runes API for accessing ChatGPT state inside .mcp.svelte components.
What it provides:
useOpenAI() - Hook to access ChatGPT contextrequestDisplayMode(), openExternal(), callTool(), sendFollowUpMessage()Usage:
<script lang="ts">
import { useOpenAI } from 'chat-app-kit/api';
const openai = useOpenAI({ widgetState: { count: 0 } });
// Reactive access to ChatGPT state
$effect(() => console.log(openai.theme)); // 'light' | 'dark'
// State persists automatically
openai.widgetState.count++;
</script>
<button onclick={() => openai.requestDisplayMode('fullscreen')}>
Expand
</button>
SvelteKit server hook that implements the Model Context Protocol to serve widgets, tools, resources, and prompts.
What it does:
widget:// URIs).widget() method/mcp endpoint)Setup:
// src/hooks.server.ts
import { handleMCP, tool } from 'chat-app-kit/mcp';
import * as widgets from './mcp/widgets'; // Auto-generated
import { z } from 'zod';
export const handle = handleMCP({
name: 'my-app',
version: '1.0.0',
domain: 'https://my-app.example.com',
widgets, // Automatically registers all compiled widgets
tools: {
greet: tool('Greet a user')
.input(z.object({ name: z.string() }))
.widget(widgets.greetingWidget) // Links tool to widget
.handle(async ({ input }) => `Hello ${input.name}`)
},
resources: {},
prompts: {}
});
Greeting.mcp.svelte → widgets/greeting.jswidgets.ts with export const greetingWidget = widget('greeting', {...})greetingWidget as resource at widget://greeting.js.widget(greetingWidget) adding metadatauseOpenAI() to access Context API → widget renders.mcp.svelte files reload instantly in dev mode