claudemesh-cli 0.7.1 → 0.8.1
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/index.js +703 -20
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -47663,6 +47663,75 @@ var TOOLS = [
|
|
|
47663
47663
|
},
|
|
47664
47664
|
required: ["name"]
|
|
47665
47665
|
}
|
|
47666
|
+
},
|
|
47667
|
+
{
|
|
47668
|
+
name: "mesh_mcp_deploy",
|
|
47669
|
+
description: "Deploy an MCP server to the mesh from a zip file or git repo. Runs on the broker VPS, persists across peer sessions. Default scope: private (only you).",
|
|
47670
|
+
inputSchema: {
|
|
47671
|
+
type: "object",
|
|
47672
|
+
properties: {
|
|
47673
|
+
server_name: { type: "string", description: "Unique name for the server in this mesh" },
|
|
47674
|
+
file_id: { type: "string", description: "File ID of uploaded zip (from share_file)" },
|
|
47675
|
+
git_url: { type: "string", description: "Git repo URL" },
|
|
47676
|
+
git_branch: { type: "string", description: "Branch to clone (default: main)" },
|
|
47677
|
+
env: { type: "object", description: "Environment variables. Use $vault:<key> for vault secrets." },
|
|
47678
|
+
runtime: { type: "string", enum: ["node", "python", "bun"], description: "Runtime (auto-detected if omitted)" },
|
|
47679
|
+
memory_mb: { type: "number", description: "Memory limit in MB (default: 256)" },
|
|
47680
|
+
network_allow: { type: "array", items: { type: "string" }, description: "Allowed outbound hosts (default: none)" },
|
|
47681
|
+
scope: { description: "Visibility: 'peer' (default), 'mesh', or {group/groups/role/peers}" }
|
|
47682
|
+
},
|
|
47683
|
+
required: ["server_name"]
|
|
47684
|
+
}
|
|
47685
|
+
},
|
|
47686
|
+
{
|
|
47687
|
+
name: "mesh_mcp_undeploy",
|
|
47688
|
+
description: "Stop and remove a managed MCP server from the mesh.",
|
|
47689
|
+
inputSchema: { type: "object", properties: { server_name: { type: "string" } }, required: ["server_name"] }
|
|
47690
|
+
},
|
|
47691
|
+
{
|
|
47692
|
+
name: "mesh_mcp_update",
|
|
47693
|
+
description: "Pull latest code and restart a git-sourced MCP server.",
|
|
47694
|
+
inputSchema: { type: "object", properties: { server_name: { type: "string" } }, required: ["server_name"] }
|
|
47695
|
+
},
|
|
47696
|
+
{
|
|
47697
|
+
name: "mesh_mcp_logs",
|
|
47698
|
+
description: "View recent logs from a managed MCP server.",
|
|
47699
|
+
inputSchema: { type: "object", properties: { server_name: { type: "string" }, lines: { type: "number", description: "Lines (default: 50, max: 1000)" } }, required: ["server_name"] }
|
|
47700
|
+
},
|
|
47701
|
+
{
|
|
47702
|
+
name: "mesh_mcp_scope",
|
|
47703
|
+
description: "Get or set the visibility scope of a deployed MCP server.",
|
|
47704
|
+
inputSchema: { type: "object", properties: { server_name: { type: "string" }, scope: { description: "New scope to set. Omit to read current." } }, required: ["server_name"] }
|
|
47705
|
+
},
|
|
47706
|
+
{
|
|
47707
|
+
name: "mesh_mcp_schema",
|
|
47708
|
+
description: "Inspect tool schemas for a deployed MCP server.",
|
|
47709
|
+
inputSchema: { type: "object", properties: { server_name: { type: "string" }, tool_name: { type: "string", description: "Specific tool (omit for all)" } }, required: ["server_name"] }
|
|
47710
|
+
},
|
|
47711
|
+
{
|
|
47712
|
+
name: "mesh_mcp_catalog",
|
|
47713
|
+
description: "List all deployed services in the mesh with status, scope, and tool count.",
|
|
47714
|
+
inputSchema: { type: "object", properties: {} }
|
|
47715
|
+
},
|
|
47716
|
+
{
|
|
47717
|
+
name: "mesh_skill_deploy",
|
|
47718
|
+
description: "Deploy a multi-file skill bundle from a zip or git repo.",
|
|
47719
|
+
inputSchema: { type: "object", properties: { file_id: { type: "string" }, git_url: { type: "string" }, git_branch: { type: "string" } } }
|
|
47720
|
+
},
|
|
47721
|
+
{
|
|
47722
|
+
name: "vault_set",
|
|
47723
|
+
description: "Store an encrypted credential in your vault. Reference in mesh_mcp_deploy with $vault:<key>.",
|
|
47724
|
+
inputSchema: { type: "object", properties: { key: { type: "string" }, value: { type: "string", description: "Secret value or local file path (for type=file)" }, type: { type: "string", enum: ["env", "file"] }, mount_path: { type: "string" }, description: { type: "string" } }, required: ["key", "value"] }
|
|
47725
|
+
},
|
|
47726
|
+
{
|
|
47727
|
+
name: "vault_list",
|
|
47728
|
+
description: "List your vault entries (keys and metadata only, no secret values).",
|
|
47729
|
+
inputSchema: { type: "object", properties: {} }
|
|
47730
|
+
},
|
|
47731
|
+
{
|
|
47732
|
+
name: "vault_delete",
|
|
47733
|
+
description: "Remove a credential from your vault.",
|
|
47734
|
+
inputSchema: { type: "object", properties: { key: { type: "string" } }, required: ["key"] }
|
|
47666
47735
|
}
|
|
47667
47736
|
];
|
|
47668
47737
|
|
|
@@ -47751,6 +47820,10 @@ class BrokerClient {
|
|
|
47751
47820
|
peerFileResponseResolvers = new Map;
|
|
47752
47821
|
peerDirResponseResolvers = new Map;
|
|
47753
47822
|
sharedDirs = [process.cwd()];
|
|
47823
|
+
_serviceCatalog = [];
|
|
47824
|
+
get serviceCatalog() {
|
|
47825
|
+
return this._serviceCatalog;
|
|
47826
|
+
}
|
|
47754
47827
|
closed = false;
|
|
47755
47828
|
reconnectAttempt = 0;
|
|
47756
47829
|
helloTimer = null;
|
|
@@ -47858,6 +47931,9 @@ class BrokerClient {
|
|
|
47858
47931
|
this._statsCounters.errors = rs.errors ?? 0;
|
|
47859
47932
|
}
|
|
47860
47933
|
}
|
|
47934
|
+
if (msg.services) {
|
|
47935
|
+
this._serviceCatalog = msg.services;
|
|
47936
|
+
}
|
|
47861
47937
|
resolve();
|
|
47862
47938
|
return;
|
|
47863
47939
|
}
|
|
@@ -48146,6 +48222,14 @@ class BrokerClient {
|
|
|
48146
48222
|
mcpListResolvers = new Map;
|
|
48147
48223
|
mcpCallResolvers = new Map;
|
|
48148
48224
|
mcpCallForwardHandler = null;
|
|
48225
|
+
vaultAckResolvers = new Map;
|
|
48226
|
+
vaultListResolvers = new Map;
|
|
48227
|
+
mcpDeployResolvers = new Map;
|
|
48228
|
+
mcpLogsResolvers = new Map;
|
|
48229
|
+
mcpSchemaServiceResolvers = new Map;
|
|
48230
|
+
mcpCatalogResolvers = new Map;
|
|
48231
|
+
mcpScopeResolvers = new Map;
|
|
48232
|
+
skillDeployResolvers = new Map;
|
|
48149
48233
|
async messageStatus(messageId) {
|
|
48150
48234
|
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
48151
48235
|
return null;
|
|
@@ -48678,6 +48762,138 @@ class BrokerClient {
|
|
|
48678
48762
|
this.ws.send(JSON.stringify({ type: "peer_dir_request", targetPubkey, dirPath, ...pattern ? { pattern } : {}, _reqId: reqId }));
|
|
48679
48763
|
});
|
|
48680
48764
|
}
|
|
48765
|
+
async vaultSet(key, ciphertext, nonce, sealedKey, entryType, mountPath, description) {
|
|
48766
|
+
return new Promise((resolve) => {
|
|
48767
|
+
const reqId = `vset_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
48768
|
+
const timer = setTimeout(() => {
|
|
48769
|
+
this.vaultAckResolvers.delete(reqId);
|
|
48770
|
+
resolve(false);
|
|
48771
|
+
}, 1e4);
|
|
48772
|
+
this.vaultAckResolvers.set(reqId, { resolve, timer });
|
|
48773
|
+
this.sendRaw({ type: "vault_set", key, ciphertext, nonce, sealed_key: sealedKey, entry_type: entryType, mount_path: mountPath, description, _reqId: reqId });
|
|
48774
|
+
});
|
|
48775
|
+
}
|
|
48776
|
+
async vaultList() {
|
|
48777
|
+
return new Promise((resolve) => {
|
|
48778
|
+
const reqId = `vlist_${Date.now()}`;
|
|
48779
|
+
const timer = setTimeout(() => {
|
|
48780
|
+
this.vaultListResolvers.delete(reqId);
|
|
48781
|
+
resolve([]);
|
|
48782
|
+
}, 1e4);
|
|
48783
|
+
this.vaultListResolvers.set(reqId, { resolve, timer });
|
|
48784
|
+
this.sendRaw({ type: "vault_list", _reqId: reqId });
|
|
48785
|
+
});
|
|
48786
|
+
}
|
|
48787
|
+
async vaultDelete(key) {
|
|
48788
|
+
return new Promise((resolve) => {
|
|
48789
|
+
const reqId = `vdel_${Date.now()}`;
|
|
48790
|
+
const timer = setTimeout(() => {
|
|
48791
|
+
this.vaultAckResolvers.delete(reqId);
|
|
48792
|
+
resolve(false);
|
|
48793
|
+
}, 1e4);
|
|
48794
|
+
this.vaultAckResolvers.set(reqId, { resolve, timer });
|
|
48795
|
+
this.sendRaw({ type: "vault_delete", key, _reqId: reqId });
|
|
48796
|
+
});
|
|
48797
|
+
}
|
|
48798
|
+
async mcpDeploy(serverName, source, config2, scope) {
|
|
48799
|
+
return new Promise((resolve) => {
|
|
48800
|
+
const reqId = `deploy_${Date.now()}`;
|
|
48801
|
+
const timer = setTimeout(() => {
|
|
48802
|
+
this.mcpDeployResolvers.delete(reqId);
|
|
48803
|
+
resolve({ status: "timeout" });
|
|
48804
|
+
}, 60000);
|
|
48805
|
+
this.mcpDeployResolvers.set(reqId, { resolve, timer });
|
|
48806
|
+
this.sendRaw({ type: "mcp_deploy", server_name: serverName, source, config: config2, scope, _reqId: reqId });
|
|
48807
|
+
});
|
|
48808
|
+
}
|
|
48809
|
+
async mcpUndeploy(serverName) {
|
|
48810
|
+
return new Promise((resolve) => {
|
|
48811
|
+
const reqId = `undeploy_${Date.now()}`;
|
|
48812
|
+
const timer = setTimeout(() => {
|
|
48813
|
+
this.mcpDeployResolvers.delete(reqId);
|
|
48814
|
+
resolve(false);
|
|
48815
|
+
}, 1e4);
|
|
48816
|
+
this.mcpDeployResolvers.set(reqId, { resolve: (r) => resolve(r.status === "stopped"), timer });
|
|
48817
|
+
this.sendRaw({ type: "mcp_undeploy", server_name: serverName, _reqId: reqId });
|
|
48818
|
+
});
|
|
48819
|
+
}
|
|
48820
|
+
async mcpUpdate(serverName) {
|
|
48821
|
+
return new Promise((resolve) => {
|
|
48822
|
+
const reqId = `update_${Date.now()}`;
|
|
48823
|
+
const timer = setTimeout(() => {
|
|
48824
|
+
this.mcpDeployResolvers.delete(reqId);
|
|
48825
|
+
resolve({ status: "timeout" });
|
|
48826
|
+
}, 60000);
|
|
48827
|
+
this.mcpDeployResolvers.set(reqId, { resolve, timer });
|
|
48828
|
+
this.sendRaw({ type: "mcp_update", server_name: serverName, _reqId: reqId });
|
|
48829
|
+
});
|
|
48830
|
+
}
|
|
48831
|
+
async mcpLogs(serverName, lines) {
|
|
48832
|
+
return new Promise((resolve) => {
|
|
48833
|
+
const reqId = `logs_${Date.now()}`;
|
|
48834
|
+
const timer = setTimeout(() => {
|
|
48835
|
+
this.mcpLogsResolvers.delete(reqId);
|
|
48836
|
+
resolve([]);
|
|
48837
|
+
}, 1e4);
|
|
48838
|
+
this.mcpLogsResolvers.set(reqId, { resolve, timer });
|
|
48839
|
+
this.sendRaw({ type: "mcp_logs", server_name: serverName, lines, _reqId: reqId });
|
|
48840
|
+
});
|
|
48841
|
+
}
|
|
48842
|
+
async mcpScope(serverName, scope) {
|
|
48843
|
+
return new Promise((resolve) => {
|
|
48844
|
+
const reqId = `scope_${Date.now()}`;
|
|
48845
|
+
const timer = setTimeout(() => {
|
|
48846
|
+
this.mcpScopeResolvers.delete(reqId);
|
|
48847
|
+
resolve({ scope: { type: "peer" }, deployed_by: "unknown" });
|
|
48848
|
+
}, 1e4);
|
|
48849
|
+
this.mcpScopeResolvers.set(reqId, { resolve, timer });
|
|
48850
|
+
this.sendRaw({ type: "mcp_scope", server_name: serverName, scope, _reqId: reqId });
|
|
48851
|
+
});
|
|
48852
|
+
}
|
|
48853
|
+
async mcpServiceSchema(serverName, toolName) {
|
|
48854
|
+
return new Promise((resolve) => {
|
|
48855
|
+
const reqId = `schema_${Date.now()}`;
|
|
48856
|
+
const timer = setTimeout(() => {
|
|
48857
|
+
this.mcpSchemaServiceResolvers.delete(reqId);
|
|
48858
|
+
resolve([]);
|
|
48859
|
+
}, 1e4);
|
|
48860
|
+
this.mcpSchemaServiceResolvers.set(reqId, { resolve, timer });
|
|
48861
|
+
this.sendRaw({ type: "mcp_schema", server_name: serverName, tool_name: toolName, _reqId: reqId });
|
|
48862
|
+
});
|
|
48863
|
+
}
|
|
48864
|
+
async mcpCatalog() {
|
|
48865
|
+
return new Promise((resolve) => {
|
|
48866
|
+
const reqId = `catalog_${Date.now()}`;
|
|
48867
|
+
const timer = setTimeout(() => {
|
|
48868
|
+
this.mcpCatalogResolvers.delete(reqId);
|
|
48869
|
+
resolve([]);
|
|
48870
|
+
}, 1e4);
|
|
48871
|
+
this.mcpCatalogResolvers.set(reqId, { resolve, timer });
|
|
48872
|
+
this.sendRaw({ type: "mcp_catalog", _reqId: reqId });
|
|
48873
|
+
});
|
|
48874
|
+
}
|
|
48875
|
+
async skillDeploy(source) {
|
|
48876
|
+
return new Promise((resolve) => {
|
|
48877
|
+
const reqId = `skilldeploy_${Date.now()}`;
|
|
48878
|
+
const timer = setTimeout(() => {
|
|
48879
|
+
this.skillDeployResolvers.delete(reqId);
|
|
48880
|
+
resolve({ name: "unknown", files: [] });
|
|
48881
|
+
}, 30000);
|
|
48882
|
+
this.skillDeployResolvers.set(reqId, { resolve, timer });
|
|
48883
|
+
this.sendRaw({ type: "skill_deploy", source, _reqId: reqId });
|
|
48884
|
+
});
|
|
48885
|
+
}
|
|
48886
|
+
async getServiceTools(serviceName) {
|
|
48887
|
+
const cached2 = this._serviceCatalog.find((s) => s.name === serviceName);
|
|
48888
|
+
if (cached2?.tools?.length)
|
|
48889
|
+
return cached2.tools;
|
|
48890
|
+
return this.mcpServiceSchema(serviceName);
|
|
48891
|
+
}
|
|
48892
|
+
sendRaw(payload) {
|
|
48893
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
48894
|
+
return;
|
|
48895
|
+
this.ws.send(JSON.stringify(payload));
|
|
48896
|
+
}
|
|
48681
48897
|
close() {
|
|
48682
48898
|
this.closed = true;
|
|
48683
48899
|
this.stopStatsReporting();
|
|
@@ -49179,6 +49395,78 @@ class BrokerClient {
|
|
|
49179
49395
|
this.resolveFromMap(this.webhookListResolvers, msgReqId, webhooks);
|
|
49180
49396
|
return;
|
|
49181
49397
|
}
|
|
49398
|
+
if (msg.type === "vault_ack") {
|
|
49399
|
+
const reqId = msg._reqId;
|
|
49400
|
+
if (reqId && this.vaultAckResolvers.has(reqId)) {
|
|
49401
|
+
const r = this.vaultAckResolvers.get(reqId);
|
|
49402
|
+
clearTimeout(r.timer);
|
|
49403
|
+
this.vaultAckResolvers.delete(reqId);
|
|
49404
|
+
r.resolve(msg.action !== "not_found");
|
|
49405
|
+
}
|
|
49406
|
+
}
|
|
49407
|
+
if (msg.type === "vault_list_result") {
|
|
49408
|
+
const reqId = msg._reqId;
|
|
49409
|
+
if (reqId && this.vaultListResolvers.has(reqId)) {
|
|
49410
|
+
const r = this.vaultListResolvers.get(reqId);
|
|
49411
|
+
clearTimeout(r.timer);
|
|
49412
|
+
this.vaultListResolvers.delete(reqId);
|
|
49413
|
+
r.resolve(msg.entries ?? []);
|
|
49414
|
+
}
|
|
49415
|
+
}
|
|
49416
|
+
if (msg.type === "mcp_deploy_status") {
|
|
49417
|
+
const reqId = msg._reqId;
|
|
49418
|
+
if (reqId && this.mcpDeployResolvers.has(reqId)) {
|
|
49419
|
+
const r = this.mcpDeployResolvers.get(reqId);
|
|
49420
|
+
clearTimeout(r.timer);
|
|
49421
|
+
this.mcpDeployResolvers.delete(reqId);
|
|
49422
|
+
r.resolve({ status: msg.status, tools: msg.tools, error: msg.error });
|
|
49423
|
+
}
|
|
49424
|
+
}
|
|
49425
|
+
if (msg.type === "mcp_logs_result") {
|
|
49426
|
+
const reqId = msg._reqId;
|
|
49427
|
+
if (reqId && this.mcpLogsResolvers.has(reqId)) {
|
|
49428
|
+
const r = this.mcpLogsResolvers.get(reqId);
|
|
49429
|
+
clearTimeout(r.timer);
|
|
49430
|
+
this.mcpLogsResolvers.delete(reqId);
|
|
49431
|
+
r.resolve(msg.lines ?? []);
|
|
49432
|
+
}
|
|
49433
|
+
}
|
|
49434
|
+
if (msg.type === "mcp_schema_result") {
|
|
49435
|
+
const reqId = msg._reqId;
|
|
49436
|
+
if (reqId && this.mcpSchemaServiceResolvers.has(reqId)) {
|
|
49437
|
+
const r = this.mcpSchemaServiceResolvers.get(reqId);
|
|
49438
|
+
clearTimeout(r.timer);
|
|
49439
|
+
this.mcpSchemaServiceResolvers.delete(reqId);
|
|
49440
|
+
r.resolve(msg.tools ?? []);
|
|
49441
|
+
}
|
|
49442
|
+
}
|
|
49443
|
+
if (msg.type === "mcp_catalog_result") {
|
|
49444
|
+
const reqId = msg._reqId;
|
|
49445
|
+
if (reqId && this.mcpCatalogResolvers.has(reqId)) {
|
|
49446
|
+
const r = this.mcpCatalogResolvers.get(reqId);
|
|
49447
|
+
clearTimeout(r.timer);
|
|
49448
|
+
this.mcpCatalogResolvers.delete(reqId);
|
|
49449
|
+
r.resolve(msg.services ?? []);
|
|
49450
|
+
}
|
|
49451
|
+
}
|
|
49452
|
+
if (msg.type === "mcp_scope_result") {
|
|
49453
|
+
const reqId = msg._reqId;
|
|
49454
|
+
if (reqId && this.mcpScopeResolvers.has(reqId)) {
|
|
49455
|
+
const r = this.mcpScopeResolvers.get(reqId);
|
|
49456
|
+
clearTimeout(r.timer);
|
|
49457
|
+
this.mcpScopeResolvers.delete(reqId);
|
|
49458
|
+
r.resolve({ scope: msg.scope, deployed_by: msg.deployed_by });
|
|
49459
|
+
}
|
|
49460
|
+
}
|
|
49461
|
+
if (msg.type === "skill_deploy_ack") {
|
|
49462
|
+
const reqId = msg._reqId;
|
|
49463
|
+
if (reqId && this.skillDeployResolvers.has(reqId)) {
|
|
49464
|
+
const r = this.skillDeployResolvers.get(reqId);
|
|
49465
|
+
clearTimeout(r.timer);
|
|
49466
|
+
this.skillDeployResolvers.delete(reqId);
|
|
49467
|
+
r.resolve({ name: msg.name, files: msg.files ?? [] });
|
|
49468
|
+
}
|
|
49469
|
+
}
|
|
49182
49470
|
if (msg.type === "error") {
|
|
49183
49471
|
this.debug(`broker error: ${msg.code} ${msg.message}`);
|
|
49184
49472
|
const id = msg.id ? String(msg.id) : null;
|
|
@@ -49232,7 +49520,15 @@ class BrokerClient {
|
|
|
49232
49520
|
[this.peerFileResponseResolvers, { error: "broker error" }],
|
|
49233
49521
|
[this.peerDirResponseResolvers, { error: "broker error" }],
|
|
49234
49522
|
[this.webhookAckResolvers, null],
|
|
49235
|
-
[this.webhookListResolvers, []]
|
|
49523
|
+
[this.webhookListResolvers, []],
|
|
49524
|
+
[this.vaultAckResolvers, false],
|
|
49525
|
+
[this.vaultListResolvers, []],
|
|
49526
|
+
[this.mcpDeployResolvers, { status: "error" }],
|
|
49527
|
+
[this.mcpLogsResolvers, []],
|
|
49528
|
+
[this.mcpSchemaServiceResolvers, []],
|
|
49529
|
+
[this.mcpCatalogResolvers, []],
|
|
49530
|
+
[this.mcpScopeResolvers, { scope: { type: "peer" }, deployed_by: "unknown" }],
|
|
49531
|
+
[this.skillDeployResolvers, { name: "unknown", files: [] }]
|
|
49236
49532
|
];
|
|
49237
49533
|
for (const [map2, defaultVal] of allMaps) {
|
|
49238
49534
|
const first = map2.entries().next().value;
|
|
@@ -49428,6 +49724,10 @@ function formatPush(p, meshSlug) {
|
|
|
49428
49724
|
${body}`;
|
|
49429
49725
|
}
|
|
49430
49726
|
async function startMcpServer() {
|
|
49727
|
+
const serviceIdx = process.argv.indexOf("--service");
|
|
49728
|
+
if (serviceIdx !== -1 && process.argv[serviceIdx + 1]) {
|
|
49729
|
+
return startServiceProxy(process.argv[serviceIdx + 1]);
|
|
49730
|
+
}
|
|
49431
49731
|
const config2 = loadConfig();
|
|
49432
49732
|
const myName = config2.displayName ?? "unnamed";
|
|
49433
49733
|
const myRole = config2.role ?? process.env.CLAUDEMESH_ROLE ?? null;
|
|
@@ -50672,6 +50972,178 @@ ${lines.join(`
|
|
|
50672
50972
|
const ok = await client2.deleteWebhook(delName);
|
|
50673
50973
|
return text(ok ? `Webhook "${delName}" deactivated.` : `Failed to deactivate webhook "${delName}".`, !ok);
|
|
50674
50974
|
}
|
|
50975
|
+
case "vault_set": {
|
|
50976
|
+
const { key, value, type: vType, mount_path, description } = args ?? {};
|
|
50977
|
+
if (!key || !value)
|
|
50978
|
+
return text("vault_set: `key` and `value` required", true);
|
|
50979
|
+
const client2 = allClients()[0];
|
|
50980
|
+
if (!client2)
|
|
50981
|
+
return text("vault_set: not connected", true);
|
|
50982
|
+
const entryType = vType ?? "env";
|
|
50983
|
+
let plaintext = value;
|
|
50984
|
+
if (entryType === "file") {
|
|
50985
|
+
const { existsSync: existsSync2, readFileSync: readFileSync2 } = await import("node:fs");
|
|
50986
|
+
if (!existsSync2(value))
|
|
50987
|
+
return text(`vault_set: file not found: ${value}`, true);
|
|
50988
|
+
plaintext = readFileSync2(value, "base64");
|
|
50989
|
+
}
|
|
50990
|
+
const encoded = Buffer.from(plaintext).toString("base64");
|
|
50991
|
+
const ok = await client2.vaultSet(key, encoded, "placeholder-nonce", "placeholder-sealed", entryType, mount_path, description);
|
|
50992
|
+
if (!ok)
|
|
50993
|
+
return text("vault_set: broker did not acknowledge", true);
|
|
50994
|
+
return text(`Vault entry "${key}" stored (${entryType}).`);
|
|
50995
|
+
}
|
|
50996
|
+
case "vault_list": {
|
|
50997
|
+
const client2 = allClients()[0];
|
|
50998
|
+
if (!client2)
|
|
50999
|
+
return text("vault_list: not connected", true);
|
|
51000
|
+
const entries = await client2.vaultList();
|
|
51001
|
+
if (entries.length === 0)
|
|
51002
|
+
return text("Vault is empty.");
|
|
51003
|
+
const lines = entries.map((e) => `- **${e.key}** (${e.entry_type}${e.mount_path ? ` → ${e.mount_path}` : ""})${e.description ? ` — ${e.description}` : ""} (${e.updated_at})`);
|
|
51004
|
+
return text(`${entries.length} vault entry(s):
|
|
51005
|
+
${lines.join(`
|
|
51006
|
+
`)}`);
|
|
51007
|
+
}
|
|
51008
|
+
case "vault_delete": {
|
|
51009
|
+
const { key } = args ?? {};
|
|
51010
|
+
if (!key)
|
|
51011
|
+
return text("vault_delete: `key` required", true);
|
|
51012
|
+
const client2 = allClients()[0];
|
|
51013
|
+
if (!client2)
|
|
51014
|
+
return text("vault_delete: not connected", true);
|
|
51015
|
+
const ok = await client2.vaultDelete(key);
|
|
51016
|
+
return text(ok ? `Vault entry "${key}" deleted.` : `Vault entry "${key}" not found.`);
|
|
51017
|
+
}
|
|
51018
|
+
case "mesh_mcp_deploy": {
|
|
51019
|
+
const { server_name, file_id, git_url, git_branch, env: deployEnv, runtime, memory_mb, network_allow, scope } = args ?? {};
|
|
51020
|
+
if (!server_name)
|
|
51021
|
+
return text("mesh_mcp_deploy: `server_name` required", true);
|
|
51022
|
+
if (!file_id && !git_url)
|
|
51023
|
+
return text("mesh_mcp_deploy: either `file_id` or `git_url` required", true);
|
|
51024
|
+
const client2 = allClients()[0];
|
|
51025
|
+
if (!client2)
|
|
51026
|
+
return text("mesh_mcp_deploy: not connected", true);
|
|
51027
|
+
const source = file_id ? { type: "zip", file_id } : { type: "git", url: git_url, branch: git_branch };
|
|
51028
|
+
const config3 = {};
|
|
51029
|
+
if (deployEnv)
|
|
51030
|
+
config3.env = deployEnv;
|
|
51031
|
+
if (runtime)
|
|
51032
|
+
config3.runtime = runtime;
|
|
51033
|
+
if (memory_mb)
|
|
51034
|
+
config3.memory_mb = memory_mb;
|
|
51035
|
+
if (network_allow)
|
|
51036
|
+
config3.network_allow = network_allow;
|
|
51037
|
+
const result = await client2.mcpDeploy(server_name, source, Object.keys(config3).length > 0 ? config3 : undefined, scope);
|
|
51038
|
+
const toolList = result.tools?.map((t) => ` - ${t.name}: ${t.description}`).join(`
|
|
51039
|
+
`) ?? " (pending)";
|
|
51040
|
+
return text(`Deployed "${server_name}" (status: ${result.status}).
|
|
51041
|
+
|
|
51042
|
+
Tools:
|
|
51043
|
+
${toolList}
|
|
51044
|
+
|
|
51045
|
+
Default scope: peer (private). Use mesh_mcp_scope to share.`);
|
|
51046
|
+
}
|
|
51047
|
+
case "mesh_mcp_undeploy": {
|
|
51048
|
+
const { server_name } = args ?? {};
|
|
51049
|
+
if (!server_name)
|
|
51050
|
+
return text("mesh_mcp_undeploy: `server_name` required", true);
|
|
51051
|
+
const client2 = allClients()[0];
|
|
51052
|
+
if (!client2)
|
|
51053
|
+
return text("mesh_mcp_undeploy: not connected", true);
|
|
51054
|
+
const ok = await client2.mcpUndeploy(server_name);
|
|
51055
|
+
return text(ok ? `Service "${server_name}" undeployed.` : `Failed to undeploy "${server_name}".`);
|
|
51056
|
+
}
|
|
51057
|
+
case "mesh_mcp_update": {
|
|
51058
|
+
const { server_name } = args ?? {};
|
|
51059
|
+
if (!server_name)
|
|
51060
|
+
return text("mesh_mcp_update: `server_name` required", true);
|
|
51061
|
+
const client2 = allClients()[0];
|
|
51062
|
+
if (!client2)
|
|
51063
|
+
return text("mesh_mcp_update: not connected", true);
|
|
51064
|
+
const result = await client2.mcpUpdate(server_name);
|
|
51065
|
+
return text(`Updated "${server_name}" (status: ${result.status}).`);
|
|
51066
|
+
}
|
|
51067
|
+
case "mesh_mcp_logs": {
|
|
51068
|
+
const { server_name, lines: logLines } = args ?? {};
|
|
51069
|
+
if (!server_name)
|
|
51070
|
+
return text("mesh_mcp_logs: `server_name` required", true);
|
|
51071
|
+
const client2 = allClients()[0];
|
|
51072
|
+
if (!client2)
|
|
51073
|
+
return text("mesh_mcp_logs: not connected", true);
|
|
51074
|
+
const logs = await client2.mcpLogs(server_name, logLines);
|
|
51075
|
+
if (logs.length === 0)
|
|
51076
|
+
return text(`No logs for "${server_name}".`);
|
|
51077
|
+
return text(`Logs for "${server_name}" (${logs.length} lines):
|
|
51078
|
+
\`\`\`
|
|
51079
|
+
${logs.join(`
|
|
51080
|
+
`)}
|
|
51081
|
+
\`\`\``);
|
|
51082
|
+
}
|
|
51083
|
+
case "mesh_mcp_scope": {
|
|
51084
|
+
const { server_name, scope } = args ?? {};
|
|
51085
|
+
if (!server_name)
|
|
51086
|
+
return text("mesh_mcp_scope: `server_name` required", true);
|
|
51087
|
+
const client2 = allClients()[0];
|
|
51088
|
+
if (!client2)
|
|
51089
|
+
return text("mesh_mcp_scope: not connected", true);
|
|
51090
|
+
const result = await client2.mcpScope(server_name, scope);
|
|
51091
|
+
if (scope !== undefined) {
|
|
51092
|
+
return text(`Scope for "${server_name}" updated to: ${JSON.stringify(result.scope)}`);
|
|
51093
|
+
}
|
|
51094
|
+
return text(`**${server_name}** scope: ${JSON.stringify(result.scope)}
|
|
51095
|
+
Deployed by: ${result.deployed_by}`);
|
|
51096
|
+
}
|
|
51097
|
+
case "mesh_mcp_schema": {
|
|
51098
|
+
const { server_name, tool_name } = args ?? {};
|
|
51099
|
+
if (!server_name)
|
|
51100
|
+
return text("mesh_mcp_schema: `server_name` required", true);
|
|
51101
|
+
const client2 = allClients()[0];
|
|
51102
|
+
if (!client2)
|
|
51103
|
+
return text("mesh_mcp_schema: not connected", true);
|
|
51104
|
+
const tools = await client2.mcpServiceSchema(server_name, tool_name);
|
|
51105
|
+
if (tools.length === 0)
|
|
51106
|
+
return text(`No tools found for "${server_name}"${tool_name ? ` (tool: ${tool_name})` : ""}.`);
|
|
51107
|
+
const lines = tools.map((t) => `### ${t.name}
|
|
51108
|
+
${t.description}
|
|
51109
|
+
\`\`\`json
|
|
51110
|
+
${JSON.stringify(t.inputSchema, null, 2)}
|
|
51111
|
+
\`\`\``);
|
|
51112
|
+
return text(`Tools for "${server_name}":
|
|
51113
|
+
|
|
51114
|
+
${lines.join(`
|
|
51115
|
+
|
|
51116
|
+
`)}`);
|
|
51117
|
+
}
|
|
51118
|
+
case "mesh_mcp_catalog": {
|
|
51119
|
+
const client2 = allClients()[0];
|
|
51120
|
+
if (!client2)
|
|
51121
|
+
return text("mesh_mcp_catalog: not connected", true);
|
|
51122
|
+
const services = await client2.mcpCatalog();
|
|
51123
|
+
if (services.length === 0)
|
|
51124
|
+
return text("No services deployed in the mesh.");
|
|
51125
|
+
const lines = services.map((s) => {
|
|
51126
|
+
const scopeStr = typeof s.scope === "string" ? s.scope : JSON.stringify(s.scope);
|
|
51127
|
+
return `- **${s.name}** (${s.type}, ${s.status}) — ${s.description}
|
|
51128
|
+
${s.tool_count} tools | scope: ${scopeStr} | by ${s.deployed_by} | ${s.source_type}${s.runtime ? ` (${s.runtime})` : ""}`;
|
|
51129
|
+
});
|
|
51130
|
+
return text(`${services.length} service(s) in mesh:
|
|
51131
|
+
|
|
51132
|
+
${lines.join(`
|
|
51133
|
+
`)}`);
|
|
51134
|
+
}
|
|
51135
|
+
case "mesh_skill_deploy": {
|
|
51136
|
+
const { file_id, git_url, git_branch } = args ?? {};
|
|
51137
|
+
if (!file_id && !git_url)
|
|
51138
|
+
return text("mesh_skill_deploy: either `file_id` or `git_url` required", true);
|
|
51139
|
+
const client2 = allClients()[0];
|
|
51140
|
+
if (!client2)
|
|
51141
|
+
return text("mesh_skill_deploy: not connected", true);
|
|
51142
|
+
const source = file_id ? { type: "zip", file_id } : { type: "git", url: git_url, branch: git_branch };
|
|
51143
|
+
const result = await client2.skillDeploy(source);
|
|
51144
|
+
return text(`Skill "${result.name}" deployed.
|
|
51145
|
+
Files: ${result.files.join(", ")}`);
|
|
51146
|
+
}
|
|
50675
51147
|
default:
|
|
50676
51148
|
return text(`Unknown tool: ${name}`, true);
|
|
50677
51149
|
}
|
|
@@ -50830,6 +51302,120 @@ ${lines.join(`
|
|
|
50830
51302
|
process.on("SIGTERM", shutdown);
|
|
50831
51303
|
process.on("SIGINT", shutdown);
|
|
50832
51304
|
}
|
|
51305
|
+
async function startServiceProxy(serviceName) {
|
|
51306
|
+
const config2 = loadConfig();
|
|
51307
|
+
if (config2.meshes.length === 0) {
|
|
51308
|
+
process.stderr.write(`[mesh:${serviceName}] no meshes joined
|
|
51309
|
+
`);
|
|
51310
|
+
process.exit(1);
|
|
51311
|
+
}
|
|
51312
|
+
const mesh = config2.meshes[0];
|
|
51313
|
+
const client2 = new BrokerClient(mesh, {
|
|
51314
|
+
displayName: config2.displayName ?? `proxy:${serviceName}`
|
|
51315
|
+
});
|
|
51316
|
+
try {
|
|
51317
|
+
await client2.connect();
|
|
51318
|
+
} catch (e) {
|
|
51319
|
+
process.stderr.write(`[mesh:${serviceName}] broker connect failed: ${e instanceof Error ? e.message : String(e)}
|
|
51320
|
+
`);
|
|
51321
|
+
process.exit(1);
|
|
51322
|
+
}
|
|
51323
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
51324
|
+
let tools = [];
|
|
51325
|
+
try {
|
|
51326
|
+
const fetched = await client2.getServiceTools(serviceName);
|
|
51327
|
+
tools = fetched;
|
|
51328
|
+
} catch {
|
|
51329
|
+
const cached2 = client2.serviceCatalog.find((s) => s.name === serviceName);
|
|
51330
|
+
if (cached2) {
|
|
51331
|
+
tools = cached2.tools;
|
|
51332
|
+
}
|
|
51333
|
+
}
|
|
51334
|
+
if (tools.length === 0) {
|
|
51335
|
+
process.stderr.write(`[mesh:${serviceName}] no tools found — service may not be running
|
|
51336
|
+
`);
|
|
51337
|
+
}
|
|
51338
|
+
const server = new Server({ name: `mesh:${serviceName}`, version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
51339
|
+
server.setRequestHandler(ListToolsRequestSchema, () => ({
|
|
51340
|
+
tools: tools.map((t) => ({
|
|
51341
|
+
name: t.name,
|
|
51342
|
+
description: `[mesh:${serviceName}] ${t.description}`,
|
|
51343
|
+
inputSchema: t.inputSchema
|
|
51344
|
+
}))
|
|
51345
|
+
}));
|
|
51346
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
51347
|
+
const toolName = req.params.name;
|
|
51348
|
+
const args = req.params.arguments ?? {};
|
|
51349
|
+
if (client2.status !== "open") {
|
|
51350
|
+
let waited = 0;
|
|
51351
|
+
while (client2.status !== "open" && waited < 1e4) {
|
|
51352
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
51353
|
+
waited += 500;
|
|
51354
|
+
}
|
|
51355
|
+
if (client2.status !== "open") {
|
|
51356
|
+
return {
|
|
51357
|
+
content: [
|
|
51358
|
+
{
|
|
51359
|
+
type: "text",
|
|
51360
|
+
text: `Service temporarily unavailable — broker reconnecting. Retry in a few seconds.`
|
|
51361
|
+
}
|
|
51362
|
+
],
|
|
51363
|
+
isError: true
|
|
51364
|
+
};
|
|
51365
|
+
}
|
|
51366
|
+
}
|
|
51367
|
+
try {
|
|
51368
|
+
const result = await client2.mcpCall(serviceName, toolName, args);
|
|
51369
|
+
if (result.error) {
|
|
51370
|
+
return {
|
|
51371
|
+
content: [{ type: "text", text: `Error: ${result.error}` }],
|
|
51372
|
+
isError: true
|
|
51373
|
+
};
|
|
51374
|
+
}
|
|
51375
|
+
const resultText = typeof result.result === "string" ? result.result : JSON.stringify(result.result, null, 2);
|
|
51376
|
+
return {
|
|
51377
|
+
content: [{ type: "text", text: resultText }]
|
|
51378
|
+
};
|
|
51379
|
+
} catch (e) {
|
|
51380
|
+
return {
|
|
51381
|
+
content: [
|
|
51382
|
+
{
|
|
51383
|
+
type: "text",
|
|
51384
|
+
text: `Call failed: ${e instanceof Error ? e.message : String(e)}`
|
|
51385
|
+
}
|
|
51386
|
+
],
|
|
51387
|
+
isError: true
|
|
51388
|
+
};
|
|
51389
|
+
}
|
|
51390
|
+
});
|
|
51391
|
+
client2.onPush((push) => {
|
|
51392
|
+
if (push.event === "mcp_undeployed" && push.eventData?.name === serviceName) {
|
|
51393
|
+
process.stderr.write(`[mesh:${serviceName}] service undeployed — exiting
|
|
51394
|
+
`);
|
|
51395
|
+
client2.close();
|
|
51396
|
+
process.exit(0);
|
|
51397
|
+
}
|
|
51398
|
+
if (push.event === "mcp_updated" && push.eventData?.name === serviceName) {
|
|
51399
|
+
const newTools = push.eventData?.tools;
|
|
51400
|
+
if (Array.isArray(newTools)) {
|
|
51401
|
+
tools = newTools;
|
|
51402
|
+
server.notification({
|
|
51403
|
+
method: "notifications/tools/list_changed"
|
|
51404
|
+
}).catch(() => {});
|
|
51405
|
+
}
|
|
51406
|
+
}
|
|
51407
|
+
});
|
|
51408
|
+
const transport = new StdioServerTransport;
|
|
51409
|
+
await server.connect(transport);
|
|
51410
|
+
const keepalive = setInterval(() => {}, 1000);
|
|
51411
|
+
const shutdown = () => {
|
|
51412
|
+
clearInterval(keepalive);
|
|
51413
|
+
client2.close();
|
|
51414
|
+
process.exit(0);
|
|
51415
|
+
};
|
|
51416
|
+
process.on("SIGTERM", shutdown);
|
|
51417
|
+
process.on("SIGINT", shutdown);
|
|
51418
|
+
}
|
|
50833
51419
|
|
|
50834
51420
|
// src/commands/install.ts
|
|
50835
51421
|
init_config();
|
|
@@ -51526,8 +52112,8 @@ async function runHook(args) {
|
|
|
51526
52112
|
// src/commands/launch.ts
|
|
51527
52113
|
init_config();
|
|
51528
52114
|
import { spawn } from "node:child_process";
|
|
51529
|
-
import { mkdtempSync, writeFileSync as writeFileSync4, rmSync, readdirSync, statSync } from "node:fs";
|
|
51530
|
-
import { tmpdir, hostname as hostname2 } from "node:os";
|
|
52115
|
+
import { mkdtempSync, writeFileSync as writeFileSync4, rmSync, readdirSync, statSync, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
52116
|
+
import { tmpdir, hostname as hostname2, homedir as homedir4 } from "node:os";
|
|
51531
52117
|
import { join as join4 } from "node:path";
|
|
51532
52118
|
import { createInterface } from "node:readline";
|
|
51533
52119
|
async function pickMesh(meshes) {
|
|
@@ -51726,6 +52312,44 @@ async function runLaunch(flags, rawArgs) {
|
|
|
51726
52312
|
rmSync(full, { recursive: true, force: true });
|
|
51727
52313
|
}
|
|
51728
52314
|
} catch {}
|
|
52315
|
+
try {
|
|
52316
|
+
const claudeConfigPath = join4(homedir4(), ".claude.json");
|
|
52317
|
+
if (existsSync3(claudeConfigPath)) {
|
|
52318
|
+
const claudeConfig = JSON.parse(readFileSync3(claudeConfigPath, "utf-8"));
|
|
52319
|
+
const mcpServers = claudeConfig.mcpServers ?? {};
|
|
52320
|
+
let cleaned = 0;
|
|
52321
|
+
for (const key of Object.keys(mcpServers)) {
|
|
52322
|
+
if (!key.startsWith("mesh:"))
|
|
52323
|
+
continue;
|
|
52324
|
+
const meta2 = mcpServers[key]?._meshSession;
|
|
52325
|
+
if (!meta2?.pid)
|
|
52326
|
+
continue;
|
|
52327
|
+
try {
|
|
52328
|
+
process.kill(meta2.pid, 0);
|
|
52329
|
+
} catch {
|
|
52330
|
+
delete mcpServers[key];
|
|
52331
|
+
cleaned++;
|
|
52332
|
+
}
|
|
52333
|
+
}
|
|
52334
|
+
if (cleaned > 0) {
|
|
52335
|
+
claudeConfig.mcpServers = mcpServers;
|
|
52336
|
+
writeFileSync4(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
52337
|
+
`, "utf-8");
|
|
52338
|
+
}
|
|
52339
|
+
}
|
|
52340
|
+
} catch {}
|
|
52341
|
+
let serviceCatalog = [];
|
|
52342
|
+
try {
|
|
52343
|
+
const tmpClient = new BrokerClient(mesh, { displayName });
|
|
52344
|
+
await tmpClient.connect();
|
|
52345
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
52346
|
+
serviceCatalog = tmpClient.serviceCatalog;
|
|
52347
|
+
tmpClient.close();
|
|
52348
|
+
} catch {
|
|
52349
|
+
if (!args.quiet) {
|
|
52350
|
+
console.log(" (Could not fetch service catalog — mesh services won't be natively available)");
|
|
52351
|
+
}
|
|
52352
|
+
}
|
|
51729
52353
|
const tmpDir = mkdtempSync(join4(tmpdir(), "claudemesh-"));
|
|
51730
52354
|
const sessionConfig = {
|
|
51731
52355
|
version: 1,
|
|
@@ -51743,6 +52367,50 @@ async function runLaunch(flags, rawArgs) {
|
|
|
51743
52367
|
await confirmPermissions();
|
|
51744
52368
|
}
|
|
51745
52369
|
}
|
|
52370
|
+
const meshMcpEntries = [];
|
|
52371
|
+
if (serviceCatalog.length > 0) {
|
|
52372
|
+
const claudeConfigPath = join4(homedir4(), ".claude.json");
|
|
52373
|
+
let claudeConfig = {};
|
|
52374
|
+
try {
|
|
52375
|
+
claudeConfig = JSON.parse(readFileSync3(claudeConfigPath, "utf-8"));
|
|
52376
|
+
} catch {
|
|
52377
|
+
claudeConfig = {};
|
|
52378
|
+
}
|
|
52379
|
+
const mcpServers = claudeConfig.mcpServers ?? {};
|
|
52380
|
+
const sessionTag = `${process.pid}`;
|
|
52381
|
+
for (const svc of serviceCatalog) {
|
|
52382
|
+
if (svc.status !== "running")
|
|
52383
|
+
continue;
|
|
52384
|
+
const entryKey = `mesh:${svc.name}:${sessionTag}`;
|
|
52385
|
+
const entry = {
|
|
52386
|
+
command: "claudemesh",
|
|
52387
|
+
args: ["mcp", "--service", svc.name],
|
|
52388
|
+
env: {
|
|
52389
|
+
CLAUDEMESH_CONFIG_DIR: tmpDir
|
|
52390
|
+
},
|
|
52391
|
+
_meshSession: {
|
|
52392
|
+
pid: process.pid,
|
|
52393
|
+
meshSlug: mesh.slug,
|
|
52394
|
+
serviceName: svc.name,
|
|
52395
|
+
createdAt: new Date().toISOString()
|
|
52396
|
+
}
|
|
52397
|
+
};
|
|
52398
|
+
mcpServers[entryKey] = entry;
|
|
52399
|
+
meshMcpEntries.push({ key: entryKey, entry });
|
|
52400
|
+
}
|
|
52401
|
+
claudeConfig.mcpServers = mcpServers;
|
|
52402
|
+
writeFileSync4(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
52403
|
+
`, "utf-8");
|
|
52404
|
+
if (!args.quiet && meshMcpEntries.length > 0) {
|
|
52405
|
+
console.log(` ${meshMcpEntries.length} mesh service(s) registered as native MCPs:`);
|
|
52406
|
+
for (const { key } of meshMcpEntries) {
|
|
52407
|
+
const svcName = key.split(":")[1];
|
|
52408
|
+
const svc = serviceCatalog.find((s) => s.name === svcName);
|
|
52409
|
+
console.log(` ${svcName} (${svc?.tools.length ?? 0} tools)`);
|
|
52410
|
+
}
|
|
52411
|
+
console.log("");
|
|
52412
|
+
}
|
|
52413
|
+
}
|
|
51746
52414
|
const filtered = [];
|
|
51747
52415
|
for (let i = 0;i < args.claudeArgs.length; i++) {
|
|
51748
52416
|
if (args.claudeArgs[i] === "--dangerously-load-development-channels" || args.claudeArgs[i] === "--dangerously-skip-permissions") {
|
|
@@ -51767,10 +52435,25 @@ async function runLaunch(flags, rawArgs) {
|
|
|
51767
52435
|
...process.env,
|
|
51768
52436
|
CLAUDEMESH_CONFIG_DIR: tmpDir,
|
|
51769
52437
|
CLAUDEMESH_DISPLAY_NAME: displayName,
|
|
52438
|
+
MCP_TIMEOUT: process.env.MCP_TIMEOUT ?? "30000",
|
|
52439
|
+
MAX_MCP_OUTPUT_TOKENS: process.env.MAX_MCP_OUTPUT_TOKENS ?? "50000",
|
|
51770
52440
|
...role ? { CLAUDEMESH_ROLE: role } : {}
|
|
51771
52441
|
}
|
|
51772
52442
|
});
|
|
51773
52443
|
const cleanup = () => {
|
|
52444
|
+
if (meshMcpEntries.length > 0) {
|
|
52445
|
+
try {
|
|
52446
|
+
const claudeConfigPath = join4(homedir4(), ".claude.json");
|
|
52447
|
+
const claudeConfig = JSON.parse(readFileSync3(claudeConfigPath, "utf-8"));
|
|
52448
|
+
const mcpServers = claudeConfig.mcpServers ?? {};
|
|
52449
|
+
for (const { key } of meshMcpEntries) {
|
|
52450
|
+
delete mcpServers[key];
|
|
52451
|
+
}
|
|
52452
|
+
claudeConfig.mcpServers = mcpServers;
|
|
52453
|
+
writeFileSync4(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
52454
|
+
`, "utf-8");
|
|
52455
|
+
} catch {}
|
|
52456
|
+
}
|
|
51774
52457
|
try {
|
|
51775
52458
|
rmSync(tmpDir, { recursive: true, force: true });
|
|
51776
52459
|
} catch {}
|
|
@@ -51803,12 +52486,12 @@ async function runLaunch(flags, rawArgs) {
|
|
|
51803
52486
|
}
|
|
51804
52487
|
|
|
51805
52488
|
// src/commands/status.ts
|
|
51806
|
-
import { statSync as statSync2, existsSync as
|
|
52489
|
+
import { statSync as statSync2, existsSync as existsSync4 } from "node:fs";
|
|
51807
52490
|
init_config();
|
|
51808
52491
|
// package.json
|
|
51809
52492
|
var package_default = {
|
|
51810
52493
|
name: "claudemesh-cli",
|
|
51811
|
-
version: "0.
|
|
52494
|
+
version: "0.8.1",
|
|
51812
52495
|
description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
|
|
51813
52496
|
keywords: [
|
|
51814
52497
|
"claude-code",
|
|
@@ -51909,7 +52592,7 @@ async function runStatus() {
|
|
|
51909
52592
|
console.log("─".repeat(60));
|
|
51910
52593
|
const configPath = getConfigPath();
|
|
51911
52594
|
let configPerms = "missing";
|
|
51912
|
-
if (
|
|
52595
|
+
if (existsSync4(configPath)) {
|
|
51913
52596
|
const st = statSync2(configPath);
|
|
51914
52597
|
const mode = (st.mode & 511).toString(8).padStart(4, "0");
|
|
51915
52598
|
configPerms = mode === "0600" ? `${mode} ✓` : `${mode} ⚠ (expected 0600)`;
|
|
@@ -51958,8 +52641,8 @@ async function runStatus() {
|
|
|
51958
52641
|
|
|
51959
52642
|
// src/commands/doctor.ts
|
|
51960
52643
|
init_config();
|
|
51961
|
-
import { existsSync as
|
|
51962
|
-
import { homedir as
|
|
52644
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
|
|
52645
|
+
import { homedir as homedir5, platform as platform2 } from "node:os";
|
|
51963
52646
|
import { join as join5 } from "node:path";
|
|
51964
52647
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
51965
52648
|
function checkNode() {
|
|
@@ -51984,8 +52667,8 @@ function checkClaudeOnPath() {
|
|
|
51984
52667
|
};
|
|
51985
52668
|
}
|
|
51986
52669
|
function checkMcpRegistered() {
|
|
51987
|
-
const claudeConfig = join5(
|
|
51988
|
-
if (!
|
|
52670
|
+
const claudeConfig = join5(homedir5(), ".claude.json");
|
|
52671
|
+
if (!existsSync5(claudeConfig)) {
|
|
51989
52672
|
return {
|
|
51990
52673
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
51991
52674
|
pass: false,
|
|
@@ -51993,7 +52676,7 @@ function checkMcpRegistered() {
|
|
|
51993
52676
|
};
|
|
51994
52677
|
}
|
|
51995
52678
|
try {
|
|
51996
|
-
const cfg = JSON.parse(
|
|
52679
|
+
const cfg = JSON.parse(readFileSync4(claudeConfig, "utf-8"));
|
|
51997
52680
|
const registered = Boolean(cfg.mcpServers?.["claudemesh"]);
|
|
51998
52681
|
return {
|
|
51999
52682
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
@@ -52010,8 +52693,8 @@ function checkMcpRegistered() {
|
|
|
52010
52693
|
}
|
|
52011
52694
|
}
|
|
52012
52695
|
function checkHooksRegistered() {
|
|
52013
|
-
const settings = join5(
|
|
52014
|
-
if (!
|
|
52696
|
+
const settings = join5(homedir5(), ".claude", "settings.json");
|
|
52697
|
+
if (!existsSync5(settings)) {
|
|
52015
52698
|
return {
|
|
52016
52699
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
52017
52700
|
pass: false,
|
|
@@ -52019,7 +52702,7 @@ function checkHooksRegistered() {
|
|
|
52019
52702
|
};
|
|
52020
52703
|
}
|
|
52021
52704
|
try {
|
|
52022
|
-
const raw =
|
|
52705
|
+
const raw = readFileSync4(settings, "utf-8");
|
|
52023
52706
|
const has = raw.includes("claudemesh hook ");
|
|
52024
52707
|
return {
|
|
52025
52708
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
@@ -52036,7 +52719,7 @@ function checkHooksRegistered() {
|
|
|
52036
52719
|
}
|
|
52037
52720
|
function checkConfigFile() {
|
|
52038
52721
|
const path = getConfigPath();
|
|
52039
|
-
if (!
|
|
52722
|
+
if (!existsSync5(path)) {
|
|
52040
52723
|
return {
|
|
52041
52724
|
name: "~/.claudemesh/config.json exists and parses",
|
|
52042
52725
|
pass: true,
|
|
@@ -52140,15 +52823,15 @@ async function runDoctor() {
|
|
|
52140
52823
|
|
|
52141
52824
|
// src/commands/welcome.ts
|
|
52142
52825
|
init_config();
|
|
52143
|
-
import { existsSync as
|
|
52144
|
-
import { homedir as
|
|
52826
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
|
|
52827
|
+
import { homedir as homedir6 } from "node:os";
|
|
52145
52828
|
import { join as join6 } from "node:path";
|
|
52146
52829
|
function detectState() {
|
|
52147
|
-
const claudeConfig = join6(
|
|
52830
|
+
const claudeConfig = join6(homedir6(), ".claude.json");
|
|
52148
52831
|
let mcpRegistered = false;
|
|
52149
|
-
if (
|
|
52832
|
+
if (existsSync6(claudeConfig)) {
|
|
52150
52833
|
try {
|
|
52151
|
-
const cfg = JSON.parse(
|
|
52834
|
+
const cfg = JSON.parse(readFileSync5(claudeConfig, "utf-8"));
|
|
52152
52835
|
mcpRegistered = Boolean(cfg.mcpServers?.["claudemesh"]);
|
|
52153
52836
|
} catch {}
|
|
52154
52837
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudemesh-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"prettier": "3.6.2",
|
|
49
49
|
"typescript": "5.9.3",
|
|
50
50
|
"vitest": "4.0.14",
|
|
51
|
-
"@turbostarter/
|
|
51
|
+
"@turbostarter/vitest-config": "0.1.0",
|
|
52
52
|
"@turbostarter/tsconfig": "0.1.0",
|
|
53
53
|
"@turbostarter/prettier-config": "0.1.0",
|
|
54
|
-
"@turbostarter/
|
|
54
|
+
"@turbostarter/eslint-config": "0.1.0"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "bun build src/index.ts --target=node --outfile dist/index.js --banner \"#!/usr/bin/env node\" && chmod +x dist/index.js",
|