The server package provides five method decorators for declaring MCP handlers: @Tool, @Resource, @ResourceTemplate, @Prompt, and @Completion. All are applied to methods on NestJS @Injectable() providers.
Declares a method as an MCP tool handler.
import { Injectable } from '@nestjs/common';
import { Tool } from '@nest-mcp/server';
import { z } from 'zod';
import type { McpExecutionContext } from '@nest-mcp/common';
@Injectable()
export class MathService {
@Tool({
name: 'multiply',
description: 'Multiply two numbers',
parameters: z.object({
a: z.number().describe('First factor'),
b: z.number().describe('Second factor'),
}),
})
async multiply(args: { a: number; b: number }, ctx: McpExecutionContext) {
return { content: [{ type: 'text', text: String(args.a * args.b) }] };
}
}| Option | Type | Required | Description |
|---|---|---|---|
name |
string |
No | Tool name (defaults to the method name) |
title |
string |
No | Human-readable display title |
description |
string |
Yes | Tool description for the AI client |
parameters |
ZodType |
No | Zod schema for input validation |
outputSchema |
ZodType |
No | Zod schema describing the output |
annotations |
ToolAnnotations |
No | Behavioral hints for the client |
icons |
Icon[] |
No | Icons for UI display |
execution |
ToolExecution |
No | Execution hints (e.g., task support) |
_meta |
Record<string, unknown> |
No | Opaque metadata passed through to clients |
@Tool({
name: 'delete-file',
description: 'Delete a file from the filesystem',
parameters: z.object({ path: z.string() }),
annotations: {
destructiveHint: true,
readOnlyHint: false,
idempotentHint: true,
},
})| Annotation | Type | Description |
|---|---|---|
title |
string |
Display title |
readOnlyHint |
boolean |
Tool only reads data |
destructiveHint |
boolean |
Tool performs destructive operations |
idempotentHint |
boolean |
Calling multiple times has same effect |
openWorldHint |
boolean |
Tool interacts with the outside world |
streamingHint |
boolean |
Tool emits incremental content via streamContent |
Tool handlers receive two arguments:
args-- Validated input parametersctx--McpExecutionContextwith session info, user, logging, progress reporting, etc.
The return value is automatically normalized (see Getting Started).
Declares a method as an MCP resource handler.
import { Injectable } from '@nestjs/common';
import { Resource } from '@nest-mcp/server';
@Injectable()
export class DataService {
@Resource({
uri: 'data://users/count',
name: 'user-count',
description: 'Total number of registered users',
mimeType: 'text/plain',
})
async getUserCount() {
return '42';
}
}| Option | Type | Required | Description |
|---|---|---|---|
uri |
string |
Yes | Resource URI |
name |
string |
No | Resource name (defaults to method name) |
title |
string |
No | Human-readable display title |
description |
string |
No | Resource description |
mimeType |
string |
No | MIME type of the resource content |
icons |
Icon[] |
No | Icons for UI display |
_meta |
Record<string, unknown> |
No | Opaque metadata |
Resource handlers receive:
uri--URLobject of the requested resourcectx--McpExecutionContext
Declares a method as an MCP resource template handler. Templates use URI patterns with parameters.
import { Injectable } from '@nestjs/common';
import { ResourceTemplate } from '@nest-mcp/server';
@Injectable()
export class UserService {
@ResourceTemplate({
uriTemplate: 'users://{userId}/profile',
name: 'user-profile',
description: 'User profile by ID',
mimeType: 'application/json',
})
async getProfile(uri: URL, params: { userId: string }) {
return JSON.stringify({ id: params.userId, name: 'Alice' });
}
}| Option | Type | Required | Description |
|---|---|---|---|
uriTemplate |
string |
Yes | URI template with {param} placeholders |
name |
string |
No | Template name (defaults to method name) |
title |
string |
No | Human-readable display title |
description |
string |
No | Template description |
mimeType |
string |
No | MIME type of the resource content |
icons |
Icon[] |
No | Icons for UI display |
_meta |
Record<string, unknown> |
No | Opaque metadata |
Resource template handlers receive:
uri--URLobject of the resolved URIparams-- Extracted template parameters as a key-value objectctx--McpExecutionContext
Declares a method as an MCP prompt handler.
import { Injectable } from '@nestjs/common';
import { Prompt } from '@nest-mcp/server';
import { z } from 'zod';
@Injectable()
export class PromptService {
@Prompt({
name: 'code-review',
description: 'Generate a code review prompt',
parameters: z.object({
language: z.string().describe('Programming language'),
code: z.string().describe('Code to review'),
}),
})
async codeReview(args: { language: string; code: string }) {
return {
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Review this ${args.language} code:\n\n${args.code}`,
},
},
],
};
}
}| Option | Type | Required | Description |
|---|---|---|---|
name |
string |
No | Prompt name (defaults to method name) |
title |
string |
No | Human-readable display title |
description |
string |
No | Prompt description |
parameters |
ZodObject |
No | Zod schema for prompt arguments |
icons |
Icon[] |
No | Icons for UI display |
_meta |
Record<string, unknown> |
No | Opaque metadata |
Prompt handlers receive:
args-- Validated prompt argumentsctx--McpExecutionContext
Prompt handlers must return { messages: [...] }.
Declares a method as a completion handler for prompt arguments or resource template parameters. Provides auto-complete suggestions to clients.
import { Injectable } from '@nestjs/common';
import { Completion } from '@nest-mcp/server';
@Injectable()
export class CompletionService {
@Completion({
refType: 'ref/prompt',
refName: 'code-review',
})
async completeCodeReview(argName: string, argValue: string) {
if (argName === 'language') {
const languages = ['typescript', 'python', 'rust', 'go', 'java'];
return {
values: languages.filter(l => l.startsWith(argValue.toLowerCase())),
};
}
return { values: [] };
}
}| Option | Type | Required | Description |
|---|---|---|---|
refType |
'ref/prompt' | 'ref/resource' |
Yes | Whether this completes a prompt or resource template |
refName |
string |
Yes | The prompt name or resource template URI |
Completion handlers receive:
argName-- Name of the argument being completedargValue-- Current value (prefix) typed by the usercontext-- Optional context from the completion request
Return { values: string[], hasMore?: boolean, total?: number }.
If no custom @Completion handler is registered, the framework provides default completion for ZodEnum fields on prompts.
- Auth Decorators --
@Public,@Scopes,@Roles,@Guards - Resilience Decorators --
@RateLimit,@Retry,@CircuitBreaker,@Timeout - Middleware --
@UseMiddleware - Execution Pipeline -- How decorators interact in the request lifecycle