@myvillage/cli 1.22.0 → 1.23.0
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/package.json
CHANGED
|
@@ -66,11 +66,27 @@ export async function agentLoop(agentName, { signal }) {
|
|
|
66
66
|
// Initialize MCP tools
|
|
67
67
|
let tools;
|
|
68
68
|
try {
|
|
69
|
-
|
|
69
|
+
const result = await getMCPTools(agentDir, config);
|
|
70
|
+
tools = result.tools;
|
|
71
|
+
const servers = result.servers;
|
|
72
|
+
const totalTools = Object.keys(tools).length;
|
|
73
|
+
const failed = servers.filter(s => s.status === 'failed');
|
|
74
|
+
|
|
70
75
|
logActivity(agentDir, {
|
|
71
|
-
type: '
|
|
72
|
-
|
|
76
|
+
type: 'loaded_tools',
|
|
77
|
+
model: modelId,
|
|
78
|
+
totalTools,
|
|
79
|
+
servers,
|
|
73
80
|
});
|
|
81
|
+
|
|
82
|
+
// Surface failed MCP connections as an error event too, so they show up
|
|
83
|
+
// in the activity panel's error filter — easy to miss in the success log.
|
|
84
|
+
if (failed.length > 0) {
|
|
85
|
+
logActivity(agentDir, {
|
|
86
|
+
type: 'error',
|
|
87
|
+
error: `Failed to load ${failed.length} MCP server(s): ${failed.map(s => `${s.name} (${s.error})`).join('; ')}`,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
74
90
|
} catch (err) {
|
|
75
91
|
logActivity(agentDir, { type: 'error', error: `Failed to initialize tools: ${err.message}` });
|
|
76
92
|
throw err;
|
|
@@ -20,13 +20,21 @@ export async function getMCPTools(agentDir, agentConfig) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const allTools = {};
|
|
23
|
+
// Per-server connection status. Returned alongside `tools` so the agent
|
|
24
|
+
// loop can surface failed MCP connections in the activity log — without
|
|
25
|
+
// this, a developer whose `filesystem` MCP fails to spawn sees a silent
|
|
26
|
+
// agent that "refuses" file tasks and has no way to know why.
|
|
27
|
+
const servers = [];
|
|
23
28
|
|
|
24
29
|
for (const [name, server] of Object.entries(toolsConfig.servers || {})) {
|
|
25
30
|
if (server.command === 'internal') {
|
|
26
31
|
// Legacy internal tools — skip (replaced by MCP server)
|
|
32
|
+
servers.push({ name, status: 'skipped', reason: 'legacy internal' });
|
|
27
33
|
continue;
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
const transport = server.url ? 'sse' : 'stdio';
|
|
37
|
+
|
|
30
38
|
try {
|
|
31
39
|
const { experimental_createMCPClient: createMCPClient } = await import('ai');
|
|
32
40
|
let client;
|
|
@@ -61,14 +69,29 @@ export async function getMCPTools(agentDir, agentConfig) {
|
|
|
61
69
|
|
|
62
70
|
activeClients.push(client);
|
|
63
71
|
const tools = await client.tools();
|
|
72
|
+
const toolNames = Object.keys(tools);
|
|
64
73
|
Object.assign(allTools, tools);
|
|
74
|
+
servers.push({
|
|
75
|
+
name,
|
|
76
|
+
transport,
|
|
77
|
+
status: 'connected',
|
|
78
|
+
toolCount: toolNames.length,
|
|
79
|
+
toolNames,
|
|
80
|
+
});
|
|
65
81
|
} catch (err) {
|
|
66
82
|
// Log but don't fail — agent can still work with other tools
|
|
67
|
-
|
|
83
|
+
const message = err?.message || String(err);
|
|
84
|
+
console.error(`[mcp-client] Failed to connect to ${name}: ${message}`);
|
|
85
|
+
servers.push({
|
|
86
|
+
name,
|
|
87
|
+
transport,
|
|
88
|
+
status: 'failed',
|
|
89
|
+
error: message,
|
|
90
|
+
});
|
|
68
91
|
}
|
|
69
92
|
}
|
|
70
93
|
|
|
71
|
-
return allTools;
|
|
94
|
+
return { tools: allTools, servers };
|
|
72
95
|
}
|
|
73
96
|
|
|
74
97
|
export async function cleanupMCPClients() {
|