fix: improve MCP tool probing reliability

- Increase default probe timeout from 10s to 30s to handle slow
  package managers (uvx, npx) that install on first run
- Add console logging for probe success/failure to aid debugging
- Probe manually configured MCP servers (not just discovered ones)
  so all servers with wildcard tools get their tools discovered

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-28 19:30:42 +01:00
co-authored by Copilot
parent 8312a47bf1
commit b4b0bf54d2
2 changed files with 33 additions and 2 deletions
+28
View File
@@ -2130,10 +2130,14 @@ export class AryxAppService extends EventEmitter<AppServiceEvents> {
}
private async probeAllAcceptedMcpServers(workspace: WorkspaceState): Promise<void> {
// Probe discovered MCP servers (from config files)
await this.probeDiscoveredMcpServersFromState(workspace.settings.discoveredUserTooling);
for (const project of workspace.projects) {
await this.probeDiscoveredMcpServersFromState(project.discoveredTooling);
}
// Probe manually configured MCP servers that have empty tools arrays
await this.probeManualMcpServers(workspace);
}
private async probeDiscoveredMcpServersFromState(
@@ -2185,6 +2189,30 @@ export class AryxAppService extends EventEmitter<AppServiceEvents> {
}
}
private async probeManualMcpServers(workspace: WorkspaceState): Promise<void> {
const manualServers = workspace.settings.tooling.mcpServers.filter(
(server) => server.tools.length === 0 && (!server.probedTools || server.probedTools.length === 0),
);
if (manualServers.length === 0) return;
const tokenLookup = (url: string) => getStoredToken(url)?.accessToken;
const results = await probeServers(manualServers, tokenLookup);
let changed = false;
for (const result of results) {
if (result.status !== 'success' || result.tools.length === 0) continue;
const server = workspace.settings.tooling.mcpServers.find((s) => s.id === result.serverId);
if (server) {
server.probedTools = result.tools;
changed = true;
}
}
if (changed) {
await this.persistAndBroadcast(workspace);
}
}
private discoveredServerToDefinition(server: DiscoveredMcpServer): McpServerDefinition {
if (server.transport === 'local') {
return {
+5 -2
View File
@@ -19,7 +19,7 @@ export interface McpProbeResult {
}
const CLIENT_INFO = { name: 'aryx', version: '1.0.0' };
const DEFAULT_TIMEOUT_MS = 10_000;
const DEFAULT_TIMEOUT_MS = 30_000;
const MAX_CONCURRENCY = 5;
export async function probeServers(
@@ -65,6 +65,7 @@ export async function probeServer(
`Probe timed out after ${timeoutMs}ms`,
);
console.log(`[aryx mcp-probe] ${server.name}: discovered ${tools.length} tool(s)`);
return {
serverId: server.id,
serverName: server.name,
@@ -72,12 +73,14 @@ export async function probeServer(
status: 'success',
};
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
console.warn(`[aryx mcp-probe] ${server.name}: failed — ${message}`);
return {
serverId: server.id,
serverName: server.name,
tools: [],
status: 'failed',
error: error instanceof Error ? error.message : String(error),
error: message,
};
}
}