Skip to main content
LeanMCP provides TypeScript decorators to define tools, prompts, and resources with automatic type inference and schema generation.

Core Decorators

@Tool

Marks a method as an MCP tool (callable function).
@Tool(options?: ToolOptions): MethodDecorator
options
ToolOptions

Example

import { Tool } from '@leanmcp/core';

class AnalyzeSentimentInput {
  @SchemaConstraint({ description: 'Text to analyze' })
  text!: string;

  @Optional()
  language?: string;
}

class SentimentService {
  @Tool({
    description: 'Analyze sentiment of text',
    inputClass: AnalyzeSentimentInput,
  })
  async analyzeSentiment(args: AnalyzeSentimentInput) {
    return {
      sentiment: 'positive',
      score: 0.85,
      text: args.text,
    };
  }

  // Tool with OAuth requirement
  @Tool({
    description: 'Fetch private user data',
    securitySchemes: [{ type: 'oauth2', scopes: ['read:user'] }],
  })
  async fetchPrivateData() {
    return { data: 'private' };
  }
}

@Prompt

Marks a method as an MCP prompt template.
@Prompt(options?: PromptOptions): MethodDecorator
options
PromptOptions

Example

import { Prompt } from '@leanmcp/core';

class PromptInput {
  @SchemaConstraint({ description: 'Topic to write about' })
  topic!: string;
}

class PromptService {
  @Prompt({
    description: 'Generate a blog post prompt',
    inputClass: PromptInput,
  })
  blogPostPrompt(args: PromptInput) {
    return {
      messages: [
        {
          role: 'user',
          content: {
            type: 'text',
            text: `Write a blog post about ${args.topic}`,
          },
        },
      ],
    };
  }
}

@Resource

Marks a method as an MCP resource (data source/endpoint).
@Resource(options?: ResourceOptions): MethodDecorator
options
ResourceOptions

Example

import { Resource } from '@leanmcp/core';

class StatsService {
  @Resource({
    description: 'Service statistics',
    mimeType: 'application/json',
  })
  getStats() {
    return {
      requests: 1234,
      uptime: process.uptime(),
    };
  }

  @Resource({
    description: 'Custom resource',
    uri: 'custom://my-resource',
    mimeType: 'text/plain',
  })
  getCustomResource() {
    return 'Custom resource content';
  }
}

Schema Decorators

@Optional

Marks a class property as optional in the JSON Schema.
@Optional(): PropertyDecorator

Example

import { Optional, SchemaConstraint } from '@leanmcp/core';

class MyInput {
  @SchemaConstraint({ description: 'Required field' })
  required!: string;

  @Optional()
  @SchemaConstraint({ description: 'Optional field' })
  optional?: string;
}

@SchemaConstraint

Adds JSON Schema constraints and metadata to a property.
@SchemaConstraint(constraints: {
  description?: string;
  minLength?: number;
  maxLength?: number;
  minimum?: number;
  maximum?: number;
  pattern?: string;
  enum?: any[];
  default?: any;
  type?: string;
}): PropertyDecorator
constraints
object
required

Example

import { SchemaConstraint, Optional } from '@leanmcp/core';

class ValidationExample {
  @SchemaConstraint({
    description: 'User email address',
    pattern: '^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$',
  })
  email!: string;

  @SchemaConstraint({
    description: 'User age',
    minimum: 0,
    maximum: 120,
  })
  age!: number;

  @SchemaConstraint({
    description: 'Account type',
    enum: ['free', 'pro', 'enterprise'],
  })
  accountType!: string;

  @Optional()
  @SchemaConstraint({
    description: 'Bio (max 500 chars)',
    maxLength: 500,
  })
  bio?: string;
}

Authentication Decorators

@Auth

Basic metadata decorator: @Auth adds authentication metadata but does not enforce authentication. For full authentication with token verification, use @Authenticated from @leanmcp/auth.
Adds authentication requirements to a class or method.
@Auth(options: AuthOptions): ClassDecorator & MethodDecorator
options
AuthOptions
required

Example

import { Auth, Tool } from '@leanmcp/core';

// Class-level auth (applies to all methods)
@Auth({ provider: 'clerk' })
class SecureService {
  @Tool({ description: 'Get user data' })
  async getUserData() {
    return { user: 'data' };
  }
}

// Method-level auth
class MixedService {
  @Tool({ description: 'Public method' })
  async publicMethod() {
    return 'public';
  }

  @Tool({ description: 'Premium feature' })
  @Auth({ provider: 'stripe' })
  async premiumMethod() {
    return 'premium';
  }
}
The examples above add authentication metadata to tools but do not enforce authentication. To enforce authentication with token verification, use @Authenticated from @leanmcp/auth. See Authentication Integration for more details.

@UserEnvs

Injects environment variables or user-level configuration into the service instance.
@UserEnvs(): PropertyDecorator

Example

import { UserEnvs, Tool } from '@leanmcp/core';

class ConfigurableService {
  @UserEnvs()
  envs!: Record<string, string | undefined>;

  @Tool({ description: 'Get API key' })
  async getApiKey() {
    return this.envs.API_KEY || 'not-configured';
  }
}

UI & Rendering Decorators

@UI

Links a UI component or frontend visualization to a tool or resource.
@UI(component: string): ClassDecorator & MethodDecorator
component
string
required
UI component name or path

Example

import { UI, Tool } from '@leanmcp/core';

@UI('ChartComponent')
class VisualizationService {
  @Tool({ description: 'Get chart data' })
  async getChartData() {
    return {
      labels: ['Jan', 'Feb', 'Mar'],
      values: [10, 20, 30],
    };
  }
}

@Render

Specifies how the output should be rendered.
@Render(format: 'markdown' | 'html' | 'json' | 'chart' | 'table' | string): MethodDecorator
format
string
required
Render format: ‘markdown’, ‘html’, ‘json’, ‘chart’, ‘table’, or custom format

Example

import { Render, Tool } from '@leanmcp/core';

class ContentService {
  @Tool({ description: 'Get formatted report' })
  @Render('markdown')
  async getReport() {
    return '# Report\n\nThis is a **markdown** report.';
  }

  @Tool({ description: 'Get JSON data' })
  @Render('json')
  async getData() {
    return { data: 'value' };
  }
}

Workflow Decorators

@Deprecated

Marks a tool, prompt, or resource as deprecated.
@Deprecated(message?: string): ClassDecorator & MethodDecorator
message
string
Optional deprecation message (default: ‘This feature is deprecated’)

Example

import { Deprecated, Tool } from '@leanmcp/core';

class LegacyService {
  @Tool({ description: 'Old method' })
  @Deprecated('Use newMethod instead')
  async oldMethod() {
    return 'old';
  }

  @Tool({ description: 'New method' })
  async newMethod() {
    return 'new';
  }
}

// When oldMethod is called, logs: "DEPRECATED: oldMethod - Use newMethod instead"

Helper Functions

getMethodMetadata()

Get all metadata for a specific method.
function getMethodMetadata(method: Function): {
  toolName?: string;
  toolDescription?: string;
  promptName?: string;
  promptDescription?: string;
  resourceUri?: string;
  resourceName?: string;
  resourceDescription?: string;
  inputSchema?: object;
  outputSchema?: object;
  authProvider?: string;
  authRequired?: boolean;
  uiComponent?: string;
  renderFormat?: string;
  deprecated?: boolean;
  deprecationMessage?: string;
}

getDecoratedMethods()

Get all methods with a specific decorator from a class.
function getDecoratedMethods(
  target: any,
  metadataKey: string
): Array<{
  method: Function;
  propertyKey: string;
  metadata: any;
}>

Example

import { getDecoratedMethods } from '@leanmcp/core';

class MyService {
  @Tool({ description: 'Tool 1' })
  async tool1() {}

  @Tool({ description: 'Tool 2' })
  async tool2() {}
}

const toolMethods = getDecoratedMethods(MyService, 'tool:name');
console.log(toolMethods); // [{ method: ..., propertyKey: 'tool1', ... }, ...]

Build docs developers (and LLMs) love