taffy123d

ToolKit本地技能Agent

Community taffy123d
Updated

大学生自学agent开发中...

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/health GET 健康检查
/api/tools GET 获取技能列表
/api/config GET 获取配置
/api/config POST 保存配置
/api/test-connection POST 测试 API 连接
/api/chat POST 聊天(支持对话历史)
/api/chat/stream POST 流式聊天(SSE)
/api/chat/clear POST 清除对话历史
/api/sessions GET 获取所有会话列表
/api/sessions/<id> DELETE 删除指定会话
/api/sessions/<id>/history GET 获取会话历史记录

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() 路由的异常处理和日志输出

MCP Server · Populars

MCP Server · New

    NameetP

    pdfmux

    PDF extraction that checks its own work. #2 reading order accuracy — zero AI, zero GPU, zero cost.

    Community NameetP
    node9-ai

    🛡️ Node9 Proxy

    The Execution Security Layer for the Agentic Era. Providing deterministic "Sudo" governance and audit logs for autonomous AI agents.

    Community node9-ai
    initMAX

    Zabbix MCP Server

    MCP server for the complete Zabbix API — 220 tools, multi-server support, bearer auth, systemd ready. Works with ChatGPT, Claude, VS Code, Codex, JetBrains and any MCP client.

    Community initMAX
    superradcompany

    microsandbox

    opensource secure local-first sandboxes for ai agents

    Community superradcompany
    vasylenko

    Bear Notes MCP Server

    MCP Server for Bear note taking app available as Claude Desktop extension or standalone server for any other AI tool

    Community vasylenko