Skip to content

Add outputSchema to ModelContextTool and RegisteredTool - #254

Merged
domfarolino merged 8 commits into
webmachinelearning:mainfrom
beaufortfrancois:outputSchema
Nov 2, 2026
Merged

domfarolino merged 8 commits into
webmachinelearning:mainfrom
beaufortfrancois:outputSchema

Conversation

@beaufortfrancois

@beaufortfrancois beaufortfrancois commented Aug 21, 2026 •

Copy link
Copy Markdown
Collaborator

This PR adds an optional outputSchema member to the ModelContextTool and RegisteredTool dictionaries to enable browser agents and in-page agents to help LLMs reliably reason about the return values of tools.

While responseConstraint was previously discussed, that name is too specific to the Built-in AI / Prompt API. TheoutputSchema name aligns directly with the MCP Tools specification outputSchema used to define expected structured outputs with JSON Schema.

FIX #9


Preview | Diff

@arnabwithab arnabwithab mentioned this pull request Sep 3, 2026
7 tasks done
arnabwithab added a commit to arnabwithab/webmcp that referenced this pull request Sep 3, 2026
Codify WebMCP JSON Schema subset (Draft 2020-12) per 2026-03-05 CG resolution.
Meta-validation in registerTool() (TypeError on invalid schema) and input
validation in executeTool() parallel block before tool execute steps
(DataError with {path,reason,schemaPath} for agent self-correction).

Spec-only per review; WPT split to web-platform-tests/wpt (tentative).
Coordinates with webmachinelearning#254 (outputSchema, same dictionaries).
@volkandkaya

Copy link
Copy Markdown

Is this still planned on being added?

@beaufortfrancois

Copy link
Copy Markdown
Collaborator Author

Is this still planned on being added?

I hope so :) 🤞

@domfarolino I've started experimenting with outputSchema in Chromium with https://chromium-review.googlesource.com/c/chromium/src/+/8398367 to test it out.

@markafoltz markafoltz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few questions/comments about how the serialization result is passed around (might be missing some key idea)

Comment thread index.bs Resolved
Comment thread index.bs Resolved
Comment thread index.bs Resolved
Comment thread index.bs Resolved
Comment thread index.bs Resolved
Comment thread index.bs Resolved

@markafoltz markafoltz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good % a few optional suggested edits

Comment thread index.bs Resolved
Comment thread index.bs Resolved
Comment thread index.bs Resolved
Comment thread index.bs Resolved
Comment thread README.md Resolved
Comment thread index.bs Resolved
@kenchris

Copy link
Copy Markdown

Thanks for working on this. One thing I'd like to see said explicitly is that leaving out outputSchema is the normal case. A lot of tools return text, and for those, plain text is often the better result: It is cheaper for the model than structured JSON, and a schema would only wrap the text in an object like { "text": "..." } for no benefit. MCP works like that too, where text content is the default and outputSchema with structured output is an addition for tools that want it. The text in the PR says output is expected to conform to the schema, which is fine when there is one, but a sentence saying that tools without one are not expected to return structured data would make that clear.

Related, and a question more than a request: since results are serialized as JSON, a tool that returns a string comes back as a JSON string with quotes and escaped newlines. Is that the intended shape for text results, or is a plain text result something to look at separately (maybe together with the typed results work in #41 and #282)?

On sjdallst2's question about validation, I'd say a result that doesn't match should reach the host as a tool error, so the host can tell it from a normal result and decide what to do. Also, a schema is written by the page, so the description fields inside it are model-visible text from the page and should get the same treatment as tool descriptions.

Comment thread index.bs Resolved
@beaufortfrancois

Copy link
Copy Markdown
Collaborator Author

@kenchris We're discussing whether outputSchema should be optional or not in #92

@beaufortfrancois

Copy link
Copy Markdown
Collaborator Author

@domfarolino I think we're good now.

@domfarolino
domfarolino merged commit 6cd745a into webmachinelearning:main Nov 2, 2026
2 checks passed
github-actions Bot added a commit that referenced this pull request Nov 2, 2026
SHA: 6cd745a
Reason: push, by domfarolino

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@beaufortfrancois
beaufortfrancois deleted the outputSchema branch November 2, 2026 13:12
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Nov 2, 2026
This adds an optional outputSchema dictionary member to
ModelContextTool and RegisteredTool to define the expected structure
of tool execution return values. Upon registration, outputSchema is
serialized with the tool schema serialization algorithm, throwing
a TypeError on serialization failure before checking abort signals.
getTools() exposes outputSchema as a parsed JSON Schema object, or
undefined when omitted.

Spec PR: webmachinelearning/webmcp#254

Bug: 489045948
Bug: 565876481
Change-Id: I5e333c74c834cd6bc29253609e4e3d74edb09d08
beckysiegel pushed a commit to chromium/chromium that referenced this pull request Nov 2, 2026
This adds an optional outputSchema dictionary member to
ModelContextTool and RegisteredTool to define the expected structure
of tool execution return values. Upon registration, outputSchema is
serialized with the tool schema serialization algorithm, throwing
a TypeError on serialization failure before checking abort signals.
getTools() exposes outputSchema as a parsed JSON Schema object, or
undefined when omitted.

Spec PR: webmachinelearning/webmcp#254

Bug: 489045948
Bug: 565876481
Change-Id: I5e333c74c834cd6bc29253609e4e3d74edb09d08
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8398367
Reviewed-by: Khushal Sagar <khushalsagar@chromium.org>
Reviewed-by: Dominic Farolino <dom@chromium.org>
Commit-Queue: Fr <beaufort.francois@gmail.com>
Cr-Commit-Position: refs/heads/main@{#1732837}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Nov 2, 2026
This adds an optional outputSchema dictionary member to
ModelContextTool and RegisteredTool to define the expected structure
of tool execution return values. Upon registration, outputSchema is
serialized with the tool schema serialization algorithm, throwing
a TypeError on serialization failure before checking abort signals.
getTools() exposes outputSchema as a parsed JSON Schema object, or
undefined when omitted.

Spec PR: webmachinelearning/webmcp#254

Bug: 489045948
Bug: 565876481
Change-Id: I5e333c74c834cd6bc29253609e4e3d74edb09d08
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8398367
Reviewed-by: Khushal Sagar <khushalsagar@chromium.org>
Reviewed-by: Dominic Farolino <dom@chromium.org>
Commit-Queue: Fr <beaufort.francois@gmail.com>
Cr-Commit-Position: refs/heads/main@{#1732837}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Nov 2, 2026
This adds an optional outputSchema dictionary member to
ModelContextTool and RegisteredTool to define the expected structure
of tool execution return values. Upon registration, outputSchema is
serialized with the tool schema serialization algorithm, throwing
a TypeError on serialization failure before checking abort signals.
getTools() exposes outputSchema as a parsed JSON Schema object, or
undefined when omitted.

Spec PR: webmachinelearning/webmcp#254

Bug: 489045948
Bug: 565876481
Change-Id: I5e333c74c834cd6bc29253609e4e3d74edb09d08
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8398367
Reviewed-by: Khushal Sagar <khushalsagar@chromium.org>
Reviewed-by: Dominic Farolino <dom@chromium.org>
Commit-Queue: Fr <beaufort.francois@gmail.com>
Cr-Commit-Position: refs/heads/main@{#1732837}
beaufortfrancois added a commit to GoogleChromeLabs/webmcp-extension that referenced this pull request Nov 4, 2026
Follows webmachinelearning/webmcp#254, which adds
an optional outputSchema to ModelContextTool and RegisteredTool.

The content script forwards RegisteredTool.outputSchema to the side panel,
which sends it as its own field of each tool declaration.

Only Gemini gives it to the model, as responseJsonSchema on the function
declaration. The AI SDK's Google provider only sends name, description and
parametersJsonSchema, and the SDK's own tool outputSchema never reaches any
provider, so the Google provider's fetch adds the field to the request
body. The model is opened for each turn with that turn's output schemas,
so concurrent chats never see each other's tools.

OpenAI, Anthropic, Ollama and the on-device Prompt API have no such field,
and the schema is not mixed into the tool description either.

webmcp-types does not declare outputSchema yet, so the WebMCP types are
augmented locally until it does.
beaufortfrancois added a commit to GoogleChromeLabs/webmcp-extension that referenced this pull request Nov 4, 2026
Follows webmachinelearning/webmcp#254, which adds
an optional outputSchema to ModelContextTool and RegisteredTool.

The content script forwards RegisteredTool.outputSchema to the side panel,
which sends it as its own field of each tool declaration.

Only Gemini gives it to the model, as responseJsonSchema on the function
declaration. The AI SDK's Google provider only sends name, description and
parametersJsonSchema, and the SDK's own tool outputSchema never reaches any
provider, so the Google provider's fetch adds the field to the request
body. The model is opened for each turn with that turn's output schemas,
so concurrent chats never see each other's tools.

OpenAI, Anthropic, Ollama and the on-device Prompt API have no such field,
and the schema is not mixed into the tool description either.

webmcp-types does not declare outputSchema yet, so the WebMCP types are
augmented locally until it does.
beaufortfrancois added a commit to GoogleChromeLabs/webmcp-extension that referenced this pull request Nov 4, 2026
Follows webmachinelearning/webmcp#254, which adds
an optional outputSchema to ModelContextTool and RegisteredTool.

The content script forwards RegisteredTool.outputSchema to the side panel,
which checks every result of that tool against it, before the result is
truncated or spotlighted. A result that does not match goes back to the
model as a tool error saying where it differs, as MCP clients do with
structured content. A schema that cannot be used is the page's mistake,
so the result is then passed on unchecked.

The check is done in the side panel, so it holds for the backend server
and the on-device Prompt API alike. The schema is not sent to any model:
only Gemini has a field for it, and the model is better served by results
known to match than by a description of what they should look like.

Results are validated with @cfworker/json-schema, which never evaluates
code, as the extension's content security policy requires.

webmcp-types does not declare outputSchema yet
(webmachinelearning/webmcp-types#16), so
RegisteredTool is augmented locally until it does.
MrSunshyne added a commit to MrSunshyne/vue-webmcp that referenced this pull request Nov 7, 2026
The spec added outputSchema to ModelContextTool and RegisteredTool
(webmachinelearning/webmcp#254, merged 2026-11-02; Chrome 159): a JSON
Schema for the tool's result, which agents may use to reject a result
that does not validate.

It is reactive and compared by content like inputSchema, so a change
re-registers the tool and a rebuilt identical object does not.
useWebMCPTools and defineWebMCPTool take it through the shared options
type, the stub stores it and returns it from getTools(), and the
descriptor and RegisteredTool types declare it until webmcp-types does
(its PR #16 is open).

Normalization is unchanged, as in use-webmcp-tool's open PR #18: the
spec defines no structured result field, and a { content } value already
passes through untouched for tools that want to add structuredContent.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce outputSchema (was: Should output also have a schema?)

6 participants