热插拔多智能体助手

一个生产级AI代理平台,支持运行时工具热插拔、LLM驱动的路由和全栈可观测性,新功能可通过添加Python文件实现无需重启或重新部署。

  • by Arj-01
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 Arj-01/mcp-hotswap-agent

使用说明

MCP热插拔多代理助手

通过模型上下文协议热插拔AI工具

一个生产级的人工智能代理平台,具有运行时工具热交换、LLM驱动的路由和全栈可观察性。通过删除Python文件可以添加新功能——无需重新启动代理,无需更改代码,也无需重新部署。

100%本地。 与Ollama一起完全在您的机器上运行。没有API密钥,没有云成本。


主要特点

  • 热插拔工具架构 --工具服务器开始处于休眠状态(AST已扫描,未运行)。它们在单个查询生命周期内按需加载、执行和使用后自动分离。
  • 动态工具发现 --路由器代理在启动时发现MCP服务器,并静态扫描休眠插件。新工具在通过REST API注册时立即出现。
  • LLM供电路由 --Ollama(llama3.2)从自然语言中选择正确的工具;支持并行多工具调度 asyncio.gather().
  • 自动参数校正 --当计数匹配时,将LLM生成的错误参数名称位置重新映射到架构正确的名称——零手动干预。
  • 完全可观察性 --6普罗米修斯指标,带有预构建的Grafana仪表板,涵盖P50/P95/P99延迟、工具调用率和错误率。
  • 对话记忆 --每个会话的聊天历史记录保存在Redis中,跨会话隔离。
  • 一个命令部署 — bash scripts/start.sh 显示全部7项服务,完全有线。

🏗 建筑

它是如何工作的:

  1. 用户通过Streamlit UI发送自然语言查询
  2. FastAPI路由器代理将查询+可用工具列表发送给Ollama
  3. LLM决定调用哪些工具(零、一或多)
  4. 休眠服务器按需热插拔——加载、执行,然后自动分离
  5. 工具通过MCP stdio会话并行执行
  6. 结果被合成为单个响应

技术栈

层 技术 目的
LLM Ollama+llama3.2 本地推理,零成本工具布线
代理 FastAPI+asyncio 具有并行工具执行的异步路由器代理
工具协议 MCP SDK(stdio传输) 标准化的工具发现和执行
热插拔引擎 AST扫描器+停止事件 休眠插件生命周期管理
注册表 Redis哈希+排序集 工具元数据、服务器映射、脚本路径
聊天历史 Redis列表(上限,50毫秒) 每会话会话持久性
UI Streamlit 聊天界面+服务器管理面板
监控 普罗米修斯+格拉法纳 6台仪器,P50/P95/P99延迟仪表板
编排 Docker Compose 7服务单命令部署

MCP工具服务器

服务器 工具 说明
计算器 (休眠-按需热插拔) calculate, percentage, split_bill, unit_convert, loan_emi 数学、转换、金融
网络研究 search_web, fetch_url, summarize_url DuckDuckGo搜索,页面抓取
笔记创建者 create_note, create_note_from_topic, list_notes, read_note 带YAML frontmatter的Markdown注释
油管 get_transcript, summarize_video, ask_about_video 转录提取、视频问答

4台服务器上共有14个工具。 计算器在需要之前保持休眠状态,证明零停机热插拔。


快速开始

先决条件

  • Docker桌面(分配4 GB+RAM)
  • Ollama与骆驼3.2拉
ollama pull llama3.2

跑

git clone https://github.com/Arj-01/mcp-hotswap-agent.git
cd mcp-hotswap-agent
bash scripts/start.sh

这将启动所有7个服务(API、前端、Redis、Ollama、Prometheus、Grafana),并自动提取LLM模型。

服务 URL
聊天界面 http://localhost:8501
代理API http://localhost:8000/docs
格拉法纳 http://localhost:3000(管理员/管理员)
普罗米修斯 http://localhost:9090

本地开发

# Install dependencies
pip install -e ".[dev]"

# Start Redis and Ollama
redis-server &
ollama serve &

# Start the API
uvicorn agents.main:app --reload --port 8000

# Start the frontend (separate terminal)
streamlit run frontend/app.py

热交换演示

查看核心价值主张的实际应用——计算器服务器在启动时处于休眠状态,然后在会话中期热插拔:

零代码更改。零重启。

bash scripts/load_test.sh
Servers at startup:
  - youtube_summary_server  (3 tools, active)
  - notes_creator_server    (4 tools, active)
  - web_research_server     (3 tools, active)

Dormant: calculator (calculate, percentage, split_bill, unit_convert, loan_emi)

Query 1: "search for latest AI news"     → search_web       hot-plug: NO
Query 2: "say hello in French"           → none (LLM)       hot-plug: NO
Query 4: "calculate 42 * 58"             → calculate        hot-plug: YES ⚡ calculator_server
Query 5: "search for python tutorials"   → search_web       hot-plug: NO  (calculator detached)
Query 8: "calculate 15% of 8500"         → calculate        hot-plug: YES ⚡ fresh plug again
Query 11: "split bill of 2400 for 3"     → split_bill       hot-plug: YES ⚡ third cycle

ALL TESTS PASSED ✓  (12/12)
Hot-plug cycles: attached 3× · detached 3× · perfect symmetry

API终点

方法 端点 描述
POST /query 向路由器代理发送查询
GET /tools 列出所有已注册的工具
GET /servers 列出已连接的MCP服务器
POST /servers/register 注册新的MCP服务器
DELETE /servers/{name} 断开服务器连接
GET /chat/history/{session_id} 获取对话历史记录
DELETE /chat/history/{session_id} 清除会话历史记录
GET /health 健康检查(服务器、工具、Redis)
GET /metrics 普罗米修斯指标

监控

自动配置 MCP助理 Grafana仪表板包括:

面板 公制
查询总数 sum(queries_total)
活动服务器 active_servers_count
可用工具 available_tools_count
错误率 queries_total{status="error"} /总计×100
每分钟查询次数 rate(queries_total[1m]) * 60
响应时间P50/P95/P99 histogram_quantile 超过 query_duration_seconds_bucket
按服务器调用工具 rate(tool_calls_total[5m]) 按服务器
工具响应时间 histogram_quantile(0.95, ...) 通过工具

访问地址: http://localhost:3000 (管理员/管理员)

Grafana屏幕截图


聊天界面


添加自定义工具服务器

将Python文件放入 servers/:

# servers/my_tools_server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("my-tools")

@mcp.tool()
def greet(name: str) -> str:
    """Say hello to someone."""
    return f"Hello, {name}!"

if __name__ == "__main__":
    mcp.run(transport="stdio")

通过API注册-无需重新启动:

curl -X POST http://localhost:8000/servers/register \
  -H "Content-Type: application/json" \
  -d '{"name": "my-tools", "script_path": "servers/my_tools_server.py"}'

代理立即开始将查询路由到您的新工具。


项目结构

mcp-hotswap-agent/
├── agents/
│   ├── main.py              # FastAPI app with all endpoints
│   ├── router_agent.py      # LLM-powered tool routing + hot-swap logic
│   ├── mcp_client.py        # MCP stdio session manager + AST plugin scanner
│   ├── tool_registry.py     # Redis-backed tool storage (Hash + Sorted Set)
│   ├── chat_history.py      # Session-isolated conversation persistence
│   ├── config.py            # Settings (env vars)
│   └── metrics.py           # Prometheus counters / histograms / gauges
├── servers/
│   ├── calculator_server.py      # Math, finance, unit conversion (dormant)
│   ├── web_research_server.py    # DuckDuckGo search, URL fetch
│   ├── notes_creator_server.py   # Markdown notes with YAML frontmatter
│   └── youtube_summary_server.py # Transcript extraction, video Q&A
├── frontend/
│   └── app.py               # Streamlit chat UI + server management
├── docker/
│   ├── Dockerfile
│   ├── Dockerfile.frontend
│   └── docker-compose.yml   # 7-service orchestration
├── monitoring/
│   ├── prometheus.yml
│   ├── grafana-dashboard.json
│   ├── grafana-datasource.yml
│   └── grafana-dashboard-provider.yml
├── scripts/
│   ├── start.sh             # One-command Docker startup
│   ├── load_test.sh         # 12-query hot-swap verification test
│   └── e2e_smoke.sh         # E2E smoke test against live stack
├── screenshots/
│   ├── architecture.png
│   └── grafana-metrics/
│       ├── metrics_1.png
│       ├── metrics_2.png
│       ├── metrics_3.png
│       └── metrics_4.png
├── tests/
│   ├── test_hotswap.py          # Hot-plug lifecycle: attach → execute → detach → rescan
│   ├── test_integration.py      # Full API flows (ASGI client + fakeredis)
│   ├── test_error_scenarios.py  # Ollama offline, timeout, garbage JSON, tool errors
│   ├── test_param_correction.py # LLM param name correction edge cases
│   ├── test_chat_history.py     # Session-isolated Redis chat history
│   └── test_tool_registry.py    # Redis registry CRUD
└── pyproject.toml

测试

# Run all 40+ tests
pytest tests/ -v

# Run specific modules
pytest tests/test_hotswap.py -v
pytest tests/test_integration.py -v
pytest tests/test_error_scenarios.py -v

# E2E smoke test (requires docker compose up)
bash scripts/e2e_smoke.sh

# Hot-swap load test (12 queries, 3 hot-plug cycles)
bash scripts/load_test.sh

主要功能(详细)

  • 热插拔生命周期 --休眠扫描→ 热插拔→ 执行→ 自动分离→ 重新扫描,在3个独立循环中通过完美的附着/分离对称性进行验证。
  • 异步会话管理器 背景 asyncio.Task 每个服务器都有停止事件信号,以实现清洁生命周期;连接失败时重试一次;会话丢失时自动重新连接。
  • 并行工具执行 --多工具查询通过以下方式并发调度 asyncio.gather() 具有每个工具的延迟跟踪功能。
  • 参数自动校正 --当参数计数与模式匹配时,LLM键名的位置重新映射不匹配——在4种边缘情况下进行了测试。
  • 测试了5种故障模式 --Ollama离线、ReadTimeout、垃圾JSON(重试+回退)、工具异常传播、合成失败回退到级联。
  • Redis数据模型 — tools:{name} 搞砸, server_tools:{name} 设置, tool_index 排序集, chat:{session_id} capped List——所有操作都通过异步管道实现原子性。