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
JavaScript
/**
* 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;
}
}