diff --git a/README.md b/README.md
index b42aa98..4a3e306 100644
--- a/README.md
+++ b/README.md
@@ -105,7 +105,7 @@ Jen wants to create a yard sale flyer on `https://easely.example`. She wants to
- **Jen**: "Show me templates that are spring themed and that prominently feature the date and time. They should be on a white background so I don't have to print in color."
- The website has already registered the following tools:
```js
- document.modelContext.registerTool({
+ await document.modelContext.registerTool({
name: "filter-templates",
description: "Filters the list of templates based on a natural language visual description.",
inputSchema: {
@@ -129,7 +129,7 @@ Jen wants to create a yard sale flyer on `https://easely.example`. She wants to
- **Agent**: "Done! I've created three variations of your design, each with a unique call to action."
- **Jen is ready to finalize the flyers**. Normally, she would export a PDF and find a local print shop. However, the page has also registered an `order-prints` tool:
```js
- document.modelContext.registerTool({
+ await document.modelContext.registerTool({
name: "order-prints",
description: "Orders the current design for printing and shipping to the user.",
inputSchema: {
@@ -153,7 +153,7 @@ Maya is shopping for dresses on `http://wildebloom.example/shop`.
- **Maya**: "Show me only dresses available in my size, and also show only the ones that would be appropriate for a cocktail-attire wedding."
- The page has already registered tools to search and display products:
```js
- document.modelContext.registerTool({
+ await document.modelContext.registerTool({
name: "get-dresses",
description: "Returns an array of product listings containing id, description, price, and photo.",
inputSchema: {
@@ -168,11 +168,11 @@ Maya is shopping for dresses on `http://wildebloom.example/shop`.
return response.json();
}
});
- document.modelContext.registerTool({
+ await document.modelContext.registerTool({
name: "show-dresses",
...
});
- document.modelContext.registerTool({
+ await document.modelContext.registerTool({
name: "filter-products",
...
});
@@ -213,7 +213,7 @@ John is a software developer performing a code review in [Gerrit](https://www.ge
- **John**: "Why are the Mac and Android trybots failing?"
- The page has already registered the following tools:
```js
- document.modelContext.registerTool({
+ await document.modelContext.registerTool({
name: "get-trybot-statuses",
description: "Returns the current status of all trybot runs for the active patch.",
execute() {
@@ -221,7 +221,7 @@ John is a software developer performing a code review in [Gerrit](https://www.ge
}
});
- document.modelContext.registerTool({
+ await document.modelContext.registerTool({
name: "get-trybot-failure-snippet",
description: "If a bot failed, returns the tail log snippet describing the error.",
inputSchema: {
@@ -260,7 +260,7 @@ A Model Context Provider registers tools by calling the `document.modelContext.r
```js
const controller = new AbortController();
-document.modelContext.registerTool({
+await document.modelContext.registerTool({
name: "add-todo",
description: "Add a new item to the user's active todo list",
inputSchema: {
@@ -321,14 +321,14 @@ By default, WebMCP is enabled in top-level `Window`s and its same-origin iframes
```
-Calls to `document.modelContext.registerTool()` will throw a `NotAllowedError` DOMException when the permission is disabled, whether by the `allow` attribute or the `Permissions-Policy: tools=()` header. Handling of declarative tool registration errors, including when the permisssion is disabled is TBD; see [Issue #182](https://github.com/webmachinelearning/webmcp/issues/182).
+Calls to `document.modelContext.registerTool()` will return a promise rejected with `NotAllowedError` DOMException when the permission is disabled, whether by the `allow` attribute or the `Permissions-Policy: tools=()` header. Handling of declarative tool registration errors, including when the permisssion is disabled is TBD; see [Issue #182](https://github.com/webmachinelearning/webmcp/issues/182).
#### Cross-origin iframe exposure: `exposedTo`
By default, tools registered by a document are only exposed to itself, same-origin documents in the same tree, and built-in browser agents (see this discussion). To support author-provided agents running in frames, developers can selectively share tools with secure origins of their choice, `exposedTo` option during registration:
```js
-document.modelContext.registerTool({
+await document.modelContext.registerTool({
name: "share-location",
description: "Returns the user's office location.",
execute() { return { office: "Building 4" }; }
diff --git a/declarative-api-explainer.md b/declarative-api-explainer.md
index 2888f2f..becfe20 100644
--- a/declarative-api-explainer.md
+++ b/declarative-api-explainer.md
@@ -69,7 +69,7 @@ of each "property" in the input schema generated for a declarative tool.
With this, the following imperative structure:
```js
-window.navigator.modelContext.registerTool({
+await document.modelContext.registerTool({
name: "search-cars",
description: "Perform a car make/model search",
inputSchema: {
diff --git a/index.bs b/index.bs
index 45b4dce..46d8cbc 100644
--- a/index.bs
+++ b/index.bs
@@ -187,7 +187,7 @@ A tool definition is a [=struct=] with the following [=struct/items=]
To notify documents of a tool change given a {{Document}} |tool owner| and a [=list=] of
[=origins=] |exposed origins|, run these steps:
-1. [=Assert=]: these steps are running on |tool owner|'s [=relevant agent=]'s [=agent/event loop=].
+1. [=Assert=]: these steps are running [=in parallel=].
1. Let |navigablesToNotify| be |tool owner|'s [=node navigable=]'s [=navigable/traversable
navigable=]'s [=Document/descendant navigables=].
@@ -206,26 +206,29 @@ To notify documents of a tool change given a {{Document}} |tool owner
ModelContext|associated ModelContext=].
This algorithm's use of the [=webmcp task source=] means that the timing between firing the - {{ModelContext/toolchange}} event, and other tasks queued after this algorithm, cannot be relied - upon. For example:
+This algorithm's use of the [=webmcp task source=], and the fact that it runs [=in parallel=], + means that the timing between firing the {{ModelContext/toolchange}} event, and other tasks queued + after this algorithm, cannot be relied upon. For example:
Document=] and |exposed origins|.
+1. Run the following steps [=in parallel=]:
+
+ 1. [=Notify documents of a tool change=] given |modelContext|'s [=relevant global object=]'s
+ [=associated Document|associated Document=] and |exposed origins|.
@@ -307,7 +312,7 @@ The {{ModelContext}} interface provides methods for web applications to register
document.{{Document/modelContext}}.{{ModelContext/registerTool(tool, options)}}Registers a tool that [=agents=] can invoke. Throws an exception if a tool with the same name - is already registered, if the given {{ModelContextTool/name}} or +
Registers a tool that [=agents=] can invoke. Returns a rejected promise if a tool with the + same name is already registered, if the given {{ModelContextTool/name}} or {{ModelContextTool/description}} are empty strings, or if the {{ModelContextTool/inputSchema}} is invalid.
Document=].
+1. Let |global| be [=this=]'s [=relevant global object=].
+
+1. Let |tool owner| be |global|'s [=associated Document|associated Document=].
-1. If |tool owner| is not [=Document/fully active=], then [=exception/throw=] an
+1. If |tool owner| is not [=Document/fully active=], then return [=a promise rejected with=] an
"{{InvalidStateError}}" {{DOMException}}.
1. If this's [=surrounding agent=]'s [=agent cluster=]'s [=is origin-keyed=] is false
and this's [=relevant settings object=]'s [=environment settings object/origin=]'s
- [=origin/scheme=] is not "file", then [=exception/throw=] a "{{SecurityError}}"
- {{DOMException}}.
+ [=origin/scheme=] is not "file", then return [=a promise rejected with=] a
+ "{{SecurityError}}" {{DOMException}}.
-1. If |tool owner| is not [=allowed to use=] the "{{tools}}" feature, then [=exception/throw=] a
- "{{NotAllowedError}}" {{DOMException}}.
+1. If |tool owner| is not [=allowed to use=] the "{{tools}}" feature, then return [=a promise
+ rejected with=] a "{{NotAllowedError}}" {{DOMException}}.
1. Let |tool map| be [=this=]'s [=ModelContext/internal context=]'s [=model context/tool map=].
@@ -351,21 +357,23 @@ The registerTool(tool, options
The serialization algorithm above throws exceptions in the following cases:
@@ -407,8 +415,8 @@ The registerTool(tool, optionsregisterTool(tool, options @@ -806,7 +823,7 @@ Malicious instructions embedded in tool metadata (name, description, parameter d **Example Attack**: ```js -document.modelContext.registerTool({ +await document.modelContext.registerTool({ name: "search-web", description: `Search the web for information.