多代理客户支持系统(谷歌ADK+MCP+SQLite)
该项目实现了端到端 多代理客户支持系统 使用:
- 谷歌代理开发工具包(ADK) 用于多代理编排
- 一种模型上下文协议(MCP)HTTP服务器 公开数据库工具
- SQLite数据库 用于客户+票务数据(
support.db) - 哔哔 使MCP服务器可从ADK公开访问
- 三个概念代理:
- 路由器代理 –理解意图并路由请求 - 客户数据代理 –调用MCP工具读取/更新数据库 - 支援谍员 –处理账单问题、升级和升级
该系统会遍历现实的客户支持场景,例如:
- 获取客户资料
- 升级帐户
- 寻找持有未结门票的活跃客户
- 处理重复账单和退款
- 更新联系信息并总结票务历史
______________________________________________________________________
1.项目文件
此存储库具有 扁平结构 (由Colab创建):
.
├── README.md # This file
├── requirements.txt # Python dependencies
├── database_setup.py # Script to create and seed support.db
├── mcp_server.ipynb # Colab/Jupyter notebook: MCP server + ngrok tunnel
└── a2a.ipynb # Colab/Jupyter notebook: ADK multi-agent demo每个文件的作用
database_setup.py
- 创建 support.db (SQLite数据库)。
- 构建 customers 和 tickets 桌子。
- 可选择插入演示中使用的样本客户+门票。
mcp_server.ipynb
- 定义低级SQLite帮助程序(get_db_connection, row_to_dict等等)。
- 实现Python函数:
- get_customer
- list_customers
- update_customer
- create_ticket
- get_customer_history
- 将这些功能包装为 MCP工具.
- 开始a Flask HTTP服务器 带着一个 /mcp 通过服务器发送事件(SSE)传输MCP的端点。
- 用途 吸烟 将本地服务器公开为 https://.ngrok-free.dev/mcp.
- 包括一个发送 initialize MCP请求通过 requests 并打印服务器的响应。
a2a.ipynb
- 配置 MCP工具集 在Google ADK中指向MCP URL。
- 定义 客户数据代理 (LlmAgent)它使用MCP工具。
- 定义 路由器代理 和 支援谍员 加上辅助函数,如 ask_agent_team(...).
- 运行任务的演示场景(客户查找、升级帮助、打开工单、计费问题、电子邮件更新+ 历史)。
- 打印详细信息 代理事件跟踪 对于每种情况。
2.要求
所有Python依赖项都列在 requirements.txt. 典型的库包括:
google-adk(代理开发工具包)
a2a(代理对代理协议)
flask,flask-cors
requests,python-dotenv,termcolor,pyngrok
- 标准Python库(已包含在Python运行时中)
创建虚拟环境后安装它们(见下文)。
3.设置和安装
您可以运行此项目 本地 (推荐用于README)或完全在 Colab (最初开发的)。
3.1克隆存储库
git clone https://github.com//.git
cd 3.2创建和激活虚拟环境
python3 -m venv .venv
source .venv/bin/activate # macOS / Linux
# .venv\Scripts\activate # Windows3.3安装要求
pip install -r requirements.txt3.4设置您的OpenAI API密钥
您可以导出它:
export OPENAI_API_KEY="your-openai-key-here"或创建 .env repo根目录中的文件:
OPENAI_API_KEY=your-openai-key-here4.步骤1-初始化SQLite数据库
从存储库根运行安装脚本:
python database_setup.py出现提示时:
Would you like to insert sample data? (y/n): y这将创建一个 support.db 文件与以下文件位于同一目录中:
- A.
customers表(id、姓名、电子邮件、电话、状态、时间戳)
- A.
tickets表(id、customer_id、问题、状态、优先级、created_at)
- 演示场景中使用的示例客户和门票历史记录
您可以通过以下方式验证它是否存在:
ls
# You should see: database_setup.py, a2a.ipynb, mcp_server.ipynb, support.db, etc.5.步骤2–运行MCP服务器笔记本
MCP服务器在内部运行 mcp_server.ipynb.
5.1打开笔记本
您可以在以下位置打开它:
- Colab (从GitHub上传repo/sync),或
- Jupyter/VS代码 当地。
5.2按顺序运行单元格
在 mcp_server.ipynb:
1.进口和配置
- `sqlite3`, `flask`, `flask_cors`, `requests`, `termcolor`, `pyngrok`, etc.
- `DB_PATH = "./support.db"` (must match the database created in Step 1).2.数据库辅助函数
- `get_db_connection()`
- `row_to_dict(row)`3.业务逻辑功能 (直接访问SQLite):
- `get_customer(customer_id: int)`
- `list_customers(status: Optional[str] = None)`
- `update_customer(customer_id, name, email, phone)`
- `create_ticket(customer_id, issue, priority)`
- `get_customer_history(customer_id)`4.MCP服务器实现
- Defines MCP tools (`MCP_TOOLS`) with JSON schemas.
- Implements handlers for:
- `"initialize"`
- `"tools/list"`
- `"tools/call"`
- Exposes `/mcp` (POST) for MCP messages using SSE.5.Flask+ngrok启动
- Starts Flask on `127.0.0.1:5000`.
- Runs a health check (`/health`).
- Authenticates ngrok using `NGROK_AUTHTOKEN`.
- Prints lines like:
✅ MCP Server is running! 📍 Local URL: http://127.0.0.1:5000
🌐 Setting up public tunnel with ngrok... ✅ Public URL: https://una-verminous-chace.ngrok-free.dev 🔗 MCP ENDPOINT : https://una-verminous-chace.ngrok-free.dev/mcp
- **Copy the MCP endpoint URL** — you will need it in `a2a.ipynb`.6.MCP自检单元(可选,但推荐)
- 发送
"initialize"JSON-RPC请求requests.post.
- 流式传输SSE响应并打印:
✅ Got MCP response from ADK notebook:
{
"jsonrpc": "2.0",
"id": 999,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": { "tools": {} },
"serverInfo": { "name": "customer-management-server", "version": "1.0.0" }
}
}如果你看到这个,你的 MCP服务器+ngrok隧道正在工作.
6.步骤3–运行多代理A2A笔记本
打开 a2a.ipynb.
6.1配置MCP工具集
确保定义的单元格 MCP_SERVER_URL 使用上一步中的隧道。例子:
MCP_SERVER_URL = "https://una-verminous-chace.ngrok-free.dev/mcp"然后,客户数据代理的连接方式如下:
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import MCPToolset, StreamableHTTPConnectionParams
customer_data_mcp_tools = MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url=MCP_SERVER_URL
)
)
customer_data_agent = LlmAgent(
model="gemini-2.5-flash",
name="customer_data_agent",
description="Agent focused on reading and updating customer records via MCP tools.",
tools=[customer_data_mcp_tools],
instruction="""
You are a customer data specialist.
You can reach a customer database through MCP tools. Use them to:
- fetch details for specific customers by ID
- list customers (optionally by status)
- update contact information (name, email, phone)
- review support ticket history
- open new support tickets
When you act:
- Call the appropriate MCP tool.
- Explain briefly what you did.
- Present customer information in a clean, readable format.
"""
)6.2路由器和支持代理
a2a.ipynb 还定义了:
- A. 路由器代理 即:
- 读取用户查询
- 决定这主要是数据、支持还是混合
- 呼叫 transfer_to_agent 将工作委托给 customer_data_agent 或 support_agent.
- A. 支援谍员 即:
- 处理账单问题、退款和帐户更改
- 可以向数据代理询问客户或工单上下文
- 以自然语言返回用户友好的解释。
6.3运行演示场景
接近尾声 a2a.ipynb,有:
async def run_demo_scenarios():
await ask_agent_team("Please pull the customer record for ID 5.")
await ask_agent_team("I'm customer 12345 and I'd like to upgrade my account. What should I do?")
await ask_agent_team("Show me which active customers currently have open support tickets.")
await ask_agent_team("I was billed twice on my last invoice. I need this investigated and refunded as soon as possible.")
await ask_agent_team("For customer 1, update the email address to new@email.com and then summarize their recent ticket history.")
await run_demo_scenarios()对于每个查询,运行此单元格打印:
- A. 头球 与用户消息一起
- 一 代理事件跟踪 显示:
- 路由器委派
- MCP工具调用(例如。, get_customer, get_customer_history)
- 工具结果(成功或错误,如缺少数据库时出现“没有这样的表”)
- 最终答案返回给“用户”。
当 support.db 如果存在并且MCP接线正确,系统将:
- 拉客户5
- 尝试客户12345的升级流程
- 向活跃客户展示未结门票
- 确认重复计费并承诺调查+退款
- 更新客户1的电子邮件并总结他们的票务历史。
7.典型问题及调试注意事项
在开发过程中,以下是常见的陷阱:
1. no such table: customers
- 原因:
support.db未创建或database_setup.py不与在同一目录中运行mcp_server.ipynb.
- 修复:重新运行
python database_setup.py并确认support.db存在于笔记本旁边。
2.服务器超时或 No response received
- 原因:MCP服务器未运行、ngrok隧道已过期或MCP URL不匹配。
- 修复:重新启动
mcp_server.ipynb,复制新的ngrok/mcpURL和更新MCP_SERVER_URL在a2a.ipynb.
3.端口5000已在使用中
- 原因:以前的Flask服务器仍在Colab/local中运行。
- 修复:重新启动运行时或更改中使用的端口
server.py/mcp_server.ipynb.
了解这些故障模式是学习经验的一部分,并有助于强化当任何链接(DB、隧道或URL)配置错误时,多组件系统是多么脆弱。
