资讯动态

SQLite+FTS5+BM25构建本地上下文感知系统(context-mode)实战指南

发布时间:2026/10/15 12:16:13 来源:尧图企业网站定制
1. “context-mode”到底是什么别被术语唬住它本质是让工具真正“听懂你话”的底层机制最近在多个技术社区和开发群聊里“context-mode”这个词出现频率陡增尤其和MCP、SQLite、FTS5、BM25这些词高频捆绑。很多人第一反应是“又一个新概念是不是某个大厂刚发布的黑科技”其实完全不是。我从去年底开始在三个不同项目中深度落地这个模式实测下来它根本不是什么颠覆性发明而是一套把已有成熟技术重新拧成一股绳的工程实践方法论——核心目标就一个让本地运行的工具比如代码编辑器插件、CLI命令行工具、甚至轻量桌面应用在处理用户请求时不再只盯着当前光标位置那几行代码或当前打开的文件而是能主动、精准、低延迟地调用它“本该知道”的上下文信息。什么叫“本该知道”举个最直白的例子你在VS Code里写一个Java Service类光标停在getUserById()方法里按快捷键想查这个方法被哪些Controller调用了。传统做法是靠符号跳转Symbol Navigation但一旦涉及Spring AOP代理、动态代理或跨模块调用符号跳转就失效了。而启用context-mode后工具会瞬间从本地SQLite数据库里拉出过去24小时所有与User实体相关的日志片段、测试用例断言、Git提交记录中修改过的字段名、甚至你上周在Notion里写的接口设计文档草稿如果已同步索引全部按相关性排序直接呈现在侧边栏。这不是AI幻觉是真实数据的实时聚合。关键词“context-mode”本身没有官方定义它更像是开发者社区自发形成的一个共识性标签指代一种以本地SQLite为中枢、以FTS5全文检索为引擎、以BM25算法为打分标准、由MCP协议统一调度的上下文感知工作流。MCPModel Context Protocol在这里不是某种神秘协议而是指一套轻量级的进程间通信规范——它规定了前端UI比如IDE插件如何向后台服务比如一个常驻内存的Rust编写的索引服务发送查询请求以及后者如何返回结构化上下文片段。SQLite之所以成为事实标准是因为它零配置、单文件、ACID可靠且FTS5模块原生支持BM25——这三点加起来让“在笔记本上跑一个毫秒级响应的语义搜索引擎”从理论变成了每天都在发生的日常。适合谁参考如果你正在做以下任何一件事这篇就是为你写的给VS Code/IntelliJ开发插件想让插件“更聪明”而不是更重维护一个需要频繁查日志、翻文档、比对历史版本的运维或测试平台在资源受限的嵌入式设备或老旧笔记本上部署本地知识库或者单纯厌倦了每次搜索都要切到浏览器、输关键词、再人工筛选结果。它不依赖GPU不调用远程API所有数据留在你硬盘里连网络都不用开。我用一台2015年的MacBook Pro实测十万条日志记录的BM25相关性检索平均响应时间是37ms——比你敲完回车键的手速还快。2. 整体架构设计为什么必须是SQLiteFTS5BM25MCP这条技术链2.1 拒绝“高大上”陷阱为什么不用Elasticsearch或PostgreSQL刚接触context-mode时我也本能地想用更“专业”的方案。试过Docker跑一个精简版Elasticsearch也试过PostgreSQL开启pg_trgm扩展。结果呢前者启动要12秒内存常驻600MB一次简单查询带宽占用2MB后者建全文索引耗时8分钟且pg_trgm只支持n-gram模糊匹配对“用户管理”和“user management”这种跨语言同义词束手无策。而context-mode要解决的核心矛盾是在资源有限的终端设备上实现亚秒级、高相关性、零外部依赖的上下文召回。所有技术选型都必须服务于这个铁律。SQLite胜出的关键在于它把“数据库”这个概念降维到了“文件系统扩展”。你不需要守护进程、不需要端口、不需要用户权限管理。一个.db文件双击就能用DB Browser for SQLite打开查看用sqlite3 my.db命令行就能执行任意SQL在C#、Python、Rust里连接字符串就是Data Sourcemy.db——就这么简单。更重要的是SQLite的FTS5模块是内建的编译时默认开启无需额外安装扩展。我对比过FTS4和FTS5FTS4的BM25实现是硬编码的简化版权重无法调整FTS5则提供了完整的bm25()函数允许你精细控制k1词频饱和度和b文档长度归一化参数这对提升技术文档检索准确率至关重要——比如在查“NullPointerException”时我们希望它优先匹配堆栈跟踪里的完整异常类名而不是泛泛匹配所有含“null”的日志行。2.2 BM25不是玄学手把手算清你的第一条相关性分数很多教程把BM25讲得云里雾里动不动就贴公式。其实你只要记住三件事它解决的核心问题是为什么“在100篇文档中出现5次的词”比“在10篇文档中出现5次的词”价值更低它的打分结果是一个可比数字值越大文档越相关但它本身没单位不能直接说“0.8分比0.3分好两倍多”。在SQLite FTS5里你调用bm25()函数时传的两个参数就是在告诉引擎“这是我业务场景下的最佳平衡点”。来算个真实例子。假设你要索引一批Linux系统日志其中一条是Jan 15 10:23:41 server sshd[1234]: Failed password for root from 192.168.1.100 port 54322 ssh2你想让包含Failed password的行排在前面。先看基础数据这条日志总长度字数L 82所有日志的平均长度AvgL 75Failed在整个日志库中出现的文档数DF 120共10000条日志Failed在这条日志中出现次数TF 1BM25公式核心部分是score TF / (TF k1 * (1 - b b * L/AvgL)) * log((N - DF 0.5) / (DF 0.5))SQLite FTS5的bm25(k1,b)函数就是封装了这个计算。我实测发现对技术日志这类短文本k11.2, b0.75效果最好k11.2让词频增长更平缓避免单个高频词如“the”主导分数b0.75强调文档长度归一化确保一条82字的日志和一条200字的错误报告在长度惩罚上合理。你不需要背公式但必须理解调整这两个参数就是在教引擎“什么对你更重要”。我在RuoYi-Vue-Pro项目合并MCP功能时把b从默认0.5调到0.85因为项目文档普遍很长短小精悍的报错提示反而更珍贵——调参后NullPointerException的召回准确率从68%升到92%。2.3 MCP协议不是新协议而是给老技术装上“神经突触”MCPModel Context Protocol这个词听起来很AI但拆开看它解决的只是三个古老问题怎么让前端IDE插件安全地告诉后端索引服务“我要查‘Redis连接超时’请给我Top10相关片段”后端查完后怎么把结果含原文、来源文件、时间戳、相关性分数打包不丢不乱地送回去如果用户同时开了5个编辑器窗口每个窗口发来不同请求后端怎么不搞混、不阻塞、不崩溃答案就是MCP定义的极简JSON-RPC风格消息{ jsonrpc: 2.0, method: context.search, params: { query: Redis连接超时, limit: 10, filters: [log, config] }, id: 12345 }响应也是标准JSON{ jsonrpc: 2.0, result: [ { content: redis.timeout5000 # 单位毫秒, source: /app/config/application.yml, timestamp: 2024-05-20T09:15:22Z, score: 0.924 } ], id: 12345 }关键在于MCP不规定传输层——你可以用Unix Domain SocketLinux/macOS、Named PipeWindows甚至HTTP调试用。我选择Unix Socket因为零序列化开销单次请求往返0.5ms。所谓“协议”本质就是约定好“说话的格式”而不是发明新语言。这也是为什么x32dbg的MCP插件、IDA的MCP插件、甚至CherryStudio的MCP流式输出工具都能无缝对接同一个后端服务——它们只是换了种方式“开口说话”。3. 核心细节解析从建库、索引到查询每一步都是经验之谈3.1 SQLite建库与FTS5虚拟表字段设计决定80%的检索质量建一个能支撑context-mode的SQLite库远不止CREATE TABLE那么简单。我踩过最大的坑是在初期把所有数据塞进一个content TEXT字段结果发现无法区分“代码片段”和“日志文本”的语义权重时间戳只能存字符串排序和范围查询慢得像蜗牛来源文件路径过长FTS5索引膨胀到原始数据的3倍。正确的做法是用物理表FTS5虚拟表双层结构。物理表存元数据FTS5表专注全文检索。我的标准建表SQL如下-- 物理表存不可变元数据 CREATE TABLE context_items ( id INTEGER PRIMARY KEY, source_type TEXT NOT NULL CHECK(source_type IN (log, code, doc, note)), source_path TEXT NOT NULL, timestamp DATETIME NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- FTS5虚拟表专注文本检索关联物理表 CREATE VIRTUAL TABLE context_fts USING fts5( title, -- 文档标题如UserService.java content, -- 主体内容最大2MB tokenizeunicode61 remove_diacritics1, -- 支持中文分词 contentcontext_items, content_rowidid ); -- 创建触发器保持物理表和FTS5表同步 CREATE TRIGGER context_items_ai AFTER INSERT ON context_items BEGIN INSERT INTO context_fts(rowid, title, content) VALUES (new.id, new.source_path, new.content); END;这里有几个血泪经验tokenizeunicode61 remove_diacritics1是必须的。它让SQLite把café和cafe视为同一词对国际化项目至关重要。不加这个你搜résumé永远找不到resume。content_rowidid这个绑定让FTS5表和物理表通过rowid强关联。查询时你拿到FTS5的rowid就能用SELECT * FROM context_items WHERE id ?瞬间查到完整元数据避免N1查询。title字段单独拎出来是为了给它更高权重。我在查询时会用bm25(1.2, 0.75, title, content)让标题匹配的分数天然比正文高30%——毕竟NullPointerException出现在标题里比出现在某行日志正文里相关性高得多。提示不要在FTS5表里存二进制数据如图片base64。FTS5是为文本优化的存大二进制会让索引体积暴增查询变慢。我的做法是图片存文件系统FTS5里只存img src/path/to/img.png这样的HTML标签既保留语义又不拖累性能。3.2 数据摄入管道十万条数据如何在30秒内完成索引“十万条数据SQLite查询需要多久”这是热搜里最常问的问题。答案取决于你怎么喂数据。我实测过三种方式方式10万条日志索引耗时内存峰值索引体积适用场景逐条INSERT12分38秒8MB120MB调试用绝对不用在生产事务包裹批量INSERT48秒45MB95MB小批量更新1000条FTS5的optimize命令临时表导入27秒18MB88MB推荐全量重建最优解是第三种。原理是先把原始数据导入一个临时表再用FTS5的INSERT INTO ... SELECT一次性灌入最后执行INSERT INTO context_fts(context_fts) VALUES(optimize)强制合并段。具体步骤创建临时表CREATE TEMP TABLE temp_import AS SELECT * FROM context_items LIMIT 0;用.import命令SQLite CLI或sqlite3_exec()批量导入CSVsqlite3 my.db .mode csv .import /tmp/logs.csv temp_import一次性灌入FTS5INSERT INTO context_fts(rowid, title, content) SELECT id, source_path, content FROM temp_import;优化索引INSERT INTO context_fts(context_fts) VALUES(optimize);为什么快因为避免了FTS5内部段segment的频繁分裂和合并。逐条插入时每条记录都可能触发段分裂而批量导入后一次optimize引擎会智能合并所有小段为几个大段查询时只需读取更少的磁盘块。我在Rocky Linux上用C#写的摄入服务就是这套流程实测吞吐量稳定在3800条/秒。注意optimize不是万能的。如果数据持续写入频繁调用它反而降低写入性能。我的策略是每天凌晨3点自动触发全量optimize白天写入时只用事务批量INSERT不调用optimize。3.3 查询实现从基础BM25到多条件融合的实战技巧最简单的查询就是SELECT c.*, f.score FROM context_items c JOIN context_fts f ON c.id f.rowid WHERE f MATCH Redis连接超时 ORDER BY f.score DESC LIMIT 10;但这只是入门。真实场景需要更精细的控制。以下是我在Codex接入蓝湖MCP、Dify浏览器MCP等项目中沉淀的四个必用技巧技巧1用highlight()函数高亮关键词FTS5内置highlight()能自动给匹配词加b标签SELECT highlight(context_fts, 2, b, /b) as highlighted_content FROM context_fts WHERE context_fts MATCH NullPointerException;返回的highlighted_content里NullPointerException会被包在b里前端直接innerHTML渲染即可。比自己用正则替换稳得多且支持中文分词边界。技巧2用snippet()生成摘要预览用户不想点开每条结果看全文。snippet()能提取匹配词周围的上下文SELECT snippet(context_fts, 2, b, /b, ..., 10) as preview FROM context_fts WHERE context_fts MATCH Redis连接超时;参数10表示最多返回10个词的摘要。实测下来...作为省略符比[...]更自然且不会和代码里的省略号混淆。技巧3多字段加权查询当title和content重要性不同时用bm25()显式加权SELECT c.*, bm25(1.2, 0.75, title, content) as score FROM context_items c JOIN context_fts f ON c.id f.rowid WHERE f MATCH title:Redis AND content:超时 ORDER BY score DESC;注意MATCH子句里的title:前缀它让FTS5只在title字段里搜Redis在content字段里搜超时比全文混搜精准得多。技巧4时间衰减因子新日志比旧日志更有参考价值。我在查询时动态加入时间权重SELECT c.*, bm25(1.2, 0.75, title, content) * (1.0 / (1.0 0.0001 * (julianday(now) - julianday(c.timestamp)))) as final_score FROM context_items c JOIN context_fts f ON c.id f.rowid WHERE f.MATCH Redis连接超时 ORDER BY final_score DESC;julianday()把日期转为天数0.0001是衰减系数——距今100天的日志分数衰减约1%足够平滑。这个小改动让线上故障排查的首次命中率提升了22%。4. 实操过程从零搭建一个可运行的context-mode服务含完整代码4.1 环境准备Linux/macOS/Windows全平台兼容方案第一步永远是确认SQLite版本。FTS5和BM25支持要求SQLite ≥ 3.19.02017年发布但很多系统自带版本太老。比如Ubuntu 20.04默认是3.31够用但CentOS 7默认是3.7必须升级。我的跨平台安装脚本如下Linux/macOS用Homebrew或apt# macOS brew install sqlite3 # Ubuntu/Debian sudo apt update sudo apt install sqlite3 libsqlite3-dev # CentOS/Rocky Linux需编译 wget https://www.sqlite.org/2023/sqlite-autoconf-3430000.tar.gz tar xzf sqlite-autoconf-3430000.tar.gz cd sqlite-autoconf-3430000 ./configure --prefix/usr/local make sudo make install export PATH/usr/local/bin:$PATH # 加入~/.bashrcWindows免安装方案直接下载预编译二进制访问 https://www.sqlite.org/download.html下载sqlite-tools-win32-x86-*.zip32位通用或sqlite-tools-win32-x64-*.zip64位解压后sqlite3.exe就是全部双击即用。验证是否支持FTS5sqlite3 --version # 输出应类似3.43.0 2023-08-29 19:01:37 ... sqlite3 :memory: PRAGMA compile_options; | grep -i fts5 # 应输出ENABLE_FTS5注意Windows下用sqlite3.exe时路径中的反斜杠\要写成正斜杠/或双反斜杠\\否则SQLITE_ERROR。比如C:/data/my.db不是C:\data\my.db。4.2 后端服务用Rust写一个极简MCP服务器附完整源码为什么选Rust因为context-mode服务的核心诉求是零依赖、静默运行、内存可控、启动飞快。Rust编译出的二进制文件是单文件无运行时内存占用恒定在12MB左右比Node.js的300MB或Python的150MB友好太多。以下是我开源的mcp-context-server核心逻辑已删减日志和错误处理保留主干// main.rs use std::collections::HashMap; use std::fs; use std::net::{TcpListener, TcpStream}; use std::io::{Read, Write}; use rusqlite::{Connection, params}; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] struct JsonRequest { jsonrpc: String, method: String, params: SearchParams, id: u64, } #[derive(Deserialize)] struct SearchParams { query: String, limit: usize, filters: VecString, } #[derive(Serialize)] struct JsonReply { jsonrpc: String, result: VecSearchResult, id: u64, } #[derive(Serialize)] struct SearchResult { content: String, source: String, timestamp: String, score: f64, } fn handle_search(conn: Connection, params: SearchParams) - VecSearchResult { let mut stmt conn.prepare( SELECT c.content, c.source_path, c.timestamp, bm25(1.2, 0.75, f.title, f.content) as score FROM context_items c JOIN context_fts f ON c.id f.rowid WHERE f MATCH ?1 ORDER BY score DESC LIMIT ?2 ).unwrap(); let mut rows stmt.query_map(params, |row| { Ok(SearchResult { content: row.get(0)?, source: row.get(1)?, timestamp: row.get(2)?, score: row.get(3)?, }) }).unwrap(); let mut results Vec::new(); while let Some(row) rows.next() { if let Ok(r) row { results.push(r); } } results } fn main() - std::io::Result() { let listener TcpListener::bind(127.0.0.1:8080)?; println!(MCP Context Server listening on 127.0.0.1:8080); for stream in listener.incoming() { let mut stream stream?; let mut buffer [0; 1024]; let n stream.read(mut buffer)?; let request_str String::from_utf8_lossy(buffer[..n]); // 解析JSON-RPC let req: JsonRequest serde_json::from_str(request_str).unwrap(); // 执行查询 let conn Connection::open(context.db).unwrap(); let results handle_search(conn, req.params); // 构造响应 let reply JsonReply { jsonrpc: 2.0.to_string(), result: results, id: req.id, }; let reply_str serde_json::to_string(reply).unwrap(); // 发送响应 stream.write_all(reply_str.as_bytes())?; } Ok(()) }编译命令cargo build --release # 生成 ./target/release/mcp-context-server这个二进制文件就是你的context-mode心脏。把它放在后台运行nohup ./target/release/mcp-context-server /dev/null 21 前端插件如VS Code的MCP扩展就可以通过TCP向127.0.0.1:8080发请求了。整个服务没有Web框架、没有ORM、没有中间件就是裸SQL和裸Socket所以它能在树莓派上跑在WSL里跑在Docker容器里跑毫无压力。4.3 前端集成VS Code插件三步接入MCP有了后端前端接入就简单了。以VS Code为例我写了一个最小可行插件extension.tsimport * as vscode from vscode; import * as net from net; export function activate(context: vscode.ExtensionContext) { let disposable vscode.commands.registerCommand(context.search, async () { const editor vscode.window.activeTextEditor; if (!editor) return; const selection editor.selection; const word editor.document.getText(selection).trim() || error; // 构造MCP请求 const request JSON.stringify({ jsonrpc: 2.0, method: context.search, params: { query: word, limit: 5 }, id: Date.now() }); // TCP连接后端 const client net.createConnection({ port: 8080 }, () { client.write(request); }); client.on(data, (data) { try { const reply JSON.parse(data.toString()); const results reply.result as Array{content: string, source: string, score: number}; // 显示结果 const items results.map(r ({ label: ${r.source} (score: ${r.score.toFixed(3)}), description: r.content.substring(0, 50) ... })); vscode.window.showQuickPick(items).then(item { if (item) { vscode.window.showInformationMessage(Match: ${item.label}); } }); } catch (e) { vscode.window.showErrorMessage(MCP query failed); } client.destroy(); }); }); context.subscriptions.push(disposable); }安装步骤把代码存为extension.tsnpm install types/vscode --save-devvsce package打包成.vsixVS Code里CtrlShiftP→Extensions: Install from VSIX→ 选中打包文件。重启VS Code按CtrlShiftP输入context.search回车选中一段文字如NullPointerException就会弹出Top5相关上下文。整个过程从点击到结果弹出实测平均耗时210ms含网络往返比传统全局搜索快5倍。5. 常见问题与排查技巧实录那些文档里不会写的坑5.1 “Codex无法找到MCP”先检查这三件事这是新手最高频的报错。表面看是Codex找不到服务实际90%是环境配置问题。按顺序排查端口是否被占# Linux/macOS lsof -i :8080 # Windows netstat -ano | findstr :8080如果有其他进程占着要么杀掉它kill -9 PID要么改MCP服务端口改TcpListener::bind里的端口号。防火墙是否拦截Codex运行在浏览器沙箱里无法直连127.0.0.1。必须用localhost且Chrome/Firefox默认允许。如果还是不行在Chrome地址栏输入chrome://flags/#unsafely-treat-insecure-origin-as-secure把http://localhost:8080加进去并启用Insecure origins treated as secure。CORS头缺失仅限HTTP方式如果你用HTTP而非TCP比如调试时后端必须返回CORS头stream.write_all(bHTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\n\r\n)?; stream.write_all(reply_str.as_bytes())?;否则浏览器会静默失败控制台只报“CORS error”。5.2 “SQLite修改字段的类型”误区FTS5表不能ALTER COLUMN很多开发者想给FTS5表加个priority INTEGER字段来手动干预排序然后执行ALTER TABLE context_fts ADD COLUMN priority INTEGER;结果报错Error: near ADD: syntax error。这是因为FTS5虚拟表不支持ALTER TABLE。正确做法只有两个方案A推荐用物理表存priority查询时JOINALTER TABLE context_items ADD COLUMN priority INTEGER DEFAULT 0; -- 查询时 SELECT c.*, f.score * (1.0 c.priority * 0.1) as weighted_score FROM context_items c JOIN context_fts f ON c.id f.rowid WHERE f.MATCH query;方案B重建FTS5表-- 1. 导出数据 .output backup.csv .mode csv SELECT rowid, title, content FROM context_fts; .output stdout -- 2. 删除旧表 DROP TABLE context_fts; -- 3. 重建加新字段 CREATE VIRTUAL TABLE context_fts USING fts5(title, content, priority); -- 4. 导入数据需修改CSV格式方案B耗时长且期间服务不可用只建议在初始化阶段用。5.3 性能瓶颈定位当查询变慢先看这三个指标不是所有慢都是SQL问题。我用sqlite3_analyzer工具SQLite官网提供分析过上百个生产库慢查询的根因分布如下根因占比诊断命令解决方案FTS5段过多100个42%SELECT count(*) FROM context_fts_segdir;执行INSERT INTO context_fts(context_fts) VALUES(optimize);未建索引的物理表JOIN28%EXPLAIN QUERY PLAN SELECT ...在context_items.id上建CREATE INDEX idx_items_id ON context_items(id);查询未用MATCH走了全表扫描19%EXPLAIN QUERY PLAN SELECT * FROM context_fts WHERE content LIKE %xxx%;强制用WHERE context_fts MATCH xxx禁用LIKE最狠的诊断命令是# 开启SQLite查询分析 sqlite3 my.db EXPLAIN QUERY PLAN SELECT c.* FROM context_items c JOIN context_fts f ON c.idf.rowid WHERE f MATCH error; # 输出应包含SCAN TABLE context_fts VIRTUAL TABLE INDEX 0:~ # 如果出现SCAN TABLE context_fts说明没走FTS5索引是严重错误5.4 Windows下“x32dbg 的mcp插件”加载失败试试这个注册表补丁x32dbg是32位程序而很多新编译的MCP服务是64位。32位进程无法加载64位DLL。解决方案用Rust编译32位版本rustup target add i686-pc-windows-msvc cargo build --target i686-pc-windows-msvc --release把生成的mcp-context-server.exe放到x32dbg的plugins目录关键一步在Windows注册表HKEY_CURRENT_USER\Software\x32dbg\Plugins下新建字符串值MCP_SERVER_PATH值设为C:\full\path\to\mcp-context-server.exe。x32dbg插件会读这个注册表项来定位服务而不是硬编码路径。这个技巧是我在逆向x32dbg源码时发现的官方文档完全没提。6. 进阶扩展从单机context-mode到团队知识协同网络6.1 多人共享索引用SQLite WAL模式实现安全并发一个团队共用一个context.db很多人觉得不可能怕写冲突。其实SQLite的WALWrite-Ahead Logging模式就是为此生的。启用方式极其简单PRAGMA journal_mode WAL; PRAGMA synchronous NORMAL;WAL模式下写操作不锁整个数据库只锁需要修改的页读操作完全不阻塞可以同时有100个客户端读。我在一个5人开发组实测共享一个NAS上的context.db挂载为/mnt/nas/context.db每人本地运行自己的MCP服务Connection::open(/mnt/nas/context.db)同时执行INSERT INTO context_items ...零冲突零死锁查询响应时间比单机慢15%但在可接受范围内。注意WAL模式要求数据库文件所在文件系统支持原子renameNTFS、ext4、APFS都支持但NFSv3不支持。如果挂载NFS务必用NFSv4。6.2 与现有系统集成RuoYi-Vue-Pro合并MCP功能的实操路径RuoYi-Vue-Pro是JavaVue的后台管理系统。要把MCP能力注入进去我做了三件事后端增加MCP查询EndpointSpring BootPostMapping(/api/mcp/search) public ListContextResult search(RequestBody McpRequest req) { // 直接JDBC查context.db返回JSON return jdbcTemplate.query(SELECT ..., new ContextRowMapper(), req.getQuery()); }前端Vue组件调用template input v-modelquery keyup.enterdoSearch placeholder

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑