Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit eeb1676

Browse files
committed
feat: add Gitee branch operation tools, including create, list, and get branch functions
Signed-off-by: 诺墨 <[email protected]>
1 parent c9a174e commit eeb1676

File tree

4 files changed

+197
-0
lines changed

4 files changed

+197
-0
lines changed

common/types.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,54 @@ GiteeRepositorySchema = z.object({
117117
}).optional(),
118118
});
119119

120+
export const GiteeBranchSchema = z.object({
121+
name: z.string(),
122+
commit: z.object({
123+
sha: z.string(),
124+
url: z.string().url(),
125+
}),
126+
protected: z.boolean(),
127+
protection_url: z.string().url().optional(),
128+
});
129+
130+
export const GiteeCompleteBranchSchema = GiteeBranchSchema.extend({
131+
_links: z.object({
132+
self: z.string().url(),
133+
html: z.string().url(),
134+
}),
135+
});
136+
137+
export const GiteeCommitSchema = z.object({
138+
url: z.string().url(),
139+
sha: z.string(),
140+
html_url: z.string().url(),
141+
comments_url: z.string().url(),
142+
commit: z.object({
143+
url: z.string().url(),
144+
author: z.object({
145+
name: z.string(),
146+
email: z.string().email(),
147+
date: z.string(),
148+
}),
149+
committer: z.object({
150+
name: z.string(),
151+
email: z.string().email(),
152+
date: z.string(),
153+
}),
154+
message: z.string(),
155+
tree: z.object({
156+
url: z.string().url(),
157+
sha: z.string(),
158+
}),
159+
}),
160+
author: GiteeUserSchema.nullable(),
161+
committer: GiteeUserSchema.nullable(),
162+
parents: z.array(z.object({
163+
url: z.string().url(),
164+
sha: z.string(),
165+
})),
166+
});
167+
120168
// Type Exports
121169
export type GiteeUser = z.infer<typeof GiteeUserSchema>;
122170
export type GiteeRepository = z.infer<typeof GiteeRepositorySchema>;

common/utils.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,23 @@ export function validateOwnerName(owner: string): string {
160160
}
161161
return sanitized;
162162
}
163+
164+
export async function checkBranchExists(
165+
owner: string,
166+
repo: string,
167+
branch: string
168+
): Promise<boolean> {
169+
try {
170+
await giteeRequest(`https://gitee.com/api/v5/repos/${owner}/${repo}/branches/${branch}`, "GET");
171+
return true;
172+
} catch (error) {
173+
if (error && typeof error === "object" && "name" in error && error.name === "GiteeResourceNotFoundError") {
174+
return false;
175+
}
176+
throw error;
177+
}
178+
}
179+
163180
export async function checkUserExists(username: string): Promise<boolean> {
164181
try {
165182
await giteeRequest(`https://gitee.com/api/v5/users/${username}`, "GET");

index.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { MCPServer } from "./common/server.js";
33
import { VERSION } from "./common/version.js";
44

55
// 导入操作模块
6+
import * as branchOperations from "./operations/branches.js";
67
import * as repoOperations from "./operations/repos.js";
78
import * as userOperations from "./operations/users.js";
89
import { z } from 'zod';
@@ -64,6 +65,44 @@ export function createGiteeMCPServer() {
6465
},
6566
});
6667

68+
// 注册分支操作工具
69+
server.registerTool({
70+
name: "create_branch",
71+
description: "在 Gitee 仓库中创建一个新分支",
72+
schema: branchOperations.CreateBranchSchema,
73+
handler: async (params: any) => {
74+
const { owner, repo, branch_name, refs } = params;
75+
return await branchOperations.createBranchFromRef(owner, repo, branch_name, refs);
76+
},
77+
});
78+
79+
server.registerTool({
80+
name: "list_branches",
81+
description: "列出 Gitee 仓库中的分支",
82+
schema: branchOperations.ListBranchesSchema,
83+
handler: async (params: any) => {
84+
const { owner, repo, sort, direction, page, per_page } = params;
85+
return await branchOperations.listBranches(
86+
owner,
87+
repo,
88+
sort,
89+
direction,
90+
page,
91+
per_page
92+
);
93+
},
94+
});
95+
96+
server.registerTool({
97+
name: "get_branch",
98+
description: "获取 Gitee 仓库中的特定分支信息",
99+
schema: branchOperations.GetBranchSchema,
100+
handler: async (params: any) => {
101+
const { owner, repo, branch } = params;
102+
return await branchOperations.getBranch(owner, repo, branch);
103+
},
104+
});
105+
67106
// 注册用户操作工具
68107
server.registerTool({
69108
name: "get_user",

operations/branches.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { z } from "zod";
2+
import { giteeRequest, validateBranchName, validateOwnerName, validateRepositoryName } from "../common/utils.js";
3+
import { GiteeCompleteBranchSchema, GiteeBranchSchema } from "../common/types.js";
4+
5+
// Schema 定义
6+
export const CreateBranchSchema = z.object({
7+
owner: z.string().describe("仓库所属空间地址 (企业、组织或个人的地址 path)"),
8+
repo: z.string().describe("仓库路径 (path)"),
9+
branch_name: z.string().describe("新创建的分支名称"),
10+
refs: z.string().default("master").describe("起点名称,默认:master"),
11+
});
12+
13+
export const ListBranchesSchema = z.object({
14+
owner: z.string().describe("仓库所属空间地址 (企业、组织或个人的地址 path)"),
15+
repo: z.string().describe("仓库路径 (path)"),
16+
sort: z.enum(["name", "updated"]).default("name").optional().describe("排序字段"),
17+
direction: z.enum(["asc", "desc"]).default("asc").optional().describe("排序方向"),
18+
page: z.number().int().default(1).optional().describe("当前的页码"),
19+
per_page: z.number().int().min(1).max(100).optional().describe("每页的数量,最大为 100"),
20+
});
21+
22+
export const GetBranchSchema = z.object({
23+
owner: z.string().describe("仓库所属空间地址 (企业、组织或个人的地址 path)"),
24+
repo: z.string().describe("仓库路径 (path)"),
25+
branch: z.string().describe("分支名称"),
26+
});
27+
28+
// 类型导出
29+
export type CreateBranchOptions = z.infer<typeof CreateBranchSchema>;
30+
export type ListBranchesOptions = z.infer<typeof ListBranchesSchema>;
31+
export type GetBranchOptions = z.infer<typeof GetBranchSchema>;
32+
33+
// 函数实现
34+
export async function createBranchFromRef(
35+
owner: string,
36+
repo: string,
37+
branchName: string,
38+
refs: string = "master"
39+
) {
40+
owner = validateOwnerName(owner);
41+
repo = validateRepositoryName(repo);
42+
branchName = validateBranchName(branchName);
43+
44+
const url = `https://gitee.com/api/v5/repos/${owner}/${repo}/branches`;
45+
const body = {
46+
branch_name: branchName,
47+
refs: refs,
48+
};
49+
50+
const response = await giteeRequest(url, "POST", body);
51+
return GiteeBranchSchema.parse(response);
52+
}
53+
54+
export async function listBranches(
55+
owner: string,
56+
repo: string,
57+
sort?: string,
58+
direction?: string,
59+
page?: number,
60+
per_page?: number
61+
) {
62+
owner = validateOwnerName(owner);
63+
repo = validateRepositoryName(repo);
64+
65+
const url = new URL(`https://gitee.com/api/v5/repos/${owner}/${repo}/branches`);
66+
67+
if (sort) {
68+
url.searchParams.append("sort", sort);
69+
}
70+
if (direction) {
71+
url.searchParams.append("direction", direction);
72+
}
73+
if (page !== undefined) {
74+
url.searchParams.append("page", page.toString());
75+
}
76+
if (per_page !== undefined) {
77+
url.searchParams.append("per_page", per_page.toString());
78+
}
79+
80+
const response = await giteeRequest(url.toString());
81+
return z.array(GiteeBranchSchema).parse(response);
82+
}
83+
84+
export async function getBranch(owner: string, repo: string, branch: string) {
85+
owner = validateOwnerName(owner);
86+
repo = validateRepositoryName(repo);
87+
branch = validateBranchName(branch);
88+
89+
const url = `https://gitee.com/api/v5/repos/${owner}/${repo}/branches/${branch}`;
90+
const response = await giteeRequest(url);
91+
92+
return GiteeCompleteBranchSchema.parse(response);
93+
}

0 commit comments

Comments
 (0)