内容
# Mendix MCP 服务器
MCP(Model Context Protocol)服务器,公开 **Mendix 模型 SDK**、**Mendix 平台 API**、**部署 API** 和运行应用程序的 **运行时 OQL 端点**,作为一套 AI 代理(如 Claude Code)可以调用的工具。
简而言之:它允许 LLM 读取和修改 Mendix 应用程序模型 - 创建模块、实体、属性、关联、页面、微流、REST 服务、安全规则、导航和枚举 - 然后提交、部署或查询结果,所有操作都通过 HTTP 上的普通工具调用。
## 目录
- [工作原理](#工作原理)
- [架构](#架构)
- [它所连接的四个 Mendix 接口](#它所连接的四个Mendix接口)
- [工作副本生命周期(核心模式)](#工作副本生命周期(核心模式))
- [请求生命周期](#请求生命周期)
- [设置](#设置)
- [配置](#配置)
- [运行服务器](#运行服务器)
- [连接 MCP 客户端](#连接MCP客户端)
- [工具目录](#工具目录)
- [项目布局](#项目布局)
- [典型任务流程](#典型任务流程)
- [注意事项、限制和陷阱](#注意事项、限制和陷阱)
## 工作原理
Mendix 应用程序不会作为松散的文件编辑。模型存储在 Mendix 的 **团队服务器** 上,编程方式更改模型的规范方法是使用 **Mendix 模型 SDK**(`mendixmodelsdk`)通过 **平台 SDK**(`mendixplatformsdk`)驱动。模式始终是:
1. 从分支打开应用程序的 **临时在线工作副本**。
2. 打开其 **模型**(整个应用程序的实时、类型化、内存对象图)。
3. 读取或 mutate 模型元素(实体、页面、微流等)。
4. **刷新** 待处理更改并 **提交** 工作副本回分支。
该服务器将该模式封装在约 60 个离散的 MCP 工具中。每个工具都是一个薄的、聚焦的操作(“向实体添加属性”,“向页面添加小部件”,“创建 REST 操作”),它:
- 需要一个 `app_id`(通常还有一个 `branch`,默认为 `main`),
- 打开一个新的工作副本 + 模型,
- 执行一个范围明确的更改,
- 使用生成的消息提交,并
- 返回人类/JSON 结果。
AI 代理将这些小工具编排成更大的更改。服务器本身保持无状态 - 它在调用之间不保留会话。
## 架构
```
┌───────────────────┐ JSON-RPC over HTTP (POST /mcp) ┌────────────────────────┐
│ MCP 客户端 │ ───────────────────────────────────────► │ Mendix MCP 服务器 │
│ (Claude Code 等)│ ◄─────────────────────────────────────── │ (Node.js,端口 3001) │
└───────────────────┘ 工具结果 / 流式事件 └───────────┬────────────┘
│
┌──────────────────────────────────────────────────────┼───────────────────────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌────────────────────┐ ┌──────────────────────────┐ ┌──────────────────────┐ ┌────────────────────┐
│ 平台 SDK │ │ 部署 API(v2) │ │ 运行时 OQL 端点 │ │ 本地 FS / Web │
│ + 模型 SDK │ │ deploy.mendix.com │ │ /rest/oql/v1/query │ │ (glob/读取/写入/ │
│ (团队服务器模型)│ │ │ │ 在运行的应用程序上 │ │ 获取文档搜索) │
└────────────────────┘ └──────────────────────────┘ └──────────────────────┘ └────────────────────┘
▲ ▲ ▲
MENDIX_PAT MENDIX_USERNAME + MENDIX_RUNTIME_TOKEN
MENDIX_API_KEY
```
两个源文件构成了主干:
- [`src/server.ts`](src/server.ts) - HTTP + MCP 传输层。构建一个 `McpServer`,注册每个工具组,并通过 **Streamable HTTP** 传输在 `POST /mcp` 上提供它们。
- [`src/mendix-client.ts`](src/mendix-client.ts) - 共享的 Mendix 帮助层:身份验证、工作副本/模型生命周期、模块/文档查找、多语言文本处理和结果格式化。
其他所有内容都位于 [`src/tools/`](src/tools/) 下,每个功能区域一个文件,每个文件导出一个 `registerXxxTools(server)` 函数,由 `server.ts` 调用。
## 它所连接的四个 Mendix 接口
服务器 **不** 直接调用单一的 Mendix API。不同的工具使用不同的 Mendix 接口,每个接口都有自己的凭证:
| 接口 | 使用工具 | 凭证 | 功能 |
| --- | --- | --- | --- |
| **模型 SDK / 平台 SDK** | 大多数工具 - 领域、页面、流程、安全、导航、枚举、REST 建模、`ped_*`、`project_commit/branch/export/settings` | `MENDIX_PAT` | 在团队服务器上打开工作副本并读取/修改应用程序模型。 |
| **部署 API v2** (`deploy.mendix.com`) | `project_deploy`、`project_get_deploy_status` | `MENDIX_USERNAME` + `MENDIX_API_KEY` | 触发云部署并报告其状态。 |
| **运行时 OQL 端点** (`/rest/oql/v1/query`) | `oql_read` | `MENDIX_RUNTIME_TOKEN` | 对实时运行的应用程序实例运行 OQL 并返回数据。 |
| **本地 FS / 公共 Web** | `glob`、`read_file`、`write_file`、`read_skill`、`web_fetch`、`search_mendix_knowledge_base`、`oql_generate` | 无 | 本地文件操作、文档搜索和纯字符串生成 - 无需 Mendix 身份验证。 |
## 工作副本生命周期(核心模式)
几乎所有修改模型的工具都遵循相同的模式,通过 [`src/mendix-client.ts`](src/mendix-client.ts) 中的帮助程序实现:
```ts
// 1. 为应用程序/分支打开新的工作副本并打开其模型。
const wc = await getWorkingCopy(app_id, branch); // createTemporaryWorkingCopy(branch)
const model = await wc.openModel();
// 2. 定位目标元素。
const mod = findModule(model, moduleName); // 按名称
const doc = findDocument(model, moduleName, docName); // 递归文件夹搜索
// 3. 修改内存模型图(创建/更新/删除 SDK 对象)。
// ...
// 4. 刷新待处理更改并将工作副本提交回分支。
await commitWC(wc, model, "描述性提交消息", branch);
```
只读工具跳过步骤 4,只需调用 `getModel(app_id, branch)` 即可打开一个用于检查的临时工作副本。
`mendix-client.ts` 中的关键帮助程序:
- `mendix` - 单例 `MendixPlatformClient`。其 PAT 通过 `setPlatformConfig(...)` 桥接到 SDK 预期的 `MENDIX_TOKEN` 机制。
- `getWorkingCopy(appId, branch)` / `getModel(appId, branch)` - 打开工作副本/模型。
- `commitWC(wc, model, message, branch)` - `flushChanges()` 然后 `commitToRepository(...)`。
- `findModule` / `findDocument` / `splitQualifiedName` - 解析 `Module.Element` 名称,递归搜索文件夹。
- `setText` / `readText` / `getProjectLanguageCodes` - Mendix 用户可见的文本永远不是一个纯字符串;它是一个 `Text`,为每个配置的语言持有一個 `Translation`。`setText` 为 **所有** 项目语言写入一个翻译(避免一致性错误)并缓存每个模型的语言列表。
- `ok(msg)` / `json(data)` / `errorResult(err)` - 规范化工具返回负载。
- `safe(handler)` - 将每个工具处理程序包装起来,以便抛出的错误变成 MCP 错误结果(`isError: true`)而不是使服务器崩溃。
## 请求生命周期
[`src/server.ts`](src/server.ts) 中的 HTTP 层以 **无状态模式** 运行:
1. 客户端将 JSON-RPC MCP 消息 POST 到 `http://localhost:3001/mcp`。
2. 读取并解析消息体。
3. 为每个请求构建一个新的 `McpServer` + `StreamableHTTPServerTransport` 对(仅限一次 `connect()` - 重用它会在第二次调用时抛出异常 - 因此服务器每次构建一对新的对,而不是保持会话)。
4. 所有工具组都在新服务器上注册,服务器连接到传输层,传输层处理请求/响应。
5. 在连接关闭时,传输层和服务器都已关闭。
任何非 `/mcp` 路径都返回 `404`。错误作为 JSON-RPC 错误对象返回(`code: -32603`)。
## 设置
### 先决条件
- **Node.js**(支持 ES 模块 / `NodeNext`;推荐 Node 18 及以上以支持全局 `fetch`)。
- 具有以下内容的 **Mendix 帐户**:
- **个人访问令牌(PAT)**,具有 `mx:modelrepository` 作用域(用于模型编辑),
- 可选的 **API 密钥 + 用户名**(用于部署),
- 可选的 **运行时令牌**(用于实时 OQL 查询)。
- 应用程序的 **应用程序 ID**(在 Mendix 门户 / 开发者门户中找到)。
### 安装
```bash
npm install
```
## 配置
复制 [.env.example](.env.example) 到 `.env` 并填写您的凭证:
```dotenv
MENDIX_PAT=your_personal_access_token # 模型/平台 SDK - 模型编辑
MENDIX_USERNAME=your@email.com # 部署 API - 部署
MENDIX_API_KEY=your_deploy_api_key # 部署 API - 部署
MENDIX_RUNTIME_TOKEN=your_runtime_token # 运行时 OQL - 实时数据查询
PORT=3001 # HTTP 端口(默认为 3001)
```
`.env` 在启动时通过 `dotenv/config` 自动加载。每个凭证仅适用于使用它的工具 - 您可以使用 `MENDIX_PAT` 运行模型编辑工具。
## 运行服务器
```bash
# 类型检查 + 编译 TypeScript → dist/
npm run build
# 运行编译后的服务器
npm start
# → Mendix MCP -> http://localhost:3001/mcp
# 或直接从源代码在开发期间运行(ts-node 加载器):
npm run dev
# 文件更改时自动重启:
npm run watch
```
## 连接 MCP 客户端
将任何 MCP 客户端指向 HTTP 端点。对于 **Claude Code**,添加一个 HTTP MCP 服务器:
```bash
claude mcp add --transport http mendix http://localhost:3001/mcp
```
或使用支持 Streamable HTTP 传输的客户端配置文件,使用 URL `http://localhost:3001/mcp`。连接后,客户端会发现以下所有工具,代理可以按名称调用它们。
## 工具目录
所有涉及模型的工具都接受 `app_id` 和(通常)可选的 `branch`(默认为 `main`)。按源文件分组:
### 文件系统和知识 - [`filesystem.ts`](src/tools/filesystem.ts),[`knowledge.ts`](src/tools/knowledge.ts)
| 工具 | 描述 |
| --- | --- |
| `glob` | 查找匹配 glob 模式的文件。 |
| `read_file` | 读取文件的内容。 |
| `write_file` | 写入或覆盖文件。 |
| `read_skill` | 从技能库读取技能/片段。 |
| `web_fetch` | 从 URL 获取内容。 |
| `search_mendix_knowledge_base` | 搜索 Mendix 文档/知识库(docs.mendix.com)。 |
### 平台/元素文档操作 (`ped_*`) - [`ped.ts`](src/tools/ped.ts)
通用、低级别的构建块,用于构建更高级的工具。
| 工具 | 描述 |
| --- | --- |
| `ped_read_document` | 读取文档的完整 JSON 表示。 |
| `ped_get_schema` | 总结文档类型的 SDK 类 + 公共属性。 |
| `ped_create_document` | 创建页面、微流、纳米流、枚举或片段。 |
| `ped_create_module` | 创建新模块。 |
| `ped_update_document` | 将键值属性更新应用于文档。 |
| `ped_check_errors` | 对模型运行一致性检查。 |
| `ped_find_document` | 按名称子字符串/模块/类型搜索文档。 |
| `ped_list_folder` | 列出直接位于模块(或子文件夹)下的文档。 |
### 领域模型 - [`domain.ts`](src/tools/domain.ts)
| 工具 | 描述 |
| --- | --- |
| `entity_create` | 创建实体(通过泛化持久化;请参见下面的注释)。 |
| `entity_add_attribute` | 添加属性(可选默认值 + 必要规则)。 |
| `entity_update_attribute` | 将属性更新应用于属性。 |
| `entity_delete_attribute` | 删除属性。 |
| `entity_list_attributes` | 列出实体的属性及其名称 + 类型。 |
| `entity_set_access_rules` | 设置实体访问规则。 |
| `entity_copy` | 复制实体(包括属性)。 |
| `entity_delete` | 删除实体。 |
| `association_create` | 在两个实体之间创建关联(跨模块 OK)。 |
| `association_set_properties` | 将属性更新应用于关联。 |
| `domain_model_export` | 导出模块的精选摘要。 |
支持的属性类型:`String, Integer, Long, Decimal, Boolean, DateTime, Enum, AutoNumber, Binary, HashString`.
### 枚举、常量和片段 - [`enums.ts`](src/tools/enums.ts)
| 工具 | 描述 |
| --- | --- |
| `enum_add_value` / `enum_update_value` / `enum_list_values` | 管理枚举值。 |
| `constant_create` / `constant_set_value` | 创建/设置常量文档。 |
| `snippet_create` / `snippet_add_to_page` | 创建可重用片段并将其放在页面上。 |
### 页面和小部件 - [`pages.ts`](src/tools/pages.ts)
| 工具 | 描述 |
| --- | --- |
| `page_add_widget` / `page_remove_widget` / `page_move_widget` | 添加/删除/重新定位小部件。 |
| `page_set_widget_property` | 设置单个小部件属性(动态键值)。 |
| `page_set_data_source` | 连接小部件的数据源。 |
| `page_set_conditional_visibility` | 在小部件上设置可见性表达式。 |
| `page_set_layout` | 更改页面的布局。 |
| `page_add_listview` | 添加连接到实体的 ListView。 |
| `page_add_datagrid` | 添加连接到实体的 DataGrid,每个属性一列。 |
| `page_set_class` | 设置小部件的 CSS 类。 |
| `page_duplicate` | 复制页面。 |
| `page_set_navigation_target` | 使 ActionButton 导航到另一个页面。 |
| `page_set_button_caption` | 设置按钮的标题。 |
### 微流/纳米流 - [`flows.ts`](src/tools/flows.ts)
| 工具 | 描述 |
| --- | --- |
| `flow_add_activity` | 添加活动节点。 |
| `flow_add_decision` | 添加具有表达式条件的独家分支。 |
| `flow_connect_activities` | 用流连接节点。 |
| `flow_configure_activity` | 配置活动的属性。 |
| `flow_add_variable` | 添加创建变量的活动。 |
| `flow_add_retrieve` | 添加数据库检索(按实体列表)。 |
| `flow_add_commit` | 添加提交对象活动。 |
| `flow_add_loop` | 添加循环遍历列表变量(空正文)。 |
| `flow_add_error_handler` | 添加错误处理程序。 |
| `flow_call_microflow` | 调用另一个微流与参数映射。 |
| `flow_call_rest_service` | 添加调用 REST 服务的活动。 |
| `flow_get_activities` | 列出所有节点(id, type, position)。 |
| `flow_run_microflow` | 运行微流。 |
### REST 服务 - [`rest.ts`](src/tools/rest.ts)
| 工具 | 描述 |
| --- | --- |
| `rest_create_consumed_service` / `rest_add_operation` | 建模消耗的 REST 服务 + 操作。 |
| `rest_create_published_service` / `rest_add_published_resource` | 在基路径上建模发布的 REST 服务。 |
| `rest_import_openapi` | 从 OpenAPI/Swagger 规范(实用、非 `$ref` 解析器)导入到消耗的服务。 |
| `rest_list_services` | 列出所有消耗的 + 已发布的服务。 |
| `rest_set_mapping` | 配置映射。 |
| `rest_test_operation` | 调用操作进行测试。 |
### 安全 - [`security.ts`](src/tools/security.ts)
| 工具 | 描述 |
| --- | --- |
| `security_create_userrole` / `security_list_roles` | 管理项目用户角色。 |
| `security_set_page_access` | 设置模块角色允许在页面上访问。 |
| `security_set_microflow_access` | 设置模块角色允许访问微流。 |
| `security_set_entity_access` | 设置实体访问规则。 |
| `security_get_access_summary` | 汇总访问配置。 |
### 导航 - [`navigation.ts`](src/tools/navigation.ts)
| 工具 | 描述 |
| --- | --- |
| `navigation_get_menu` | 读取导航配置文件的菜单。 |
| `navigation_add_menu_item` / `navigation_remove_menu_item` | 添加/删除菜单项。 |
| `navigation_reorder_items` | 重新排序菜单项。 |
| `navigation_set_home_page` | 设置配置文件的首页。 |
### OQL - [`oql.ts`](src/tools/oql.ts)
| 工具 | 描述 | 认证 |
| --- | --- | --- |
| `oql_generate` | 从参数生成 OQL 字符串(本地模板)。 | 无 |
| `oql_read` | 对实时运行的应用程序运行 OQL(`POST /rest/oql/v1/query`)。 | `MENDIX_RUNTIME_TOKEN` |
### 部署和项目 - [`deployment.ts`](src/tools/deployment.ts)
| 工具 | 描述 | 认证 |
| --- | --- | --- |
| `project_commit` | 打开工作副本并提交(检查点历史)。 | `MENDIX_PAT` |
| `project_create_branch` | 创建分支。 | `MENDIX_PAT` |
| `project_get_revisions` | 获取分支的提交历史(团队服务器 API)。 | `MENDIX_PAT` |
| `project_deploy` | 部署到云环境(Sandbox/Test/Acceptance/Production)。 | `MENDIX_USERNAME` + `MENDIX_API_KEY` |
| `project_get_deploy_status` | 获取部署的状态。 | `MENDIX_USERNAME` + `MENDIX_API_KEY` |
| `project_export_mpk` | 导出模型为本地 `.mpk`。 | `MENDIX_PAT` |
| `project_get_settings` | 获取应用程序的项目设置文档。 | `MENDIX_PAT` |
## 工具目录
所有涉及模型的工具都接受 `app_id` 和(通常)可选的 `branch`(默认为 `main`)。按源文件分组:
### 文件系统和知识 — [`filesystem.ts`](src/tools/filesystem.ts),[`knowledge.ts`](src/tools/knowledge.ts)
| 工具 | 描述 |
|---|---|
| `glob` | 查找匹配 glob 模式的文件。 |
| `read_file` | 读取文件的内容。 |
| `write_file` | 写入或覆盖文件。 |
| `read_skill` | 从技能库读取技能/片段。 |
| `web_fetch` | 从 URL 获取内容。 |
| `search_mendix_knowledge_base` | 搜索 Mendix 文档/知识库(docs.mendix.com)。 |
### 平台/元素文档操作 (`ped_*`) - [`ped.ts`](src/tools/ped.ts)
通用、低级别的构建块,用于构建更高级的工具。
| 工具 | 描述 |
|---|---|
| `ped_read_document` | 读取文档的完整 JSON 表示。 |
| `ped_get_schema` | 总结文档类型的 SDK 类 + 公共属性。 |
| `ped_create_document` | 创建页面、微流、纳米流、枚举或片段。 |
| `ped_create_module` | 创建新模块。 |
| `ped_update_document` | 将键值属性更新应用于文档。 |
| `ped_check_errors` | 对模型运行一致性检查。 |
| `ped_find_document` | 按名称子字符串/模块/类型搜索文档。 |
| `ped_list_folder` | 列出直接位于模块(或子文件夹)下的文档。 |
### 领域模型 - [`domain.ts`](src/tools/domain.ts)
| 工具 | 描述 |
|---|---|
| `entity_create` | 创建实体(通过泛化持久化;参见下面的注释)。 |
| `entity_add_attribute` | 添加属性(可选默认值 + 必要规则)。 |
| `entity_update_attribute` | 将属性更新应用于属性。 |
| `entity_delete_attribute` | 删除属性。 |
| `entity_list_attributes` | 列出实体的属性及其名称 + 类型。 |
| `entity_set_access_rules` | 设置实体访问规则。 |
| `entity_copy` | 复制实体(包括属性)。 |
| `entity_delete` | 删除实体。 |
| `association_create` | 在两个实体之间创建关联(跨模块 OK)。 |
| `association_set_properties` | 将属性更新应用于关联。 |
| `domain_model_export` | 导出模块的精选摘要。 |
支持的属性类型:`String, Integer, Long, Decimal, Boolean, DateTime, Enum, AutoNumber, Binary, HashString`.
### 枚举、常量和片段 - [`enums.ts`](src/tools/enums.ts)
| 工具 | 描述 |
|---|---|
| `enum_add_value` / `enum_update_value` / `enum_list_values` | 管理枚举值。 |
| `constant_create` / `constant_set_value` | 创建/设置常量文档。 |
| `snippet_create` / `snippet_add_to_page` | 创建可重用片段并将其放在页面上。 |
### 页面和小部件 - [`pages.ts`](src/tools/pages.ts)
| 工具 | 描述 |
|---|---|
| `page_add_widget` / `page_remove_widget` / `page_move_widget` | 添加/删除/重新定位小部件。 |
| `page_set_widget_property` | 设置单个小部件属性(动态键值)。 |
| `page_set_data_source` | 连接小部件的数据源。 |
| `page_set_conditional_visibility` | 在小部件上设置可见性表达式。 |
| `page_set_layout` | 更改页面的布局。 |
| `page_add_listview` | 添加连接到实体的 ListView。 |
| `page_add_datagrid` | 添加连接到实体的 DataGrid,每个属性一列。 |
| `page_set_class` | 设置小部件的 CSS 类。 |
| `page_duplicate` | 复制页面。 |
| `page_set_navigation_target` | 使 ActionButton 导航到另一个页面。 |
| `page_set_button_caption` | 设置按钮的标题。 |
### 微流/纳米流 - [`flows.ts`](src/tools/flows.ts)
| 工具 | 描述 |
|---|---|
| `flow_add_activity` | 添加活动节点。 |
| `flow_add_decision` | 添加具有表达式条件的独家分支。 |
| `flow_connect_activities` | 用流连接活动。 |
| `flow_configure_activity` | 配置活动的属性。 |
| `flow_add_variable` | 添加创建变量的活动。 |
| `flow_add_retrieve` | 添加数据库检索(按实体列表)。 |
| `flow_add_commit` | 添加提交对象活动。 |
| `flow_add_loop` | 添加循环遍历列表变量(空正文)。 |
| `flow_add_error_handler` | 添加错误处理程序。 |
| `flow_call_microflow` | 调用另一个微流与参数映射。 |
| `flow_call_rest_service` | 添加调用 REST 服务的活动。 |
| `flow_get_activities` | 列出所有节点(id, type, position)。 |
| `flow_run_microflow` | 运行微流。 |
### REST 服务 - [`rest.ts`](src/tools/rest.ts)
| 工具 | 描述 |
|---|---|
| `rest_create_consumed_service` / `rest_add_operation` | 建模消耗的 REST 服务 + 操作。 |
| `rest_create_published_service` / `rest_add_published_resource` | 在基路径上建模发布的 REST 服务。 |
| `rest_import_openapi` | 从 OpenAPI/Swagger 规范(实用、非 `$ref` 解析器)导入到消耗的服务中。 |
| `rest_list_services` | 列出所有消耗的 + 已发布的服务。 |
| `rest_set_mapping` | 配置映射。 |
| `rest_test_operation` | 调用操作进行测试。 |
### 安全 - [`security.ts`](src/tools/security.ts)
| 工具 | 描述 |
|---|---|
| `security_create_userrole` / `security_list_roles` | 管理项目用户角色。 |
| `security_set_page_access` | 设置模块角色允许访问页面。 |
| `security_set_microflow_access` | 设置模块角色允许访问微流。 |
| `security_set_entity_access` | 设置实体访问规则。 |
| `security_get_access_summary` | 汇总访问配置。 |
### 导航 - [`navigation.ts`](src/tools/navigation.ts)
| 工具 | 描述 |
|---|---|
| `navigation_get_menu` | 读取导航配置文件的菜单。 |
| `navigation_add_menu_item` / ` ニュースカテゴリーassistant
# Mendix MCP 服务器
MCP(Model Context Protocol)服务器,公开 **Mendix 模型 SDK**、**Mendix 平台 API**、**部署 API** 和运行应用程序的 **运行时 OQL 端点**,作为一套 AI 代理(如 Claude Code)可以调用的工具。
简而言之:它允许 LLM 读取和修改 Mendix 应用程序模型 - 创建模块、实体、属性、关联、页面、微流、REST 服务、安全规则、导航和枚举 - 然后提交、部署或查询结果,所有操作都通过 HTTP 上的普通工具调用。
## 目录
- [工作原理](#工作原理)
- [架构](#架构)
- [它所连接的四个 Mendix 接口](#它所连接的四个Mendix接口)
- [工作副本生命周期(核心模式)](#工作副本生命周期(核心模式))
- [请求生命周期](#请求生命周期)
- [设置](#设置)
- [配置](#配置)
- [运行服务器](#运行服务器)
- [连接 MCP 客户端](#连接MCP客户端)
- [工具目录](#工具目录)
- [项目布局](#项目布局)
- [典型任务流程](#典型任务流程)
- [注意事项、限制和陷阱](#注意事项、限制和陷阱)
## 工作原理
Mendix 应用程序不会作为松散的文件编辑。模型存储在 Mendix 的 **团队服务器** 上,编程方式更改模型的规范方法是使用 **Mendix 模型 SDK**(`mendixmodelsdk`)通过 **平台 SDK**(`mendixplatformsdk`)驱动。模式始终是:
1. 从分支打开应用程序的 **临时在线工作副本**。
2. 打开其 **模型**(整个应用程序的实时、类型化、内存对象图)。
3. 读取或 mutate 模型元素(实体、页面、微流等)。
4. **刷新** 待处理更改并 **提交** 工作副本回分支。
该服务器将该模式封装在约 60 个离散的 MCP 工具中。每个工具都是一个薄的、聚焦的操作(“向实体添加属性”,“向页面添加小部件”,“创建 REST 操作”),它:
- 需要一个 `app_id`(通常还有一个 `branch`,默认为 `main`),
- 打开一个新的工作副本 + 模型,
- 执行一个范围明确的更改,
- 使用生成的消息提交,并
- 返回人类/JSON 结果。
AI 代理将这些小工具编排成更大的更改。服务器本身保持无状态 - 它在调用之间不保留会话。
## 架构
```
┌───────────────────┐ JSON-RPC over HTTP (POST /mcp) ┌────────────────────────┐
│ MCP 客户端 │ ───────────────────────────────────────► │ Mendix MCP 服务器 │
│ (Claude Code 等)│ ◄─────────────────────────────────────── │ (Node.js,端口 3001) │
└───────────────────┘ 工具结果 / 流式事件 └───────────┬────────────┘
│
┌──────────────────────────────────────────────────────┼───────────────────────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌────────────────────┐ ┌──────────────────────────┐ ┌──────────────────────┐ ┌────────────────────┐
│ 平台 SDK │ │ 部署 API(v2) │ │ 运行时 OQL 端点 │ │ 本地 FS / Web │
│ + 模型 SDK │ │ deploy.mendix.com │ │ /rest/oql/v1/query │ │ (glob/读取/写入/ │
│ (团队服务器模型)│ │ │ │ 在运行的应用程序上 │ │ 获取文档搜索) │
└────────────────────┘ └──────────────────────────┘ └──────────────────────┘ └────────────────────┘
▲ ▲ ▲
MENDIX_PAT MENDIX_USERNAME + MENDIX_RUNTIME_TOKEN
MENDIX_API_KEY
```
## 它所连接的四个 Mendix 接口
服务器 **不** 直接调用单一的 Mendix API。不同的工具使用不同的 Mendix 接口,每个接口都有自己的凭证:
| 接口 | 使用工具 | 凭证 | 功能 |
| --- | --- | --- | --- |
| **模型 SDK / 平台 SDK** | 大多数工具 - 领域、页面、流程、安全、导航、枚举、REST 建模、`ped_*`、`project_commit/branch/export/settings` | `MENDIX_PAT` | 在团队服务器上打开工作副本并读取/修改应用程序模型。 |
| **部署 API v2** (`deploy.mendix.com`) | `project_deploy`、`project_get_deploy_status` | `MENDIX_USERNAME` + `MENDIX_API_KEY` | 触发云部署并报告其状态。 |
| **运行时 OQL 端点** (`/rest/oql/v1/query`) | `oql_read` | `MENDIX_RUNTIME_TOKEN` | 对实时运行的应用程序实例运行 OQL 并返回数据。 |
| **本地 FS / 公共 Web** | `glob`、`read_file`、`write_file`、`read_skill`、`web_fetch`、`search_mendix_knowledge_base`、`oql_generate` | 无 | 本地文件操作、文档搜索和纯字符串生成 - 无需 Mendix 身份验证。 |
## 工作副本生命周期(核心模式)
几乎所有修改模型的工具都遵循相同的模式,通过 [`src/mendix-client.ts`](src/mendix-client.ts) 中的帮助程序实现:
```ts
// 1. 为应用程序/分支打开新的工作副本并打开其模型。
const wc = await getWorkingCopy(app_id, branch); // createTemporaryWorkingCopy(branch)
const model = await wc.openModel();
// 2. 定位目标元素。
const mod = findModule(model, moduleName); // 按名称
const doc = findDocument(model, moduleName, docName); // 递归文件夹搜索
// 3. 修改内存模型图(创建/更新/删除 SDK 对象)。
// 4. 刷新待处理更改并将工作副本提交回分支。
await commitWC(wc, model, "描述性提交消息", branch);
```
只读工具跳过步骤 4,只需调用 `getModel(app_id, branch)` 即可打开一个用于检查的临时工作副本。
## 请求生命周期
[`src/server.ts`](src/server.ts) 中的 HTTP 层以 **无状态模式** 运行:
1. 客户端将 JSON-RPC MCP 消息 POST 到 `http://localhost:3001/mcp`。
2. 读取并解析消息体。
3. 为每个请求构建一个新的 `McpServer` + `StreamableHTTPServerTransport` 对(仅限一次 `connect()` - 重用它会在第二次调用时抛出异常 - 因此服务器每次构建一对新的对,而不是保持会话)。
4. 所有工具组都在新服务器上注册,服务器连接到传输层,传输层处理请求/响应。
5. 在连接关闭时,传输层和服务器都已关闭。
任何非 `/mcp` 路径都返回 `404`。错误作为 JSON-RPC 错误对象返回(`code: -32603`)。
## 设置
### 先决条件
- **Node.js**(支持 ES 模块 / `NodeNext`;推荐 Node 18 及以上以支持全局 `fetch`)。
- 具有以下内容的 **Mendix 帐户**:
- **个人访问令牌(PAT)**,具有 `mx:modelrepository` 作用域(用于模型编辑),
- 可选的 **API 密钥 + 用户名**(用于部署),
- 可选的 **运行时令牌**(用于实时 OQL 查询)。
- 应用程序的 **应用程序 ID**(在 Mendix 门户 / 开发者门户中找到)。
### 安装
```bash
npm install
```
## 配置
复制 [.env.example](.env.example) 到 `.env` 并填写您的凭证:
```dotenv
MENDIX_PAT=your_personal_access_token # 模型/平台 SDK - 模型编辑
MENDIX_USERNAME=your@email.com # 部署 API - 部署
MENDIX_API_KEY=your_deploy_api_key # 部署 API - 部署
MENDIX_RUNTIME_TOKEN=your_runtime_token # 运行时 OQL - 实时数据查询
PORT=3001 # HTTP 端口(默认为 3001)
```
`.env` 在启动时通过 `dotenv/config` 自动加载。每个凭证仅适用于使用它的工具 - 您可以使用 `MENDIX_PAT` 运行模型编辑工具。
## 运行服务器
```bash
# 类型检查 + 编译 TypeScript → dist/
npm run build
# 运行编译后的服务器
npm start
# → Mendix MCP -> http://localhost:3001/mcp
# 或直接从源代码在开发期间运行(ts-node 加载器):
npm run dev
# 文件更改时自动重启:
npm run watch
```
## 连接 MCP 客户端
将任何 MCP 客户端指向 HTTP 端点。对于 **Claude Code**,添加一个 HTTP MCP 服务器:
```bash
claude mcp add --transport http mendix http://localhost:3001/mcp
```
或使用支持 Streamable HTTP 传输的客户端配置文件,使用 URL `http://localhost:3001/mcp`。连接后,客户端会发现以下所有工具,代理可以按名称调用它们。
## 工具目录
所有涉及模型的工具都接受 `app_id` 和(通常)可选的 `branch`(默认为 `main`)。按源文件分组:
### 文件系统和知识 - [`filesystem.ts`](src/tools/filesystem.ts),[`knowledge.ts`](src/tools/knowledge.ts)
| 工具 | 描述 |
|---|---|
| `glob` | 查找匹配 glob 模式的文件。 |
| `read_file` | 读取文件的内容。 |
| `write_file` | 写入或覆盖文件。 |
| `read_skill` | 从技能库读取技能/片段。 |
| `web_fetch` | 从 URL 获取内容。 |
| `search_mendix_knowledge_base` | 搜索 Mendix 文档/知识库(docs.mendix.com)。 |
### 平台/元素文档操作 (`ped_*`) - [`ped.ts`](src/tools/ped.ts)
通用、低级别的构建块,用于构建更高级的工具。
| 工具 | 描述 |
|---|---|
| `ped_read_document` | 读取文档的完整 JSON 表示。 |
| `ped_get_schema` | 总结文档类型的 SDK 类 + 公共属性。 |
| `ped_create_document` | 创建页面、微流、纳米流、枚举或片段。 |
| `ped_create_module` | 创建新模块。 |
| `ped_update_document` | 将键值属性更新应用于文档。 |
| `ped_check_errors` | 对模型运行一致性检查。 |
| `ped_find_document` | 按名称子字符串/模块/类型搜索文档。 |
| `ped_list_folder` | 列出直接位于模块(或子文件夹)下的文档。 |
### 领域模型 - [`domain.ts`](src/tools/domain.ts)
| 工具 | 描述 |
|---|---|
| `entity_create` | 创建实体(通过泛化持久化;请参见下面的注释)。 |
| `entity_add_attribute` | 添加属性(可选默认值 + 必要规则)。 |
## 项目布局
```
mendix-mcp-server/
├── src/
│ ├── server.ts # HTTP + MCP 传输;注册所有工具组
│ ├── mendix-client.ts # 认证,工作副本/模型生命周期,帮助函数
│ └── tools/
│ ├── filesystem.ts # glob / 读取 / 写入 / 获取 / 读取技能
│ ├── knowledge.ts # Mendix 文档搜索
│ ├── ped.ts # 通用文档/模块操作(创建/读取/更新/错误)
│ ├── domain.ts # 实体,属性,关联
│ ├── enums.ts # 枚举,常量,代码片段
│ ├── pages.ts # 页面和部件
│ ├── flows.ts # 微流 / 纳米流
│ ├── rest.ts # 已消费和已发布的 REST 服务,OpenAPI 导入
│ ├── security.ts # 用户角色,页面/微流/实体访问
│ ├── navigation.ts # 导航菜单
│ ├── oql.ts # OQL 生成 + 实时读取
│ └── deployment.ts # 提交,分支,部署,导出,设置
├── dist/ # 编译输出(npm run build)
├── package.json
├── tsconfig.json
├── .env / .env.example # 凭证和端口
└── README.md
```
---
## 典型任务的端到端流程
假设代理被要求: *"在 `Sales` 模块中添加一个 `Customer` 实体,并带有一个 `Name` 字段,将其放在数据网格上,并部署到 Sandbox 环境中。"*
1. **`entity_create`** → 打开应用程序的工作副本,在 `Sales` 中创建 `Customer` 实体,并提交。
2. **`entity_add_attribute`** → 打开一个新的工作副本,添加 `Name`(字符串),并提交。
3. **`ped_create_document`** → 创建一个 `CustomerOverview` 页面。
4. **`page_add_datagrid`** → 将数据网格连接到 `Sales.Customer`,每个属性一个列,并提交。
5. **`navigation_add_menu_item`** → 将页面链接到导航菜单中。
6. **`ped_check_errors`** → 运行一致性检查以确认模型有效。
7. **`project_deploy`** → 调用部署 API 以推送到 Sandbox 环境中。
8. **`project_get_deploy_status`** → 轮询直到部署报告成功。
每个步骤都是一个单独的无状态 HTTP 调用;代理决定顺序并对每个工具的结果做出反应。
---
## 注意事项,限制和陷阱
- **设计上无状态。** 不保持会话;每个请求都建立和拆除自己的 MCP 服务器/传输对。这是故意的 — MCP SDK 禁止重用连接的对。
- **每次变更调用都会重新打开工作副本。** 由于工具是独立的,多步骤更改是一系列提交,而不是一个原子事务。使用 `project_commit` 来检查点并使用 `ped_check_errors` 来验证。
- **文本是多语言的。** 任何标题/标签/标题都是 `Text`,每个项目语言都有一个 `Translation`。始终使用 `setText`/`readText` 帮助函数(高级别工具为您执行此操作)— 不要假设一个普通的字符串。
- **实体持久性** 通过实体的 *generalization* 来表示,而不是一个独立的标志:一个带有 `persistable=true/false` 的 `NoGeneralization`,或者一个指向父实体的 `Generalization`(然后确定持久性)。
- **`rest_import_openapi` 很务实,但不完整。** 它读取 `info.title`,服务器 URL 和 `paths.*.<method>.operationId`,但 **不** 解析 `$ref`s 或导入参数/响应模式。
- **凭证范围。** 模型工具只需要 `MENDIX_PAT`;部署工具还需要 `MENDIX_USERNAME` + `MENDIX_API_KEY`;`oql_read` 需要 `MENDIX_RUNTIME_TOKEN`。缺少凭证时,只有在调用相关工具时才会产生明确的错误。
- **错误是非致命的。** `safe()` 包装器将抛出的错误转换为 MCP 错误结果,因此失败的工具调用返回错误有效载荷而不是使服务器宕机。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器