UNPKG

cnb-mcp-server

Version:

MCP Server for the cnb API, enabling file operations, repository management, search functionality, and more.

294 lines (293 loc) 11.2 kB
/** * Issue操作 */ import { z } from 'zod'; import { getQueryParams } from '../common/utils.js'; // 创建Issue参数Schema export const CreateIssueSchema = z.object({ owner: z.string().describe('仓库拥有者'), repo: z.string().describe('仓库名称'), title: z.string().describe('Issue标题'), body: z.string().optional().describe('Issue内容'), assignees: z.array(z.string()).optional().describe('指派给哪些用户'), labels: z.array(z.string()).optional().describe('标签列表'), priority: z.string().optional().describe('优先级') }); // 获取Issue参数Schema export const GetIssueSchema = z.object({ owner: z.string().describe('仓库拥有者'), repo: z.string().describe('仓库名称'), issue_number: z.number().describe('Issue编号') }); // 更新Issue参数Schema export const UpdateIssueOptionsSchema = z.object({ owner: z.string().describe('仓库拥有者'), repo: z.string().describe('仓库名称'), issue_number: z.number().describe('Issue编号'), title: z.string().optional().describe('Issue标题'), body: z.string().optional().describe('Issue内容'), state: z.enum(['open', 'closed']).optional().describe('Issue状态'), assignees: z.array(z.string()).optional().describe('指派给哪些用户'), labels: z.array(z.string()).optional().describe('标签列表'), priority: z.string().optional().describe('优先级') }); // 列出Issue参数Schema export const ListIssuesOptionsSchema = z.object({ owner: z.string().describe('仓库拥有者'), repo: z.string().describe('仓库名称'), state: z.enum(['open', 'closed', 'all']).default('open').describe('Issue状态'), labels: z.string().optional().describe('标签,多个标签用逗号分隔'), sort: z.enum(['created', 'updated', 'comments']).default('created').describe('排序字段'), direction: z.enum(['asc', 'desc']).default('desc').describe('排序方向'), since: z.string().optional().describe('筛选在此日期之后更新的Issue, ISO日期格式'), page: z.number().default(1).describe('页码'), perPage: z.number().default(30).describe('每页数量') }); // Issue评论参数Schema export const IssueCommentSchema = z.object({ owner: z.string().describe('仓库拥有者'), repo: z.string().describe('仓库名称'), issue_number: z.number().describe('Issue编号'), body: z.string().describe('评论内容') }); /** * 创建Issue */ export async function createIssue(owner, repo, title, body, assignees, labels, priority, accessToken) { try { const requestBody = { title }; if (body) { requestBody.body = body; } if (assignees && assignees.length > 0) { requestBody.assignees = assignees; } if (labels && labels.length > 0) { requestBody.labels = labels; } if (priority) { requestBody.priority = priority; } console.log(`创建Issue: ${owner}/${repo} - ${title}`); const token = accessToken || process.env.CNB_ACCESS_TOKEN || ''; const url = `https://api.cnb.cool/${owner}/${repo}/-/issues`; const headers = { 'accept': 'application/json', 'Authorization': token, 'Content-Type': 'application/json' }; // 直接使用fetch发送请求 const response = await fetch(url, { method: 'POST', headers, body: JSON.stringify(requestBody) }); console.log(`创建Issue响应状态: ${response.status}`); if (response.ok) { const result = await response.json(); console.log(`Issue创建成功: #${result.number}`); return result; } else { // 处理错误 const errorText = await response.text(); console.log('创建Issue错误:', errorText); throw new Error(`创建Issue失败: ${response.status} ${errorText}`); } } catch (error) { console.log('创建Issue请求错误:', error instanceof Error ? error.message : String(error)); throw error; } } /** * 获取Issue */ export async function getIssue(owner, repo, issueNumber, accessToken) { try { console.log(`获取Issue信息: ${owner}/${repo}#${issueNumber}`); const token = accessToken || process.env.CNB_ACCESS_TOKEN || ''; const url = `https://api.cnb.cool/${owner}/${repo}/-/issues/${issueNumber}`; const headers = { 'accept': 'application/json', 'Authorization': token }; // 直接使用fetch发送请求 const response = await fetch(url, { method: 'GET', headers }); console.log(`获取Issue响应状态: ${response.status}`); if (response.ok) { const result = await response.json(); console.log('获取Issue成功'); return result; } else { // 处理错误 const errorText = await response.text(); console.log('获取Issue错误:', errorText); throw new Error(`获取Issue失败: ${response.status} ${errorText}`); } } catch (error) { console.log('获取Issue请求错误:', error instanceof Error ? error.message : String(error)); throw error; } } /** * 更新Issue */ export async function updateIssue(owner, repo, issueNumber, updateData, accessToken) { try { console.log(`更新Issue: ${owner}/${repo}#${issueNumber}`); const token = accessToken || process.env.CNB_ACCESS_TOKEN || ''; const url = `https://api.cnb.cool/${owner}/${repo}/-/issues/${issueNumber}`; const headers = { 'accept': 'application/json', 'Authorization': token, 'Content-Type': 'application/json' }; // 直接使用fetch发送请求 const response = await fetch(url, { method: 'PATCH', headers, body: JSON.stringify(updateData) }); console.log(`更新Issue响应状态: ${response.status}`); if (response.ok) { const result = await response.json(); console.log(`Issue更新成功: #${result.number}`); return result; } else { // 处理错误 const errorText = await response.text(); console.log('更新Issue错误:', errorText); throw new Error(`更新Issue失败: ${response.status} ${errorText}`); } } catch (error) { console.log('更新Issue请求错误:', error instanceof Error ? error.message : String(error)); throw error; } } /** * 列出仓库的Issue */ export async function listIssues(owner, repo, options = {}, accessToken) { try { const params = getQueryParams({ page: options.page || 1, page_size: options.perPage || 30, state: options.state, labels: options.labels, sort: options.sort, direction: options.direction, since: options.since }); console.log(`列出Issue: ${owner}/${repo}${params}`); const token = accessToken || process.env.CNB_ACCESS_TOKEN || ''; const url = `https://api.cnb.cool/${owner}/${repo}/-/issues${params}`; const headers = { 'accept': 'application/json', 'Authorization': token }; // 直接使用fetch发送请求 const response = await fetch(url, { method: 'GET', headers }); console.log(`列出Issue响应状态: ${response.status}`); if (response.ok) { const result = await response.json(); console.log(`找到 ${result.length} 个Issue`); return result; } else { // 处理错误 const errorText = await response.text(); console.log('列出Issue错误:', errorText); throw new Error(`列出Issue失败: ${response.status} ${errorText}`); } } catch (error) { console.log('列出Issue请求错误:', error instanceof Error ? error.message : String(error)); throw error; } } /** * 添加Issue评论 */ export async function addIssueComment(owner, repo, issueNumber, body, accessToken) { try { console.log(`添加Issue评论: ${owner}/${repo}#${issueNumber}`); const token = accessToken || process.env.CNB_ACCESS_TOKEN || ''; const url = `https://api.cnb.cool/${owner}/${repo}/-/issues/${issueNumber}/comments`; const headers = { 'accept': 'application/json', 'Authorization': token, 'Content-Type': 'application/json' }; // 直接使用fetch发送请求 const response = await fetch(url, { method: 'POST', headers, body: JSON.stringify({ body }) }); console.log(`添加Issue评论响应状态: ${response.status}`); if (response.ok) { const result = await response.json(); console.log(`Issue评论添加成功: ${result.id}`); return result; } else { // 处理错误 const errorText = await response.text(); console.log('添加Issue评论错误:', errorText); throw new Error(`添加Issue评论失败: ${response.status} ${errorText}`); } } catch (error) { console.log('添加Issue评论请求错误:', error instanceof Error ? error.message : String(error)); throw error; } } /** * 获取Issue评论 */ export async function getIssueComments(owner, repo, issueNumber, page = 1, perPage = 30, accessToken) { try { const params = getQueryParams({ page, page_size: perPage }); console.log(`获取Issue评论: ${owner}/${repo}#${issueNumber}${params}`); const token = accessToken || process.env.CNB_ACCESS_TOKEN || ''; const url = `https://api.cnb.cool/${owner}/${repo}/-/issues/${issueNumber}/comments${params}`; const headers = { 'accept': 'application/json', 'Authorization': token }; // 直接使用fetch发送请求 const response = await fetch(url, { method: 'GET', headers }); console.log(`获取Issue评论响应状态: ${response.status}`); if (response.ok) { const result = await response.json(); console.log(`获取Issue评论成功,共 ${result.length} 条评论`); return result; } else { // 处理错误 const errorText = await response.text(); console.log('获取Issue评论错误:', errorText); throw new Error(`获取Issue评论失败: ${response.status} ${errorText}`); } } catch (error) { console.log('获取Issue评论请求错误:', error instanceof Error ? error.message : String(error)); throw error; } }