agentsclimarketplace

Webmcp skill

Skill Blackie360/webmcp-skill/webmcp-skill

Agent skill for implementing WebMCP on websites — expose app features to browser agents via document.modelContext.registerTool(). Install: npx skills add Blackie360/webmcp-skill -g

Install
npx -y skills add Blackie360/webmcp-skill --skill webmcp-skill

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Implements WebMCP (Web Model Context Protocol) on websites using document.modelContext.registerTool. Covers tool design, JSON Schema inputs, security annotations, origin isolation, and Chrome testing. Use when adding WebMCP tools to web apps, exposing page features to browser agents, or when the user mentions WebMCP, modelContext, or agent-ready web tools. Not for server-side MCP servers.

SKILL.md

8.2 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it

WebMCP Skill

Guide for exposing website features to browser agents via the WebMCP API.

WebMCP vs Server MCP

Server MCPWebMCP
RuntimeNode/Python serverBrowser tab (JavaScript)
APIMCP SDK server.tool()document.modelContext.registerTool()
DiscoveryClient connects to server URLAgent visits page; tools registered in-page
AuthOAuth, API keysExisting web session/cookies

For server-side MCP, use an mcp-builder skill instead. This skill is browser-only.

When to Use

  • Adding agent-callable tools to a web app
  • Replacing fragile DOM-scraping flows with structured tool calls
  • Exposing forms, cart, search, or settings actions to browser agents
  • User mentions WebMCP, modelContext, or agent-ready web tools

When NOT to Use

  • Building a standalone MCP server (backend)
  • Headless automation without a visible browser tab
  • Non-web environments (CLI, mobile native)

Prerequisites

Before registering tools, verify:

  • Secure context — HTTPS or localhost
  • Origin isolation — document is origin-keyed; WebMCP disabled if document.domain is set or Origin-Agent-Cluster: ?0
  • Permissions policytools feature allowed (default self; cross-origin iframes need allow="tools")
  • Browser support — Chrome flag for local dev or origin trial for production (see references/browser-setup.md)
  • Visible tab — tool execute runs in an open browser context; no headless calls

API Choice

Simple HTML form submit?
  └─ Yes → Consider declarative HTML annotations (spec still evolving; see examples/form-tool.html)
  └─ No  → Use imperative registerTool() (recommended for SPAs and complex logic)

Prefer the imperative API until declarative form synthesis is stable in the spec.

Implementation Workflow

Copy this checklist and track progress:

Task Progress:
- [ ] Step 1: Audit UI actions worth exposing
- [ ] Step 2: Map each action to one tool (reuse existing app functions)
- [ ] Step 3: Define name, title, description, inputSchema
- [ ] Step 4: Implement execute with structured return values
- [ ] Step 5: Set annotations (readOnlyHint, untrustedContentHint)
- [ ] Step 6: Register on mount; unregister on unmount via AbortSignal
- [ ] Step 7: Test with Chrome flag + Model Context Tool Inspector

Step 1: Audit actions

List user-facing actions agents should perform: search, filter, add to cart, submit form, navigate, etc. Skip actions that require opaque visual interaction unless wrapped in a dedicated tool.

Step 2: Reuse existing logic

Call the same functions your UI buttons use. Do not duplicate business logic in execute.

Step 3: Define the tool

Name rules (from spec):

  • 1–128 characters
  • ASCII alphanumeric, _, -, . only
  • Unique within the page's tool map

Description: Plain language stating what the tool does and what side effects it has. Agents rely on this to choose tools and request user consent.

inputSchema: JSON Schema object. Keep parameters minimal — only what the action needs.

Step 4: Implement execute

Return structured JSON agents can parse. Prefer { error: "..." } over thrown exceptions for expected failures.

execute: async ({ sku, quantity = 1 }) => {
  if (!sku) return { error: 'sku is required' }
  const result = await cartService.add(sku, quantity)
  return { success: true, cartItemCount: result.count }
}

Step 5: Annotations

annotations: {
  readOnlyHint: true,           // tool does not mutate state
  untrustedContentHint: true    // output includes user-generated content
}

See references/security.md for when to set each.

Step 6: Register and clean up

const controller = new AbortController()

await document.modelContext.registerTool(
  {
    name: 'add_to_cart',
    title: 'Add to cart',
    description: 'Adds a product to the shopping cart by SKU. Does not checkout.',
    inputSchema: {
      type: 'object',
      properties: {
        sku: { type: 'string', description: 'Product SKU' },
        quantity: { type: 'integer', minimum: 1, default: 1 }
      },
      required: ['sku']
    },
    annotations: { readOnlyHint: false },
    execute: async ({ sku, quantity = 1 }) => {
      const result = await cartService.add(sku, quantity)
      return { success: true, cartItemCount: result.count }
    }
  },
  { signal: controller.signal }
)

// On page unload or component unmount:
controller.abort()

Step 7: Dynamic tools

If tools change at runtime, listen for registration updates:

document.modelContext.ontoolchange = () => {
  // Refresh UI or internal tool list
}

Tool Design Rules

  1. One action per toolsearch_products and add_to_cart are separate tools
  2. Descriptions match behavior — never describe "view cart" if execute triggers purchase
  3. State side effects explicitly — "Adds item; does not charge" vs "Completes purchase"
  4. Confirm destructive actions in-app — show a dialog inside execute before purchases, deletes, or sends
  5. Minimize inputSchema fields — avoid requesting age, location, or history unless strictly needed
  6. No injection in metadata — descriptions and return values must not contain hidden agent instructions
  7. Mark UGC as untrusted — forum posts, reviews, comments → untrustedContentHint: true

Framework Integration

Vanilla / SPA

Register after app initialization when DOM and state are ready.

React

useEffect(() => {
  const controller = new AbortController()
  void document.modelContext.registerTool({ /* ... */ }, { signal: controller.signal })
  return () => controller.abort()
}, [dependencies])

Register after hydration on SSR apps. Pass stable dependencies only.

Angular

Chrome documents experimental WebMCP support in Angular. Follow framework-specific guides when available; fall back to imperative registerTool in a service ngOnInit.

Cross-origin iframes

Parent must allow tools in the iframe:

<iframe src="https://embed.example.com" allow="tools"></iframe>

Use exposedTo in registerTool options to expose tools to specific origins. See references/api-reference.md.

Testing

  1. Enable Chrome flag: chrome://flags/#enable-webmcp-testing → Enabled → relaunch
  2. Install Model Context Tool Inspector Extension
  3. Load your page — verify tools appear in the inspector
  4. Manually invoke each tool with valid and invalid inputs
  5. Prompt the inspector agent in natural language; confirm it picks the right tool
  6. Check return values are clear and JSON Schema validates inputs

Full setup: references/browser-setup.md

Common Errors

ErrorCauseFix
SecurityErrorNot origin-isolatedRemove document.domain; check Origin-Agent-Cluster header
NotAllowedErrortools policy blockedTop-level page or add allow="tools" on iframe
InvalidStateErrorDuplicate tool nameUnregister first or use unique names
API undefinedFlag off or unsupported browserEnable flag or join origin trial

Additional Resources

What ships with it: 6 files

18.5 KB alongside SKILL.md, 1 of them executable

references/

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.