> ## Documentation Index
> Fetch the complete documentation index at: https://sunpeak.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Apps onlisttools - Declare App-Side Tools

> Declare the tools an MCP App View provides to the host. Return tool definitions so the host and model can discover and call them.

<Badge color="green">MCP Apps SDK</Badge>

```ts theme={null}
import { App } from "@modelcontextprotocol/ext-apps";
```

## Overview

`onlisttools` is a request handler that returns the list of tools your app provides to the host. The host calls this to discover what tools are available, then invokes them through [`oncalltool`](/mcp-apps/app/event-handlers/oncalltool).

To use `onlisttools`, you must declare the `tools` capability when constructing the `App`. If you set `listChanged: true`, the host will re-query this handler whenever you send a tool list changed notification, allowing your app to dynamically add or remove tools at runtime.

Because this is a **request** handler, the host waits for your response. Return an object with a `tools` array containing the tool names or definitions your app supports.

## Signature

```ts theme={null}
app.onlisttools = async (params, extra) => Promise<ListToolsResult>;
```

## Parameters

<ResponseField name="params" type="ListToolsRequest['params']">
  Standard MCP list tools request parameters (includes optional `cursor` for pagination).
</ResponseField>

## Returns

<ResponseField name="result" type="ListToolsResult">
  <ResponseField name="tools" type="Tool[]" required>
    Array of tool definitions. Each tool must have a `name` and `inputSchema` (with `type: "object"`). Optional fields: `description`, `annotations`.
  </ResponseField>
</ResponseField>

<Warning>
  Register handlers **before** calling `connect()` to avoid missing notifications during the initialization handshake.
</Warning>

## Usage

### Static tool list

```ts theme={null}
const app = new App(
  { name: "MyApp", version: "1.0.0" },
  { tools: { listChanged: true } },
);

app.onlisttools = async () => {
  return {
    tools: [
      { name: "get-selection", inputSchema: { type: "object" } },
      { name: "format-text", inputSchema: { type: "object" } },
    ],
  };
};

await app.connect();
```

### Dynamic tools based on app state

When `listChanged: true` is set, the host will re-query `onlisttools` after receiving a list-changed notification. This lets you add or remove tools based on the current state of your app:

```ts theme={null}
let hasSelection = false;

app.onlisttools = async () => {
  const tools = [
    { name: "format-text", inputSchema: { type: "object" } },
  ];
  if (hasSelection) {
    tools.push({ name: "get-selection", inputSchema: { type: "object" } });
  }
  return { tools };
};

document.addEventListener("selectionchange", () => {
  const newHasSelection = !!window.getSelection()?.toString();
  if (newHasSelection !== hasSelection) {
    hasSelection = newHasSelection;
    // Notify the host to re-query the tool list
    app.sendToolListChanged();
  }
});

await app.connect();
```

### Pair with oncalltool

The tools declared here must be handled in [`oncalltool`](/mcp-apps/app/event-handlers/oncalltool):

```ts theme={null}
app.onlisttools = async () => {
  return {
    tools: [
      { name: "get-selection", inputSchema: { type: "object" } },
      { name: "format-text", inputSchema: { type: "object" } },
    ],
  };
};

app.oncalltool = async (params) => {
  switch (params.name) {
    case "get-selection":
      return { content: [{ type: "text", text: getSelectedText() }] };
    case "format-text":
      return { content: [{ type: "text", text: formatText(params.arguments) }] };
    default:
      throw new Error(`Unknown tool: ${params.name}`);
  }
};

await app.connect();
```

## Related

* [App Tools guide](/mcp-apps/app/app-tools) -- end-to-end pattern for registering tools and handling host calls
* [Event Handlers overview](/mcp-apps/app/event-handlers) -- all notification and request handlers
* [`oncalltool`](/mcp-apps/app/event-handlers/oncalltool) -- handle incoming tool calls
* [`useAppTools`](/app-framework/hooks/use-app-tools) -- sunpeak React convenience hook for app-side tools
* [App Class constructor](/mcp-apps/app/app-class#constructor) -- declaring `tools` capability
