Skip to main content
Tools are typed actions your server can execute. They’re described with Zod schemas and exposed via MCP. Implement as a class with @Tool({...}) or as a function via tool().

Minimal tool (class)

import { Tool } from '@frontmcp/sdk';
import { z } from 'zod';

@Tool({
  name: 'greet',
  description: 'Greets a user by name',
  inputSchema: { name: z.string() },
})
export default class GreetTool {
  async execute({ name }: { name: string }) {
    return `Hello, ${name}!`;
  }
}
Register it on an app:
@App({ id: 'hello', name: 'Hello', tools: [GreetTool] })
export default class HelloApp {}

Inline tool (function builder)

import { tool } from '@frontmcp/sdk';
import { z } from 'zod';

export const Add = tool({
  name: 'add',
  description: 'Add two numbers',
  inputSchema: { a: z.number(), b: z.number() },
})((input) => input.a + input.b);
Add to app:
@App({ name: 'Calc', tools: [Add] })
class CalcApp {}

Tool metadata

@Tool({
  id?: string,
  name: string,
  description?: string,
  inputSchema: ZodSchema,
  rawInputSchema?: JSONSchema7,
  outputSchema?: ZodSchema,
  tags?: string[],
  annotations?: {
    title?: string,
    readOnlyHint?: boolean,
    destructiveHint?: boolean,
    idempotentHint?: boolean,
    openWorldHint?: boolean,
  },
  hideFromDiscovery?: boolean, // default false
})
Notes
  • annotations hint model & UI behavior (read-only, idempotent, etc.).
  • hideFromDiscovery keeps a tool callable but off tool/list.
  • Tools can attach per-tool hooks (see Advanced → Hooks).

Return values

  • Return any serializable type; if you provide outputSchema, it will validate.
  • Errors are surfaced via MCP error responses; you can also throw typed errors inside executors.