@cnbcool/mcp-server 0.4.2 → 0.4.4
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 +6 -5
- package/dist/api/group.js +18 -9
- package/dist/api/issue.js +42 -25
- package/dist/api/pull.js +27 -15
- package/dist/api/repository.js +18 -9
- package/dist/api/user.js +9 -3
- package/dist/api/workspace.js +12 -5
- package/dist/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 +12 -9
- package/dist/helpers/formatRepoUrl.js +20 -0
- package/dist/helpers/formatToolResult.js +6 -2
- package/dist/helpers/sendResponse.js +4 -1
- package/dist/stdio.js +11 -6
- package/dist/streamable.js +28 -22
- package/dist/tools/groupTools.js +40 -35
- package/dist/tools/index.js +19 -13
- package/dist/tools/issueTools.js +126 -121
- package/dist/tools/pullTools.js +74 -69
- package/dist/tools/repoTools.js +72 -74
- package/dist/tools/workspaceTools.js +32 -27
- package/package.json +14 -15
package/dist/stdio.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
8
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
9
|
+
const createMcpServer_js_1 = require("./helpers/createMcpServer.js");
|
|
10
|
+
dotenv_1.default.config();
|
|
11
|
+
const server = (0, createMcpServer_js_1.createMcpServer)();
|
|
7
12
|
async function main() {
|
|
8
13
|
console.error('server starting...');
|
|
9
|
-
const transport = new StdioServerTransport();
|
|
14
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
10
15
|
await server.connect(transport);
|
|
11
16
|
console.error('server connected');
|
|
12
17
|
}
|
package/dist/streamable.js
CHANGED
|
@@ -1,38 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
var _a;
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const express_1 = __importDefault(require("express"));
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
11
|
+
const sse_js_1 = require("@modelcontextprotocol/sdk/server/sse.js");
|
|
12
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
13
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
14
|
+
const createMcpServer_js_1 = require("./helpers/createMcpServer.js");
|
|
15
|
+
const sendResponse_js_1 = require("./helpers/sendResponse.js");
|
|
16
|
+
dotenv_1.default.config();
|
|
11
17
|
const DEFAULT_APP_PORT = 3000;
|
|
12
18
|
// Store transports for each session type
|
|
13
19
|
const transports = {
|
|
14
20
|
streamable: {},
|
|
15
21
|
sse: {}
|
|
16
22
|
};
|
|
17
|
-
const app =
|
|
18
|
-
app.use(
|
|
23
|
+
const app = (0, express_1.default)();
|
|
24
|
+
app.use(express_1.default.json());
|
|
19
25
|
app.post('/mcp', async (req, res) => {
|
|
20
26
|
const sessionId = req.headers['mcp-session-id'];
|
|
21
27
|
let transport;
|
|
22
28
|
// Reuse existing transport
|
|
23
29
|
if (sessionId && transports.streamable[sessionId]) {
|
|
24
30
|
transport = transports.streamable[sessionId];
|
|
25
|
-
if (!(transport instanceof StreamableHTTPServerTransport)) {
|
|
26
|
-
stopWithWrongTransport(res);
|
|
31
|
+
if (!(transport instanceof streamableHttp_js_1.StreamableHTTPServerTransport)) {
|
|
32
|
+
(0, sendResponse_js_1.stopWithWrongTransport)(res);
|
|
27
33
|
return;
|
|
28
34
|
}
|
|
29
35
|
await transport.handleRequest(req, res, req.body);
|
|
30
36
|
return;
|
|
31
37
|
}
|
|
32
38
|
// New initialization request
|
|
33
|
-
if (!sessionId && isInitializeRequest(req.body)) {
|
|
34
|
-
transport = new StreamableHTTPServerTransport({
|
|
35
|
-
sessionIdGenerator: () => randomUUID(),
|
|
39
|
+
if (!sessionId && (0, types_js_1.isInitializeRequest)(req.body)) {
|
|
40
|
+
transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
41
|
+
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
|
36
42
|
onsessioninitialized: (sessionId) => {
|
|
37
43
|
transports.streamable[sessionId] = transport;
|
|
38
44
|
}
|
|
@@ -43,7 +49,7 @@ app.post('/mcp', async (req, res) => {
|
|
|
43
49
|
delete transports.streamable[transport.sessionId];
|
|
44
50
|
}
|
|
45
51
|
};
|
|
46
|
-
const mcpServer = createMcpServer(req);
|
|
52
|
+
const mcpServer = (0, createMcpServer_js_1.createMcpServer)(req);
|
|
47
53
|
await mcpServer.connect(transport);
|
|
48
54
|
await transport.handleRequest(req, res, req.body);
|
|
49
55
|
return;
|
|
@@ -70,12 +76,12 @@ const handleSessionRequest = async (req, res) => {
|
|
|
70
76
|
app.get('/mcp', handleSessionRequest);
|
|
71
77
|
app.delete('/mcp', handleSessionRequest);
|
|
72
78
|
app.get('/sse', async (req, res) => {
|
|
73
|
-
const transport = new SSEServerTransport('/messages', res);
|
|
79
|
+
const transport = new sse_js_1.SSEServerTransport('/messages', res);
|
|
74
80
|
transports.sse[transport.sessionId] = transport;
|
|
75
81
|
res.on('close', () => {
|
|
76
82
|
delete transports.sse[transport.sessionId];
|
|
77
83
|
});
|
|
78
|
-
const mcpServer = createMcpServer(req);
|
|
84
|
+
const mcpServer = (0, createMcpServer_js_1.createMcpServer)(req);
|
|
79
85
|
await mcpServer.connect(transport);
|
|
80
86
|
});
|
|
81
87
|
app.post('/messages', async (req, res) => {
|
|
@@ -85,13 +91,13 @@ app.post('/messages', async (req, res) => {
|
|
|
85
91
|
res.status(400).send('No transport found for sessionId');
|
|
86
92
|
return;
|
|
87
93
|
}
|
|
88
|
-
if (!(transport instanceof SSEServerTransport)) {
|
|
89
|
-
stopWithWrongTransport(res);
|
|
94
|
+
if (!(transport instanceof sse_js_1.SSEServerTransport)) {
|
|
95
|
+
(0, sendResponse_js_1.stopWithWrongTransport)(res);
|
|
90
96
|
return;
|
|
91
97
|
}
|
|
92
98
|
await transport.handlePostMessage(req, res, req.body);
|
|
93
99
|
});
|
|
94
|
-
let port = parseInt(process.env.APP_PORT
|
|
100
|
+
let port = parseInt((_a = process.env.APP_PORT) !== null && _a !== void 0 ? _a : '', 10);
|
|
95
101
|
if (isNaN(port)) {
|
|
96
102
|
port = DEFAULT_APP_PORT;
|
|
97
103
|
}
|
package/dist/tools/groupTools.js
CHANGED
|
@@ -1,62 +1,67 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = registerGroupTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const toolNames_js_1 = require("../constants/toolNames.js");
|
|
6
|
+
const toolDescriptions_js_1 = require("../constants/toolDescriptions.js");
|
|
7
|
+
const group_js_1 = require("../api/group.js");
|
|
8
|
+
const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
|
|
9
|
+
function registerGroupTools(server) {
|
|
10
|
+
server.tool(toolNames_js_1.ToolNames.LIST_GROUPS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_GROUPS], {
|
|
11
|
+
page: zod_1.z.number().default(1).describe('第几页,从1开始'),
|
|
12
|
+
page_size: zod_1.z.number().default(10).describe('每页多少条数据'),
|
|
13
|
+
search: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库关键字'),
|
|
14
|
+
role: zod_1.z
|
|
15
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['Guest', 'Reporter', 'Developer', 'Master', 'Owner']).optional())
|
|
11
16
|
.describe('最小仓库权限')
|
|
12
17
|
}, async ({ page, page_size, search, role }) => {
|
|
13
18
|
try {
|
|
14
|
-
const groups = await listGroups({ page, page_size, search, role });
|
|
15
|
-
return formatTextToolResult(JSON.stringify(groups, null, 2),
|
|
19
|
+
const groups = await (0, group_js_1.listGroups)({ page, page_size, search, role });
|
|
20
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(groups, null, 2), toolNames_js_1.ToolNames.LIST_GROUPS);
|
|
16
21
|
}
|
|
17
22
|
catch (error) {
|
|
18
|
-
return formatToolError(error,
|
|
23
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_GROUPS);
|
|
19
24
|
}
|
|
20
25
|
});
|
|
21
|
-
server.tool(
|
|
22
|
-
group: z.string().describe('组织名称'),
|
|
23
|
-
page: z.number().default(1).describe('第几页,从1开始'),
|
|
24
|
-
page_size: z.number().default(10).describe('每页多少条数据'),
|
|
25
|
-
access: z.preprocess((val) => (val === null ? undefined : val), z.number().optional()).describe('权限等级')
|
|
26
|
+
server.tool(toolNames_js_1.ToolNames.LIST_SUB_GROUPS, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_SUB_GROUPS], {
|
|
27
|
+
group: zod_1.z.string().describe('组织名称'),
|
|
28
|
+
page: zod_1.z.number().default(1).describe('第几页,从1开始'),
|
|
29
|
+
page_size: zod_1.z.number().default(10).describe('每页多少条数据'),
|
|
30
|
+
access: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.number().optional()).describe('权限等级')
|
|
26
31
|
}, async ({ group, page, page_size, access }) => {
|
|
27
32
|
try {
|
|
28
|
-
const subGroups = await listSubGroups(group, { page, page_size, access });
|
|
29
|
-
return formatTextToolResult(JSON.stringify(subGroups, null, 2),
|
|
33
|
+
const subGroups = await (0, group_js_1.listSubGroups)(group, { page, page_size, access });
|
|
34
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(subGroups, null, 2), toolNames_js_1.ToolNames.LIST_SUB_GROUPS);
|
|
30
35
|
}
|
|
31
36
|
catch (error) {
|
|
32
|
-
return formatToolError(error,
|
|
37
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_SUB_GROUPS);
|
|
33
38
|
}
|
|
34
39
|
});
|
|
35
|
-
server.tool(
|
|
36
|
-
group: z.string().describe('组织路径')
|
|
40
|
+
server.tool(toolNames_js_1.ToolNames.GET_GROUP, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.GET_GROUP], {
|
|
41
|
+
group: zod_1.z.string().describe('组织路径')
|
|
37
42
|
}, async ({ group }) => {
|
|
38
43
|
try {
|
|
39
|
-
const groupInfo = await getGroup(group);
|
|
40
|
-
return formatTextToolResult(JSON.stringify(groupInfo, null, 2),
|
|
44
|
+
const groupInfo = await (0, group_js_1.getGroup)(group);
|
|
45
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(groupInfo, null, 2), toolNames_js_1.ToolNames.GET_GROUP);
|
|
41
46
|
}
|
|
42
47
|
catch (error) {
|
|
43
|
-
return formatToolError(error,
|
|
48
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.GET_GROUP);
|
|
44
49
|
}
|
|
45
50
|
});
|
|
46
|
-
server.tool(
|
|
47
|
-
path: z.string().describe('组织路径'),
|
|
48
|
-
description: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('组织描述'),
|
|
49
|
-
remark: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库备注'),
|
|
50
|
-
bind_domain: z
|
|
51
|
-
.preprocess((val) => (val === null ? undefined : val), z.string().optional())
|
|
51
|
+
server.tool(toolNames_js_1.ToolNames.CREATE_GROUP, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CREATE_GROUP], {
|
|
52
|
+
path: zod_1.z.string().describe('组织路径'),
|
|
53
|
+
description: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('组织描述'),
|
|
54
|
+
remark: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库备注'),
|
|
55
|
+
bind_domain: zod_1.z
|
|
56
|
+
.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
|
|
52
57
|
.describe('根组织绑定的域名')
|
|
53
58
|
}, async ({ path, description, remark, bind_domain }) => {
|
|
54
59
|
try {
|
|
55
|
-
const data = await createGroup({ path, description, remark, bind_domain });
|
|
56
|
-
return formatTextToolResult(JSON.stringify(data, null, 2),
|
|
60
|
+
const data = await (0, group_js_1.createGroup)({ path, description, remark, bind_domain });
|
|
61
|
+
return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.CREATE_GROUP);
|
|
57
62
|
}
|
|
58
63
|
catch (error) {
|
|
59
|
-
return formatToolError(error,
|
|
64
|
+
return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CREATE_GROUP);
|
|
60
65
|
}
|
|
61
66
|
});
|
|
62
67
|
}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerTools = registerTools;
|
|
7
|
+
const client_js_1 = __importDefault(require("../api/client.js"));
|
|
8
|
+
const groupTools_js_1 = __importDefault(require("./groupTools.js"));
|
|
9
|
+
const repoTools_js_1 = __importDefault(require("./repoTools.js"));
|
|
10
|
+
const issueTools_js_1 = __importDefault(require("./issueTools.js"));
|
|
11
|
+
const workspaceTools_js_1 = __importDefault(require("./workspaceTools.js"));
|
|
12
|
+
const pullTools_js_1 = __importDefault(require("./pullTools.js"));
|
|
13
|
+
function registerTools(server, token) {
|
|
14
|
+
client_js_1.default.initialize({
|
|
9
15
|
baseUrl: process.env.API_BASE_URL || 'https://api.cnb.cool',
|
|
10
16
|
token: process.env.API_TOKEN || token || ''
|
|
11
17
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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);
|
|
17
23
|
}
|