@cnbcool/mcp-server 0.4.0 → 0.4.2
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/CHANGELOG.md +33 -0
- package/README_zh.md +64 -0
- package/dist/helpers/formatToolResult.js +21 -0
- package/dist/tools/groupTools.js +11 -70
- package/dist/tools/issueTools.js +45 -208
- package/dist/tools/pullTools.js +15 -119
- package/dist/tools/repoTools.js +13 -95
- package/dist/tools/workspaceTools.js +5 -34
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
## 0.4.0 (May 8, 2025)
|
|
2
|
+
|
|
3
|
+
### New Features
|
|
4
|
+
|
|
5
|
+
- Supports streamable http server
|
|
6
|
+
- Supports backwards compatibility, sse http server
|
|
7
|
+
- Supports list, update and create pull requests
|
|
8
|
+
- Supports get current repository information
|
|
9
|
+
|
|
10
|
+
## 0.3.3 (May 7, 2025)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- Format repository creation response
|
|
15
|
+
- Format group creation response
|
|
16
|
+
|
|
17
|
+
## 0.3.2 (May 6, 2025)
|
|
18
|
+
|
|
19
|
+
### New Features
|
|
20
|
+
|
|
21
|
+
- Supports list groups with various filters
|
|
22
|
+
- Supports list sub-groups with various filters
|
|
23
|
+
- Supports get group details
|
|
24
|
+
- Supports create group
|
|
25
|
+
- Supports create repository
|
|
26
|
+
|
|
27
|
+
## 0.3.1 (April 23, 2025)
|
|
28
|
+
|
|
29
|
+
### New Features
|
|
30
|
+
|
|
31
|
+
- Bump to @modelcontextprotocol/sdk 1.10.2
|
|
32
|
+
- Add zod preprocess, convert null to undefined
|
|
33
|
+
|
|
1
34
|
## 0.3.0 (April 23, 2025)
|
|
2
35
|
|
|
3
36
|
### New Features
|
package/README_zh.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# CNB MCP Server
|
|
2
|
+
|
|
3
|
+
CNB(https://cnb.cool) 支持 MCP 协议的 MCP Server
|
|
4
|
+
|
|
5
|
+
## 使用方法
|
|
6
|
+
|
|
7
|
+
### STDIO
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"mcpServers": {
|
|
12
|
+
"cnb": {
|
|
13
|
+
"command": "npx",
|
|
14
|
+
"args": ["-y", "-p", "@cnbcool/mcp-server", "cnb-mcp-stdio"],
|
|
15
|
+
"env": {
|
|
16
|
+
"API_BASE_URL": "<BASE_URL>", // 可选,默认值: https://api.cnb.cool
|
|
17
|
+
"API_TOKEN": "<YOUR_TOKEN>"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 环境要求
|
|
25
|
+
|
|
26
|
+
1. node >= 18
|
|
27
|
+
|
|
28
|
+
## 开发指南
|
|
29
|
+
|
|
30
|
+
1. `npm install`
|
|
31
|
+
2. `npx openapi-typescript@5.4.2 https://api.cnb.cool/swagger.json -o src/schema.d.ts`
|
|
32
|
+
3. 复制 `.env.example` 并重命名为 `.env` 并填写相应值
|
|
33
|
+
4. `npm run build`
|
|
34
|
+
5. `npx @modelcontextprotocol/inspector node dist/stdio.js`
|
|
35
|
+
|
|
36
|
+
> @modelcontextprotocol/inspector 需要 Node.js: ^22.7.5
|
|
37
|
+
|
|
38
|
+
> https://github.com/modelcontextprotocol/inspector?tab=readme-ov-file#requirements
|
|
39
|
+
|
|
40
|
+
## 预览方法
|
|
41
|
+
|
|
42
|
+
1. npm run build
|
|
43
|
+
2. 设置 mcpServers 配置:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"cnb": {
|
|
49
|
+
"command": "node",
|
|
50
|
+
"args": ["/path/to/cnbcool/mcp-server/dist/stdio.js"],
|
|
51
|
+
"env": {
|
|
52
|
+
"API_BASE_URL": "<BASE_URL>", // optional, defualt vaule: https://api.cnb.cool
|
|
53
|
+
"API_TOKEN": "<YOUR_TOKEN>"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 使用CodeBuddy自动根据swagger.json补充接口MCP Tools
|
|
61
|
+
|
|
62
|
+
1. `wget https://api.cnb.cool/swagger.json -O ./swagger.json`
|
|
63
|
+
2. `npx split-swagger s ./swagger.json ./swagger`
|
|
64
|
+
3. 参考prompt.txt中提示词,调整为有变动的json文件,然后让ai代码助手执行
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function formatTextToolResult(text, toolName) {
|
|
2
|
+
return {
|
|
3
|
+
content: [
|
|
4
|
+
{
|
|
5
|
+
type: 'text',
|
|
6
|
+
text
|
|
7
|
+
}
|
|
8
|
+
]
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function formatToolError(error, toolName) {
|
|
12
|
+
return {
|
|
13
|
+
content: [
|
|
14
|
+
{
|
|
15
|
+
type: 'text',
|
|
16
|
+
text: `Error ${toolName}:\n${error instanceof Error ? error.message : String(error)}`
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
isError: true
|
|
20
|
+
};
|
|
21
|
+
}
|
package/dist/tools/groupTools.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { createGroup, getGroup, listGroups, listSubGroups } from '../api/group.js';
|
|
3
|
+
import { formatTextToolResult, formatToolError } from '../helpers/formatToolResult.js';
|
|
3
4
|
export default function registerGroupTools(server) {
|
|
4
5
|
server.tool('list-groups', '获取当前用户拥有权限的顶层组织列表', {
|
|
5
6
|
page: z.number().default(1).describe('第几页,从1开始'),
|
|
@@ -10,26 +11,11 @@ export default function registerGroupTools(server) {
|
|
|
10
11
|
.describe('最小仓库权限')
|
|
11
12
|
}, async ({ page, page_size, search, role }) => {
|
|
12
13
|
try {
|
|
13
|
-
const
|
|
14
|
-
return
|
|
15
|
-
content: [
|
|
16
|
-
{
|
|
17
|
-
type: 'text',
|
|
18
|
-
text: JSON.stringify(repos, null, 2)
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
};
|
|
14
|
+
const groups = await listGroups({ page, page_size, search, role });
|
|
15
|
+
return formatTextToolResult(JSON.stringify(groups, null, 2), 'list-groups');
|
|
22
16
|
}
|
|
23
17
|
catch (error) {
|
|
24
|
-
return
|
|
25
|
-
content: [
|
|
26
|
-
{
|
|
27
|
-
type: 'text',
|
|
28
|
-
text: `Error listing repositories: ${error instanceof Error ? error.message : String(error)}`
|
|
29
|
-
}
|
|
30
|
-
],
|
|
31
|
-
isError: true
|
|
32
|
-
};
|
|
18
|
+
return formatToolError(error, 'list-groups');
|
|
33
19
|
}
|
|
34
20
|
});
|
|
35
21
|
server.tool('list-sub-groups', '查询当前用户在指定组织下拥有指定权限的子组织列表', {
|
|
@@ -40,51 +26,21 @@ export default function registerGroupTools(server) {
|
|
|
40
26
|
}, async ({ group, page, page_size, access }) => {
|
|
41
27
|
try {
|
|
42
28
|
const subGroups = await listSubGroups(group, { page, page_size, access });
|
|
43
|
-
return
|
|
44
|
-
content: [
|
|
45
|
-
{
|
|
46
|
-
type: 'text',
|
|
47
|
-
text: JSON.stringify(subGroups, null, 2)
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
};
|
|
29
|
+
return formatTextToolResult(JSON.stringify(subGroups, null, 2), 'list-sub-groups');
|
|
51
30
|
}
|
|
52
31
|
catch (error) {
|
|
53
|
-
return
|
|
54
|
-
content: [
|
|
55
|
-
{
|
|
56
|
-
type: 'text',
|
|
57
|
-
text: `Error listing repositories: ${error instanceof Error ? error.message : String(error)}`
|
|
58
|
-
}
|
|
59
|
-
],
|
|
60
|
-
isError: true
|
|
61
|
-
};
|
|
32
|
+
return formatToolError(error, 'list-sub-groups');
|
|
62
33
|
}
|
|
63
34
|
});
|
|
64
35
|
server.tool('get-group', '获取指定组织信息', {
|
|
65
36
|
group: z.string().describe('组织路径')
|
|
66
37
|
}, async ({ group }) => {
|
|
67
38
|
try {
|
|
68
|
-
const
|
|
69
|
-
return
|
|
70
|
-
content: [
|
|
71
|
-
{
|
|
72
|
-
type: 'text',
|
|
73
|
-
text: JSON.stringify(data, null, 2)
|
|
74
|
-
}
|
|
75
|
-
]
|
|
76
|
-
};
|
|
39
|
+
const groupInfo = await getGroup(group);
|
|
40
|
+
return formatTextToolResult(JSON.stringify(groupInfo, null, 2), 'get-group');
|
|
77
41
|
}
|
|
78
42
|
catch (error) {
|
|
79
|
-
return
|
|
80
|
-
content: [
|
|
81
|
-
{
|
|
82
|
-
type: 'text',
|
|
83
|
-
text: `Error getting repository: ${error instanceof Error ? error.message : String(error)}`
|
|
84
|
-
}
|
|
85
|
-
],
|
|
86
|
-
isError: true
|
|
87
|
-
};
|
|
43
|
+
return formatToolError(error, 'get-group');
|
|
88
44
|
}
|
|
89
45
|
});
|
|
90
46
|
server.tool('create-group', '创建新组织', {
|
|
@@ -97,25 +53,10 @@ export default function registerGroupTools(server) {
|
|
|
97
53
|
}, async ({ path, description, remark, bind_domain }) => {
|
|
98
54
|
try {
|
|
99
55
|
const data = await createGroup({ path, description, remark, bind_domain });
|
|
100
|
-
return
|
|
101
|
-
content: [
|
|
102
|
-
{
|
|
103
|
-
type: 'text',
|
|
104
|
-
text: JSON.stringify(data, null, 2)
|
|
105
|
-
}
|
|
106
|
-
]
|
|
107
|
-
};
|
|
56
|
+
return formatTextToolResult(JSON.stringify(data, null, 2), 'create-group');
|
|
108
57
|
}
|
|
109
58
|
catch (error) {
|
|
110
|
-
return
|
|
111
|
-
content: [
|
|
112
|
-
{
|
|
113
|
-
type: 'text',
|
|
114
|
-
text: `Error creating repository: ${error instanceof Error ? error.message : String(error)}`
|
|
115
|
-
}
|
|
116
|
-
],
|
|
117
|
-
isError: true
|
|
118
|
-
};
|
|
59
|
+
return formatToolError(error, 'create-group');
|
|
119
60
|
}
|
|
120
61
|
});
|
|
121
62
|
}
|
package/dist/tools/issueTools.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { createIssue, createIssueComment, getIssue, listIssueComments, listIssues, updateIssue, updateIssueComment, listIssueLabels, addIssueLabels, setIssueLabels, deleteIssueLabels, deleteIssueLabel } from '../api/issue.js';
|
|
3
|
+
import { formatTextToolResult, formatToolError } from '../helpers/formatToolResult.js';
|
|
3
4
|
export default function registerIssueTools(server) {
|
|
4
5
|
server.tool('list-issues', '查询仓库的 Issues', {
|
|
5
6
|
repo: z.string().describe('仓库路径'),
|
|
@@ -43,25 +44,10 @@ export default function registerIssueTools(server) {
|
|
|
43
44
|
updated_time_end,
|
|
44
45
|
order_by
|
|
45
46
|
});
|
|
46
|
-
return
|
|
47
|
-
content: [
|
|
48
|
-
{
|
|
49
|
-
type: 'text',
|
|
50
|
-
text: JSON.stringify(issues, null, 2)
|
|
51
|
-
}
|
|
52
|
-
]
|
|
53
|
-
};
|
|
47
|
+
return formatTextToolResult(JSON.stringify(issues, null, 2), 'list-issues');
|
|
54
48
|
}
|
|
55
49
|
catch (error) {
|
|
56
|
-
return
|
|
57
|
-
content: [
|
|
58
|
-
{
|
|
59
|
-
type: 'text',
|
|
60
|
-
text: `Error listing issues: \n${error instanceof Error ? error.message : String(error)}`
|
|
61
|
-
}
|
|
62
|
-
],
|
|
63
|
-
isError: true
|
|
64
|
-
};
|
|
50
|
+
return formatToolError(error, 'list-issues');
|
|
65
51
|
}
|
|
66
52
|
});
|
|
67
53
|
server.tool('get-issue', '获取指定 Issue 信息', {
|
|
@@ -70,25 +56,10 @@ export default function registerIssueTools(server) {
|
|
|
70
56
|
}, async ({ repo, issueId }) => {
|
|
71
57
|
try {
|
|
72
58
|
const issues = await getIssue(repo, issueId);
|
|
73
|
-
return
|
|
74
|
-
content: [
|
|
75
|
-
{
|
|
76
|
-
type: 'text',
|
|
77
|
-
text: JSON.stringify(issues, null, 2)
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
};
|
|
59
|
+
return formatTextToolResult(JSON.stringify(issues, null, 2), 'get-issue');
|
|
81
60
|
}
|
|
82
61
|
catch (error) {
|
|
83
|
-
return
|
|
84
|
-
content: [
|
|
85
|
-
{
|
|
86
|
-
type: 'text',
|
|
87
|
-
text: `Error listing issues: \n${error instanceof Error ? error.message : String(error)}`
|
|
88
|
-
}
|
|
89
|
-
],
|
|
90
|
-
isError: true
|
|
91
|
-
};
|
|
62
|
+
return formatToolError(error, 'get-issue');
|
|
92
63
|
}
|
|
93
64
|
});
|
|
94
65
|
server.tool('create-issue', '创建一个 Issue. 如需添加 Issue 标签,需要另外调用 add-issue-labels', {
|
|
@@ -101,35 +72,28 @@ export default function registerIssueTools(server) {
|
|
|
101
72
|
labels: z
|
|
102
73
|
.preprocess((val) => (val === null ? undefined : val), z.array(z.string()).optional())
|
|
103
74
|
.describe('一个或多个 Issue 标签'),
|
|
104
|
-
priority: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('Issue 优先级')
|
|
105
|
-
|
|
75
|
+
priority: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('Issue 优先级'),
|
|
76
|
+
end_date: z
|
|
77
|
+
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
78
|
+
.describe('Issue 截止时间,格式为 YYYY-MM-DD'),
|
|
79
|
+
start_date: z
|
|
80
|
+
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
81
|
+
.describe('Issue 起始时间,格式为 YYYY-MM-DD')
|
|
82
|
+
}, async ({ repo, title, body, assignees, labels, priority, end_date, start_date }) => {
|
|
106
83
|
try {
|
|
107
84
|
const issue = await createIssue(repo, {
|
|
108
85
|
title,
|
|
109
86
|
body,
|
|
110
87
|
assignees,
|
|
111
88
|
labels,
|
|
112
|
-
priority
|
|
89
|
+
priority,
|
|
90
|
+
end_date,
|
|
91
|
+
start_date
|
|
113
92
|
});
|
|
114
|
-
return
|
|
115
|
-
content: [
|
|
116
|
-
{
|
|
117
|
-
type: 'text',
|
|
118
|
-
text: `Issue created successfully:\n${JSON.stringify(issue, null, 2)}`
|
|
119
|
-
}
|
|
120
|
-
]
|
|
121
|
-
};
|
|
93
|
+
return formatTextToolResult(JSON.stringify(issue, null, 2), 'create-issue');
|
|
122
94
|
}
|
|
123
95
|
catch (error) {
|
|
124
|
-
return
|
|
125
|
-
content: [
|
|
126
|
-
{
|
|
127
|
-
type: 'text',
|
|
128
|
-
text: `Error creating issue: \n${error instanceof Error ? error.message : String(error)}`
|
|
129
|
-
}
|
|
130
|
-
],
|
|
131
|
-
isError: true
|
|
132
|
-
};
|
|
96
|
+
return formatToolError(error, 'create-issue');
|
|
133
97
|
}
|
|
134
98
|
});
|
|
135
99
|
server.tool('update-issue', '更新一个 Issue。 如需更新 Issue 标签,需要另外调用 set-issue-labels', {
|
|
@@ -138,38 +102,31 @@ export default function registerIssueTools(server) {
|
|
|
138
102
|
title: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('Issue 标题'),
|
|
139
103
|
body: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('Issue 描述'),
|
|
140
104
|
priority: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('Issue 优先级'),
|
|
105
|
+
end_date: z
|
|
106
|
+
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
107
|
+
.describe('Issue 截止时间,格式为 YYYY-MM-DD'),
|
|
108
|
+
start_date: z
|
|
109
|
+
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
110
|
+
.describe('Issue 起始时间,格式为 YYYY-MM-DD'),
|
|
141
111
|
state: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('Issue 状态'),
|
|
142
112
|
state_reason: z
|
|
143
113
|
.preprocess((val) => (val === null ? undefined : val), z.enum(['completed', 'not_planned', 'reopened']).optional())
|
|
144
114
|
.describe('Issue 状态原因')
|
|
145
|
-
}, async ({ repo, issueId, title, body, priority, state, state_reason }) => {
|
|
115
|
+
}, async ({ repo, issueId, title, body, priority, end_date, start_date, state, state_reason }) => {
|
|
146
116
|
try {
|
|
147
117
|
const issue = await updateIssue(repo, issueId, {
|
|
148
118
|
title,
|
|
149
119
|
body,
|
|
150
120
|
priority,
|
|
121
|
+
end_date,
|
|
122
|
+
start_date,
|
|
151
123
|
state,
|
|
152
124
|
state_reason
|
|
153
125
|
});
|
|
154
|
-
return
|
|
155
|
-
content: [
|
|
156
|
-
{
|
|
157
|
-
type: 'text',
|
|
158
|
-
text: `Issue updated successfully:\n${JSON.stringify(issue, null, 2)}`
|
|
159
|
-
}
|
|
160
|
-
]
|
|
161
|
-
};
|
|
126
|
+
return formatTextToolResult(JSON.stringify(issue, null, 2), 'update-issue');
|
|
162
127
|
}
|
|
163
128
|
catch (error) {
|
|
164
|
-
return
|
|
165
|
-
content: [
|
|
166
|
-
{
|
|
167
|
-
type: 'text',
|
|
168
|
-
text: `Error updating issue: \n${error instanceof Error ? error.message : String(error)}`
|
|
169
|
-
}
|
|
170
|
-
],
|
|
171
|
-
isError: true
|
|
172
|
-
};
|
|
129
|
+
return formatToolError(error, 'update-issue');
|
|
173
130
|
}
|
|
174
131
|
});
|
|
175
132
|
server.tool('list-issue-comments', '查询 Issue 评论列表', {
|
|
@@ -180,25 +137,10 @@ export default function registerIssueTools(server) {
|
|
|
180
137
|
}, async ({ repo, issueId, page, page_size }) => {
|
|
181
138
|
try {
|
|
182
139
|
const comments = await listIssueComments(repo, issueId, { page, page_size });
|
|
183
|
-
return
|
|
184
|
-
content: [
|
|
185
|
-
{
|
|
186
|
-
type: 'text',
|
|
187
|
-
text: JSON.stringify(comments, null, 2)
|
|
188
|
-
}
|
|
189
|
-
]
|
|
190
|
-
};
|
|
140
|
+
return formatTextToolResult(JSON.stringify(comments, null, 2), 'list-issue-comments');
|
|
191
141
|
}
|
|
192
142
|
catch (error) {
|
|
193
|
-
return
|
|
194
|
-
content: [
|
|
195
|
-
{
|
|
196
|
-
type: 'text',
|
|
197
|
-
text: `Error listing issue comments: \n${error instanceof Error ? error.message : String(error)}`
|
|
198
|
-
}
|
|
199
|
-
],
|
|
200
|
-
isError: true
|
|
201
|
-
};
|
|
143
|
+
return formatToolError(error, 'list-issue-comments');
|
|
202
144
|
}
|
|
203
145
|
});
|
|
204
146
|
server.tool('create-issue-comment', '创建一个 Issue 评论', {
|
|
@@ -208,25 +150,10 @@ export default function registerIssueTools(server) {
|
|
|
208
150
|
}, async ({ repo, issueId, body }) => {
|
|
209
151
|
try {
|
|
210
152
|
const comment = await createIssueComment(repo, issueId, { body });
|
|
211
|
-
return
|
|
212
|
-
content: [
|
|
213
|
-
{
|
|
214
|
-
type: 'text',
|
|
215
|
-
text: `Comment created successfully:\n${JSON.stringify(comment, null, 2)}`
|
|
216
|
-
}
|
|
217
|
-
]
|
|
218
|
-
};
|
|
153
|
+
return formatTextToolResult(JSON.stringify(comment, null, 2), 'create-issue-comment');
|
|
219
154
|
}
|
|
220
155
|
catch (error) {
|
|
221
|
-
return
|
|
222
|
-
content: [
|
|
223
|
-
{
|
|
224
|
-
type: 'text',
|
|
225
|
-
text: `Error creating comment: \n${error instanceof Error ? error.message : String(error)}`
|
|
226
|
-
}
|
|
227
|
-
],
|
|
228
|
-
isError: true
|
|
229
|
-
};
|
|
156
|
+
return formatToolError(error, 'create-issue-comment');
|
|
230
157
|
}
|
|
231
158
|
});
|
|
232
159
|
server.tool('update-issue-comment', '更新一个 Issue 评论', {
|
|
@@ -237,25 +164,10 @@ export default function registerIssueTools(server) {
|
|
|
237
164
|
}, async ({ repo, issueId, commentId, body }) => {
|
|
238
165
|
try {
|
|
239
166
|
const comment = await updateIssueComment(repo, issueId, commentId, { body });
|
|
240
|
-
return
|
|
241
|
-
content: [
|
|
242
|
-
{
|
|
243
|
-
type: 'text',
|
|
244
|
-
text: `Comment updated successfully:\n${JSON.stringify(comment, null, 2)}`
|
|
245
|
-
}
|
|
246
|
-
]
|
|
247
|
-
};
|
|
167
|
+
return formatTextToolResult(JSON.stringify(comment, null, 2), 'update-issue-comment');
|
|
248
168
|
}
|
|
249
169
|
catch (error) {
|
|
250
|
-
return
|
|
251
|
-
content: [
|
|
252
|
-
{
|
|
253
|
-
type: 'text',
|
|
254
|
-
text: `Error updating comment: \n${error instanceof Error ? error.message : String(error)}`
|
|
255
|
-
}
|
|
256
|
-
],
|
|
257
|
-
isError: true
|
|
258
|
-
};
|
|
170
|
+
return formatToolError(error, 'update-issue-comment');
|
|
259
171
|
}
|
|
260
172
|
});
|
|
261
173
|
server.tool('list-issue-labels', '查询指定Issue的标签', {
|
|
@@ -264,25 +176,10 @@ export default function registerIssueTools(server) {
|
|
|
264
176
|
}, async ({ repo, issueId }) => {
|
|
265
177
|
try {
|
|
266
178
|
const labels = await listIssueLabels(repo, issueId);
|
|
267
|
-
return
|
|
268
|
-
content: [
|
|
269
|
-
{
|
|
270
|
-
type: 'text',
|
|
271
|
-
text: JSON.stringify(labels, null, 2)
|
|
272
|
-
}
|
|
273
|
-
]
|
|
274
|
-
};
|
|
179
|
+
return formatTextToolResult(JSON.stringify(labels, null, 2), 'list-issue-labels');
|
|
275
180
|
}
|
|
276
181
|
catch (error) {
|
|
277
|
-
return
|
|
278
|
-
content: [
|
|
279
|
-
{
|
|
280
|
-
type: 'text',
|
|
281
|
-
text: `Error listing issue labels: \n${error instanceof Error ? error.message : String(error)}`
|
|
282
|
-
}
|
|
283
|
-
],
|
|
284
|
-
isError: true
|
|
285
|
-
};
|
|
182
|
+
return formatToolError(error, 'list-issue-labels');
|
|
286
183
|
}
|
|
287
184
|
});
|
|
288
185
|
server.tool('add-issue-labels', '为指定Issue添加标签', {
|
|
@@ -292,25 +189,10 @@ export default function registerIssueTools(server) {
|
|
|
292
189
|
}, async ({ repo, issueId, labels }) => {
|
|
293
190
|
try {
|
|
294
191
|
const result = await addIssueLabels(repo, issueId, labels);
|
|
295
|
-
return
|
|
296
|
-
content: [
|
|
297
|
-
{
|
|
298
|
-
type: 'text',
|
|
299
|
-
text: `Labels added successfully:\n${JSON.stringify(result, null, 2)}`
|
|
300
|
-
}
|
|
301
|
-
]
|
|
302
|
-
};
|
|
192
|
+
return formatTextToolResult(JSON.stringify(result, null, 2), 'add-issue-labels');
|
|
303
193
|
}
|
|
304
194
|
catch (error) {
|
|
305
|
-
return
|
|
306
|
-
content: [
|
|
307
|
-
{
|
|
308
|
-
type: 'text',
|
|
309
|
-
text: `Error adding labels: \n${error instanceof Error ? error.message : String(error)}`
|
|
310
|
-
}
|
|
311
|
-
],
|
|
312
|
-
isError: true
|
|
313
|
-
};
|
|
195
|
+
return formatToolError(error, 'add-issue-labels');
|
|
314
196
|
}
|
|
315
197
|
});
|
|
316
198
|
server.tool('set-issue-labels', '设置Issue的标签(替换所有现有标签)', {
|
|
@@ -320,25 +202,10 @@ export default function registerIssueTools(server) {
|
|
|
320
202
|
}, async ({ repo, issueId, labels }) => {
|
|
321
203
|
try {
|
|
322
204
|
const result = await setIssueLabels(repo, issueId, labels);
|
|
323
|
-
return
|
|
324
|
-
content: [
|
|
325
|
-
{
|
|
326
|
-
type: 'text',
|
|
327
|
-
text: `Labels set successfully:\n${JSON.stringify(result, null, 2)}`
|
|
328
|
-
}
|
|
329
|
-
]
|
|
330
|
-
};
|
|
205
|
+
return formatTextToolResult(JSON.stringify(result, null, 2), 'set-issue-labels');
|
|
331
206
|
}
|
|
332
207
|
catch (error) {
|
|
333
|
-
return
|
|
334
|
-
content: [
|
|
335
|
-
{
|
|
336
|
-
type: 'text',
|
|
337
|
-
text: `Error setting labels: \n${error instanceof Error ? error.message : String(error)}`
|
|
338
|
-
}
|
|
339
|
-
],
|
|
340
|
-
isError: true
|
|
341
|
-
};
|
|
208
|
+
return formatToolError(error, 'set-issue-labels');
|
|
342
209
|
}
|
|
343
210
|
});
|
|
344
211
|
server.tool('delete-issue-labels', '删除Issue的所有标签', {
|
|
@@ -347,25 +214,10 @@ export default function registerIssueTools(server) {
|
|
|
347
214
|
}, async ({ repo, issueId }) => {
|
|
348
215
|
try {
|
|
349
216
|
await deleteIssueLabels(repo, issueId);
|
|
350
|
-
return
|
|
351
|
-
content: [
|
|
352
|
-
{
|
|
353
|
-
type: 'text',
|
|
354
|
-
text: 'All labels deleted successfully'
|
|
355
|
-
}
|
|
356
|
-
]
|
|
357
|
-
};
|
|
217
|
+
return formatTextToolResult('All labels deleted', 'delete-issue-labels');
|
|
358
218
|
}
|
|
359
219
|
catch (error) {
|
|
360
|
-
return
|
|
361
|
-
content: [
|
|
362
|
-
{
|
|
363
|
-
type: 'text',
|
|
364
|
-
text: `Error deleting labels: \n${error instanceof Error ? error.message : String(error)}`
|
|
365
|
-
}
|
|
366
|
-
],
|
|
367
|
-
isError: true
|
|
368
|
-
};
|
|
220
|
+
return formatToolError(error, 'delete-issue-labels');
|
|
369
221
|
}
|
|
370
222
|
});
|
|
371
223
|
server.tool('delete-issue-label', '删除Issue的指定标签', {
|
|
@@ -375,25 +227,10 @@ export default function registerIssueTools(server) {
|
|
|
375
227
|
}, async ({ repo, issueId, labelName }) => {
|
|
376
228
|
try {
|
|
377
229
|
await deleteIssueLabel(repo, issueId, labelName);
|
|
378
|
-
return {
|
|
379
|
-
content: [
|
|
380
|
-
{
|
|
381
|
-
type: 'text',
|
|
382
|
-
text: `Label "${labelName}" deleted successfully`
|
|
383
|
-
}
|
|
384
|
-
]
|
|
385
|
-
};
|
|
230
|
+
return formatTextToolResult(`${labelName} deleted`, 'delete-issue-label');
|
|
386
231
|
}
|
|
387
232
|
catch (error) {
|
|
388
|
-
return
|
|
389
|
-
content: [
|
|
390
|
-
{
|
|
391
|
-
type: 'text',
|
|
392
|
-
text: `Error deleting label: \n${error instanceof Error ? error.message : String(error)}`
|
|
393
|
-
}
|
|
394
|
-
],
|
|
395
|
-
isError: true
|
|
396
|
-
};
|
|
233
|
+
return formatToolError(error, 'delete-issue-label');
|
|
397
234
|
}
|
|
398
235
|
});
|
|
399
236
|
}
|
package/dist/tools/pullTools.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { listPulls, getPull, createPull, updatePull, mergePull, listPullComments, createPullComment } from '../api/pull.js';
|
|
3
|
+
import { formatTextToolResult, formatToolError } from '../helpers/formatToolResult.js';
|
|
3
4
|
export default function registerPullTools(server) {
|
|
4
5
|
server.tool('list-pulls', '查询仓库的Pull Requests', {
|
|
5
6
|
repo: z.string().describe('仓库路径,格式为 {group}/{repo}'),
|
|
@@ -17,25 +18,10 @@ export default function registerPullTools(server) {
|
|
|
17
18
|
}, async ({ repo, ...params }) => {
|
|
18
19
|
try {
|
|
19
20
|
const pulls = await listPulls(repo, params);
|
|
20
|
-
return
|
|
21
|
-
content: [
|
|
22
|
-
{
|
|
23
|
-
type: 'text',
|
|
24
|
-
text: JSON.stringify(pulls, null, 2)
|
|
25
|
-
}
|
|
26
|
-
]
|
|
27
|
-
};
|
|
21
|
+
return formatTextToolResult(JSON.stringify(pulls, null, 2), 'list-pulls');
|
|
28
22
|
}
|
|
29
23
|
catch (error) {
|
|
30
|
-
return
|
|
31
|
-
content: [
|
|
32
|
-
{
|
|
33
|
-
type: 'text',
|
|
34
|
-
text: `Error listing pulls: \n${error instanceof Error ? error.message : String(error)}`
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
isError: true
|
|
38
|
-
};
|
|
24
|
+
return formatToolError(error, 'list-pulls');
|
|
39
25
|
}
|
|
40
26
|
});
|
|
41
27
|
server.tool('get-pull', '获取单个Pull Request详情', {
|
|
@@ -44,25 +30,10 @@ export default function registerPullTools(server) {
|
|
|
44
30
|
}, async ({ repo, number }) => {
|
|
45
31
|
try {
|
|
46
32
|
const pull = await getPull(repo, number);
|
|
47
|
-
return
|
|
48
|
-
content: [
|
|
49
|
-
{
|
|
50
|
-
type: 'text',
|
|
51
|
-
text: JSON.stringify(pull, null, 2)
|
|
52
|
-
}
|
|
53
|
-
]
|
|
54
|
-
};
|
|
33
|
+
return formatTextToolResult(JSON.stringify(pull, null, 2), 'get-pull');
|
|
55
34
|
}
|
|
56
35
|
catch (error) {
|
|
57
|
-
return
|
|
58
|
-
content: [
|
|
59
|
-
{
|
|
60
|
-
type: 'text',
|
|
61
|
-
text: `Error getting pull request: \n${error instanceof Error ? error.message : String(error)}`
|
|
62
|
-
}
|
|
63
|
-
],
|
|
64
|
-
isError: true
|
|
65
|
-
};
|
|
36
|
+
return formatToolError(error, 'get-pull');
|
|
66
37
|
}
|
|
67
38
|
});
|
|
68
39
|
server.tool('create-pull', '创建Pull Request', {
|
|
@@ -75,25 +46,10 @@ export default function registerPullTools(server) {
|
|
|
75
46
|
}, async ({ repo, ...params }) => {
|
|
76
47
|
try {
|
|
77
48
|
const pull = await createPull(repo, params);
|
|
78
|
-
return
|
|
79
|
-
content: [
|
|
80
|
-
{
|
|
81
|
-
type: 'text',
|
|
82
|
-
text: JSON.stringify(pull, null, 2)
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
};
|
|
49
|
+
return formatTextToolResult(JSON.stringify(pull, null, 2), 'create-pull');
|
|
86
50
|
}
|
|
87
51
|
catch (error) {
|
|
88
|
-
return
|
|
89
|
-
content: [
|
|
90
|
-
{
|
|
91
|
-
type: 'text',
|
|
92
|
-
text: `Error creating pull request: \n${error instanceof Error ? error.message : String(error)}`
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
isError: true
|
|
96
|
-
};
|
|
52
|
+
return formatToolError(error, 'create-pull');
|
|
97
53
|
}
|
|
98
54
|
});
|
|
99
55
|
server.tool('update-pull', '更新Pull Request', {
|
|
@@ -107,25 +63,10 @@ export default function registerPullTools(server) {
|
|
|
107
63
|
}, async ({ repo, number, ...params }) => {
|
|
108
64
|
try {
|
|
109
65
|
const pull = await updatePull(repo, number, params);
|
|
110
|
-
return
|
|
111
|
-
content: [
|
|
112
|
-
{
|
|
113
|
-
type: 'text',
|
|
114
|
-
text: JSON.stringify(pull, null, 2)
|
|
115
|
-
}
|
|
116
|
-
]
|
|
117
|
-
};
|
|
66
|
+
return formatTextToolResult(JSON.stringify(pull, null, 2), 'update-pull');
|
|
118
67
|
}
|
|
119
68
|
catch (error) {
|
|
120
|
-
return
|
|
121
|
-
content: [
|
|
122
|
-
{
|
|
123
|
-
type: 'text',
|
|
124
|
-
text: `Error updating pull request: \n${error instanceof Error ? error.message : String(error)}`
|
|
125
|
-
}
|
|
126
|
-
],
|
|
127
|
-
isError: true
|
|
128
|
-
};
|
|
69
|
+
return formatToolError(error, 'update-pull');
|
|
129
70
|
}
|
|
130
71
|
});
|
|
131
72
|
server.tool('merge-pull', '合并Pull Request', {
|
|
@@ -141,25 +82,10 @@ export default function registerPullTools(server) {
|
|
|
141
82
|
}, async ({ repo, number, ...params }) => {
|
|
142
83
|
try {
|
|
143
84
|
const result = await mergePull(repo, number, params);
|
|
144
|
-
return
|
|
145
|
-
content: [
|
|
146
|
-
{
|
|
147
|
-
type: 'text',
|
|
148
|
-
text: JSON.stringify(result, null, 2)
|
|
149
|
-
}
|
|
150
|
-
]
|
|
151
|
-
};
|
|
85
|
+
return formatTextToolResult(JSON.stringify(result, null, 2), 'merge-pull');
|
|
152
86
|
}
|
|
153
87
|
catch (error) {
|
|
154
|
-
return
|
|
155
|
-
content: [
|
|
156
|
-
{
|
|
157
|
-
type: 'text',
|
|
158
|
-
text: `Error merging pull request: \n${error instanceof Error ? error.message : String(error)}`
|
|
159
|
-
}
|
|
160
|
-
],
|
|
161
|
-
isError: true
|
|
162
|
-
};
|
|
88
|
+
return formatToolError(error, 'merge-pull');
|
|
163
89
|
}
|
|
164
90
|
});
|
|
165
91
|
server.tool('list-pull-comments', '列出Pull Request的评论', {
|
|
@@ -170,25 +96,10 @@ export default function registerPullTools(server) {
|
|
|
170
96
|
}, async ({ repo, number, ...params }) => {
|
|
171
97
|
try {
|
|
172
98
|
const comments = await listPullComments(repo, number, params);
|
|
173
|
-
return
|
|
174
|
-
content: [
|
|
175
|
-
{
|
|
176
|
-
type: 'text',
|
|
177
|
-
text: JSON.stringify(comments, null, 2)
|
|
178
|
-
}
|
|
179
|
-
]
|
|
180
|
-
};
|
|
99
|
+
return formatTextToolResult(JSON.stringify(comments, null, 2), 'list-pull-comments');
|
|
181
100
|
}
|
|
182
101
|
catch (error) {
|
|
183
|
-
return
|
|
184
|
-
content: [
|
|
185
|
-
{
|
|
186
|
-
type: 'text',
|
|
187
|
-
text: `Error listing pull request comments: \n${error instanceof Error ? error.message : String(error)}`
|
|
188
|
-
}
|
|
189
|
-
],
|
|
190
|
-
isError: true
|
|
191
|
-
};
|
|
102
|
+
return formatToolError(error, 'list-pull-comments');
|
|
192
103
|
}
|
|
193
104
|
});
|
|
194
105
|
server.tool('create-pull-comment', '创建Pull Request评论', {
|
|
@@ -198,25 +109,10 @@ export default function registerPullTools(server) {
|
|
|
198
109
|
}, async ({ repo, number, body }) => {
|
|
199
110
|
try {
|
|
200
111
|
await createPullComment(repo, number, { body });
|
|
201
|
-
return
|
|
202
|
-
content: [
|
|
203
|
-
{
|
|
204
|
-
type: 'text',
|
|
205
|
-
text: JSON.stringify({ message: 'Comment created successfully' }, null, 2)
|
|
206
|
-
}
|
|
207
|
-
]
|
|
208
|
-
};
|
|
112
|
+
return formatTextToolResult('Comment created', 'create-pull-comment');
|
|
209
113
|
}
|
|
210
114
|
catch (error) {
|
|
211
|
-
return
|
|
212
|
-
content: [
|
|
213
|
-
{
|
|
214
|
-
type: 'text',
|
|
215
|
-
text: `Error creating pull request comment: \n${error instanceof Error ? error.message : String(error)}`
|
|
216
|
-
}
|
|
217
|
-
],
|
|
218
|
-
isError: true
|
|
219
|
-
};
|
|
115
|
+
return formatToolError(error, 'create-pull-comment');
|
|
220
116
|
}
|
|
221
117
|
});
|
|
222
118
|
}
|
package/dist/tools/repoTools.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { createRepository, getRepository, listGroupRepositories, listRepositories } from '../api/repository.js';
|
|
3
3
|
import { getUser } from '../api/user.js';
|
|
4
|
+
import { formatTextToolResult, formatToolError } from '../helpers/formatToolResult.js';
|
|
4
5
|
export default function registerRepoTools(server) {
|
|
5
6
|
server.tool('list-repositories', '获取当前用户拥有指定权限及其以上权限的仓库', {
|
|
6
7
|
page: z.number().default(1).describe('第几页,从1开始,默认值是1'),
|
|
@@ -21,25 +22,10 @@ export default function registerRepoTools(server) {
|
|
|
21
22
|
}, async ({ page, page_size, search, filter_type, role, order_by, desc }) => {
|
|
22
23
|
try {
|
|
23
24
|
const repos = await listRepositories({ page, page_size, search, filter_type, role, order_by, desc });
|
|
24
|
-
return
|
|
25
|
-
content: [
|
|
26
|
-
{
|
|
27
|
-
type: 'text',
|
|
28
|
-
text: JSON.stringify(repos, null, 2)
|
|
29
|
-
}
|
|
30
|
-
]
|
|
31
|
-
};
|
|
25
|
+
return formatTextToolResult(JSON.stringify(repos, null, 2), 'list-repositories');
|
|
32
26
|
}
|
|
33
27
|
catch (error) {
|
|
34
|
-
return
|
|
35
|
-
content: [
|
|
36
|
-
{
|
|
37
|
-
type: 'text',
|
|
38
|
-
text: `Error listing repositories: ${error instanceof Error ? error.message : String(error)}`
|
|
39
|
-
}
|
|
40
|
-
],
|
|
41
|
-
isError: true
|
|
42
|
-
};
|
|
28
|
+
return formatToolError(error, 'list-repositories');
|
|
43
29
|
}
|
|
44
30
|
});
|
|
45
31
|
server.tool('list-group-repositories', '获取分组里当前用户有权限的仓库', {
|
|
@@ -70,51 +56,21 @@ export default function registerRepoTools(server) {
|
|
|
70
56
|
order_by,
|
|
71
57
|
desc
|
|
72
58
|
});
|
|
73
|
-
return
|
|
74
|
-
content: [
|
|
75
|
-
{
|
|
76
|
-
type: 'text',
|
|
77
|
-
text: JSON.stringify(repos, null, 2)
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
};
|
|
59
|
+
return formatTextToolResult(JSON.stringify(repos, null, 2), 'list-group-repositories');
|
|
81
60
|
}
|
|
82
61
|
catch (error) {
|
|
83
|
-
return
|
|
84
|
-
content: [
|
|
85
|
-
{
|
|
86
|
-
type: 'text',
|
|
87
|
-
text: `Error listing repositories: ${error instanceof Error ? error.message : String(error)}`
|
|
88
|
-
}
|
|
89
|
-
],
|
|
90
|
-
isError: true
|
|
91
|
-
};
|
|
62
|
+
return formatToolError(error, 'list-group-repositories');
|
|
92
63
|
}
|
|
93
64
|
});
|
|
94
65
|
server.tool('get-repository', '获取指定仓库信息', {
|
|
95
66
|
repo: z.string().describe('仓库路径')
|
|
96
67
|
}, async ({ repo }) => {
|
|
97
68
|
try {
|
|
98
|
-
const
|
|
99
|
-
return
|
|
100
|
-
content: [
|
|
101
|
-
{
|
|
102
|
-
type: 'text',
|
|
103
|
-
text: JSON.stringify(data, null, 2)
|
|
104
|
-
}
|
|
105
|
-
]
|
|
106
|
-
};
|
|
69
|
+
const repoInfo = await getRepository(repo);
|
|
70
|
+
return formatTextToolResult(JSON.stringify(repoInfo, null, 2), 'get-repository');
|
|
107
71
|
}
|
|
108
72
|
catch (error) {
|
|
109
|
-
return
|
|
110
|
-
content: [
|
|
111
|
-
{
|
|
112
|
-
type: 'text',
|
|
113
|
-
text: `Error getting repository: ${error instanceof Error ? error.message : String(error)}`
|
|
114
|
-
}
|
|
115
|
-
],
|
|
116
|
-
isError: true
|
|
117
|
-
};
|
|
73
|
+
return formatToolError(error, 'get-repository');
|
|
118
74
|
}
|
|
119
75
|
});
|
|
120
76
|
server.tool('create-repository', '创建仓库', {
|
|
@@ -133,25 +89,10 @@ export default function registerRepoTools(server) {
|
|
|
133
89
|
}
|
|
134
90
|
try {
|
|
135
91
|
const data = await createRepository(repoGroup, { name, description, license, visibility });
|
|
136
|
-
return
|
|
137
|
-
content: [
|
|
138
|
-
{
|
|
139
|
-
type: 'text',
|
|
140
|
-
text: JSON.stringify(data, null, 2)
|
|
141
|
-
}
|
|
142
|
-
]
|
|
143
|
-
};
|
|
92
|
+
return formatTextToolResult(JSON.stringify(data, null, 2), 'create-repository');
|
|
144
93
|
}
|
|
145
94
|
catch (error) {
|
|
146
|
-
return
|
|
147
|
-
content: [
|
|
148
|
-
{
|
|
149
|
-
type: 'text',
|
|
150
|
-
text: `Error creating repository: ${error instanceof Error ? error.message : String(error)}`
|
|
151
|
-
}
|
|
152
|
-
],
|
|
153
|
-
isError: true
|
|
154
|
-
};
|
|
95
|
+
return formatToolError(error, 'create-repository');
|
|
155
96
|
}
|
|
156
97
|
});
|
|
157
98
|
server.tool('get-current-repo', '获取当前仓库对应的CNB仓库信息', {
|
|
@@ -174,37 +115,14 @@ export default function registerRepoTools(server) {
|
|
|
174
115
|
}
|
|
175
116
|
}
|
|
176
117
|
if (!repoPath) {
|
|
177
|
-
return {
|
|
178
|
-
content: [
|
|
179
|
-
{
|
|
180
|
-
type: 'text',
|
|
181
|
-
text: `无法从远程仓库URL解析出仓库路径: ${remote_url}`
|
|
182
|
-
}
|
|
183
|
-
],
|
|
184
|
-
isError: true
|
|
185
|
-
};
|
|
118
|
+
return formatToolError(`无法从远程仓库URL解析出仓库路径: ${remote_url}`, 'get-current-repo');
|
|
186
119
|
}
|
|
187
120
|
// 获取仓库信息
|
|
188
121
|
const data = await getRepository(repoPath);
|
|
189
|
-
return
|
|
190
|
-
content: [
|
|
191
|
-
{
|
|
192
|
-
type: 'text',
|
|
193
|
-
text: JSON.stringify(data, null, 2)
|
|
194
|
-
}
|
|
195
|
-
]
|
|
196
|
-
};
|
|
122
|
+
return formatTextToolResult(JSON.stringify(data, null, 2), 'get-current-repo');
|
|
197
123
|
}
|
|
198
124
|
catch (error) {
|
|
199
|
-
return
|
|
200
|
-
content: [
|
|
201
|
-
{
|
|
202
|
-
type: 'text',
|
|
203
|
-
text: `Error getting current repository: ${error instanceof Error ? error.message : String(error)}`
|
|
204
|
-
}
|
|
205
|
-
],
|
|
206
|
-
isError: true
|
|
207
|
-
};
|
|
125
|
+
return formatToolError(error, 'get-current-repo');
|
|
208
126
|
}
|
|
209
127
|
});
|
|
210
128
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { deleteWorkspace, listWorkspace } from '../api/workspace.js';
|
|
3
|
+
import { formatTextToolResult, formatToolError } from '../helpers/formatToolResult.js';
|
|
3
4
|
export default function registerWorkspaceTools(server) {
|
|
4
5
|
server.tool('list-workspace', '获取我的云原生开发环境列表', {
|
|
5
6
|
branch: z
|
|
@@ -34,25 +35,10 @@ export default function registerWorkspaceTools(server) {
|
|
|
34
35
|
slug,
|
|
35
36
|
status
|
|
36
37
|
});
|
|
37
|
-
return
|
|
38
|
-
content: [
|
|
39
|
-
{
|
|
40
|
-
type: 'text',
|
|
41
|
-
text: JSON.stringify(workspaces, null, 2)
|
|
42
|
-
}
|
|
43
|
-
]
|
|
44
|
-
};
|
|
38
|
+
return formatTextToolResult(JSON.stringify(workspaces, null, 2), 'list-workspace');
|
|
45
39
|
}
|
|
46
40
|
catch (error) {
|
|
47
|
-
return
|
|
48
|
-
content: [
|
|
49
|
-
{
|
|
50
|
-
type: 'text',
|
|
51
|
-
text: `Error listing workspace: ${error instanceof Error ? error.message : String(error)}`
|
|
52
|
-
}
|
|
53
|
-
],
|
|
54
|
-
isError: true
|
|
55
|
-
};
|
|
41
|
+
return formatToolError(error, 'list-workspace');
|
|
56
42
|
}
|
|
57
43
|
});
|
|
58
44
|
server.tool('delete-workspace', '删除我的云原生开发环境', {
|
|
@@ -62,25 +48,10 @@ export default function registerWorkspaceTools(server) {
|
|
|
62
48
|
const result = await deleteWorkspace({
|
|
63
49
|
pipelineId
|
|
64
50
|
});
|
|
65
|
-
return
|
|
66
|
-
content: [
|
|
67
|
-
{
|
|
68
|
-
type: 'text',
|
|
69
|
-
text: JSON.stringify(result, null, 2)
|
|
70
|
-
}
|
|
71
|
-
]
|
|
72
|
-
};
|
|
51
|
+
return formatTextToolResult(JSON.stringify(result, null, 2), 'delete-workspace');
|
|
73
52
|
}
|
|
74
53
|
catch (error) {
|
|
75
|
-
return
|
|
76
|
-
content: [
|
|
77
|
-
{
|
|
78
|
-
type: 'text',
|
|
79
|
-
text: `error delete workspace: ${error instanceof Error ? error.message : String(error)}`
|
|
80
|
-
}
|
|
81
|
-
],
|
|
82
|
-
isError: true
|
|
83
|
-
};
|
|
54
|
+
return formatToolError(error, 'delete-workspace');
|
|
84
55
|
}
|
|
85
56
|
});
|
|
86
57
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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.2",
|
|
5
5
|
"main": "./dist/stdio.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cnb-mcp-stdio": "dist/stdio.js",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"dist/",
|
|
34
34
|
"package.json",
|
|
35
35
|
"CHANGELOG.md",
|
|
36
|
-
"README.md"
|
|
36
|
+
"README.md",
|
|
37
|
+
"README_zh.md"
|
|
37
38
|
],
|
|
38
39
|
"engines": {
|
|
39
40
|
"node": ">= 18",
|