内容
# Tekla MCP 服务器
[](LICENSE)
[](https://github.com/tempalg1n/tekla-mcp-server/actions/workflows/ci.yml)
一个 [MCP](https://modelcontextprotocol.io/) 服务器,通过 [Tekla Open API](https://developer.tekla.com/doc/tekla-structures/2026/tekla-structures-64304) 将 AI 助手连接到 **Tekla Structures** 模型。
询问有关钢结构的自然语言问题 — 重量、数量、材料、剖面、选择 — 并让助手为您查询开放模型。
> **状态:早期开发中。** 服务器在 Windows 上构建和运行,并已在实时 Tekla 2023 模型上进行测试。工具集正在增长;API 和行为可能会在版本之间发生变化。请参见 [路线图](#路线图)。
**语言:** 简体中文(此文件)
---
## 为什么有这个项目
Tekla Structures 拥有丰富的 BIM 数据 — 零件、组件、重量、类别、用户定义属性 — 但这些数据被锁定在仅限 Windows 的 .NET API 后。AI 助手需要一个结构化、安全桥梁来读取(和选择性更新)模型数据,而无需手动导出或自定义宏。
该服务器通过 **模型上下文协议** 提供此桥梁:一种标准方法,用于 Claude、Cursor 等 MCP 客户端调用开放 Tekla 模型上的类型化工具。
**您今天可以做到:**
- 检查连接状态、模型名称和对象数量
- 按类型、类别、剖面、材料和名称筛选和搜索零件
- 按 UDA 或任意属性值筛选对象(包括按值发现属性)
- 使用工具跨工具筛选计算重量和数量
- 按字段(类型、类别、剖面、材料、名称)分组指标
- 分析材料分解(物料清单样式)
- 分析给定剖面的唯一连接类型(梁端邻近启发式)
- 读取 Tekla 中的当前 UI 选择
- 按筛选器在 Tekla UI 中选择对象
- 读取和写入用户定义属性(UDA),默认为安全预览写入
---
## 架构
服务器使用 **C#** 编写,因为 Tekla Open API 作为 .NET 程序集(`.NET Framework 4.8`,x64)提供。所有 MCP 工具都依赖于单个抽象 — `ITeklaModelService` — 它有两个后端:
| 后端 | 构建 | 目的 |
|---|---|---|
| `MockTeklaModelService` | `net8.0` | 用于开发和测试的综合钢框架(约 42 个对象),无需 Tekla |
| `TeklaModelService` | `net48`(Windows) | 来自开放 Tekla 模型的实时数据(在 Tekla 2023 上验证) |
详情:[docs/architecture.md](docs/architecture.md)。
---
## 仓库布局
```
tekla-mcp-server/
├── README.md ← 你在这里
├── LICENSE
├── CONTRIBUTING.md
├── AGENTS.md ← AI 辅助开发的约定
├── docs/
│ ├── architecture.md
│ └── tekla-api-notes.md
├── TeklaMcp.sln
├── src/
│ ├── TeklaMcp.Core/ ← 接口 + DTO(netstandard2.0)
│ ├── TeklaMcp.Mock/ ← 模拟后端(netstandard2.0)
│ ├── TeklaMcp.Scripting/ ← C# 脚本逃生口 + API 参考搜索(netstandard2.0)
│ ├── TeklaMcp.Tekla/ ← Tekla Open API 后端(net48,Windows)
│ └── TeklaMcp.Server/ ← MCP 主机 + 工具(net8.0;+net48 在 Windows 上)
└── tests/
└── TeklaMcp.Tests/ ← 单元测试(net8.0,仅模拟)
```
---
## 工具
所有工具都使用 `tekla_` 前缀。
| 工具 | 描述 |
|---|---|
| `tekla_get_connection_info` | 检查是否打开模型;返回名称、路径和活动后端。 |
| `tekla_report_gap` | 报告缺少的功能 / 数据不足;返回一个可以直接提交的 issue 草稿。 |
| `tekla_get_model_summary` | 模型范围的摘要:对象数量、总重量、按类型/类别/剖面/材料分类。 |
| `tekla_list_objects` | 列出具有核心属性的对象(有限)。 |
| `tekla_find_objects` | 按筛选器搜索:类型、类别、剖面、材料、名称。 |
| `tekla_get_object_by_guid` | 按 GUID 获取单个对象。 |
| `tekla_get_properties` | 读取任意命名属性(报告属性、UDA、内置属性)用于按 GUID 对象。 |
| `tekla_get_selected_objects` | 返回当前在 Tekla UI 中选择的对象。 |
| `tekla_find_attributes_by_value` | 按已知值查找可能的属性名称(`BK1` → 匹配字段)。 |
| `tekla_analyze_by_material` | 材料分解(按钢等级计算数量 + 重量)。 |
| `tekla_count_objects` | 计算匹配筛选器的对象(快速:不物化每个对象的数据;无限计数)。 |
| `tekla_sum_weight` | 计算匹配筛选器的对象的总重量。 |
| `tekla_group_weight_by` | 按字段(`type`、`class`、`profile`、`material`、`name`、`assembly`)分组计算 + 重量。 |
| `tekla_list_distinct_values` | 具有数量 + 重量的字段的独特值。 |
| `tekla_list_assemblies` | 列出组件标记(ASSEMBLY_POS)以及零件数量 + 总重量。 |
| `tekla_count_assemblies` | 计算不同的组件标记(独特的组件类型)。 |
| `tekla_get_assembly_parts` | 列出共享给定组件标记的所有零件。 |
| `tekla_find_modeling_issues` | 质量检查电池:缺少材料/剖面/类别、零重量、无编号;按 GUID 分组。 |
| `tekla_export_objects` | 将筛选的对象导出为 CSV/Markdown 表(物料清单)。 |
| `tekla_analyze_profile_connections` | 估计给定剖面的独特连接/节点类型。 |
| `tekla_select_objects` | 在 Tekla UI 中选择匹配的对象;支持 UDA/属性筛选器和 `guidIn`;返回 `selectedCount` + 预览。 |
| `tekla_get_object_udas` | 读取按 GUID 对象的 UDA 字段。 |
| `tekla_set_object_udas` | 设置对象的 UDA(默认为 `apply=false`)。 |
| `tekla_set_udas_by_filter` | 按筛选器批量更新 UDA(默认为 `apply=false`)。 |
### 编写工具 — 创建 / 编辑 / 删除
> ⚠️ **变异工具。** 每个写入工具默认运行在 **预览模式**(`apply=false`):它返回计划(数量 + 预览)并且不更改任何内容。传递 `apply=true` 以提交。创建/修改的对象使用 `MCP_ORIGIN` UDA 进行标记,以便可以找到并恢复它们;Tekla 的原生 **Ctrl+Z** 也会撤销已提交的更改。坐标是 **全局** 模型坐标(毫米)。
| 工具 | 描述 |
|---|---|
| `tekla_list_grids` | 列出网格线(轴、标签、坐标)。 |
| `tekla_resolve_point` | 从轴标签 + 高程解析点(例如 `1` × `Д` × `6000`)。 |
| `tekla_create_beam` | 在两点之间创建梁。 |
| `tekla_create_column` | 在(x,y)处创建垂直柱,从 bottomZ 到 topZ。 |
| `tekla_create_plate` | 从 3+ 点创建轮廓板。 |
| `tekla_modify_part` | 编辑一个零件:剖面/材料/类别/名称和/或端点。 |
| `tekla_swap_handles` | 交换匹配零件的开始/结束句柄。 |
| `tekla_delete_objects` | 按筛选器或 GUID 列表删除对象。 |
| `tekla_create_beam_between_grids` | 在两个网格交叉点之间创建一个梁,在某个高程处。 |
| `tekla_create_column_grid` | 在每个 X×Y 坐标交叉点创建列。 |
| `tekla_generate_frame` | 生成一个完整的有框框架(柱 + 每层梁)。 |
| `tekla_straighten_columns` | 使倾斜的柱子直立(顶部对齐底部)。 |
| `tekla_fix_column_handles` | 重新定向翻转的柱子(交换倒置句柄)。 |
### C# 脚本逃生口
Tekla Open API 比这个工具集大得多。当没有专用工具满足需求时,代理可以运行一个简短的、**策略检查的 C# 脚本**,针对实时模型 — 在验证 API 签名后:
| 工具 | 描述 |
|---|---|
| `tekla_search_api` | 在本地生成的 Tekla Open API 参考(类型 + 成员签名)上进行关键字搜索。 |
| `tekla_get_api_doc` | 完整引用页面,用于一种类型:每个构造函数/属性/方法签名,带有摘要。 |
| `tekla_run_csharp` | 运行 C# 脚本(顶级语句,Tekla 命名空间预导入,`Print(...)` 用于输出,最后一个表达式 = JSON 返回值)。 |
安全模型:
- **默认情况下只读,同意后写入。** 变异成员(`Insert`/`Modify`/`Delete`/`CommitChanges`/`SetUserProperty`/`Operation.*`)在调用未设置 `allowMutations=true` 时被拒绝 — 并且工具合同要求代理显示脚本并在设置前获得您的明确同意。脚本更改应尽可能使用 `MCP_ORIGIN` UDA 进行标记;已提交的更改可以使用 Tekla 的 **Ctrl+Z** 撤销。
- **无主机访问。** 语法级策略禁止文件系统、网络、进程、反射、线程和 `Console`(stdout 属于 MCP 协议)。 `#r`/`#load` 和 `await` 也被拒绝。
- **硬超时**(默认 60 秒,最大 600 秒)在专用线程上。
- **有界输出。** `Print` 限制为 500 行;返回值防御性地呈现为 JSON(深度/大小限制,每个属性尝试/捕获)。
`tekla_search_api` 读取 [tools/TeklaApiDoc](tools/TeklaApiDoc/README.md) 生成的引用,位于 `reference/tekla-api`(或 `TEKLA_MCP_API_REF_DIR`)。在每个机器上生成一次 — 借助它,代理验证签名而不是编造它们。
### 报告空白
服务器附带 MCP **指令**,为连接的代理提供了一个升级渠道:首先使用专用工具;用脚本逃生口桥接一次性需求(绝不是外部临时自动化,绝不是构造的数据);并为缺少或重复的内容调用 `tekla_report_gap`。`tekla_report_gap` 返回一个可以直接提交的 GitHub 问题草稿(并在本地记录请求)供您提交 — 循环脚本正是需要构建一流工具的信号。服务器本身从不创建问题(它不持有 GitHub 凭证)。
### 共享筛选器参数
大多数查询和分析工具接受:
- `type` — 准确的对象类型(`Beam`、`ContourPlate`、`Bolt`,...)
- `class` — 准确的类别
- `profile` — 剖面子字符串
- `material` — 材料子字符串
- `nameContains` — 名称子字符串
- `udaName` + `udaEquals` — 准确的 UDA 匹配
- `attributeName` + `attributeEquals` / `attributeContains` — 准确/子字符串匹配任何已知属性
- `guidIn` — 显式 GUID 允许列表(用于 `tekla_select_objects`)
- `useSelection` — 将工具范围限定在 **当前 Tekla UI 选择** 而不是整个模型(更快;启用“分析我选择的工作流”)
### 示例提示
- “列(`Beam` 类型,名称包含 `Column`)的总重量是多少?”
- “显示当前模型中按重量排名前几的材料。”
- “按剖面分组梁并显示每个组的重量。”
- “有多少对象属于 20 类?”
- “在 Tekla 中选择所有 20 类对象。”
- “查找 `BK1` 存储的位置(`tekla_find_attributes_by_value`)。”
- “选择 `RU_FN1_MRK = BK1` 的列。”
- “梁具有 `20P` 剖面有多少个独特的连接类型?”
- “读取此 GUID 的 UDA `USER_FIELD_1` 和 `USER_PHASE`。”
- “预览在所有 `I30K1` 列上设置 `USER_FIELD_1=KMD; USER_PHASE=2` 而不应用。”
- “我选择了一些零件 — 求它们的重量并按剖面分组(`useSelection=true`)。”
- “有多少个独特的组件标记,它们中最重的是哪个?”
- “列出组件 `B1` 的零件。”
- “运行建模问题检查并显示缺少的材料或未编号的内容。”
- “读取此 GUID 的 `VOLUME`、`AREA` 和 `PHASE`(`tekla_get_properties`)。”
- “导出所有 20 类梁的 CSV 物料清单。”
### UDA 写入安全
`tekla_set_object_udas` 和 `tekla_set_udas_by_filter` 默认 **预览模式**(`apply=false`)。传递 `apply=true` 以提交更改。批量写入受 `limit` 限制(默认 200 个对象)。
---
## 要求
**生产(实时 Tekla 模型):**
- Windows x64
- Tekla Structures 已安装,**运行并打开模型**
- [.NET SDK 8+](https://dotnet.microsoft.com/download)
- [.NET Framework 4.8 开发者包](https://dotnet.microsoft.com/download/dotnet-framework/net48)
**开发/测试(模拟后端,无 Tekla):**
- [.NET SDK 8+](https://dotnet.microsoft.com/download)
---
## 快速入门
### Windows — 从 GitHub 版本安装(推荐)
版本提供 **每个 Tekla 版本的一个 zip** — 选择与您的 Tekla 匹配的版本:
1. 打开 **[Releases](https://github.com/tempalg1n/tekla-mcp-server/releases)** 并下载适用于您的 Tekla 版本的 zip:`TeklaMcp.Server-vX.Y.Z-tekla2021.zip` … `-tekla2026.zip`(例如运行 Tekla Structures 2023 → `…-tekla2023.zip`)。
2. 将 zip 提取到一个文件夹(保持所有 `.dll` 文件在 `.exe` 旁边)。
3. 打开 Tekla Structures 并加载模型,并将您的 MCP 客户端指向 `TeklaMcp.Server.exe`(请参见 [MCP 客户端配置](#mcp-客户端配置))。
> **为什么每个版本都有单独的 zip?** Tekla Open API 协议是版本锁定的,因此服务器必须编译为它所对应的 Tekla。zip **不** 捆绑 Tekla DLL — 它从已安装的 Tekla 运行时加载它们,验证版本匹配。错误的 zip 会出现明确的消息,指出正确的名称。如果自动检测 Tekla `bin` 文件夹失败,请设置 `TEKLA_BIN_DIR` 环境变量。参见 [docs/tekla-api-notes.md](docs/tekla-api-notes.md#tekla-version-compatibility)。
>
> **如果 Tekla 已打开但服务器显示“未连接”:** 错误消息列出了客户端通道和 `Tekla.Structures.Model-*` 命名管道,Tekla 实际发布。服务器自动匹配发布的通道(一些设置发布 `…-Console:<version>` 而不是默认的 `…-:<version>`)。要强制指定通道,请设置 `TEKLA_MCP_CHANNEL` 环境变量以获取确切的管道名称。
参见 [docs/releasing.md](docs/releasing.md) 以了解维护人员如何发布版本。
### Windows — 从源代码构建
```powershell
# 传递与您安装的 Tekla 匹配的 TeklaVersion(NuGet 包版本,年份优先 —
# 参见 docs/releasing.md 以获取每个年份的准确每年的字符串):
dotnet build TeklaMcp.sln -c Release -p:TeklaVersion=2023.0.1
# 打开 Tekla Structures 并加载模型,然后:
dotnet run --project src/TeklaMcp.Server -f net48 -c Release`
```powershell
# 强制使用模拟后端,即使在 Windows 上(例如,当 Tekla 未打开 Tekla 时使用)
```powershell
$env:TEKLA_MCP_USE_MOCK = "1"
dotnet run --project src/TeklaMcp.Server -f net48
```
### 模拟后端(无 Tekla)
```bash
dotnet run --project src/TeklaMcp.Server
```
服务器通过 **stdio** 与 MCP 对话,并等待客户端。交互式测试工具:
```bash
npx @modelcontextprotocol/inspector dotnet run --project src/TeklaMcp.Server
```
[scripts/mcp_smoke_test.py](scripts/mcp_smoke_test.py) 提供了一个 Python 冒烟测试脚本。
### 安全重建助手(Windows)
对于本地开发,您可以使用 [scripts/build-safe.ps1](scripts/build-safe.ps1)。
它停止运行的 `TeklaMcp.Server` 进程(避免锁定 `net48` DLL),然后运行 `clean` + `build`。
```powershell
# 默认:杀死正在运行的服务器进程,清理,构建(Release)
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-safe.ps1
# 仅构建服务器项目
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-safe.ps1 -ServerOnly
# 更快的循环:跳过清理
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-safe.ps1 -SkipClean
# 在构建后包含 Python MCP 冒烟测试
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-safe.ps1 -RunSmokeTest
```
---
## 路线图
- [x] 核心读取工具:连接、摘要、列表、查找、选择
- [x] 分析:计数、重量求和、分组、材料分解
- [x] 通过 `tekla_select_objects` 进行 UI 选择
- [x] 默认情况下具有预览的安全 UDA 读取/写入
- [ ] 更广泛的对象覆盖:螺栓、组件、钢筋、几何形状
- [ ] 核心和模拟层的自动化测试
- [ ] 2023-2026 年 Tekla 兼容性矩阵
欢迎贡献 — 请参见 [CONTRIBUTING.md](CONTRIBUTING.md)。
发布历史记录:[CHANGELOG.md](CHANGELOG.md)。
---
## 致谢
本项目由 **[Claude Opus 4.8](https://www.anthropic.com/claude)** (Anthropic)使用 AI 辅助架构、实现和文档设计。
Tekla Structures 是 [Trimble](https://www.tekla.com/) 的产品。本项目与 Trimble 无关联,也未获得 Trimble 的认可。
---
## 许可
[MIT](LICENSE) — 请参阅 LICENSE 文件以获取详细信息。
</div>