Skip to main content

Full Example

Production-ready Svelte example with runes and actions

Quick start

git clone https://github.com/WebMCP-org/examples.git
cd examples/svelte && pnpm install && pnpm dev

The pattern

Use onMount/onDestroy for lifecycle management:
<script lang="ts">
  import { onMount, onDestroy } from 'svelte';
  import '@mcp-b/global';

  let count = $state(0);
  let reg: { unregister: () => void } | null = null;

  onMount(() => {
    reg = navigator.modelContext.registerTool({
      name: 'increment',
      description: 'Increment the counter',
      inputSchema: {
        type: 'object',
        properties: { amount: { type: 'number' } }
      },
      async execute({ amount = 1 }) {
        count += amount as number;
        return { content: [{ type: 'text', text: `Count: ${count}` }] };
      }
    });
  });

  onDestroy(() => reg?.unregister());
</script>

<p>Count: {count}</p>

SvelteKit SSR

Add the browser check to avoid SSR errors:
<script lang="ts">
  import { browser } from '$app/environment';
  import { onMount, onDestroy } from 'svelte';
  import '@mcp-b/global';

  let reg: { unregister: () => void } | null = null;

  onMount(() => {
    if (!browser) return;
    reg = navigator.modelContext.registerTool({ /* ... */ });
  });

  onDestroy(() => reg?.unregister());
</script>

Using actions

Svelte actions encapsulate tool registration cleanly:
import '@mcp-b/global';

export function webmcp(node: HTMLElement, tool: Parameters<typeof navigator.modelContext.registerTool>[0]) {
  const reg = navigator.modelContext.registerTool(tool);
  return { destroy: () => reg.unregister() };
}
<div use:webmcp={{ name: 'my_tool', description: 'My tool', ... }}>
  Content
</div>

Common issues

Move registration to +layout.svelte for persistence across routes.

Development

Use Chrome DevTools MCP for AI-driven development - your AI can write, discover, and test tools in real-time.