首页
/ g4f Discord Bot:用 gpt4free 在 Discord 中搭建免 API Key 的 AI 聊天机器人并接入 MCP 工具

g4f Discord Bot:用 gpt4free 在 Discord 中搭建免 API Key 的 AI 聊天机器人并接入 MCP 工具

2026-09-04 13:31:23作者:裘旻烁

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 应用

  1. 进入 Discord Developer Portal,创建一个新应用;
  2. Bot 标签页点击 Reset Token 获取 token;
  3. Privileged Gateway Intents 中开启 Message Content Intent(机器人需要读取消息内容才能工作,对应 bot.py 中的 intents.message_content = True);
  4. 通过 OAuth2 → URL Generator 邀请机器人进服务器:scopes 选 botapplications.commands,permissions 至少包含 Send MessagesRead Message History

2. 配置环境变量

cd projects/discord-bot
cp .env.example .env
# 编辑 .env,粘贴你的 DISCORD_TOKEN

3. 安装依赖

机器人在 g4f 依赖之外还需要 discord.pypython-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.examplegpt-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 每用户保存的最大消息条数,决定 dequemaxlenbot.py
G4F_PROXY (无) g4f 请求的可选代理,例如 socks5://127.0.0.1:1080
G4F_ENABLED_TOOLS (安全集) 启动时启用的 MCP 工具,逗号分隔;不设置时使用 SAFE_DEFAULT_TOOLSbot.py
G4F_MAX_TOOL_LOOPS 4 工具调用轮数上限,达到后强制收尾(bot.py
G4F_IMAGE_MODEL flux /image 与频道自动出图使用的图像模型(bot.py
G4F_API_KEY / G4F_MEDIA_PROVIDER (可选) 传入异步客户端工厂的参数,媒体生成默认走 AnyProviderbot.py
G4F_IMAGE_CHANNELS (未设置即关闭) 逗号分隔的频道 ID 列表;设置后机器人会监听这些频道,把成员发的任意消息当作绘图 prompt 自动出图(bot.pyon_message

MCP 工具集成:让 AI 自主调用工具

机器人集成了 g4f 内置的 MCP 服务器,使模型在对话中可以自主调用工具。整体流程(来自 README):

  1. 你提出一个需要联网/生成资源的问题(例如“X 的最新消息?”);
  2. 模型决定调用 web_search 并返回 tool call;
  3. 机器人通过 MCPServer 执行工具,把结果追加进对话,再次请求模型;
  4. 循环重复,直到模型给出最终答案或触及 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 实现 initializetools/listtools/callping 四个方法(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 删除工作区文件

需要说明的是:上表来自 READMEmcp_tools.pyALL_AVAILABLE_TOOLS。从源码结构看,当前 MCPServer 的注册表 实际注册的名字还包括 fetch_webpagefile_search_globgrep_searchcreate_filegithub_repogithub_text_search 等,而 web_scrapefile_searchfile_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),其行为是:

  1. 无工具快速路径:若 tools 为 False 或没有任何已启用的工具定义,直接走 _stream_response() 流式返回;
  2. 带工具阶段(非流式)_completion_with_tools()stream=Falsetools=mcp.definitionstool_choice="auto" 请求补全(bot.py)。模型若返回 tool_calls,机器人先在原消息上显示 “🔧 Running tools: ...”,再逐个执行并把 assistant 的 tool-call 消息与工具结果一并追加进 working_messages,然后进入下一轮;
  3. 轮数上限:最多 MAX_TOOL_LOOPS 轮(默认 4)。用尽后记录警告日志,并对累积了所有工具结果的消息做最后一次无工具的流式请求,让模型总结已有信息给出答案(bot.py);
  4. 收尾展示_finalize_response() 用最终回复原地编辑交互消息;如果本轮用过工具,还会在回复末尾附上折叠式的工具结果摘要,并对整体做截断(bot.py)。

流式细节上,_stream_response() 每累积 80 个字符就 edit_original_response 一次并追加 “▌” 光标,编辑失败静默吞掉 HTTPException(避免限流打断流程)(bot.py)。由于 Discord 单条消息上限为 2000 字符,_truncate() 以 1900 为安全阈值做截断加省略号(bot.py)。历史方面,/chat 在拿到回复后才会把本轮 user/assistant 两条消息压入该用户的 dequebot.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.pybot.py)。

图像生成

/image 命令调用 client.images.generate(prompt=..., model=..., response_format="url"),若结果以 http(s):// 开头则以 Embed 图片形式发送,否则把原始结果放进代码块展示(bot.pybot.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,仅在你信任服务器成员时再启用。
登录后查看全文
热门项目推荐
相关项目推荐