在LM Studio中利用四个MCP服务器构建本地研究智能体。
LM Studio中的本地研究代理,配备四个MCP服务器:文件系统、GitHub、SearXNG和Camofox,以及经过简化的工具架构、计划提示和基础演示。
来源: How to Turn LM Studio Into a Local Research Agent With MCP Servers
能够搜索、读取文件或提交拉取请求的本地模型已经很有用了。而那种能在同一条推理链中整合所有这些功能来回答单个问题的本地模型,则堪称研究助手。在LM Studio中实现从前者到后者的跨越,需要四台MCP服务器协同工作,同时还得有策略防止它们组合后的工具架构占用过大的上下文窗口,此外还需某种机制促使90亿参数级别的模型能够完成多步骤任务,而非仅调用一个工具后就停止。
这四台服务器分别是文件系统服务器、GitHub服务器、用于搜索的自托管SearXNG实例,以及用于查看搜索结果页面的基于Camofox的浏览器(Camofox)。文件系统服务器的型号为@modelcontextprotocol/server-filesystem,且仅能访问指定目录。通过OAuth可访问GitHub,地址为api.githubcopilot.com/mcp/。SearXNG和Camofox均在Docker环境中运行,通过mcp-searxng和camofox-mcp实现连接。它们各自独立运行。有趣的是,当单个聊天窗口同时整合了所有这些功能时会发生什么。
在进行任何接线操作之前需注意一点:此处的一切都是为常规的在线研究设计的,比如竞争分析、对供应商的尽职调查,或是核实文章中的说法。代理并不知道正在研究什么,也不关心这些,它只会按照指示搜索、获取并读取相关内容。
整个设置流程分为四个阶段:合并服务器、筛选工具列表、为模型提供操作方案,以及运行基础演示。
第一阶段:将四台服务器整合到同一聊天界面中
LM Studio并未限制单次聊天可使用的MCP服务器数量。它会加载所有服务器,并将每台服务器对应的工具结构信息传递给模型。这正是该设置的优势所在,但正如下一阶段将展示的那样,这也是它首先带来的问题。
文件系统及 GitHub 项的配置与独立部署时的设置相同,SearXNG 和 Camofox 项也是如此。后台容器必须已经启动,且其 docker-compose.yml 与 searxng/settings.yml 文件也需存在,因为这些文件此处不会重复配置。唯一的变化是,这四个项现在都位于同一个 mcp.json 文件中:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/jes/research-workspace"
]
},
"github": {
"url": "https://api.githubcopilot.com/mcp/",
"auth": {
"CLIENT_ID": "<your Client ID>",
"CLIENT_SECRET": "<your client secret>"
}
},
"searxng": {
"command": "npx",
"args": ["-y", "mcp-searxng"],
"env": {
"SEARXNG_URL": "http://localhost:8080"
}
},
"camofox": {
"command": "npx",
"args": ["-y", "camofox-mcp"],
"env": {
"CAMOFOX_URL": "http://localhost:8765",
"CAMOFOX_API_KEY": "your-camofox-api-key",
"CAMOFOX_AUTH_MODE": "api_key"
}
}
}
}
有三点细节值得注意。
github选项会触发独立的 OAuth 流程。服务器首次尝试加载时会要求输入相关信息。由于 GitHub 的接口不支持动态客户端注册,因此必须事先手动注册一个 GitHub OAuth 应用,没有其他捷径可走。- 文件系统服务器允许使用的目录是可自行选择的。使用专用的
research-workspace文件夹比使用用户主目录更佳,因为这样能明确显示模型可以访问哪些内容。 CAMOFOX_URL和SEARXNG_URL必须指向 Docker 容器。如果这些容器没有运行,虽然服务器仍能在 LM Studio 中加载,但任何针对它们的工具调用都会失败,初次遇到这种情况时会造成大约二十分钟的困惑。
当这四项功能全部启用,且MCP面板中每个服务器名称旁边的绿色小点变为实心时,该聊天界面就会包含四种文件系统工具、数十种GitHub工具、四种SearXNG工具以及大约四十五种Camofox工具。对于一个90亿参数的模型而言,需要处理的信息量实在庞大,而这正是下一阶段要解决的问题。
第二阶段:维持上下文预算
仅GitHub工具的数量就已构成风险,Camofox工具也是如此。再加上SearXNG工具和文件系统工具,负荷会更加沉重。
在实际问题中的文字被模型读取之前,每个工具的名称、描述及参数结构就已经被分解为标记,纳入模型的上下文中。在参数量有限的小型模型上,这些开销会占用大量可用资源。
最直接的解决办法就是不要启用每台服务器上的所有工具。对于 GitHub,有比在 MCP 面板中手动切换工具更简便的方法。远程服务器会接受 X-MCP-Readonly 标头,这样在 LM Studio 查看其余架构之前,整个连接就会被限制为仅能使用只读工具。使用该标头后,前一步骤中的 github 条目变为:
{
"github": {
"url": "https://api.githubcopilot.com/mcp/",
"auth": {
"CLIENT_ID": "<your Client ID>",
"CLIENT_SECRET": "<your client secret>"
},
"headers": {
"X-MCP-Readonly": "true"
}
}
}
当开启该头部信息后,服务器仅会提供读取类工具:pull_request_read、issue_read、list_commits、get_file_contents、search_repositories以及search_code。任何能够执行删除、合并、推送或创建操作的工具都不存在。这一限制是由GitHub端强制实施的,并非由LM Studio隐藏按钮所致,因此属于真正的限制。这也意味着那些被禁用的写入类工具的架构根本不会被转换为上下文中的令牌,而这正是该阶段的初衷。
如果需要更精细的控制,可以使用X-MCP-Tools,它允许通过逗号分隔的方式明确指定允许使用的工具列表,例如search_code,search_repositories,get_file_contents,list_commits。这种方式适用于明确不需要使用问题处理和拉取请求相关工具的场景。
处于此状态的 GitHub MCP 截图将仅显示 get、read、list、scan 和 search 工具,因为只读标志已被设置为 true,同时还可以选择关闭那些不必要的工具,从而降低令牌成本。
Camofox 没有对应的服务器端标志,因此其工具需要在 MCP 面板中逐个关闭。对于仅用于研究的聊天场景,可关闭的选项包括 delete_download、import_cookies 以及所有与配置文件相关的功能,如 save_profile 和 load_profile,因为研究过程无需使用已保存的浏览器配置文件。
原则是仅保留使用场景所需的功能,其余功能一律禁用。对大多数服务器而言,这属于上下文资源分配的决策,而非安全考虑。GitHub 的情况则有所不同,因为是其服务器端强制实施该规则的。
第4阶段的演示根本不需要GitHub的写入权限,因为唯一的GitHub操作只是读取一个清单文件,这样一来就可以继续保持只读限制。如果后续有任务需要写入数据,比如创建一个问题来记录代理发现的异常,那就为该对话单独设置一个标题。在同一个会话中混用只读和可写入的GitHub连接并不是正确的处理方式。
上下文窗口本身也需要重视。当初架构仅来自单台服务器时,设定4096个令牌作为最低阈值是合理的。但如今有了四台服务器以及经过精简但仍相当庞大的工具列表,4096的数值已经不够用了。应根据模型和硬件的承载能力以及预期对话的时长,将滑块调得更高,甚至可能超过32k。并没有绝对正确的数值,这是在推理空间与可用VRAM之间的权衡,因此请留意LM Studio在聊天输入框下方显示的上下文完整性百分比,并据此进行调整。
第三阶段:模型可遵循的计划
手工编写的智能体有一个LM Studio聊天界面无法自动提供的优势。在脚本中,系统提示语是完全受控的Python字符串,可以明确写出循环流程:搜索、选择来源、获取内容,然后判断该内容是否能回答问题,或是需要再次搜索。
与其暗示存在隐藏的规划选项,不如明确说明LM Studio实际具备的功能。实际上并不存在这样的规划选项,也没有独立的规划设置。
现有的是聊天侧边栏中“模型参数”下的“系统提示语”字段。该提示语可以与温度参数和上下文设置一起保存为带名称的预设,这样无需在每次会话中重新输入。这与手工编写的智能体使用的机制相同,只不过是以文本框的形式呈现,而非代码中的字符串。
类似这样的系统提示语适用于研究类聊天场景:
You are a research assistant with tools for web search, page fetching,
file storage, and GitHub. When asked a factual question you cannot
answer with confidence from memory, follow this plan:
1. Search for the topic using searxng_web_search. Look at more than one
result before deciding a source is good.
2. Fetch the most promising source with camofox's navigate and
snapshot or extract_structured tools, not just the search snippet.
When using camofox always open a new tab before trying to navigate
to a page.
3. If the question needs more than one source to answer confidently,
search again and fetch again before answering.
4. If asked to save findings, write them to a markdown file in the
workspace using the filesystem tools, don't just describe them in chat.
5. State which sources you actually fetched, not just which ones you
found in search results.
关于其运行方式的几点说明:
- 它属于普通散文形式,没有状态机来约束其结构。模型所看到的就是指令内容,它通常会按照这些指令的框架进行响应,但并无保证,就像处理脚本中的系统提示一样。
- 第5步的重要性超出表面所见。如果没有这一步,模型往往会仅依据搜索结果片段作答,而跳过数据获取环节,这就违背了将Camofox纳入处理流程的初衷。
- 将结果保存为预设后,便可在不同对话中直接使用,无需再次粘贴。
在截图中,提示词位于“模型参数”下方,而预设则被保存为“研究对话”。有了提示词和精简后的工具列表,模型便具备了相应的能力以及大致的使用计划。剩下的问题就是它是否真的会按照计划执行。
第4阶段:证明工具已被使用的演示
一个合格的基准测试必须要求使用真实工具。仅凭记忆无法得出正确答案,因此模型要么获取真实来源信息,要么进行猜测。任务内容不能是模型已经记住的,需要能够独立验证,且应具有足够的一般性,避免涉及特定个人。
一个合适的测试示例:让智能体访问某个正在维护或被广泛使用的代码库,然后让它追踪某个特定版本的依赖项,直至找到针对该版本的任何安全警告。在填入三个占位符后,即可将下面的提示语粘贴到聊天界面中:
I want you to check one dependency in a GitHub repository for known
security advisories. Do this:
1. In the repository <owner>/<repo>, read <manifest-file> using
get_file_contents.
2. From that file, find the exact pinned version of the dependency
"<dependency-name>".
3. Search the web for known security advisories filed against that
specific version of "<dependency-name>".
4. Fetch the actual advisory page(s) you find rather than relying on
the search snippet alone.
5. Write a short summary to dependency-risk.md in the workspace: the
dependency name, the pinned version, any advisories found (with
severity and a link), and a one-line recommendation.
占位符的使用方式如下:
<owner>/<repo>表示任何具有读取权限的仓库。个人项目与作为依赖的公共项目均可使用。<manifest-file>指定项目所依赖的依赖文件,例如go.mod、pyproject.toml、requirements.txt或package.json。<dependency-name>是该清单中的某个单个依赖项,最好是真正有用的那个。
如果没有合适的仓库可用,OWASP提供的故意设计为不安全的训练应用juice-shop/juice-shop可以充当替代。其package.json中包含了足够多的曾被标记为有问题的依赖项,因此搜索通常能找到合适的选项,而express-jwt和sanitize-html都是不错的初始选择。填妥后的版本如下:
I want you to check one dependency in a GitHub repository for known
security advisories. Do this:
1. In the repository juice-shop/juice-shop, read package.json using
get_file_contents.
2. From that file, find the exact pinned version of the dependency
"express-jwt".
3. Search the web for known security advisories filed against that
specific version of "express-jwt".
4. Fetch the actual advisory page(s) you find rather than relying
on the search snippet alone.
5. Write a short summary to dependency-risk.md in the workspace:
the dependency name, the pinned version,
any advisories found (with severity and a link),
and a one-line recommendation.
发送该指令后,代理将按照顺序执行五个步骤:读取GitHub内容、外部搜索、外部数据获取,最后是文件写入,具体速度取决于硬件的性能。
执行此指令时调用了全部四个MCP服务器,共消耗了37803个令牌。
选择此指令是有意为之。答案取决于相关代码库及其固定内容,而且用于搜索的CVE数据库会持续更新,因此无法提前给出确定的结果。
验证模型是否正常工作需要两个步骤。首先打开清单文件并亲自阅读其中标记的版本,以确认GitHub返回的结果是否正确。之后,通过GitHub自身的安全公告搜索功能或NVD来核对相关警告信息。如果这两者的结果都与模型的报告一致,那就构成了真实的依据:说明模型确实读取了清单文件,也确实获取了相关警告页面,而非凭着“某个库曾有过CVE”这类模糊的记忆来回答问题。
演示还表明,仅使用第二阶段的只读标头就足够了。整个流程包括从GitHub读取数据、外部搜索、外部获取内容以及本地文件写入,因此无需GitHub的写入权限,该标头也可以保留。通过一次请求即可同时调用所有四台服务器:GitHub读取清单,SearXNG搜索相关警告信息,Camofox获取警告页面内容,文件系统则保存最终结果。这为在开展实际研究之前快速确认整个架构连接正确提供了便利。
存在的缺陷
与其假装整个流程端到端都可靠,不如明确指出其中的薄弱环节。
有时模型会直接从搜索片段中获取答案而跳过页面获取步骤,即便系统提示要求它这样做。这种情况在那些简短且看似简单的提问中更为常见,因为模型似乎认为这些搜索片段已经足够好。随后发送一条指令要求其获取完整页面通常就能解决问题。并非模型无法做到,只是90亿参数的模型在某些判断上会出现失误。
偶尔,面对数十个从未使用过的GitHub工具时,模型会选择某个看似合理但实际上错误的工具,比如本应使用list_issues却选了list_pull_requests。在第二阶段进行的筛选是最佳的防御措施——通过减少相似选项的数量,就能降低选错工具的概率。
尽管如此,这些措施仍无法让该代理成为确定性的处理流程。在需要确定性的场景中,脚本才是合适的工具,而手写的循环更接近这一要求。将各组件集成到LM Studio中的优势在于模型能够适应任何被提出的问题,但代价是其有时会表现不佳。通过观察它处理几项研究问题,就能最快了解它在哪些方面值得信赖,哪些方面需要进一步引导。
最终配置
经过四个阶段的设置后,LM Studio的聊天界面会运行四个MCP服务器。其工具列表已被精简,以便为思考留出足够空间。系统提示为原本空白的9B模型提供了遵循的结构,而接地演示则确保实际页面会被获取,而非从内存中召回答案。具体而言:
- 在单个聊天窗口中即可使用文件系统、GitHub、SearXNG和Camofox功能。
- 精简后的工具集,再加上足够大的上下文窗口,可容纳完整的架构而无需局限于单服务器模式。
- 系统提示可保存为预设,这样模型就能自动规划搜索、获取和保存的流程,使用的是LM Studio界面实际提供的功能,而非并不存在的配置选项。
- 可通过重复执行的演示来验证各部分功能,所有部分均可独立检查,且仅需一个提示即可同时调用四台服务器。
还有扩展的空间。在 SearXNG 之外再增加一个搜索后端,就可以对搜索结果进行相互核对。每次获取数据后都进行摘要处理,就能避免过长页面在加载时占用过多上下文。对于经常使用此工具的人来说,通过脚本自动生成预设配置,就能让每次新的研究对话都处于正确设置状态,无需手动调整。
有一个结论反复出现:在手动将文件系统、搜索功能、浏览功能以及代码托管服务这些组件整合在一起,并观察每个环节可能出现的问题后,就会发现更复杂的代理框架本质上还是那些相同的组件,只不过被额外的抽象层所掩盖。只有那些已经了解其底层原理的人,才会认为接受这种权衡是合理的。
相关阅读
- 实用指南:使用EODHD的MCP服务器构建AI金融智能体 — 该指南的详细操作步骤,包括合同、检查项,以及为无需自行开发MCP系统的团队提供的现成代码模板。
- Playwright还是浏览器智能体?脚本自动化为何仍占优势 — 对Playwright脚本与基于MCP的浏览器智能体的对比分析:脆弱性、确定性、成本、实际发票处理案例、值得关注的工具、安全风险以及决策框架。