# Webmcp Org NPM Packages Webmcp

> WebMCP Development

- Skill: `tomevault-io/webmcp-org-npm-packages-webmcp` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/webmcp-org-npm-packages-webmcp`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/webmcp-org-npm-packages-webmcp/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/webmcp-org-npm-packages-webmcp

---


# WebMCP Development

Create MCP tools for any website or web app. Inject, test, iterate.

## Quick Start

**The universal development loop:**

1. **Navigate**: `navigate_page` to target URL
2. **Reload**: `navigate_page` with `type="reload"` (clears stale state from prior sessions)
3. **Explore**: `take_snapshot` to understand page structure
4. **Write**: Tool code (just JavaScript with `execute:` function)
5. **Inject**: `inject_webmcp_script` - polyfill auto-injected if needed
6. **Verify**: `diff_webmcp_tools` to see registered tools
7. **Test**: Call tools directly: `mcp__chrome-devtools__webmcp_{domain}_page{idx}_{name}`
8. **Debug**: `list_console_messages` if failures
9. **Iterate**: Fix code, reinject, retest

**IMPORTANT**: Always reload the page before injecting to avoid stale polyfill issues.

```javascript
// Minimal tool - no imports needed!
navigator.modelContext.registerTool({
  name: 'get_page_title',
  description: 'Get the current page title',
  inputSchema: { type: 'object', properties: {} },
  execute: async () => ({
    content: [{ type: 'text', text: document.title }],
  }),
});
```

## Context Detection

**React/Vue/Next.js app?**
-> See [REACT_INTEGRATION.md](references/REACT_INTEGRATION.md)

**External site (Notion, GitHub)?**
-> See [USERSCRIPT_GUIDE.md](references/USERSCRIPT_GUIDE.md)

**Running Rails/Django/Laravel app?**
-> See [PRODUCTION_TESTING.md](references/PRODUCTION_TESTING.md)

**Vanilla JS/HTML?**
-> See [VANILLA_JS.md](references/VANILLA_JS.md)

## Tool Naming

After injection, tools become first-class MCP tools:

| Your Tool Name | Becomes                                   |
| -------------- | ----------------------------------------- |
| `search_pages` | `webmcp_notion_so_page0_search_pages`     |
| `list_orders`  | `webmcp_localhost_3000_page0_list_orders` |

## inject_webmcp_script Tool

The key tool for development iteration:

```javascript
// Option 1: Inline code (quick prototyping)
inject_webmcp_script({
  code: `
    navigator.modelContext.registerTool({
      name: 'my_tool',
      description: 'Description here',
      inputSchema: { type: 'object', properties: {} },
      execute: async () => ({
        content: [{ type: 'text', text: 'Result' }]
      })
    });
  `,
  wait_for_tools: true, // Wait for registration (default: true)
  timeout: 5000, // Max wait time ms (default: 5000)
});

// Option 2: TypeScript file (production development)
inject_webmcp_script({
  file_path: './tools/src/mysite.ts',
  // TypeScript auto-bundled via esbuild (~10ms)
  // Imports from node_modules resolved automatically
});
```

**Features:**

- Auto-detects if polyfill needed (checks `navigator.modelContext`)
- Prepends @mcp-b/global polyfill if missing
- **Auto-bundles TypeScript** (.ts/.tsx) via esbuild
- Resolves imports from node_modules (e.g., @webmcp/helpers)
- Waits for tools to register
- Returns registered tool names
- Handles CSP errors gracefully

## @webmcp/helpers Package

**NOTE: Not published yet.** The site-package template includes inline helpers until published.

Lightweight tree-shakable helpers for userscripts:

```typescript
// Helper functions (inlined in template until package published)
function textResponse(text: string): ToolResponse;
function jsonResponse(data: unknown, indent = 2): ToolResponse;
function errorResponse(message: string): ToolResponse;
function getAllElements(selector: string): Element[];
function getText(selectorOrElement: string | Element | null): string | null;
function waitForElement(selector: string, timeout = 5000): Promise<Element>;
```

See [HELPERS_API.md](references/HELPERS_API.md) for full API.

## Calling Injected Tools

After injection, tools are automatically registered with the Chrome DevTools MCP server
and become immediately callable. The server sends `tools/list_changed` notifications
to inform clients about new tools.

### Tool Naming Convention

Tools follow the pattern: `webmcp_{sanitized_domain}_page{N}_{tool_name}`

Examples:

- `webmcp_news_ycombinator_com_page0_get_stories`
- `webmcp_old_reddit_com_page0_get_posts`
- `webmcp_github_com_page1_search_repos`

### In Claude Code Sessions

When calling tools in Claude Code, use the MCP server prefix:

```javascript
mcp__chrome -
  devtools__webmcp_news_ycombinator_com_page0_get_stories({
    limit: 10,
  });
```

The `mcp__chrome-devtools__` prefix routes the call to the correct MCP server.

### In MCP SDK / Tests

When using the MCP SDK directly (e.g., in test scripts), call by the tool name only:

```javascript
await client.callTool({
  name: 'webmcp_news_ycombinator_com_page0_get_stories',
  arguments: { limit: 10 },
});
```

**No prefix needed** - the SDK already knows which server to call.

## Self-Testing Protocol

**CRITICAL**: Verify every tool before considering done.

1. `diff_webmcp_tools` -> Tools appear as `webmcp_{domain}_page{idx}_{name}`
2. Call each tool using the correct calling convention (see above)
3. If fails: `list_console_messages` + `take_snapshot`
4. Fix -> reinject -> retest
5. Only done when ALL tools pass

See [SELF_TESTING.md](references/SELF_TESTING.md) for detailed protocol.

## Tool Design Principles

**Categories by safety:**

- **Read-only** (`readOnlyHint: true`): No side effects
- **Read-write**: Modify UI, reversible
- **Destructive** (`destructiveHint: true`): Permanent actions

**Two-tool pattern for forms:**

- `fill_*_form` (read-write) - populate fields
- `submit_*_form` (destructive) - commit changes

**Handler return format:**

```javascript
// Success
return {
  content: [{ type: 'text', text: 'Result data' }],
};

// Error
return {
  content: [{ type: 'text', text: 'Error message' }],
  isError: true,
};
```

See [TOOL_DESIGN.md](references/TOOL_DESIGN.md) for patterns.

## Common Patterns

### Scraping Data

```javascript
navigator.modelContext.registerTool({
  name: 'get_items',
  description: 'Get items from the page',
  inputSchema: {
    type: 'object',
    properties: {
      limit: { type: 'number', description: 'Max items (default: 10)' },
    },
  },
  execute: async ({ limit = 10 }) => {
    const items = [];
    document.querySelectorAll('.item').forEach((el, i) => {
      if (i >= limit) return;
      items.push({
        title: el.querySelector('.title')?.textContent?.trim() || '',
        url: el.querySelector('a')?.href || '',
      });
    });
    return {
      content: [{ type: 'text', text: JSON.stringify(items, null, 2) }],
    };
  },
});
```

### Form Filling

```javascript
// Step 1: Fill form (read-write, reversible)
navigator.modelContext.registerTool({
  name: 'fill_contact_form',
  description: 'Fill contact form fields. Call submit_contact_form to send.',
  inputSchema: {
    type: 'object',
    properties: {
      name: { type: 'string' },
      email: { type: 'string' },
      message: { type: 'string' },
    },
  },
  execute: async ({ name, email, message }) => {
    if (name) document.querySelector('#name').value = name;
    if (email) document.querySelector('#email').value = email;
    if (message) document.querySelector('#message').value = message;
    return { content: [{ type: 'text', text: 'Form filled' }] };
  },
});

// Step 2: Submit form (destructive)
navigator.modelContext.registerTool({
  name: 'submit_contact_form',
  description: 'Submit the contact form. Sends the message.',
  inputSchema: { type: 'object', properties: {} },
  execute: async () => {
    document.querySelector('form#contact').submit();
    return { content: [{ type: 'text', text: 'Form submitted' }] };
  },
});
```

### Navigation

```javascript
navigator.modelContext.registerTool({
  name: 'navigate_to',
  description: 'Navigate to a section',
  inputSchema: {
    type: 'object',
    properties: {
      section: { type: 'string', enum: ['home', 'about', 'contact'] },
    },
    required: ['section'],
  },
  execute: async ({ section }) => {
    const urls = { home: '/', about: '/about', contact: '/contact' };
    window.location.href = urls[section];
    return { content: [{ type: 'text', text: `Navigating to ${section}...` }] };
  },
});
```

## When to Use This Skill

**Use when:**

- Creating MCP tools for any website
- Testing tools on your running app
- Adding MCP to vanilla JS/HTML/CSS apps
- Prototyping before committing to an approach

**Don't use when:**

- Site already has WebMCP (just use existing tools)
- Just exploring without building tools

## API Reference

Search docs for specifics:

```
mcp__docs__SearchWebMcpDocumentation("registerTool inputSchema")
mcp__docs__SearchWebMcpDocumentation("tool annotations")
```

## Example Scripts

Reference implementations available in `examples/`:

- `hackernews.js` - Hacker News
- `github.js` - GitHub repositories
- `wikipedia.js` - Wikipedia articles
- `reddit.js` - Reddit posts/comments
- `youtube.js` - YouTube videos
- `twitter.js` - Twitter/X
- `amazon.js` - Amazon products
- `linkedin.js` - LinkedIn profiles/jobs
- `stackoverflow.js` - Stack Overflow Q&A
- `notion.js` - Notion pages/databases
- `google-docs.js` - Google Docs

## Creating a Site Package

For distributable tools + documentation, use the site package template:

```bash
# Copy template
cp -r templates/site-package ./mysite-mcp

# Update placeholders: {{site}}, {{Site}}, {{site_url}}
# Edit: SKILL.md, tools/src/{{site}}.ts, etc.

# Install dependencies
cd mysite-mcp/tools && npm install

# Develop tools
inject_webmcp_script({ file_path: "./mysite-mcp/tools/src/mysite.ts" })
```

**Site package structure:**

```
mysite-mcp/
├── SKILL.md              # Main skill (Setup + Workflows)
├── tools/
│   ├── package.json      # Dependencies (@webmcp/helpers)
│   └── src/mysite.ts     # Tool implementations
├── reference/
│   ├── api.md            # Detailed API docs
│   └── workflows.md      # Usage examples
└── README.md
```

The SKILL.md includes a **Setup section** that tells future agents where to find and inject the tools.

## Troubleshooting

See [TROUBLESHOOTING.md](references/TROUBLESHOOTING.md)

**Common issues:**

| Issue                               | Solution                                                |
| ----------------------------------- | ------------------------------------------------------- |
| Connection timeout / stale polyfill | `navigate_page` with `type="reload"`, then reinject     |
| CSP blocking injection              | Use browser extension approach                          |
| Tools not registering               | Check console for errors                                |
| Stale tools after navigation        | Reinject script                                         |
| Selector not finding element        | Use take_snapshot to verify page state                  |
| TypeScript build fails              | Check for syntax errors, run `pnpm install`             |
| Imports not resolved                | Ensure dependencies in package.json, run install        |
| `handler` not recognized            | Use `execute:` instead of `handler:` in tool definition |

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/webmcp-org) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-11 -->

