MCP Hub
Back to servers

Doubao MCP Agent

A local skill assistant based on the Model Context Protocol that integrates with the Volcengine Doubao API to provide tools like calculators and weather queries. It features a Web interface and a modular architecture that allows developers to easily register and deploy custom local AI skills.

glama
Stars
5
Forks
2
Updated
Mar 31, 2026
Validated
Apr 4, 2026

ToolKit本地技能Agent

一个基于 MCP (Model Context Protocol) 协议的本地技能助手,支持计算器、天气查询等自定义技能,提供 Web 界面和 API 接口。

项目结构

..
├── .env                    # 大模型 API 配置
├── chat_history.db         # SQLite 对话历史数据库(自动生成)
├── index.html              # 前端 Web 界面
├── main.py                 # 主入口(命令行界面)
├── mcp_server.py          # MCP 服务端(核心)
├── server.py               # Flask 后端服务
├── requirements.txt        # 依赖清单
├── README.md               # 项目说明
├── tree.txt                # 目录结构
├── client/                 # 客户端目录
│   ├── doubao_mcp_client.py  # 豆包 API 客户端
│   └── __init__.py
├── config/                 # 配置目录
│   ├── settings.py         # 全局配置
│   └── __init__.py
└── skills/                 # 技能实现目录
    ├── calculator.py       # 计算器技能
    ├── weather.py          # 天气查询技能
    ├── web_search/         # 网络搜索技能目录
    │   └── web_search.py   # DuckDuckGo搜索实现
    |   └── SKILL.md  # skill描述
    |   └── _init_.py   
    └── __init__.py

技术栈

后端框架:Python + Flask 构建 Web 服务,提供 RESTful API 与 SSE 流式输出接口

AI 协议与模型调用:基于 OpenAI 兼容 SDK 对接大模型 API,支持豆包等 OpenAI 格式模型接入

核心协议:MCP(Model Context Protocol)实现工具调用标准化,统一技能注册与调度

异步架构:asyncio 异步处理 + 线程池隔离,解决 Flask 同步环境下异步调用阻塞问题

数据持久化:SQLite 实现多会话对话上下文存储,支持会话管理与历史加载

技能插件化:模块化技能系统,支持计算器、天气、网络搜索等可插拔工具扩展

前端:原生 HTML/JS 实现 Web 交互界面,支持 Markdown 渲染、流式打字效果、思维链展示

工程化 :api变量配置(.env)、依赖管理(uv/pip)、错误重试与降级机制、工具调用缓存

核心功能

稳定的异步处理 - 修复了Flask路由中直接使用asyncio.run()的问题,使用线程池执行异步函数

对话历史持久化 - 使用 SQLite 存储对话历史,服务重启不丢失,支持多会话管理

工具调用容错 - 自动重试机制,工具调用失败时降级到模型直接回答

MCP 工具缓存 - 首次获取工具列表后缓存,减少重复初始化开销

流式输出 - 实现了完整的SSE流式接口,支持逐字输出体验

工具调用提示 - 当调用技能时,会显示"【调用了工具:{工具名称}】"的提示信息

多端支持 - 提供Web界面和命令行界面两种交互方式

丰富的技能 - 内置计算器、天气查询和网络搜索技能

技能管理 - 前端可视化技能管理,可自由开关技能

Markdown渲染 - 支持Markdown格式的回复,支持代码高亮、表格、列表、数学公式等

思维链展示 - 可折叠的AI思考过程展示,便于理解推理逻辑

多会话管理 - 支持创建多个独立对话,每个对话独立保存历史

历史对话加载 - 切换会话时自动加载历史对话,完整记录交互过程

环境要求

  • Python 3.11+
  • openaiSDK(api)
  • uv 包管理工具(推荐)或 pip

安装

方法一:使用 uv 包管理工具(推荐)

  1. 安装 uv

    # Windows
    Set-ExecutionPolicy RemoteSigned -Scope CurrentUser 
    irm https://astral.sh/uv/install.ps1 | iex
    
    # macOS / Linux
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
  2. 克隆项目

    git clone https://github.com/taffy123d/Doubao-MCP-agent
    cd <项目目录>
    
  3. 创建虚拟环境

    uv venv
    
  4. 安装依赖

    uv sync
    

方法二:使用 pip

  1. 克隆项目

    git clone https://github.com/taffy123d/Doubao-MCP-agent
    cd <项目目录>
    
  2. 创建虚拟环境

    python -m venv venv
    
  3. 激活虚拟环境

    # Windows
    venv\Scripts\activate
    
    # macOS / Linux
    source venv/bin/activate
    
  4. 安装依赖

    pip install -r requirements.txt
    

配置

  • 在前端配置api密钥
  • 或在 .env 文件中填写 API 密钥:
# OpenAI 兼容格式的 API 配置
OPENAI_API_KEY=你的API密钥
OPENAI_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
OPENAI_MODEL=你的模型ID

运行

方法一:完整启动(推荐)

uv run server.py
#或者
python server.py
  • 前端访问:http://localhost:5000
  • API 接口:http://localhost:5000/api/*

方法二:命令行界面

uv run main.py
#或者
python main.py
  • 直接在终端中进行对话
  • 支持多轮对话和历史记录
  • 输入 clear清除历史 可以清除对话历史
  • 输入 exitquit退出 可以退出程序

API 接口

接口方法说明
/GET前端页面
/api/healthGET健康检查
/api/toolsGET获取技能列表
/api/configGET获取配置
/api/configPOST保存配置
/api/test-connectionPOST测试 API 连接
/api/chatPOST聊天(支持对话历史)
/api/chat/streamPOST流式聊天(SSE)
/api/chat/clearPOST清除对话历史
/api/sessionsGET获取所有会话列表
/api/sessions/<id>DELETE删除指定会话
/api/sessions/<id>/historyGET获取会话历史记录

API 请求示例

聊天接口

curl -X POST http://localhost:5000/api/chat \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "你的API密钥",
    "model": "你的模型ID",
    "base_url": "https://ark.cn-beijing.volces.com/api/v3",
    "message": "北京天气",
    "session_id": "default"
  }'

流式聊天接口

curl -X POST http://localhost:5000/api/chat/stream \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "你的API密钥",
    "model": "你的模型ID",
    "base_url": "https://ark.cn-beijing.volces.com/api/v3",
    "message": "北京天气",
    "session_id": "default"
  }'

清除历史接口

curl -X POST http://localhost:5000/api/chat/clear \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "default"
  }'

如何使用

Web 界面

  1. 配置 API

    • 在左侧配置面板填写 API Key 和 Endpoint ID
    • 点击「测试」按钮验证连接
  2. 聊天

    • 在输入框中输入问题
    • 支持的技能:
      • 计算器:计算 123+456
      • 天气查询:北京天气
      • 网络搜索:搜索 最新AI新闻
  3. 技能管理

    • 点击左侧「🔧 技能管理」展开面板
    • 查看所有可用技能及其描述
    • 点击开关按钮启用/禁用技能
    • 只有启用的技能才会被调用
  4. 多会话管理

    • 点击左侧「💬 对话管理」展开面板
    • 点击「➕ 新建对话」创建新会话
    • 点击会话列表项切换到对应对话
    • 点击🗑️删除不需要的对话
    • 每个会话独立保存历史记录
  5. 查看结果

    • 系统会自动调用相应的技能并返回结果
    • 支持Markdown格式的回复(代码高亮、表格、列表等)
    • 可点击「🧠 思考过程」查看AI的推理逻辑
    • 支持多轮对话

命令行界面

  1. 运行程序

    python main.py
    
  2. 输入问题

    • 直接在终端中输入你的问题
    • 支持的技能:
      • 计算器:计算 123+456
      • 天气查询:北京天气
  3. 查看结果

    • 系统会自动调用相应的技能并返回结果
    • 支持多轮对话
    • 输入 clear清除历史 可以清除对话历史

如何增加新技能

步骤 1:创建技能文件

skills/ 目录下创建新的技能文件,例如 my_skill.py

"""我的自定义技能"""
from mcp.server.fastmcp import FastMCP

def register_my_skill(mcp: FastMCP):
    """注册技能到 MCP 服务"""
    
    @mcp.tool()
    def my_skill(param1: str, param2: int = 1) -> str:
        """
        我的自定义技能描述
        示例:my_skill(param1="值", param2=2)
        
        Args:
            param1: 参数1描述
            param2: 参数2描述(默认值)
        Returns:
            技能执行结果
        """
        try:
            # 技能逻辑实现
            result = f"处理结果: {param1} - {param2}"
            return result
        except Exception as e:
            return f"处理失败: {str(e)}"

步骤 2:注册技能

编辑 skills/__init__.py,添加新技能的注册函数:

from .calculator import register_calculator_tool
from .weather import register_weather_tool
from .my_skill import register_my_skill

__all__ = [
    "register_calculator_tool", 
    "register_weather_tool",
    "register_my_skill"
]

步骤 3:更新 MCP 服务

编辑 mcp_server.py,添加新技能的注册:

from skills import register_calculator_tool, register_weather_tool, register_my_skill

# 注册所有技能工具
register_calculator_tool(mcp)
register_weather_tool(mcp)
register_my_skill(mcp)  # 添加这一行

步骤 4:重启服务

重新启动 MCP 服务和后端服务,新技能即可使用。

技能开发规范

  1. 文件命名:使用小写字母和下划线
  2. 函数命名register_xxx_tool 格式
  3. 工具装饰器:使用 @mcp.tool() 装饰
  4. 文档字符串:包含功能描述、示例和参数说明
  5. 错误处理:捕获异常并返回友好提示
  6. 参数类型:使用类型注解

如何创建复杂 Skill(带 SKILL.md)

对于功能较复杂的技能,建议创建独立的 skill 目录,包含技能实现和 SKILL.md 描述文件。

目录结构

skills/
└── my_complex_skill/          # skill 目录
    ├── __init__.py            # 导出配置(必选)
    ├── my_skill.py            # 技能实现(必选)
    └── SKILL.md               # skill 描述文档(必选)

步骤 1:创建 skill 目录和实现文件

skills/ 目录下创建新的 skill 目录,例如 skills/my_complex_skill/

1.1 创建技能实现文件 my_skill.py

"""我的复杂技能实现"""
from mcp.server.fastmcp import FastMCP
from duckduckgo_search import AsyncDuckDuckGoSearcher  # 示例依赖

def register_my_complex_skill(mcp: FastMCP):
    """注册复杂技能到 MCP 服务"""
    
    @mcp.tool()
    async def my_complex_skill(query: str, limit: int = 5) -> str:
        """
        我的复杂技能描述
        
        Args:
            query: 查询关键词
            limit: 返回结果数量,默认5
        
        Returns:
            格式化的搜索结果
        """
        try:
            async with AsyncDuckDuckGoSearcher() as searcher:
                results = await searcher.atext(query, max_results=limit)
                # 处理并返回结果
                return f"找到 {len(results)} 条结果..."
        except Exception as e:
            return f"搜索失败: {str(e)}"

1.2 创建 __init__.py 导出配置

"""my_complex_skill - 我的复杂技能"""
from .my_skill import register_my_complex_skill

__all__ = ["register_my_complex_skill"]

1.3 创建 SKILL.md 描述文档

# 我的复杂技能

## 功能描述
一句话描述技能功能...

## 使用场景
### ✅ 适用场景
- 场景1
- 场景2

## 参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| query | string | 是 | - | 查询关键词 |

## 使用示例
```python
# 示例1
my_complex_skill(query="关键词")

返回结果格式

  • 结果1:xxx
  • 结果2:xxx

异常处理

错误类型处理方式
网络错误返回友好的错误提示

注意事项

  1. 注意事项1
  2. 注意事项2

### 步骤 2:更新 skills/__init__.py

```python
from .calculator import register_calculator_tool
from .weather import register_weather_tool
from .web_search import register_web_search_tool
from .my_complex_skill import register_my_complex_skill  # 新增

__all__ = [
    "register_calculator_tool", 
    "register_weather_tool",
    "register_web_search_tool",
    "register_my_complex_skill"  # 新增
]

步骤 3:更新 mcp_server.py

from skills import (
    register_calculator_tool, 
    register_weather_tool, 
    register_web_search_tool,
    register_my_complex_skill  # 新增
)

# 注册所有技能工具
register_calculator_tool(mcp)
register_weather_tool(mcp)
register_web_search_tool(mcp)
register_my_complex_skill(mcp)  # 新增

步骤 4:安装额外依赖(如需要)

如果新 skill 需要额外的 Python 包,在使用 uv add 导入或requirements.txt 中添加:

uv add 包名称
或
包名称 >=版本号 #requirements.txt

然后运行:

uv sync
# 或
pip install 包名称

步骤 5:重启服务

重新启动服务,新技能即可使用。

SKILL.md 规范

字段必填说明
# 标题技能名称
## 功能描述一句话说明技能作用
## 使用场景建议列出适用场景
## 参数说明建议表格形式说明参数
## 使用示例建议代码和对话示例
## 返回结果格式建议说明返回内容结构
## 异常处理建议错误处理方式
## 注意事项建议使用注意点

示例技能

计算器技能

  • 功能:支持加减乘除、括号、幂运算
  • 调用计算 (10+5)*2

天气查询技能

  • 功能:查询城市天气和预报
  • 调用上海天气北京天气 3天

网络搜索技能

  • 功能:使用DuckDuckGo搜索最新资讯
  • 调用搜索 Python最新版本搜索 今天科技新闻
  • 依赖ddgs 库(pip install duckduckgo-search)

技术亮点

  1. 异步处理优化 - 使用线程池执行异步函数,避免了每次请求创建新事件循环的问题
  2. 对话历史持久化 - 基于 SQLite 的持久化存储,服务重启不丢失,支持多会话隔离
  3. 工具调用容错 - 失败自动重试 2 次,降级到模型直接回答,提升鲁棒性
  4. MCP 工具缓存 - 减少重复初始化开销,提升响应速度
  5. 流式输出实现 - 完整的 SSE 流式接口,提供更好的用户体验
  6. 工具调用提示 - 清晰的工具调用提示,提升用户体验
  7. 多端支持 - 同时提供 Web 界面和命令行界面
  8. 技能管理系统 - 前端可视化技能管理,支持灵活开关
  9. Markdown渲染 - 完整的Markdown支持,包括代码高亮、表格等
  10. 思维链展示 - 可折叠的AI推理过程展示
  11. 多会话管理 - 完整的会话创建、切换、删除功能
  12. 历史对话加载 - 自动加载和展示会话历史

注意事项

  1. API 密钥安全:不要将 API 密钥提交到版本控制
  2. 技能安全性:避免在技能中执行危险操作
  3. 性能优化:对于耗时操作,考虑使用异步处理
  4. 错误处理:确保技能能优雅处理异常情况

故障排除

  • 连接失败:检查 API 密钥和网络连接
  • 技能不响应:检查 MCP 服务是否正常运行
  • 前端不显示:检查浏览器控制台是否有错误
  • 流式接口问题:确保网络连接稳定,避免中途断开
  • 数据库错误:检查 chat_history.db 文件权限,确保可读写

数据存储

项目使用 SQLite 数据库持久化对话历史:

  • 数据库文件chat_history.db(项目根目录,首次运行自动生成)
  • 表结构
    CREATE TABLE messages (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      session_id TEXT NOT NULL,    -- 会话ID,支持多会话隔离
      role TEXT NOT NULL,           -- 角色(user/assistant/tool)
      content TEXT NOT NULL,        -- 消息内容
      timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
    )
    
  • 查询历史:使用 SQLite 工具或命令行查看
    sqlite3 chat_history.db "SELECT * FROM messages ORDER BY timestamp DESC LIMIT 10;"
    

扩展建议

  1. 更多技能:添加翻译、股票查询、新闻等技能
  2. 多语言支持:添加多语言界面
  3. 部署优化:使用 Docker 容器化部署
  4. 技能市场:创建技能市场,支持用户分享和下载技能
  5. 模型切换:支持切换不同的大语言模型

更新日志

2026-03-29 重大更新

API 调用方式升级

  • httpx → OpenAI SDK:所有 API 调用从 httpx 直接 HTTP 请求改为 openai>=1.0.0 SDK 方式
  • 配置字段重命名
    • DOUBAO_API_KEYOPENAI_API_KEY
    • DOUBAO_ENDPOINT_IDOPENAI_MODEL
    • DOUBAO_BASE_URLOPENAI_BASE_URL(去掉了 /chat/completions 后缀)

工具调用优化

  • Schema 清理:自动移除 titledefault 等豆包 API 不支持的字段
  • Description 清理:压缩多余空白字符,优化格式
  • 消息转换:添加 _msg_to_dict() 函数,正确处理 OpenAI SDK 返回的 ChatCompletionMessage 对象
  • 第二次调用:修复工具调用后二次请求的消息格式问题

Bug 修复

  • ✅ 修复 "Object of type ChatCompletionMessage is not JSON serializable" 错误
  • ✅ 修复消息历史保存时的类型转换问题
  • ✅ 添加详细的异常堆栈跟踪,便于调试

架构改进

  • 添加 _msg_to_dict() 辅助函数,统一消息格式转换
  • 添加 API 类型检测(讯飞 API 自动跳过 tools 参数)
  • 优化 chat() 路由的异常处理和日志输出

Reviews

No reviews yet

Sign in to write a review