Skip to content

Commit 93ed252

Browse files
committed
Add getTools()
1 parent 8aecdb8 commit 93ed252

1 file changed

Lines changed: 177 additions & 1 deletion

File tree

index.bs

Lines changed: 177 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ The {{ModelContext}} interface provides methods for web applications to register
314314
[Exposed=Window, SecureContext]
315315
interface ModelContext : EventTarget {
316316
Promise<undefined> registerTool(ModelContextTool tool, optional ModelContextRegisterToolOptions options = {});
317+
Promise<sequence<RegisteredTool>> getTools(optional ModelContextGetToolOptions options = {});
317318

318319
attribute EventHandler ontoolchange;
319320
};
@@ -331,6 +332,12 @@ is a [=model context=] [=struct=] created alongside the {{ModelContext}}.
331332
{{ModelContextTool/description}} are empty strings, or if the {{ModelContextTool/inputSchema}}
332333
is invalid.</p>
333334
</dd>
335+
336+
<dt><code><var ignore>document</var>.{{Document/modelContext}}.{{ModelContext/getTools(options)}}</code></dt>
337+
<dd>
338+
<p>Returns a promise that resolves to a list of registered tools from this document and its
339+
descendants that are exposed to this document.</p>
340+
</dd>
334341
</dl>
335342

336343

@@ -464,6 +471,112 @@ The <dfn method for=ModelContext>registerTool(<var>tool</var>, <var>options</var
464471

465472
</div>
466473

474+
<div algorithm>
475+
The <dfn method for=ModelContext>getTools(<var>options</var>)</dfn> method steps are:
476+
477+
1. Let |global| be [=this=]'s [=relevant global object=].
478+
479+
1. Let |tool owner| be |global|'s [=associated Document|associated <code>Document</code>=].
480+
481+
1. If |tool owner| is not [=Document/fully active=], then return [=a promise rejected with=] an
482+
"{{InvalidStateError}}" {{DOMException}}.
483+
484+
1. If this's [=surrounding agent=]'s [=agent cluster=]'s [=is origin-keyed=] is false and this's
485+
[=relevant settings object=]'s [=environment settings object/origin=]'s [=origin/scheme=] is not
486+
<code>"file"</code>, then return [=a promise rejected with=] a "{{SecurityError}}"
487+
{{DOMException}}.
488+
489+
1. If |tool owner| is not [=allowed to use=] the "{{tools}}" feature, then return [=a promise
490+
rejected with=] a "{{NotAllowedError}}" {{DOMException}}.
491+
492+
1. Let |from origins| be an empty [=list=] of [=origins=].
493+
494+
1. If |options|'s {{ModelContextGetToolOptions/fromOrigins}} [=map/exists=], then:
495+
496+
1. [=list/For each=] |origin| of |options|'s {{ModelContextGetToolOptions/fromOrigins}}:
497+
498+
1. Let |parsedURL| be the result of running the [=URL parser=] on |origin|.
499+
500+
1. If |parsedURL| is failure or its [=url/origin=] is not [$is origin potentially
501+
trustworthy?|potentially trustworthy$], then return [=a promise rejected with=] a
502+
"{{SecurityError}}" {{DOMException}}.
503+
504+
1. [=list/Append=] |parsedURL|'s [=url/origin=] to |from origins|.
505+
506+
1. Let |promise| be [=a new promise=] created in [=this=]'s [=relevant realm=].
507+
508+
1. Run the following steps [=in parallel=]:
509+
510+
1. Let |tools| be an empty [=list=] of {{RegisteredTool}} dictionaries.
511+
512+
1. Let |navigables| be |tool owner|'s [=node navigable=]'s [=navigable/traversable navigable=]'s
513+
[=Document/inclusive descendant navigables=].
514+
515+
1. [=list/For each=] |navigable| of |navigables|:
516+
517+
1. Let |targetDocument| be |navigable|'s [=navigable/active document=].
518+
519+
1. If |targetDocument| is not [=allowed to use=] the "{{tools}}" feature, then
520+
[=iteration/continue=].
521+
522+
1. Let |targetOrigin| be |targetDocument|'s [=Document/origin=].
523+
524+
1. Let |callerOrigin| be |tool owner|'s [=Document/origin=].
525+
526+
1. Let |is visible to caller| be true if |targetOrigin| is [=same origin=] with
527+
|callerOrigin|, or if |from origins| [=list/contains=] |targetOrigin|. Otherwise, let it be
528+
false.
529+
530+
1. If |is visible to caller| is false, then [=iteration/continue=].
531+
532+
1. Let |targetToolMap| be |targetDocument|'s [=Document/associated ModelContext|associated
533+
<code>ModelContext</code>=]'s [=ModelContext/internal context=]'s [=model context/tool
534+
map=].
535+
536+
1. [=map/For each=] <var ignore>tool name</var> → |tool definition| of |targetToolMap|:
537+
538+
1. If [=tool is visible to an origin=] given |targetOrigin|, |tool definition|'s [=tool
539+
definition/exposed origins=], and |callerOrigin| is false, then [=iteration/continue=].
540+
541+
1. Let |registeredTool| be a new {{RegisteredTool}} dictionary, with the following fields:
542+
543+
: {{RegisteredTool/name}}
544+
:: |tool definition|'s [=tool definition/name=]
545+
546+
: {{RegisteredTool/title}}
547+
:: |tool definition|'s [=tool definition/title=]
548+
549+
: {{RegisteredTool/description}}
550+
:: |tool definition|'s [=tool definition/description=]
551+
552+
: {{RegisteredTool/inputSchema}}
553+
:: |tool definition|'s [=tool definition/input schema=] if it is not the empty string;
554+
otherwise undefined.
555+
556+
: {{RegisteredTool/window}}
557+
:: |targetDocument|'s [=relevant global object=]
558+
559+
: {{RegisteredTool/origin}}
560+
:: |targetOrigin|, [=serialization of an origin|serialized=].
561+
562+
: {{RegisteredTool/annotations}}
563+
:: A new {{ToolAnnotations}} dictionary whose {{ToolAnnotations/readOnlyHint}} is |tool
564+
definition|'s [=tool definition/read-only hint=] and
565+
{{ToolAnnotations/untrustedContentHint}} is |tool definition|'s [=tool
566+
definition/untrusted content hint=].
567+
568+
1. [=list/Append=] |registeredTool| to |tools|.
569+
570+
1. [=list/Sort in ascending order=] |tools|, with |a| being less than |b| if
571+
|a|["{{RegisteredTool/name}}"] is [=code unit less than=] |b|["{{RegisteredTool/name}}"].
572+
573+
1. [=Queue a global task=] on the [=webmcp task source=] given |global| to [=resolve=] |promise|
574+
with |tools|.
575+
576+
1. Return |promise|.
577+
578+
</div>
579+
467580
<h4 id="model-context-tool">ModelContextTool Dictionary</h4>
468581

469582
The {{ModelContextTool}} dictionary describes a tool that can be invoked by [=agents=].
@@ -508,7 +621,8 @@ callback ToolExecuteCallback = Promise<any> (object input);
508621

509622
<dt><code><var ignore>tool</var>["{{ModelContextTool/inputSchema}}"]</code></dt>
510623
<dd>
511-
<p>A JSON Schema [[!JSON-SCHEMA]] object describing the expected input parameters for the tool.
624+
<p>A stringified JSON Schema object describing the expected input parameters for the tool
625+
[[!JSON-SCHEMA]].
512626
</dd>
513627

514628
<dt><code><var ignore>tool</var>["{{ModelContextTool/execute}}"]</code></dt>
@@ -556,6 +670,68 @@ dictionary ModelContextRegisterToolOptions {
556670
:: <p>An array of origins that control which documents this tool is exposed to, in the current document's tree.
557671
</dl>
558672

673+
<h4 id="model-context-get-tool-options">ModelContextGetToolOptions Dictionary</h4>
674+
675+
The {{ModelContextGetToolOptions}} dictionary allows web applications to filter the tools returned
676+
by {{ModelContext/getTools()}}.
677+
678+
<xmp class="idl">
679+
dictionary ModelContextGetToolOptions {
680+
sequence<USVString> fromOrigins;
681+
};
682+
</xmp>
683+
684+
<dl class="domintro">
685+
: <code><var ignore>options</var>["{{ModelContextGetToolOptions/fromOrigins}}"]</code>
686+
:: An array of origins from which to list tools. When this array is empty or omitted, only tools
687+
exposed to documents that are same-origin with the caller of {{ModelContext/getTools()}} are
688+
included in the result.
689+
</dl>
690+
691+
<h4 id="registered-tool">RegisteredTool Dictionary</h4>
692+
693+
The {{RegisteredTool}} dictionary represents a tool that has been registered and is available for
694+
invocation.
695+
696+
<xmp class="idl">
697+
dictionary RegisteredTool {
698+
required DOMString name;
699+
required DOMString description;
700+
DOMString inputSchema;
701+
// `title` can be exposed as a `DOMString` since it was taken in by a
702+
// `USVString`, meaning all unmatched surrogate processing has already been
703+
// done, and there's no need to do it again on tool exposure.
704+
DOMString title;
705+
required Window window;
706+
required USVString origin;
707+
ToolAnnotations annotations;
708+
};
709+
</xmp>
710+
711+
<dl class="domintro">
712+
: <code><var ignore>tool</var>["{{RegisteredTool/name}}"]</code>
713+
:: A unique identifier for the tool.
714+
715+
: <code><var ignore>tool</var>["{{RegisteredTool/description}}"]</code>
716+
:: A natural language description of the tool's functionality.
717+
718+
: <code><var ignore>tool</var>["{{RegisteredTool/inputSchema}}"]</code>
719+
:: A stringified JSON Schema object describing the expected input parameters for the tool
720+
[[!JSON-SCHEMA]].
721+
722+
: <code><var ignore>tool</var>["{{RegisteredTool/title}}"]</code>
723+
:: A human-readable label for the tool.
724+
725+
: <code><var ignore>tool</var>["{{RegisteredTool/window}}"]</code>
726+
:: The {{Window}} of the document that registered the tool.
727+
728+
: <code><var ignore>tool</var>["{{RegisteredTool/origin}}"]</code>
729+
:: The origin of the document that registered the tool.
730+
731+
: <code><var ignore>tool</var>["{{RegisteredTool/annotations}}"]</code>
732+
:: Optional annotations providing metadata about the tool.
733+
</dl>
734+
559735

560736
<h3 id="declarative-api">Declarative WebMCP</h3>
561737

0 commit comments

Comments
 (0)