The problem, measured
Services that do the same job do not agree on what to call it. What does that cost an agent?
MCP made tools callable and governable at scale, and deliberately left meaning out. This page shows what fills that space today: the same handful of jobs, spelled differently by every implementation. Two examples—browser operation and calendars—chosen because both have several independent implementations to compare.
Start with the expensive one
One word, two meanings, no error
Google Calendar names an event's title summary. In the 300-listing cohort, that is the most common spelling for the field—ahead of name and subject.
Almost everywhere else, a summary is an abstract: the short version of a longer text.
So a model fluent in one dialect, writing to a service that uses the other, puts the meeting title into the description field. The event is created. Nothing fails. Nobody is told.
This is not fragmentation, which costs tokens. It is a collision, where one word means different things in different dialects, and the failure is silent and plausible. Caching a tool list does not help. Reading the description more carefully does not help, because both readings are reasonable.
Example one · operating a browser
Five jobs, three vocabularies
Three independently built MCP servers drive a browser. Each exposes the same five jobs. None of them uses the same words.
The convergence is the point. Three teams, working separately, arrived at the same five jobs—which is decent evidence that the jobs are real. What they could not converge on, because nothing existed to converge on, is the vocabulary.
The workaround already in use
Ghostlight, an independent MCP server, adopts nine of the names in the column above verbatim — read_page, get_page_text, find, navigate, computer, form_input, javascript_tool, tabs_context_mcp, browser_batch — rather than choosing its own, so a model meeting it recognises something. Compare the two published tool lists and you can see it.
Then it kept going, and that is the interesting part. It added roughly eight tools of its own, in two clearly different kinds. Some are things the borrowed vocabulary had no room for but arguably should have: wait_for, so an agent knows when a page settled; dialog, so a blocking modal is reported as state rather than as an ordinary failure; act_on, an action that returns what actually happened instead of merely succeeding. The rest are genuinely its own: narrate and update_plan for a human watching, explain for asking what the current policy permits.
A floor, a set of missing-but-essential jobs, and a vendor’s own additions — found in the wild by an implementer with no way to say which was which. A model meeting Ghostlight cannot tell the borrowed nine from the other sixteen, because nothing distinguishes them. The copying buys recognition for nine tools and nothing for the rest.
Example two · calendars
Seven ways to say when
Argument names across 216 calendar-shaped tools in the cohort. Each row is one idea.
A model does not know what time it is
Two independent Google Calendar MCP servers ship get-current-time as a tool. They ship it because every relative expression a person says—next Thursday, tomorrow afternoon—needs a current instant and a timezone, and a language model has neither.
That is a contract gap patched with a tool call. A response that simply carried as_of and timezone would close it for about thirty bytes, and remove a round trip and a guess.
What we measured
Receipts
Each of these is checkable. The cohort figures are reproducible from the published structural derivation; the surface figures are readable in each project's own documentation.
- 0 of 9,390 declared members in the cohort carry any MCP tool annotation—no
readOnlyHint, no destructiveHint, no idempotentHint. The existing way to say what a tool does to the world is unused here, and MCP itself now tells clients to treat annotations as untrusted.
- 894 distinct spellings of something reference-shaped, across 164 of 300 listings.
- 161 listings paginate; 26 use a cursor. Most page by offset or page number, so "did I see everything?" is usually unanswerable.
- Three concepts, eleven spellings in the most common capability of all: a search query is
query, q, search or keyword; a result bound is limit, max_results, size, page_size, count or per_page.
- Two capability-grouping systems already exist without being called that: Playwright MCP gates tool groups behind a
--caps flag, and Ghostlight governs by capability grants rather than tool lists.
These are lexical and structural measurements of declared surfaces. A name containing cursor does not prove the value is opaque, and a captured declaration does not prove runtime behaviour. Limits are recorded in the data notice.
What is proposed instead
Name the job once, in the open
A Class Profile names a job, fixes its vocabulary, and freezes the meaning so it can be learned once and reused. Optional parts are declared, not assumed. What a backend cannot do, it says, along with what you lose.
These two were chosen to have nothing in common. A calendar touches records you own, with durable identifiers and bounded effects. An operator drives a live surface you do not control, where references go stale inside one turn and the page decides what a click does. If one shape describes both, it is probably not calendar-shaped or browser-shaped. That is the same reason a display and a mass-storage device share a framework while sharing no purpose.
operator
Operate a surface on the user's behalf.
- Floor
- Address a surface, perceive its state, act on a target, know when it settled.
- Facets
surface/browser, surface/desktop, surface/terminal, plus optional jobs like forms, dialogs, scripting, console and network inspection.
- Vendor
- Whatever is genuinely yours—recording, narration, performance tracing—kept visible without entering anyone's floor.
Note that browser is a facet, not the class. Nobody's job is "browser"; the job is having something done, using one.
calendar
Manage the entries on a calendar I control, and tell me when I am free.
- Floor
- List events, get one, create, update, cancel, find free time.
- Facets
- Invitations, recurrence, reminders, RSVP, tombstones—each declared by exact version, each stating what is lost when absent.
- Vendor
- Travel buffers, colour labels, and the rest.
This one is written down and fixture-backed, unlike the operator sketch beside it. Inviting people is a facet because a personal calendar cannot invite anyone; a cancelled entry staying fetchable is a facet because a backend that hard-deletes is still a calendar. The title field is called title—a Google projection would map summary → title and declare the collision rather than inherit it. Collapsing the two reads into one verb is proposed and not yet applied.
Nothing is replaced
Playwright MCP keeps all of its tools. So does Chrome DevTools MCP, and so does any calendar server. A profile is a shared name and a small shared floor that an existing service can present in addition to everything it already does—directly, or through a reviewed mapping written by someone else entirely.
The point is not a smaller surface. It is that an agent which has learned the job once does not have to learn it again per vendor.
What this page does not show
- Anything about behaviour. Every surface here is read from public documentation; no service was installed, connected, or invoked.
- That either contract is correct. Both are illustrations, drawn to be argued with.
- That any capability map exists. Names in the measured corpus do not carry function well enough to cluster on—a map is declared by authors, not derived from tool names.
- That anything conforms. There is no runner, no passing claim, no receipt, and no independent implementation.
- That these measurements generalise beyond one bounded directory cohort and a handful of documented surfaces.
Naming a project above describes its published surface; it is not a criticism of it. A counterexample is more useful than agreement. If a service does one of these jobs in a way the proposed floor cannot express, that is the finding worth having—see contributing.