ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DeepSeek操作MySQL数据库:用MCP实现数据库查询的完整配置指南

DeepSeek操作MySQL数据库:用MCP实现数据库查询的完整配置指南 1. 为什么要在本地让 DeepSeek 直接查 MySQL我最近在做一个库存管理的小工具后台是 MySQL前端还没写完但运营同事已经天天在群里问“低于 300 件的商品还有哪些”“上个月哪个客户买了笔记本”。每次都要我手动写 SQL 再截图发过去效率低得离谱。后来我换了个思路既然 DeepSeek 能理解自然语言MySQL 又有标准协议那能不能让模型自己把“人话”翻译成 SQL 并执行我只看结果这就是 MCPModel Context Protocol要解决的问题。MCP 是一套开放协议专门用来标准化 AI 模型和外部数据源、工具之间的交互方式。你可以把它理解成“AI 世界的 USB 接口”——模型不需要知道每个数据库的驱动怎么装、连接串怎么写只要按 MCP 约定暴露工具模型就能调用。DeepSeek 本身支持工具调用Function Calling配合 MCP 服务端就能实现“自然语言进查询结果出”。这个方案适合谁三类人最受益一是本地开发时不想反复切终端写 SQL 的后端同学二是需要快速做数据探查、又不想学 SQL 语法的产品/运营三是想把数据库查询能力集成进自己 Agent 应用的开发者。整个链路跑通后你问“11 月收入是多少”DeepSeek 会自动调工具、查订单表、算总和最后把数字告诉你。需要提前说明的是本文所有操作都在本地开发环境完成数据库连接信息只存在你自己的机器上。MCP 服务端通过标准输入输出和客户端通信不涉及任何外部网络转发安全性可控。下面我从环境准备开始一步步把这条链路搭起来。2. TaoToken 前置准备拿到 DeepSeek 的调用凭证DeepSeek 官方 API 在高峰期偶尔会限流而且如果你同时想对比 Claude、GPT 等模型做工具调用一个个申请 Key 很麻烦。我实测下来用 TaoToken 做统一接入层比较省事——它兼容 OpenAI 的接口格式DeepSeek 系列模型可以直接调Base URL 和 Key 一套搞定。具体操作分三步。第一步打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册账号邮箱验证后进控制台。第二步在控制台左侧找到“API Keys”点“创建新密钥”复制生成的 sk- 开头的字符串。这个 Key 只显示一次建议先存到本地环境变量里别直接写进代码提交到 Git。第三步确认你要用的模型 ID。DeepSeek 在 TaoToken 上的模型名通常是deepseek-chat对话和deepseek-reasoner推理。做数据库查询这种需要工具调用的场景用deepseek-chat就够了它对 Function Calling 的支持比较稳定。如果你后面想跑长期编码任务或 Agent 流程可以了解下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite额度更划算。配置环境变量时Linux/macOS 用exportWindows 用set# Linux / macOS export TAOTOKEN_API_KEYsk-你的密钥 export TAOTOKEN_BASE_URLhttps://taotoken.net/api # Windows PowerShell $env:TAOTOKEN_API_KEYsk-你的密钥 $env:TAOTOKEN_BASE_URLhttps://taotoken.net/api这里有个坑要注意Base URL 末尾不要加/v1TaoToken 的兼容层已经处理了路径映射加了反而会 404。Key 的权限方面建议在控制台里给这个 Key 只开“模型调用”权限不要开“账户管理”降低泄露风险。如果你还没拿到 Key可以先到模型对话页面https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite手动试几条消息确认账号能正常调用再继续。3. 可复制的 MCP 服务端配置三个工具 完整代码MCP 服务端的核心是暴露工具给模型调用。我设计了三个工具execute_mysql_query执行任意 SQL、list_tables列出所有表、get_table_schema查看表结构。为什么拆三个而不是只留一个执行 SQL 的因为 DeepSeek 有幻觉它可能先入为主认为商品表叫Product实际你的表叫products直接执行就报错。有了list_tables和get_table_schema模型会先查表名和字段再写 SQL成功率大幅提升。先装依赖pip install mcp mysql-connector-python openai然后创建mysql_mcp_server.py。数据库配置我放在文件顶部实际项目建议用环境变量import mysql.connector from mysql.connector import Error from mcp.server.fastmcp import FastMCP DB_CONFIG { host: 127.0.0.1, port: 3306, user: dev_user, password: your_password, database: shop_db, } mcp FastMCP(mysql-query-server) mcp.tool() def execute_mysql_query(sql_query: str, max_rows: int 100) - str: 执行给定的 SQL 查询语句并返回结果或错误信息。 Args: sql_query: 由 LLM 生成的 SQL 查询语句。 max_rows: SELECT 查询返回的最大行数防止结果过大。 connection None cursor None try: connection mysql.connector.connect(**DB_CONFIG) if connection.is_connected(): cursor connection.cursor(dictionaryTrue) cursor.execute(sql_query) if cursor.description: results cursor.fetchmany(max_rows) column_names [i[0] for i in cursor.description] if not results: return 查询成功执行但没有返回任何结果。 output 查询结果:\n output , .join(column_names) \n output - * len(, .join(column_names)) \n for row in results: row_values [ str(row[col]) if row[col] is not None else NULL for col in column_names ] output , .join(row_values) \n if cursor.fetchone() is not None: output f\n注意结果超过 {max_rows} 行已截断。 return output.strip() else: affected_rows cursor.rowcount connection.commit() return f操作成功执行。影响的行数: {affected_rows} except Error as e: if connection and connection.is_connected(): try: connection.rollback() except Error as rb_err: return f回滚事务时出错: {rb_err} return f数据库错误: {e} except Exception as ex: return f执行查询时发生未知错误: {ex} finally: if cursor: cursor.close() if connection and connection.is_connected(): connection.close() mcp.tool() def list_tables() - str: 获取当前数据库中所有表的列表。 return execute_mysql_query(sql_querySHOW TABLES;) mcp.tool() def get_table_schema(table_name: str) - str: 获取指定数据表的结构列信息。 Args: table_name: 需要查询结构的数据表名称。 if not table_name or not table_name.isidentifier(): return f错误无效的表名 {table_name}。 sql fDESCRIBE {table_name}; return execute_mysql_query(sql_querysql) if __name__ __main__: mcp.run()这段代码里max_rows默认 100防止模型查全表把上下文撑爆。dictionaryTrue让结果以字典返回格式化时更直观。非 SELECT 语句会 commitSELECT 不会。错误信息直接返回给模型模型看到“表不存在”会自己调list_tables重试。接下来是 MCP 客户端的配置。如果你用 Claude Code 或 Cline它们有标准的 MCP 配置文件。以 Cline 为例在cline_mcp_settings.json里加{ mcpServers: { mysql-query: { command: python, args: [/absolute/path/to/mysql_mcp_server.py], env: { TAOTOKEN_API_KEY: sk-你的密钥, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } }如果你用 Codex配置写在~/.codex/auth.json和config.toml里三件套缺一不可Base URL 填https://taotoken.net/apiKey 填你的 sk- 字符串Model ID 填deepseek-chat。Cline 的 MCP 配置里如果同时要调模型和 MCP 服务记得把模型凭证也放进env否则客户端启动时会报local proxy failed。4. 验证请求从提问到返回结果的完整链路配置写完后先单独测 MCP 服务端能不能跑。在终端执行python mysql_mcp_server.py如果没报错说明服务端在等待 stdio 输入。更直观的验证是写一个最小客户端直接调 DeepSeek 并处理工具调用。创建test_client.pyimport asyncio import json from openai import OpenAI client OpenAI( api_keysk-你的密钥, base_urlhttps://taotoken.net/api, ) TOOLS [ { type: function, function: { name: list_tables, description: 获取当前数据库中所有表的列表, parameters: {type: object, properties: {}}, }, }, { type: function, function: { name: get_table_schema, description: 获取指定数据表的结构, parameters: { type: object, properties: { table_name: {type: string, description: 表名} }, required: [table_name], }, }, }, { type: function, function: { name: execute_mysql_query, description: 执行 SQL 查询并返回结果, parameters: { type: object, properties: { sql_query: {type: string, description: SQL 语句} }, required: [sql_query], }, }, }, ] async def chat(prompt): messages [{role: user, content: prompt}] response client.chat.completions.create( modeldeepseek-chat, messagesmessages, toolsTOOLS, tool_choiceauto, ) msg response.choices[0].message if msg.tool_calls: for tc in msg.tool_calls: print(f模型请求调用: {tc.function.name}) print(f参数: {tc.function.arguments}) else: print(f直接回复: {msg.content}) asyncio.run(chat(数据库里有哪些表))运行后你会看到类似输出模型请求调用: list_tables 参数: {}这说明 DeepSeek 正确识别了工具并生成了调用请求。接下来把工具执行结果回传模型就能给出自然语言答案。完整链路是用户提问 → DeepSeek 返回 tool_calls → 客户端执行 MCP 工具 → 结果作为 tool 角色消息回传 → DeepSeek 生成最终回复。如果模型连续调多个工具比如先list_tables再get_table_schema再execute_mysql_query客户端要用循环处理直到模型不再返回 tool_calls。实测一个多表查询场景问“哪些客户购买了笔记本电脑列出邮箱”。DeepSeek 会先调list_tables看到customers、orders、products再调get_table_schema确认字段最后写 JOIN 查询。整个过程不需要你手写一行 SQL。5. 本篇常见错误排查401、local proxy failed、reading choices配置过程中最容易卡在几个报错上我逐个说下排查思路。401 Unauthorized九成是 Key 的问题。先确认TAOTOKEN_API_KEY环境变量有没有生效在 Python 里print(os.environ.get(TAOTOKEN_API_KEY))看是不是 None。如果 Key 正确还报 401检查 Base URL 是不是写成了https://taotoken.net/api/v1多写的/v1会导致鉴权路径错位。另外 Key 如果被控制台禁用或额度耗尽也会 401去 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite确认状态。local proxy failed这个报错通常出现在 Cline 或 Claude Code 启动 MCP 服务时。原因是客户端尝试用本地代理转发请求但代理进程没起来或端口被占。排查方法先确认mysql_mcp_server.py能独立运行不报错再检查 MCP 配置里的command路径是不是绝对路径相对路径在客户端工作目录下会找不到文件最后看env里有没有把TAOTOKEN_BASE_URL传进去缺了它客户端不知道往哪发请求。Error reading choices / choices 字段为空这个报错说明 API 返回体里没有choices数组通常是模型名写错了。比如把deepseek-chat写成了deepseekTaoToken 会返回错误结构。确认 Model ID 拼写DeepSeek 系列在 TaoToken 上的标准名是deepseek-chat和deepseek-reasoner。如果用的是 Claude Code 做润色类任务注意 Claude Code 的配置文件和 DeepSeek 不通用需要单独在settings.json里指定 Anthropic 格式的 Base URL。OAuth 相关报错如果你在 Claude Code 里看到 OAuth token 失效那是因为 Claude Code 默认走 Anthropic 官方鉴权。要切到 TaoToken需要在 Claude Code 的配置文件里把ANTHROPIC_BASE_URL指向https://taotoken.net/api同时把ANTHROPIC_API_KEY设成你的 sk- 密钥。ClaudeCodeAnthropic 的接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里有完整的 settings 片段照着改就行。工具调用死循环模型反复调同一个工具不返回结果。原因是工具返回的错误信息不够明确模型不知道下一步该干嘛。比如execute_mysql_query返回“数据库错误”但没说是表不存在还是语法错模型就会重试。改进方法是把 MySQL 的原始错误信息完整返回模型看到“Table shop_db.Product doesnt exist”就会去调list_tables。6. 把这条链路用起来从查询到 Agent 的延伸跑通基础查询后你可以把 MCP 服务端挂到更复杂的 Agent 流程里。比如做一个“每日库存预警”脚本定时用 DeepSeek 查低于阈值的商品自动生成补货建议发到群里。这时候 MCP 服务端不用改只需要在客户端侧加定时任务和消息推送。如果你要长期跑编码类 Agent 任务建议了解下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite它的额度模型更适合高频工具调用场景。模型对话页面https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite可以快速验证 DeepSeek 对复杂 SQL 的理解能力接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里有 MCP 和各类客户端的完整配置示例。最后提醒一个安全细节MCP 服务端的数据库账号建议只给 SELECT 权限除非你明确需要模型执行写操作。execute_mysql_query虽然能跑 INSERT/UPDATE但生产环境最好在服务端加一层 SQL 白名单校验只放行 SELECT 和 SHOW 类语句。本地开发图省事可以全开上线前一定要收紧。
返回列表