Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/tools/BaseTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ export interface ToolExecution {
taskSupport?: 'forbidden' | 'optional' | 'required';
}

export interface ToolPricing {
perCall?: number;
freeTier?: number;
}

export interface ContentAnnotations {
audience?: ('user' | 'assistant')[];
priority?: number;
Expand Down Expand Up @@ -177,6 +182,7 @@ export interface ToolProtocol extends SDKTool {
icons?: MCPIcon[];
annotations?: ToolAnnotations;
execution?: ToolExecution;
pricing?: ToolPricing;
outputSchema?: Record<string, unknown>;
_meta?: Record<string, unknown>;
};
Expand Down Expand Up @@ -227,6 +233,7 @@ export abstract class MCPTool<TInput extends Record<string, any> = any, TSchema
icons?: MCPIcon[];
annotations?: ToolAnnotations;
execution?: ToolExecution;
pricing?: ToolPricing;
protected outputSchemaShape?: z.ZodObject<any>;
[key: string]: unknown;

Expand Down Expand Up @@ -861,6 +868,7 @@ export abstract class MCPTool<TInput extends Record<string, any> = any, TSchema
...(this.icons && this.icons.length > 0 && { icons: this.icons }),
...(this.annotations && Object.keys(this.annotations).length > 0 && { annotations: this.annotations }),
...(this.execution && Object.keys(this.execution).length > 0 && { execution: this.execution }),
...(this.pricing && Object.keys(this.pricing).length > 0 && { pricing: this.pricing }),
...(this.outputSchemaShape && { outputSchema: this.generateOutputSchema() }),
...(this.app && {
_meta: {
Expand Down
33 changes: 33 additions & 0 deletions tests/tools/tool-metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ class ToolWithEmptyIcons extends MCPTool {
async execute() { return 'ok'; }
}

class ToolWithPricing extends MCPTool {
name = 'priced_tool';
description = 'A tool with pricing';
pricing = { perCall: 0.001, freeTier: 100 };
schema = schema;
async execute() { return 'ok'; }
}

class ToolWithPartialPricing extends MCPTool {
name = 'partial_priced_tool';
description = 'A tool with partial pricing';
pricing = { perCall: 0.005 };
schema = schema;
async execute() { return 'ok'; }
}

describe('Tool Metadata', () => {
describe('title', () => {
it('should include title in toolDefinition when set', () => {
Expand Down Expand Up @@ -72,4 +88,21 @@ describe('Tool Metadata', () => {
expect('icons' in tool.toolDefinition).toBe(false);
});
});

describe('pricing', () => {
it('should include pricing in toolDefinition when set', () => {
const tool = new ToolWithPricing();
expect(tool.toolDefinition.pricing).toEqual({ perCall: 0.001, freeTier: 100 });
});

it('should include partial pricing in toolDefinition', () => {
const tool = new ToolWithPartialPricing();
expect(tool.toolDefinition.pricing).toEqual({ perCall: 0.005 });
});

it('should not include pricing key when not set', () => {
const tool = new BasicTool();
expect('pricing' in tool.toolDefinition).toBe(false);
});
});
});