Skip to main content
Glama

gitea_workflow_sync_status

Sync issue status labels with project board columns in Gitea repositories. Choose label-to-board, board-to-label, or bidirectional synchronization to maintain workflow consistency.

Instructions

Synchronize issue status labels with project board column positions. Supports label-to-board, board-to-label, or bidirectional sync.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ownerNoRepository owner. Uses context if not provided
repoNoRepository name. Uses context if not provided
directionYesSync direction

Implementation Reference

  • The core handler function implementing the 'gitea_workflow_sync_status' tool. Loads workflow config, initializes BoardSyncManager, fetches projects and issues, calculates sync actions based on direction (label-to-board, board-to-label, or both), and returns sync report.
    export async function workflowSyncStatus( ctx: WorkflowToolsContext, args: { owner?: string; repo?: string; config?: WorkflowConfig; direction: 'label-to-board' | 'board-to-label' | 'both'; } ): Promise<{ success: boolean; synced_count: number; actions: SyncAction[]; error?: string; }> { logger.debug({ args: { ...args, config: args.config ? '[provided]' : undefined } }, 'Syncing status'); const { owner, repo } = ctx.contextManager.resolveOwnerRepo(args.owner, args.repo); // 获取配置 let config = args.config; if (!config) { const loadResult = await workflowLoadConfig(ctx, { owner, repo }); if (!loadResult.success || !loadResult.config) { return { success: false, synced_count: 0, actions: [], error: loadResult.error || '无法加载配置', }; } config = loadResult.config; } const boardSyncManager = new BoardSyncManager(config); const actions: SyncAction[] = []; try { // 获取项目和列 const projects = await ctx.client.get<Array<{ id: number; title: string }>>( `/repos/${owner}/${repo}/projects` ); const workflowProject = projects.find((p) => p.title === config.board.name); if (!workflowProject) { return { success: false, synced_count: 0, actions: [], error: `未找到项目看板: ${config.board.name}`, }; } // 获取开放的 Issue const issues = await ctx.client.get<Issue[]>(`/repos/${owner}/${repo}/issues?state=open&limit=100`); // 计算同步操作(这里只返回建议的操作,实际同步需要更复杂的实现) for (const issue of issues) { const syncActions = boardSyncManager.calculateSyncActions(issue, null, args.direction); actions.push(...syncActions); } logger.info({ owner, repo, actions: actions.length }, 'Status sync calculated'); return { success: true, synced_count: actions.length, actions, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error({ owner, repo, error: errorMessage }, 'Failed to sync status'); return { success: false, synced_count: 0, actions: [], error: errorMessage, }; } }
  • Registers the 'gitea_workflow_sync_status' tool with the MCP server, defining its title, description, input schema, and wiring the handler from WorkflowTools.
    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, }; } } );
  • Zod input schema validation for the tool, defining parameters: owner (optional string), repo (optional string), direction (enum: 'label-to-board', 'board-to-label', 'both').
    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'), }),
  • Key helper method in BoardSyncManager used by the handler to compute synchronization actions between issue labels and board columns based on the specified direction.
    calculateSyncActions( issue: Issue, currentColumn: ProjectColumn | null, direction: SyncDirection ): SyncAction[] { const actions: SyncAction[] = []; const statusLabel = this.getStatusLabel(issue); const expectedColumn = statusLabel ? this.findColumnByLabel(statusLabel) : null; if (direction === 'label-to-board' || direction === 'both') { // 标签 → 看板:根据状态标签移动卡片 if (statusLabel && expectedColumn) { if (!currentColumn) { // Issue 不在看板上,需要创建卡片 actions.push({ type: 'create_card', issue_number: issue.number, details: { to_column: expectedColumn.name, }, reason: `根据标签 ${statusLabel} 添加到看板列 ${expectedColumn.name}`, }); } else if (currentColumn.name !== expectedColumn.name) { // 卡片在错误的列,需要移动 actions.push({ type: 'move_card', issue_number: issue.number, details: { from_column: currentColumn.name, to_column: expectedColumn.name, }, reason: `根据标签 ${statusLabel} 移动卡片`, }); } } } if (direction === 'board-to-label' || direction === 'both') { // 看板 → 标签:根据卡片位置更新标签 if (currentColumn) { const expectedLabel = this.findLabelByColumn(currentColumn.name); if (expectedLabel && expectedLabel !== statusLabel) { // 需要更新状态标签 if (statusLabel) { actions.push({ type: 'remove_label', issue_number: issue.number, details: { label: statusLabel }, reason: `移除旧状态标签 ${statusLabel}`, }); } actions.push({ type: 'add_label', issue_number: issue.number, details: { label: expectedLabel }, reason: `根据看板位置 ${currentColumn.name} 添加标签`, }); } } } return actions; }

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