{"record":{"id":"8bb567166c5d2672","repo":"tinyhumansai/openhuman","slug":"mcp-server-not-found","errorCode":null,"errorMessage":"MCP server '{}' not found","messagePattern":"MCP server '(.+?)' not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/mcp/registry/store.rs","lineNumber":363,"sourceCode":"    }\n}\n\npub fn get_server(config: &Config, server_id: &str) -> Result<InstalledServer> {\n    with_connection(config, |conn| get_server_conn(conn, server_id))\n}\n\npub fn get_server_conn(conn: &Connection, server_id: &str) -> Result<InstalledServer> {\n    let mut stmt = conn.prepare(\n        \"SELECT server_id, qualified_name, display_name, description, icon_url,\n                command_kind, command, args_json, env_keys_json, config_json,\n                installed_at, last_connected_at, transport, deployment_url, enabled\n         FROM mcp_servers WHERE server_id = ?1\",\n    )?;\n    let mut rows = stmt.query(params![server_id])?;\n    if let Some(row) = rows.next()? {\n        map_server_row(row).map_err(Into::into)\n    } else {\n        anyhow::bail!(\"MCP server '{}' not found\", server_id)\n    }\n}\n\npub fn delete_server(config: &Config, server_id: &str) -> Result<bool> {\n    with_connection(config, |conn| {\n        let changed = conn\n            .execute(\n                \"DELETE FROM mcp_servers WHERE server_id = ?1\",\n                params![server_id],\n            )\n            .context(\"Failed to delete mcp_server\")?;\n        Ok(changed > 0)\n    })\n}\n\npub fn update_last_connected(config: &Config, server_id: &str) -> Result<()> {\n    let ts = now_ms();\n    with_connection(config, |conn| {","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/mcp/registry/store.rs#L345-L381","documentation":"A SQLite lookup by primary key — get_server_conn(conn, server_id) against the mcp_servers table in the registry database — found no row, and the id string is echoed in the message. It means the id is stale (the server was uninstalled), foreign (belongs to a different workspace/profile database), or simply mistyped. The read-only SELECT means no state changed.","triggerScenarios":"Calling get_server/get_server_conn (directly or via an RPC/agent tool that resolves an installed MCP server) with a server_id that is absent: a UI list out of sync after an uninstall elsewhere, a flow or agent holding a previously captured id, a hand-written RPC with a wrong id, or a different workspace pointing at a different database file.","commonSituations":"Stale frontend state after uninstall; multi-profile workspaces where each profile has its own DB; automations referencing deleted servers; ids copied between environments.","solutions":["List the installed servers (store::list_servers(config) or the mcp_clients list RPC) and use a fresh id.","If the server should exist, reinstall it from the catalog and note the new id.","Remove stale references (flows, saved tool configs, UI state) that still point at the deleted id."],"exampleFix":"// before\nlet server = store::get_server(config, \"srv_abc123\")?; // bails: not found\n\n// after — validate against the live table first\nlet installed = store::list_servers(config)?;\nlet server = installed.into_iter().find(|s| s.server_id == \"srv_abc123\")\n    .ok_or_else(|| anyhow::anyhow!(\"server 'srv_abc123' not installed — reinstall it\"))?;","handlingStrategy":"validation","validationCode":"// Check existence against the live table before the point lookup\nlet exists = store::list_servers(config)?.iter().any(|s| s.server_id == server_id);\nif !exists {\n    // refresh the UI list / offer reinstall instead of calling get_server\n}","typeGuard":null,"tryCatchPattern":"Catch the bail and treat `not found` as a data-staleness signal: refresh the installed-server list, reconcile or drop the reference. Do not blind-retry the same id — nothing will create it.","preventionTips":["Refresh installed-server lists after uninstall operations.","Key automations on qualified_name (stable across reinstalls) rather than server_id (per-install).","Keep UI state scoped to the same workspace/profile database as the RPC calls."],"tags":["mcp","sqlite","not-found","registry"],"backgroundTag":"record-not-found","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}