WebMCP Imperative API: The Advanced Tool Registration Guide

The Declarative API is great for annotating existing forms. But when you need custom logic — fetching live data, handling complex inputs, or exposing dynamic capabilities — the Imperative API is where WebMCP gets powerful.

This guide covers the full Imperative API: tool registration, input schema design, execution functions, read-only vs. write tools, error handling, and advanced patterns.

Prerequisites

  • HTTPS — required for all WebMCP APIs
  • Chrome 146+ with WebMCP flag enabled for testing
  • Intermediate JavaScript — async/await, fetch, JSON
  • Familiarity with the Declarative API is helpful but not required

The Core API: navigator.modelContext.registerTool()

The Imperative API lives at navigator.modelContext. Always check for its existence before calling it — browsers without WebMCP support will not have it.

// Always guard with feature detection
if ("modelContext" in navigator) {
  navigator.modelContext.registerTool({
    name: "toolName",          // required: camelCase string
    description: "...",        // required: agent-readable description
    inputSchema: { ... },      // required: JSON Schema object
    readOnly: true,            // optional: true = no confirmation needed
    async execute(params) {    // required: async function
      return {
        content: [{ type: "text", text: "result" }]
      };
    }
  });
}

Designing Input Schemas

The inputSchema follows JSON Schema draft-07 format. Getting this right is the most important part of Imperative API implementation — a well-designed schema means agents call your tool correctly every time.

Basic Schema Structure

inputSchema: {
  type: "object",
  properties: {
    paramName: {
      type: "string",          // string, number, boolean, array
      description: "...",      // required: explain to the agent
      // Optional constraints:
      enum: ["a", "b", "c"],   // restrict to specific values
      format: "email",         // email, uri, date, date-time
      minLength: 1,
      maxLength: 200,
      pattern: "^[A-Z]{3}$"    // regex pattern
    }
  },
  required: ["paramName"]      // array of required param names
}

Full Real-World Example: Service Search Tool

navigator.modelContext.registerTool({
  name: "searchSEOServices",
  description: "Search Salam Experts SEO service packages.
    Returns packages matching the requested service type
    and optionally filtered by industry or budget tier.
    Read-only — does not submit any data.",
  readOnly: true,
  inputSchema: {
    type: "object",
    properties: {
      serviceType: {
        type: "string",
        enum: ["seo", "technical-seo", "shopify-seo",
               "local-seo", "ecommerce-seo"],
        description: "Type of SEO service"
      },
      industry: {
        type: "string",
        description: "Industry to filter by (optional).
          E.g.: healthcare, logistics, ecommerce"
      },
      budgetTier: {
        type: "string",
        enum: ["starter", "growth", "enterprise"],
        description: "Budget tier (optional)"
      }
    },
    required: ["serviceType"]
  },
  async execute({ serviceType, industry, budgetTier }) {
    try {
      const params = new URLSearchParams({ serviceType });
      if (industry) params.set("industry", industry);
      if (budgetTier) params.set("tier", budgetTier);
      const response = await fetch(`/api/services?${params}`);
      if (!response.ok) throw new Error("API error");
      const packages = await response.json();
      return {
        content: [{
          type: "text",
          text: JSON.stringify(packages, null, 2)
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Error: ${error.message}. Try visiting
            salamexperts.com/services/ directly.`
        }]
      };
    }
  }
});

Read-Only vs. Write Tools

This is a critical design decision. The readOnly flag controls whether the browser asks the user for confirmation before the agent executes the tool.

readOnly: true (No confirmation)readOnly: false (Requires confirmation)
Agent calls the tool silentlyBrowser shows user a confirmation prompt
Best for: search, get pricing, list services, fetch infoBest for: form submission, booking, purchase, data entry
User does not see a promptUser must approve before agent proceeds
Lower friction — agents prefer theseKeeps human in the loop for sensitive actions
Examples: searchProducts, getPricing, listCaseStudiesExamples: bookAudit, submitQuote, placeOrder

Design principle
Default to read-only for informational tools. Require confirmation for anything that creates a record, sends an email, or costs money. This mirrors how users expect AI agents to behave — ask before acting.

Error Handling Patterns

Always wrap execute() in try/catch. Always return a human-readable message in the error case — agents use this to tell users what went wrong.

Standard Error Pattern

async execute(params) {
  try {
    // Your logic here
    const result = await someAsyncOperation(params);
    return {
      content: [{ type: "text", text: JSON.stringify(result) }]
    };
  } catch (error) {
    // Return readable error — agent will relay this to user
    return {
      content: [{
        type: "text",
        text: `Unable to complete request: ${error.message}.
          Please visit our site directly or contact us at
          salamexperts.com/contact/`
      }]
    };
  }
}

Validation Before Execution

async execute({ email, website }) {
  // Validate on top of schema for business rules
  if (!website.startsWith("https://") &&
      !website.startsWith("http://")) {
    return {
      content: [{
        type: "text",
        text: "Please provide a full URL including
          https:// (e.g., https://yoursite.com)"
      }]
    };
  }
  // Proceed with validated data...
}

Advanced Pattern: Multiple Tools on One Page

You can register multiple tools on a single page. Register them all after the DOM is ready, wrapped in a single feature check.

document.addEventListener("DOMContentLoaded", () => {
  if (!("modelContext" in navigator)) return;
  
  // Tool 1: Search
  navigator.modelContext.registerTool({
    name: "searchServices",
    readOnly: true,
    description: "...",
    inputSchema: { ... },
    async execute(p) { ... }
  });
  
  // Tool 2: Get case study
  navigator.modelContext.registerTool({
    name: "getCaseStudy",
    readOnly: true,
    description: "Get a specific case study by industry.
      Returns: client background, results achieved,
      and services used.",
    inputSchema: {
      type: "object",
      properties: {
        industry: {
          type: "string",
          enum: ["ecommerce", "logistics", "healthcare"],
          description: "Industry for the case study"
        }
      },
      required: ["industry"]
    },
    async execute({ industry }) {
      const studies = {
        ecommerce: {
          client: "CNH Pillow",
          result: "283% organic traffic growth",
          service: "E-commerce SEO + technical SEO"
        }
      };
      const study = studies[industry];
      return {
        content: [{
          type: "text",
          text: study
            ? JSON.stringify(study)
            : `No case study available for ${industry}`
        }]
      };
    }
  });
  
  // Tool 3: Book audit (write)
  navigator.modelContext.registerTool({
    name: "bookFreeAudit",
    readOnly: false,
    description: "...",
    inputSchema: { ... },
    async execute(p) { ... }
  });
});

Testing Checklist

TestPass?
Tool appears in Model Context Tool Inspector
Description is complete and clear in Inspector
Required params enforced (omit one, see error)
Enum values work correctly
Successful execution returns structured JSON
Error case returns readable message
Write tools show browser confirmation prompt
Read-only tools call without prompt
No errors in browser DevTools console
Call to Action

Ready to implement WebMCP?

Building complex tools and want an expert review? We audit implementations, review schema design, and ensure your tools work reliably across agent scenarios.

Get WebMCP Readiness Audit

Related Reading

Author

  • Salamexperts Author Profile

    We are a digital marketing agency with over 17 years of experience and a proven track record of helping businesses succeed. Our expertise spans businesses of all sizes, enabling them to grow their online presence and connect with new customers effectively.
    In addition to offering services like consulting, SEO, social media marketing, web design, and web development, we pride ourselves on conducting thorough research on top companies and various industries. We compile this research into actionable insights and share it with our readers, providing valuable information in one convenient place rather than requiring them to visit multiple websites.
    As a team of passionate and experienced digital marketers, we are committed to helping businesses thrive and empowering our readers with knowledge and strategies for success.

    View all posts
Was this article helpful?
YesNo