{"record":{"id":"bbc30444326be713","repo":"Hmbown/CodeWhale","slug":"oauth-storage-is-disabled-for-plugin-contributed-m","errorCode":null,"errorMessage":"OAuth storage is disabled for plugin-contributed MCP servers","messagePattern":"OAuth storage is disabled for plugin-contributed MCP servers","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/mcp/oauth.rs","lineNumber":558,"sourceCode":"    OauthLoginFlow::new(\n        server_name,\n        server_url,\n        http_headers,\n        env_headers,\n        scopes,\n        oauth_client_id,\n        oauth_resource,\n        callback_port,\n        callback_url,\n    )\n    .await?\n    .finish()\n    .await\n}\n\npub fn delete_oauth_tokens_for_server(name: &str, server: &McpServerConfig) -> Result<bool> {\n    if server.reviewed_plugin.is_some() {\n        bail!(\"OAuth storage is disabled for plugin-contributed MCP servers\");\n    }\n    let Some(url) = server.url.as_deref() else {\n        bail!(\"OAuth logout is only supported for URL-based MCP servers\");\n    };\n    delete_oauth_tokens(name, url)\n}\n\nfn server_has_manual_authorization(server: &McpServerConfig) -> bool {\n    server.bearer_token_env_var.is_some()\n        || contains_authorization_header(&server.headers)\n        || contains_authorization_header(&server.env_headers)\n}\n\npub fn build_default_headers(\n    http_headers: &HashMap<String, String>,\n    env_headers: &HashMap<String, String>,\n) -> Result<HeaderMap> {\n    let mut headers = HeaderMap::new();","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/mcp/oauth.rs#L540-L576","documentation":"delete_oauth_tokens_for_server refuses to operate when server.reviewed_plugin is Some (oauth.rs:558). OAuth tokens for plugin-contributed MCP servers are deliberately never persisted in user token storage, so there is nothing to delete, and the guard also prevents a plugin-defined server name from touching the user's OAuth storage keys.","triggerScenarios":"Invoking MCP logout / token deletion on a server entry whose reviewed_plugin field is populated, i.e. one that was installed and reviewed as part of a plugin rather than user config.","commonSituations":"A plugin installed an MCP server and the user tries /mcp logout on it expecting stored tokens; cleanup scripts iterating all configured servers and calling delete_oauth_tokens_for_server on each; auditing where credentials live for plugin servers.","solutions":["Accept that no user-side tokens exist — the plugin manages its server's credentials itself","To fully reset a plugin-contributed server, disable or uninstall the contributing plugin and re-enable it","If the server must use user-managed OAuth, define your own server entry with the same url instead of relying on the plugin's"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if server.reviewed_plugin.is_some() {\n    // plugin-managed server: no user-side OAuth tokens exist; nothing to delete\n    return Ok(false);\n}","typeGuard":"fn is_plugin_contributed(server: &McpServerConfig) -> bool {\n    server.reviewed_plugin.is_some()\n}","tryCatchPattern":null,"preventionTips":["Hide logout/delete-token actions for plugin-contributed servers","Audit credential ownership per server at install time: user config vs plugin","For user-managed OAuth on the same endpoint, define your own server entry with the url"],"tags":["oauth","mcp","plugin","token-storage"],"backgroundTag":"oauth-storage-disabled","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}