agent2agent-cli 0.3.2 → 0.3.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/a2a-mcp.js +23 -7
- package/a2a.js +61 -10
- package/package.json +1 -1
package/a2a-mcp.js
CHANGED
|
@@ -24,7 +24,7 @@ const fs = require('fs');
|
|
|
24
24
|
const path = require('path');
|
|
25
25
|
const readline = require('readline');
|
|
26
26
|
|
|
27
|
-
const VERSION = '0.3.
|
|
27
|
+
const VERSION = '0.3.4';
|
|
28
28
|
const PROTOCOL_VERSION = '2024-11-05'; // MCP 当前稳定协议版本
|
|
29
29
|
|
|
30
30
|
/* ------------------------------------------------------------------ *
|
|
@@ -357,12 +357,19 @@ async function apiText(config, pathName) {
|
|
|
357
357
|
/* ------------------------------------------------------------------ *
|
|
358
358
|
* MCP stdio 传输(换行分隔 JSON-RPC 2.0)
|
|
359
359
|
* ------------------------------------------------------------------ */
|
|
360
|
+
// 兼容的 MCP 协议版本(Cursor 可能请求较新版本,回显客户端请求值)
|
|
361
|
+
const KNOWN_PROTOCOLS = ['2024-11-05', '2025-03-26', '2025-06-18'];
|
|
362
|
+
|
|
360
363
|
function main() {
|
|
364
|
+
// 找不到配置不再退出:server 照常启动(tools 可用),调用工具时才给出明确指引
|
|
361
365
|
const config = resolveConfig();
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
console.error(
|
|
365
|
-
|
|
366
|
+
const cfgMissing = !config.url;
|
|
367
|
+
if (cfgMissing) {
|
|
368
|
+
console.error(`[a2a-mcp v${VERSION}] 当前工作目录: ${process.cwd()}`);
|
|
369
|
+
console.error('[a2a-mcp] 未找到平台配置(.a2a.json):请在含 .a2a.json 的项目目录使用;');
|
|
370
|
+
console.error('[a2a-mcp] 或设置 A2A_URL / A2A_TOKEN / A2A_ACCOUNT 环境变量;首次接入:a2a init');
|
|
371
|
+
} else {
|
|
372
|
+
console.error(`[a2a-mcp v${VERSION}] 已加载配置: ${config.url}(账号: ${config.accountId || '?'})`);
|
|
366
373
|
}
|
|
367
374
|
|
|
368
375
|
const rl = readline.createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
@@ -397,14 +404,18 @@ function main() {
|
|
|
397
404
|
err && err.message ? err.message : String(err));
|
|
398
405
|
|
|
399
406
|
switch (method) {
|
|
400
|
-
case 'initialize':
|
|
407
|
+
case 'initialize': {
|
|
401
408
|
serverReady = true;
|
|
409
|
+
// 协议版本协商:回显客户端请求的已知版本,避免较新客户端不兼容
|
|
410
|
+
const reqVer = params && params.protocolVersion;
|
|
411
|
+
const ver = KNOWN_PROTOCOLS.includes(reqVer) ? reqVer : PROTOCOL_VERSION;
|
|
402
412
|
finish({
|
|
403
|
-
protocolVersion:
|
|
413
|
+
protocolVersion: ver,
|
|
404
414
|
capabilities: { tools: { listChanged: false } },
|
|
405
415
|
serverInfo: { name: 'a2a-mcp', version: VERSION },
|
|
406
416
|
});
|
|
407
417
|
break;
|
|
418
|
+
}
|
|
408
419
|
case 'ping':
|
|
409
420
|
finish({});
|
|
410
421
|
break;
|
|
@@ -413,6 +424,11 @@ function main() {
|
|
|
413
424
|
break;
|
|
414
425
|
case 'tools/call': {
|
|
415
426
|
const { name, arguments: args } = params || {};
|
|
427
|
+
if (cfgMissing) {
|
|
428
|
+
const errText = '平台未配置:请在含 .a2a.json 的项目目录使用本 MCP(Cursor 的项目级 .cursor/mcp.json 会把工作目录设为项目根),或设置 A2A_URL/A2A_TOKEN/A2A_ACCOUNT 环境变量。首次接入运行 a2a init。';
|
|
429
|
+
finish({ isError: true, content: [{ type: 'text', text: errText }] });
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
416
432
|
callTool(config, name, args || {})
|
|
417
433
|
.then((result) => {
|
|
418
434
|
const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
package/a2a.js
CHANGED
|
@@ -805,6 +805,7 @@ async function cmdUpdateSkills(opts) {
|
|
|
805
805
|
/** `a2a update`:一键更新 CLI + Skills(平台由运维执行 docker 命令) */
|
|
806
806
|
async function cmdUpdate(opts) {
|
|
807
807
|
console.log(hl('===== a2a update ====='));
|
|
808
|
+
let updated = false;
|
|
808
809
|
if (VERSION) {
|
|
809
810
|
// 先检查 CLI 版本
|
|
810
811
|
const pkg = await fetchJson('https://registry.npmjs.org/' + NPM_PACKAGE + '/latest');
|
|
@@ -813,6 +814,7 @@ async function cmdUpdate(opts) {
|
|
|
813
814
|
try {
|
|
814
815
|
execSync(`npm install -g ${NPM_PACKAGE}@latest`, { stdio: 'inherit' });
|
|
815
816
|
console.log(paint(C.green, '[CLI] 更新完成 ✅'));
|
|
817
|
+
updated = true;
|
|
816
818
|
} catch (e) {
|
|
817
819
|
console.log(paint(C.red, `[CLI] 更新失败,请手动:npm install -g ${NPM_PACKAGE}@latest`));
|
|
818
820
|
}
|
|
@@ -822,9 +824,15 @@ async function cmdUpdate(opts) {
|
|
|
822
824
|
} else {
|
|
823
825
|
console.log(paint(C.yellow, '[CLI] 单文件安装无版本信息,建议:npm install -g ' + NPM_PACKAGE));
|
|
824
826
|
}
|
|
827
|
+
if (updated) {
|
|
828
|
+
// 本进程仍是旧代码:让用户退出后重跑,以用新版本完成其余更新
|
|
829
|
+
const pkg2 = await fetchJson('https://registry.npmjs.org/' + NPM_PACKAGE + '/latest').catch(() => null);
|
|
830
|
+
console.log(paint(C.yellow, 'CLI 已更新到 v' + (pkg2 ? pkg2.version : '最新') + '。请退出后重新运行 a2a update(或直接运行 a2a update-skills)完成 skills 更新。'));
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
825
833
|
await cmdUpdateSkills({ yes: opts.yes || opts.y });
|
|
826
834
|
console.log('');
|
|
827
|
-
console.log('平台更新(在部署服务器执行):cd <仓库> && git pull && docker compose up -d --build');
|
|
835
|
+
console.log('平台更新(在部署服务器执行):cd <仓库> && git pull && docker compose up -d --build(或 docker compose -f docker-compose.pull.yml up -d)');
|
|
828
836
|
}
|
|
829
837
|
|
|
830
838
|
/* ------------------------------------------------------------------------- *
|
|
@@ -1363,6 +1371,29 @@ async function cmdHeartbeat(opts, ctx) {
|
|
|
1363
1371
|
);
|
|
1364
1372
|
}
|
|
1365
1373
|
|
|
1374
|
+
/** `a2a mcp-setup`:在当前项目生成 .cursor/mcp.json(Cursor/Windsurf 用),使用绝对路径免 PATH 问题 */
|
|
1375
|
+
async function cmdMcpSetup() {
|
|
1376
|
+
const nodePath = process.execPath; // 当前 node 绝对路径(避免 Cursor 环境 PATH 无 node/nvm)
|
|
1377
|
+
const mcpPath = path.join(__dirname, 'a2a-mcp.js');
|
|
1378
|
+
if (!fs.existsSync(mcpPath)) {
|
|
1379
|
+
fail('未找到 a2a-mcp.js(' + mcpPath + ')。请使用 npm 全局安装:npm install -g agent2agent-cli');
|
|
1380
|
+
}
|
|
1381
|
+
const config = {
|
|
1382
|
+
mcpServers: {
|
|
1383
|
+
a2a: { command: nodePath, args: [mcpPath] },
|
|
1384
|
+
},
|
|
1385
|
+
};
|
|
1386
|
+
const dir = path.join(process.cwd(), '.cursor');
|
|
1387
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
1388
|
+
const target = path.join(dir, 'mcp.json');
|
|
1389
|
+
fs.writeFileSync(target, JSON.stringify(config, null, 2) + '\n');
|
|
1390
|
+
console.log(paint(C.green, `已生成 ${target}`));
|
|
1391
|
+
console.log(' server: a2a(command=' + nodePath + ')');
|
|
1392
|
+
console.log('说明:该配置随项目提交,团队 clone 后无需再配;');
|
|
1393
|
+
console.log(' 请在当前项目(含 .a2a.json)使用,a2a-mcp 会自动匹配该项目账号。');
|
|
1394
|
+
console.log('重启 Cursor 后生效(MCP 面板应显示 13 个工具)。');
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1366
1397
|
/* ------------------------------------------------------------------------- *
|
|
1367
1398
|
* 帮助
|
|
1368
1399
|
* ------------------------------------------------------------------------- */
|
|
@@ -1389,6 +1420,7 @@ function printHelp() {
|
|
|
1389
1420
|
['sync', '双向镜像同步本地 doc 目录 ↔ 平台'],
|
|
1390
1421
|
['memory', '记忆(get / set)'],
|
|
1391
1422
|
['heartbeat', '心跳'],
|
|
1423
|
+
['mcp-setup', '生成 .cursor/mcp.json(Cursor/Windsurf MCP 接入)'],
|
|
1392
1424
|
['update-check', '检查各组件是否有新版本'],
|
|
1393
1425
|
['update', '一键更新 CLI + skills'],
|
|
1394
1426
|
['update-skills', '更新已安装的 skills(--to 指定目录 / --yes 免确认)'],
|
|
@@ -1483,16 +1515,22 @@ async function main() {
|
|
|
1483
1515
|
await cmdUpdate(opts);
|
|
1484
1516
|
return;
|
|
1485
1517
|
}
|
|
1518
|
+
if (cmd === 'mcp-setup') {
|
|
1519
|
+
await cmdMcpSetup();
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
if (cmd === 'update-check') {
|
|
1523
|
+
// 有 .a2a.json 则附带平台版本对比;无配置只检查 CLI / skills
|
|
1524
|
+
let cfg = null;
|
|
1525
|
+
try { cfg = requireConfig(opts.config); } catch (e) { cfg = null; }
|
|
1526
|
+
await cmdUpdateCheck(cfg || { config: null });
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1486
1529
|
|
|
1487
1530
|
let ctx = null;
|
|
1488
1531
|
try {
|
|
1489
1532
|
ctx = requireConfig(opts.config);
|
|
1490
1533
|
} catch (e) {
|
|
1491
|
-
// update-check 允许无配置运行(仅检查 CLI / skills);其余命令必须配置
|
|
1492
|
-
if (cmd === 'update-check') {
|
|
1493
|
-
await cmdUpdateCheck({ config: null });
|
|
1494
|
-
return;
|
|
1495
|
-
}
|
|
1496
1534
|
process.stderr.write(String(e.message || e) + '\n');
|
|
1497
1535
|
process.exit(1);
|
|
1498
1536
|
}
|
|
@@ -1552,7 +1590,20 @@ async function main() {
|
|
|
1552
1590
|
}
|
|
1553
1591
|
}
|
|
1554
1592
|
|
|
1555
|
-
main()
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1593
|
+
main()
|
|
1594
|
+
.catch((err) => {
|
|
1595
|
+
const msg = err && err.message ? err.message : String(err);
|
|
1596
|
+
fail(msg);
|
|
1597
|
+
})
|
|
1598
|
+
.finally(() => {
|
|
1599
|
+
// 统一「跑完即退」守卫:命令逻辑完成后,若仍有残留句柄(stdin 监听、定时器等)
|
|
1600
|
+
// 阻止事件循环退出,短暂等待 stdout flush 后强制退出,回到 shell。
|
|
1601
|
+
const guard = setTimeout(() => {
|
|
1602
|
+
try {
|
|
1603
|
+
process.stdin.pause();
|
|
1604
|
+
if (process.stdin.removeAllListeners) process.stdin.removeAllListeners('data');
|
|
1605
|
+
} catch (e) { /* ignore */ }
|
|
1606
|
+
process.exit(process.exitCode || 0);
|
|
1607
|
+
}, 600);
|
|
1608
|
+
if (guard.unref) guard.unref();
|
|
1609
|
+
});
|