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 +46 -29
- package/dist/skills/cd/SKILL.md +14 -3
- package/dist/skills/cd/steps.yaml +81 -11
- package/package.json +1 -1
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", "
|
|
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 = [
|
|
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
|
-
|
|
21101
|
-
|
|
21102
|
-
|
|
21103
|
-
|
|
21104
|
-
|
|
21105
|
-
|
|
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: `[${
|
|
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]
|
|
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);
|
package/dist/skills/cd/SKILL.md
CHANGED
|
@@ -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
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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
|
-
- "
|
|
357
|
+
- "参数有值直接部署:只要 config.yaml 中 params 的参数值非空,直接传递给 Jenkins,不询问"
|
|
358
|
+
- "参数为空才询问:只有参数值为空字符串、空数组或空对象时,才进入交互流程"
|
|
359
|
+
- "未配置params时:使用 buildWithParameters + {} 触发,Jenkins 使用默认值"
|
|
290
360
|
|
|
291
361
|
single_env_steps:
|
|
292
362
|
- step: 3.1
|