@cnbcool/mcp-server 0.4.3 → 0.4.5
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/README.md +35 -2
- package/README_zh.md +35 -0
- package/dist/api/client.js +2 -4
- package/dist/constants/index.js +9 -0
- package/dist/constants/toolDescriptions.js +41 -0
- package/dist/constants/toolNames.js +41 -0
- package/dist/helpers/checkRepoVisibility.js +19 -0
- package/dist/helpers/createMcpServer.js +2 -1
- package/dist/helpers/createTransport.js +45 -0
- package/dist/helpers/formatRepoUrl.js +21 -0
- package/dist/helpers/sendResponse.js +3 -3
- package/dist/streamable.js +15 -51
- package/dist/tools/groupTools.js +14 -12
- package/dist/tools/issueTools.js +38 -36
- package/dist/tools/pullTools.js +23 -21
- package/dist/tools/repoTools.js +27 -32
- package/dist/tools/workspaceTools.js +8 -6
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
CNB(https://cnb.cool) toolkits for LLMs supporting the MCP protocol
|
|
4
4
|
|
|
5
|
+
## Tool List
|
|
6
|
+
|
|
7
|
+
| Tool Name | Tool Description |
|
|
8
|
+
| :----- | :------- |
|
|
9
|
+
| cnb_list_groups | Gets a list of top-level organizations for which the current user has permissions on the CNB platform. |
|
|
10
|
+
| cnb_list_sub_groups | Gets a list of sub-organizations for which the current user has permissions on the CNB platform under a specified organization. |
|
|
11
|
+
| cnb_get_group | Gets information about a specified organization on the CNB platform. |
|
|
12
|
+
| cnb_create_group | Creates a new organization on the CNB platform. |
|
|
13
|
+
| cnb_list_repositories | Gets a list of repositories for which the current user has permissions on the CNB platform. |
|
|
14
|
+
| cnb_list_group_repositories | Gets a list of repositories for which the current user has permissions on the CNB platform under a specified organization. |
|
|
15
|
+
| cnb_get_current_repository | Gets information about the CNB platform repository corresponding to the current workspace. |
|
|
16
|
+
| cnb_get_repository | Gets information about a specified repository on the CNB platform. |
|
|
17
|
+
| cnb_create_repository | Create a new repository on the CNB platform. |
|
|
18
|
+
| cnb_list_issues | Get a list of issues in a specified repository on the CNB platform. |
|
|
19
|
+
| cnb_get_issue | Get information about a specified issue on the CNB platform. |
|
|
20
|
+
| cnb_create_issue | Create a new issue in a specified repository on the CNB platform. To add labels, use the cnb_add_issue_labels tool. |
|
|
21
|
+
| cnb_update_issue | Update information about a specified issue on the CNB platform. To update labels, call the cnb_set_issue_labels tool separately. |
|
|
22
|
+
| cnb_list_issue_comments | Get a list of comments for a specified issue on the CNB platform. |
|
|
23
|
+
| cnb_create_issue_comment | Create a new comment on a specified issue on the CNB platform. |
|
|
24
|
+
| cnb_update_issue_comment | Update the content of a comment on a specified issue on the CNB platform. |
|
|
25
|
+
| cnb_list_issue_labels | Get a list of labels for a specified issue on the CNB platform. |
|
|
26
|
+
| cnb_add_issue_labels | Add one or more labels to a specified issue on the CNB platform. |
|
|
27
|
+
| cnb_set_issue_labels | Change the labels for a specified issue on the CNB platform. |
|
|
28
|
+
| cnb_clear_issue_labels | Clear the labels for a specified issue on the CNB platform. |
|
|
29
|
+
| cnb_remove_issue_label | Remove a specified label from a specified issue on the CNB platform. |
|
|
30
|
+
| cnb_list_pulls | Get a list of merge requests for a specified repository on the CNB platform. |
|
|
31
|
+
| cnb_get_pull | Get information about a merge request specified on the CNB platform |
|
|
32
|
+
| cnb_create_pull | Create a new merge request in a repository specified on the CNB platform |
|
|
33
|
+
| cnb_update_pull | Update information about a merge request specified on the CNB platform |
|
|
34
|
+
| cnb_merge_pull | Merge a merge request specified on the CNB platform |
|
|
35
|
+
| cnb_list_pull_comments | Get a list of comments for a merge request specified on the CNB platform |
|
|
36
|
+
| cnb_create_pull_comment | Create a new comment on a merge request specified on the CNB platform |
|
|
37
|
+
| cnb_list_workspaces | Get a list of the current user's cloud-native development environments on the CNB platform |
|
|
38
|
+
| cnb_delete_workspace | Delete a specified cloud-native development environment on the CNB platform |
|
|
39
|
+
|
|
5
40
|
## How to use
|
|
6
41
|
|
|
7
42
|
### STDIO
|
|
@@ -57,5 +92,3 @@ CNB(https://cnb.cool) toolkits for LLMs supporting the MCP protocol
|
|
|
57
92
|
}
|
|
58
93
|
}
|
|
59
94
|
```
|
|
60
|
-
|
|
61
|
-
|
package/README_zh.md
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
CNB(https://cnb.cool) 支持 MCP 协议的 MCP Server
|
|
4
4
|
|
|
5
|
+
## 工具列表
|
|
6
|
+
|
|
7
|
+
| 工具名 | 工具描述 |
|
|
8
|
+
| :----- | :------- |
|
|
9
|
+
| cnb_list_groups | 获取当前用户在CNB平台里拥有权限的顶层组织列表 |
|
|
10
|
+
| cnb_list_sub_groups | 获取当前用户在CNB平台里指定组织下拥有权限的子组织列表 |
|
|
11
|
+
| cnb_get_group | 获取CNB平台指定组织的信息 |
|
|
12
|
+
| cnb_create_group | 在CNB平台创建一个新组织 |
|
|
13
|
+
| cnb_list_repositories | 获取当前用户在CNB平台里拥有权限的仓库列表 |
|
|
14
|
+
| cnb_list_group_repositories | 获取当前用户在CNB平台里指定组织下拥有权限的仓库列表 |
|
|
15
|
+
| cnb_get_current_repository | 获取当前工作区对应的CNB平台仓库信息 |
|
|
16
|
+
| cnb_get_repository | 获取CNB平台指定仓库的信息 |
|
|
17
|
+
| cnb_create_repository | 在CNB平台创建一个新仓库 |
|
|
18
|
+
| cnb_list_issues | 获取CNB平台指定仓库的ISSUE列表 |
|
|
19
|
+
| cnb_get_issue | 获取CNB平台指定ISSUE的信息 |
|
|
20
|
+
| cnb_create_issue | 在CNB平台指定的仓库创建一条新ISSUE。如需添加标签,另外调用cnb_add_issue_labels工具 |
|
|
21
|
+
| cnb_update_issue | 更新CNB平台指定ISSUE的信息。如需更新标签,另外调用cnb_set_issue_labels工具 |
|
|
22
|
+
| cnb_list_issue_comments | 获取CNB平台指定ISSUE的评论列表 |
|
|
23
|
+
| cnb_create_issue_comment | 在CNB平台指定的ISSUE创建一条新评论 |
|
|
24
|
+
| cnb_update_issue_comment | 更新CNB平台指定ISSUE评论的内容 |
|
|
25
|
+
| cnb_list_issue_labels | 获取CNB平台指定ISSUE的标签列表 |
|
|
26
|
+
| cnb_add_issue_labels | 为CNB平台指定的ISSUE添加一个或多个标签 |
|
|
27
|
+
| cnb_set_issue_labels | 变更CNB平台指定ISSUE的标签 |
|
|
28
|
+
| cnb_clear_issue_labels | 清除CNB平台指定ISSUE的标签 |
|
|
29
|
+
| cnb_remove_issue_label | 移除CNB平台指定ISSUE的指定标签 |
|
|
30
|
+
| cnb_list_pulls | 获取CNB平台指定仓库的合并请求列表 |
|
|
31
|
+
| cnb_get_pull | 获取CNB平台指定合并请求的信息 |
|
|
32
|
+
| cnb_create_pull | 在CNB平台指定的仓库创建一个新合并请求 |
|
|
33
|
+
| cnb_update_pull | 更新CNB平台指定合并请求的信息 |
|
|
34
|
+
| cnb_merge_pull | 合并CNB平台指定的合并请求 |
|
|
35
|
+
| cnb_list_pull_comments | 获取CNB平台指定合并请求的评论列表 |
|
|
36
|
+
| cnb_create_pull_comment | 在CNB平台指定的合并请求创建一条新评论 |
|
|
37
|
+
| cnb_list_workspaces | 获取当前用户在CNB平台的云原生开发环境列表 |
|
|
38
|
+
| cnb_delete_workspace | 在CNB平台删除指定的云原生开发环境 |
|
|
39
|
+
|
|
5
40
|
## 使用方法
|
|
6
41
|
|
|
7
42
|
### STDIO
|
package/dist/api/client.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
class CnbApiClient {
|
|
4
|
-
static instance = null;
|
|
5
|
-
_baseUrl;
|
|
6
|
-
_token;
|
|
7
4
|
constructor(options) {
|
|
8
5
|
this._baseUrl = options.baseUrl;
|
|
9
6
|
this._token = options.token;
|
|
@@ -28,7 +25,7 @@ class CnbApiClient {
|
|
|
28
25
|
const headers = {
|
|
29
26
|
Authorization: `Bearer ${this._token}`,
|
|
30
27
|
Accept: 'application/vnd.cnb.api+json',
|
|
31
|
-
...(config
|
|
28
|
+
...((config === null || config === void 0 ? void 0 : config.header) || {})
|
|
32
29
|
};
|
|
33
30
|
const options = {
|
|
34
31
|
method,
|
|
@@ -49,4 +46,5 @@ class CnbApiClient {
|
|
|
49
46
|
return response.json();
|
|
50
47
|
}
|
|
51
48
|
}
|
|
49
|
+
CnbApiClient.instance = null;
|
|
52
50
|
exports.default = CnbApiClient;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RepoVisibility = void 0;
|
|
4
|
+
var RepoVisibility;
|
|
5
|
+
(function (RepoVisibility) {
|
|
6
|
+
RepoVisibility["private"] = "Private";
|
|
7
|
+
RepoVisibility["public"] = "Public";
|
|
8
|
+
RepoVisibility["secret"] = "Secret";
|
|
9
|
+
})(RepoVisibility || (exports.RepoVisibility = RepoVisibility = {}));
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toolDescriptions = void 0;
|
|
4
|
+
const toolNames_1 = require("./toolNames");
|
|
5
|
+
exports.toolDescriptions = {
|
|
6
|
+
// 组织工具
|
|
7
|
+
[toolNames_1.ToolNames.LIST_GROUPS]: '获取当前用户在CNB平台里拥有权限的顶层组织列表',
|
|
8
|
+
[toolNames_1.ToolNames.LIST_SUB_GROUPS]: '获取当前用户在CNB平台里指定组织下拥有权限的子组织列表',
|
|
9
|
+
[toolNames_1.ToolNames.GET_GROUP]: '获取CNB平台指定组织的信息',
|
|
10
|
+
[toolNames_1.ToolNames.CREATE_GROUP]: '在CNB平台创建一个新组织',
|
|
11
|
+
// 仓库工具
|
|
12
|
+
[toolNames_1.ToolNames.LIST_REPOSITORIES]: '获取当前用户在CNB平台里拥有权限的仓库列表',
|
|
13
|
+
[toolNames_1.ToolNames.LIST_GROUP_REPOSITORIES]: '获取当前用户在CNB平台里指定组织下拥有权限的仓库列表',
|
|
14
|
+
[toolNames_1.ToolNames.GET_CURRENT_REPOSITORY]: '获取当前工作区对应的CNB平台仓库信息',
|
|
15
|
+
[toolNames_1.ToolNames.GET_REPOSITORY]: '获取CNB平台指定仓库的信息',
|
|
16
|
+
[toolNames_1.ToolNames.CREATE_REPOSITORY]: '在CNB平台创建一个新仓库',
|
|
17
|
+
// ISSUE 工具
|
|
18
|
+
[toolNames_1.ToolNames.LIST_ISSUES]: '获取CNB平台指定仓库的ISSUE列表',
|
|
19
|
+
[toolNames_1.ToolNames.GET_ISSUE]: '获取CNB平台指定ISSUE的信息',
|
|
20
|
+
[toolNames_1.ToolNames.CREATE_ISSUE]: `在CNB平台指定的仓库创建一条新ISSUE。如需添加标签,另外调用${toolNames_1.ToolNames.ADD_ISSUE_LABELS}工具`,
|
|
21
|
+
[toolNames_1.ToolNames.UPDATE_ISSUE]: `更新CNB平台指定ISSUE的信息。如需更新标签,另外调用${toolNames_1.ToolNames.SET_ISSUE_LABELS}工具`,
|
|
22
|
+
[toolNames_1.ToolNames.LIST_ISSUE_COMMENTS]: '获取CNB平台指定ISSUE的评论列表',
|
|
23
|
+
[toolNames_1.ToolNames.CREATE_ISSUE_COMMENT]: '在CNB平台指定的ISSUE创建一条新评论',
|
|
24
|
+
[toolNames_1.ToolNames.UPDATE_ISSUE_COMMENT]: '更新CNB平台指定ISSUE评论的内容',
|
|
25
|
+
[toolNames_1.ToolNames.LIST_ISSUE_LABELS]: '获取CNB平台指定ISSUE的标签列表',
|
|
26
|
+
[toolNames_1.ToolNames.ADD_ISSUE_LABELS]: '为CNB平台指定的ISSUE添加一个或多个标签',
|
|
27
|
+
[toolNames_1.ToolNames.SET_ISSUE_LABELS]: '变更CNB平台指定ISSUE的标签',
|
|
28
|
+
[toolNames_1.ToolNames.CLEAR_ISSUE_LABELS]: '清除CNB平台指定ISSUE的标签',
|
|
29
|
+
[toolNames_1.ToolNames.REMOVE_ISSUE_LABEL]: '移除CNB平台指定ISSUE的指定标签',
|
|
30
|
+
// 合并请求工具
|
|
31
|
+
[toolNames_1.ToolNames.LIST_PULLS]: '获取CNB平台指定仓库的合并请求列表',
|
|
32
|
+
[toolNames_1.ToolNames.GET_PULL]: '获取CNB平台指定合并请求的信息',
|
|
33
|
+
[toolNames_1.ToolNames.CREATE_PULL]: '在CNB平台指定的仓库创建一个新合并请求',
|
|
34
|
+
[toolNames_1.ToolNames.UPDATE_PULL]: '更新CNB平台指定合并请求的信息',
|
|
35
|
+
[toolNames_1.ToolNames.MERGE_PULL]: '合并CNB平台指定的合并请求',
|
|
36
|
+
[toolNames_1.ToolNames.LIST_PULL_COMMENTS]: '获取CNB平台指定合并请求的评论列表',
|
|
37
|
+
[toolNames_1.ToolNames.CREATE_PULL_COMMENT]: '在CNB平台指定的合并请求创建一条新评论',
|
|
38
|
+
// 云原生开发工具
|
|
39
|
+
[toolNames_1.ToolNames.LIST_WORKSPACES]: '获取当前用户在CNB平台的云原生开发环境列表',
|
|
40
|
+
[toolNames_1.ToolNames.DELETE_WORKSPACE]: '在CNB平台删除指定的云原生开发环境'
|
|
41
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToolNames = void 0;
|
|
4
|
+
var ToolNames;
|
|
5
|
+
(function (ToolNames) {
|
|
6
|
+
// 组织工具
|
|
7
|
+
ToolNames["LIST_GROUPS"] = "cnb_list_groups";
|
|
8
|
+
ToolNames["LIST_SUB_GROUPS"] = "cnb_list_sub_groups";
|
|
9
|
+
ToolNames["GET_GROUP"] = "cnb_get_group";
|
|
10
|
+
ToolNames["CREATE_GROUP"] = "cnb_create_group";
|
|
11
|
+
// 仓库工具
|
|
12
|
+
ToolNames["LIST_REPOSITORIES"] = "cnb_list_repositories";
|
|
13
|
+
ToolNames["LIST_GROUP_REPOSITORIES"] = "cnb_list_group_repositories";
|
|
14
|
+
ToolNames["GET_CURRENT_REPOSITORY"] = "cnb_get_current_repository";
|
|
15
|
+
ToolNames["GET_REPOSITORY"] = "cnb_get_repository";
|
|
16
|
+
ToolNames["CREATE_REPOSITORY"] = "cnb_create_repository";
|
|
17
|
+
// ISSUE 工具
|
|
18
|
+
ToolNames["LIST_ISSUES"] = "cnb_list_issues";
|
|
19
|
+
ToolNames["GET_ISSUE"] = "cnb_get_issue";
|
|
20
|
+
ToolNames["CREATE_ISSUE"] = "cnb_create_issue";
|
|
21
|
+
ToolNames["UPDATE_ISSUE"] = "cnb_update_issue";
|
|
22
|
+
ToolNames["LIST_ISSUE_COMMENTS"] = "cnb_list_issue_comments";
|
|
23
|
+
ToolNames["CREATE_ISSUE_COMMENT"] = "cnb_create_issue_comment";
|
|
24
|
+
ToolNames["UPDATE_ISSUE_COMMENT"] = "cnb_update_issue_comment";
|
|
25
|
+
ToolNames["LIST_ISSUE_LABELS"] = "cnb_list_issue_labels";
|
|
26
|
+
ToolNames["ADD_ISSUE_LABELS"] = "cnb_add_issue_labels";
|
|
27
|
+
ToolNames["SET_ISSUE_LABELS"] = "cnb_set_issue_labels";
|
|
28
|
+
ToolNames["CLEAR_ISSUE_LABELS"] = "cnb_clear_issue_labels";
|
|
29
|
+
ToolNames["REMOVE_ISSUE_LABEL"] = "cnb_remove_issue_label";
|
|
30
|
+
// 合并请求工具
|
|
31
|
+
ToolNames["LIST_PULLS"] = "cnb_list_pulls";
|
|
32
|
+
ToolNames["GET_PULL"] = "cnb_get_pull";
|
|
33
|
+
ToolNames["CREATE_PULL"] = "cnb_create_pull";
|
|
34
|
+
ToolNames["UPDATE_PULL"] = "cnb_update_pull";
|
|
35
|
+
ToolNames["MERGE_PULL"] = "cnb_merge_pull";
|
|
36
|
+
ToolNames["LIST_PULL_COMMENTS"] = "cnb_list_pull_comments";
|
|
37
|
+
ToolNames["CREATE_PULL_COMMENT"] = "cnb_create_pull_comment";
|
|
38
|
+
// 云原生开发工具
|
|
39
|
+
ToolNames["LIST_WORKSPACES"] = "cnb_list_workspaces";
|
|
40
|
+
ToolNames["DELETE_WORKSPACE"] = "cnb_delete_workspace";
|
|
41
|
+
})(ToolNames || (exports.ToolNames = ToolNames = {}));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isRepoPublic = isRepoPublic;
|
|
4
|
+
const index_js_1 = require("../constants/index.js");
|
|
5
|
+
const repository_js_1 = require("../api/repository.js");
|
|
6
|
+
const formatRepoUrl_js_1 = require("./formatRepoUrl.js");
|
|
7
|
+
async function isRepoPublic(url) {
|
|
8
|
+
const repoPath = (0, formatRepoUrl_js_1.getRepoPath)(url);
|
|
9
|
+
if (!repoPath)
|
|
10
|
+
return true;
|
|
11
|
+
try {
|
|
12
|
+
const { visibility_level } = await (0, repository_js_1.getRepository)(repoPath);
|
|
13
|
+
// @ts-expect-error 字段类型转换过,但 swagger 无法感知
|
|
14
|
+
return visibility_level === index_js_1.RepoVisibility.public;
|
|
15
|
+
}
|
|
16
|
+
catch (_a) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -5,11 +5,12 @@ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
|
5
5
|
const index_js_1 = require("../tools/index.js");
|
|
6
6
|
const package_json_1 = require("../../package.json");
|
|
7
7
|
function createMcpServer(req) {
|
|
8
|
+
var _a;
|
|
8
9
|
const mcpServer = new mcp_js_1.McpServer({
|
|
9
10
|
name: 'cnb-mcp-server',
|
|
10
11
|
version: package_json_1.version
|
|
11
12
|
});
|
|
12
|
-
const token = req
|
|
13
|
+
const token = (_a = req === null || req === void 0 ? void 0 : req.headers['authorization']) === null || _a === void 0 ? void 0 : _a.split(' ')[1];
|
|
13
14
|
(0, index_js_1.registerTools)(mcpServer, token);
|
|
14
15
|
return mcpServer;
|
|
15
16
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transports = void 0;
|
|
4
|
+
exports.createStreamableTransport = createStreamableTransport;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
7
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
8
|
+
const createMcpServer_1 = require("./createMcpServer");
|
|
9
|
+
// Store transports for each session type
|
|
10
|
+
exports.transports = {
|
|
11
|
+
streamable: {},
|
|
12
|
+
sse: {}
|
|
13
|
+
};
|
|
14
|
+
async function createStreamableTransport(req) {
|
|
15
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
16
|
+
// Reuse existing transport
|
|
17
|
+
if (sessionId && exports.transports.streamable[sessionId]) {
|
|
18
|
+
const transport = exports.transports.streamable[sessionId];
|
|
19
|
+
if (!(transport instanceof streamableHttp_js_1.StreamableHTTPServerTransport)) {
|
|
20
|
+
throw new Error('Bad Request: Session exists but uses a different transport protocol');
|
|
21
|
+
}
|
|
22
|
+
return transport;
|
|
23
|
+
}
|
|
24
|
+
// New initialization request
|
|
25
|
+
if (!sessionId && (0, types_js_1.isInitializeRequest)(req.body)) {
|
|
26
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
27
|
+
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
|
28
|
+
onsessioninitialized: (sessionId) => {
|
|
29
|
+
exports.transports.streamable[sessionId] = transport;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
// Clean up transport when closed
|
|
33
|
+
transport.onclose = () => {
|
|
34
|
+
console.log(`Transport closed for session ${transport.sessionId}`);
|
|
35
|
+
console.log(Object.keys(exports.transports.streamable));
|
|
36
|
+
if (transport.sessionId) {
|
|
37
|
+
delete exports.transports.streamable[transport.sessionId];
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const mcpServer = (0, createMcpServer_1.createMcpServer)(req);
|
|
41
|
+
await mcpServer.connect(transport);
|
|
42
|
+
return transport;
|
|
43
|
+
}
|
|
44
|
+
throw new Error('Bad Request: No valid session ID provided');
|
|
45
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRepoPath = getRepoPath;
|
|
4
|
+
function getRepoPath(url) {
|
|
5
|
+
var _a;
|
|
6
|
+
let repoPath = '';
|
|
7
|
+
if (!url)
|
|
8
|
+
return repoPath;
|
|
9
|
+
try {
|
|
10
|
+
const urlObj = new URL(url);
|
|
11
|
+
// Remove leading /
|
|
12
|
+
repoPath = urlObj.pathname.substring(1);
|
|
13
|
+
}
|
|
14
|
+
catch (_b) {
|
|
15
|
+
// ssh format address or malformed url
|
|
16
|
+
repoPath = (_a = url.split(':')[1]) !== null && _a !== void 0 ? _a : '';
|
|
17
|
+
}
|
|
18
|
+
// Remove tailing .git
|
|
19
|
+
repoPath = repoPath.replace(/\.git$/, '');
|
|
20
|
+
return repoPath;
|
|
21
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
function
|
|
3
|
+
exports.stopWithBadRequest = stopWithBadRequest;
|
|
4
|
+
function stopWithBadRequest(res, message) {
|
|
5
5
|
res.status(400).json({
|
|
6
6
|
jsonrpc: '2.0',
|
|
7
7
|
error: {
|
|
8
8
|
code: -32000,
|
|
9
|
-
message
|
|
9
|
+
message
|
|
10
10
|
},
|
|
11
11
|
id: null
|
|
12
12
|
});
|
package/dist/streamable.js
CHANGED
|
@@ -3,100 +3,64 @@
|
|
|
3
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
|
+
var _a;
|
|
6
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
8
|
const express_1 = __importDefault(require("express"));
|
|
8
|
-
const node_crypto_1 = require("node:crypto");
|
|
9
|
-
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
10
9
|
const sse_js_1 = require("@modelcontextprotocol/sdk/server/sse.js");
|
|
11
|
-
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
12
10
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
13
11
|
const createMcpServer_js_1 = require("./helpers/createMcpServer.js");
|
|
14
12
|
const sendResponse_js_1 = require("./helpers/sendResponse.js");
|
|
13
|
+
const createTransport_js_1 = require("./helpers/createTransport.js");
|
|
15
14
|
dotenv_1.default.config();
|
|
16
15
|
const DEFAULT_APP_PORT = 3000;
|
|
17
|
-
// Store transports for each session type
|
|
18
|
-
const transports = {
|
|
19
|
-
streamable: {},
|
|
20
|
-
sse: {}
|
|
21
|
-
};
|
|
22
16
|
const app = (0, express_1.default)();
|
|
23
17
|
app.use(express_1.default.json());
|
|
24
18
|
app.post('/mcp', async (req, res) => {
|
|
25
|
-
const sessionId = req.headers['mcp-session-id'];
|
|
26
19
|
let transport;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
transport = transports.streamable[sessionId];
|
|
30
|
-
if (!(transport instanceof streamableHttp_js_1.StreamableHTTPServerTransport)) {
|
|
31
|
-
(0, sendResponse_js_1.stopWithWrongTransport)(res);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
await transport.handleRequest(req, res, req.body);
|
|
35
|
-
return;
|
|
20
|
+
try {
|
|
21
|
+
transport = await (0, createTransport_js_1.createStreamableTransport)(req);
|
|
36
22
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
|
41
|
-
onsessioninitialized: (sessionId) => {
|
|
42
|
-
transports.streamable[sessionId] = transport;
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
// Clean up transport when closed
|
|
46
|
-
transport.onclose = () => {
|
|
47
|
-
if (transport.sessionId) {
|
|
48
|
-
delete transports.streamable[transport.sessionId];
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
const mcpServer = (0, createMcpServer_js_1.createMcpServer)(req);
|
|
52
|
-
await mcpServer.connect(transport);
|
|
53
|
-
await transport.handleRequest(req, res, req.body);
|
|
23
|
+
catch (err) {
|
|
24
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
25
|
+
(0, sendResponse_js_1.stopWithBadRequest)(res, message);
|
|
54
26
|
return;
|
|
55
27
|
}
|
|
56
|
-
|
|
57
|
-
res.status(400).json({
|
|
58
|
-
jsonrpc: '2.0',
|
|
59
|
-
error: {
|
|
60
|
-
code: -32000,
|
|
61
|
-
message: 'Bad Request: No valid session ID provided'
|
|
62
|
-
},
|
|
63
|
-
id: null
|
|
64
|
-
});
|
|
28
|
+
await transport.handleRequest(req, res, req.body);
|
|
65
29
|
});
|
|
66
30
|
const handleSessionRequest = async (req, res) => {
|
|
67
31
|
const sessionId = req.headers['mcp-session-id'];
|
|
68
|
-
if (!sessionId || !transports.streamable[sessionId]) {
|
|
32
|
+
if (!sessionId || !createTransport_js_1.transports.streamable[sessionId]) {
|
|
69
33
|
res.status(400).send('Invalid or missing session ID');
|
|
70
34
|
return;
|
|
71
35
|
}
|
|
72
|
-
const transport = transports.streamable[sessionId];
|
|
36
|
+
const transport = createTransport_js_1.transports.streamable[sessionId];
|
|
73
37
|
await transport.handleRequest(req, res, req.body);
|
|
74
38
|
};
|
|
75
39
|
app.get('/mcp', handleSessionRequest);
|
|
76
40
|
app.delete('/mcp', handleSessionRequest);
|
|
77
41
|
app.get('/sse', async (req, res) => {
|
|
78
42
|
const transport = new sse_js_1.SSEServerTransport('/messages', res);
|
|
79
|
-
transports.sse[transport.sessionId] = transport;
|
|
43
|
+
createTransport_js_1.transports.sse[transport.sessionId] = transport;
|
|
80
44
|
res.on('close', () => {
|
|
81
|
-
delete transports.sse[transport.sessionId];
|
|
45
|
+
delete createTransport_js_1.transports.sse[transport.sessionId];
|
|
82
46
|
});
|
|
83
47
|
const mcpServer = (0, createMcpServer_js_1.createMcpServer)(req);
|
|
84
48
|
await mcpServer.connect(transport);
|
|
85
49
|
});
|
|
86
50
|
app.post('/messages', async (req, res) => {
|
|
87
51
|
const sessionId = req.query.sessionId;
|
|
88
|
-
const transport = transports.sse[sessionId];
|
|
52
|
+
const transport = createTransport_js_1.transports.sse[sessionId];
|
|
89
53
|
if (!transport) {
|
|
90
54
|
res.status(400).send('No transport found for sessionId');
|
|
91
55
|
return;
|
|
92
56
|
}
|
|
93
57
|
if (!(transport instanceof sse_js_1.SSEServerTransport)) {
|
|
94
|
-
(0, sendResponse_js_1.
|
|
58
|
+
(0, sendResponse_js_1.stopWithBadRequest)(res, 'Bad Request: Session exists but uses a different transport protocol');
|
|
95
59
|
return;
|
|
96
60
|
}
|
|
97
61
|
await transport.handlePostMessage(req, res, req.body);
|
|
98
62
|
});
|
|
99
|
-
let port = parseInt(process.env.APP_PORT
|
|
63
|
+
let port = parseInt((_a = process.env.APP_PORT) !== null && _a !== void 0 ? _a : '', 10);
|
|
100
64
|
if (isNaN(port)) {
|
|
101
65
|
port = DEFAULT_APP_PORT;
|
|
102
66
|
}
|
package/dist/tools/groupTools.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = registerGroupTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const toolNames_js_1 = require("../constants/toolNames.js");
|
|
6
|
+
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
5
7
|
const group_js_1 = require("../api/group.js");
|
|
6
8
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
7
9
|
function registerGroupTools(server) {
|
|
8
|
-
server.tool(
|
|
10
|
+
server.tool(toolNames_js_1.ToolNames.LIST_GROUPS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_GROUPS], {
|
|
9
11
|
page: zod_1.z.number().default(1).describe('第几页,从1开始'),
|
|
10
12
|
page_size: zod_1.z.number().default(10).describe('每页多少条数据'),
|
|
11
13
|
search: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库关键字'),
|
|
@@ -15,13 +17,13 @@ function registerGroupTools(server) {
|
|
|
15
17
|
}, async ({ page, page_size, search, role }) => {
|
|
16
18
|
try {
|
|
17
19
|
const groups = await (0, group_js_1.listGroups)({ page, page_size, search, role });
|
|
18
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(groups, null, 2),
|
|
20
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(groups, null, 2), toolNames_js_1.ToolNames.LIST_GROUPS);
|
|
19
21
|
}
|
|
20
22
|
catch (error) {
|
|
21
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
23
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_GROUPS);
|
|
22
24
|
}
|
|
23
25
|
});
|
|
24
|
-
server.tool(
|
|
26
|
+
server.tool(toolNames_js_1.ToolNames.LIST_SUB_GROUPS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_SUB_GROUPS], {
|
|
25
27
|
group: zod_1.z.string().describe('组织名称'),
|
|
26
28
|
page: zod_1.z.number().default(1).describe('第几页,从1开始'),
|
|
27
29
|
page_size: zod_1.z.number().default(10).describe('每页多少条数据'),
|
|
@@ -29,24 +31,24 @@ function registerGroupTools(server) {
|
|
|
29
31
|
}, async ({ group, page, page_size, access }) => {
|
|
30
32
|
try {
|
|
31
33
|
const subGroups = await (0, group_js_1.listSubGroups)(group, { page, page_size, access });
|
|
32
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(subGroups, null, 2),
|
|
34
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(subGroups, null, 2), toolNames_js_1.ToolNames.LIST_SUB_GROUPS);
|
|
33
35
|
}
|
|
34
36
|
catch (error) {
|
|
35
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
37
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_SUB_GROUPS);
|
|
36
38
|
}
|
|
37
39
|
});
|
|
38
|
-
server.tool(
|
|
40
|
+
server.tool(toolNames_js_1.ToolNames.GET_GROUP, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.GET_GROUP], {
|
|
39
41
|
group: zod_1.z.string().describe('组织路径')
|
|
40
42
|
}, async ({ group }) => {
|
|
41
43
|
try {
|
|
42
44
|
const groupInfo = await (0, group_js_1.getGroup)(group);
|
|
43
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(groupInfo, null, 2),
|
|
45
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(groupInfo, null, 2), toolNames_js_1.ToolNames.GET_GROUP);
|
|
44
46
|
}
|
|
45
47
|
catch (error) {
|
|
46
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
48
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.GET_GROUP);
|
|
47
49
|
}
|
|
48
50
|
});
|
|
49
|
-
server.tool(
|
|
51
|
+
server.tool(toolNames_js_1.ToolNames.CREATE_GROUP, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CREATE_GROUP], {
|
|
50
52
|
path: zod_1.z.string().describe('组织路径'),
|
|
51
53
|
description: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('组织描述'),
|
|
52
54
|
remark: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库备注'),
|
|
@@ -56,10 +58,10 @@ function registerGroupTools(server) {
|
|
|
56
58
|
}, async ({ path, description, remark, bind_domain }) => {
|
|
57
59
|
try {
|
|
58
60
|
const data = await (0, group_js_1.createGroup)({ path, description, remark, bind_domain });
|
|
59
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2),
|
|
61
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.CREATE_GROUP);
|
|
60
62
|
}
|
|
61
63
|
catch (error) {
|
|
62
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
64
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CREATE_GROUP);
|
|
63
65
|
}
|
|
64
66
|
});
|
|
65
67
|
}
|
package/dist/tools/issueTools.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = registerIssueTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const toolNames_js_1 = require("../constants/toolNames.js");
|
|
6
|
+
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
5
7
|
const issue_js_1 = require("../api/issue.js");
|
|
6
8
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
7
9
|
function registerIssueTools(server) {
|
|
8
|
-
server.tool(
|
|
10
|
+
server.tool(toolNames_js_1.ToolNames.LIST_ISSUES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_ISSUES], {
|
|
9
11
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
10
12
|
page: zod_1.z.number().default(1).describe('第几页,从1开始'),
|
|
11
13
|
page_size: zod_1.z.number().default(10).describe('每页多少条数据,默认是30'),
|
|
@@ -47,25 +49,25 @@ function registerIssueTools(server) {
|
|
|
47
49
|
updated_time_end,
|
|
48
50
|
order_by
|
|
49
51
|
});
|
|
50
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issues, null, 2),
|
|
52
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issues, null, 2), toolNames_js_1.ToolNames.LIST_ISSUES);
|
|
51
53
|
}
|
|
52
54
|
catch (error) {
|
|
53
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
55
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_ISSUES);
|
|
54
56
|
}
|
|
55
57
|
});
|
|
56
|
-
server.tool(
|
|
58
|
+
server.tool(toolNames_js_1.ToolNames.GET_ISSUE, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.GET_ISSUE], {
|
|
57
59
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
58
60
|
issueId: zod_1.z.number().describe('Issue ID')
|
|
59
61
|
}, async ({ repo, issueId }) => {
|
|
60
62
|
try {
|
|
61
63
|
const issues = await (0, issue_js_1.getIssue)(repo, issueId);
|
|
62
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issues, null, 2),
|
|
64
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issues, null, 2), toolNames_js_1.ToolNames.GET_ISSUE);
|
|
63
65
|
}
|
|
64
66
|
catch (error) {
|
|
65
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
67
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.GET_ISSUE);
|
|
66
68
|
}
|
|
67
69
|
});
|
|
68
|
-
server.tool(
|
|
70
|
+
server.tool(toolNames_js_1.ToolNames.CREATE_ISSUE, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CREATE_ISSUE], {
|
|
69
71
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
70
72
|
title: zod_1.z.string().describe('Issue 标题'),
|
|
71
73
|
body: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('Issue 描述'),
|
|
@@ -93,13 +95,13 @@ function registerIssueTools(server) {
|
|
|
93
95
|
end_date,
|
|
94
96
|
start_date
|
|
95
97
|
});
|
|
96
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issue, null, 2),
|
|
98
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issue, null, 2), toolNames_js_1.ToolNames.CREATE_ISSUE);
|
|
97
99
|
}
|
|
98
100
|
catch (error) {
|
|
99
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
101
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CREATE_ISSUE);
|
|
100
102
|
}
|
|
101
103
|
});
|
|
102
|
-
server.tool(
|
|
104
|
+
server.tool(toolNames_js_1.ToolNames.UPDATE_ISSUE, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.UPDATE_ISSUE], {
|
|
103
105
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
104
106
|
issueId: zod_1.z.number().describe('Issue ID'),
|
|
105
107
|
title: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('Issue 标题'),
|
|
@@ -126,13 +128,13 @@ function registerIssueTools(server) {
|
|
|
126
128
|
state,
|
|
127
129
|
state_reason
|
|
128
130
|
});
|
|
129
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issue, null, 2),
|
|
131
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issue, null, 2), toolNames_js_1.ToolNames.UPDATE_ISSUE);
|
|
130
132
|
}
|
|
131
133
|
catch (error) {
|
|
132
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
134
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.UPDATE_ISSUE);
|
|
133
135
|
}
|
|
134
136
|
});
|
|
135
|
-
server.tool(
|
|
137
|
+
server.tool(toolNames_js_1.ToolNames.LIST_ISSUE_COMMENTS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_ISSUE_COMMENTS], {
|
|
136
138
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
137
139
|
issueId: zod_1.z.number().describe('Issue ID'),
|
|
138
140
|
page: zod_1.z.number().default(1).describe('第几页,从1开始'),
|
|
@@ -140,26 +142,26 @@ function registerIssueTools(server) {
|
|
|
140
142
|
}, async ({ repo, issueId, page, page_size }) => {
|
|
141
143
|
try {
|
|
142
144
|
const comments = await (0, issue_js_1.listIssueComments)(repo, issueId, { page, page_size });
|
|
143
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comments, null, 2),
|
|
145
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comments, null, 2), toolNames_js_1.ToolNames.LIST_ISSUE_COMMENTS);
|
|
144
146
|
}
|
|
145
147
|
catch (error) {
|
|
146
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
148
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_ISSUE_COMMENTS);
|
|
147
149
|
}
|
|
148
150
|
});
|
|
149
|
-
server.tool(
|
|
151
|
+
server.tool(toolNames_js_1.ToolNames.CREATE_ISSUE_COMMENT, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CREATE_ISSUE_COMMENT], {
|
|
150
152
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
151
153
|
issueId: zod_1.z.number().describe('Issue ID'),
|
|
152
154
|
body: zod_1.z.string().describe('评论内容')
|
|
153
155
|
}, async ({ repo, issueId, body }) => {
|
|
154
156
|
try {
|
|
155
157
|
const comment = await (0, issue_js_1.createIssueComment)(repo, issueId, { body });
|
|
156
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comment, null, 2),
|
|
158
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comment, null, 2), toolNames_js_1.ToolNames.CREATE_ISSUE_COMMENT);
|
|
157
159
|
}
|
|
158
160
|
catch (error) {
|
|
159
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
161
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CREATE_ISSUE_COMMENT);
|
|
160
162
|
}
|
|
161
163
|
});
|
|
162
|
-
server.tool(
|
|
164
|
+
server.tool(toolNames_js_1.ToolNames.UPDATE_ISSUE_COMMENT, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.UPDATE_ISSUE_COMMENT], {
|
|
163
165
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
164
166
|
issueId: zod_1.z.number().describe('Issue ID'),
|
|
165
167
|
commentId: zod_1.z.string().describe('评论 ID'),
|
|
@@ -167,73 +169,73 @@ function registerIssueTools(server) {
|
|
|
167
169
|
}, async ({ repo, issueId, commentId, body }) => {
|
|
168
170
|
try {
|
|
169
171
|
const comment = await (0, issue_js_1.updateIssueComment)(repo, issueId, commentId, { body });
|
|
170
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comment, null, 2),
|
|
172
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comment, null, 2), toolNames_js_1.ToolNames.UPDATE_ISSUE_COMMENT);
|
|
171
173
|
}
|
|
172
174
|
catch (error) {
|
|
173
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
175
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.UPDATE_ISSUE_COMMENT);
|
|
174
176
|
}
|
|
175
177
|
});
|
|
176
|
-
server.tool(
|
|
178
|
+
server.tool(toolNames_js_1.ToolNames.LIST_ISSUE_LABELS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_ISSUE_LABELS], {
|
|
177
179
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
178
180
|
issueId: zod_1.z.number().describe('Issue ID')
|
|
179
181
|
}, async ({ repo, issueId }) => {
|
|
180
182
|
try {
|
|
181
183
|
const labels = await (0, issue_js_1.listIssueLabels)(repo, issueId);
|
|
182
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(labels, null, 2),
|
|
184
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(labels, null, 2), toolNames_js_1.ToolNames.LIST_ISSUE_LABELS);
|
|
183
185
|
}
|
|
184
186
|
catch (error) {
|
|
185
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
187
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_ISSUE_LABELS);
|
|
186
188
|
}
|
|
187
189
|
});
|
|
188
|
-
server.tool(
|
|
190
|
+
server.tool(toolNames_js_1.ToolNames.ADD_ISSUE_LABELS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.ADD_ISSUE_LABELS], {
|
|
189
191
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
190
192
|
issueId: zod_1.z.number().describe('Issue ID'),
|
|
191
193
|
labels: zod_1.z.array(zod_1.z.string()).describe('要添加的标签列表,每个标签需要从仓库标签列表中选择')
|
|
192
194
|
}, async ({ repo, issueId, labels }) => {
|
|
193
195
|
try {
|
|
194
196
|
const result = await (0, issue_js_1.addIssueLabels)(repo, issueId, labels);
|
|
195
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2),
|
|
197
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.ADD_ISSUE_LABELS);
|
|
196
198
|
}
|
|
197
199
|
catch (error) {
|
|
198
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
200
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.ADD_ISSUE_LABELS);
|
|
199
201
|
}
|
|
200
202
|
});
|
|
201
|
-
server.tool(
|
|
203
|
+
server.tool(toolNames_js_1.ToolNames.SET_ISSUE_LABELS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.SET_ISSUE_LABELS], {
|
|
202
204
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
203
205
|
issueId: zod_1.z.number().describe('Issue ID'),
|
|
204
206
|
labels: zod_1.z.array(zod_1.z.string()).describe('新的标签列表(将替换所有现有标签),每个标签需要从仓库标签列表中选择')
|
|
205
207
|
}, async ({ repo, issueId, labels }) => {
|
|
206
208
|
try {
|
|
207
209
|
const result = await (0, issue_js_1.setIssueLabels)(repo, issueId, labels);
|
|
208
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2),
|
|
210
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.SET_ISSUE_LABELS);
|
|
209
211
|
}
|
|
210
212
|
catch (error) {
|
|
211
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
213
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.SET_ISSUE_LABELS);
|
|
212
214
|
}
|
|
213
215
|
});
|
|
214
|
-
server.tool(
|
|
216
|
+
server.tool(toolNames_js_1.ToolNames.CLEAR_ISSUE_LABELS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CLEAR_ISSUE_LABELS], {
|
|
215
217
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
216
218
|
issueId: zod_1.z.number().describe('Issue ID')
|
|
217
219
|
}, async ({ repo, issueId }) => {
|
|
218
220
|
try {
|
|
219
221
|
await (0, issue_js_1.deleteIssueLabels)(repo, issueId);
|
|
220
|
-
return (0, formatToolResult_js_1.formatTextToolResult)('All labels deleted',
|
|
222
|
+
return (0, formatToolResult_js_1.formatTextToolResult)('All labels deleted', toolNames_js_1.ToolNames.CLEAR_ISSUE_LABELS);
|
|
221
223
|
}
|
|
222
224
|
catch (error) {
|
|
223
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
225
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CLEAR_ISSUE_LABELS);
|
|
224
226
|
}
|
|
225
227
|
});
|
|
226
|
-
server.tool(
|
|
228
|
+
server.tool(toolNames_js_1.ToolNames.REMOVE_ISSUE_LABEL, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.REMOVE_ISSUE_LABEL], {
|
|
227
229
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
228
230
|
issueId: zod_1.z.number().describe('Issue ID'),
|
|
229
231
|
labelName: zod_1.z.string().describe('要删除的标签名称')
|
|
230
232
|
}, async ({ repo, issueId, labelName }) => {
|
|
231
233
|
try {
|
|
232
234
|
await (0, issue_js_1.deleteIssueLabel)(repo, issueId, labelName);
|
|
233
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(`${labelName} deleted`,
|
|
235
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(`${labelName} deleted`, toolNames_js_1.ToolNames.REMOVE_ISSUE_LABEL);
|
|
234
236
|
}
|
|
235
237
|
catch (error) {
|
|
236
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
238
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.REMOVE_ISSUE_LABEL);
|
|
237
239
|
}
|
|
238
240
|
});
|
|
239
241
|
}
|
package/dist/tools/pullTools.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = registerPullTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const toolNames_js_1 = require("../constants/toolNames.js");
|
|
6
|
+
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
5
7
|
const pull_js_1 = require("../api/pull.js");
|
|
6
8
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
7
9
|
function registerPullTools(server) {
|
|
8
|
-
server.tool(
|
|
10
|
+
server.tool(toolNames_js_1.ToolNames.LIST_PULLS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_PULLS], {
|
|
9
11
|
repo: zod_1.z.string().describe('仓库路径,格式为 {group}/{repo}'),
|
|
10
12
|
state: zod_1.z
|
|
11
13
|
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['open', 'closed', 'all']).optional())
|
|
@@ -21,25 +23,25 @@ function registerPullTools(server) {
|
|
|
21
23
|
}, async ({ repo, ...params }) => {
|
|
22
24
|
try {
|
|
23
25
|
const pulls = await (0, pull_js_1.listPulls)(repo, params);
|
|
24
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pulls, null, 2),
|
|
26
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pulls, null, 2), toolNames_js_1.ToolNames.LIST_PULLS);
|
|
25
27
|
}
|
|
26
28
|
catch (error) {
|
|
27
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
29
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_PULLS);
|
|
28
30
|
}
|
|
29
31
|
});
|
|
30
|
-
server.tool(
|
|
32
|
+
server.tool(toolNames_js_1.ToolNames.GET_PULL, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.GET_PULL], {
|
|
31
33
|
repo: zod_1.z.string().describe('仓库路径,格式为 {group}/{repo}'),
|
|
32
34
|
number: zod_1.z.number().describe('Pull Request编号')
|
|
33
35
|
}, async ({ repo, number }) => {
|
|
34
36
|
try {
|
|
35
37
|
const pull = await (0, pull_js_1.getPull)(repo, number);
|
|
36
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2),
|
|
38
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2), toolNames_js_1.ToolNames.GET_PULL);
|
|
37
39
|
}
|
|
38
40
|
catch (error) {
|
|
39
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
41
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.GET_PULL);
|
|
40
42
|
}
|
|
41
43
|
});
|
|
42
|
-
server.tool(
|
|
44
|
+
server.tool(toolNames_js_1.ToolNames.CREATE_PULL, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CREATE_PULL], {
|
|
43
45
|
repo: zod_1.z.string().describe('目标仓库路径,格式为 {group}/{repo}'),
|
|
44
46
|
base: zod_1.z.string().describe('目标仓库目标分支'),
|
|
45
47
|
head_repo: zod_1.z.string().optional().describe('来源仓库路径,格式为 {group}/{repo},不填则为目标仓库'),
|
|
@@ -49,13 +51,13 @@ function registerPullTools(server) {
|
|
|
49
51
|
}, async ({ repo, ...params }) => {
|
|
50
52
|
try {
|
|
51
53
|
const pull = await (0, pull_js_1.createPull)(repo, params);
|
|
52
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2),
|
|
54
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2), toolNames_js_1.ToolNames.CREATE_PULL);
|
|
53
55
|
}
|
|
54
56
|
catch (error) {
|
|
55
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
57
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CREATE_PULL);
|
|
56
58
|
}
|
|
57
59
|
});
|
|
58
|
-
server.tool(
|
|
60
|
+
server.tool(toolNames_js_1.ToolNames.UPDATE_PULL, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.UPDATE_PULL], {
|
|
59
61
|
repo: zod_1.z.string().describe('仓库路径,格式为 {group}/{repo}'),
|
|
60
62
|
number: zod_1.z.number().describe('Pull Request编号'),
|
|
61
63
|
title: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('标题'),
|
|
@@ -66,13 +68,13 @@ function registerPullTools(server) {
|
|
|
66
68
|
}, async ({ repo, number, ...params }) => {
|
|
67
69
|
try {
|
|
68
70
|
const pull = await (0, pull_js_1.updatePull)(repo, number, params);
|
|
69
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2),
|
|
71
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2), toolNames_js_1.ToolNames.UPDATE_PULL);
|
|
70
72
|
}
|
|
71
73
|
catch (error) {
|
|
72
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
74
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.UPDATE_PULL);
|
|
73
75
|
}
|
|
74
76
|
});
|
|
75
|
-
server.tool(
|
|
77
|
+
server.tool(toolNames_js_1.ToolNames.MERGE_PULL, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.MERGE_PULL], {
|
|
76
78
|
repo: zod_1.z.string().describe('仓库路径,格式为 {group}/{repo}'),
|
|
77
79
|
number: zod_1.z.number().describe('Pull Request编号'),
|
|
78
80
|
merge_style: zod_1.z
|
|
@@ -85,13 +87,13 @@ function registerPullTools(server) {
|
|
|
85
87
|
}, async ({ repo, number, ...params }) => {
|
|
86
88
|
try {
|
|
87
89
|
const result = await (0, pull_js_1.mergePull)(repo, number, params);
|
|
88
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2),
|
|
90
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.MERGE_PULL);
|
|
89
91
|
}
|
|
90
92
|
catch (error) {
|
|
91
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
93
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.MERGE_PULL);
|
|
92
94
|
}
|
|
93
95
|
});
|
|
94
|
-
server.tool(
|
|
96
|
+
server.tool(toolNames_js_1.ToolNames.LIST_PULL_COMMENTS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_PULL_COMMENTS], {
|
|
95
97
|
repo: zod_1.z.string().describe('仓库路径,格式为 {group}/{repo}'),
|
|
96
98
|
number: zod_1.z.number().describe('Pull Request编号'),
|
|
97
99
|
page: zod_1.z.number().default(1).describe('页码'),
|
|
@@ -99,23 +101,23 @@ function registerPullTools(server) {
|
|
|
99
101
|
}, async ({ repo, number, ...params }) => {
|
|
100
102
|
try {
|
|
101
103
|
const comments = await (0, pull_js_1.listPullComments)(repo, number, params);
|
|
102
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comments, null, 2),
|
|
104
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comments, null, 2), toolNames_js_1.ToolNames.LIST_PULL_COMMENTS);
|
|
103
105
|
}
|
|
104
106
|
catch (error) {
|
|
105
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
107
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_PULL_COMMENTS);
|
|
106
108
|
}
|
|
107
109
|
});
|
|
108
|
-
server.tool(
|
|
110
|
+
server.tool(toolNames_js_1.ToolNames.CREATE_PULL_COMMENT, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CREATE_PULL_COMMENT], {
|
|
109
111
|
repo: zod_1.z.string().describe('仓库路径,格式为 {group}/{repo}'),
|
|
110
112
|
number: zod_1.z.number().describe('Pull Request编号'),
|
|
111
113
|
body: zod_1.z.string().describe('评论内容')
|
|
112
114
|
}, async ({ repo, number, body }) => {
|
|
113
115
|
try {
|
|
114
116
|
await (0, pull_js_1.createPullComment)(repo, number, { body });
|
|
115
|
-
return (0, formatToolResult_js_1.formatTextToolResult)('Comment created',
|
|
117
|
+
return (0, formatToolResult_js_1.formatTextToolResult)('Comment created', toolNames_js_1.ToolNames.CREATE_PULL_COMMENT);
|
|
116
118
|
}
|
|
117
119
|
catch (error) {
|
|
118
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
120
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CREATE_PULL_COMMENT);
|
|
119
121
|
}
|
|
120
122
|
});
|
|
121
123
|
}
|
package/dist/tools/repoTools.js
CHANGED
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = registerRepoTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const toolNames_js_1 = require("../constants/toolNames.js");
|
|
6
|
+
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
5
7
|
const repository_js_1 = require("../api/repository.js");
|
|
6
8
|
const user_js_1 = require("../api/user.js");
|
|
7
9
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
10
|
+
const formatRepoUrl_js_1 = require("../helpers/formatRepoUrl.js");
|
|
11
|
+
const checkRepoVisibility_js_1 = require("../helpers/checkRepoVisibility.js");
|
|
8
12
|
function registerRepoTools(server) {
|
|
9
|
-
server.tool(
|
|
13
|
+
server.tool(toolNames_js_1.ToolNames.LIST_REPOSITORIES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_REPOSITORIES], {
|
|
14
|
+
remote_url: zod_1.z.string().describe('远程仓库URL,需要先执行`git remote get-url origin`命令获取,获取不到传空字符串'),
|
|
10
15
|
page: zod_1.z.number().default(1).describe('第几页,从1开始,默认值是1'),
|
|
11
16
|
page_size: zod_1.z.number().default(10).describe('每页多少条数据,默认值为10'),
|
|
12
17
|
search: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('查询关键字'),
|
|
@@ -22,16 +27,20 @@ function registerRepoTools(server) {
|
|
|
22
27
|
desc: zod_1.z
|
|
23
28
|
.preprocess((val) => (val === null ? undefined : val), zod_1.z.boolean().optional())
|
|
24
29
|
.describe('是否开启倒叙排序,默认值是false')
|
|
25
|
-
}, async ({ page, page_size, search, filter_type, role, order_by, desc }) => {
|
|
30
|
+
}, async ({ remote_url, page, page_size, search, filter_type, role, order_by, desc }) => {
|
|
31
|
+
const isPublic = await (0, checkRepoVisibility_js_1.isRepoPublic)(remote_url);
|
|
32
|
+
if (isPublic) {
|
|
33
|
+
filter_type = 'public';
|
|
34
|
+
}
|
|
26
35
|
try {
|
|
27
36
|
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),
|
|
37
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repos, null, 2), toolNames_js_1.ToolNames.LIST_REPOSITORIES);
|
|
29
38
|
}
|
|
30
39
|
catch (error) {
|
|
31
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
40
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_REPOSITORIES);
|
|
32
41
|
}
|
|
33
42
|
});
|
|
34
|
-
server.tool(
|
|
43
|
+
server.tool(toolNames_js_1.ToolNames.LIST_GROUP_REPOSITORIES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_GROUP_REPOSITORIES], {
|
|
35
44
|
group: zod_1.z.string().describe('组织名称'),
|
|
36
45
|
page: zod_1.z.number().default(1).describe('第几页,从1开始,默认值是1'),
|
|
37
46
|
page_size: zod_1.z.number().default(10).describe('每页多少条数据,默认值为10'),
|
|
@@ -59,24 +68,24 @@ function registerRepoTools(server) {
|
|
|
59
68
|
order_by,
|
|
60
69
|
desc
|
|
61
70
|
});
|
|
62
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repos, null, 2),
|
|
71
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repos, null, 2), toolNames_js_1.ToolNames.LIST_GROUP_REPOSITORIES);
|
|
63
72
|
}
|
|
64
73
|
catch (error) {
|
|
65
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
74
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_GROUP_REPOSITORIES);
|
|
66
75
|
}
|
|
67
76
|
});
|
|
68
|
-
server.tool(
|
|
77
|
+
server.tool(toolNames_js_1.ToolNames.GET_REPOSITORY, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.GET_REPOSITORY], {
|
|
69
78
|
repo: zod_1.z.string().describe('仓库路径')
|
|
70
79
|
}, async ({ repo }) => {
|
|
71
80
|
try {
|
|
72
81
|
const repoInfo = await (0, repository_js_1.getRepository)(repo);
|
|
73
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repoInfo, null, 2),
|
|
82
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repoInfo, null, 2), toolNames_js_1.ToolNames.GET_REPOSITORY);
|
|
74
83
|
}
|
|
75
84
|
catch (error) {
|
|
76
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
85
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.GET_REPOSITORY);
|
|
77
86
|
}
|
|
78
87
|
});
|
|
79
|
-
server.tool(
|
|
88
|
+
server.tool(toolNames_js_1.ToolNames.CREATE_REPOSITORY, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CREATE_REPOSITORY], {
|
|
80
89
|
group: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库所属分组'),
|
|
81
90
|
name: zod_1.z.string().describe('仓库名称'),
|
|
82
91
|
description: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库描述'),
|
|
@@ -92,40 +101,26 @@ function registerRepoTools(server) {
|
|
|
92
101
|
}
|
|
93
102
|
try {
|
|
94
103
|
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),
|
|
104
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.CREATE_REPOSITORY);
|
|
96
105
|
}
|
|
97
106
|
catch (error) {
|
|
98
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
107
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CREATE_REPOSITORY);
|
|
99
108
|
}
|
|
100
109
|
});
|
|
101
|
-
server.tool(
|
|
110
|
+
server.tool(toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY], {
|
|
102
111
|
remote_url: zod_1.z.string().describe('远程仓库URL, 需要先执行`git remote get-url origin`命令获取')
|
|
103
112
|
}, async ({ remote_url }) => {
|
|
104
113
|
try {
|
|
105
|
-
|
|
106
|
-
if (remote_url.startsWith('git@')) {
|
|
107
|
-
// SSH 格式: git@example.com:group/repo.git
|
|
108
|
-
const match = remote_url.match(/git@[^:]+:(.+?)(?:\.git)?$/);
|
|
109
|
-
if (match) {
|
|
110
|
-
repoPath = match[1];
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
else if (remote_url.startsWith('http')) {
|
|
114
|
-
// HTTPS 格式: https://example.com/group/repo.git
|
|
115
|
-
const match = remote_url.match(/https?:\/\/[^/]+\/(.+?)(?:\.git)?$/);
|
|
116
|
-
if (match) {
|
|
117
|
-
repoPath = match[1];
|
|
118
|
-
}
|
|
119
|
-
}
|
|
114
|
+
const repoPath = (0, formatRepoUrl_js_1.getRepoPath)(remote_url);
|
|
120
115
|
if (!repoPath) {
|
|
121
|
-
return (0, formatToolResult_js_1.formatToolError)(`无法从远程仓库URL解析出仓库路径: ${remote_url}`,
|
|
116
|
+
return (0, formatToolResult_js_1.formatToolError)(`无法从远程仓库URL解析出仓库路径: ${remote_url}`, toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY);
|
|
122
117
|
}
|
|
123
118
|
// 获取仓库信息
|
|
124
119
|
const data = await (0, repository_js_1.getRepository)(repoPath);
|
|
125
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2),
|
|
120
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY);
|
|
126
121
|
}
|
|
127
122
|
catch (error) {
|
|
128
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
123
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY);
|
|
129
124
|
}
|
|
130
125
|
});
|
|
131
126
|
}
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = registerWorkspaceTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const toolNames_js_1 = require("../constants/toolNames.js");
|
|
6
|
+
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
5
7
|
const workspace_js_1 = require("../api/workspace.js");
|
|
6
8
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
7
9
|
function registerWorkspaceTools(server) {
|
|
8
|
-
server.tool(
|
|
10
|
+
server.tool(toolNames_js_1.ToolNames.LIST_WORKSPACES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_WORKSPACES], {
|
|
9
11
|
branch: zod_1.z
|
|
10
12
|
.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
|
|
11
13
|
.describe('分支名,例如:main'),
|
|
@@ -38,23 +40,23 @@ function registerWorkspaceTools(server) {
|
|
|
38
40
|
slug,
|
|
39
41
|
status
|
|
40
42
|
});
|
|
41
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(workspaces, null, 2),
|
|
43
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(workspaces, null, 2), toolNames_js_1.ToolNames.LIST_WORKSPACES);
|
|
42
44
|
}
|
|
43
45
|
catch (error) {
|
|
44
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
46
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_WORKSPACES);
|
|
45
47
|
}
|
|
46
48
|
});
|
|
47
|
-
server.tool(
|
|
49
|
+
server.tool(toolNames_js_1.ToolNames.DELETE_WORKSPACE, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.DELETE_WORKSPACE], {
|
|
48
50
|
pipelineId: zod_1.z.string().describe('开发环境 ID')
|
|
49
51
|
}, async ({ pipelineId }) => {
|
|
50
52
|
try {
|
|
51
53
|
const result = await (0, workspace_js_1.deleteWorkspace)({
|
|
52
54
|
pipelineId
|
|
53
55
|
});
|
|
54
|
-
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2),
|
|
56
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.DELETE_WORKSPACE);
|
|
55
57
|
}
|
|
56
58
|
catch (error) {
|
|
57
|
-
return (0, formatToolResult_js_1.formatToolError)(error,
|
|
59
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.DELETE_WORKSPACE);
|
|
58
60
|
}
|
|
59
61
|
});
|
|
60
62
|
}
|
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.5",
|
|
5
5
|
"main": "./dist/stdio.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cnb-mcp-stdio": "dist/stdio.js",
|
|
@@ -46,21 +46,21 @@
|
|
|
46
46
|
"zod": "3.24.3"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@commitlint/cli": "19.8.
|
|
50
|
-
"@commitlint/config-conventional": "19.8.
|
|
51
|
-
"@eslint/js": "9.
|
|
49
|
+
"@commitlint/cli": "19.8.1",
|
|
50
|
+
"@commitlint/config-conventional": "19.8.1",
|
|
51
|
+
"@eslint/js": "9.33.0",
|
|
52
52
|
"@modelcontextprotocol/inspector": "^0.16.2",
|
|
53
53
|
"@types/express": "5.0.1",
|
|
54
|
-
"@types/node": "
|
|
55
|
-
"eslint": "
|
|
56
|
-
"eslint-config-prettier": "10.1.
|
|
57
|
-
"eslint-plugin-prettier": "5.
|
|
58
|
-
"globals": "16.
|
|
54
|
+
"@types/node": "^18.19.123",
|
|
55
|
+
"eslint": "9.33.0",
|
|
56
|
+
"eslint-config-prettier": "10.1.8",
|
|
57
|
+
"eslint-plugin-prettier": "5.5.4",
|
|
58
|
+
"globals": "16.3.0",
|
|
59
59
|
"husky": "9.1.7",
|
|
60
|
-
"lint-staged": "15.5.
|
|
61
|
-
"prettier": "3.
|
|
62
|
-
"typescript": "5.
|
|
63
|
-
"typescript-eslint": "8.
|
|
60
|
+
"lint-staged": "15.5.2",
|
|
61
|
+
"prettier": "3.6.2",
|
|
62
|
+
"typescript": "5.9.2",
|
|
63
|
+
"typescript-eslint": "8.40.0"
|
|
64
64
|
},
|
|
65
65
|
"lint-staged": {
|
|
66
66
|
"**/*": [
|