---
description: "Lists the WebMCP tools registered on this page right now, as a model reads them."
---

# `listToolDescriptors`

Lists the WebMCP tools registered on this page right now, as a model reads them. Use it in an adapter or a request of your own that does not go through the session.

## Import

```ts
import { listToolDescriptors } from "@webmcp-agents/chat";
import type { ToolDescriptor } from "@webmcp-agents/chat";
```

## Example

Send the page's current tools with a chat request.

```ts title="list-tools.ts"
import { listToolDescriptors } from "@webmcp-agents/chat";

// The tools on this page right now, as a model reads them.
const tools = await listToolDescriptors();

const res = await fetch("/api/chat", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    messages: [
      {
        id: "u-1",
        role: "user",
        parts: [{ type: "text", text: "Hi" }],
      },
    ],
    tools,
    page: { url: location.href },
  }),
});
console.log(res.status);
```

## Options

None. `listToolDescriptors()` takes no arguments and reads `document.modelContext` at the moment you call it.

## Returns

A `Promise<ToolDescriptor[]>` from `document.modelContext.getTools()`. A [`ToolDescriptor`](/docs/reference/chat/adapter-types#tooldescriptor-and-tooloutput) is `{ name, description, inputSchema }`.

- Tools whose `origin` is another origin are left out (Chrome reports where a tool lives).
- `description` falls back to the tool's `title`, then its `name`.
- `inputSchema` is parsed when it is a JSON string. A missing or unreadable schema becomes `{ type: "object", properties: {} }`.
- Without `document.modelContext` (no WebMCP, or on the server) it resolves to `[]`.

## Notes

- Tools change as the page changes (a route swaps, a form hides itself). Read the list again before every model call; [`useAgentSession`](/docs/reference/chat/use-agent-session) refreshes it on every `toolchange` and after each tool call.
- It rejects if `getTools()` rejects; `useAgentSession` treats that as an empty list.

## See also

- [Add the chat](/docs/build/add-the-chat)
- [`callModelContextTool`](/docs/reference/chat/call-model-context-tool)
- [`ToolDescriptor`](/docs/reference/chat/adapter-types#tooldescriptor-and-tooloutput)
- [`inspectTools`](/docs/reference/core/inspect-tools), where each tool's cursor would go
