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

# Tools

> Design and register MCP tools with validated inputs and typed results.

Tools let a model call server-side code. Give each tool a focused description,
validate its input, declare its behavioral annotations, and return an official
MCP `CallToolResult`.

## Register a tool

`inputSchema` accepts a Standard Schema implementation that can produce JSON
Schema. Zod is one option; ArkType and Valibot are also supported.

```typescript theme={null}
import { MCPServer } from "mcp-use";
import { z } from "zod";

const server = new MCPServer({
  name: "inventory-server",
  version: "1.0.0",
});

server.tool(
  {
    name: "lookup-inventory",
    description: "Return available inventory for one SKU.",
    inputSchema: z.object({
      sku: z.string().describe("Inventory SKU"),
    }),
    annotations: {
      readOnlyHint: true,
      destructiveHint: false,
      openWorldHint: true,
    },
  },
  async ({ sku }) => {
    const count = await inventory.count(sku);
    return {
      content: [{ type: "text", text: `${count} units available.` }],
    };
  },
);

export default server;
```

Field descriptions become hints for clients and models. The schema validates
input before the callback runs and supplies the callback's inferred TypeScript
type.

## Add tool icons

Set `icons` on the tool definition to advertise artwork on `tools/list`.
The field uses the exported MCP `Icon` type: `src`, optional `mimeType`, optional `sizes`, and optional `theme` (`"light"` or `"dark"`).
The SDK preserves icon order and these fields.

```typescript theme={null}
server.tool(
  {
    name: "open_catalog",
    title: "Catalog",
    icons: [
      { src: "catalog.svg", mimeType: "image/svg+xml", sizes: ["20x20"] },
    ],
  },
  () => ({ content: [{ type: "text", text: "Catalog is ready." }] }),
);
```

Put local files under `public/` and use a path relative to that directory.
For HTTP requests, the SDK emits an absolute URL under `<basePath>/_mcp-use/public/`.
Absolute HTTP(S) and image data URLs pass through unchanged.
Tools mounted with `server.proxy()` retain their upstream icons.

Omit `icons` to leave the tool without its own artwork; an explicit empty array stays empty.
Server constructor `icons` continues to describe server branding.
For ChatGPT launchers, add icons directly to the entrypoint tool and follow the
[entrypoint icon guide](/v2/typescript/mcp-apps/chatgpt-extensions#set-entrypoint-tool-icons).

## Return structured output

Declare `outputSchema` when clients need a typed structured result. Every
successful result from a schema-backed tool must include matching
`structuredContent`. An error result may instead set `isError: true`.

```typescript theme={null}
const availabilitySchema = z.object({
  sku: z.string(),
  available: z.number().int(),
});

server.tool(
  {
    name: "inventory-status",
    inputSchema: z.object({ sku: z.string() }),
    outputSchema: availabilitySchema,
  },
  async ({ sku }) => {
    const data = { sku, available: await inventory.count(sku) };
    return {
      content: [{ type: "text", text: JSON.stringify(data) }],
      structuredContent: data,
    };
  },
);
```

Prefer raw results:

| Need | Return |
| - | - |
| Text | `{ content: [{ type: "text", text }] }` |
| Typed JSON | `{ content, structuredContent: data }` with `outputSchema` |
| Expected failure | `{ isError: true, content: [{ type: "text", text }] }` |
| Several blocks | `{ content: [/* content blocks */] }` |

## Bind a View

Export the tool reference from the server entry so `mcp-env.d.ts` can expose
its input and output types to View code. Place the React entry at
`views/<name>/view.tsx`, set `view.name` to that directory name, and return its
data in `structuredContent`.

```typescript theme={null}
export const searchProducts = server.tool(
  {
    name: "search-products",
    inputSchema: z.object({ query: z.string() }),
    outputSchema: z.object({
      query: z.string(),
      results: z.array(z.object({ id: z.string(), name: z.string() })),
    }),
    view: { name: "product-search-result" },
  },
  async ({ query }) => {
    const data = { query, results: await products.search(query) };
    return {
      content: [
        { type: "text", text: `Found ${data.results.length} products.` },
      ],
      structuredContent: data,
    };
  },
);
```

A view-bound tool must declare `outputSchema`, and one View can bind to only
one tool. The view reads the structured data while the model reads `content`.

## Use request context

The second callback argument is scoped to the current request. It includes an
abort signal, client-reported capability metadata, progress and logging
methods, and the originating Hono request when HTTP context exists.

```typescript theme={null}
server.tool({ name: "request-info" }, async (_input, ctx) => {
  const data = {
    client: ctx.client.info().name ?? "unknown",
    supportsViews: ctx.client.supportsViews(),
    aborted: ctx.signal.aborted,
  };
  return {
    content: [{ type: "text", text: JSON.stringify(data) }],
    structuredContent: data,
  };
});
```

Client metadata is self-reported and must not be used for authorization.
`ctx.auth` is available only when the server has an OAuth provider; use its
verified provider user for access control. On a server with
`mixedAuth: true`, a tool's `securitySchemes` field marks it public
(`noauth`), optional (`noauth` and `oauth2`), or sign-in with extra `scopes`;
see
[Mixed Authentication](/v2/typescript/server/authentication/mixed-auth).

## Notify tool-list listeners

Publish a tool-list invalidation when the tools clients can discover have
changed:

```typescript theme={null}
await server.notifyToolsChanged();
```

Clients with an active subscription listener can then request `tools/list`
again. This notification does not register or replace tools; register tools
while constructing the server, before it starts handling requests.

## Test tools

Run `mcp-use dev`, open the built-in inspector, and test valid inputs, schema
failures, error results, and structured output:

```bash theme={null}
npx mcp-use dev
```

For view-bound tools, also verify that the View renders the returned
`structuredContent`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.