# -*- coding: utf-8 -*-
"""
MCP配置管理模块
用于从MCP客户端配置中读取API密钥等敏感信息
"""
import os
import json
import logging
from typing import Optional, Dict, Any
from pathlib import Path
class MCPConfigManager:
"""MCP配置管理器"""
def __init__(self, logger: Optional[logging.Logger] = None):
self.logger = logger or logging.getLogger(__name__)
self._config_cache: Optional[Dict[str, Any]] = None
self._config_paths = [
# Claude Desktop 配置路径
Path.home() / ".config" / "claude-desktop" / "config.json",
Path.home() / ".config" / "claude" / "config.json",
# 其他可能的配置路径
Path.home() / ".claude" / "config.json",
# 环境变量指定的路径
Path(os.getenv('CLAUDE_CONFIG_PATH', '')) if os.getenv('CLAUDE_CONFIG_PATH') else None
]
# 过滤掉不存在的路径
self._config_paths = [p for p in self._config_paths if p is not None and p.exists()]
def load_mcp_config(self) -> Dict[str, Any]:
"""加载MCP配置文件"""
if self._config_cache is not None:
return self._config_cache
for config_path in self._config_paths:
try:
with open(config_path, 'r', encoding='utf-8') as f:
config = json.load(f)
# 查找 article-mcp 服务配置
mcp_servers = config.get('mcpServers', {})
article_mcp_config = mcp_servers.get('article-mcp', {})
# 提取环境变量配置
env_config = article_mcp_config.get('env', {})
# 缓存配置
self._config_cache = env_config
self.logger.info(f"成功加载MCP配置: {config_path}")
return env_config
except (json.JSONDecodeError, FileNotFoundError, PermissionError) as e:
self.logger.debug(f"配置文件 {config_path} 读取失败: {e}")
continue
# 如果没有找到配置文件,返回空字典
self._config_cache = {}
self.logger.info("未找到MCP配置文件,将使用环境变量")
return {}
def get_easyscholar_key(self, param_key: Optional[str] = None) -> Optional[str]:
"""获取EasyScholar密钥,按优先级返回
优先级顺序:
1. MCP配置文件中的密钥
2. 函数参数中的密钥
3. 环境变量中的密钥
"""
# 1. 从MCP配置获取
mcp_config = self.load_mcp_config()
config_key = mcp_config.get('EASYSCHOLAR_SECRET_KEY')
if config_key:
self.logger.info("使用MCP配置中的EasyScholar密钥")
return config_key
# 2. 从函数参数获取
if param_key:
self.logger.info("使用函数参数中的EasyScholar密钥")
return param_key
# 3. 从环境变量获取
env_key = os.getenv('EASYSCHOLAR_SECRET_KEY')
if env_key:
self.logger.info("使用环境变量中的EasyScholar密钥")
return env_key
self.logger.debug("未找到EasyScholar密钥")
return None
def get_config_info(self) -> Dict[str, Any]:
"""获取配置信息(用于调试)"""
mcp_config = self.load_mcp_config()
return {
"config_paths": [str(p) for p in self._config_paths],
"config_loaded": bool(mcp_config),
"has_easyscholar_key": bool(mcp_config.get('EASYSCHOLAR_SECRET_KEY')),
"easyscholar_key_from_env": bool(os.getenv('EASYSCHOLAR_SECRET_KEY')),
"config_content": {k: "***" if "key" in k.lower() else v for k, v in mcp_config.items()}
}
# 全局配置管理器实例
_config_manager: Optional[MCPConfigManager] = None
def get_config_manager(logger: Optional[logging.Logger] = None) -> MCPConfigManager:
"""获取全局配置管理器实例"""
global _config_manager
if _config_manager is None:
_config_manager = MCPConfigManager(logger)
return _config_manager
def get_easyscholar_key(param_key: Optional[str] = None, logger: Optional[logging.Logger] = None) -> Optional[str]:
"""获取EasyScholar密钥的便捷函数"""
manager = get_config_manager(logger)
return manager.get_easyscholar_key(param_key)
def reset_config_cache():
"""重置配置缓存(用于测试)"""
global _config_manager
_config_manager = None