Skip to main content
Glama
interactive-features.md13.8 kB
# MCP 交互式功能实现指南 本文档说明如何在 Gitea MCP Server 中实现 MCP SDK 的交互式功能。 ## SDK 版本 - `@modelcontextprotocol/sdk`: v1.22.0 - 支持的交互式功能:Elicitation、Prompts、Resources ## 1. Elicitation(请求用户输入) ### 概述 Elicitation 允许 MCP 服务器在工具执行过程中主动请求用户提供额外信息,实现多轮交互。 ### API 使用 ```typescript import { Server } from '@modelcontextprotocol/sdk/server/index.js'; // 在 tool handler 中使用 const result = await server.elicitInput({ message: '请提供仓库信息', requestedSchema: { type: 'object', properties: { owner: { type: 'string', title: '仓库所有者', description: '用户名或组织名', }, repo: { type: 'string', title: '仓库名称', description: '仓库的名称', }, makeDefault: { type: 'boolean', title: '设为默认', description: '是否将此仓库设为默认上下文', default: true, }, visibility: { type: 'string', title: '仓库可见性', enum: ['public', 'private', 'internal'], enumNames: ['公开', '私有', '内部'], default: 'public', } }, required: ['owner', 'repo'], }, }); // 处理用户响应 if (result.action === 'accept') { const { owner, repo, makeDefault, visibility } = result.content; // 使用用户输入的数据继续执行 } else if (result.action === 'decline') { // 用户明确拒绝 throw new Error('User declined the operation'); } else { // 用户取消(关闭对话框等) throw new Error('Operation cancelled by user'); } ``` ### 支持的字段类型 #### 1. 字符串(String) ```typescript { type: 'string', title: '字段标题', description: '字段描述', default: '默认值', } ``` #### 2. 数字(Number) ```typescript { type: 'number', title: '数量', description: '请输入数量', default: 10, } ``` #### 3. 布尔值(Boolean) ```typescript { type: 'boolean', title: '是否启用', description: '是否启用此功能', default: true, } ``` #### 4. 单选枚举(Enum) ```typescript { type: 'string', title: '优先级', enum: ['low', 'medium', 'high'], enumNames: ['低', '中', '高'], // 可选:显示名称 default: 'medium', } ``` #### 5. 多选枚举(Multi-select) ```typescript { type: 'array', title: '标签', items: { type: 'string', }, enum: ['bug', 'feature', 'documentation'], enumNames: ['错误', '功能', '文档'], default: [], } ``` ### ElicitResult 类型 ```typescript type ElicitResult = { action: 'accept' | 'decline' | 'cancel'; content?: Record<string, string | number | boolean | string[]>; _meta?: Record<string, unknown>; }; ``` ### 限制和注意事项 1. **不支持嵌套对象**:requestedSchema 只支持顶级属性,不能嵌套对象 2. **客户端能力检查**:在使用前需确保客户端支持 elicitation(SDK 会自动检查) 3. **超时处理**:客户端可能设置超时,长时间无响应会导致请求失败 ## 2. Prompts(提示模板) ### 概述 Prompts 是可重用的提示模板,在 Claude CLI 中自动转换为斜杠命令:`/mcp__servername__promptname` ### API 使用(使用 McpServer) ```typescript import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; const mcpServer = new McpServer({ name: 'gitea-mcp-tool', version: '1.0.0', }); // 注册无参数 prompt mcpServer.registerPrompt( 'create-issue', { title: '创建 Issue', description: '交互式创建 Gitea Issue', }, async (extra) => { return { description: '请按照以下模板创建 Issue:', messages: [ { role: 'user', content: { type: 'text', text: `请帮我创建一个新的 Issue,包含以下信息: - 标题:[Issue 标题] - 内容:[详细描述] - 标签:[可选标签] - 优先级:[低/中/高] 请根据项目情况填写具体内容。`, }, }, ], }; } ); // 注册带参数 prompt mcpServer.registerPrompt( 'create-pr', { title: '创建 Pull Request', description: '交互式创建 Gitea Pull Request', argsSchema: { from_branch: z.string().describe('源分支名称'), to_branch: z.string().optional().describe('目标分支名称(默认:main)'), }, }, async (args, extra) => { const { from_branch, to_branch = 'main' } = args; return { description: `从 ${from_branch} 到 ${to_branch} 的 PR 模板`, messages: [ { role: 'user', content: { type: 'text', text: `请帮我创建一个 Pull Request: - 源分支:${from_branch} - 目标分支:${to_branch} - 标题:[PR 标题] - 描述:[详细描述变更内容] 请审查代码差异并生成合适的 PR 描述。`, }, }, ], }; } ); ``` ### API 使用(使用低级 Server API) 如果使用低级 `Server` API(当前 Gitea MCP Server 的做法),需要手动注册处理器: ```typescript import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { ListPromptsRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js'; const server = new Server({ name: 'gitea-mcp-tool', version: '1.0.0', }, { capabilities: { prompts: {}, // 声明支持 prompts }, }); // 存储已注册的 prompts const registeredPrompts = new Map(); registeredPrompts.set('create-issue', { name: 'create-issue', title: '创建 Issue', description: '交互式创建 Gitea Issue', arguments: [], // 无参数 }); registeredPrompts.set('create-pr', { name: 'create-pr', title: '创建 Pull Request', description: '交互式创建 Gitea Pull Request', arguments: [ { name: 'from_branch', description: '源分支名称', required: true, }, { name: 'to_branch', description: '目标分支名称(默认:main)', required: false, }, ], }); // 处理 prompts/list 请求 server.setRequestHandler(ListPromptsRequestSchema, async () => { return { prompts: Array.from(registeredPrompts.values()), }; }); // 处理 prompts/get 请求 server.setRequestHandler(GetPromptRequestSchema, async (request) => { const { name, arguments: args } = request.params; if (name === 'create-issue') { return { description: '请按照以下模板创建 Issue:', messages: [ { role: 'user', content: { type: 'text', text: `请帮我创建一个新的 Issue,包含以下信息: - 标题:[Issue 标题] - 内容:[详细描述] - 标签:[可选标签] - 优先级:[低/中/高] 请根据项目情况填写具体内容。`, }, }, ], }; } if (name === 'create-pr') { const fromBranch = args?.from_branch || ''; const toBranch = args?.to_branch || 'main'; return { description: `从 ${fromBranch} 到 ${toBranch} 的 PR 模板`, messages: [ { role: 'user', content: { type: 'text', text: `请帮我创建一个 Pull Request: - 源分支:${fromBranch} - 目标分支:${toBranch} - 标题:[PR 标题] - 描述:[详细描述变更内容] 请审查代码差异并生成合适的 PR 描述。`, }, }, ], }; } throw new Error(`Unknown prompt: ${name}`); }); ``` ### Prompt 消息类型 ```typescript type PromptMessage = { role: 'user' | 'assistant'; content: TextContent | ImageContent | EmbeddedResource; }; type TextContent = { type: 'text'; text: string; _meta?: Record<string, unknown>; }; type ImageContent = { type: 'image'; data: string; // Base64 编码 mimeType: string; _meta?: Record<string, unknown>; }; type EmbeddedResource = { type: 'resource'; resource: { uri: string; mimeType?: string; text?: string; }; _meta?: Record<string, unknown>; }; ``` ## 3. 在 Gitea MCP Server 中的应用场景 ### 场景 1:改进 `gitea_init` 工具 使用 Elicitation 实现真正的交互式初始化: ```typescript case 'gitea_init': { // 尝试自动检测 const gitInfo = detectGitInfo(workingDir); // 如果检测失败,使用 elicitation 请求用户输入 if (!gitInfo.owner || !gitInfo.repo) { const result = await server.elicitInput({ message: '无法自动检测仓库信息,请手动输入:', requestedSchema: { type: 'object', properties: { owner: { type: 'string', title: '仓库所有者', description: '用户名或组织名', }, repo: { type: 'string', title: '仓库名称', }, gitea_url: { type: 'string', title: 'Gitea 服务器 URL', default: config.baseUrl, }, set_as_default: { type: 'boolean', title: '设为默认上下文', default: true, }, }, required: ['owner', 'repo'], }, }); if (result.action === 'accept') { // 使用用户输入创建配置 const { owner, repo, gitea_url, set_as_default } = result.content; // ... 创建配置逻辑 } else { throw new Error('Configuration initialization cancelled'); } } break; } ``` ### 场景 2:添加常用工作流 Prompts ```typescript // /mcp__gitea-mcp-tool__create-issue registerPrompt('create-issue', { title: '创建 Issue', description: '交互式创建 Issue 的提示模板', }); // /mcp__gitea-mcp-tool__create-pr registerPrompt('create-pr', { title: '创建 Pull Request', description: '交互式创建 PR 的提示模板', argsSchema: { from_branch: z.string(), to_branch: z.string().optional(), }, }); // /mcp__gitea-mcp-tool__review-pr registerPrompt('review-pr', { title: '审查 Pull Request', description: '审查 PR 的提示模板', argsSchema: { pr_number: z.string(), }, }); ``` ### 场景 3:交互式创建 Issue ```typescript case 'gitea_create_issue': { // 如果缺少必需参数,使用 elicitation if (!args.title) { const result = await server.elicitInput({ message: '请提供 Issue 信息:', requestedSchema: { type: 'object', properties: { title: { type: 'string', title: '标题', description: 'Issue 的标题', }, body: { type: 'string', title: '内容', description: 'Issue 的详细描述', }, labels: { type: 'array', title: '标签', items: { type: 'string' }, enum: ['bug', 'feature', 'documentation', 'help-wanted'], enumNames: ['错误', '功能', '文档', '需要帮助'], }, priority: { type: 'string', title: '优先级', enum: ['low', 'medium', 'high'], enumNames: ['低', '中', '高'], default: 'medium', }, }, required: ['title', 'body'], }, }); if (result.action === 'accept') { // 使用收集的数据创建 Issue // ... 调用 Gitea API } } break; } ``` ## 4. 迁移建议 ### 从当前实现到交互式实现的迁移路径 1. **保持向后兼容**: - 保留现有的非交互式工具 - 添加新的交互式版本作为补充 2. **逐步添加功能**: - 第一步:添加 Prompts(最简单,用户体验提升明显) - 第二步:为关键工具添加 Elicitation(如 gitea_init) - 第三步:为复杂工作流添加组合使用 3. **架构选择**: - **方案 A**:保持使用低级 `Server` API(当前做法) - 优点:完全控制,灵活性高 - 缺点:需要手动实现更多代码 - **方案 B**:迁移到 `McpServer` 高级 API - 优点:代码简洁,自动处理很多细节 - 缺点:需要重构现有代码 ## 5. 实现优先级建议 ### 高优先级 1. **添加 Prompts**: - `create-issue`:创建 Issue 的提示模板 - `create-pr`:创建 PR 的提示模板 - `review-pr`:审查 PR 的提示模板 2. **改进 `gitea_init`**: - 使用 Elicitation 在自动检测失败时请求输入 ### 中优先级 3. **为复杂工具添加 Elicitation**: - `gitea_create_release`:交互式创建发布 - `gitea_create_repository`:交互式创建仓库 ### 低优先级 4. **进阶功能**: - 多步骤工作流(连续多次 elicitation) - 动态表单(根据前一步的输入调整后续字段) ## 6. 测试和验证 ### 客户端兼容性 - ✅ Claude CLI(支持 Prompts 和 Elicitation) - ⚠️ Claude Desktop(需要验证支持程度) - ⚠️ 其他 MCP 客户端(视具体实现而定) ### 测试方法 1. **Prompts 测试**: ```bash # 在 Claude CLI 中 /mcp__gitea-mcp-tool__create-issue ``` 2. **Elicitation 测试**: - 调用配置为使用 elicitation 的工具 - 验证用户输入界面是否正确显示 - 验证输入数据是否正确传递 ## 7. 参考资料 - [MCP SDK TypeScript](https://github.com/modelcontextprotocol/typescript-sdk) - [MCP Specification](https://modelcontextprotocol.io) - [MCP Apps Announcement](https://www.anthropic.com/news/mcp-apps) - SDK Version: @modelcontextprotocol/sdk@1.22.0 --- **文档创建日期**:2025-11-23 **SDK 版本**:1.22.0 **作者**:Claude (Assisted by Claude Code)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SupenBysz/gitea-mcp-tool'

If you have feedback or need assistance with the MCP directory API, please join our Discord server