@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.
@@ -1,53 +1,65 @@
1
- import { z } from 'zod';
2
- import { createRepository, getRepository, listGroupRepositories, listRepositories } from '../api/repository.js';
3
- import { getUser } from '../api/user.js';
4
- import { formatTextToolResult, formatToolError } from '../helpers/formatToolResult.js';
5
- export default function registerRepoTools(server) {
6
- server.tool('list-repositories', '获取当前用户拥有指定权限及其以上权限的仓库', {
7
- page: z.number().default(1).describe('第几页,从1开始,默认值是1'),
8
- page_size: z.number().default(10).describe('每页多少条数据,默认值为10'),
9
- search: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('查询关键字'),
10
- filter_type: z
11
- .preprocess((val) => (val === null ? undefined : val), z.enum(['private', 'public', 'encrypted']).optional())
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = registerRepoTools;
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 repository_js_1 = require("../api/repository.js");
8
+ const user_js_1 = require("../api/user.js");
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");
12
+ function registerRepoTools(server) {
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`命令获取,获取不到传空字符串'),
15
+ page: zod_1.z.number().default(1).describe('第几页,从1开始,默认值是1'),
16
+ page_size: zod_1.z.number().default(10).describe('每页多少条数据,默认值为10'),
17
+ search: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('查询关键字'),
18
+ filter_type: zod_1.z
19
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['private', 'public', 'encrypted']).optional())
12
20
  .describe('仓库类型,为空表示所有仓库类型,默认值为空'),
13
- role: z
14
- .preprocess((val) => (val === null ? undefined : val), z.enum(['Reporter', 'Developer', 'Master', 'Owner']).optional())
21
+ role: zod_1.z
22
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['Reporter', 'Developer', 'Master', 'Owner']).optional())
15
23
  .describe('最小仓库权限,当用户未指定角色时,需要主动传入Reporter'),
16
- order_by: z
17
- .preprocess((val) => (val === null ? undefined : val), z.enum(['created_at', 'last_updated_at', 'stars']).optional())
24
+ order_by: zod_1.z
25
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['created_at', 'last_updated_at', 'stars']).optional())
18
26
  .describe('排序类型,默认值是last_updated_at'),
19
- desc: z
20
- .preprocess((val) => (val === null ? undefined : val), z.boolean().optional())
27
+ desc: zod_1.z
28
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.boolean().optional())
21
29
  .describe('是否开启倒叙排序,默认值是false')
22
- }, 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
+ }
23
35
  try {
24
- const repos = await listRepositories({ page, page_size, search, filter_type, role, order_by, desc });
25
- return formatTextToolResult(JSON.stringify(repos, null, 2), 'list-repositories');
36
+ const repos = await (0, repository_js_1.listRepositories)({ page, page_size, search, filter_type, role, order_by, desc });
37
+ return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repos, null, 2), toolNames_js_1.ToolNames.LIST_REPOSITORIES);
26
38
  }
27
39
  catch (error) {
28
- return formatToolError(error, 'list-repositories');
40
+ return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_REPOSITORIES);
29
41
  }
30
42
  });
31
- server.tool('list-group-repositories', '获取分组里当前用户有权限的仓库', {
32
- group: z.string().describe('组织名称'),
33
- page: z.number().default(1).describe('第几页,从1开始,默认值是1'),
34
- page_size: z.number().default(10).describe('每页多少条数据,默认值为10'),
35
- search: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库关键字'),
36
- filter_type: z
37
- .preprocess((val) => (val === null ? undefined : val), z.enum(['private', 'public', 'encrypted']).optional())
43
+ server.tool(toolNames_js_1.ToolNames.LIST_GROUP_REPOSITORIES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_GROUP_REPOSITORIES], {
44
+ group: zod_1.z.string().describe('组织名称'),
45
+ page: zod_1.z.number().default(1).describe('第几页,从1开始,默认值是1'),
46
+ page_size: zod_1.z.number().default(10).describe('每页多少条数据,默认值为10'),
47
+ search: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库关键字'),
48
+ filter_type: zod_1.z
49
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['private', 'public', 'encrypted']).optional())
38
50
  .describe('仓库类型'),
39
- descendant: z
40
- .preprocess((val) => (val === null ? undefined : val), z.enum(['all', 'sub', 'grand']).optional())
51
+ descendant: zod_1.z
52
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['all', 'sub', 'grand']).optional())
41
53
  .describe('查全部、直接属于当前组织的仓库、子组织的仓库'),
42
- order_by: z
43
- .preprocess((val) => (val === null ? undefined : val), z.enum(['created_at', 'last_updated_at', 'stars', 'slug_path']).optional())
54
+ order_by: zod_1.z
55
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['created_at', 'last_updated_at', 'stars', 'slug_path']).optional())
44
56
  .describe('排序类型'),
45
- desc: z
46
- .preprocess((val) => (val === null ? undefined : val), z.boolean().optional())
57
+ desc: zod_1.z
58
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.boolean().optional())
47
59
  .describe('是否开启倒叙排序,默认值是false')
48
60
  }, async ({ group, page, page_size, search, filter_type, descendant, order_by, desc }) => {
49
61
  try {
50
- const repos = await listGroupRepositories(group, {
62
+ const repos = await (0, repository_js_1.listGroupRepositories)(group, {
51
63
  page,
52
64
  page_size,
53
65
  search,
@@ -56,73 +68,59 @@ export default function registerRepoTools(server) {
56
68
  order_by,
57
69
  desc
58
70
  });
59
- return formatTextToolResult(JSON.stringify(repos, null, 2), 'list-group-repositories');
71
+ return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repos, null, 2), toolNames_js_1.ToolNames.LIST_GROUP_REPOSITORIES);
60
72
  }
61
73
  catch (error) {
62
- return formatToolError(error, 'list-group-repositories');
74
+ return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_GROUP_REPOSITORIES);
63
75
  }
64
76
  });
65
- server.tool('get-repository', '获取指定仓库信息', {
66
- repo: z.string().describe('仓库路径')
77
+ server.tool(toolNames_js_1.ToolNames.GET_REPOSITORY, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.GET_REPOSITORY], {
78
+ repo: zod_1.z.string().describe('仓库路径')
67
79
  }, async ({ repo }) => {
68
80
  try {
69
- const repoInfo = await getRepository(repo);
70
- return formatTextToolResult(JSON.stringify(repoInfo, null, 2), 'get-repository');
81
+ const repoInfo = await (0, repository_js_1.getRepository)(repo);
82
+ return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(repoInfo, null, 2), toolNames_js_1.ToolNames.GET_REPOSITORY);
71
83
  }
72
84
  catch (error) {
73
- return formatToolError(error, 'get-repository');
85
+ return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.GET_REPOSITORY);
74
86
  }
75
87
  });
76
- server.tool('create-repository', '创建仓库', {
77
- group: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库所属分组'),
78
- name: z.string().describe('仓库名称'),
79
- description: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库描述'),
80
- license: z.preprocess((val) => (val === null ? undefined : val), z.string().optional()).describe('仓库许可'),
81
- visibility: z
82
- .preprocess((val) => (val === null ? undefined : val), z.enum(['public', 'private', 'secret']).default('public'))
88
+ server.tool(toolNames_js_1.ToolNames.CREATE_REPOSITORY, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.CREATE_REPOSITORY], {
89
+ group: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库所属分组'),
90
+ name: zod_1.z.string().describe('仓库名称'),
91
+ description: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库描述'),
92
+ license: zod_1.z.preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional()).describe('仓库许可'),
93
+ visibility: zod_1.z
94
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['public', 'private', 'secret']).default('public'))
83
95
  .describe('仓库可见性')
84
96
  }, async ({ group, name, description, license, visibility }) => {
85
97
  let repoGroup = group;
86
98
  if (!repoGroup) {
87
- const { username = '' } = await getUser();
99
+ const { username = '' } = await (0, user_js_1.getUser)();
88
100
  repoGroup = username;
89
101
  }
90
102
  try {
91
- const data = await createRepository(repoGroup, { name, description, license, visibility });
92
- return formatTextToolResult(JSON.stringify(data, null, 2), 'create-repository');
103
+ const data = await (0, repository_js_1.createRepository)(repoGroup, { name, description, license, visibility });
104
+ return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.CREATE_REPOSITORY);
93
105
  }
94
106
  catch (error) {
95
- return formatToolError(error, 'create-repository');
107
+ return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.CREATE_REPOSITORY);
96
108
  }
97
109
  });
98
- server.tool('get-current-repo', '获取当前仓库对应的CNB仓库信息', {
99
- remote_url: z.string().describe('远程仓库URL, 需要先执行`git remote get-url origin`命令获取')
110
+ server.tool(toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY], {
111
+ remote_url: zod_1.z.string().describe('远程仓库URL, 需要先执行`git remote get-url origin`命令获取')
100
112
  }, async ({ remote_url }) => {
101
113
  try {
102
- let repoPath = '';
103
- if (remote_url.startsWith('git@')) {
104
- // SSH 格式: git@example.com:group/repo.git
105
- const match = remote_url.match(/git@[^:]+:(.+?)(?:\.git)?$/);
106
- if (match) {
107
- repoPath = match[1];
108
- }
109
- }
110
- else if (remote_url.startsWith('http')) {
111
- // HTTPS 格式: https://example.com/group/repo.git
112
- const match = remote_url.match(/https?:\/\/[^/]+\/(.+?)(?:\.git)?$/);
113
- if (match) {
114
- repoPath = match[1];
115
- }
116
- }
114
+ const repoPath = (0, formatRepoUrl_js_1.getRepoPath)(remote_url);
117
115
  if (!repoPath) {
118
- return formatToolError(`无法从远程仓库URL解析出仓库路径: ${remote_url}`, 'get-current-repo');
116
+ return (0, formatToolResult_js_1.formatToolError)(`无法从远程仓库URL解析出仓库路径: ${remote_url}`, toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY);
119
117
  }
120
118
  // 获取仓库信息
121
- const data = await getRepository(repoPath);
122
- return formatTextToolResult(JSON.stringify(data, null, 2), 'get-current-repo');
119
+ const data = await (0, repository_js_1.getRepository)(repoPath);
120
+ return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(data, null, 2), toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY);
123
121
  }
124
122
  catch (error) {
125
- return formatToolError(error, 'get-current-repo');
123
+ return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.GET_CURRENT_REPOSITORY);
126
124
  }
127
125
  });
128
126
  }
@@ -1,32 +1,37 @@
1
- import { z } from 'zod';
2
- import { deleteWorkspace, listWorkspace } from '../api/workspace.js';
3
- import { formatTextToolResult, formatToolError } from '../helpers/formatToolResult.js';
4
- export default function registerWorkspaceTools(server) {
5
- server.tool('list-workspace', '获取我的云原生开发环境列表', {
6
- branch: z
7
- .preprocess((val) => (val === null ? undefined : val), z.string().optional())
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = registerWorkspaceTools;
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 workspace_js_1 = require("../api/workspace.js");
8
+ const formatToolResult_js_1 = require("../helpers/formatToolResult.js");
9
+ function registerWorkspaceTools(server) {
10
+ server.tool(toolNames_js_1.ToolNames.LIST_WORKSPACES, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.LIST_WORKSPACES], {
11
+ branch: zod_1.z
12
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
8
13
  .describe('分支名,例如:main'),
9
- start: z
10
- .preprocess((val) => (val === null ? undefined : val), z.string().optional())
14
+ start: zod_1.z
15
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
11
16
  .describe('查询结束时间,格式:YYYY-MM-DD HH:mm:ssZZ,例如:2024-12-01 00:00:00+0800'),
12
- end: z
13
- .preprocess((val) => (val === null ? undefined : val), z.string().optional())
17
+ end: zod_1.z
18
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
14
19
  .describe('查询开始时间,格式:YYYY-MM-DD HH:mm:ssZZ,例如:2024-12-01 00:00:00+0800'),
15
- page: z
16
- .preprocess((val) => (val === null ? undefined : val), z.number().optional())
20
+ page: zod_1.z
21
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.number().optional())
17
22
  .describe('分页页码,从 1 开始,默认为 1'),
18
- page_size: z
19
- .preprocess((val) => (val === null ? undefined : val), z.number().optional())
23
+ page_size: zod_1.z
24
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.number().optional())
20
25
  .describe('每页条数,默认为 20,最高 100'),
21
- slug: z
22
- .preprocess((val) => (val === null ? undefined : val), z.string().optional())
26
+ slug: zod_1.z
27
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.string().optional())
23
28
  .describe('仓库路径,例如:groupname/reponame'),
24
- status: z
25
- .preprocess((val) => (val === null ? undefined : val), z.enum(['running', 'closed']).optional())
29
+ status: zod_1.z
30
+ .preprocess((val) => (val === null ? undefined : val), zod_1.z.enum(['running', 'closed']).optional())
26
31
  .describe('开发环境状态,running: 开发环境已启动,closed:开发环境已关闭,默认为所有状态')
27
32
  }, async ({ branch, page, page_size, start, end, slug, status }) => {
28
33
  try {
29
- const workspaces = await listWorkspace({
34
+ const workspaces = await (0, workspace_js_1.listWorkspace)({
30
35
  branch,
31
36
  page,
32
37
  pageSize: page_size,
@@ -35,23 +40,23 @@ export default function registerWorkspaceTools(server) {
35
40
  slug,
36
41
  status
37
42
  });
38
- return formatTextToolResult(JSON.stringify(workspaces, null, 2), 'list-workspace');
43
+ return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(workspaces, null, 2), toolNames_js_1.ToolNames.LIST_WORKSPACES);
39
44
  }
40
45
  catch (error) {
41
- return formatToolError(error, 'list-workspace');
46
+ return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.LIST_WORKSPACES);
42
47
  }
43
48
  });
44
- server.tool('delete-workspace', '删除我的云原生开发环境', {
45
- pipelineId: z.string().describe('开发环境 ID')
49
+ server.tool(toolNames_js_1.ToolNames.DELETE_WORKSPACE, toolDescriptions_js_1.toolDescriptions[toolNames_js_1.ToolNames.DELETE_WORKSPACE], {
50
+ pipelineId: zod_1.z.string().describe('开发环境 ID')
46
51
  }, async ({ pipelineId }) => {
47
52
  try {
48
- const result = await deleteWorkspace({
53
+ const result = await (0, workspace_js_1.deleteWorkspace)({
49
54
  pipelineId
50
55
  });
51
- return formatTextToolResult(JSON.stringify(result, null, 2), 'delete-workspace');
56
+ return (0, formatToolResult_js_1.formatTextToolResult)(JSON.stringify(result, null, 2), toolNames_js_1.ToolNames.DELETE_WORKSPACE);
52
57
  }
53
58
  catch (error) {
54
- return formatToolError(error, 'delete-workspace');
59
+ return (0, formatToolResult_js_1.formatToolError)(error, toolNames_js_1.ToolNames.DELETE_WORKSPACE);
55
60
  }
56
61
  });
57
62
  }
package/package.json CHANGED
@@ -1,13 +1,12 @@
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.2",
4
+ "version": "0.4.4",
5
5
  "main": "./dist/stdio.js",
6
6
  "bin": {
7
7
  "cnb-mcp-stdio": "dist/stdio.js",
8
8
  "cnb-mcp-streamable": "dist/streamable.js"
9
9
  },
10
- "type": "module",
11
10
  "scripts": {
12
11
  "build": "tsc",
13
12
  "watch": "tsc --watch",
@@ -47,21 +46,21 @@
47
46
  "zod": "3.24.3"
48
47
  },
49
48
  "devDependencies": {
50
- "@commitlint/cli": "19.8.0",
51
- "@commitlint/config-conventional": "19.8.0",
52
- "@eslint/js": "9.24.0",
53
- "@modelcontextprotocol/inspector": "^0.11.0",
49
+ "@commitlint/cli": "19.8.1",
50
+ "@commitlint/config-conventional": "19.8.1",
51
+ "@eslint/js": "9.33.0",
52
+ "@modelcontextprotocol/inspector": "^0.16.2",
54
53
  "@types/express": "5.0.1",
55
- "@types/node": "22.13.9",
56
- "eslint": "9.24.0",
57
- "eslint-config-prettier": "10.1.2",
58
- "eslint-plugin-prettier": "5.2.6",
59
- "globals": "16.0.0",
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",
60
59
  "husky": "9.1.7",
61
- "lint-staged": "15.5.1",
62
- "prettier": "3.5.3",
63
- "typescript": "5.8.2",
64
- "typescript-eslint": "8.30.1"
60
+ "lint-staged": "15.5.2",
61
+ "prettier": "3.6.2",
62
+ "typescript": "5.9.2",
63
+ "typescript-eslint": "8.40.0"
65
64
  },
66
65
  "lint-staged": {
67
66
  "**/*": [