Skip to main content

Tools

Tools are the primary way to expose functionality in an MCP server. They represent actions that an AI assistant can invoke.

Basic Tool

Use the @Tool decorator to expose a method as a tool:

import 'reflect-metadata';
import { createServer, MCPServer, Tool, Param } from '@mcpkit-dev/core';

@MCPServer({ name: 'my-server', version: '1.0.0' })
class MyServer {
@Tool({ description: 'Add two numbers together' })
async add(
@Param({ name: 'a', description: 'First number' }) a: number,
@Param({ name: 'b', description: 'Second number' }) b: number
): Promise<number> {
return a + b;
}
}

const server = createServer(MyServer);
await server.listen();

Tool Options

@Tool({
// Required: Description shown to the AI
description: 'Fetch user data from the database',

// Optional: Custom tool name (defaults to method name)
name: 'fetch_user',

// Optional: Explicit Zod schema for parameters
schema: z.object({
userId: z.string().uuid(),
includeProfile: z.boolean().optional(),
}),

// Optional: Tool annotations for AI behavior hints
annotations: {
destructive: false, // Does this tool modify data?
requiresConfirmation: false, // Should the AI ask before executing?
cacheable: true, // Can results be cached?
},
})
async fetchUser(args: { userId: string; includeProfile?: boolean }) {
// implementation
}

Parameter Types

Using @Param Decorator

The @Param decorator allows fine-grained control over parameters:

@Tool({ description: 'Create a user' })
async createUser(
// Required parameter
@Param({
name: 'name',
description: 'User full name',
})
name: string,

// Optional parameter with default
@Param({
name: 'role',
description: 'User role',
optional: true,
})
role: 'admin' | 'user' = 'user',

// Parameter with explicit schema
@Param({
name: 'age',
schema: z.number().min(18).max(120),
})
age: number
): Promise<User> {
// implementation
}

Using Zod Schema

For complex parameter validation, use a Zod schema:

import { z } from 'zod';

const CreateUserSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
age: z.number().int().min(18),
role: z.enum(['admin', 'user', 'moderator']).default('user'),
settings: z.object({
notifications: z.boolean().default(true),
theme: z.enum(['light', 'dark']).default('light'),
}).optional(),
});

@Tool({
description: 'Create a new user account',
schema: CreateUserSchema,
})
async createUser(args: z.infer<typeof CreateUserSchema>) {
const { name, email, age, role, settings } = args;
// implementation
}

Return Types

Tools can return various types:

String Response

@Tool({ description: 'Greet user' })
async greet(@Param({ name: 'name' }) name: string): Promise<string> {
return `Hello, ${name}!`;
}

Object Response

Objects are automatically serialized to JSON:

@Tool({ description: 'Get user' })
async getUser(@Param({ name: 'id' }) id: string): Promise<User> {
return {
id,
name: 'John Doe',
email: 'john@example.com',
};
}

MCP Tool Result

For full control over the response:

import { ToolResult } from '@mcpkit-dev/core';

@Tool({ description: 'Process image' })
async processImage(
@Param({ name: 'url' }) url: string
): Promise<ToolResult> {
const image = await fetchImage(url);

return {
content: [
{
type: 'text',
text: 'Image processed successfully',
},
{
type: 'image',
data: image.base64,
mimeType: 'image/png',
},
],
};
}

Error Handling

Errors are automatically caught and returned as tool errors:

@Tool({ description: 'Fetch user' })
async fetchUser(@Param({ name: 'id' }) id: string) {
const user = await db.users.findById(id);

if (!user) {
throw new Error(`User ${id} not found`);
}

return user;
}

For custom error handling:

import { ToolExecutionError } from '@mcpkit-dev/core';

@Tool({ description: 'Transfer funds' })
async transfer(
@Param({ name: 'from' }) from: string,
@Param({ name: 'to' }) to: string,
@Param({ name: 'amount' }) amount: number
) {
if (amount <= 0) {
throw new ToolExecutionError('Amount must be positive');
}

// implementation
}

Protected Tools

Use @RequireAuth to protect tools:

import { RequireAuth } from '@mcpkit-dev/core';

@Tool({ description: 'Delete user' })
@RequireAuth({ roles: ['admin'] })
async deleteUser(@Param({ name: 'id' }) id: string) {
await db.users.delete(id);
return { deleted: true };
}

Monitored Tools

Add logging with @Monitor:

import { Monitor } from '@mcpkit-dev/core';

@Tool({ description: 'Process payment' })
@Monitor({
logArgs: true,
logResult: true,
logDuration: true,
})
async processPayment(@Param({ name: 'amount' }) amount: number) {
// Execution will be logged
return { success: true };
}

Traced Tools

Add distributed tracing with @Traced:

import { Traced } from '@mcpkit-dev/core';

@Tool({ description: 'External API call' })
@Traced({
name: 'external.api.call',
kind: 'client',
attributes: { 'api.name': 'payment-service' },
})
async callExternalApi(@Param({ name: 'data' }) data: string) {
return await externalApi.call(data);
}