@myvillage/cli 1.21.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;
|
|
@@ -152,8 +168,18 @@ export async function agentLoop(agentName, { signal }) {
|
|
|
152
168
|
mentionsFound = contextResult.mentionsCount;
|
|
153
169
|
|
|
154
170
|
if (activeTask) {
|
|
155
|
-
|
|
156
|
-
context
|
|
171
|
+
// A claimed task takes over the iteration. The default monitoring
|
|
172
|
+
// context becomes secondary background; the instruction is the
|
|
173
|
+
// primary user prompt and the system prompt switches to a
|
|
174
|
+
// task-execution framing so the LLM doesn't drift back into
|
|
175
|
+
// "report on the feed" mode.
|
|
176
|
+
const instructionText = activeTask.instruction
|
|
177
|
+
|| (activeTask.input ? JSON.stringify(activeTask.input, null, 2) : '');
|
|
178
|
+
|
|
179
|
+
systemPrompt = `${systemPrompt}\n\n## ACTIVE TASK MODE\nA client has assigned you a task. Your job this iteration is to execute the instruction below using your available tools. The feed context is provided only for situational awareness — do not let "no new feed activity" prevent you from carrying out the task.`;
|
|
180
|
+
|
|
181
|
+
context = `## TASK (id=${activeTask.id}, type=${activeTask.taskType})\n${instructionText}\n\n---\n\n## FEED CONTEXT (for awareness only)\n${context}`;
|
|
182
|
+
|
|
157
183
|
logActivity(agentDir, { type: 'task_claimed', taskId: activeTask.id, taskType: activeTask.taskType });
|
|
158
184
|
}
|
|
159
185
|
|
|
@@ -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() {
|