{"record":{"id":"cae2d44bb2e62a03","repo":"moeru-ai/airi","slug":"mcp-server-is-not-running-servername","errorCode":null,"errorMessage":"mcp server is not running: ${serverName}","messagePattern":"mcp server is not running: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/stage-tamagotchi/src/main/services/airi/mcp-servers/index.ts","lineNumber":281,"sourceCode":"          toolName: item.name,\n          description: item.description,\n          inputSchema: item.inputSchema,\n        }))\n      }\n      catch (error) {\n        log.withFields({ serverName }).withError(error).warn('failed to list tools from mcp server')\n        return []\n      }\n    }))\n\n    return listResult.flat()\n  }\n\n  const callTool = async (payload: ElectronMcpCallToolPayload): Promise<ElectronMcpCallToolResult> => {\n    const { serverName, toolName } = parseQualifiedToolName(payload.name)\n    const session = sessions.get(serverName)\n    if (!session) {\n      throw new Error(`mcp server is not running: ${serverName}`)\n    }\n\n    let result\n    try {\n      result = await session.client.callTool({\n        name: toolName,\n        arguments: payload.arguments ?? {},\n      }, undefined, {\n        timeout: mcpRequestTimeoutMsec,\n        maxTotalTimeout: mcpRequestMaxTotalTimeoutMsec,\n      })\n    }\n    catch (error) {\n      const fallbackToolName = resolveFallbackToolName(toolName)\n      if (!fallbackToolName || fallbackToolName === toolName) {\n        throw error\n      }\n","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/apps/stage-tamagotchi/src/main/services/airi/mcp-servers/index.ts#L263-L299","documentation":"Thrown by the MCP (Model Context Protocol) server manager's callTool when parseQualifiedToolName extracts a serverName that has no entry in the live sessions map. The sessions map is populated when an MCP server is started and removed when it stops or crashes, so the error means the referenced server is not currently connected.","triggerScenarios":"Calling ElectronMcpCallToolPayload with a qualified tool name like 'myServer.someTool' when 'myServer' was never started, was started and then stopped, or crashed silently. Also triggered if the serverName is misspelled or uses the wrong separator (parseQualifiedToolName splits on toolNameSeparator).","commonSituations":"The MCP server process exited or was restarted between tool listing and tool call; the user disabled a server in config but the renderer still holds a cached tool list; a server failed health checks and was evicted from the sessions map; the separator in the qualified name doesn't match toolNameSeparator.","solutions":["Check whether the server is in the running state by inspecting the MCP servers status list before issuing the call.","Restart or re-enable the MCP server named in the error, then retry the tool call.","Verify the payload.name uses the correct qualified format 'serverName<separator>toolName' matching the configured toolNameSeparator.","If the server crashes repeatedly, inspect lastError in the server status to find the root cause of the process exit."],"exampleFix":"// before\nconst result = await callTool({ name: 'myServer.search', arguments: { q } })\n\n// after\nconst status = await listServers()\nif (!status.some(s => s.name === 'myServer' && s.status === 'running')) {\n  await startServer('myServer')\n}\nconst result = await callTool({ name: 'myServer.search', arguments: { q } })","handlingStrategy":"validation","validationCode":"// Check the server is running before calling a tool\nconst servers = await listMcpServers()\nconst running = servers.some(s => s.name === serverName && s.status === 'running')\nif (!running) {\n  await startMcpServer(serverName)\n}","typeGuard":"function isRunningServer(s: { status?: string }): boolean {\n  return s.status === 'running'\n}","tryCatchPattern":"try {\n  return await callTool(payload)\n} catch (e) {\n  if (/mcp server is not running/.test(errorMessageFrom(e) ?? '')) {\n    await startMcpServer(serverName)\n    return await callTool(payload)\n  }\n  throw e\n}","preventionTips":["Refresh the cached tool list whenever the server lifecycle changes (start/stop/crash) so callers don't hold stale server names.","Expose a 'isServerRunning(name)' check next to callTool so callers can gate calls.","Listen for server-stopped events and disable UI affordances that target that server."],"tags":["mcp","ipc","process-lifecycle","extensions"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}