adhdev 0.9.65 → 0.9.67
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/cli/index.js +685 -57
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +390 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +428 -11
- package/vendor/mcp-server/index.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
3
25
|
|
|
4
26
|
// src/server.ts
|
|
5
27
|
var import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
@@ -1242,6 +1264,248 @@ async function checkPendingCloud(transport, daemonId, format) {
|
|
|
1242
1264
|
${lines.join("\n\n")}`;
|
|
1243
1265
|
}
|
|
1244
1266
|
|
|
1267
|
+
// src/tools/mesh-tools.ts
|
|
1268
|
+
function findNode(mesh, nodeId) {
|
|
1269
|
+
const node = mesh.nodes.find((n) => n.id === nodeId);
|
|
1270
|
+
if (!node) throw new Error(`Node '${nodeId}' is not a member of mesh '${mesh.name}'`);
|
|
1271
|
+
return node;
|
|
1272
|
+
}
|
|
1273
|
+
var MESH_STATUS_TOOL = {
|
|
1274
|
+
name: "mesh_status",
|
|
1275
|
+
description: "Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions. Use this to decide which node to send work to.",
|
|
1276
|
+
inputSchema: {
|
|
1277
|
+
type: "object",
|
|
1278
|
+
properties: {}
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
var MESH_LIST_NODES_TOOL = {
|
|
1282
|
+
name: "mesh_list_nodes",
|
|
1283
|
+
description: "List all nodes in the mesh with their capabilities, platform, and workspace paths.",
|
|
1284
|
+
inputSchema: {
|
|
1285
|
+
type: "object",
|
|
1286
|
+
properties: {}
|
|
1287
|
+
}
|
|
1288
|
+
};
|
|
1289
|
+
var MESH_SEND_TASK_TOOL = {
|
|
1290
|
+
name: "mesh_send_task",
|
|
1291
|
+
description: "Send a natural-language task to an agent session on a mesh node. The agent will execute the task autonomously.",
|
|
1292
|
+
inputSchema: {
|
|
1293
|
+
type: "object",
|
|
1294
|
+
properties: {
|
|
1295
|
+
node_id: { type: "string", description: "Target node ID (from mesh_list_nodes)." },
|
|
1296
|
+
session_id: { type: "string", description: "Agent session ID on the target node." },
|
|
1297
|
+
message: { type: "string", description: "Natural-language task to send to the agent." }
|
|
1298
|
+
},
|
|
1299
|
+
required: ["node_id", "session_id", "message"]
|
|
1300
|
+
}
|
|
1301
|
+
};
|
|
1302
|
+
var MESH_READ_CHAT_TOOL = {
|
|
1303
|
+
name: "mesh_read_chat",
|
|
1304
|
+
description: "Read recent chat messages from a delegated agent session on a mesh node. Use this to check progress.",
|
|
1305
|
+
inputSchema: {
|
|
1306
|
+
type: "object",
|
|
1307
|
+
properties: {
|
|
1308
|
+
node_id: { type: "string", description: "Target node ID." },
|
|
1309
|
+
session_id: { type: "string", description: "Agent session ID to read from." },
|
|
1310
|
+
tail: { type: "number", description: "Number of recent messages to return (default: 10)." }
|
|
1311
|
+
},
|
|
1312
|
+
required: ["node_id", "session_id"]
|
|
1313
|
+
}
|
|
1314
|
+
};
|
|
1315
|
+
var MESH_LAUNCH_SESSION_TOOL = {
|
|
1316
|
+
name: "mesh_launch_session",
|
|
1317
|
+
description: "Launch a new agent session on a mesh node. Returns the session ID for subsequent send_task/read_chat calls.",
|
|
1318
|
+
inputSchema: {
|
|
1319
|
+
type: "object",
|
|
1320
|
+
properties: {
|
|
1321
|
+
node_id: { type: "string", description: "Target node ID." },
|
|
1322
|
+
type: { type: "string", description: 'Provider type (e.g. "claude-cli", "gemini-cli", "cursor").' }
|
|
1323
|
+
},
|
|
1324
|
+
required: ["node_id", "type"]
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
var MESH_GIT_STATUS_TOOL = {
|
|
1328
|
+
name: "mesh_git_status",
|
|
1329
|
+
description: "Get git status for a mesh node workspace \u2014 branch, dirty state, changed files.",
|
|
1330
|
+
inputSchema: {
|
|
1331
|
+
type: "object",
|
|
1332
|
+
properties: {
|
|
1333
|
+
node_id: { type: "string", description: "Target node ID." }
|
|
1334
|
+
},
|
|
1335
|
+
required: ["node_id"]
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
var MESH_CHECKPOINT_TOOL = {
|
|
1339
|
+
name: "mesh_checkpoint",
|
|
1340
|
+
description: "Create a git checkpoint (commit) on a mesh node workspace.",
|
|
1341
|
+
inputSchema: {
|
|
1342
|
+
type: "object",
|
|
1343
|
+
properties: {
|
|
1344
|
+
node_id: { type: "string", description: "Target node ID." },
|
|
1345
|
+
message: { type: "string", description: "Checkpoint commit message." }
|
|
1346
|
+
},
|
|
1347
|
+
required: ["node_id", "message"]
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
var MESH_APPROVE_TOOL = {
|
|
1351
|
+
name: "mesh_approve",
|
|
1352
|
+
description: "Approve or reject a pending action on a delegated agent session.",
|
|
1353
|
+
inputSchema: {
|
|
1354
|
+
type: "object",
|
|
1355
|
+
properties: {
|
|
1356
|
+
node_id: { type: "string", description: "Target node ID." },
|
|
1357
|
+
session_id: { type: "string", description: "Agent session ID with pending approval." },
|
|
1358
|
+
action: { type: "string", enum: ["approve", "reject"], description: "Action to take." }
|
|
1359
|
+
},
|
|
1360
|
+
required: ["node_id", "session_id", "action"]
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
var ALL_MESH_TOOLS = [
|
|
1364
|
+
MESH_STATUS_TOOL,
|
|
1365
|
+
MESH_LIST_NODES_TOOL,
|
|
1366
|
+
MESH_SEND_TASK_TOOL,
|
|
1367
|
+
MESH_READ_CHAT_TOOL,
|
|
1368
|
+
MESH_LAUNCH_SESSION_TOOL,
|
|
1369
|
+
MESH_GIT_STATUS_TOOL,
|
|
1370
|
+
MESH_CHECKPOINT_TOOL,
|
|
1371
|
+
MESH_APPROVE_TOOL
|
|
1372
|
+
];
|
|
1373
|
+
async function meshStatus(ctx) {
|
|
1374
|
+
const { mesh, transport } = ctx;
|
|
1375
|
+
const results = [];
|
|
1376
|
+
for (const node of mesh.nodes) {
|
|
1377
|
+
const entry = {
|
|
1378
|
+
nodeId: node.id,
|
|
1379
|
+
workspace: node.workspace
|
|
1380
|
+
};
|
|
1381
|
+
try {
|
|
1382
|
+
if (isLocalTransport(transport)) {
|
|
1383
|
+
const statusResult = await transport.command("git_status", { workspace: node.workspace });
|
|
1384
|
+
const status = statusResult?.status ?? statusResult;
|
|
1385
|
+
entry.health = status?.isGitRepo ? status?.isDirty ? "dirty" : "online" : "degraded";
|
|
1386
|
+
entry.branch = status?.branch;
|
|
1387
|
+
entry.isDirty = status?.isDirty;
|
|
1388
|
+
entry.uncommittedChanges = status?.uncommittedChanges ?? 0;
|
|
1389
|
+
} else {
|
|
1390
|
+
entry.health = "unknown";
|
|
1391
|
+
entry.note = "Cloud status probe not yet implemented for mesh nodes";
|
|
1392
|
+
}
|
|
1393
|
+
} catch (e) {
|
|
1394
|
+
entry.health = "degraded";
|
|
1395
|
+
entry.error = e.message;
|
|
1396
|
+
}
|
|
1397
|
+
results.push(entry);
|
|
1398
|
+
}
|
|
1399
|
+
return JSON.stringify({
|
|
1400
|
+
meshId: mesh.id,
|
|
1401
|
+
meshName: mesh.name,
|
|
1402
|
+
repoIdentity: mesh.repoIdentity,
|
|
1403
|
+
policy: mesh.policy,
|
|
1404
|
+
refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1405
|
+
nodes: results
|
|
1406
|
+
}, null, 2);
|
|
1407
|
+
}
|
|
1408
|
+
async function meshListNodes(ctx) {
|
|
1409
|
+
const { mesh } = ctx;
|
|
1410
|
+
return JSON.stringify({
|
|
1411
|
+
meshId: mesh.id,
|
|
1412
|
+
meshName: mesh.name,
|
|
1413
|
+
nodes: mesh.nodes.map((n) => ({
|
|
1414
|
+
nodeId: n.id,
|
|
1415
|
+
workspace: n.workspace,
|
|
1416
|
+
repoRoot: n.repoRoot,
|
|
1417
|
+
isLocalWorktree: n.isLocalWorktree,
|
|
1418
|
+
policy: n.policy,
|
|
1419
|
+
userOverrides: n.userOverrides
|
|
1420
|
+
}))
|
|
1421
|
+
}, null, 2);
|
|
1422
|
+
}
|
|
1423
|
+
async function meshSendTask(ctx, args) {
|
|
1424
|
+
const node = findNode(ctx.mesh, args.node_id);
|
|
1425
|
+
if (node.policy.readOnly) {
|
|
1426
|
+
return JSON.stringify({ error: `Node '${args.node_id}' is read-only` });
|
|
1427
|
+
}
|
|
1428
|
+
if (isLocalTransport(ctx.transport)) {
|
|
1429
|
+
await ctx.transport.command("send_chat", {
|
|
1430
|
+
message: args.message,
|
|
1431
|
+
sessionId: args.session_id
|
|
1432
|
+
});
|
|
1433
|
+
return JSON.stringify({ success: true, nodeId: args.node_id, sessionId: args.session_id });
|
|
1434
|
+
} else {
|
|
1435
|
+
return JSON.stringify({ error: "Cloud mesh send_task not yet implemented" });
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
async function meshReadChat(ctx, args) {
|
|
1439
|
+
findNode(ctx.mesh, args.node_id);
|
|
1440
|
+
if (isLocalTransport(ctx.transport)) {
|
|
1441
|
+
const result = await ctx.transport.command("read_chat", {
|
|
1442
|
+
sessionId: args.session_id,
|
|
1443
|
+
tailLimit: args.tail ?? 10
|
|
1444
|
+
});
|
|
1445
|
+
return JSON.stringify(result, null, 2);
|
|
1446
|
+
} else {
|
|
1447
|
+
return JSON.stringify({ error: "Cloud mesh read_chat not yet implemented" });
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
async function meshLaunchSession(ctx, args) {
|
|
1451
|
+
const node = findNode(ctx.mesh, args.node_id);
|
|
1452
|
+
if (isLocalTransport(ctx.transport)) {
|
|
1453
|
+
const result = await ctx.transport.command("launch_cli", {
|
|
1454
|
+
type: args.type,
|
|
1455
|
+
dir: node.workspace
|
|
1456
|
+
});
|
|
1457
|
+
return JSON.stringify(result, null, 2);
|
|
1458
|
+
} else {
|
|
1459
|
+
return JSON.stringify({ error: "Cloud mesh launch_session not yet implemented" });
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
async function meshGitStatus(ctx, args) {
|
|
1463
|
+
const node = findNode(ctx.mesh, args.node_id);
|
|
1464
|
+
if (isLocalTransport(ctx.transport)) {
|
|
1465
|
+
const statusResult = await ctx.transport.command("git_status", {
|
|
1466
|
+
workspace: node.workspace
|
|
1467
|
+
});
|
|
1468
|
+
const diffResult = await ctx.transport.command("git_diff_summary", {
|
|
1469
|
+
workspace: node.workspace
|
|
1470
|
+
});
|
|
1471
|
+
return JSON.stringify({
|
|
1472
|
+
nodeId: args.node_id,
|
|
1473
|
+
workspace: node.workspace,
|
|
1474
|
+
status: statusResult?.status ?? statusResult,
|
|
1475
|
+
diff: diffResult?.diffSummary ?? diffResult
|
|
1476
|
+
}, null, 2);
|
|
1477
|
+
} else {
|
|
1478
|
+
return JSON.stringify({ error: "Cloud mesh git_status not yet implemented" });
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
async function meshCheckpoint(ctx, args) {
|
|
1482
|
+
const node = findNode(ctx.mesh, args.node_id);
|
|
1483
|
+
if (node.policy.readOnly) {
|
|
1484
|
+
return JSON.stringify({ error: `Node '${args.node_id}' is read-only \u2014 cannot checkpoint` });
|
|
1485
|
+
}
|
|
1486
|
+
if (isLocalTransport(ctx.transport)) {
|
|
1487
|
+
const result = await ctx.transport.command("git_checkpoint", {
|
|
1488
|
+
workspace: node.workspace,
|
|
1489
|
+
message: args.message
|
|
1490
|
+
});
|
|
1491
|
+
return JSON.stringify(result, null, 2);
|
|
1492
|
+
} else {
|
|
1493
|
+
return JSON.stringify({ error: "Cloud mesh checkpoint not yet implemented" });
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
async function meshApprove(ctx, args) {
|
|
1497
|
+
findNode(ctx.mesh, args.node_id);
|
|
1498
|
+
if (isLocalTransport(ctx.transport)) {
|
|
1499
|
+
const result = await ctx.transport.command("resolve_action", {
|
|
1500
|
+
sessionId: args.session_id,
|
|
1501
|
+
action: args.action === "reject" ? "reject" : "approve"
|
|
1502
|
+
});
|
|
1503
|
+
return JSON.stringify(result, null, 2);
|
|
1504
|
+
} else {
|
|
1505
|
+
return JSON.stringify({ error: "Cloud mesh approve not yet implemented" });
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1245
1509
|
// src/server.ts
|
|
1246
1510
|
async function startMcpServer(opts) {
|
|
1247
1511
|
const transport = opts.mode === "cloud" ? new CloudTransport({ apiKey: opts.apiKey, baseUrl: opts.baseUrl }) : new LocalTransport({ port: opts.port, password: opts.password });
|
|
@@ -1253,6 +1517,150 @@ async function startMcpServer(opts) {
|
|
|
1253
1517
|
process.exit(1);
|
|
1254
1518
|
}
|
|
1255
1519
|
const isLocal = opts.mode === "local";
|
|
1520
|
+
if (opts.meshId) {
|
|
1521
|
+
let mesh;
|
|
1522
|
+
if (opts.mode === "cloud" && opts.apiKey) {
|
|
1523
|
+
try {
|
|
1524
|
+
const base = opts.baseUrl || "https://api.adhf.dev";
|
|
1525
|
+
const res = await fetch(`${base}/api/v1/repo-meshes/${opts.meshId}`, {
|
|
1526
|
+
headers: { "Authorization": `Bearer ${opts.apiKey}`, "Content-Type": "application/json" }
|
|
1527
|
+
});
|
|
1528
|
+
if (res.ok) {
|
|
1529
|
+
const data = await res.json();
|
|
1530
|
+
const rm = data.mesh;
|
|
1531
|
+
const nodes = data.nodes || [];
|
|
1532
|
+
let policy = {};
|
|
1533
|
+
try {
|
|
1534
|
+
policy = JSON.parse(rm.policy_json || rm.policy || "{}");
|
|
1535
|
+
} catch {
|
|
1536
|
+
}
|
|
1537
|
+
let coordinator = {};
|
|
1538
|
+
try {
|
|
1539
|
+
coordinator = JSON.parse(rm.coordinator_json || rm.coordinator_config || "{}");
|
|
1540
|
+
} catch {
|
|
1541
|
+
}
|
|
1542
|
+
mesh = {
|
|
1543
|
+
id: rm.id,
|
|
1544
|
+
name: rm.name,
|
|
1545
|
+
repoIdentity: rm.repo_identity,
|
|
1546
|
+
repoRemoteUrl: rm.repo_remote_url,
|
|
1547
|
+
defaultBranch: rm.default_branch,
|
|
1548
|
+
policy: {
|
|
1549
|
+
requirePreTaskCheckpoint: false,
|
|
1550
|
+
requirePostTaskCheckpoint: true,
|
|
1551
|
+
requireApprovalForPush: true,
|
|
1552
|
+
requireApprovalForDestructiveGit: true,
|
|
1553
|
+
dirtyWorkspaceBehavior: "warn",
|
|
1554
|
+
maxParallelTasks: 2,
|
|
1555
|
+
...policy
|
|
1556
|
+
},
|
|
1557
|
+
coordinator,
|
|
1558
|
+
nodes: nodes.map((n) => ({
|
|
1559
|
+
id: n.id,
|
|
1560
|
+
workspace: n.workspace,
|
|
1561
|
+
repoRoot: n.repo_root,
|
|
1562
|
+
userOverrides: {},
|
|
1563
|
+
policy: {},
|
|
1564
|
+
isLocalWorktree: false
|
|
1565
|
+
})),
|
|
1566
|
+
createdAt: rm.created_at,
|
|
1567
|
+
updatedAt: rm.updated_at
|
|
1568
|
+
};
|
|
1569
|
+
process.stderr.write(`[adhdev-mcp] Loaded mesh config from cloud API
|
|
1570
|
+
`);
|
|
1571
|
+
}
|
|
1572
|
+
} catch (e) {
|
|
1573
|
+
process.stderr.write(`[adhdev-mcp] Cloud mesh fetch failed, falling back to local: ${e.message}
|
|
1574
|
+
`);
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
if (!mesh) {
|
|
1578
|
+
try {
|
|
1579
|
+
const { getMesh } = await import("@adhdev/daemon-core");
|
|
1580
|
+
mesh = getMesh(opts.meshId);
|
|
1581
|
+
} catch (e) {
|
|
1582
|
+
process.stderr.write(`[adhdev-mcp] Failed to load mesh config: ${e.message}
|
|
1583
|
+
`);
|
|
1584
|
+
process.exit(1);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
if (!mesh) {
|
|
1588
|
+
process.stderr.write(`[adhdev-mcp] Mesh '${opts.meshId}' not found in ${opts.mode === "cloud" ? "cloud or local" : "local"} config. Use 'adhdev mesh list' to see available meshes.
|
|
1589
|
+
`);
|
|
1590
|
+
process.exit(1);
|
|
1591
|
+
}
|
|
1592
|
+
const meshCtx = { mesh, transport };
|
|
1593
|
+
let coordinatorPrompt = "";
|
|
1594
|
+
try {
|
|
1595
|
+
const { buildCoordinatorSystemPrompt } = await import("@adhdev/daemon-core");
|
|
1596
|
+
coordinatorPrompt = buildCoordinatorSystemPrompt({ mesh });
|
|
1597
|
+
} catch {
|
|
1598
|
+
coordinatorPrompt = `You are a Repo Mesh Coordinator for "${mesh.name}" (${mesh.repoIdentity}). Use mesh_* tools to orchestrate work.`;
|
|
1599
|
+
}
|
|
1600
|
+
const server2 = new import_server.Server(
|
|
1601
|
+
{ name: "adhdev-mcp-server", version: "0.9.67" },
|
|
1602
|
+
{ capabilities: { tools: {}, resources: {} } }
|
|
1603
|
+
);
|
|
1604
|
+
const { ListResourcesRequestSchema, ReadResourceRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
|
|
1605
|
+
server2.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
1606
|
+
resources: [{
|
|
1607
|
+
uri: "coordinator://system-prompt",
|
|
1608
|
+
name: "Coordinator System Prompt",
|
|
1609
|
+
description: `System prompt for mesh "${mesh.name}" coordinator`,
|
|
1610
|
+
mimeType: "text/plain"
|
|
1611
|
+
}]
|
|
1612
|
+
}));
|
|
1613
|
+
server2.setRequestHandler(ReadResourceRequestSchema, async (req) => {
|
|
1614
|
+
if (req.params.uri === "coordinator://system-prompt") {
|
|
1615
|
+
return { contents: [{ uri: req.params.uri, mimeType: "text/plain", text: coordinatorPrompt }] };
|
|
1616
|
+
}
|
|
1617
|
+
throw new Error(`Unknown resource: ${req.params.uri}`);
|
|
1618
|
+
});
|
|
1619
|
+
server2.setRequestHandler(import_types.ListToolsRequestSchema, async () => ({ tools: ALL_MESH_TOOLS }));
|
|
1620
|
+
server2.setRequestHandler(import_types.CallToolRequestSchema, async (req) => {
|
|
1621
|
+
const { name, arguments: args } = req.params;
|
|
1622
|
+
const a = args ?? {};
|
|
1623
|
+
try {
|
|
1624
|
+
let text;
|
|
1625
|
+
switch (name) {
|
|
1626
|
+
case "mesh_status":
|
|
1627
|
+
text = await meshStatus(meshCtx);
|
|
1628
|
+
break;
|
|
1629
|
+
case "mesh_list_nodes":
|
|
1630
|
+
text = await meshListNodes(meshCtx);
|
|
1631
|
+
break;
|
|
1632
|
+
case "mesh_send_task":
|
|
1633
|
+
text = await meshSendTask(meshCtx, a);
|
|
1634
|
+
break;
|
|
1635
|
+
case "mesh_read_chat":
|
|
1636
|
+
text = await meshReadChat(meshCtx, a);
|
|
1637
|
+
break;
|
|
1638
|
+
case "mesh_launch_session":
|
|
1639
|
+
text = await meshLaunchSession(meshCtx, a);
|
|
1640
|
+
break;
|
|
1641
|
+
case "mesh_git_status":
|
|
1642
|
+
text = await meshGitStatus(meshCtx, a);
|
|
1643
|
+
break;
|
|
1644
|
+
case "mesh_checkpoint":
|
|
1645
|
+
text = await meshCheckpoint(meshCtx, a);
|
|
1646
|
+
break;
|
|
1647
|
+
case "mesh_approve":
|
|
1648
|
+
text = await meshApprove(meshCtx, a);
|
|
1649
|
+
break;
|
|
1650
|
+
default:
|
|
1651
|
+
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
1652
|
+
}
|
|
1653
|
+
return { content: [{ type: "text", text }] };
|
|
1654
|
+
} catch (err) {
|
|
1655
|
+
return { content: [{ type: "text", text: `Error: ${err?.message ?? String(err)}` }], isError: true };
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1658
|
+
const stdioTransport2 = new import_stdio.StdioServerTransport();
|
|
1659
|
+
await server2.connect(stdioTransport2);
|
|
1660
|
+
process.stderr.write(`[adhdev-mcp] Server running in ${opts.mode} mesh mode \u2014 mesh: ${mesh.name} (${mesh.repoIdentity})
|
|
1661
|
+
`);
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1256
1664
|
const allTools = [
|
|
1257
1665
|
LIST_DAEMONS_TOOL,
|
|
1258
1666
|
LIST_SESSIONS_TOOL,
|
|
@@ -1270,7 +1678,7 @@ async function startMcpServer(opts) {
|
|
|
1270
1678
|
...isLocal ? [SCREENSHOT_TOOL] : []
|
|
1271
1679
|
];
|
|
1272
1680
|
const server = new import_server.Server(
|
|
1273
|
-
{ name: "adhdev-mcp-server", version: "0.9.
|
|
1681
|
+
{ name: "adhdev-mcp-server", version: "0.9.66" },
|
|
1274
1682
|
{ capabilities: { tools: {} } }
|
|
1275
1683
|
);
|
|
1276
1684
|
server.setRequestHandler(import_types.ListToolsRequestSchema, async () => ({ tools: allTools }));
|
|
@@ -1373,6 +1781,7 @@ function parseArgs(argv) {
|
|
|
1373
1781
|
let baseUrl;
|
|
1374
1782
|
let port;
|
|
1375
1783
|
let password;
|
|
1784
|
+
let meshId;
|
|
1376
1785
|
for (let i = 0; i < args.length; i++) {
|
|
1377
1786
|
const arg = args[i];
|
|
1378
1787
|
if ((arg === "--api-key" || arg === "-k") && args[i + 1]) {
|
|
@@ -1387,6 +1796,10 @@ function parseArgs(argv) {
|
|
|
1387
1796
|
port = Number(arg.slice("--port=".length));
|
|
1388
1797
|
} else if (arg === "--password" && args[i + 1]) {
|
|
1389
1798
|
password = args[++i];
|
|
1799
|
+
} else if ((arg === "--repo-mesh" || arg === "--mesh") && args[i + 1]) {
|
|
1800
|
+
meshId = args[++i];
|
|
1801
|
+
} else if (arg?.startsWith("--repo-mesh=")) {
|
|
1802
|
+
meshId = arg.slice("--repo-mesh=".length);
|
|
1390
1803
|
} else if (arg === "--help" || arg === "-h") {
|
|
1391
1804
|
printHelp();
|
|
1392
1805
|
process.exit(0);
|
|
@@ -1394,30 +1807,34 @@ function parseArgs(argv) {
|
|
|
1394
1807
|
}
|
|
1395
1808
|
if (!apiKey && process.env.ADHDEV_API_KEY) apiKey = process.env.ADHDEV_API_KEY;
|
|
1396
1809
|
if (!password && process.env.ADHDEV_PASSWORD) password = process.env.ADHDEV_PASSWORD;
|
|
1810
|
+
if (!meshId && process.env.ADHDEV_MESH_ID) meshId = process.env.ADHDEV_MESH_ID;
|
|
1397
1811
|
const mode = apiKey ? "cloud" : "local";
|
|
1398
|
-
return { mode, port, password, apiKey, baseUrl };
|
|
1812
|
+
return { mode, port, password, apiKey, baseUrl, meshId };
|
|
1399
1813
|
}
|
|
1400
1814
|
function printHelp() {
|
|
1401
1815
|
console.error(`
|
|
1402
1816
|
adhdev-mcp \u2014 ADHDev MCP Server
|
|
1403
1817
|
|
|
1404
1818
|
Usage:
|
|
1405
|
-
adhdev-mcp
|
|
1406
|
-
adhdev-mcp --api-key <key>
|
|
1819
|
+
adhdev-mcp Local mode (requires standalone daemon)
|
|
1820
|
+
adhdev-mcp --api-key <key> Cloud mode (ADHDev cloud API)
|
|
1821
|
+
adhdev-mcp --repo-mesh <mesh_id> Mesh mode (coordinator-scoped tools)
|
|
1407
1822
|
|
|
1408
1823
|
Options:
|
|
1409
|
-
--port <n>
|
|
1410
|
-
--password <pass>
|
|
1411
|
-
--api-key <key>
|
|
1412
|
-
--base-url <url>
|
|
1413
|
-
--
|
|
1824
|
+
--port <n> Standalone daemon port (default: 3847)
|
|
1825
|
+
--password <pass> Standalone daemon password (if set)
|
|
1826
|
+
--api-key <key> ADHDev cloud API key (switches to cloud mode)
|
|
1827
|
+
--base-url <url> Override cloud API base URL
|
|
1828
|
+
--repo-mesh <mesh_id> Enable mesh mode \u2014 exposes only mesh-scoped coordinator tools
|
|
1829
|
+
--help Show this help
|
|
1414
1830
|
|
|
1415
1831
|
Environment variables:
|
|
1416
1832
|
ADHDEV_API_KEY API key (cloud mode)
|
|
1417
1833
|
ADHDEV_PASSWORD Daemon password (local mode)
|
|
1834
|
+
ADHDEV_MESH_ID Mesh ID (mesh mode)
|
|
1418
1835
|
|
|
1419
|
-
|
|
1420
|
-
|
|
1836
|
+
Standard tools: list_daemons, list_sessions, launch_session, stop_session, check_pending, read_chat, send_chat, approve, git_status, git_log, git_diff, git_checkpoint, git_push, screenshot
|
|
1837
|
+
Mesh tools: mesh_status, mesh_list_nodes, mesh_send_task, mesh_read_chat, mesh_launch_session, mesh_git_status, mesh_checkpoint, mesh_approve
|
|
1421
1838
|
`.trim());
|
|
1422
1839
|
}
|
|
1423
1840
|
startMcpServer(parseArgs(process.argv)).catch((err) => {
|