Skip to main content

Community Example

Full-stack Nuxt 3 with SSR support by Mike Chao
Nuxt’s SSR requires ensuring WebMCP code only runs on the client.

Client-Only Plugin

Create a plugin that initializes WebMCP on the client:
import '@mcp-b/global';

export default defineNuxtPlugin(() => {
  // .client.ts suffix ensures this only runs in browser
});

Basic Usage

Use import.meta.client to guard registration:
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';

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

if (import.meta.client) {
  onMounted(() => {
    reg = navigator.modelContext.registerTool({
      name: 'get_page',
      description: 'Get current page info',
      inputSchema: { type: 'object', properties: {} },
      async execute() {
        return { content: [{ type: 'text', text: window.location.pathname }] };
      }
    });
  });

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

With Server Data

<script setup lang="ts">
const route = useRoute();
const { data: product } = await useFetch(`/api/products/${route.params.id}`);

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

if (import.meta.client) {
  onMounted(() => {
    reg = navigator.modelContext.registerTool({
      name: 'get_product',
      description: 'Get current product details',
      inputSchema: { type: 'object', properties: {} },
      async execute() {
        if (!product.value) return { content: [{ type: 'text', text: 'No product' }] };
        return { content: [{ type: 'text', text: JSON.stringify(product.value) }] };
      }
    });
  });

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

ClientOnly Wrapper

For client-only components:
<template>
  <ClientOnly>
    <ToolRegistrationComponent />
  </ClientOnly>
  <NuxtPage />
</template>

Common Gotchas

Register tools in app.vue or a layout so they persist across routes.

Development

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