From 051a68803333c29a926ec0805c7c0b2eaa16fbf6 Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Thu, 5 Mar 2026 16:09:09 -0500 Subject: [PATCH 1/2] add agent skills for webmcp-react setup and tool scaffolding Add two agent skills installable via `npx skills add MCPCat/webmcp-react`: - webmcp-setup: bootstraps webmcp-react into a React or Next.js app - webmcp-add-tool: scaffolds new MCP tool components with Zod schemas Also add a callout in the README pointing users to the skills CLI. Made-with: Cursor --- README.md | 10 ++ skills/webmcp-add-tool/SKILL.md | 213 ++++++++++++++++++++++++++++++++ skills/webmcp-setup/SKILL.md | 167 +++++++++++++++++++++++++ 3 files changed, 390 insertions(+) create mode 100644 skills/webmcp-add-tool/SKILL.md create mode 100644 skills/webmcp-setup/SKILL.md diff --git a/README.md b/README.md index d65df32..3a607c6 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,16 @@ export default function App() { That's it. The tool is registered on `navigator.modelContext` and can be called by WebMCP-compatible agents. +### Using an AI agent? + +This repo ships with [agent skills](./skills) that can set up webmcp-react and scaffold tools for you. Install them with the [skills CLI](https://skills.sh): + +```bash +npx skills add MCPCat/webmcp-react +``` + +Works with Cursor, Claude Code, GitHub Copilot, Cline, and [18+ other agents](https://vercel.com/docs/agent-resources/skills). + ## How it works [WebMCP](https://www.w3.org/community/webmcp/) is an emerging web standard that adds `navigator.modelContext` to the browser, an API that lets any page expose typed, callable tools to AI agents. Native browser support is still experimental and may evolve quickly. Chrome recently [released it in Early Preview](https://developer.chrome.com/blog/webmcp-epp). diff --git a/skills/webmcp-add-tool/SKILL.md b/skills/webmcp-add-tool/SKILL.md new file mode 100644 index 0000000..0a81999 --- /dev/null +++ b/skills/webmcp-add-tool/SKILL.md @@ -0,0 +1,213 @@ +--- +name: webmcp-add-tool +description: Scaffolds a new WebMCP tool component using useMcpTool with Zod schema, handler, annotations, and wires it into the WebMCPProvider tree. Use when the user wants to expose functionality as an MCP tool, make something callable by AI, add a new tool, or create an AI-accessible action. +--- + +# Add a WebMCP Tool + +## Overview + +Each tool is a React component that calls `useMcpTool`. It registers on mount, unregisters on unmount. Tools can be headless (return `null`) or render UI showing execution state. + +## Workflow + +1. **Determine** the tool's name, description, input schema, and what the handler does +2. **Choose** headless vs UI tool +3. **Scaffold** using the appropriate template below +4. **Set annotations** based on tool behavior +5. **Wire** the component into the `` tree + +## Template: Headless tool + +For tools that do work without rendering anything visible: + +```tsx +import { useMcpTool } from "webmcp-react"; +import { z } from "zod"; + +export function MyTool() { + useMcpTool({ + name: "my_tool", + description: "One-line description of what this tool does", + input: z.object({ + // Define each input field with .describe() for AI context + query: z.string().describe("The search query"), + }), + handler: async ({ query }) => { + // Implement tool logic here + const result = await doSomething(query); + return { + content: [{ type: "text", text: JSON.stringify(result) }], + }; + }, + }); + return null; +} +``` + +## Template: Tool with execution state UI + +For tools that show loading, results, or errors: + +```tsx +import { useMcpTool } from "webmcp-react"; +import { z } from "zod"; + +export function MyTool() { + const { state, execute, reset } = useMcpTool({ + name: "my_tool", + description: "One-line description of what this tool does", + input: z.object({ + text: z.string().describe("Input text to process"), + }), + handler: async ({ text }) => { + const result = await process(text); + return { content: [{ type: "text", text: result }] }; + }, + onSuccess: (result) => { + // Optional: analytics, toast, etc. + }, + onError: (error) => { + // Optional: error reporting + }, + }); + + return ( +
+ + {state.lastResult &&

{state.lastResult.content[0].text}

} + {state.error &&

{state.error.message}

} + Executions: {state.executionCount} +
+ ); +} +``` + +## Annotations + +Set annotations to hint AI agents about tool behavior. Only include annotations that apply: + +```tsx +useMcpTool({ + // ... + annotations: { + title: "Human-friendly title", // Display name for the tool + readOnlyHint: true, // Tool only reads data, no side effects + destructiveHint: true, // Tool deletes or irreversibly modifies data + idempotentHint: true, // Safe to call multiple times with same input + openWorldHint: true, // Tool interacts with external systems + }, +}); +``` + +**Guideline for choosing annotations:** + +| Tool behavior | Annotations to set | +|---|---| +| Fetches/queries data | `readOnlyHint: true` | +| Creates a record | `idempotentHint: false` (or omit, false is default) | +| Deletes or overwrites data | `destructiveHint: true` | +| Calls an external API | `openWorldHint: true` | +| Can be retried safely | `idempotentHint: true` | + +## Return format + +Handlers must return `CallToolResult`: + +```tsx +// Text content (most common) +return { + content: [{ type: "text", text: "result string" }], +}; + +// Structured content (for machine-readable results alongside text) +return { + content: [{ type: "text", text: "Human summary" }], + structuredContent: { key: "value", count: 42 }, +}; + +// Error result (caught by the framework, but you can also return errors explicitly) +return { + content: [{ type: "text", text: "Something went wrong" }], + isError: true, +}; + +// Image content +return { + content: [{ type: "image", data: base64String, mimeType: "image/png" }], +}; +``` + +## Dynamic tools + +Tools register on mount and unregister on unmount. Use conditional rendering to dynamically control which tools are available: + +```tsx +function App({ user }) { + return ( + + + {user.isAdmin && } + {featureFlags.betaSearch && } + + ); +} +``` + +## Wiring into the provider + +Render the tool component anywhere inside ``. Common patterns: + +**Dedicated tools file** (recommended for apps with many tools): + +```tsx +// components/mcp-tools.tsx +export function McpTools() { + return ( + <> + + + + + ); +} + +// In app root: + + + + +``` + +**Colocated with feature** (when the tool is tightly coupled to a specific component): + +```tsx +function ProductPage({ product }) { + return ( +
+ + +
+ ); +} +``` + +## Naming conventions + +- Tool names: `snake_case` (e.g., `search_catalog`, `delete_user`, `get_order_status`) +- Component names: PascalCase ending in `Tool` (e.g., `SearchCatalogTool`, `DeleteUserTool`) +- Descriptions: start with a verb, be specific (e.g., "Search the product catalog by keyword" not "Search stuff") + +## Checklist + +Before finishing, verify: + +- [ ] Tool name is unique across the app +- [ ] Description clearly explains what the tool does (AI agents read this) +- [ ] All input fields have `.describe()` for AI context +- [ ] Handler returns `CallToolResult` with `content` array +- [ ] Appropriate annotations are set +- [ ] Component is rendered inside `` +- [ ] For Next.js: file has `"use client"` directive diff --git a/skills/webmcp-setup/SKILL.md b/skills/webmcp-setup/SKILL.md new file mode 100644 index 0000000..21838ff --- /dev/null +++ b/skills/webmcp-setup/SKILL.md @@ -0,0 +1,167 @@ +--- +name: webmcp-setup +description: Bootstraps webmcp-react into an existing React or Next.js app. Installs dependencies, adds WebMCPProvider, creates a first tool, and configures the MCP client bridge. Use when the user wants to set up WebMCP, add MCP tools to their app, integrate webmcp-react, or make their React app accessible to AI agents. +--- + +# Set Up webmcp-react + +## Overview + +`webmcp-react` exposes React app functionality as typed tools on `navigator.modelContext` (the W3C WebMCP API). AI agents discover and call these tools. This skill bootstraps the full setup. + +## Step 1: Install dependencies + +```bash +npm install webmcp-react zod +``` + +`zod` is a peer dependency used for typed tool input schemas. + +## Step 2: Add WebMCPProvider + +All `useMcpTool` calls must be descendants of ``. It installs a polyfill when native browser support is absent. + +### React / Vite + +Wrap the app root: + +```tsx +import { WebMCPProvider } from "webmcp-react"; + +function App() { + return ( + + {/* existing app content */} + + ); +} +``` + +### Next.js (App Router) + +Create a client component wrapper since webmcp-react uses browser APIs: + +```tsx +// app/providers.tsx +"use client"; + +import { WebMCPProvider } from "webmcp-react"; + +export function Providers({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} +``` + +Then wrap `children` in the root layout: + +```tsx +// app/layout.tsx +import { Providers } from "./providers"; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + {children} + + + ); +} +``` + +The library ships with a `"use client"` banner in its build output, so no `transpilePackages` config is needed when installing from npm. + +## Step 3: Create a first tool + +Create a simple tool component to verify the wiring works: + +```tsx +// components/mcp-tools.tsx (add "use client" at top if Next.js) +import { useMcpTool } from "webmcp-react"; +import { z } from "zod"; + +export function GreetTool() { + useMcpTool({ + name: "greet", + description: "Greet someone by name", + input: z.object({ + name: z.string().describe("The name to greet"), + }), + handler: async ({ name }) => ({ + content: [{ type: "text", text: `Hello, ${name}!` }], + }), + }); + return null; +} +``` + +Render it inside the provider: + +```tsx + + + {/* rest of app */} + +``` + +## Step 4: Connect to AI clients + +Desktop MCP clients (Cursor, Claude Code) cannot access `navigator.modelContext` directly. A Chrome extension + local MCP server bridges the gap. + +### 4a. Install the Chrome extension + +Install the "WebMCP Bridge" extension from the Chrome Web Store, or build from source: + +```bash +git clone https://github.com/MCPCat/webmcp-react.git +cd webmcp-react/extension && pnpm install && pnpm build +``` + +Then load unpacked from `extension/dist/` at `chrome://extensions/`. + +### 4b. Configure the MCP client + +**Cursor** -- add to `.cursor/mcp.json`: + +```json +{ + "mcpServers": { + "webmcp-server": { + "command": "npx", + "args": ["webmcp-server"] + } + } +} +``` + +**Claude Code:** + +```bash +claude mcp add --transport stdio webmcp-server -- npx webmcp-server +``` + +### 4c. Activate the extension + +1. Open your app in Chrome +2. Click the WebMCP Bridge extension icon +3. Choose "Always on" for persistent activation, or "Until reload" for one-shot testing +4. Green dot = connected to MCP client and tools are available + +## Step 5: Verify + +1. Run the app in the browser +2. Open the extension popup -- registered tools should appear +3. From Cursor or Claude Code, the tools should be discoverable and callable + +## Troubleshooting + +| Symptom | Fix | +|---------|-----| +| Tools not appearing in AI client | Check extension is activated (green/yellow dot). Verify MCP server is running. | +| Yellow dot (no MCP connection) | Ensure `webmcp-server` is configured in your MCP client. Check port 12315 is free. | +| `useMcpTool` warning about missing provider | Ensure the component is rendered inside ``. | +| Next.js hydration errors | Add `"use client"` to any file using `useMcpTool` or `WebMCPProvider`. | From 80a5b13c22396aa8f8e1dff50289df9a3853e8ef Mon Sep 17 00:00:00 2001 From: Naseem Alnaji Date: Thu, 5 Mar 2026 16:14:36 -0500 Subject: [PATCH 2/2] Fix casing in skills CLI command for webmcp-react --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a607c6..3833a98 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ That's it. The tool is registered on `navigator.modelContext` and can be called This repo ships with [agent skills](./skills) that can set up webmcp-react and scaffold tools for you. Install them with the [skills CLI](https://skills.sh): ```bash -npx skills add MCPCat/webmcp-react +npx skills add mcpcat/webmcp-react ``` Works with Cursor, Claude Code, GitHub Copilot, Cline, and [18+ other agents](https://vercel.com/docs/agent-resources/skills).