@cnbcool/mcp-server 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.js +4 -1
- package/dist/api/group.js +18 -9
- package/dist/api/issue.js +42 -25
- package/dist/api/pull.js +27 -15
- package/dist/api/repository.js +18 -9
- package/dist/api/user.js +9 -3
- package/dist/api/workspace.js +12 -5
- package/dist/helpers/createMcpServer.js +10 -8
- package/dist/helpers/formatToolResult.js +6 -2
- package/dist/helpers/sendResponse.js +4 -1
- package/dist/stdio.js +11 -6
- package/dist/streamable.js +26 -21
- package/dist/tools/groupTools.js +34 -31
- package/dist/tools/index.js +19 -13
- package/dist/tools/issueTools.js +112 -109
- package/dist/tools/pullTools.js +65 -62
- package/dist/tools/repoTools.js +56 -53
- package/dist/tools/workspaceTools.js +28 -25
- package/package.json +3 -4
package/dist/tools/repoTools.js
CHANGED
|
@@ -1,53 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = registerRepoTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const repository_js_1 = require("../api/repository.js");
|
|
6
|
+
const user_js_1 = require("../api/user.js");
|
|
7
|
+
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
8
|
+
function registerRepoTools(server) {
|
|
6
9
|
server.tool('list-repositories', '获取当前用户拥有指定权限及其以上权限的仓库', {
|
|
7
|
-
page: z.number().default(1).describe('第几页,从1开始,默认值是1'),
|
|
8
|
-
page_size: z.number().default(10).describe('每页多少条数据,默认值为10'),
|
|
9
|
-
search: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('查询关键字'),
|
|
10
|
-
filter_type: z
|
|
11
|
-
.preprocess((val) => (val === null ? undefined : val), z.enum(['private', 'public', 'encrypted']).optional())
|
|
10
|
+
page: zod_1.z.number().default(1).describe('第几页,从1开始,默认值是1'),
|
|
11
|
+
page_size: zod_1.z.number().default(10).describe('每页多少条数据,默认值为10'),
|
|
12
|
+
search: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('查询关键字'),
|
|
13
|
+
filter_type: zod_1.z
|
|
14
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['private', 'public', 'encrypted']).optional())
|
|
12
15
|
.describe('仓库类型,为空表示所有仓库类型,默认值为空'),
|
|
13
|
-
role: z
|
|
14
|
-
.preprocess((val) => (val === null ? undefined : val), z.enum(['Reporter', 'Developer', 'Master', 'Owner']).optional())
|
|
16
|
+
role: zod_1.z
|
|
17
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['Reporter', 'Developer', 'Master', 'Owner']).optional())
|
|
15
18
|
.describe('最小仓库权限,当用户未指定角色时,需要主动传入Reporter'),
|
|
16
|
-
order_by: z
|
|
17
|
-
.preprocess((val) => (val === null ? undefined : val), z.enum(['created_at', 'last_updated_at', 'stars']).optional())
|
|
19
|
+
order_by: zod_1.z
|
|
20
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['created_at', 'last_updated_at', 'stars']).optional())
|
|
18
21
|
.describe('排序类型,默认值是last_updated_at'),
|
|
19
|
-
desc: z
|
|
20
|
-
.preprocess((val) => (val === null ? undefined : val), z.boolean().optional())
|
|
22
|
+
desc: zod_1.z
|
|
23
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.boolean().optional())
|
|
21
24
|
.describe('是否开启倒叙排序,默认值是false')
|
|
22
25
|
}, async ({ page, page_size, search, filter_type, role, order_by, desc }) => {
|
|
23
26
|
try {
|
|
24
|
-
const repos = await listRepositories({ page, page_size, search, filter_type, role, order_by, desc });
|
|
25
|
-
return formatTextToolResult(JSON.stringify(repos, null, 2), 'list-repositories');
|
|
27
|
+
const repos = await (0, repository_js_1.listRepositories)({ page, page_size, search, filter_type, role, order_by, desc });
|
|
28
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repos, null, 2), 'list-repositories');
|
|
26
29
|
}
|
|
27
30
|
catch (error) {
|
|
28
|
-
return formatToolError(error, 'list-repositories');
|
|
31
|
+
return (0, formatToolResult_js_1.formatToolError)(error, 'list-repositories');
|
|
29
32
|
}
|
|
30
33
|
});
|
|
31
34
|
server.tool('list-group-repositories', '获取分组里当前用户有权限的仓库', {
|
|
32
|
-
group: z.string().describe('组织名称'),
|
|
33
|
-
page: z.number().default(1).describe('第几页,从1开始,默认值是1'),
|
|
34
|
-
page_size: z.number().default(10).describe('每页多少条数据,默认值为10'),
|
|
35
|
-
search: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库关键字'),
|
|
36
|
-
filter_type: z
|
|
37
|
-
.preprocess((val) => (val === null ? undefined : val), z.enum(['private', 'public', 'encrypted']).optional())
|
|
35
|
+
group: zod_1.z.string().describe('组织名称'),
|
|
36
|
+
page: zod_1.z.number().default(1).describe('第几页,从1开始,默认值是1'),
|
|
37
|
+
page_size: zod_1.z.number().default(10).describe('每页多少条数据,默认值为10'),
|
|
38
|
+
search: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库关键字'),
|
|
39
|
+
filter_type: zod_1.z
|
|
40
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['private', 'public', 'encrypted']).optional())
|
|
38
41
|
.describe('仓库类型'),
|
|
39
|
-
descendant: z
|
|
40
|
-
.preprocess((val) => (val === null ? undefined : val), z.enum(['all', 'sub', 'grand']).optional())
|
|
42
|
+
descendant: zod_1.z
|
|
43
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['all', 'sub', 'grand']).optional())
|
|
41
44
|
.describe('查全部、直接属于当前组织的仓库、子组织的仓库'),
|
|
42
|
-
order_by: z
|
|
43
|
-
.preprocess((val) => (val === null ? undefined : val), z.enum(['created_at', 'last_updated_at', 'stars', 'slug_path']).optional())
|
|
45
|
+
order_by: zod_1.z
|
|
46
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['created_at', 'last_updated_at', 'stars', 'slug_path']).optional())
|
|
44
47
|
.describe('排序类型'),
|
|
45
|
-
desc: z
|
|
46
|
-
.preprocess((val) => (val === null ? undefined : val), z.boolean().optional())
|
|
48
|
+
desc: zod_1.z
|
|
49
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.boolean().optional())
|
|
47
50
|
.describe('是否开启倒叙排序,默认值是false')
|
|
48
51
|
}, async ({ group, page, page_size, search, filter_type, descendant, order_by, desc }) => {
|
|
49
52
|
try {
|
|
50
|
-
const repos = await listGroupRepositories(group, {
|
|
53
|
+
const repos = await (0, repository_js_1.listGroupRepositories)(group, {
|
|
51
54
|
page,
|
|
52
55
|
page_size,
|
|
53
56
|
search,
|
|
@@ -56,47 +59,47 @@ export default function registerRepoTools(server) {
|
|
|
56
59
|
order_by,
|
|
57
60
|
desc
|
|
58
61
|
});
|
|
59
|
-
return formatTextToolResult(JSON.stringify(repos, null, 2), 'list-group-repositories');
|
|
62
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repos, null, 2), 'list-group-repositories');
|
|
60
63
|
}
|
|
61
64
|
catch (error) {
|
|
62
|
-
return formatToolError(error, 'list-group-repositories');
|
|
65
|
+
return (0, formatToolResult_js_1.formatToolError)(error, 'list-group-repositories');
|
|
63
66
|
}
|
|
64
67
|
});
|
|
65
68
|
server.tool('get-repository', '获取指定仓库信息', {
|
|
66
|
-
repo: z.string().describe('仓库路径')
|
|
69
|
+
repo: zod_1.z.string().describe('仓库路径')
|
|
67
70
|
}, async ({ repo }) => {
|
|
68
71
|
try {
|
|
69
|
-
const repoInfo = await getRepository(repo);
|
|
70
|
-
return formatTextToolResult(JSON.stringify(repoInfo, null, 2), 'get-repository');
|
|
72
|
+
const repoInfo = await (0, repository_js_1.getRepository)(repo);
|
|
73
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repoInfo, null, 2), 'get-repository');
|
|
71
74
|
}
|
|
72
75
|
catch (error) {
|
|
73
|
-
return formatToolError(error, 'get-repository');
|
|
76
|
+
return (0, formatToolResult_js_1.formatToolError)(error, 'get-repository');
|
|
74
77
|
}
|
|
75
78
|
});
|
|
76
79
|
server.tool('create-repository', '创建仓库', {
|
|
77
|
-
group: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库所属分组'),
|
|
78
|
-
name: z.string().describe('仓库名称'),
|
|
79
|
-
description: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库描述'),
|
|
80
|
-
license: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库许可'),
|
|
81
|
-
visibility: z
|
|
82
|
-
.preprocess((val) => (val === null ? undefined : val), z.enum(['public', 'private', 'secret']).default('public'))
|
|
80
|
+
group: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库所属分组'),
|
|
81
|
+
name: zod_1.z.string().describe('仓库名称'),
|
|
82
|
+
description: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库描述'),
|
|
83
|
+
license: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库许可'),
|
|
84
|
+
visibility: zod_1.z
|
|
85
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['public', 'private', 'secret']).default('public'))
|
|
83
86
|
.describe('仓库可见性')
|
|
84
87
|
}, async ({ group, name, description, license, visibility }) => {
|
|
85
88
|
let repoGroup = group;
|
|
86
89
|
if (!repoGroup) {
|
|
87
|
-
const { username = '' } = await getUser();
|
|
90
|
+
const { username = '' } = await (0, user_js_1.getUser)();
|
|
88
91
|
repoGroup = username;
|
|
89
92
|
}
|
|
90
93
|
try {
|
|
91
|
-
const data = await createRepository(repoGroup, { name, description, license, visibility });
|
|
92
|
-
return formatTextToolResult(JSON.stringify(data, null, 2), 'create-repository');
|
|
94
|
+
const data = await (0, repository_js_1.createRepository)(repoGroup, { name, description, license, visibility });
|
|
95
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), 'create-repository');
|
|
93
96
|
}
|
|
94
97
|
catch (error) {
|
|
95
|
-
return formatToolError(error, 'create-repository');
|
|
98
|
+
return (0, formatToolResult_js_1.formatToolError)(error, 'create-repository');
|
|
96
99
|
}
|
|
97
100
|
});
|
|
98
101
|
server.tool('get-current-repo', '获取当前仓库对应的CNB仓库信息', {
|
|
99
|
-
remote_url: z.string().describe('远程仓库URL, 需要先执行`git remote get-url origin`命令获取')
|
|
102
|
+
remote_url: zod_1.z.string().describe('远程仓库URL, 需要先执行`git remote get-url origin`命令获取')
|
|
100
103
|
}, async ({ remote_url }) => {
|
|
101
104
|
try {
|
|
102
105
|
let repoPath = '';
|
|
@@ -115,14 +118,14 @@ export default function registerRepoTools(server) {
|
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
120
|
if (!repoPath) {
|
|
118
|
-
return formatToolError(`无法从远程仓库URL解析出仓库路径: ${remote_url}`, 'get-current-repo');
|
|
121
|
+
return (0, formatToolResult_js_1.formatToolError)(`无法从远程仓库URL解析出仓库路径: ${remote_url}`, 'get-current-repo');
|
|
119
122
|
}
|
|
120
123
|
// 获取仓库信息
|
|
121
|
-
const data = await getRepository(repoPath);
|
|
122
|
-
return formatTextToolResult(JSON.stringify(data, null, 2), 'get-current-repo');
|
|
124
|
+
const data = await (0, repository_js_1.getRepository)(repoPath);
|
|
125
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), 'get-current-repo');
|
|
123
126
|
}
|
|
124
127
|
catch (error) {
|
|
125
|
-
return formatToolError(error, 'get-current-repo');
|
|
128
|
+
return (0, formatToolResult_js_1.formatToolError)(error, 'get-current-repo');
|
|
126
129
|
}
|
|
127
130
|
});
|
|
128
131
|
}
|
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = registerWorkspaceTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const workspace_js_1 = require("../api/workspace.js");
|
|
6
|
+
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
7
|
+
function registerWorkspaceTools(server) {
|
|
5
8
|
server.tool('list-workspace', '获取我的云原生开发环境列表', {
|
|
6
|
-
branch: z
|
|
7
|
-
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
9
|
+
branch: zod_1.z
|
|
10
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
|
|
8
11
|
.describe('分支名,例如:main'),
|
|
9
|
-
start: z
|
|
10
|
-
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
12
|
+
start: zod_1.z
|
|
13
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
|
|
11
14
|
.describe('查询结束时间,格式:YYYY-MM-DD HH:mm:ssZZ,例如:2024-12-01 00:00:00+0800'),
|
|
12
|
-
end: z
|
|
13
|
-
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
15
|
+
end: zod_1.z
|
|
16
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
|
|
14
17
|
.describe('查询开始时间,格式:YYYY-MM-DD HH:mm:ssZZ,例如:2024-12-01 00:00:00+0800'),
|
|
15
|
-
page: z
|
|
16
|
-
.preprocess((val) => (val === null ? undefined : val), z.number().optional())
|
|
18
|
+
page: zod_1.z
|
|
19
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.number().optional())
|
|
17
20
|
.describe('分页页码,从 1 开始,默认为 1'),
|
|
18
|
-
page_size: z
|
|
19
|
-
.preprocess((val) => (val === null ? undefined : val), z.number().optional())
|
|
21
|
+
page_size: zod_1.z
|
|
22
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.number().optional())
|
|
20
23
|
.describe('每页条数,默认为 20,最高 100'),
|
|
21
|
-
slug: z
|
|
22
|
-
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
24
|
+
slug: zod_1.z
|
|
25
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
|
|
23
26
|
.describe('仓库路径,例如:groupname/reponame'),
|
|
24
|
-
status: z
|
|
25
|
-
.preprocess((val) => (val === null ? undefined : val), z.enum(['running', 'closed']).optional())
|
|
27
|
+
status: zod_1.z
|
|
28
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['running', 'closed']).optional())
|
|
26
29
|
.describe('开发环境状态,running: 开发环境已启动,closed:开发环境已关闭,默认为所有状态')
|
|
27
30
|
}, async ({ branch, page, page_size, start, end, slug, status }) => {
|
|
28
31
|
try {
|
|
29
|
-
const workspaces = await listWorkspace({
|
|
32
|
+
const workspaces = await (0, workspace_js_1.listWorkspace)({
|
|
30
33
|
branch,
|
|
31
34
|
page,
|
|
32
35
|
pageSize: page_size,
|
|
@@ -35,23 +38,23 @@ export default function registerWorkspaceTools(server) {
|
|
|
35
38
|
slug,
|
|
36
39
|
status
|
|
37
40
|
});
|
|
38
|
-
return formatTextToolResult(JSON.stringify(workspaces, null, 2), 'list-workspace');
|
|
41
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(workspaces, null, 2), 'list-workspace');
|
|
39
42
|
}
|
|
40
43
|
catch (error) {
|
|
41
|
-
return formatToolError(error, 'list-workspace');
|
|
44
|
+
return (0, formatToolResult_js_1.formatToolError)(error, 'list-workspace');
|
|
42
45
|
}
|
|
43
46
|
});
|
|
44
47
|
server.tool('delete-workspace', '删除我的云原生开发环境', {
|
|
45
|
-
pipelineId: z.string().describe('开发环境 ID')
|
|
48
|
+
pipelineId: zod_1.z.string().describe('开发环境 ID')
|
|
46
49
|
}, async ({ pipelineId }) => {
|
|
47
50
|
try {
|
|
48
|
-
const result = await deleteWorkspace({
|
|
51
|
+
const result = await (0, workspace_js_1.deleteWorkspace)({
|
|
49
52
|
pipelineId
|
|
50
53
|
});
|
|
51
|
-
return formatTextToolResult(JSON.stringify(result, null, 2), 'delete-workspace');
|
|
54
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), 'delete-workspace');
|
|
52
55
|
}
|
|
53
56
|
catch (error) {
|
|
54
|
-
return formatToolError(error, 'delete-workspace');
|
|
57
|
+
return (0, formatToolResult_js_1.formatToolError)(error, 'delete-workspace');
|
|
55
58
|
}
|
|
56
59
|
});
|
|
57
60
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cnbcool/mcp-server",
|
|
3
3
|
"description": "CNB MCP Server. A comprehensive MCP server that provides seamless integration to the CNB's API(https://cnb.cool), offering a wide range of tools for repository management, pipelines operations and collaboration features",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.3",
|
|
5
5
|
"main": "./dist/stdio.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cnb-mcp-stdio": "dist/stdio.js",
|
|
8
8
|
"cnb-mcp-streamable": "dist/streamable.js"
|
|
9
9
|
},
|
|
10
|
-
"type": "module",
|
|
11
10
|
"scripts": {
|
|
12
11
|
"build": "tsc",
|
|
13
12
|
"watch": "tsc --watch",
|
|
@@ -50,10 +49,10 @@
|
|
|
50
49
|
"@commitlint/cli": "19.8.0",
|
|
51
50
|
"@commitlint/config-conventional": "19.8.0",
|
|
52
51
|
"@eslint/js": "9.24.0",
|
|
53
|
-
"@modelcontextprotocol/inspector": "^0.
|
|
52
|
+
"@modelcontextprotocol/inspector": "^0.16.2",
|
|
54
53
|
"@types/express": "5.0.1",
|
|
55
54
|
"@types/node": "22.13.9",
|
|
56
|
-
"eslint": "9.
|
|
55
|
+
"eslint": "^9.32.0",
|
|
57
56
|
"eslint-config-prettier": "10.1.2",
|
|
58
57
|
"eslint-plugin-prettier": "5.2.6",
|
|
59
58
|
"globals": "16.0.0",
|