内容
<div align="center">
<h1>JustBetter MCP</h1>
<p><em>一个具有动态、基于检索的工具注入的MCP网关。</em></p>
<p>
<img src="https://img.shields.io/badge/TypeScript-5.0-blue" alt="TypeScript" />
<img src="https://img.shields.io/badge/Node.js-18+-green" alt="Node" />
<img src="https://img.shields.io/badge/ONNX-MiniLM-orange" alt="ONNX" />
<img src="https://img.shields.io/badge/sqlite--vec-Vector_DB-blueviolet" alt="SQLite Vec" />
</p>
</div>
<br/>
> **问题:**
> 将大型语言模型(LLM)连接到标准的模型上下文协议(MCP)服务器(例如文件系统、网络搜索器和数据库)会在LLM的上下文窗口中注入数十或数百种工具。
>
> 这个令牌膨胀问题导致`node_modules`爆炸、上下文限制被突破和工具选择准确性严重下降。
> **解决方案:**
> JustBetter MCP通过充当网关/代理来解决这个问题。与其将每个连接服务器的所有工具转储到每个请求中,它使用动态的、基于检索的工具注入来限制发送到LLM的工具。
>
> 它在两种主要模式下运行:**模式2**本质上等同于Anthropic的MCP工具搜索或OpenAI Codex的工具搜索,其中LLM在对话中反应性地请求工具。**模式1**是我们自定义的方法,它在第一次LLM调用之前对原始提示执行语义检索。模式1实现了几乎相同的结果,但可能表现更好,因为LLM不必花费推理时间思考要搜索哪些工具。有关此性能差异的更多详细信息,请参见[令牌使用分析](#令牌使用分析)部分。
---
### 快速链接
- [架构和工作原理](#架构和工作原理)
- [令牌使用分析](#令牌使用分析)
- [设置和快速入门](#设置和快速入门)
---
## 架构和工作原理
JustBetter MCP根据您的配置和客户端生态系统,以两种不同的模式运行。
### 模式1:语义提示注入(JustBetter CLI)
当使用启用语义注入的JustBetter CLI(`"semanticPromptInjection": true`)时,网关充当双重代理。它拦截HTTP聊天请求,对提示进行语义搜索,并在请求到达LLM之前,将所需的确切工具静默注入到有效载荷中。
#### 流程图样式
```mermaid
graph TD
User["用户提示"] --> CLI["JustBetter CLI"]
subgraph "提示拦截(HTTP)"
CLI -->|"1. 聊天请求"| APIProxy["LLM API 代理(:4141)"]
APIProxy <-->|"2. 语义搜索"| Catalog[("工具目录(sqlite-vec)")]
APIProxy -->|"3. 注入模式"| LLM["实际LLM API"]
LLM -->|"4. 响应"| APIProxy
APIProxy -->|"5. 返回JSON"| CLI
end
subgraph "工具执行(MCP)"
CLI -->|"6. 执行工具"| MCPProxy["MCP网关代理"]
MCPProxy -->|"7. 安全门"| Gates["幻觉/批准门"]
Gates -->|"通过"| Upstream["上游MCP服务器"]
Upstream -->|"8. 工具结果"| MCPProxy
MCPProxy -->|"9. 返回"| CLI
end
```
#### 序列图样式
```mermaid
sequenceDiagram
actor User
participant CLI as JustBetter CLI
participant Proxy as LLM API 代理
participant DB as 工具目录
participant LLM as 实际LLM API
participant MCP as MCP网关
participant Upstream as 上游服务器
User->>CLI: 发送提示
note over CLI,LLM: 1. 提示拦截(HTTP)
CLI->>Proxy: 聊天请求
Proxy->>DB: 语义搜索
DB-->>Proxy: 顶部K模式
Proxy->>LLM: 注入模式和转发
LLM-->>Proxy: 返回工具调用JSON
Proxy-->>CLI: 返回响应
note over CLI,Upstream: 2. 工具执行(MCP标准输入输出)
CLI->>MCP: 执行工具
MCP->>MCP: 幻觉/批准门
MCP->>Upstream: 路由到上游服务器
Upstream-->>MCP: 工具结果
MCP-->>CLI: 返回结果
```
### 模式2:反应性工具发现(Cursor,Claude Desktop和CLI)
此模式由Claude Desktop和Cursor等第三方客户端原生使用,也可以在JustBetter CLI中通过设置`"semanticPromptInjection": false`启用。
在此模式下,网关采用反应性方法。它隐藏了上游工具的大型目录,以防止令牌膨胀,并仅公开一个`request_tools`基元。 AI在需要时显式向网关请求工具。这与Anthropic的MCP工具搜索和OpenAI Codex的工具搜索的行为类似,通过一次额外的往返换取巨大的上下文节省。
#### 流程图样式
```mermaid
graph TD
User["用户提示"] --> Client["Claude Desktop / Cursor"]
Client -->|"1. 直接请求"| LLM["Anthropic/OpenAI API"]
LLM -->|"2. '我需要工具!'"| Client
subgraph "反应性工具发现(MCP标准输入输出)"
Client -->|"3. call_tool('request_tools', query)"| MCPProxy["MCP网关代理"]
MCPProxy <-->|"4. 语义搜索"| Catalog[("工具目录(sqlite-vec)")]
MCPProxy -->|"5. 返回紧凑确认"| Client
end
Client -->|"6. 下一回合:执行工具"| MCPProxy
MCPProxy -->|"7. 安全门"| Upstream["上游MCP服务器"]
Upstream -->|"8. 工具结果"| MCPProxy
MCPProxy -->|"9. 返回"| Client
```
#### 序列图样式
```mermaid
sequenceDiagram
actor User
participant Client as Claude Desktop/Cursor
participant LLM as Anthropic/OpenAI API
participant MCP as MCP网关
participant DB as 工具目录
participant Upstream as 上游服务器
User->>Client: 发送提示
note over Client,LLM: 1. 初始请求
Client->>LLM: 直接聊天请求
LLM-->>Client: "我需要工具!"
note over Client,DB: 2. 反应性工具发现
Client->>MCP: call_tool('request_tools')
MCP->>DB: 语义搜索
DB-->>MCP: 顶部K模式
MCP-->>Client: 返回紧凑确认
note over Client,Upstream: 3. 工具执行
Client->>LLM: 下一回合(带有模式)
LLM-->>Client: 执行实际工具
Client->>MCP: 执行工具
MCP->>Upstream: 路由到上游服务器
Upstream-->>MCP: 工具结果
MCP-->>Client: 返回结果
```
### 核心管道安全
无论使用哪种模式,所有工具执行都经过严格的安全机制:
- **幻觉门:** 阻止LLM调用任何未明确注入或请求的工具。
- **前提条件门:** 跳过和隐藏其上游服务器已断开连接或缺乏所需身份验证范围的工具。
- **隔离机制:** 使用模式指纹(SHA-256)标记上游工具更改。如果工具的模式意外更改,则在人工批准之前将其隔离。
---
## 令牌使用分析
### 实验设置
- **模型:** `mistral-large-latest`
- **连接服务器:** `filesystem`,`sqlite`,`websearch`和`terminal`
- **模式3(基准):** 为了比较,我们将模式3建立为基准场景,其中完全绕过语义搜索,并将所有连接的上游服务器的所有可用工具直接转储到上下文窗口中。
### 提示1:多步骤顺序执行
**提示:** *"按顺序运行这些操作,在移动到下一个操作之前确认每个操作的输出:检查Node版本,列出已安装的顶级npm包,并检查当前的git状态。确认所有三个操作后,搜索当前Node.js LTS版本,并根据您的发现告诉我是否应该升级。"*
**总令牌使用量:
<div align="center">
<img src="./charts/prompt1_tokens.png" alt="提示1的令牌使用比较" width="800" />
</div>
### 提示2:多领域知识检索
**提示:** *"搜索Model Context Protocol的最新发行说明,检查modelcontextprotocol/servers GitHub存储库中的开放问题,并为每个找到的两个内容在名为'digest'的sqlite表中插入一行摘要(带有'source'和'summary'列)。"*
**总令牌使用量:
<div align="center">
<img src="./charts/prompt2_tokens.png" alt="提示2的令牌使用比较" width="800" />
</div>
---
## 解释和注意事项
1. **模式1与模式2性能:** 模式1(语义注入)和模式2(反应性发现)都实现了几乎相同的、高度优化的令牌效率。然而,**模式1**在复杂或长期任务的输出质量方面具有理论上的优势。通过在推理之前在代理中处理语义搜索和模式注入,它消除了强制LLM暂停并思考要搜索哪些工具的认知开销,从而保留了其解决实际用户任务的推理能力。
2. **全部注入基准(模式3):** 正如预期的那样,将所有可用的工具从所有连接的MCP服务器直接注入提示(模式3)表现最差,消耗了大量的上下文并降低了整体效率。
3. **OpenCode比较:** 虽然OpenCode在这些测试中表现出最高的令牌使用量,但一个重要的注意事项是OpenCode的环境包括广泛的内置系统提示和默认原生工具,这些都贡献了其令牌计数。虽然这不是一个纯粹的工具开销的完美比较,但它作为一个高度相关的现实基准,证明了JustBetter MCP旨在解决的令牌膨胀问题。
4. **未来工作:输出质量:** 虽然模式1减少认知负荷的理论优势应该在理论上转化为LLM推理能力和整体输出质量的可衡量的改进,但我们尚未进行严格的量化测试来证明这一影响。验证这一假设仍然是未来工作的一个关键主题。
---
## 设置和快速入门
### 最低要求
- **Node.js** (v18+)
- **npm**,**yarn**或**pnpm**
### 配置
在项目根目录中创建一个`config.json`。以下是一个示例格式,详细说明了固定的工具列表、上游服务器列表和LLM代理配置:
```json
{
"semanticPromptInjection": false,
"injectAllTools": false,
"apiProvider": "mistral",
"upstreamServers": [
{
"name": "filesystem",
"command": "npx.cmd",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"./"
]
},
{
"name": "sqlite",
"command": "npx.cmd",
"args": [
"-y",
"mcp-server-sqlite-npx",
"database.db"
]
},
{
"name": "websearch",
"command": "npx.cmd",
"args": [
"tsx",
"src/websearch-server.ts"
]
},
{
"name": "terminal",
"command": "npx.cmd",
"args": [
"tsx",
"src/terminal-server.ts"
]
},
{
"name": "github",
"command": "npx.cmd",
"args": [
"-y",
"@modelcontextprotocol/server-github"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "您的GitHub PAT"
}
}
],
"llmProxy": {
"port": 4141,
"geminiApiKey": "您的Gemini API密钥",
"mistralApiKey": "您的Mistral API密钥",
"model": "mistral-large-2512"
},
"pinnedTools": [],
"destructiveTools": [
"delete_file",
"drop_table"
]
}
```
### 运行网关和TUI
1. **安装依赖项:**
```bash
npm install
```
2. **启动网关和仪表板:**
```bash
npm run dev
```
*(或根据package.json脚本的标准节点执行,例如`npx tsx src/cli.ts`)*
3. **配置您的AI客户端:** 将您的客户端(例如Cursor、Claude Desktop或自定义CLI)设置为使用`http://localhost:4141/v1`作为OpenAI兼容的API基地址。