Writing

FootyCal: adding WebMCP

Adding browser tools to FootyCal after OpenAI introduced WebMCP support in Codex and ChatGPT Work.

OpenAI added WebMCP support to the built-in browser used by Codex and ChatGPT Work. That prompted me to add it to FootyCal.

FootyCal takes a few preferences and produces a calendar URL, so there was an obvious function to expose. The homepage now registers two tools: list_subscription_options and prepare_subscription.

The registration for the second looks like this, with the error handling omitted and the description shortened:

import { prepareSubscription, subscriptionSchema } from './subscriptions';

if (typeof document.modelContext?.registerTool === 'function') {
  await document.modelContext.registerTool({
    name: 'prepare_subscription',
    description: 'Return an AFL calendar URL for the given preferences.',
    inputSchema: subscriptionSchema,
    annotations: { readOnlyHint: true },
    execute: async input => prepareSubscription(input),
  });
}

The browser makes the tool’s name, description and input schema available to the agent. When it calls the tool, the browser runs execute in the page and returns the result.

An agent can first call list_subscription_options to get the valid teams, venues, cities and defaults. For a request like “St Kilda away games in Melbourne or Geelong, with full team names”, it can then call prepare_subscription with:

{
  "scope": "team",
  "team": "saints",
  "filter": "away",
  "cities": ["melbourne", "geelong"],
  "names": "full"
}

prepareSubscription validates the arguments and builds the URL. Unknown teams and unsupported combinations return errors. Both tools run locally in the page; subscribing to the returned URL is the caller’s responsibility.

I also exposed the same functions through GET /api/subscriptions/options and POST /api/subscriptions/prepare. Those use the same validation and work for agents without a WebMCP browser.

I’m curious whether this gets any use. WebMCP is still experimental, and using it means having an agent visit the site in a supporting browser. I haven’t added tracking for the browser tool calls, so I don’t have a usage figure. For now I wanted to see what was involved in supporting it.