内容
# 4D 数据 MCP
一个适用于 4D 数据库的 [MCP(模型上下文协议)](https://modelcontextprotocol.io) 服务器。它允许 MCP 客户端 — Claude Code、Claude Desktop 或任何其他支持 MCP 的工具 — discover 一个 4D 应用程序的模式,查询和修改其数据通过 ORDA,并调用白名单项目方法,所有这些都通过在 4D 中强制执行的每个令牌功能进行控制。
该系统构建为两个协作的半部分,通过版本化的 HTTP 线缆合约连接:
```
MCP 客户端(Claude Code / Claude Desktop / ...)
│ stdio (MCP 协议)
▼
半部分 A — mcp-server/ Node.js stdio MCP 服务器
│ POST /mcp — JSON 信封 {v:1, action, params},Bearer 令牌
▼
半部分 B — 4d-mcp-server/ 4D 组件:HTTP 处理器 + ORDA
│
▼
主机 4D 应用程序的数据存储(ds)
```
## 两个半部分如何协同工作
**半部分 A** (`mcp-server/`) 是一个薄的 Node.js 翻译器。它通过 stdio 与客户端通信 MCP,并公开一个工具用于每个线路操作(`4d_get_schema_digest`、`4d_query_entities`、`4d_get_entity`、`4d_create_entity`、`4d_update_entity`、`4d_delete_entity`、`4d_call_method`)。每个工具调用都被封装在 JSON 信封中,并作为 `POST /mcp` 与 Bearer 令牌一起转发。它除了构造信封、响应验证和错误映射之外,没有自己的逻辑 — 它正好显示出半部分 B 允许的内容。
**半部分 B** (`4d-mcp-server/`) 是一个安装在主机应用程序中的 4D 组件。它的 `POST /mcp` 处理器验证 Bearer 令牌,将其解析为功能对象(它可以读取/写入哪些数据类,可以调用哪些操作),应用部署配置门控(启用标志、HTTPS 要求、主体大小限制、速率限制、表暴露),然后路由到主机 `ds` 的匹配 ORDA 操作。所有安全强制都在这里,在 4D 端。
它们之间的合约 — 信封形状、八个操作、错误分类、分页规则 — 在 **`ai-context/mcp_data_wire_contract.md` (v1)** 中指定,这是两个半部分都遵循的真实来源。任一半部分都可以独立于它进行测试:半部分 A 的单元测试在 4D 的固定装置上运行,而半部分 B 的 curl 套件在没有 MCP 客户端的情况下练习真正的 HTTP 路径。
一个典型的会话:客户端调用 `4d_get_schema_digest` 以了解其令牌可以看到哪些数据类和可调用操作,然后查询/创建/更新实体或调用白名单方法。合约错误以类型代码返回(`CAP_DENIED`、`BAD_PARAMS`、`NOT_FOUND`,...),以便模型可以合理地做出反应。
## 仓库布局
| 路径 | 它是什么 |
|------|-----------|
| `mcp-server/` | 半部分 A — Node.js/TypeScript stdio MCP 服务器([README](mcp-server/README.md)) |
| `4d-mcp-server/` | 半部分 B — 4D 组件项目([README](ai-context/README_halfB.md)) |
| `4d-mcp-server_Build/` | 已构建组件输出 |
| `ai-context/` | 线缆合约、设计笔记、每半部分文档 |
## 安装和设置
### 半部分 B — 4D 组件
需要 **4D 20 R8+** (HTTP 请求处理器)。
1. **编译,然后构建。** 在 4D IDE 中:运行 `4d-mcp-server` 的编译,然后构建应用程序。构建设置中 `BuildCompiled=False`,因此在编译之前构建会静默打包过时的代码。(无头替代:使用 tool4d 运行 `MCP_Build` — 请参阅 [半部分 B README](ai-context/README_halfB.md#building-the-component) 获取 tool4d 无法自行执行的打包步骤。)
2. **安装到主机中。** 将构建的组件放入主机应用程序的 `Components/` 文件夹中。
3. **在主机启动时启动它。** 从主机的 `On Startup` / `On Server Startup` 数据库方法中调用 `MCP_Initialize_Host`:
```4d
数组 文本($names; 0)
组件 列表($names)
变量 $mcp : 对象
变量 $f : 4D.函数
如果(在数组中查找($names; "4d-mcp-server")>0)
$f:=字符串公式("MCP_Initialize_Host")
$mcp:=$f.调用()
结束如果
```
`组件列表` 保护加上 `字符串公式` 间接意味着主机编译并运行干净,即使未安装组件(或稍后删除) — 直接调用 `MCP_Initialize_Host` 将无法编译。
> 首次运行时,这会将默认部署配置 `4D-mcp-config.pref` 复制到主机的 `Project/Sources/` 中,然后在配置的 `HTTP_PORT` (默认为 **8044**;将 `0` 设置为从主机主 Web 服务器提供 `/mcp` 服务)上启动组件自己的 Web 服务器。调用是幂等的,可以安全地重新运行。
4. **配置令牌和暴露。** 编辑主机 `Project/Sources/` 中的 `4D-mcp-config.pref`:
- 表暴露和动词门控(`ENABLED`、`ALLOW_READ/WRITE/DELETE`、`ALLOW_CALL_METHOD`)。
- `METHOD_WHITELIST` — 将面向客户端的操作名称映射到主机项目方法的 `4d_call_method`。
令牌将 Bearer 字符串映射到功能对象(可读/可写数据类、可调用操作);v1 在 `MCP_Auth._loadTokens()` 中定义,可替换为基于表的存储。有关确切形状,请参阅 [半部分 B README](ai-context/README_halfB.md)。
### 半部分 A — Node MCP 服务器
需要 **Node 18.17+**。
```bash
cd mcp-server
npm install
npm run build
```
配置通过环境变量进行:
| 环境变量 | 默认值 | 含义 |
|---------|---------|---------|
| `FOURD_MCP_URL` | `http://localhost:8044/mcp` | 半部分 B 端点 |
| `FOURD_MCP_TOKEN` | — (必填) | Bearer 令牌 |
| `FOURD_MCP_TIMEOUT_MS` | `30000` | 每个请求的超时时间 |
在 Claude Code 中注册:
```bash
claude mcp add 4d-data \
--env FOURD_MCP_URL=http://localhost:8044/mcp \
--env FOURD_MCP_TOKEN=您的令牌 \
-- node /path/to/mcp-server/dist/index.js
```
或在 `mcpServers` JSON 块中(Claude Desktop 和类似):
```json
{
"mcpServers": {
"4d-data": {
"command": "node",
"args": ["/path/to/mcp-server/dist/index.js"],
"env": {
"FOURD_MCP_URL": "http://localhost:8044/mcp",
"FOURD_MCP_TOKEN": "您的令牌"
}
}
}
}
```
### 验证设置
在主机 4D 应用程序运行时(半部分 B 在端口 8044 上):
```bash
# 半部分 B 独自,通过真正的 HTTP:
cd 4d-mcp-server && ./test/run_curl_tests.sh
# 半部分 A 对抗实时半部分 B:
cd mcp-server
FOURD_MCP_URL=http://localhost:8044/mcp FOURD_MCP_TOKEN=机密_完整 \
npm run test:integration
```
半部分 A 的单元测试(`npm test`)和半部分 B 的逻辑测试(`MCP_RunHeadlessTests` 在 tool4d 下)根本不需要运行的服务器。
## 文档
- **线路合约(真实来源):** [`ai-context/mcp_data_wire_contract.md`](ai-context/mcp_data_wire_contract.md)
- **半部分 A 详细信息:** [`mcp-server/README.md`](mcp-server/README.md)
- **半部分 B 详细信息:** [`ai-context/README_halfB.md`](ai-context/README_halfB.md)
- **设计笔记:** [`ai-context/design_notes_halfB.md`](ai-context/design_notes_halfB.md)