All articles
DeveloperJuly 14, 20268 min read

WebMCP Implementation Examples

Copy-paste registerTool() patterns for the most common WebMCP use cases: e-commerce, SaaS, content sites, and forms.

The minimal tool

Every tool needs three fields: name, description, and inputSchema. The execute function runs in the browser when the agent calls the tool.

Minimal registerTool() example
navigator.modelContext.registerTool({
  name: "getPageTitle",
  description: "Get the title of the current page",
  inputSchema: { type: "object", properties: {}, required: [] },
  execute: async () => ({ title: document.title })
})

E-commerce: add to cart

The most common e-commerce tool. The agent passes a product ID and quantity; the execute function calls your existing cart API or dispatches a DOM event.

addToCart
navigator.modelContext.registerTool({
  name: "addToCart",
  description: "Add a product to the shopping cart",
  inputSchema: {
    type: "object",
    properties: {
      productId: { type: "string", description: "Product SKU or ID" },
      quantity:  { type: "number", description: "Number of units", minimum: 1 }
    },
    required: ["productId", "quantity"]
  },
  execute: async ({ productId, quantity }) => {
    const res = await fetch("/cart/add", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ id: productId, quantity })
    })
    const data = await res.json()
    return { success: res.ok, cartCount: data.item_count }
  }
})

E-commerce: search products

searchProducts
navigator.modelContext.registerTool({
  name: "searchProducts",
  description: "Search the product catalogue and return matching items",
  inputSchema: {
    type: "object",
    properties: {
      query:    { type: "string",  description: "Search query" },
      maxItems: { type: "number",  description: "Max results to return", default: 5 }
    },
    required: ["query"]
  },
  execute: async ({ query, maxItems = 5 }) => {
    const res = await fetch(`/search?q=${encodeURIComponent(query)}&limit=${maxItems}`)
    const data = await res.json()
    return {
      results: data.products.map(p => ({
        id: p.id, title: p.title, price: p.price, url: p.url
      }))
    }
  }
})

SaaS: create a record

For authenticated SaaS apps — the execute function runs in the browser using the user's existing session cookies. No token passing required.

createTask (SaaS example)
navigator.modelContext.registerTool({
  name: "createTask",
  description: "Create a new task in the current project",
  inputSchema: {
    type: "object",
    properties: {
      title:    { type: "string", description: "Task title" },
      assignee: { type: "string", description: "Assignee username (optional)" },
      dueDate:  { type: "string", description: "Due date as YYYY-MM-DD (optional)" }
    },
    required: ["title"]
  },
  execute: async ({ title, assignee, dueDate }) => {
    const res = await fetch("/api/tasks", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ title, assignee, due_date: dueDate })
    })
    const task = await res.json()
    return { taskId: task.id, url: task.url }
  }
})

Content site: search articles

searchArticles
navigator.modelContext.registerTool({
  name: "searchArticles",
  description: "Search published articles by keyword",
  inputSchema: {
    type: "object",
    properties: {
      query:    { type: "string", description: "Search keyword" },
      maxItems: { type: "number", description: "Max results", default: 3 }
    },
    required: ["query"]
  },
  execute: async ({ query, maxItems = 3 }) => {
    const res = await fetch(`/api/search?q=${encodeURIComponent(query)}&n=${maxItems}`)
    const data = await res.json()
    return { articles: data.hits.map(h => ({ title: h.title, url: h.url, excerpt: h.excerpt })) }
  }
})

Form: newsletter subscribe

Expose subscription forms as tools so agents can complete them without DOM interaction.

subscribeNewsletter
navigator.modelContext.registerTool({
  name: "subscribeNewsletter",
  description: "Subscribe an email address to the newsletter",
  inputSchema: {
    type: "object",
    properties: {
      email: { type: "string", format: "email", description: "Email address to subscribe" }
    },
    required: ["email"]
  },
  execute: async ({ email }) => {
    const res = await fetch("/api/newsletter/subscribe", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email })
    })
    return { success: res.ok }
  }
})

Using Aigentably instead of writing this manually

All of the above can be defined in the Aigentably dashboard — no JavaScript to write. You define the tool name, description, input schema fields, and the execute logic (which Aigentably wraps in executeJs), then paste one script tag. The snippet fetches your tool definitions and calls registerTool() automatically.

The benefit: you can update tools without deploying code. Change the inputSchema, update the execute logic, or add new tools — it takes effect the next time the snippet loads.

Related

Add WebMCP to your site in 30 seconds

Define tools in the dashboard. No code to write or deploy.

Get started free