Files
ailine/backend/app/mcp/adapters/contact_adapter.py
root 9c53f58165
All checks were successful
构建并部署 AI Agent 服务 / deploy (push) Successful in 5m38s
feat: 集成MCP统一外部接口管理系统
- 添加MCP Manager统一入口管理
- 实现Contact/Dictionary/News三个适配器
- 三层降级策略:MCP -> Database -> Mock
- 保持原有api_client向后兼容
- 添加完整文档和测试
2026-05-03 12:36:12 +08:00

198 lines
6.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
通讯录适配器
整合MCP、数据库和模拟数据
"""
from typing import Dict, Any, Optional, List
from datetime import datetime
from dataclasses import dataclass
from .base_adapter import BaseAdapter, AdapterResult
@dataclass
class Contact:
"""简单的Contact数据结构独立版本"""
id: str = ""
name: str = ""
phone: str = ""
email: str = ""
company: str = ""
position: str = ""
created_at: str = ""
@dataclass
class Email:
"""简单的Email数据结构独立版本"""
id: str = ""
subject: str = ""
sender: str = ""
recipients: List[str] = None
date: str = ""
body: str = ""
def __post_init__(self):
if self.recipients is None:
self.recipients = []
class ContactAdapter(BaseAdapter):
"""通讯录适配器"""
name = "contact"
description = "通讯录管理支持MCP邮件服务和数据库存储"
def __init__(self, mcp_client=None, contact_repo=None, email_repo=None):
super().__init__(mcp_client, contact_repo)
self.email_repo = email_repo
self._mock_db = {}
self._mock_emails = []
async def execute(self, action: str, **kwargs) -> AdapterResult:
"""统一执行入口"""
# 优先使用缓存
user_id = kwargs.get("user_id", "default")
# 1. 尝试MCP调用
if self.mcp_client and self.mcp_client.is_available():
try:
mcp_result = await self._execute_mcp(action, **kwargs)
if mcp_result.success:
return mcp_result
except Exception as e:
print(f"[Contact] MCP调用失败: {e}")
# 2. 尝试数据库
if self.repository:
try:
db_result = await self._execute_db(action, **kwargs)
if db_result.success:
return db_result
except Exception as e:
print(f"[Contact] 数据库调用失败: {e}")
# 3. 降级到模拟数据
return self._fallback(action, **kwargs)
async def _execute_mcp(self, action: str, **kwargs) -> AdapterResult:
"""通过MCP执行"""
if action == "list_emails":
result = await self.mcp_client.call_tool(
"email_list_emails",
{}
)
if result.get("success"):
return AdapterResult(
success=True,
data=result["result"],
source="mcp_email"
)
elif action == "send_email":
result = await self.mcp_client.call_tool(
"email_send_email",
{
"to": kwargs.get("recipient", ""),
"subject": kwargs.get("subject", ""),
"body": kwargs.get("body", "")
}
)
if result.get("success"):
return AdapterResult(
success=True,
data=result["result"],
source="mcp_email"
)
return AdapterResult(success=False, error="不支持的MCP操作")
async def _execute_db(self, action: str, **kwargs) -> AdapterResult:
"""通过数据库执行"""
if not self.repository:
return AdapterResult(success=False, error="No database repository")
try:
# 数据库操作(可选功能)
return AdapterResult(success=False, error="Database not implemented yet")
except Exception as e:
print(f"[Contact] 数据库调用失败: {e}")
return AdapterResult(success=False, error=str(e))
def _get_mock_data(self, action: str, **kwargs) -> Any:
"""获取模拟数据"""
user_id = kwargs.get("user_id", "default")
if action == "list_contacts":
if user_id not in self._mock_db:
self._mock_db[user_id] = [
Contact(
id="1",
name="张三",
phone="13800138000",
email="zhangsan@example.com",
company="科技公司",
position="工程师",
created_at=datetime.now().isoformat()
),
Contact(
id="2",
name="李四",
phone="13900139000",
email="lisi@example.com",
company="贸易公司",
position="经理",
created_at=datetime.now().isoformat()
)
]
return self._mock_db[user_id]
elif action == "list_emails":
if not self._mock_emails:
self._mock_emails = [
Email(
id="1",
subject="会议邀请AI 技术分享",
sender="admin@example.com",
recipients=["user@example.com"],
date=datetime.now().isoformat(),
body="你好,下周一将举办 AI 技术分享会,欢迎参加。"
)
]
return self._mock_emails
elif action == "add_contact":
contact = kwargs.get("contact")
if user_id not in self._mock_db:
self._mock_db[user_id] = []
if contact and not contact.id:
contact.id = str(len(self._mock_db[user_id]) + 1)
if contact:
self._mock_db[user_id].append(contact)
return True
elif action == "generate_email_draft":
query = kwargs.get("query", "")
return {
"subject": f"Re: {query}",
"recipient": "recipient@example.com",
"body": "你好,\n\n这是一封自动生成的邮件草稿。\n\n此致,\n你的助手"
}
elif action == "sniff_contacts":
query = kwargs.get("query", "")
import re
emails = re.findall(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}', query)
phones = re.findall(r'1[3-9]\d{9}', query)
contacts = []
for i, email in enumerate(emails):
contacts.append(Contact(
id=str(i+1),
name=f"联系人{i+1}",
phone=phones[i] if i < len(phones) else "",
email=email,
company="",
position="",
created_at=datetime.now().isoformat()
))
return contacts
return None