Skip to main content
Prompts, resources, sampling, and elicitation are MCP-B extension features, not part of the strict WebMCP core. They require @mcp-b/global (which installs BrowserMcpServer as navigator.modelContext). For background on this distinction, see Strict Core vs MCP-B Extensions.

Register a prompt

A prompt is a reusable message template that AI clients can discover and invoke with arguments.
1

Import @mcp-b/global

import '@mcp-b/global';
2

Register the prompt

const { unregister } = navigator.modelContext.registerPrompt({
  name: 'greeting',
  description: 'Generate a greeting message',
  argsSchema: {
    type: 'object',
    properties: {
      name: { type: 'string', description: 'Name to greet' }
    },
    required: ['name']
  },
  get: async ({ name }) => ({
    messages: [
      { role: 'user', content: { type: 'text', text: `Hello, ${name}!` } }
    ]
  })
});
3

Unregister when done

unregister();

React

Use the useWebMCPPrompt hook from @mcp-b/react-webmcp. It handles registration and cleanup on unmount.
import { useWebMCPPrompt } from '@mcp-b/react-webmcp';

function CodeReviewPrompt() {
  const { isRegistered } = useWebMCPPrompt({
    name: 'review_code',
    description: 'Review code for best practices',
    argsSchema: {
      type: 'object',
      properties: {
        code: { type: 'string', description: 'The code to review' },
        language: { type: 'string', description: 'Programming language' },
      },
      required: ['code'],
    } as const,
    get: async ({ code, language }) => ({
      messages: [{
        role: 'user',
        content: {
          type: 'text',
          text: `Please review this ${language ?? ''} code:\n\n${code}`
        }
      }]
    }),
  });

  return <div>Code review prompt {isRegistered ? 'ready' : 'loading'}</div>;
}

Register a resource

A resource exposes readable data (configuration, documents, state) to AI clients.
1

Import @mcp-b/global

import '@mcp-b/global';
2

Register the resource

const { unregister } = navigator.modelContext.registerResource({
  uri: 'app://config',
  name: 'App Configuration',
  description: 'Current application configuration',
  mimeType: 'application/json',
  read: async () => ({
    contents: [{ uri: 'app://config', text: JSON.stringify(appConfig) }]
  })
});
3

Unregister when done

unregister();

React

Use the useWebMCPResource hook from @mcp-b/react-webmcp.
import { useWebMCPResource } from '@mcp-b/react-webmcp';

function AppSettingsResource() {
  const { isRegistered } = useWebMCPResource({
    uri: 'config://app-settings',
    name: 'App Settings',
    description: 'Application configuration',
    mimeType: 'application/json',
    read: async (uri) => ({
      contents: [{
        uri: uri.href,
        text: JSON.stringify({ theme: 'dark', language: 'en' })
      }]
    }),
  });

  return <div>Settings resource {isRegistered ? 'ready' : 'loading'}</div>;
}

Use sampling and elicitation

Sampling lets your page request LLM completions from the connected client. Elicitation lets your page request structured input from the user through the client. Both methods delegate to the MCP SDK and require an active transport connection. See the @mcp-b/webmcp-ts-sdk reference for parameter and return type details.

React

@mcp-b/react-webmcp provides useSampling and useElicitation hooks that manage loading state, errors, and request counts.
import { useSampling } from '@mcp-b/react-webmcp';

function AIAssistant() {
  const { state, createMessage } = useSampling();

  const handleAsk = async () => {
    const result = await createMessage({
      messages: [
        { role: 'user', content: { type: 'text', text: 'Summarize this page.' } }
      ],
      maxTokens: 200,
    });
    console.log(result.content);
  };

  return (
    <button onClick={handleAsk} disabled={state.isLoading}>
      Ask AI
    </button>
  );
}