add-mcp-tool
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAdd MCP Tool
添加MCP工具
Add a new tool to an existing FastMCP server with interactive configuration.
通过交互式配置向现有FastMCP服务器添加新工具。
Usage
使用方法
bash
/add-mcp-tool [tool-name]bash
/add-mcp-tool [tool-name]Arguments
参数
- : Optional - Name for the new tool (will prompt if not provided)
[tool-name]
- :可选 - 新工具的名称(如果未提供,将提示输入)
[tool-name]
Execution Instructions for Claude Code
Claude Code执行说明
When this command is run:
- Locate the FastMCP server in the current project
- Gather tool requirements through interactive questions
- Generate tool code based on configuration
- Add tool to server by modifying existing files or creating new ones
运行此命令时:
- 定位FastMCP服务器:在当前项目中找到FastMCP服务器
- 收集工具需求:通过交互式问题收集工具需求
- 生成工具代码:根据配置生成工具代码
- 向服务器添加工具:修改现有文件或创建新文件来添加工具
Interactive Session Flow
交互式会话流程
1. Locate Server
1. 定位服务器
First, find the FastMCP server in the project:
Looking for FastMCP server...
Found: src/server.ts
Is this the correct server file? (yes/no):If not found:
I couldn't find a FastMCP server. Please provide the path to your server file:首先,在项目中找到FastMCP服务器:
正在查找FastMCP服务器...
已找到:src/server.ts
这是正确的服务器文件吗?(是/否):如果未找到:
我无法找到FastMCP服务器。请提供您的服务器文件路径:2. Tool Basics
2. 工具基础信息
Let's add a new tool to your MCP server.
Tool name (lowercase, use hyphens):
Example: "fetch-data", "create-file", "query-database"
Tool name:Tool description (shown to LLM clients):
Example: "Fetches data from the specified API endpoint"
Description:让我们为您的MCP服务器添加一个新工具。
工具名称(小写,使用连字符):
示例:"fetch-data", "create-file", "query-database"
工具名称:工具描述(将展示给LLM客户端):
示例:"从指定API端点获取数据"
描述:3. Parameters
3. 参数配置
Does this tool require parameters?
1. No parameters
2. Simple parameters (strings, numbers, booleans)
3. Complex parameters (objects, arrays, enums)
Select (1-3):If parameters needed:
Let's define the parameters one by one.
Parameter 1:
Name:
Type (string/number/boolean/array/object):
Required? (yes/no):
Description:
Add another parameter? (yes/no):For enum types:
Enum values (comma-separated):
Example: "json,xml,csv"
Values:此工具是否需要参数?
1. 无参数
2. 简单参数(字符串、数字、布尔值)
3. 复杂参数(对象、数组、枚举)
请选择(1-3):如果需要参数:
让我们逐一定义参数。
参数1:
名称:
类型(string/number/boolean/array/object):
是否必填?(是/否):
描述:
是否添加另一个参数?(是/否):对于枚举类型:
枚举值(逗号分隔):
示例:"json,xml,csv"
值:4. Return Type
4. 返回类型
What does this tool return?
1. Simple text response
2. Multiple content items
3. Image content
4. Audio content
5. Resource reference
6. Custom structure
Select (1-6):此工具返回什么类型的内容?
1. 简单文本响应
2. 多个内容项
3. 图片内容
4. 音频内容
5. 资源引用
6. 自定义结构
请选择(1-6):5. Tool Features
5. 工具功能
Which features do you need?
[ ] Logging (log.info, log.error, etc.)
[ ] Progress reporting (for long operations)
[ ] Streaming output (for text generation)
[ ] Authorization check (canAccess)
[ ] Error handling with UserError
Select features (comma-separated numbers, or 'none'):您需要哪些功能?
[ ] 日志记录(log.info、log.error等)
[ ] 进度报告(针对长时操作)
[ ] 流式输出(针对文本生成)
[ ] 权限校验(canAccess)
[ ] 基于UserError的错误处理
请选择功能(逗号分隔的数字,或输入'none'):6. Tool Annotations
6. 工具注解
Optional annotations for LLM clients:
Read-only hint (tool doesn't modify state)? (yes/no) [default: no]:
Open-world hint (tool accesses external systems)? (yes/no) [default: no]:
Streaming hint (tool produces streaming output)? (yes/no) [default: no]:为LLM客户端添加可选注解:
是否为只读提示(工具不修改状态)?(是/否)[默认:否]:
是否为开放世界提示(工具访问外部系统)?(是/否)[默认:否]:
是否为流式提示(工具生成流式输出)?(是/否)[默认:否]:Generated Code Examples
生成的代码示例
Simple Tool (no parameters)
简单工具(无参数)
typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
execute: async () => {
return "Result here";
},
});typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
execute: async () => {
return "Result here";
},
});Tool with Parameters
带参数的工具
typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
{{#each parameters}}
{{name}}: z.{{type}}(){{#if description}}.describe("{{description}}"){{/if}}{{#unless required}}.optional(){{/unless}},
{{/each}}
}),
execute: async (args) => {
const { {{parameterNames}} } = args;
// TODO: Implement tool logic
return "Processed: " + JSON.stringify(args);
},
});typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
{{#each parameters}}
{{name}}: z.{{type}}(){{#if description}}.describe("{{description}}"){{/if}}{{#unless required}}.optional(){{/unless}},
{{/each}}
}),
execute: async (args) => {
const { {{parameterNames}} } = args;
// TODO: Implement tool logic
return "Processed: " + JSON.stringify(args);
},
});Tool with Logging
带日志记录的工具
typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
url: z.string().describe("URL to fetch"),
}),
execute: async (args, { log }) => {
log.info("Starting operation", { url: args.url });
try {
// TODO: Implement logic
const result = await fetchData(args.url);
log.info("Operation completed successfully");
return result;
} catch (error) {
log.error("Operation failed", { error: String(error) });
throw error;
}
},
});typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
url: z.string().describe("URL to fetch"),
}),
execute: async (args, { log }) => {
log.info("Starting operation", { url: args.url });
try {
// TODO: Implement logic
const result = await fetchData(args.url);
log.info("Operation completed successfully");
return result;
} catch (error) {
log.error("Operation failed", { error: String(error) });
throw error;
}
},
});Tool with Progress Reporting
带进度报告的工具
typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
items: z.array(z.string()).describe("Items to process"),
}),
execute: async (args, { reportProgress }) => {
const total = args.items.length;
const results: string[] = [];
for (let i = 0; i < total; i++) {
await reportProgress({ progress: i, total });
// TODO: Process each item
results.push("Processed: " + args.items[i]);
}
await reportProgress({ progress: total, total });
return results.join("\n");
},
});typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
items: z.array(z.string()).describe("Items to process"),
}),
execute: async (args, { reportProgress }) => {
const total = args.items.length;
const results: string[] = [];
for (let i = 0; i < total; i++) {
await reportProgress({ progress: i, total });
// TODO: Process each item
results.push("Processed: " + args.items[i]);
}
await reportProgress({ progress: total, total });
return results.join("\n");
},
});Tool with Streaming Output
带流式输出的工具
typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
prompt: z.string().describe("Input prompt"),
}),
annotations: {
streamingHint: true,
},
execute: async (args, { streamContent }) => {
// Stream content progressively
await streamContent({ type: "text", text: "Processing...\n" });
// TODO: Generate content
const chunks = ["First ", "part, ", "second ", "part."];
for (const chunk of chunks) {
await streamContent({ type: "text", text: chunk });
await new Promise(r => setTimeout(r, 100));
}
return; // Return undefined when using streaming
},
});typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
prompt: z.string().describe("Input prompt"),
}),
annotations: {
streamingHint: true,
},
execute: async (args, { streamContent }) => {
// Stream content progressively
await streamContent({ type: "text", text: "Processing...\n" });
// TODO: Generate content
const chunks = ["First ", "part, ", "second ", "part."];
for (const chunk of chunks) {
await streamContent({ type: "text", text: chunk });
await new Promise(r => setTimeout(r, 100));
}
return; // Return undefined when using streaming
},
});Tool with Authorization
带权限校验的工具
typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
canAccess: (auth) => {
// Return true if user is authorized
return auth?.role === "admin";
},
execute: async (args, { session }) => {
// Tool is only executed if canAccess returns true
return "Welcome, " + session.id;
},
});typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
canAccess: (auth) => {
// Return true if user is authorized
return auth?.role === "admin";
},
execute: async (args, { session }) => {
// Tool is only executed if canAccess returns true
return "Welcome, " + session.id;
},
});Tool with UserError
带UserError的工具
typescript
import { UserError } from "fastmcp";
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
id: z.string().describe("Resource ID"),
}),
execute: async (args) => {
// Validate input
if (!args.id.match(/^[a-z0-9-]+$/)) {
throw new UserError("Invalid ID format. Use lowercase letters, numbers, and hyphens only.");
}
// Check resource exists
const resource = await findResource(args.id);
if (!resource) {
throw new UserError(`Resource not found: ${args.id}`);
}
return JSON.stringify(resource);
},
});typescript
import { UserError } from "fastmcp";
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
id: z.string().describe("Resource ID"),
}),
execute: async (args) => {
// Validate input
if (!args.id.match(/^[a-z0-9-]+$/)) {
throw new UserError("Invalid ID format. Use lowercase letters, numbers, and hyphens only.");
}
// Check resource exists
const resource = await findResource(args.id);
if (!resource) {
throw new UserError(`Resource not found: ${args.id}`);
}
return JSON.stringify(resource);
},
});Tool with Image Content
带图片内容的工具
typescript
import { imageContent } from "fastmcp";
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
imageId: z.string().describe("Image identifier"),
}),
execute: async (args) => {
// Return image from URL
return imageContent({
url: `https://example.com/images/${args.imageId}.png`,
});
// Or from file path:
// return imageContent({ path: `/path/to/${args.imageId}.png` });
// Or from buffer:
// return imageContent({ buffer: imageBuffer });
},
});typescript
import { imageContent } from "fastmcp";
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
parameters: z.object({
imageId: z.string().describe("Image identifier"),
}),
execute: async (args) => {
// Return image from URL
return imageContent({
url: `https://example.com/images/${args.imageId}.png`,
});
// Or from file path:
// return imageContent({ path: `/path/to/${args.imageId}.png` });
// Or from buffer:
// return imageContent({ buffer: imageBuffer });
},
});Tool with Multiple Content Types
带多种内容类型的工具
typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
execute: async () => {
return {
content: [
{ type: "text", text: "Here's the analysis:" },
{ type: "text", text: "Line 1: Found 5 issues" },
{ type: "text", text: "Line 2: 3 warnings" },
],
};
},
});typescript
server.addTool({
name: "{{tool-name}}",
description: "{{description}}",
execute: async () => {
return {
content: [
{ type: "text", text: "Here's the analysis:" },
{ type: "text", text: "Line 1: Found 5 issues" },
{ type: "text", text: "Line 2: 3 warnings" },
],
};
},
});File Placement Options
文件放置选项
Where should the tool code be added?
1. Inline in server.ts (simple projects)
2. New file in tools/ directory (recommended for organization)
3. Existing tools file (specify which)
Select (1-3):工具代码应放置在何处?
1. 内联到server.ts中(适用于简单项目)
2. tools/目录下的新文件(推荐用于项目组织)
3. 现有工具文件中(指定具体文件)
请选择(1-3):Implementation Notes
实现说明
- Find existing server: Use Glob/Grep to locate FastMCP server files
- Parse existing structure: Understand current tool organization
- Generate imports: Add necessary imports (z, UserError, imageContent, etc.)
- Insert code: Add tool at appropriate location
- Preserve formatting: Match existing code style
- Summary: Show the generated tool and file location
- 查找现有服务器:使用Glob/Grep定位FastMCP服务器文件
- 解析现有结构:理解当前工具的组织方式
- 生成导入语句:添加必要的导入(z、UserError、imageContent等)
- 插入代码:在合适的位置添加工具代码
- 保留格式:匹配现有代码风格
- 总结:展示生成的工具及文件位置