☰
Java 实现 MCP server 接入 TaoToken:打通 DeepSeek 与达梦数据库的企业智能问答配置骨架
2026/9/28 18:50:39 网站建设 项目流程

1. 为什么要在 Java 里自己写 MCP server

企业内网做智能问答,最尴尬的一点是:大模型很聪明,但它看不到你库里的表结构,也不知道“上季度华东区退货率”到底对应哪张表、哪个字段。业务同事用自然语言问一句,模型只能靠猜,猜出来的 SQL 十有八九跑不通。DeepSeek 这类模型在自然语言理解上已经够用,缺的是把它和达梦数据库连起来的那根“数据线”。

MCP(Model Context Protocol)解决的正是这件事。它给模型和业务系统之间定了一套标准接口:模型负责理解人话,MCP server 负责把“查库表结构”“执行 SQL”这些动作暴露成工具,模型按需调用。落到 Java 技术栈里,就是用一个 Spring Boot 服务把达梦的元数据查询和 SQL 执行包装成 MCP tool,再通过 TaoToken 统一走 DeepSeek 的 API 通道。

这套骨架适合谁?适合手里有达梦、团队主力是 Java、又不想把数据库账号密码散落在各个客户端配置里的内网项目。下面我按“先跑通、再排错”的顺序,把配置骨架和验证动作完整给出来。

2. TaoToken 前置:统一 Key 与 API 通道

在写 MCP server 之前,先把模型侧的通道理顺。企业内网常见的问题是:每个开发者各自申请 Key、各自配 base_url,最后审计和额度都失控。TaoToken 在这里的角色是统一入口——你拿到一个 Key,模型对话、编码、Agent 调用都走同一个通道,MCP server 里只需要维护一份配置。

具体动作分三步。第一,登录控制台创建 API Key,建议按项目或按人建,方便后面查用量。第二,确认你要用的模型名,DeepSeek 系列在模型对话页可以直接试跑,先确认通道通不通,再去写 Java 代码,能省掉一半“到底是网络问题还是代码问题”的排查时间。第三,把 base_url 记成https://taotoken.net/api,注意这个地址不带任何查询参数,Key 走标准的 Authorization 头。

如果你后面要做长期编码或 Agent 类任务,可以顺带看一下 Coding Plan,它更适合高频、长会话的场景;只是跑通本篇的问答骨架,用按量 Key 就够了。相关入口我放在文末 CTA 里,这里先把配置写清楚。

3. 可复制的 MCP server 配置骨架

3.1 pom 依赖与启动类

新建一个 Maven 项目,Java 17。核心依赖是 Spring AI 的 MCP server starter,用 webflux 版本走 SSE 传输,这样客户端可以用 SSE 方式连进来。

<dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-server-webflux</artifactId> <version>1.0.0-M6</version> </dependency> <dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver18</artifactId> <version>8.1.3.140</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> </dependencies>

启动类上开启工具扫描,并把 MCP server 的传输方式声明出来:

@SpringBootApplication public class McpServerApplication { public static void main(String[] args) { SpringApplication.run(McpServerApplication.class, args); } @Bean public ToolCallbackProvider databaseTools(DatabaseMetadataService service) { return MethodToolCallbackProvider.builder() .toolObjects(service) .build(); } }

3.2 达梦连接参数

达梦的 JDBC URL 格式和 MySQL 不太一样,schema 要显式带上,否则元数据查询会拿到空结果。下面这份配置放在application.yml里,账号密码建议走环境变量,不要硬编码进仓库。

spring: datasource: url: jdbc:dm://10.10.20.31:5236?schema=BIZ_DW&characterEncoding=UTF-8 username: ${DM_USER} password: ${DM_PWD} driver-class-name: dm.jdbc.driver.DmDriver hikari: maximum-pool-size: 5 connection-timeout: 10000 server: port: 8080

这里有个容易踩的点:达梦默认端口是 5236,不是 3306;schema参数写错的话,getTables返回的列表会是空的,模型就会以为“这个库没表”,然后开始编。所以第一次接的时候,先用客户端工具确认 schema 名,再填进来。

3.3 两个核心 Tool 的实现

MCP server 对外暴露两个工具:一个查库表结构,一个执行 SQL。注解@Tool的 description 非常关键,模型就是靠这段文字判断什么时候该调哪个工具,所以描述要写清楚“返回什么、参数是什么”。

@Service public class DatabaseMetadataService { private final JdbcTemplate jdbcTemplate; public DatabaseMetadataService(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @Tool(description = "获取当前达梦数据库中所有表名及字段注释,用于理解业务数据结构") public String listTables() { String sql = "SELECT TABLE_NAME, COMMENTS FROM USER_TAB_COMMENTS"; List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql); return rows.toString(); } @Tool(description = "执行只读 SELECT 查询并返回结果,入参为完整 SQL 语句") public String executeQuery(@ToolParam(description = "标准 SQL 查询语句") String sql) { if (!sql.trim().toUpperCase().startsWith("SELECT")) { return "仅允许执行 SELECT 查询"; } List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql); return rows.toString(); } }

注意executeQuery里加了一道 SELECT 白名单校验。内网环境里,MCP server 直连生产库本身就有风险,至少要把写操作挡在工具层,别指望模型每次都听话。

3.4 客户端侧 settings.json 示例

如果你用的是支持 MCP 的桌面客户端,配置通常长这样。服务器类型选 SSE,URL 指向本机 8080 的/sse路径:

{ "mcpServers": { "dm-intelligence": { "type": "sse", "url": "http://localhost:8080/sse", "enabled": true } } }

模型侧的 API 配置单独填:base_url 用https://taotoken.net/api,Key 填你在控制台建的那把,模型选deepseek-reasoner或deepseek-chat。这两块分开配,后面换模型不用动 MCP 配置。

4. 验证请求与预期返回

配置写完,先别急着在聊天框里问业务问题,按下面顺序验证,能快速定位问题出在哪一层。

第一步,确认 MCP server 起来了。启动日志里应该能看到工具注册信息,类似Registered tools: listTables, executeQuery。如果没看到,多半是ToolCallbackProvider那个 Bean 没生效。

第二步,直接 curl 一下 SSE 端点,确认服务在监听:

curl -N http://localhost:8080/sse

正常会保持连接并返回事件流。如果连接被拒,检查端口和防火墙。

第三步,在客户端里点开工具页签,手动触发listTables。预期返回是一串表名和注释,比如[{TABLE_NAME=ORDER_MAIN, COMMENTS=订单主表}, ...]。这一步通了,说明达梦连接没问题。

第四步,发一句自然语言问题,比如“订单主表里有多少条记录”。预期链路是:模型先调listTables确认表存在,再调executeQuery执行SELECT COUNT(1) FROM ORDER_MAIN,最后把数字用人话回给你。如果模型直接编了个数字而没调工具,说明工具描述不够清楚,或者客户端没启用 MCP。

5. 本篇常见错排查

报错一:getTables返回空列表。九成是 schema 参数没配对。达梦对 schema 大小写敏感,BIZ_DW和biz_dw可能指向不同对象。先用达梦客户端执行SELECT USER FROM DUAL确认当前 schema。

报错二:SQL 里带*被正则拦下。有些客户端会对工具入参做校验,SELECT *里的星号可能触发规则。规避方式是在工具描述里引导模型写具体字段名,或者在服务端做一次参数清洗,把*展开成字段列表。我试过在提示词里加一句“查询时请列出具体字段”,命中率会高很多。

报错三:模型不调工具,直接回答。检查两处:一是客户端里 MCP 开关是否打开,二是@Tool的 description 是否太笼统。把“查询数据库”改成“执行只读 SELECT 并返回结果集”,模型判断会更准。

报错四:连接超时。内网到达梦的 5236 端口如果不通,Hikari 会在 10 秒后抛异常。先在服务器上telnet 10.10.20.31 5236确认网络,再排查账号权限。

报错五:返回结果太长被截断。大表全量查询会把上下文撑爆。建议在executeQuery里加LIMIT兜底,或者在工具描述里要求模型必须带行数限制。

6. 把通道和工具串起来

到这里,Java 版 MCP server 的骨架就跑通了:达梦负责数据,MCP 负责把数据能力暴露成工具,DeepSeek 负责理解问题并决定调哪个工具,TaoToken 负责把模型调用收敛到一个 Key 和一条通道上。四者各司其职,换数据库或换模型时,改动面都很小。

下一步可以做的:把listTables升级成带字段类型和注释的完整元数据,让模型生成 SQL 更准;给executeQuery加超时和行数上限,避免拖垮库;如果要做长期在线的 Agent,把 Key 换成 Coding Plan 那类更适合长会话的额度。

需要建 Key 或看接入细节,可以从这几个入口进:API Key 管理在 console,接入文档在 doc,想先试模型效果就去 模型对话。先把listTables调通,再往业务问题上走,这条路会顺很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询