Skip to main content
Glama
label.ts13.1 kB
/** * Label Management Tools * * Label 管理相关的 MCP 工具实现 */ import type { GiteaClient } from '../gitea-client.js'; import type { ContextManager } from '../context-manager.js'; import type { GiteaLabel, CreateLabelOptions, UpdateLabelOptions, } from '../types/gitea.js'; import { createLogger } from '../logger.js'; const logger = createLogger('tools:label'); export interface LabelToolsContext { client: GiteaClient; contextManager: ContextManager; } // ============================================================ // 仓库 Label 管理 // ============================================================ /** * 创建仓库 Label */ export async function createRepoLabel( ctx: LabelToolsContext, args: { owner?: string; repo?: string; name: string; color: string; description?: string; exclusive?: boolean; is_archived?: boolean; token?: string; } ) { logger.debug({ args }, 'Creating repository label'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); const labelOptions: CreateLabelOptions = { name: args.name, color: args.color, description: args.description, exclusive: args.exclusive, is_archived: args.is_archived, }; const label = await ctx.client.post<GiteaLabel>( `/repos/${owner}/${repo}/labels`, labelOptions, args.token ); logger.info({ owner, repo, label: label.name }, 'Repository label created successfully'); return { success: true, label: { id: label.id, name: label.name, color: label.color, description: label.description, exclusive: label.exclusive, is_archived: label.is_archived, url: label.url, }, }; } /** * 列出仓库所有 Labels */ export async function listRepoLabels( ctx: LabelToolsContext, args: { owner?: string; repo?: string; page?: number; limit?: number; token?: string; } ) { logger.debug({ args }, 'Listing repository labels'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); const labels = await ctx.client.get<GiteaLabel[]>(`/repos/${owner}/${repo}/labels`, { page: args.page || 1, limit: args.limit || 30, }, args.token); logger.debug({ count: labels.length }, 'Repository labels listed'); return { success: true, labels: labels.map((label) => ({ id: label.id, name: label.name, color: label.color, description: label.description, exclusive: label.exclusive, is_archived: label.is_archived, url: label.url, })), pagination: { page: args.page || 1, limit: args.limit || 30, total: labels.length, }, }; } /** * 获取仓库 Label 详情 */ export async function getRepoLabel( ctx: LabelToolsContext, args: { owner?: string; repo?: string; id: number; token?: string; } ) { logger.debug({ args }, 'Getting repository label'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); const label = await ctx.client.get<GiteaLabel>(`/repos/${owner}/${repo}/labels/${args.id}`, undefined, args.token); logger.debug({ label: label.name }, 'Repository label retrieved'); return { success: true, label: { id: label.id, name: label.name, color: label.color, description: label.description, exclusive: label.exclusive, is_archived: label.is_archived, url: label.url, }, }; } /** * 更新仓库 Label */ export async function updateRepoLabel( ctx: LabelToolsContext, args: { owner?: string; repo?: string; id: number; name?: string; color?: string; description?: string; exclusive?: boolean; is_archived?: boolean; token?: string; } ) { logger.debug({ args }, 'Updating repository label'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); const updateOptions: UpdateLabelOptions = { name: args.name, color: args.color, description: args.description, exclusive: args.exclusive, is_archived: args.is_archived, }; const label = await ctx.client.patch<GiteaLabel>( `/repos/${owner}/${repo}/labels/${args.id}`, updateOptions, args.token ); logger.info({ owner, repo, label: label.name }, 'Repository label updated successfully'); return { success: true, label: { id: label.id, name: label.name, color: label.color, description: label.description, exclusive: label.exclusive, is_archived: label.is_archived, url: label.url, }, }; } /** * 删除仓库 Label */ export async function deleteRepoLabel( ctx: LabelToolsContext, args: { owner?: string; repo?: string; id: number; token?: string; } ) { logger.debug({ args }, 'Deleting repository label'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); await ctx.client.delete(`/repos/${owner}/${repo}/labels/${args.id}`, undefined, args.token); logger.info({ owner, repo, label_id: args.id }, 'Repository label deleted successfully'); return { success: true, message: `Label #${args.id} has been deleted from ${owner}/${repo}`, }; } // ============================================================ // 组织 Label 管理 // ============================================================ /** * 创建组织 Label */ export async function createOrgLabel( ctx: LabelToolsContext, args: { org: string; name: string; color: string; description?: string; exclusive?: boolean; is_archived?: boolean; token?: string; } ) { logger.debug({ args }, 'Creating organization label'); const labelOptions: CreateLabelOptions = { name: args.name, color: args.color, description: args.description, exclusive: args.exclusive, is_archived: args.is_archived, }; const label = await ctx.client.post<GiteaLabel>( `/orgs/${args.org}/labels`, labelOptions, args.token ); logger.info({ org: args.org, label: label.name }, 'Organization label created successfully'); return { success: true, label: { id: label.id, name: label.name, color: label.color, description: label.description, exclusive: label.exclusive, is_archived: label.is_archived, url: label.url, }, }; } /** * 列出组织所有 Labels */ export async function listOrgLabels( ctx: LabelToolsContext, args: { org: string; page?: number; limit?: number; token?: string; } ) { logger.debug({ args }, 'Listing organization labels'); const labels = await ctx.client.get<GiteaLabel[]>(`/orgs/${args.org}/labels`, { page: args.page || 1, limit: args.limit || 30, }, args.token); logger.debug({ count: labels.length }, 'Organization labels listed'); return { success: true, labels: labels.map((label) => ({ id: label.id, name: label.name, color: label.color, description: label.description, exclusive: label.exclusive, is_archived: label.is_archived, url: label.url, })), pagination: { page: args.page || 1, limit: args.limit || 30, total: labels.length, }, }; } /** * 获取组织 Label 详情 */ export async function getOrgLabel( ctx: LabelToolsContext, args: { org: string; id: number; token?: string; } ) { logger.debug({ args }, 'Getting organization label'); const label = await ctx.client.get<GiteaLabel>(`/orgs/${args.org}/labels/${args.id}`, undefined, args.token); logger.debug({ label: label.name }, 'Organization label retrieved'); return { success: true, label: { id: label.id, name: label.name, color: label.color, description: label.description, exclusive: label.exclusive, is_archived: label.is_archived, url: label.url, }, }; } /** * 更新组织 Label */ export async function updateOrgLabel( ctx: LabelToolsContext, args: { org: string; id: number; name?: string; color?: string; description?: string; exclusive?: boolean; is_archived?: boolean; token?: string; } ) { logger.debug({ args }, 'Updating organization label'); const updateOptions: UpdateLabelOptions = { name: args.name, color: args.color, description: args.description, exclusive: args.exclusive, is_archived: args.is_archived, }; const label = await ctx.client.patch<GiteaLabel>( `/orgs/${args.org}/labels/${args.id}`, updateOptions, args.token ); logger.info({ org: args.org, label: label.name }, 'Organization label updated successfully'); return { success: true, label: { id: label.id, name: label.name, color: label.color, description: label.description, exclusive: label.exclusive, is_archived: label.is_archived, url: label.url, }, }; } /** * 删除组织 Label */ export async function deleteOrgLabel( ctx: LabelToolsContext, args: { org: string; id: number; token?: string; } ) { logger.debug({ args }, 'Deleting organization label'); await ctx.client.delete(`/orgs/${args.org}/labels/${args.id}`, undefined, args.token); logger.info({ org: args.org, label_id: args.id }, 'Organization label deleted successfully'); return { success: true, message: `Label #${args.id} has been deleted from organization ${args.org}`, }; } // ============================================================ // Issue Label 操作 // ============================================================ /** * 为 Issue 添加 Labels */ export async function addIssueLabels( ctx: LabelToolsContext, args: { owner?: string; repo?: string; index: number; labels: number[]; token?: string; } ) { logger.debug({ args }, 'Adding labels to issue'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); const labels = await ctx.client.post<GiteaLabel[]>( `/repos/${owner}/${repo}/issues/${args.index}/labels`, { labels: args.labels }, args.token ); logger.info( { owner, repo, issue: args.index, labels: labels.length }, 'Labels added to issue successfully' ); return { success: true, labels: labels.map((label) => ({ id: label.id, name: label.name, color: label.color, description: label.description, })), }; } /** * 替换 Issue 的所有 Labels */ export async function replaceIssueLabels( ctx: LabelToolsContext, args: { owner?: string; repo?: string; index: number; labels: number[]; token?: string; } ) { logger.debug({ args }, 'Replacing issue labels'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); const labels = await ctx.client.put<GiteaLabel[]>( `/repos/${owner}/${repo}/issues/${args.index}/labels`, { labels: args.labels }, args.token ); logger.info( { owner, repo, issue: args.index, labels: labels.length }, 'Issue labels replaced successfully' ); return { success: true, labels: labels.map((label) => ({ id: label.id, name: label.name, color: label.color, description: label.description, })), }; } /** * 删除 Issue 的特定 Label */ export async function removeIssueLabel( ctx: LabelToolsContext, args: { owner?: string; repo?: string; index: number; id: number; token?: string; } ) { logger.debug({ args }, 'Removing label from issue'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); await ctx.client.delete(`/repos/${owner}/${repo}/issues/${args.index}/labels/${args.id}`, undefined, args.token); logger.info( { owner, repo, issue: args.index, label_id: args.id }, 'Label removed from issue successfully' ); return { success: true, message: `Label #${args.id} has been removed from issue #${args.index}`, }; } /** * 清除 Issue 的所有 Labels */ export async function clearIssueLabels( ctx: LabelToolsContext, args: { owner?: string; repo?: string; index: number; token?: string; } ) { logger.debug({ args }, 'Clearing all labels from issue'); const owner = args.owner || ctx.contextManager.getOwner(); const repo = args.repo || ctx.contextManager.getRepo(); await ctx.client.delete(`/repos/${owner}/${repo}/issues/${args.index}/labels`, undefined, args.token); logger.info( { owner, repo, issue: args.index }, 'All labels cleared from issue successfully' ); return { success: true, message: `All labels have been cleared from issue #${args.index}`, }; }

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