g4f Discord Bot:用 gpt4free 在 Discord 中搭建免 API Key 的 AI 聊天机器人并接入 MCP 工具
projects/discord-bot 是 gpt4free(g4f)仓库自带的 Discord 机器人示例:基于 discord.py 和 g4f 的异步客户端,让你的 Discord 服务器成员通过斜杠命令直接与免费大模型对话,无需任何 API Key。读完本篇,你可以完成机器人从申请到运行的全流程部署,理解它的 MCP 工具调用循环、流式回复与按用户隔离的历史管理是如何实现的,并知道如何通过环境变量与运行时命令管理模型与工具。
功能概览
机器人以 commands.Bot + 斜杠命令(bot.tree)方式实现,源码入口为 bot.py。除 README 中列出的核心命令外,从源码看它还提供了运行时切换模型、模型目录查询和独立图像生成等扩展命令:
| 命令 | 作用 | 源码依据 |
|---|---|---|
/ask |
一次性提问,不保留历史,支持 tools 布尔参数 |
bot.py |
/chat |
带按用户隔离历史的对话模式 | bot.py |
/clear |
清空当前用户的对话历史 | bot.py |
/model |
查看当前配置的模型名 | bot.py |
/setmodel |
运行时切换模型(带字符白名单校验) | bot.py |
/models |
尽力拉取当前 provider 的模型目录 | bot.py |
/searchmodel |
按关键字搜索模型目录(limit 限制在 1~30) | bot.py |
/image |
根据 prompt 生成图片,返回 URL 并以 Embed 展示 | bot.py |
/tools |
列出/启用/禁用 MCP 工具 | bot.py |
其他关键特性:
- 流式回复:通过
edit_original_response原地编辑消息,营造“打字机”效果; - MCP 工具调用:模型可自主调用网络搜索、网页抓取、图像生成、文本转语音等工具,机器人执行后把结果回灌对话,循环直至模型给出最终答案;
- 按用户历史隔离:使用
deque(maxlen=G4F_MAX_HISTORY)为每个用户维护消息窗口,默认 12 条。
部署步骤
1. 创建 Discord 应用
- 进入 Discord Developer Portal,创建一个新应用;
- 在 Bot 标签页点击 Reset Token 获取 token;
- 在 Privileged Gateway Intents 中开启 Message Content Intent(机器人需要读取消息内容才能工作,对应 bot.py 中的
intents.message_content = True); - 通过 OAuth2 → URL Generator 邀请机器人进服务器:scopes 选
bot、applications.commands,permissions 至少包含Send Messages、Read Message History。
2. 配置环境变量
cd projects/discord-bot
cp .env.example .env
# 编辑 .env,粘贴你的 DISCORD_TOKEN
3. 安装依赖
机器人在 g4f 依赖之外还需要 discord.py 和 python-dotenv:
pip install discord.py python-dotenv
4. 运行
python bot.py
正常启动后控制台会输出(对应 on_ready 事件):
[INFO] Logged in as YourBot#1234 (id=...)
[INFO] Synced N slash commands
若未设置 token,main() 会直接以 DISCORD_TOKEN not set 退出(bot.py)。
配置项详解(.env)
所有设置都在 .env 中,模板见 .env.example。下表继承 README 的说明,并补充了从 bot.py 源码 中确认到的更多变量:
| 变量 | 默认值 | 说明 |
|---|---|---|
DISCORD_TOKEN |
(必填) | Discord bot token |
G4F_MODEL |
.env.example 写 gpt-4o-mini;源码读取时的兜底为 auto |
传给 g4f 的模型名。代码里读取为 os.getenv("G4F_MODEL", "auto")(bot.py),因此不设环境变量时按 auto 解析,实际取值以你写入 .env 的内容为准 |
G4F_SYSTEM_PROMPT |
见 .env.example | 助手系统提示词;源码内置默认提示词还会引导模型“需要新鲜信息时用 web_search、被要求画图时用 image_generation”(bot.py) |
G4F_MAX_HISTORY |
12 |
每用户保存的最大消息条数,决定 deque 的 maxlen(bot.py) |
G4F_PROXY |
(无) | g4f 请求的可选代理,例如 socks5://127.0.0.1:1080 |
G4F_ENABLED_TOOLS |
(安全集) | 启动时启用的 MCP 工具,逗号分隔;不设置时使用 SAFE_DEFAULT_TOOLS(bot.py) |
G4F_MAX_TOOL_LOOPS |
4 |
工具调用轮数上限,达到后强制收尾(bot.py) |
G4F_IMAGE_MODEL |
flux |
/image 与频道自动出图使用的图像模型(bot.py) |
G4F_API_KEY / G4F_MEDIA_PROVIDER |
(可选) | 传入异步客户端工厂的参数,媒体生成默认走 AnyProvider(bot.py) |
G4F_IMAGE_CHANNELS |
(未设置即关闭) | 逗号分隔的频道 ID 列表;设置后机器人会监听这些频道,把成员发的任意消息当作绘图 prompt 自动出图(bot.py、on_message) |
MCP 工具集成:让 AI 自主调用工具
机器人集成了 g4f 内置的 MCP 服务器,使模型在对话中可以自主调用工具。整体流程(来自 README):
- 你提出一个需要联网/生成资源的问题(例如“X 的最新消息?”);
- 模型决定调用
web_search并返回 tool call; - 机器人通过
MCPServer执行工具,把结果追加进对话,再次请求模型; - 循环重复,直到模型给出最终答案或触及
G4F_MAX_TOOL_LOOPS。
MCPToolManager:定义、执行与展示
工具管理集中在 mcp_tools.py,核心是 MCPToolManager 类:
- 安全默认集:
SAFE_DEFAULT_TOOLS = {web_search, web_scrape, mark_it_down, text_to_audio, image_generation}(mcp_tools.py)。文件、Python、补丁类工具因操作机器人本机的~/.g4f/workspace目录而被排除在默认集之外——只有在信任 Discord 用户时才应手动启用。 - 定义构建:
_rebuild_definitions()从MCPServer.get_tool_list()取出每个工具的name/description/inputSchema,按 OpenAI function-calling 格式封装为{"type": "function", "function": {...}},供chat.completions.create(tools=...)使用(mcp_tools.py)。注意构建时会取“启用集合”与“服务器已注册工具”的交集:不在服务器注册表里的名字不会真正暴露给模型。 - 执行:
execute_tool()构造一条 JSON-RPC 2.0 的MCPRequest(method="tools/call", params={"name": ..., "arguments": ...}),交由MCPServer.handle_request()执行(mcp_tools.py);execute_tool_calls()则把每个结果包装成role="tool"、携带tool_call_id的消息,内容以 JSON 字符串回灌(mcp_tools.py)。 - 展示:
format_tool_results_for_discord()把每次工具结果渲染成带代码块的 Markdown 摘要,超过 800 字符自动截断(mcp_tools.py)。
底层 MCPServer 的实现要点
MCP server 以 JSON-RPC 2.0 实现 initialize、tools/list、tools/call、ping 四个方法(server.py),同时支持 stdio 与 HTTP 两种传输。机器人侧默认以 safe_mode=True 构造它,源码注释说明 safe mode 下 Python 沙箱的模块白名单不可被调用方扩展、工作区根目录列举也被限制(server.py)。各工具的具体实现(DuckDuckGo 搜索、页面抓取、图像生成、受限 Python 执行、工作区文件读写等)位于 g4f/mcp/tools.py,例如 WebSearchTool 的入参为 query(必填)、max_results(默认 5)、region(默认 en-us)(tools.py)。
可用工具一览
| 工具 | 说明 | 默认启用? |
|---|---|---|
web_search |
通过 DuckDuckGo 搜索网络 | 是 |
web_scrape |
提取 URL 的文本内容 | 是 |
mark_it_down |
把 URL 转成 Markdown | 是 |
text_to_audio |
文本生成语音 URL | 是 |
image_generation |
根据 prompt 生成图像 | 是 |
python_execute |
在沙箱中运行 Python | 否 |
apply_patch |
应用 unified diff 补丁 | 否 |
file_read |
读取 ~/.g4f/workspace 中的文件 |
否 |
file_read_lines |
读取工作区文件的行范围 | 否 |
file_search |
在工作区中搜索文件 | 否 |
file_write |
向工作区写文件 | 否 |
file_list |
列出工作区文件 | 否 |
file_delete |
删除工作区文件 | 否 |
需要说明的是:上表来自 README 与 mcp_tools.py 的 ALL_AVAILABLE_TOOLS。从源码结构看,当前 MCPServer 的注册表 实际注册的名字还包括 fetch_webpage、file_search_glob、grep_search、create_file、github_repo、github_text_search 等,而 web_scrape、file_search、file_read_lines 并未以同名形式出现在注册表中——由于 MCPToolManager 只把“启用集合 ∩ 服务器注册表”暴露给模型,实际生效的工具以服务器注册表为准;行范围读取能力在 file_read 工具的描述中(支持 startLine/endLine,见 tools.py 的文件头注释)。启用时 enable() 也会校验 name in self.server.tools,未注册的名字会启用失败(mcp_tools.py)。
运行时管理与按请求禁用
- 使用
/tools斜杠命令管理:
/tools # 列出已启用与可启用的工具
/tools action:enable name:python_execute
/tools action:disable name:image_generation
- 或在
.env中固定启动集合:
G4F_ENABLED_TOOLS=web_search,web_scrape,image_generation
/ask与/chat都接受可选的tools布尔参数(默认true),可在单次请求中禁用工具:
/ask question:"What is 2+2?" tools:False
工具调用循环与流式输出(源码解析)
/ask 和 /chat 的最终处理都汇聚到 _run_tool_loop()(bot.py),其行为是:
- 无工具快速路径:若
tools为 False 或没有任何已启用的工具定义,直接走_stream_response()流式返回; - 带工具阶段(非流式):
_completion_with_tools()以stream=False、tools=mcp.definitions、tool_choice="auto"请求补全(bot.py)。模型若返回tool_calls,机器人先在原消息上显示 “🔧 Running tools: ...”,再逐个执行并把 assistant 的 tool-call 消息与工具结果一并追加进working_messages,然后进入下一轮; - 轮数上限:最多
MAX_TOOL_LOOPS轮(默认 4)。用尽后记录警告日志,并对累积了所有工具结果的消息做最后一次无工具的流式请求,让模型总结已有信息给出答案(bot.py); - 收尾展示:
_finalize_response()用最终回复原地编辑交互消息;如果本轮用过工具,还会在回复末尾附上折叠式的工具结果摘要,并对整体做截断(bot.py)。
流式细节上,_stream_response() 每累积 80 个字符就 edit_original_response 一次并追加 “▌” 光标,编辑失败静默吞掉 HTTPException(避免限流打断流程)(bot.py)。由于 Discord 单条消息上限为 2000 字符,_truncate() 以 1900 为安全阈值做截断加省略号(bot.py)。历史方面,/chat 在拿到回复后才会把本轮 user/assistant 两条消息压入该用户的 deque(bot.py),历史保存在进程内存中,重启即清空。
切换模型与 Provider
README 给出的方式是修改 import 与 AsyncClient 构造:
from g4f.Provider import Gemini, OpenaiChat, BingCreateImages
client = AsyncClient(provider=Gemini)
当前 bot.py 的实际代码 则通过 ClientFactory 创建异步客户端:
client = ClientFactory.create_async_client(provider="default",
api_key=os.getenv("G4F_API_KEY"),
media_provider=os.getenv("G4F_MEDIA_PROVIDER", AnyProvider))
从源码结构看,ClientFactory.create_async_client 支持按名称、按类或自定义 base_url 三种方式指定 provider(client/init.py),provider 解析逻辑(含自定义 provider 与动态 provider 查找)在 factory.py。因此把 provider="default" 换成具体名称(如某个 provider 类或字符串)即可切换,README 建议用 g4f --help 查看可用 provider 列表。此外 /setmodel 切换模型名时会经过字符白名单校验(仅允许字母、数字和 -_.:),非法字符会被拒绝(bot.py、bot.py)。
图像生成
/image 命令调用 client.images.generate(prompt=..., model=..., response_format="url"),若结果以 http(s):// 开头则以 Embed 图片形式发送,否则把原始结果放进代码块展示(bot.py、bot.py)。设置 G4F_IMAGE_CHANNELS 后,on_message 事件会监听指定频道:忽略机器人消息与空内容,先发送 “🖼️ Generating…” 占位消息,出图成功后原地替换为 Embed(bot.py)。这为“专用绘图频道”玩法提供了开箱即用的支持。
项目结构与注意事项
projects/discord-bot/
├── bot.py # 主机器人逻辑(命令、工具调用循环、流式输出)
├── mcp_tools.py # MCP 工具管理器(定义、执行、展示)
├── .env.example # 环境变量模板
└── README.md # 文档
使用注意事项(来自 README 并结合源码):
- g4f 依赖免费的第三方 provider,可用性与质量会波动,某个模型请求失败时可尝试换模型或换 provider;
- 机器人全程使用异步客户端(
ClientFactory.create_async_client),保证流式输出期间事件循环保持响应; - Discord 消息上限 2000 字符,长回复会被截断(代码中阈值为 1900);
- 历史仅存于内存,按用户隔离且长度受
G4F_MAX_HISTORY约束;进程重启即丢失; - 文件/Python/补丁类工具操作的是运行 bot 的主机的
~/.g4f/workspace,仅在你信任服务器成员时再启用。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00