Example file
03-inspect-and-call.html
Lists the tools the script registers and lets you call any of them yourself, in any browser.
To try this page, download it, replace the placeholders and put it on a test page of your website. Opening the file from your computer won't work, because the embeds check the website address they're on.
<!--
How to see the tools the script offers, and call one yourself, without an
AI assistant. Before the snippet loads, a small wrapper goes in front of
document.modelContext. It records each tool and passes it on to the
browser. In a browser without WebMCP it stands in for WebMCP, so
this page works in any browser (AI assistants won't see the tools then).
Replace wmk_YOUR_KEY with your integration's key.
Each call goes to Subcontext for real: register_interest,
share_requirements and book_callback save contacts, leads and bookings
to your account. Use test details.
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WebMCP: see and call the tools</title>
<style>
section { border: 1px solid #ccc; padding: 0 1rem 1rem; margin: 1rem 0; }
textarea { width: 100%; font-family: monospace; }
pre { white-space: pre-wrap; }
</style>
</head>
<body>
<h1>See the tools and call them</h1>
<p>
This page lists every tool the script offers and lets you call any of them, as an AI assistant
would. Edit the input before you call a tool.
</p>
<p><button id="destroy">SubcontextWebMCP.destroy()</button></p>
<div id="tools">No tools yet.</div>
<script>
// 1. Before the script loads: put a wrapper in front of the browser's WebMCP
// (or a stand-in when there is none). The script uses document.modelContext
// first, so the wrapper sees every tool.
var tools = {}
var browser = document.modelContext || navigator.modelContext // undefined without WebMCP
Object.defineProperty(document, 'modelContext', {
configurable: true,
value: {
registerTool: function (tool, options) {
tools[tool.name] = tool
// destroy() aborts this signal, which is how the script removes a tool.
options.signal.addEventListener('abort', function () { delete tools[tool.name]; render() })
render()
return browser ? browser.registerTool(tool, options) : Promise.resolve()
},
unregisterTool: function (name) {
if (browser && browser.unregisterTool) return browser.unregisterTool(name)
}
}
})
// Example input for each tool. The slugs are placeholders: list_products gives you real ones.
// book_callback's start must be a future time inside your business hours:
// here, 2pm on the next weekday.
var callbackDay = new Date()
do { callbackDay.setDate(callbackDay.getDate() + 1) } while (callbackDay.getDay() === 0 || callbackDay.getDay() === 6)
var callbackStart = callbackDay.toISOString().slice(0, 10) + 'T14:00:00'
var SAMPLE_INPUT = {
show_product: { slug: 'PRODUCT_SLUG' },
compare_products: { slugs: ['FIRST_SLUG', 'SECOND_SLUG'] },
explain_cover: { slug: 'PRODUCT_SLUG' },
check_availability: { product_type: 'term' },
answer_question: { question: 'Do you cover people who have had cancer in the past?' },
book_callback: { name: 'Test Visitor', phone: '+447700900123', start: callbackStart, reason: 'Questions about life cover' },
register_interest: { name: 'Test Visitor', email: 'test.visitor@example.com', message: 'Interested in term life cover' },
share_requirements: { email: 'test.visitor@example.com', requirements: { budget: '30 a month' } }
}
// 2. A card for each tool: its name and description, an input box and a Call button.
function render() {
var list = document.getElementById('tools')
list.textContent = Object.keys(tools).length ? '' : 'No tools registered.'
Object.keys(tools).forEach(function (name) {
var tool = tools[name]
var card = document.createElement('section')
card.innerHTML = '<h3></h3><p></p><textarea rows="4"></textarea><button></button><pre></pre>'
var parts = card.children
parts[0].textContent = tool.title + ' (' + name + ')' + (tool.annotations.readOnlyHint === false ? ': saves to your account' : '')
parts[1].textContent = tool.description
parts[2].value = JSON.stringify(SAMPLE_INPUT[name] || {}, null, 2)
parts[3].textContent = 'Call ' + name
parts[3].onclick = function () { call(tool, parts[2].value, parts[4]) }
list.appendChild(card)
})
}
// 3. Call a tool the way an AI assistant does: execute(input) gives the tool's
// result, or fails with the error message from Subcontext.
function call(tool, inputText, output) {
output.textContent = 'Calling...'
Promise.resolve().then(function () { return tool.execute(JSON.parse(inputText)) }).then(
function (data) { output.textContent = JSON.stringify(data, null, 2) },
function (error) { output.textContent = 'Error: ' + error.message }
)
}
document.getElementById('destroy').onclick = function () { SubcontextWebMCP.destroy() }
</script>
<!-- 4. The snippet as usual, after the wrapper. Replace wmk_YOUR_KEY with your integration's key (starts wmk_).
In the dashboard: Organisation > Agent access > Manage WebMCP tools, then open the integration. -->
<script id="webmcp-embed-script" src="https://js.subcontext.com/webmcp-latest.js"
data-key="wmk_YOUR_KEY" async></script>
</body>
</html>