postar-pipe-mcp 1.0.1 → 1.0.2

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/server.js CHANGED
@@ -21015,7 +21015,7 @@ function registerGitLab(manager2) {
21015
21015
  manager2.registerConfig("gitlab", {
21016
21016
  name: "gitlab",
21017
21017
  command: "npx",
21018
- args: ["-y", "@structured-world/gitlab-mcp"],
21018
+ args: ["-y", "gitlab-core-mcp"],
21019
21019
  env: {
21020
21020
  GITLAB_API_URL: gitlabUrl,
21021
21021
  GITLAB_TOKEN: gitlabToken
@@ -21057,11 +21057,21 @@ function initMCPClients() {
21057
21057
  }
21058
21058
  const GITLAB_PREFIX = "mcp_gitlab_";
21059
21059
  function getRegisteredServers() {
21060
- const servers = ["gitlab"];
21060
+ const servers = [];
21061
+ if (process.env.GITLAB_TOKEN) {
21062
+ servers.push("gitlab");
21063
+ console.error("[MCP-PIPE][DEBUG] 检测到 GITLAB_TOKEN,添加 gitlab 服务器");
21064
+ } else {
21065
+ console.error("[MCP-PIPE][DEBUG] 未检测到 GITLAB_TOKEN");
21066
+ }
21061
21067
  if (process.env.JENKINS_URL && process.env.JENKINS_USER && process.env.JENKINS_TOKEN) {
21062
21068
  servers.push("jenkins");
21069
+ console.error("[MCP-PIPE][DEBUG] 检测到默认 Jenkins 配置");
21070
+ } else {
21071
+ console.error("[MCP-PIPE][DEBUG] 未检测到默认 Jenkins 配置 (JENKINS_URL/JENKINS_USER/JENKINS_TOKEN)");
21063
21072
  }
21064
21073
  const urlPattern = /^JENKINS_([A-Z0-9_]+)_URL$/;
21074
+ console.error("[MCP-PIPE][DEBUG] 开始检测命名 Jenkins 实例...");
21065
21075
  for (const key of Object.keys(process.env)) {
21066
21076
  const match = key.match(urlPattern);
21067
21077
  if (!match) continue;
@@ -21070,11 +21080,14 @@ function getRegisteredServers() {
21070
21080
  const tokenKey = `JENKINS_${suffix}_TOKEN`;
21071
21081
  const user = process.env[userKey];
21072
21082
  const token = process.env[tokenKey];
21083
+ console.error(`[MCP-PIPE][DEBUG] 检查 ${key} -> suffix=${suffix}, user=${!!user}, token=${!!token}`);
21073
21084
  if (user && token) {
21074
21085
  const instanceName = `jenkins-${suffix.toLowerCase().replace(/_/g, "-")}`;
21075
21086
  servers.push(instanceName);
21087
+ console.error(`[MCP-PIPE][DEBUG] ✅ 添加命名 Jenkins 实例: ${instanceName}`);
21076
21088
  }
21077
21089
  }
21090
+ console.error(`[MCP-PIPE][DEBUG] 最终注册的服务器列表: ${servers.join(", ") || "(空)"}`);
21078
21091
  return servers;
21079
21092
  }
21080
21093
  function getToolPrefix(serverName) {
@@ -21097,41 +21110,45 @@ async function getProxiedTools() {
21097
21110
  const jenkinsServers = servers.filter((s) => s.startsWith("jenkins") && s !== "jenkins");
21098
21111
  const mainJenkins = servers.includes("jenkins") ? "jenkins" : null;
21099
21112
  const otherServers = servers.filter((s) => !s.startsWith("jenkins"));
21100
- if (mainJenkins) {
21101
- const prefix = getToolPrefix(mainJenkins);
21102
- try {
21103
- const tools = await manager2.listTools(mainJenkins);
21104
- for (const tool of tools.tools || []) {
21105
- const proxiedToolName = `${prefix}${tool.name}`;
21113
+ const allJenkinsServers = mainJenkins ? [mainJenkins, ...jenkinsServers] : jenkinsServers;
21114
+ let isFirstJenkins = true;
21115
+ for (const serverName of allJenkinsServers) {
21116
+ const prefix = getToolPrefix(serverName);
21117
+ if (isFirstJenkins) {
21118
+ try {
21119
+ const tools = await manager2.listTools(serverName);
21120
+ for (const tool of tools.tools || []) {
21121
+ const proxiedToolName = `${prefix}${tool.name}`;
21122
+ const proxiedTool = {
21123
+ ...tool,
21124
+ name: proxiedToolName,
21125
+ description: `[${serverName}] ${tool.description || ""}`
21126
+ };
21127
+ allTools.push(proxiedTool);
21128
+ toolSchemaCache.set(proxiedToolName, tool.inputSchema);
21129
+ }
21130
+ console.error(`[MCP-PIPE] 已从 ${serverName} 获取 ${tools.tools?.length || 0} 个工具`);
21131
+ isFirstJenkins = false;
21132
+ } catch (error2) {
21133
+ console.error(`[MCP-PIPE] 无法从 ${serverName} 获取工具列表:`, error2);
21134
+ continue;
21135
+ }
21136
+ } else {
21137
+ const sourcePrefix = mainJenkins ? getToolPrefix(mainJenkins) : getToolPrefix(allJenkinsServers[0]);
21138
+ const jenkinsTools = allTools.filter((t) => t.name.startsWith(sourcePrefix));
21139
+ for (const tool of jenkinsTools) {
21140
+ const originalToolName = tool.name.slice(sourcePrefix.length);
21141
+ const proxiedToolName = `${prefix}${originalToolName}`;
21106
21142
  const proxiedTool = {
21107
21143
  ...tool,
21108
21144
  name: proxiedToolName,
21109
- description: `[${mainJenkins}] ${tool.description || ""}`
21145
+ description: `[${serverName}] ${tool.description || ""}`
21110
21146
  };
21111
21147
  allTools.push(proxiedTool);
21112
21148
  toolSchemaCache.set(proxiedToolName, tool.inputSchema);
21113
21149
  }
21114
- console.error(`[MCP-PIPE] 已代理 ${mainJenkins} ${tools.tools?.length || 0} 个工具`);
21115
- } catch (error2) {
21116
- console.error(`[MCP-PIPE] 无法获取 ${mainJenkins} 的工具列表:`, error2);
21117
- }
21118
- }
21119
- for (const serverName of jenkinsServers) {
21120
- const prefix = getToolPrefix(serverName);
21121
- const sourcePrefix = mainJenkins ? getToolPrefix(mainJenkins) : prefix;
21122
- const jenkinsTools = allTools.filter((t) => t.name.startsWith(sourcePrefix));
21123
- for (const tool of jenkinsTools) {
21124
- const originalToolName = tool.name.slice(sourcePrefix.length);
21125
- const proxiedToolName = `${prefix}${originalToolName}`;
21126
- const proxiedTool = {
21127
- ...tool,
21128
- name: proxiedToolName,
21129
- description: `[${serverName}] ${tool.description || ""}`
21130
- };
21131
- allTools.push(proxiedTool);
21132
- toolSchemaCache.set(proxiedToolName, tool.inputSchema);
21150
+ console.error(`[MCP-PIPE] 已为 ${serverName} 生成 ${jenkinsTools.length} 个工具别名`);
21133
21151
  }
21134
- console.error(`[MCP-PIPE] 已为 ${serverName} 生成 ${jenkinsTools.length} 个工具别名`);
21135
21152
  }
21136
21153
  for (const serverName of otherServers) {
21137
21154
  const prefix = getToolPrefix(serverName);
@@ -117,9 +117,20 @@ version: 1.0.1
117
117
  - Jenkins 将使用所有参数的默认值进行构建
118
118
 
119
119
  2. **若 `config.yaml` 中配置了 `params`**:
120
- - 遍历 `jenkins.{ENV}.params` 中的每个参数
121
- - **参数值已填写**(非空字符串、非空数组):直接使用该值
122
- - **参数值为空字符串 `""` 或空数组 `[]`**:进入交互流程,让用户选择
120
+ - 遍历 `jenkins.{ENV}.params` 中的每个参数,根据参数值类型处理:
121
+
122
+ **参数值为数组**(如 `['test', 'pre']`):
123
+ - → **使用同一个 Jenkins Job,依次部署多次**
124
+ - 第 1 次: 传递 `{参数名: 'test'}`
125
+ - 第 2 次: 传递 `{参数名: 'pre'}`
126
+ - 示例: `ENV: ['test', 'pre']` → 第1次传 `{ENV: 'test'}`,第2次传 `{ENV: 'pre'}`
127
+
128
+ **参数值为字符串**(如 `'test'`):
129
+ - → **部署一次,传递该值**
130
+ - 示例: `ENV: 'test'` → 传递 `{ENV: 'test'}`
131
+
132
+ **参数值为空**(空字符串 `''`、空数组 `[]`、空对象 `{}`):
133
+ - → 进入交互流程,让用户选择
123
134
 
124
135
  > **交互执行原则、选项获取优先级、占位符替换等详细逻辑**,请参考 `steps.yaml` 中的 `step: 2`
125
136
 
@@ -230,15 +230,36 @@ steps:
230
230
  - condition: "config.yaml 中未配置 params 或 params 为空对象 {}"
231
231
  action: "使用 buildWithParameters 模式触发构建,传递空对象 {}"
232
232
  result: "Jenkins 将使用所有参数的默认值进行构建"
233
+ note: "✅ 未配置任何参数时,直接使用 Jenkins 默认值"
233
234
 
234
235
  - condition: "config.yaml 中配置了 params"
235
236
  action: "遍历 jenkins.{ENV}.params 中的每个参数"
236
237
  sub_rules:
237
- - condition: "参数值已填写(非空字符串、非空数组)"
238
- action: "直接使用该值"
238
+ - condition: "参数值已填写(非空字符串、非空数组、非空对象)"
239
+ action: "根据参数值类型处理"
240
+ value_types:
241
+ - type: "数组(如 ['test', 'pre'])"
242
+ action: "使用同一个 Jenkins Job,依次部署多次,每次传递数组中的一个值"
243
+ example: |
244
+ ENV: ['test', 'pre'] →
245
+ 第 1 次部署: 调用 Jenkins Job,传递 {ENV: 'test'}
246
+ 第 2 次部署: 调用 Jenkins Job,传递 {ENV: 'pre'}
247
+
248
+ 任何参数的数组都这样处理:
249
+ DEPLOY_ENV: ['dev', 'test', 'prod'] → 部署 3 次
250
+ note: "数组表示对同一个 Job 进行多次部署,每次使用数组中的一个值"
251
+
252
+ - type: "字符串(如 'test')"
253
+ action: "部署一次,传递该值"
254
+ example: "ENV: 'test' → 调用 Jenkins Job,传递 {ENV: 'test'}"
255
+
256
+ - type: "其他类型(数字、对象等)"
257
+ action: "直接作为 Jenkins 构建参数传递"
258
+ example: "BUILD_NAME: 'build:dev' → 传递 {BUILD_NAME: 'build:dev'}"
239
259
 
240
- - condition: "参数值为空字符串或空数组"
260
+ - condition: "参数值为空字符串 '' 或空数组 [] 或空对象 {}"
241
261
  action: "进入交互流程,让用户选择"
262
+ note: "只有参数值为空时才询问用户"
242
263
 
243
264
  interaction_rules:
244
265
  - "全面暂停:一旦检测到任何需要交互的参数,立即暂停所有后续执行流程"
@@ -277,16 +298,65 @@ steps:
277
298
  execution_mode: "顺序执行,严禁并行"
278
299
 
279
300
  multi_env_flow: |
280
- 环境1交互(如需要) 部署 → 完成
281
-
282
- 环境2 → 交互(如需要) → 部署 → 完成
283
-
284
- 环境3 → 交互(如需要) → 部署 → 完成
301
+ 检查params配置有值直接部署 / 空值才交互 → 完成
302
+
303
+ multi_env_example: |
304
+ 场景A: config.yaml 中某参数为数组
305
+ jenkins:
306
+ 'dev':
307
+ fullname: "dev-platforms-advertiser"
308
+ params:
309
+ ENV: ['test', 'pre']
310
+ BUILD_NAME: "build:dev"
311
+
312
+ 执行流程:
313
+ → 读取 params.ENV = ['test', 'pre'] (数组)
314
+ → 使用同一个 Jenkins Job (dev-platforms-advertiser) 依次部署:
315
+ 第 1 次: 传递参数 {ENV: 'test', BUILD_NAME: 'build:dev'}
316
+ 第 2 次: 传递参数 {ENV: 'pre', BUILD_NAME: 'build:dev'}
317
+ → 不询问用户,直接依次部署
318
+
319
+ 场景B: config.yaml 中某参数为字符串
320
+ jenkins:
321
+ 'dev':
322
+ fullname: "dev-platforms-advertiser"
323
+ params:
324
+ ENV: 'test'
325
+
326
+ 执行流程:
327
+ → 读取 params.ENV = 'test' (字符串)
328
+ → 使用 Jenkins Job (dev-platforms-advertiser) 部署一次
329
+ → 传递参数 {ENV: 'test'}
330
+ → 不询问用户,直接部署
331
+
332
+ 场景C: config.yaml 中 ENV 参数为空
333
+ jenkins:
334
+ 'dev':
335
+ fullname: "dev-platforms-advertiser"
336
+ params:
337
+ ENV: []
338
+
339
+ 执行流程:
340
+ → 读取 params.ENV = [] (空数组)
341
+ → 进入交互流程,询问用户选择部署环境
342
+ → 等待用户选择后继续
343
+ → 触发构建
344
+
345
+ 场景D: config.yaml 中未配置 params
346
+ jenkins:
347
+ 'dev':
348
+ fullname: "dev-platforms-advertiser"
349
+
350
+ 执行流程:
351
+ → 未配置 params
352
+ → 使用 buildWithParameters + {} 触发构建
353
+ → Jenkins 使用所有参数默认值
354
+ → 部署完成
285
355
 
286
356
  rules:
287
- - "逐个遍历环境:一次只处理一个环境,严禁一次性收集所有环境的交互参数"
288
- - "只有当前环境部署完成后,才能继续下一个环境"
289
- - "各环境独立:比如 test 环境未配置 params 时,应直接使用 Jenkins 默认值"
357
+ - "参数有值直接部署:只要 config.yaml 中 params 的参数值非空,直接传递给 Jenkins,不询问"
358
+ - "参数为空才询问:只有参数值为空字符串、空数组或空对象时,才进入交互流程"
359
+ - "未配置params时:使用 buildWithParameters + {} 触发,Jenkins 使用默认值"
290
360
 
291
361
  single_env_steps:
292
362
  - step: 3.1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postar-pipe-mcp",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Unified CI/CD MCP Server - orchestrates GitLab and Jenkins MCPs with dynamic skills",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",