---
title: "Tools"
description: "Create MCP tools with Zod validation and type safety."
canonical_url: "https://mcp-toolkit.nuxt.dev/tools/overview"
---
# Tools

> Create MCP tools with Zod validation and type safety.

## What are Tools?

Tools are functions that AI assistants can call to perform actions or retrieve information. They accept validated input parameters and return structured results.

<prompt :actions="["copy","cursor","windsurf"]" description="Scaffold a new MCP tool" icon="i-lucide-wrench">

Create a new MCP tool in my Nuxt app using @nuxtjs/mcp-toolkit.

- Create a file in server/mcp/tools/ (e.g. server/mcp/tools/my-tool.ts)
- Use defineMcpTool (auto-imported) with a description and handler
- Import Zod with `import { z } from 'zod'` and define input parameters in inputSchema (e.g. z.string().describe('...'))
- The handler receives validated input and returns a string, number, boolean, object, or full CallToolResult
- Throw errors with createError({ statusCode, message }) from h3 for error cases
- Name and title are auto-generated from the filename (e.g. my-tool.ts → name: 'my-tool', title: 'My Tool')
- Add annotations for behavioral hints (readOnlyHint, destructiveHint, idempotentHint, openWorldHint)
- Use subdirectories to auto-infer groups (e.g. tools/admin/delete-user.ts → group: 'admin')

Docs: [https://mcp-toolkit.nuxt.dev/tools/overview](https://mcp-toolkit.nuxt.dev/tools/overview)

</prompt>

## Basic Tool Definition

Here's a simple tool that echoes back a message:

```typescript [server/mcp/tools/echo.ts]
import { z } from 'zod'
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpTool({
  name: 'echo',
  description: 'Echo back a message',
  inputSchema: {
    message: z.string().describe('The message to echo back'),
  },
  handler: async ({ message }) => `Echo: ${message}`,
})
```

## Auto-Generated Name and Title

You can omit `name` and `title` - they will be automatically generated from the filename:

```typescript [server/mcp/tools/list-documentation.ts]
import { defineMcpTool } from '@nuxtjs/mcp-toolkit/server'

export default defineMcpTool({
  // name and title are auto-generated from filename:
  // name: 'list-documentation'
  // title: 'List Documentation'
  description: 'List all documentation files',
  handler: async () => {
    // ...
  },
})
```

The filename `list-documentation.ts` automatically becomes:

- `name`: `list-documentation` (kebab-case)
- `title`: `List Documentation` (title case)

You can still provide `name` or `title` explicitly to override the auto-generated values.

## Tool Structure

A tool definition consists of:

<code-group>

```typescript [Required Fields]
export default defineMcpTool({
  name: 'tool-name',        // Unique identifier (optional - auto-generated from filename)
  inputSchema: { ... },      // Zod schema for input validation
  handler: async (args) => {
    return 'result'          // string, number, boolean, object, or CallToolResult
  },
})
```

```typescript [Optional Fields]
export default defineMcpTool({
  name: 'tool-name',              // Optional - auto-generated from filename
  title: 'Tool Title',            // Optional - auto-generated from filename
  description: 'Tool description',  // What the tool does
  inputSchema: { ... },            // Optional - Zod schema for input validation
  outputSchema: { ... },            // Zod schema for structured output
  annotations: { ... },             // Behavioral hints for clients
  inputExamples: [{ ... }],         // Concrete usage examples
  handler: async (args) => { ... },
})
```

</code-group>

## Going further

Once you've authored a few tools, branch out:

<card-group>
<card color="neutral" icon="i-lucide-globe" title="Integrate external APIs" to="https://mcp-toolkit.nuxt.dev/examples/api-integration">

Call third-party services, use `useEvent()`, and cache responses with Nitro.

</card>

<card color="neutral" icon="i-lucide-shield-check" title="Authenticate clients" to="https://mcp-toolkit.nuxt.dev/examples/authentication">

Bearer tokens, Better Auth API keys, and per-tool `enabled` guards.

</card>

<card color="neutral" icon="i-lucide-terminal" title="Use Code Mode" to="https://mcp-toolkit.nuxt.dev/advanced/code-mode">

Let the LLM orchestrate multiple tool calls in a single sandboxed JS execution.

</card>

<card color="neutral" icon="i-lucide-network" title="Multi-handler organization" to="https://mcp-toolkit.nuxt.dev/handlers/organization">

Attribute tools to dedicated MCP routes via the `handlers/<name>/` folder convention.

</card>
</card-group>

---

- [Schema & handler](https://mcp-toolkit.nuxt.dev/tools/schema-handler)
- [Annotations](https://mcp-toolkit.nuxt.dev/tools/annotations)
- [Errors & caching](https://mcp-toolkit.nuxt.dev/tools/errors-caching)
- [Groups & advanced](https://mcp-toolkit.nuxt.dev/tools/groups-organization)


## Sitemap

See the full [sitemap](https://mcp-toolkit.nuxt.dev/sitemap.md) for all pages.
