@cnbcool/mcp-server 0.4.5 → 0.5.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/dist/api/client.js +0 -12
- package/dist/api/group.js +10 -17
- package/dist/api/issue.js +26 -32
- package/dist/api/pull.js +16 -22
- package/dist/api/repository.js +10 -16
- package/dist/api/user.js +2 -7
- package/dist/api/workspace.js +6 -12
- package/dist/helpers/checkRepoVisibility.js +2 -2
- package/dist/helpers/createTransport.js +31 -4
- package/dist/helpers/sendResponse.js +34 -0
- package/dist/streamable.js +16 -3
- package/dist/tools/groupTools.js +5 -5
- package/dist/tools/index.js +6 -6
- package/dist/tools/issueTools.js +13 -13
- package/dist/tools/pullTools.js +8 -8
- package/dist/tools/repoTools.js +8 -8
- package/dist/tools/workspaceTools.js +3 -3
- package/package.json +2 -2
package/dist/api/client.js
CHANGED
|
@@ -8,17 +8,6 @@ class CnbApiClient {
|
|
|
8
8
|
get baseUrl() {
|
|
9
9
|
return this._baseUrl;
|
|
10
10
|
}
|
|
11
|
-
static initialize(options) {
|
|
12
|
-
if (!CnbApiClient.instance) {
|
|
13
|
-
CnbApiClient.instance = new CnbApiClient(options);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
static getInstance() {
|
|
17
|
-
if (!CnbApiClient.instance) {
|
|
18
|
-
throw new Error('CnbApiClient not initialized. Call CnbApiClient.initialize(baseUrl, token) first.');
|
|
19
|
-
}
|
|
20
|
-
return CnbApiClient.instance;
|
|
21
|
-
}
|
|
22
11
|
async request(method, path, body, config, responseType = 'json' // 'json' | 'text' | 'raw'
|
|
23
12
|
) {
|
|
24
13
|
const url = `${this._baseUrl}${path}`;
|
|
@@ -46,5 +35,4 @@ class CnbApiClient {
|
|
|
46
35
|
return response.json();
|
|
47
36
|
}
|
|
48
37
|
}
|
|
49
|
-
CnbApiClient.instance = null;
|
|
50
38
|
exports.default = CnbApiClient;
|
package/dist/api/group.js
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.listGroups = listGroups;
|
|
7
4
|
exports.listSubGroups = listSubGroups;
|
|
8
5
|
exports.getGroup = getGroup;
|
|
9
6
|
exports.createGroup = createGroup;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const cnbInst = client_js_1.default.getInstance();
|
|
13
|
-
const url = new URL('/user/groups', cnbInst.baseUrl);
|
|
7
|
+
async function listGroups(client, params) {
|
|
8
|
+
const url = new URL('/user/groups', client.baseUrl);
|
|
14
9
|
if (params) {
|
|
15
10
|
for (const [key, value] of Object.entries(params)) {
|
|
16
11
|
if (value === undefined)
|
|
@@ -18,11 +13,10 @@ async function listGroups(params) {
|
|
|
18
13
|
url.searchParams.set(key, value.toString());
|
|
19
14
|
}
|
|
20
15
|
}
|
|
21
|
-
return
|
|
16
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
22
17
|
}
|
|
23
|
-
async function listSubGroups(group, params) {
|
|
24
|
-
const
|
|
25
|
-
const url = new URL(`/user/groups/${group}`, cnbInst.baseUrl);
|
|
18
|
+
async function listSubGroups(client, group, params) {
|
|
19
|
+
const url = new URL(`/user/groups/${group}`, client.baseUrl);
|
|
26
20
|
if (params) {
|
|
27
21
|
for (const [key, value] of Object.entries(params)) {
|
|
28
22
|
if (value === undefined)
|
|
@@ -30,20 +24,19 @@ async function listSubGroups(group, params) {
|
|
|
30
24
|
url.searchParams.set(key, value.toString());
|
|
31
25
|
}
|
|
32
26
|
}
|
|
33
|
-
return
|
|
27
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
34
28
|
}
|
|
35
|
-
async function getGroup(group) {
|
|
36
|
-
|
|
37
|
-
return cnbInst.request('GET', `/${group}`);
|
|
29
|
+
async function getGroup(client, group) {
|
|
30
|
+
return client.request('GET', `/${group}`);
|
|
38
31
|
}
|
|
39
|
-
async function createGroup(params) {
|
|
32
|
+
async function createGroup(client, params) {
|
|
40
33
|
const body = Object.entries(params).reduce((acc, [key, value]) => {
|
|
41
34
|
if (value === undefined)
|
|
42
35
|
return acc;
|
|
43
36
|
Object.assign(acc, { [key]: value });
|
|
44
37
|
return acc;
|
|
45
38
|
}, {});
|
|
46
|
-
const response = await
|
|
39
|
+
const response = await client.request('POST', '/groups', body, {
|
|
47
40
|
header: { 'Content-Type': 'application/json' }
|
|
48
41
|
}, 'raw');
|
|
49
42
|
if (response.status === 201) {
|
package/dist/api/issue.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.listIssues = listIssues;
|
|
7
4
|
exports.getIssue = getIssue;
|
|
@@ -15,10 +12,8 @@ exports.addIssueLabels = addIssueLabels;
|
|
|
15
12
|
exports.setIssueLabels = setIssueLabels;
|
|
16
13
|
exports.deleteIssueLabels = deleteIssueLabels;
|
|
17
14
|
exports.deleteIssueLabel = deleteIssueLabel;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const cnbInst = client_js_1.default.getInstance();
|
|
21
|
-
const url = new URL(`/${repo}/-/issues`, cnbInst.baseUrl);
|
|
15
|
+
async function listIssues(client, repo, params) {
|
|
16
|
+
const url = new URL(`/${repo}/-/issues`, client.baseUrl);
|
|
22
17
|
if (params) {
|
|
23
18
|
for (const [key, value] of Object.entries(params)) {
|
|
24
19
|
if (value === undefined)
|
|
@@ -26,30 +21,29 @@ async function listIssues(repo, params) {
|
|
|
26
21
|
url.searchParams.set(key, value.toString());
|
|
27
22
|
}
|
|
28
23
|
}
|
|
29
|
-
return
|
|
24
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
30
25
|
}
|
|
31
|
-
async function getIssue(repo, issueId) {
|
|
32
|
-
return
|
|
26
|
+
async function getIssue(client, repo, issueId) {
|
|
27
|
+
return client.request('GET', `/${repo}/-/issues/${issueId}`);
|
|
33
28
|
}
|
|
34
|
-
async function createIssue(repo, params) {
|
|
29
|
+
async function createIssue(client, repo, params) {
|
|
35
30
|
const newParams = Object.entries(params).reduce((acc, [key, value]) => {
|
|
36
31
|
if (value === undefined)
|
|
37
32
|
return acc;
|
|
38
33
|
Object.assign(acc, { [key]: value });
|
|
39
34
|
return acc;
|
|
40
35
|
}, {});
|
|
41
|
-
return
|
|
36
|
+
return client.request('POST', `/${repo}/-/issues`, newParams, {
|
|
42
37
|
header: { 'Content-Type': 'application/json' }
|
|
43
38
|
});
|
|
44
39
|
}
|
|
45
|
-
async function updateIssue(repo, issueId, params) {
|
|
46
|
-
return
|
|
40
|
+
async function updateIssue(client, repo, issueId, params) {
|
|
41
|
+
return client.request('PATCH', `/${repo}/-/issues/${issueId}`, params, {
|
|
47
42
|
header: { 'Content-Type': 'application/json' }
|
|
48
43
|
});
|
|
49
44
|
}
|
|
50
|
-
async function listIssueComments(repo, issueId, params) {
|
|
51
|
-
const
|
|
52
|
-
const url = new URL(`/${repo}/-/issues/${issueId}/comments`, cnbInst.baseUrl);
|
|
45
|
+
async function listIssueComments(client, repo, issueId, params) {
|
|
46
|
+
const url = new URL(`/${repo}/-/issues/${issueId}/comments`, client.baseUrl);
|
|
53
47
|
if (params) {
|
|
54
48
|
for (const [key, value] of Object.entries(params)) {
|
|
55
49
|
if (value === undefined)
|
|
@@ -57,34 +51,34 @@ async function listIssueComments(repo, issueId, params) {
|
|
|
57
51
|
url.searchParams.set(key, value.toString());
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
|
-
return
|
|
54
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
61
55
|
}
|
|
62
|
-
async function createIssueComment(repo, issueId, params) {
|
|
63
|
-
return
|
|
56
|
+
async function createIssueComment(client, repo, issueId, params) {
|
|
57
|
+
return client.request('POST', `/${repo}/-/issues/${issueId}/comments`, params, {
|
|
64
58
|
header: { 'Content-Type': 'application/json' }
|
|
65
59
|
});
|
|
66
60
|
}
|
|
67
|
-
async function updateIssueComment(repo, issueId, commentId, params) {
|
|
68
|
-
return
|
|
61
|
+
async function updateIssueComment(client, repo, issueId, commentId, params) {
|
|
62
|
+
return client.request('PATCH', `/${repo}/-/issues/${issueId}/comments/${commentId}`, params, {
|
|
69
63
|
header: { 'Content-Type': 'application/json' }
|
|
70
64
|
});
|
|
71
65
|
}
|
|
72
|
-
async function listIssueLabels(repo, issueId) {
|
|
73
|
-
return
|
|
66
|
+
async function listIssueLabels(client, repo, issueId) {
|
|
67
|
+
return client.request('GET', `/${repo}/-/issues/${issueId}/labels`);
|
|
74
68
|
}
|
|
75
|
-
async function addIssueLabels(repo, issueId, labels) {
|
|
76
|
-
return
|
|
69
|
+
async function addIssueLabels(client, repo, issueId, labels) {
|
|
70
|
+
return client.request('POST', `/${repo}/-/issues/${issueId}/labels`, { labels }, {
|
|
77
71
|
header: { 'Content-Type': 'application/json' }
|
|
78
72
|
});
|
|
79
73
|
}
|
|
80
|
-
async function setIssueLabels(repo, issueId, labels) {
|
|
81
|
-
return
|
|
74
|
+
async function setIssueLabels(client, repo, issueId, labels) {
|
|
75
|
+
return client.request('PUT', `/${repo}/-/issues/${issueId}/labels`, { labels }, {
|
|
82
76
|
header: { 'Content-Type': 'application/json' }
|
|
83
77
|
});
|
|
84
78
|
}
|
|
85
|
-
async function deleteIssueLabels(repo, issueId) {
|
|
86
|
-
await
|
|
79
|
+
async function deleteIssueLabels(client, repo, issueId) {
|
|
80
|
+
await client.request('DELETE', `/${repo}/-/issues/${issueId}/labels`);
|
|
87
81
|
}
|
|
88
|
-
async function deleteIssueLabel(repo, issueId, labelName) {
|
|
89
|
-
await
|
|
82
|
+
async function deleteIssueLabel(client, repo, issueId, labelName) {
|
|
83
|
+
await client.request('DELETE', `/${repo}/-/issues/${issueId}/labels/${encodeURIComponent(labelName)}`);
|
|
90
84
|
}
|
package/dist/api/pull.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.listPulls = listPulls;
|
|
7
4
|
exports.getPull = getPull;
|
|
@@ -10,10 +7,8 @@ exports.updatePull = updatePull;
|
|
|
10
7
|
exports.mergePull = mergePull;
|
|
11
8
|
exports.listPullComments = listPullComments;
|
|
12
9
|
exports.createPullComment = createPullComment;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const cnbInst = client_js_1.default.getInstance();
|
|
16
|
-
const url = new URL(`/${repo}/-/pulls`, cnbInst.baseUrl);
|
|
10
|
+
async function listPulls(client, repo, params) {
|
|
11
|
+
const url = new URL(`/${repo}/-/pulls`, client.baseUrl);
|
|
17
12
|
if (params) {
|
|
18
13
|
for (const [key, value] of Object.entries(params)) {
|
|
19
14
|
if (value === undefined)
|
|
@@ -21,29 +16,28 @@ async function listPulls(repo, params) {
|
|
|
21
16
|
url.searchParams.set(key, value.toString());
|
|
22
17
|
}
|
|
23
18
|
}
|
|
24
|
-
return
|
|
19
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
25
20
|
}
|
|
26
|
-
async function getPull(repo, number) {
|
|
27
|
-
return
|
|
21
|
+
async function getPull(client, repo, number) {
|
|
22
|
+
return client.request('GET', `/${repo}/-/pulls/${number}`);
|
|
28
23
|
}
|
|
29
|
-
async function createPull(repo, params) {
|
|
30
|
-
return
|
|
24
|
+
async function createPull(client, repo, params) {
|
|
25
|
+
return client.request('POST', `/${repo}/-/pulls`, params, {
|
|
31
26
|
header: { 'Content-Type': 'application/json' }
|
|
32
27
|
});
|
|
33
28
|
}
|
|
34
|
-
async function updatePull(repo, number, params) {
|
|
35
|
-
return
|
|
29
|
+
async function updatePull(client, repo, number, params) {
|
|
30
|
+
return client.request('PATCH', `/${repo}/-/pulls/${number}`, params, {
|
|
36
31
|
header: { 'Content-Type': 'application/json' }
|
|
37
32
|
});
|
|
38
33
|
}
|
|
39
|
-
async function mergePull(repo, number, params) {
|
|
40
|
-
return
|
|
34
|
+
async function mergePull(client, repo, number, params) {
|
|
35
|
+
return client.request('PUT', `/${repo}/-/pulls/${number}/merge`, params, {
|
|
41
36
|
header: { 'Content-Type': 'application/json' }
|
|
42
37
|
});
|
|
43
38
|
}
|
|
44
|
-
async function listPullComments(repo, number, params) {
|
|
45
|
-
const
|
|
46
|
-
const url = new URL(`/${repo}/-/pulls/${number}/comments`, cnbInst.baseUrl);
|
|
39
|
+
async function listPullComments(client, repo, number, params) {
|
|
40
|
+
const url = new URL(`/${repo}/-/pulls/${number}/comments`, client.baseUrl);
|
|
47
41
|
if (params) {
|
|
48
42
|
for (const [key, value] of Object.entries(params)) {
|
|
49
43
|
if (value === undefined)
|
|
@@ -51,10 +45,10 @@ async function listPullComments(repo, number, params) {
|
|
|
51
45
|
url.searchParams.set(key, value.toString());
|
|
52
46
|
}
|
|
53
47
|
}
|
|
54
|
-
return
|
|
48
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
55
49
|
}
|
|
56
|
-
async function createPullComment(repo, number, params) {
|
|
57
|
-
const response = await
|
|
50
|
+
async function createPullComment(client, repo, number, params) {
|
|
51
|
+
const response = await client.request('POST', `/${repo}/-/pulls/${number}/comments`, params, {
|
|
58
52
|
header: { 'Content-Type': 'application/json' }
|
|
59
53
|
}, 'raw');
|
|
60
54
|
if (response.status === 201) {
|
package/dist/api/repository.js
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.listRepositories = listRepositories;
|
|
7
4
|
exports.listGroupRepositories = listGroupRepositories;
|
|
8
5
|
exports.getRepository = getRepository;
|
|
9
6
|
exports.createRepository = createRepository;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const cnbInst = client_js_1.default.getInstance();
|
|
13
|
-
const url = new URL('/user/repos', cnbInst.baseUrl);
|
|
7
|
+
async function listRepositories(client, params) {
|
|
8
|
+
const url = new URL('/user/repos', client.baseUrl);
|
|
14
9
|
if (params) {
|
|
15
10
|
for (const [key, value] of Object.entries(params)) {
|
|
16
11
|
if (value === undefined)
|
|
@@ -18,11 +13,10 @@ async function listRepositories(params) {
|
|
|
18
13
|
url.searchParams.set(key, value.toString());
|
|
19
14
|
}
|
|
20
15
|
}
|
|
21
|
-
return
|
|
16
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
22
17
|
}
|
|
23
|
-
async function listGroupRepositories(group, params) {
|
|
24
|
-
const
|
|
25
|
-
const url = new URL(`/${group}/-/repos`, cnbInst.baseUrl);
|
|
18
|
+
async function listGroupRepositories(client, group, params) {
|
|
19
|
+
const url = new URL(`/${group}/-/repos`, client.baseUrl);
|
|
26
20
|
if (params) {
|
|
27
21
|
for (const [key, value] of Object.entries(params)) {
|
|
28
22
|
if (value === undefined)
|
|
@@ -30,19 +24,19 @@ async function listGroupRepositories(group, params) {
|
|
|
30
24
|
url.searchParams.set(key, value.toString());
|
|
31
25
|
}
|
|
32
26
|
}
|
|
33
|
-
return
|
|
27
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
34
28
|
}
|
|
35
|
-
async function getRepository(repo) {
|
|
36
|
-
return
|
|
29
|
+
async function getRepository(client, repo) {
|
|
30
|
+
return client.request('GET', `/${repo}`);
|
|
37
31
|
}
|
|
38
|
-
async function createRepository(group, params) {
|
|
32
|
+
async function createRepository(client, group, params) {
|
|
39
33
|
const body = Object.entries(params).reduce((acc, [key, value]) => {
|
|
40
34
|
if (value === undefined)
|
|
41
35
|
return acc;
|
|
42
36
|
Object.assign(acc, { [key]: value });
|
|
43
37
|
return acc;
|
|
44
38
|
}, {});
|
|
45
|
-
const response = await
|
|
39
|
+
const response = await client.request('POST', `/${group}/-/repos`, body, {
|
|
46
40
|
header: { 'Content-Type': 'application/json' }
|
|
47
41
|
}, 'raw');
|
|
48
42
|
if (response.status === 201) {
|
package/dist/api/user.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.getUser = getUser;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const cnbInst = client_js_1.default.getInstance();
|
|
10
|
-
return cnbInst.request('GET', '/user');
|
|
4
|
+
async function getUser(client) {
|
|
5
|
+
return client.request('GET', '/user');
|
|
11
6
|
}
|
package/dist/api/workspace.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.listWorkspace = listWorkspace;
|
|
7
4
|
exports.deleteWorkspace = deleteWorkspace;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const cnbInst = client_js_1.default.getInstance();
|
|
11
|
-
const url = new URL('/workspace/list', cnbInst.baseUrl);
|
|
5
|
+
async function listWorkspace(client, params) {
|
|
6
|
+
const url = new URL('/workspace/list', client.baseUrl);
|
|
12
7
|
if (params) {
|
|
13
8
|
for (const [key, value] of Object.entries(params)) {
|
|
14
9
|
if (value === undefined)
|
|
@@ -16,12 +11,11 @@ async function listWorkspace(params) {
|
|
|
16
11
|
url.searchParams.set(key, value.toString());
|
|
17
12
|
}
|
|
18
13
|
}
|
|
19
|
-
return
|
|
14
|
+
return client.request('GET', `${url.pathname}${url.search}`);
|
|
20
15
|
}
|
|
21
|
-
async function deleteWorkspace(params) {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
return cnbInst.request('POST', `${url.pathname}`, params, {
|
|
16
|
+
async function deleteWorkspace(client, params) {
|
|
17
|
+
const url = new URL('/workspace/delete', client.baseUrl);
|
|
18
|
+
return client.request('POST', `${url.pathname}`, params, {
|
|
25
19
|
header: { 'Content-Type': 'application/json' }
|
|
26
20
|
});
|
|
27
21
|
}
|
|
@@ -4,12 +4,12 @@ exports.isRepoPublic = isRepoPublic;
|
|
|
4
4
|
const index_js_1 = require("../constants/index.js");
|
|
5
5
|
const repository_js_1 = require("../api/repository.js");
|
|
6
6
|
const formatRepoUrl_js_1 = require("./formatRepoUrl.js");
|
|
7
|
-
async function isRepoPublic(url) {
|
|
7
|
+
async function isRepoPublic(client, url) {
|
|
8
8
|
const repoPath = (0, formatRepoUrl_js_1.getRepoPath)(url);
|
|
9
9
|
if (!repoPath)
|
|
10
10
|
return true;
|
|
11
11
|
try {
|
|
12
|
-
const { visibility_level } = await (0, repository_js_1.getRepository)(repoPath);
|
|
12
|
+
const { visibility_level } = await (0, repository_js_1.getRepository)(client, repoPath);
|
|
13
13
|
// @ts-expect-error 字段类型转换过,但 swagger 无法感知
|
|
14
14
|
return visibility_level === index_js_1.RepoVisibility.public;
|
|
15
15
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.transports = void 0;
|
|
4
4
|
exports.createStreamableTransport = createStreamableTransport;
|
|
5
|
+
exports.createStatelessStreamableTransport = createStatelessStreamableTransport;
|
|
5
6
|
const node_crypto_1 = require("node:crypto");
|
|
6
7
|
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
7
8
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
@@ -17,7 +18,10 @@ async function createStreamableTransport(req) {
|
|
|
17
18
|
if (sessionId && exports.transports.streamable[sessionId]) {
|
|
18
19
|
const transport = exports.transports.streamable[sessionId];
|
|
19
20
|
if (!(transport instanceof streamableHttp_js_1.StreamableHTTPServerTransport)) {
|
|
20
|
-
throw
|
|
21
|
+
throw {
|
|
22
|
+
status: 400,
|
|
23
|
+
message: 'Session exists but uses a different transport protocol'
|
|
24
|
+
};
|
|
21
25
|
}
|
|
22
26
|
return transport;
|
|
23
27
|
}
|
|
@@ -31,8 +35,6 @@ async function createStreamableTransport(req) {
|
|
|
31
35
|
});
|
|
32
36
|
// Clean up transport when closed
|
|
33
37
|
transport.onclose = () => {
|
|
34
|
-
console.log(`Transport closed for session ${transport.sessionId}`);
|
|
35
|
-
console.log(Object.keys(exports.transports.streamable));
|
|
36
38
|
if (transport.sessionId) {
|
|
37
39
|
delete exports.transports.streamable[transport.sessionId];
|
|
38
40
|
}
|
|
@@ -41,5 +43,30 @@ async function createStreamableTransport(req) {
|
|
|
41
43
|
await mcpServer.connect(transport);
|
|
42
44
|
return transport;
|
|
43
45
|
}
|
|
44
|
-
throw
|
|
46
|
+
throw {
|
|
47
|
+
status: 400,
|
|
48
|
+
message: 'No valid session ID provided'
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async function createStatelessStreamableTransport(req, res) {
|
|
52
|
+
try {
|
|
53
|
+
const mcpServer = (0, createMcpServer_1.createMcpServer)(req);
|
|
54
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
55
|
+
sessionIdGenerator: undefined
|
|
56
|
+
});
|
|
57
|
+
res.on('close', () => {
|
|
58
|
+
console.log('Request closed');
|
|
59
|
+
void transport.close();
|
|
60
|
+
void mcpServer.close();
|
|
61
|
+
});
|
|
62
|
+
await mcpServer.connect(transport);
|
|
63
|
+
return transport;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('Error handling MCP request:', error);
|
|
67
|
+
if (!res.headersSent) {
|
|
68
|
+
throw new Error('Internal Server Error');
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
45
72
|
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stopWithError = stopWithError;
|
|
3
4
|
exports.stopWithBadRequest = stopWithBadRequest;
|
|
5
|
+
exports.stopWithMethodNotAllowed = stopWithMethodNotAllowed;
|
|
6
|
+
exports.stopWithServerError = stopWithServerError;
|
|
7
|
+
function stopWithError(res, status, message) {
|
|
8
|
+
if (status === 400) {
|
|
9
|
+
stopWithBadRequest(res, message);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (status === 405) {
|
|
13
|
+
stopWithMethodNotAllowed(res, message);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
stopWithServerError(res, message);
|
|
17
|
+
}
|
|
4
18
|
function stopWithBadRequest(res, message) {
|
|
5
19
|
res.status(400).json({
|
|
6
20
|
jsonrpc: '2.0',
|
|
@@ -11,3 +25,23 @@ function stopWithBadRequest(res, message) {
|
|
|
11
25
|
id: null
|
|
12
26
|
});
|
|
13
27
|
}
|
|
28
|
+
function stopWithMethodNotAllowed(res, message) {
|
|
29
|
+
res.writeHead(405).end(JSON.stringify({
|
|
30
|
+
jsonrpc: '2.0',
|
|
31
|
+
error: {
|
|
32
|
+
code: -32000,
|
|
33
|
+
message
|
|
34
|
+
},
|
|
35
|
+
id: null
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
function stopWithServerError(res, message) {
|
|
39
|
+
res.status(500).json({
|
|
40
|
+
jsonrpc: '2.0',
|
|
41
|
+
error: {
|
|
42
|
+
code: -32603,
|
|
43
|
+
message
|
|
44
|
+
},
|
|
45
|
+
id: null
|
|
46
|
+
});
|
|
47
|
+
}
|
package/dist/streamable.js
CHANGED
|
@@ -18,16 +18,27 @@ app.use(express_1.default.json());
|
|
|
18
18
|
app.post('/mcp', async (req, res) => {
|
|
19
19
|
let transport;
|
|
20
20
|
try {
|
|
21
|
-
transport =
|
|
21
|
+
transport = process.env.MODE_STATELESS
|
|
22
|
+
? await (0, createTransport_js_1.createStatelessStreamableTransport)(req, res)
|
|
23
|
+
: await (0, createTransport_js_1.createStreamableTransport)(req);
|
|
22
24
|
}
|
|
23
25
|
catch (err) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
if (typeof err === 'object' && err !== null && 'status' in err && 'message' in err) {
|
|
27
|
+
const { status, message } = err;
|
|
28
|
+
(0, sendResponse_js_1.stopWithError)(res, status, message);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
32
|
+
(0, sendResponse_js_1.stopWithServerError)(res, message !== null && message !== void 0 ? message : 'Unknown error');
|
|
26
33
|
return;
|
|
27
34
|
}
|
|
28
35
|
await transport.handleRequest(req, res, req.body);
|
|
29
36
|
});
|
|
30
37
|
const handleSessionRequest = async (req, res) => {
|
|
38
|
+
if (process.env.MODE_STATELESS) {
|
|
39
|
+
(0, sendResponse_js_1.stopWithMethodNotAllowed)(res, 'Method not allowed');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
31
42
|
const sessionId = req.headers['mcp-session-id'];
|
|
32
43
|
if (!sessionId || !createTransport_js_1.transports.streamable[sessionId]) {
|
|
33
44
|
res.status(400).send('Invalid or missing session ID');
|
|
@@ -36,7 +47,9 @@ const handleSessionRequest = async (req, res) => {
|
|
|
36
47
|
const transport = createTransport_js_1.transports.streamable[sessionId];
|
|
37
48
|
await transport.handleRequest(req, res, req.body);
|
|
38
49
|
};
|
|
50
|
+
// SSE notifications not supported in stateless mode
|
|
39
51
|
app.get('/mcp', handleSessionRequest);
|
|
52
|
+
// Session termination not needed in stateless mode
|
|
40
53
|
app.delete('/mcp', handleSessionRequest);
|
|
41
54
|
app.get('/sse', async (req, res) => {
|
|
42
55
|
const transport = new sse_js_1.SSEServerTransport('/messages', res);
|
package/dist/tools/groupTools.js
CHANGED
|
@@ -6,7 +6,7 @@ const toolNames_js_1 = require("../constants/toolNames.js");
|
|
|
6
6
|
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
7
7
|
const group_js_1 = require("../api/group.js");
|
|
8
8
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
9
|
-
function registerGroupTools(server) {
|
|
9
|
+
function registerGroupTools(server, client) {
|
|
10
10
|
server.tool(toolNames_js_1.ToolNames.LIST_GROUPS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_GROUPS], {
|
|
11
11
|
page: zod_1.z.number().default(1).describe('第几页,从1开始'),
|
|
12
12
|
page_size: zod_1.z.number().default(10).describe('每页多少条数据'),
|
|
@@ -16,7 +16,7 @@ function registerGroupTools(server) {
|
|
|
16
16
|
.describe('最小仓库权限')
|
|
17
17
|
}, async ({ page, page_size, search, role }) => {
|
|
18
18
|
try {
|
|
19
|
-
const groups = await (0, group_js_1.listGroups)({ page, page_size, search, role });
|
|
19
|
+
const groups = await (0, group_js_1.listGroups)(client, { page, page_size, search, role });
|
|
20
20
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(groups, null, 2), toolNames_js_1.ToolNames.LIST_GROUPS);
|
|
21
21
|
}
|
|
22
22
|
catch (error) {
|
|
@@ -30,7 +30,7 @@ function registerGroupTools(server) {
|
|
|
30
30
|
access: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.number().optional()).describe('权限等级')
|
|
31
31
|
}, async ({ group, page, page_size, access }) => {
|
|
32
32
|
try {
|
|
33
|
-
const subGroups = await (0, group_js_1.listSubGroups)(group, { page, page_size, access });
|
|
33
|
+
const subGroups = await (0, group_js_1.listSubGroups)(client, group, { page, page_size, access });
|
|
34
34
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(subGroups, null, 2), toolNames_js_1.ToolNames.LIST_SUB_GROUPS);
|
|
35
35
|
}
|
|
36
36
|
catch (error) {
|
|
@@ -41,7 +41,7 @@ function registerGroupTools(server) {
|
|
|
41
41
|
group: zod_1.z.string().describe('组织路径')
|
|
42
42
|
}, async ({ group }) => {
|
|
43
43
|
try {
|
|
44
|
-
const groupInfo = await (0, group_js_1.getGroup)(group);
|
|
44
|
+
const groupInfo = await (0, group_js_1.getGroup)(client, group);
|
|
45
45
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(groupInfo, null, 2), toolNames_js_1.ToolNames.GET_GROUP);
|
|
46
46
|
}
|
|
47
47
|
catch (error) {
|
|
@@ -57,7 +57,7 @@ function registerGroupTools(server) {
|
|
|
57
57
|
.describe('根组织绑定的域名')
|
|
58
58
|
}, async ({ path, description, remark, bind_domain }) => {
|
|
59
59
|
try {
|
|
60
|
-
const data = await (0, group_js_1.createGroup)({ path, description, remark, bind_domain });
|
|
60
|
+
const data = await (0, group_js_1.createGroup)(client, { path, description, remark, bind_domain });
|
|
61
61
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.CREATE_GROUP);
|
|
62
62
|
}
|
|
63
63
|
catch (error) {
|
package/dist/tools/index.js
CHANGED
|
@@ -11,13 +11,13 @@ const issueTools_js_1 = __importDefault(require("./issueTools.js"));
|
|
|
11
11
|
const workspaceTools_js_1 = __importDefault(require("./workspaceTools.js"));
|
|
12
12
|
const pullTools_js_1 = __importDefault(require("./pullTools.js"));
|
|
13
13
|
function registerTools(server, token) {
|
|
14
|
-
client_js_1.default
|
|
14
|
+
const client = new client_js_1.default({
|
|
15
15
|
baseUrl: process.env.API_BASE_URL || 'https://api.cnb.cool',
|
|
16
16
|
token: process.env.API_TOKEN || token || ''
|
|
17
17
|
});
|
|
18
|
-
(0, groupTools_js_1.default)(server);
|
|
19
|
-
(0, repoTools_js_1.default)(server);
|
|
20
|
-
(0, issueTools_js_1.default)(server);
|
|
21
|
-
(0, workspaceTools_js_1.default)(server);
|
|
22
|
-
(0, pullTools_js_1.default)(server);
|
|
18
|
+
(0, groupTools_js_1.default)(server, client);
|
|
19
|
+
(0, repoTools_js_1.default)(server, client);
|
|
20
|
+
(0, issueTools_js_1.default)(server, client);
|
|
21
|
+
(0, workspaceTools_js_1.default)(server, client);
|
|
22
|
+
(0, pullTools_js_1.default)(server, client);
|
|
23
23
|
}
|
package/dist/tools/issueTools.js
CHANGED
|
@@ -6,7 +6,7 @@ const toolNames_js_1 = require("../constants/toolNames.js");
|
|
|
6
6
|
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
7
7
|
const issue_js_1 = require("../api/issue.js");
|
|
8
8
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
9
|
-
function registerIssueTools(server) {
|
|
9
|
+
function registerIssueTools(server, client) {
|
|
10
10
|
server.tool(toolNames_js_1.ToolNames.LIST_ISSUES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_ISSUES], {
|
|
11
11
|
repo: zod_1.z.string().describe('仓库路径'),
|
|
12
12
|
page: zod_1.z.number().default(1).describe('第几页,从1开始'),
|
|
@@ -36,7 +36,7 @@ function registerIssueTools(server) {
|
|
|
36
36
|
.describe('Issue 排序顺序.example: created_at, -updated_at, reference_count。‘-’ prefix means descending order')
|
|
37
37
|
}, async ({ repo, page, page_size, state, keyword, priority, labels, authors, assignees, updated_time_begin, updated_time_end, order_by }) => {
|
|
38
38
|
try {
|
|
39
|
-
const issues = await (0, issue_js_1.listIssues)(repo, {
|
|
39
|
+
const issues = await (0, issue_js_1.listIssues)(client, repo, {
|
|
40
40
|
page,
|
|
41
41
|
page_size,
|
|
42
42
|
state,
|
|
@@ -60,7 +60,7 @@ function registerIssueTools(server) {
|
|
|
60
60
|
issueId: zod_1.z.number().describe('Issue ID')
|
|
61
61
|
}, async ({ repo, issueId }) => {
|
|
62
62
|
try {
|
|
63
|
-
const issues = await (0, issue_js_1.getIssue)(repo, issueId);
|
|
63
|
+
const issues = await (0, issue_js_1.getIssue)(client, repo, issueId);
|
|
64
64
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(issues, null, 2), toolNames_js_1.ToolNames.GET_ISSUE);
|
|
65
65
|
}
|
|
66
66
|
catch (error) {
|
|
@@ -86,7 +86,7 @@ function registerIssueTools(server) {
|
|
|
86
86
|
.describe('Issue 起始时间,格式为 YYYY-MM-DD')
|
|
87
87
|
}, async ({ repo, title, body, assignees, labels, priority, end_date, start_date }) => {
|
|
88
88
|
try {
|
|
89
|
-
const issue = await (0, issue_js_1.createIssue)(repo, {
|
|
89
|
+
const issue = await (0, issue_js_1.createIssue)(client, repo, {
|
|
90
90
|
title,
|
|
91
91
|
body,
|
|
92
92
|
assignees,
|
|
@@ -119,7 +119,7 @@ function registerIssueTools(server) {
|
|
|
119
119
|
.describe('Issue 状态原因')
|
|
120
120
|
}, async ({ repo, issueId, title, body, priority, end_date, start_date, state, state_reason }) => {
|
|
121
121
|
try {
|
|
122
|
-
const issue = await (0, issue_js_1.updateIssue)(repo, issueId, {
|
|
122
|
+
const issue = await (0, issue_js_1.updateIssue)(client, repo, issueId, {
|
|
123
123
|
title,
|
|
124
124
|
body,
|
|
125
125
|
priority,
|
|
@@ -141,7 +141,7 @@ function registerIssueTools(server) {
|
|
|
141
141
|
page_size: zod_1.z.number().default(30).describe('每页多少条数据,默认是30')
|
|
142
142
|
}, async ({ repo, issueId, page, page_size }) => {
|
|
143
143
|
try {
|
|
144
|
-
const comments = await (0, issue_js_1.listIssueComments)(repo, issueId, { page, page_size });
|
|
144
|
+
const comments = await (0, issue_js_1.listIssueComments)(client, repo, issueId, { page, page_size });
|
|
145
145
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comments, null, 2), toolNames_js_1.ToolNames.LIST_ISSUE_COMMENTS);
|
|
146
146
|
}
|
|
147
147
|
catch (error) {
|
|
@@ -154,7 +154,7 @@ function registerIssueTools(server) {
|
|
|
154
154
|
body: zod_1.z.string().describe('评论内容')
|
|
155
155
|
}, async ({ repo, issueId, body }) => {
|
|
156
156
|
try {
|
|
157
|
-
const comment = await (0, issue_js_1.createIssueComment)(repo, issueId, { body });
|
|
157
|
+
const comment = await (0, issue_js_1.createIssueComment)(client, repo, issueId, { body });
|
|
158
158
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comment, null, 2), toolNames_js_1.ToolNames.CREATE_ISSUE_COMMENT);
|
|
159
159
|
}
|
|
160
160
|
catch (error) {
|
|
@@ -168,7 +168,7 @@ function registerIssueTools(server) {
|
|
|
168
168
|
body: zod_1.z.string().describe('评论内容')
|
|
169
169
|
}, async ({ repo, issueId, commentId, body }) => {
|
|
170
170
|
try {
|
|
171
|
-
const comment = await (0, issue_js_1.updateIssueComment)(repo, issueId, commentId, { body });
|
|
171
|
+
const comment = await (0, issue_js_1.updateIssueComment)(client, repo, issueId, commentId, { body });
|
|
172
172
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comment, null, 2), toolNames_js_1.ToolNames.UPDATE_ISSUE_COMMENT);
|
|
173
173
|
}
|
|
174
174
|
catch (error) {
|
|
@@ -180,7 +180,7 @@ function registerIssueTools(server) {
|
|
|
180
180
|
issueId: zod_1.z.number().describe('Issue ID')
|
|
181
181
|
}, async ({ repo, issueId }) => {
|
|
182
182
|
try {
|
|
183
|
-
const labels = await (0, issue_js_1.listIssueLabels)(repo, issueId);
|
|
183
|
+
const labels = await (0, issue_js_1.listIssueLabels)(client, repo, issueId);
|
|
184
184
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(labels, null, 2), toolNames_js_1.ToolNames.LIST_ISSUE_LABELS);
|
|
185
185
|
}
|
|
186
186
|
catch (error) {
|
|
@@ -193,7 +193,7 @@ function registerIssueTools(server) {
|
|
|
193
193
|
labels: zod_1.z.array(zod_1.z.string()).describe('要添加的标签列表,每个标签需要从仓库标签列表中选择')
|
|
194
194
|
}, async ({ repo, issueId, labels }) => {
|
|
195
195
|
try {
|
|
196
|
-
const result = await (0, issue_js_1.addIssueLabels)(repo, issueId, labels);
|
|
196
|
+
const result = await (0, issue_js_1.addIssueLabels)(client, repo, issueId, labels);
|
|
197
197
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.ADD_ISSUE_LABELS);
|
|
198
198
|
}
|
|
199
199
|
catch (error) {
|
|
@@ -206,7 +206,7 @@ function registerIssueTools(server) {
|
|
|
206
206
|
labels: zod_1.z.array(zod_1.z.string()).describe('新的标签列表(将替换所有现有标签),每个标签需要从仓库标签列表中选择')
|
|
207
207
|
}, async ({ repo, issueId, labels }) => {
|
|
208
208
|
try {
|
|
209
|
-
const result = await (0, issue_js_1.setIssueLabels)(repo, issueId, labels);
|
|
209
|
+
const result = await (0, issue_js_1.setIssueLabels)(client, repo, issueId, labels);
|
|
210
210
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.SET_ISSUE_LABELS);
|
|
211
211
|
}
|
|
212
212
|
catch (error) {
|
|
@@ -218,7 +218,7 @@ function registerIssueTools(server) {
|
|
|
218
218
|
issueId: zod_1.z.number().describe('Issue ID')
|
|
219
219
|
}, async ({ repo, issueId }) => {
|
|
220
220
|
try {
|
|
221
|
-
await (0, issue_js_1.deleteIssueLabels)(repo, issueId);
|
|
221
|
+
await (0, issue_js_1.deleteIssueLabels)(client, repo, issueId);
|
|
222
222
|
return (0, formatToolResult_js_1.formatTextToolResult)('All labels deleted', toolNames_js_1.ToolNames.CLEAR_ISSUE_LABELS);
|
|
223
223
|
}
|
|
224
224
|
catch (error) {
|
|
@@ -231,7 +231,7 @@ function registerIssueTools(server) {
|
|
|
231
231
|
labelName: zod_1.z.string().describe('要删除的标签名称')
|
|
232
232
|
}, async ({ repo, issueId, labelName }) => {
|
|
233
233
|
try {
|
|
234
|
-
await (0, issue_js_1.deleteIssueLabel)(repo, issueId, labelName);
|
|
234
|
+
await (0, issue_js_1.deleteIssueLabel)(client, repo, issueId, labelName);
|
|
235
235
|
return (0, formatToolResult_js_1.formatTextToolResult)(`${labelName} deleted`, toolNames_js_1.ToolNames.REMOVE_ISSUE_LABEL);
|
|
236
236
|
}
|
|
237
237
|
catch (error) {
|
package/dist/tools/pullTools.js
CHANGED
|
@@ -6,7 +6,7 @@ const toolNames_js_1 = require("../constants/toolNames.js");
|
|
|
6
6
|
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
7
7
|
const pull_js_1 = require("../api/pull.js");
|
|
8
8
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
9
|
-
function registerPullTools(server) {
|
|
9
|
+
function registerPullTools(server, client) {
|
|
10
10
|
server.tool(toolNames_js_1.ToolNames.LIST_PULLS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_PULLS], {
|
|
11
11
|
repo: zod_1.z.string().describe('仓库路径,格式为 {group}/{repo}'),
|
|
12
12
|
state: zod_1.z
|
|
@@ -22,7 +22,7 @@ function registerPullTools(server) {
|
|
|
22
22
|
per_page: zod_1.z.number().default(30).describe('每页数量')
|
|
23
23
|
}, async ({ repo, ...params }) => {
|
|
24
24
|
try {
|
|
25
|
-
const pulls = await (0, pull_js_1.listPulls)(repo, params);
|
|
25
|
+
const pulls = await (0, pull_js_1.listPulls)(client, repo, params);
|
|
26
26
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pulls, null, 2), toolNames_js_1.ToolNames.LIST_PULLS);
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
@@ -34,7 +34,7 @@ function registerPullTools(server) {
|
|
|
34
34
|
number: zod_1.z.number().describe('Pull Request编号')
|
|
35
35
|
}, async ({ repo, number }) => {
|
|
36
36
|
try {
|
|
37
|
-
const pull = await (0, pull_js_1.getPull)(repo, number);
|
|
37
|
+
const pull = await (0, pull_js_1.getPull)(client, repo, number);
|
|
38
38
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2), toolNames_js_1.ToolNames.GET_PULL);
|
|
39
39
|
}
|
|
40
40
|
catch (error) {
|
|
@@ -50,7 +50,7 @@ function registerPullTools(server) {
|
|
|
50
50
|
body: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('描述')
|
|
51
51
|
}, async ({ repo, ...params }) => {
|
|
52
52
|
try {
|
|
53
|
-
const pull = await (0, pull_js_1.createPull)(repo, params);
|
|
53
|
+
const pull = await (0, pull_js_1.createPull)(client, repo, params);
|
|
54
54
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2), toolNames_js_1.ToolNames.CREATE_PULL);
|
|
55
55
|
}
|
|
56
56
|
catch (error) {
|
|
@@ -67,7 +67,7 @@ function registerPullTools(server) {
|
|
|
67
67
|
.describe('状态')
|
|
68
68
|
}, async ({ repo, number, ...params }) => {
|
|
69
69
|
try {
|
|
70
|
-
const pull = await (0, pull_js_1.updatePull)(repo, number, params);
|
|
70
|
+
const pull = await (0, pull_js_1.updatePull)(client, repo, number, params);
|
|
71
71
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(pull, null, 2), toolNames_js_1.ToolNames.UPDATE_PULL);
|
|
72
72
|
}
|
|
73
73
|
catch (error) {
|
|
@@ -86,7 +86,7 @@ function registerPullTools(server) {
|
|
|
86
86
|
.describe('合并提交信息')
|
|
87
87
|
}, async ({ repo, number, ...params }) => {
|
|
88
88
|
try {
|
|
89
|
-
const result = await (0, pull_js_1.mergePull)(repo, number, params);
|
|
89
|
+
const result = await (0, pull_js_1.mergePull)(client, repo, number, params);
|
|
90
90
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.MERGE_PULL);
|
|
91
91
|
}
|
|
92
92
|
catch (error) {
|
|
@@ -100,7 +100,7 @@ function registerPullTools(server) {
|
|
|
100
100
|
per_page: zod_1.z.number().default(30).describe('每页数量')
|
|
101
101
|
}, async ({ repo, number, ...params }) => {
|
|
102
102
|
try {
|
|
103
|
-
const comments = await (0, pull_js_1.listPullComments)(repo, number, params);
|
|
103
|
+
const comments = await (0, pull_js_1.listPullComments)(client, repo, number, params);
|
|
104
104
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(comments, null, 2), toolNames_js_1.ToolNames.LIST_PULL_COMMENTS);
|
|
105
105
|
}
|
|
106
106
|
catch (error) {
|
|
@@ -113,7 +113,7 @@ function registerPullTools(server) {
|
|
|
113
113
|
body: zod_1.z.string().describe('评论内容')
|
|
114
114
|
}, async ({ repo, number, body }) => {
|
|
115
115
|
try {
|
|
116
|
-
await (0, pull_js_1.createPullComment)(repo, number, { body });
|
|
116
|
+
await (0, pull_js_1.createPullComment)(client, repo, number, { body });
|
|
117
117
|
return (0, formatToolResult_js_1.formatTextToolResult)('Comment created', toolNames_js_1.ToolNames.CREATE_PULL_COMMENT);
|
|
118
118
|
}
|
|
119
119
|
catch (error) {
|
package/dist/tools/repoTools.js
CHANGED
|
@@ -9,7 +9,7 @@ const user_js_1 = require("../api/user.js");
|
|
|
9
9
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
10
10
|
const formatRepoUrl_js_1 = require("../helpers/formatRepoUrl.js");
|
|
11
11
|
const checkRepoVisibility_js_1 = require("../helpers/checkRepoVisibility.js");
|
|
12
|
-
function registerRepoTools(server) {
|
|
12
|
+
function registerRepoTools(server, client) {
|
|
13
13
|
server.tool(toolNames_js_1.ToolNames.LIST_REPOSITORIES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_REPOSITORIES], {
|
|
14
14
|
remote_url: zod_1.z.string().describe('远程仓库URL,需要先执行`git remote get-url origin`命令获取,获取不到传空字符串'),
|
|
15
15
|
page: zod_1.z.number().default(1).describe('第几页,从1开始,默认值是1'),
|
|
@@ -28,12 +28,12 @@ function registerRepoTools(server) {
|
|
|
28
28
|
.preprocess((val) => (val === null ? undefined : val), zod_1.z.boolean().optional())
|
|
29
29
|
.describe('是否开启倒叙排序,默认值是false')
|
|
30
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);
|
|
31
|
+
const isPublic = await (0, checkRepoVisibility_js_1.isRepoPublic)(client, remote_url);
|
|
32
32
|
if (isPublic) {
|
|
33
33
|
filter_type = 'public';
|
|
34
34
|
}
|
|
35
35
|
try {
|
|
36
|
-
const repos = await (0, repository_js_1.listRepositories)({ page, page_size, search, filter_type, role, order_by, desc });
|
|
36
|
+
const repos = await (0, repository_js_1.listRepositories)(client, { page, page_size, search, filter_type, role, order_by, desc });
|
|
37
37
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repos, null, 2), toolNames_js_1.ToolNames.LIST_REPOSITORIES);
|
|
38
38
|
}
|
|
39
39
|
catch (error) {
|
|
@@ -59,7 +59,7 @@ function registerRepoTools(server) {
|
|
|
59
59
|
.describe('是否开启倒叙排序,默认值是false')
|
|
60
60
|
}, async ({ group, page, page_size, search, filter_type, descendant, order_by, desc }) => {
|
|
61
61
|
try {
|
|
62
|
-
const repos = await (0, repository_js_1.listGroupRepositories)(group, {
|
|
62
|
+
const repos = await (0, repository_js_1.listGroupRepositories)(client, group, {
|
|
63
63
|
page,
|
|
64
64
|
page_size,
|
|
65
65
|
search,
|
|
@@ -78,7 +78,7 @@ function registerRepoTools(server) {
|
|
|
78
78
|
repo: zod_1.z.string().describe('仓库路径')
|
|
79
79
|
}, async ({ repo }) => {
|
|
80
80
|
try {
|
|
81
|
-
const repoInfo = await (0, repository_js_1.getRepository)(repo);
|
|
81
|
+
const repoInfo = await (0, repository_js_1.getRepository)(client, repo);
|
|
82
82
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repoInfo, null, 2), toolNames_js_1.ToolNames.GET_REPOSITORY);
|
|
83
83
|
}
|
|
84
84
|
catch (error) {
|
|
@@ -96,11 +96,11 @@ function registerRepoTools(server) {
|
|
|
96
96
|
}, async ({ group, name, description, license, visibility }) => {
|
|
97
97
|
let repoGroup = group;
|
|
98
98
|
if (!repoGroup) {
|
|
99
|
-
const { username = '' } = await (0, user_js_1.getUser)();
|
|
99
|
+
const { username = '' } = await (0, user_js_1.getUser)(client);
|
|
100
100
|
repoGroup = username;
|
|
101
101
|
}
|
|
102
102
|
try {
|
|
103
|
-
const data = await (0, repository_js_1.createRepository)(repoGroup, { name, description, license, visibility });
|
|
103
|
+
const data = await (0, repository_js_1.createRepository)(client, repoGroup, { name, description, license, visibility });
|
|
104
104
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.CREATE_REPOSITORY);
|
|
105
105
|
}
|
|
106
106
|
catch (error) {
|
|
@@ -116,7 +116,7 @@ function registerRepoTools(server) {
|
|
|
116
116
|
return (0, formatToolResult_js_1.formatToolError)(`无法从远程仓库URL解析出仓库路径: ${remote_url}`, toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY);
|
|
117
117
|
}
|
|
118
118
|
// 获取仓库信息
|
|
119
|
-
const data = await (0, repository_js_1.getRepository)(repoPath);
|
|
119
|
+
const data = await (0, repository_js_1.getRepository)(client, repoPath);
|
|
120
120
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY);
|
|
121
121
|
}
|
|
122
122
|
catch (error) {
|
|
@@ -6,7 +6,7 @@ const toolNames_js_1 = require("../constants/toolNames.js");
|
|
|
6
6
|
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
7
7
|
const workspace_js_1 = require("../api/workspace.js");
|
|
8
8
|
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
9
|
-
function registerWorkspaceTools(server) {
|
|
9
|
+
function registerWorkspaceTools(server, client) {
|
|
10
10
|
server.tool(toolNames_js_1.ToolNames.LIST_WORKSPACES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_WORKSPACES], {
|
|
11
11
|
branch: zod_1.z
|
|
12
12
|
.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
|
|
@@ -31,7 +31,7 @@ function registerWorkspaceTools(server) {
|
|
|
31
31
|
.describe('开发环境状态,running: 开发环境已启动,closed:开发环境已关闭,默认为所有状态')
|
|
32
32
|
}, async ({ branch, page, page_size, start, end, slug, status }) => {
|
|
33
33
|
try {
|
|
34
|
-
const workspaces = await (0, workspace_js_1.listWorkspace)({
|
|
34
|
+
const workspaces = await (0, workspace_js_1.listWorkspace)(client, {
|
|
35
35
|
branch,
|
|
36
36
|
page,
|
|
37
37
|
pageSize: page_size,
|
|
@@ -50,7 +50,7 @@ function registerWorkspaceTools(server) {
|
|
|
50
50
|
pipelineId: zod_1.z.string().describe('开发环境 ID')
|
|
51
51
|
}, async ({ pipelineId }) => {
|
|
52
52
|
try {
|
|
53
|
-
const result = await (0, workspace_js_1.deleteWorkspace)({
|
|
53
|
+
const result = await (0, workspace_js_1.deleteWorkspace)(client, {
|
|
54
54
|
pipelineId
|
|
55
55
|
});
|
|
56
56
|
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.DELETE_WORKSPACE);
|
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
|
+
"version": "0.5.1",
|
|
5
5
|
"main": "./dist/stdio.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cnb-mcp-stdio": "dist/stdio.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"typescript": ">=5.5"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@modelcontextprotocol/sdk": "1.
|
|
43
|
+
"@modelcontextprotocol/sdk": "1.12.1",
|
|
44
44
|
"dotenv": "16.5.0",
|
|
45
45
|
"express": "5.1.0",
|
|
46
46
|
"zod": "3.24.3"
|