Zero-JavaScript WebMCP: Mastering the Declarative Form API
The Power of Simplicity
Not every WebMCP integration needs JavaScript. The declarative API lets you add AI agent support to existing HTML forms by adding a few attributes. This is the lowest-friction path to making your site agent-friendly.
Basic Syntax
Add three attributes to any <form> element:
<form toolname="search_products"
tooldescription="Search for products by keyword and category"
method="GET"
action="/search">
<input name="q" type="text" placeholder="Search..." required />
<select name="category">
<option value="">All Categories</option>
<option value="electronics">Electronics</option>
<option value="books">Books</option>
</select>
<button type="submit">Search</button>
</form>
The browser automatically:
- Reads the form fields and generates a JSON Schema for the tool's input parameters.
- Maps field names, types, and validation attributes (
required,min,max,pattern) to schema constraints. - Registers the tool with the provided name and description.
How Agent Invocation Works
When an AI agent invokes a declarative form tool:
- The browser focuses the form (scrolling it into view).
- Fields are pre-filled visually with the agent's provided values.
- The user sees the pre-filled form and confirms the submission.
- On confirmation, the form submits normally through its
actionURL.
If toolautosubmit="true" is set, the confirmation step is skipped and the form submits immediately. Use this only for read-only, non-sensitive operations like search.
The agentInvoked Flag
When a form submission is triggered by an AI agent, the SubmitEvent has an agentInvoked property set to true. This lets your backend differentiate between human and agent submissions:
document.querySelector('form').addEventListener('submit', (e) => {
if (e.agentInvoked) {
// Track agent-driven submission
analytics.track('agent_form_submit', { tool: 'search_products' });
}
});
Field Type Mapping
| HTML Input Type | JSON Schema Type |
|---|---|
text | string |
number | number (with min/max) |
email | string (format: email) |
date | string (format: date) |
checkbox | boolean |
select | string (enum from options) |
textarea | string |
Real-World Examples
Hotel Search
<form toolname="search_hotels"
tooldescription="Search hotels by destination, dates, guests, and price range"
toolautosubmit="true">
<input name="destination" type="text" required />
<input name="checkin" type="date" required />
<input name="checkout" type="date" required />
<input name="guests" type="number" min="1" max="10" value="2" />
<input name="maxPrice" type="number" min="0" />
<button type="submit">Search</button>
</form>
Support Ticket
<form toolname="create_ticket"
tooldescription="Create a customer support ticket with subject, priority, and description"
method="POST"
action="/api/tickets">
<input name="subject" type="text" required maxlength="200" />
<select name="priority" required>
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</select>
<textarea name="description" required maxlength="5000"></textarea>
<button type="submit">Submit Ticket</button>
</form>
When to Choose Declarative vs. Imperative
- Declarative: Existing forms, simple CRUD operations, search interfaces, contact forms.
- Imperative: Multi-step workflows, dynamic schemas, operations without a form UI, complex business logic.
The declarative API is designed to be the easy on-ramp. Start here, and add imperative tools only when the declarative approach cannot express your requirements.