@cnbcool/mcp-server 0.4.0 → 0.4.1
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 +25 -204
- 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', {
|
|
@@ -111,25 +82,10 @@ export default function registerIssueTools(server) {
|
|
|
111
82
|
labels,
|
|
112
83
|
priority
|
|
113
84
|
});
|
|
114
|
-
return
|
|
115
|
-
content: [
|
|
116
|
-
{
|
|
117
|
-
type: 'text',
|
|
118
|
-
text: `Issue created successfully:\n${JSON.stringify(issue, null, 2)}`
|
|
119
|
-
}
|
|
120
|
-
]
|
|
121
|
-
};
|
|
85
|
+
return formatTextToolResult(JSON.stringify(issue, null, 2), 'create-issue');
|
|
122
86
|
}
|
|
123
87
|
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
|
-
};
|
|
88
|
+
return formatToolError(error, 'create-issue');
|
|
133
89
|
}
|
|
134
90
|
});
|
|
135
91
|
server.tool('update-issue', '更新一个 Issue。 如需更新 Issue 标签,需要另外调用 set-issue-labels', {
|
|
@@ -151,25 +107,10 @@ export default function registerIssueTools(server) {
|
|
|
151
107
|
state,
|
|
152
108
|
state_reason
|
|
153
109
|
});
|
|
154
|
-
return
|
|
155
|
-
content: [
|
|
156
|
-
{
|
|
157
|
-
type: 'text',
|
|
158
|
-
text: `Issue updated successfully:\n${JSON.stringify(issue, null, 2)}`
|
|
159
|
-
}
|
|
160
|
-
]
|
|
161
|
-
};
|
|
110
|
+
return formatTextToolResult(JSON.stringify(issue, null, 2), 'update-issue');
|
|
162
111
|
}
|
|
163
112
|
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
|
-
};
|
|
113
|
+
return formatToolError(error, 'update-issue');
|
|
173
114
|
}
|
|
174
115
|
});
|
|
175
116
|
server.tool('list-issue-comments', '查询 Issue 评论列表', {
|
|
@@ -180,25 +121,10 @@ export default function registerIssueTools(server) {
|
|
|
180
121
|
}, async ({ repo, issueId, page, page_size }) => {
|
|
181
122
|
try {
|
|
182
123
|
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
|
-
};
|
|
124
|
+
return formatTextToolResult(JSON.stringify(comments, null, 2), 'list-issue-comments');
|
|
191
125
|
}
|
|
192
126
|
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
|
-
};
|
|
127
|
+
return formatToolError(error, 'list-issue-comments');
|
|
202
128
|
}
|
|
203
129
|
});
|
|
204
130
|
server.tool('create-issue-comment', '创建一个 Issue 评论', {
|
|
@@ -208,25 +134,10 @@ export default function registerIssueTools(server) {
|
|
|
208
134
|
}, async ({ repo, issueId, body }) => {
|
|
209
135
|
try {
|
|
210
136
|
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
|
-
};
|
|
137
|
+
return formatTextToolResult(JSON.stringify(comment, null, 2), 'create-issue-comment');
|
|
219
138
|
}
|
|
220
139
|
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
|
-
};
|
|
140
|
+
return formatToolError(error, 'create-issue-comment');
|
|
230
141
|
}
|
|
231
142
|
});
|
|
232
143
|
server.tool('update-issue-comment', '更新一个 Issue 评论', {
|
|
@@ -237,25 +148,10 @@ export default function registerIssueTools(server) {
|
|
|
237
148
|
}, async ({ repo, issueId, commentId, body }) => {
|
|
238
149
|
try {
|
|
239
150
|
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
|
-
};
|
|
151
|
+
return formatTextToolResult(JSON.stringify(comment, null, 2), 'update-issue-comment');
|
|
248
152
|
}
|
|
249
153
|
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
|
-
};
|
|
154
|
+
return formatToolError(error, 'update-issue-comment');
|
|
259
155
|
}
|
|
260
156
|
});
|
|
261
157
|
server.tool('list-issue-labels', '查询指定Issue的标签', {
|
|
@@ -264,25 +160,10 @@ export default function registerIssueTools(server) {
|
|
|
264
160
|
}, async ({ repo, issueId }) => {
|
|
265
161
|
try {
|
|
266
162
|
const labels = await listIssueLabels(repo, issueId);
|
|
267
|
-
return
|
|
268
|
-
content: [
|
|
269
|
-
{
|
|
270
|
-
type: 'text',
|
|
271
|
-
text: JSON.stringify(labels, null, 2)
|
|
272
|
-
}
|
|
273
|
-
]
|
|
274
|
-
};
|
|
163
|
+
return formatTextToolResult(JSON.stringify(labels, null, 2), 'list-issue-labels');
|
|
275
164
|
}
|
|
276
165
|
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
|
-
};
|
|
166
|
+
return formatToolError(error, 'list-issue-labels');
|
|
286
167
|
}
|
|
287
168
|
});
|
|
288
169
|
server.tool('add-issue-labels', '为指定Issue添加标签', {
|
|
@@ -292,25 +173,10 @@ export default function registerIssueTools(server) {
|
|
|
292
173
|
}, async ({ repo, issueId, labels }) => {
|
|
293
174
|
try {
|
|
294
175
|
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
|
-
};
|
|
176
|
+
return formatTextToolResult(JSON.stringify(result, null, 2), 'add-issue-labels');
|
|
303
177
|
}
|
|
304
178
|
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
|
-
};
|
|
179
|
+
return formatToolError(error, 'add-issue-labels');
|
|
314
180
|
}
|
|
315
181
|
});
|
|
316
182
|
server.tool('set-issue-labels', '设置Issue的标签(替换所有现有标签)', {
|
|
@@ -320,25 +186,10 @@ export default function registerIssueTools(server) {
|
|
|
320
186
|
}, async ({ repo, issueId, labels }) => {
|
|
321
187
|
try {
|
|
322
188
|
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
|
-
};
|
|
189
|
+
return formatTextToolResult(JSON.stringify(result, null, 2), 'set-issue-labels');
|
|
331
190
|
}
|
|
332
191
|
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
|
-
};
|
|
192
|
+
return formatToolError(error, 'set-issue-labels');
|
|
342
193
|
}
|
|
343
194
|
});
|
|
344
195
|
server.tool('delete-issue-labels', '删除Issue的所有标签', {
|
|
@@ -347,25 +198,10 @@ export default function registerIssueTools(server) {
|
|
|
347
198
|
}, async ({ repo, issueId }) => {
|
|
348
199
|
try {
|
|
349
200
|
await deleteIssueLabels(repo, issueId);
|
|
350
|
-
return
|
|
351
|
-
content: [
|
|
352
|
-
{
|
|
353
|
-
type: 'text',
|
|
354
|
-
text: 'All labels deleted successfully'
|
|
355
|
-
}
|
|
356
|
-
]
|
|
357
|
-
};
|
|
201
|
+
return formatTextToolResult('All labels deleted', 'delete-issue-labels');
|
|
358
202
|
}
|
|
359
203
|
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
|
-
};
|
|
204
|
+
return formatToolError(error, 'delete-issue-labels');
|
|
369
205
|
}
|
|
370
206
|
});
|
|
371
207
|
server.tool('delete-issue-label', '删除Issue的指定标签', {
|
|
@@ -375,25 +211,10 @@ export default function registerIssueTools(server) {
|
|
|
375
211
|
}, async ({ repo, issueId, labelName }) => {
|
|
376
212
|
try {
|
|
377
213
|
await deleteIssueLabel(repo, issueId, labelName);
|
|
378
|
-
return {
|
|
379
|
-
content: [
|
|
380
|
-
{
|
|
381
|
-
type: 'text',
|
|
382
|
-
text: `Label "${labelName}" deleted successfully`
|
|
383
|
-
}
|
|
384
|
-
]
|
|
385
|
-
};
|
|
214
|
+
return formatTextToolResult(`${labelName} deleted`, 'delete-issue-label');
|
|
386
215
|
}
|
|
387
216
|
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
|
-
};
|
|
217
|
+
return formatToolError(error, 'delete-issue-label');
|
|
397
218
|
}
|
|
398
219
|
});
|
|
399
220
|
}
|
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.1",
|
|
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",
|