Skip to main content
Glama
workflow-registry.ts13.7 kB
/** * Workflow Tools Registry * 工作流管理工具注册模块 */ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import * as WorkflowTools from '../tools/workflow.js'; import type { ToolContext } from '../index.js'; import { createLogger } from '../logger.js'; const logger = createLogger('registry:workflow'); /** * 注册所有工作流管理工具 */ export function registerWorkflowTools(mcpServer: McpServer, ctx: ToolContext) { // 1. gitea_workflow_init - 初始化工作流配置 mcpServer.registerTool( 'gitea_workflow_init', { title: '初始化工作流配置', description: 'Initialize Issue workflow configuration for a project. Generates .gitea/issue-workflow.yaml with labels, board columns, and automation rules based on project type.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), project_type: z .enum(['backend', 'frontend', 'fullstack', 'library']) .describe('Project type for template selection'), language: z.string().optional().describe('Primary programming language (e.g., go, typescript, python)'), }), }, async (args) => { try { const result = await WorkflowTools.workflowInit( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 2. gitea_workflow_load_config - 加载工作流配置 mcpServer.registerTool( 'gitea_workflow_load_config', { title: '加载工作流配置', description: 'Load and parse the workflow configuration from .gitea/issue-workflow.yaml. Returns the parsed config and validation results.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), }), }, async (args) => { try { const result = await WorkflowTools.workflowLoadConfig( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 3. gitea_workflow_sync_labels - 同步标签系统 mcpServer.registerTool( 'gitea_workflow_sync_labels', { title: '同步标签系统', description: 'Sync repository labels based on workflow configuration. Creates status/*, priority/*, type/* and other labels defined in the config.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), dry_run: z.boolean().optional().describe('Preview changes without applying (default: false)'), }), }, async (args) => { try { const result = await WorkflowTools.workflowSyncLabels( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 4. gitea_workflow_sync_board - 同步项目看板 mcpServer.registerTool( 'gitea_workflow_sync_board', { title: '同步项目看板', description: 'Create or update project board with columns mapped to status labels. Columns: Backlog, In Progress, Review, Testing, Done.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), board_name: z.string().optional().describe('Project board name (default: from config)'), }), }, async (args) => { try { const result = await WorkflowTools.workflowSyncBoard( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 5. gitea_workflow_check_issues - 检查并应用工作流规则 mcpServer.registerTool( 'gitea_workflow_check_issues', { title: '检查 Issue 工作流', description: 'Check all open issues against workflow rules. Identifies missing labels, conflicts, and provides suggestions for improvement.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), issue_number: z.number().optional().describe('Check only a specific issue (optional)'), rules: z.array(z.string()).optional().describe('Apply only specific rules (optional)'), }), }, async (args) => { try { const result = await WorkflowTools.workflowCheckIssues( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 6. gitea_workflow_infer_labels - 智能标签推断 mcpServer.registerTool( 'gitea_workflow_infer_labels', { title: '智能标签推断', description: 'Infer labels for an issue based on title and body content. Uses keyword matching and pattern recognition to suggest type, priority, and area labels.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), issue_number: z.number().describe('Issue number to analyze'), auto_apply: z.boolean().optional().describe('Automatically apply inferred labels (default: false)'), }), }, async (args) => { try { const result = await WorkflowTools.workflowInferLabels( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 7. gitea_workflow_check_blocked - 检测阻塞 Issue mcpServer.registerTool( 'gitea_workflow_check_blocked', { title: '检测阻塞 Issue', description: 'Detect issues that are blocked or exceeding SLA. Checks for stale issues based on priority-specific time limits.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), threshold_hours: z.number().optional().describe('Override default SLA hours threshold'), }), }, async (args) => { try { const result = await WorkflowTools.workflowCheckBlocked( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 8. gitea_workflow_escalate_priority - 优先级升级 mcpServer.registerTool( 'gitea_workflow_escalate_priority', { title: '优先级升级', description: 'Automatically escalate priority for aged issues. P3→P2 after 30 days, P2→P1 after 14 days, P1→P0 after 3 days. Security issues are always P0.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), dry_run: z.boolean().optional().describe('Preview changes without applying (default: false)'), }), }, async (args) => { try { const result = await WorkflowTools.workflowEscalatePriority( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 9. gitea_workflow_sync_status - 状态双向同步 mcpServer.registerTool( 'gitea_workflow_sync_status', { title: '状态双向同步', description: 'Synchronize issue status labels with project board column positions. Supports label-to-board, board-to-label, or bidirectional sync.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), direction: z .enum(['label-to-board', 'board-to-label', 'both']) .describe('Sync direction'), }), }, async (args) => { try { const result = await WorkflowTools.workflowSyncStatus( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); // 10. gitea_workflow_generate_report - 生成工作流报告 mcpServer.registerTool( 'gitea_workflow_generate_report', { title: '生成工作流报告', description: 'Generate a comprehensive workflow report including issue statistics, health score, and recommendations. Output in JSON and Markdown formats.', inputSchema: z.object({ owner: z.string().optional().describe('Repository owner. Uses context if not provided'), repo: z.string().optional().describe('Repository name. Uses context if not provided'), time_range: z .enum(['day', 'week', 'month']) .optional() .describe('Time range for statistics (default: all time)'), }), }, async (args) => { try { const result = await WorkflowTools.workflowGenerateReport( { client: ctx.client, contextManager: ctx.contextManager }, args ); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], isError: !result.success, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text' as const, text: `Error: ${errorMessage}` }], isError: true, }; } } ); logger.info('Registered 10 workflow tools'); }

Implementation Reference

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