
Cursor не открывает .rvt как текст. Он подключается к уже запущенному Revit и работает с живой моделью: читает коллекторы, меняет параметры, переименовывает виды, применяет шаблоны. Ниже — рабочая схема, собранная на Revit 2022 и проверенная на шаблоне выпуска (штампы, листы, спецификации, диспетчер). Это не обзор «всех MCP для Revit», а точная инструкция: какие пакеты, какие файлы, какие формулировки задач дают результат, а какие упираются в API.
Зачем отдельный коннектор
Типичная ошибка: установить коммерческий A.I. Connector, увидеть список инструментов в Cursor и начать править модель. У бесплатной редакции запись часто отключена: чтение есть, set_* нет. Тогда Cursor честно отвечает «я вижу штриховки, но переименовать не могу» — и предлагает Dynamo.
Рабочий бесплатный путь с чтением и записью:
| Слой | Роль |
|---|---|
| Autodesk Revit | Модель, API |
| pyRevit | Расширение внутри процесса Revit, Routes API |
| mcp-server-for-revit-python | MCP-сервер: Cursor говорит с ним, он ходит в Routes |
| Cursor | Агент, правила, чат |
Ключевой инструмент не «кнопка переименовать лист», а execute_revit_code: произвольный IronPython 2.7 в контексте открытого документа. Готовые get_* / list_* удобны для разведки; любая нестандартная правка — код.
Архитектура: два сервера, не один
Cursor (Agent)
│ MCP stdio
▼
main.py — FastMCP «Revit MCP Server»
│ HTTP http://127.0.0.1:48884/revit_mcp/...
▼
pyRevit Routes (живёт внутри Revit)
│ Revit API / IronPython
▼
Открытый .rvt
Они не конкурируют за один порт.
- MCP-сервер слушает Cursor по stdio (так прописано в
mcp.json). - pyRevit Routes слушает
127.0.0.1:48884. - Исключение:
launch_revitиlist_revit_installationsработают на стороне MCP (реестр Windows +subprocess), затем опрашивают/status/, пока мост не ответит.
Проверка, что Revit-сторона жива — в браузере:
http://127.0.0.1:48884/revit_mcp/status/
Ожидаемый ответ:
{
"status": "active",
"health": "healthy",
"revit_available": true,
"document_title": "имя_открытого_файла",
"api_name": "revit_mcp"
}
Если страница не открывается — Cursor бесполезен, какой бы mcp.json ни был. Сначала Revit + pyRevit + открытая модель.
Состав стека: точные имена
Приложения
| Что | Версия / пакет | Зачем |
|---|---|---|
| Autodesk Revit | 2022 (в этой связке) | Хост модели |
| pyRevit | 6.5.5 (6.5.5.26237+2044) | Routes + IronPython 2.7 внутри Revit |
| Cursor | текущий desktop | Агент + MCP-клиент |
| uv | uv.exe (у Cursor часто лежит в Hermes) | Запуск MCP-сервера |
Репозиторий коннектора:
https://github.com/mcp-servers-for-revit/mcp-server-for-revit-python
Имена внутри:
- MCP-сервер:
main.py, пакетmcp[cli](FastMCP) - pyRevit-расширение:
revit-mcp-python(extension.json→"name": "revit-mcp-python") - Routes API name:
revit_mcp - В Cursor сервер называется
Revit(в логах инструментов — namespaceuser-Revit)
Python-пакеты MCP-сервера
Файл requirements.txt коннектора (ориентир; uv run --with mcp[cli] может подтянуть mcp отдельно на лету):
annotated-types==0.7.0
anyio==4.9.0
certifi==2025.4.26
click==8.1.8
colorama==0.4.6
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
httpx-sse==0.4.0
idna==3.15
markdown-it-py==3.0.0
mcp==1.28.1
mdurl==0.1.2
pydantic==2.11.4
pydantic-core==2.33.2
pydantic-settings==2.9.1
pygments==2.19.1
python-dotenv==1.2.2
python-multipart==0.0.31
rich==14.0.0
shellingham==1.5.4
sniffio==1.3.1
sse-starlette==2.3.5
starlette==1.3.1
typer==0.15.4
typing-extensions==4.13.2
typing-inspection==0.4.0
uvicorn==0.34.2
На стороне Revit отдельный venv не нужен: код маршрутов исполняет IronPython 2.7 движка pyRevit (IPY2712PR). Это не CPython 3.
uv на Windows
Официально:
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
В рабочей конфигурации Cursor запускает не «системный» uv из PATH, а:
C:\Users\<user>\AppData\Local\hermes\bin\uv.exe
Если uv в терминале «не находится», в mcp.json лучше указать полный путь к этому uv.exe.
Установка по шагам
1. pyRevit
- Поставить pyRevit (тот же major, что в таблице выше).
- Привязать к нужной версии Revit (здесь — 2022).
- Открыть Revit → вкладка pyRevit должна появиться на ленте.
Конфиг pyRevit: %APPDATA%\pyRevit\pyRevit_config.ini
Рабочий фрагмент:
[environment]
clones = {"master":"C:\\Users\\<user>\\AppData\\Roaming\\pyRevit-Master"}
[core]
userextensions = ["C:\\Users\\<user>\\AppData\\Roaming\\pyRevit\\Extensions"]
[routes]
enabled = true
host = "127.0.0.1"
port = 48884
[revit-mcp-python.extension]
disabled = false
В UI то же самое:
- pyRevit → Settings → Routes — включить Routes Server.
- Host
127.0.0.1, port48884.
2. Расширение MCP внутри Revit
Клонировать репозиторий, например:
C:\Users\<user>\Documents\__projects\non\mcp-server-for-revit-python
В pyRevit расширение должно лежать как папка с суффиксом .extension. На практике это копия:
%APPDATA%\pyRevit\Extensions\revit-mcp-python.extension\
Внутри обязательны startup.py, extension.json, каталог revit_mcp\.
Два способа установки из README проекта:
- pyRevit → Extensions → MCP Server for Revit Python → Install (путь по умолчанию как раз
%APPDATA%\pyRevit\Extensions). - Вручную: клон → имя папки с
.extension→ Settings → Custom Extensions → путь → Save → Reload pyRevit (иногда полный рестарт Revit).
После загрузки startup.py регистрирует маршруты: status, model_info, views, placement, colors, code_execution, document.
Две копии — ловушка. Cursor гоняет main.py из папки проекта. Revit грузит маршруты из %APPDATA%\pyRevit\Extensions\.... Правка revit_mcp\code_execution.py только в проекте не попадёт в Revit, пока не синхронизируете extension и не перезагрузите pyRevit.
3. Cursor MCP
Файл: %USERPROFILE%\.cursor\mcp.json
Рабочая конфигурация:
{
"mcpServers": {
"Revit": {
"command": "C:\\Users\\<user>\\AppData\\Local\\hermes\\bin\\uv.exe",
"args": [
"run",
"--directory",
"C:\\Users\\<user>\\Documents\\__projects\\non\\mcp-server-for-revit-python",
"--with",
"mcp[cli]",
"mcp",
"run",
"main.py"
],
"timeout": 60000
}
}
}
Что важно:
--directory— корень клона, чтобыmain.pyи пакетtoolsнаходились.--with mcp[cli]— uv подтягивает MCP SDK, даже если локальный venv неполный.timeout: 60000 — 60 секунд на вызов. Совпадает с таймаутомexecute_revit_codeна HTTP (timeout=60.0). Массовые коллекторы по большому шаблону иногда упираются сюда: дробите задачу или поднимайте оба таймаута согласованно.- После правки
mcp.jsonполностью перезапустите Cursor, не только окно чата.
В Cursor: Settings → MCP — сервер Revit должен быть зелёным, когда Revit открыт и /status/ отвечает.
4. Правило агента (обязательно)
Готовые MCP-кнопки не покрывают BIM-шаблон. Без правила агент будет звать несуществующие set_* или Nonica. Файл проекта:
.cursor/rules/revit-mcp.mdc
---
description: Use pyRevit MCP Python as the primary Revit connection
alwaysApply: true
---
Revit is connected through **pyRevit MCP Python**, not NonicaTab write tools.
- Prefer `execute_revit_code` for any model change (rename fill patterns, set parameters, collectors).
- Ready-made tools (`get_revit_model_info`, `get_current_view_elements`, `list_levels`, …) are fine for reads.
- Code is IronPython 2.7: no f-strings, no type hints, wrap edits in a Transaction (the tool may already wrap one — do not double-start if it errors).
- Do not call Nonica `set_*` tools. Nonica Free cannot write.
- Before destructive edits, ask the user to save a copy of the `.rvt`.
- Routes API: `http://127.0.0.1:48884/revit_mcp/` — Revit must be open with pyRevit loaded.
alwaysApply: true — правило висит на каждом чате в этом workspace.
5. Порядок запуска в рабочий день
- Открыть Revit 2022.
- Открыть модель или шаблон (не пустой splash без документа).
- Убедиться, что на ленте есть pyRevit.
- Проверить
http://127.0.0.1:48884/revit_mcp/status/. - Открыть Cursor в папке проекта (там же правило и клон MCP).
- В чате: «проверь доступ к Revit» — агент должен вызвать
get_revit_statusи увидеть имя файла.
Workshared-файл: агент ходит в локальную копию, которая сейчас открыта. sync_with_central есть, но это уже осознанный шаг, не фон.
Каталог инструментов
Готовые инструменты (то, что Cursor реально видит у сервера Revit):
Статус и модель
| Инструмент | Назначение |
|---|---|
get_revit_status | Жив ли Routes, имя документа |
get_revit_model_info | Сводка по открытой модели |
list_levels | Уровни и отметки |
Виды и картинка
| Инструмент | Назначение |
|---|---|
list_revit_views | Экспортируемые виды по типам |
get_revit_view | PNG вида по имени (агент видит чертёж) |
get_current_view_info | Активный вид: масштаб, шаблон, дисциплина |
get_current_view_elements | Элементы текущего вида (limit по умолчанию 5000) |
get_revit_view — недооценённый инструмент: можно попросить «открой лист 01.0.1 и покажи, что на штампе», не гадая по именам параметров.
Семейства
| Инструмент | Назначение |
|---|---|
list_family_categories | Категории семейств |
list_families | Типы, фильтр contains, limit (по умолчанию 50) |
place_family | Постановка экземпляра в точку |
Для аудита штампов list_families с contains: "sx__Лист" быстрее, чем писать коллектор. Для «какие типы реально вставлены на листы» — всё равно execute_revit_code: готовый список типов не говорит, где instance.
Цвет
| Инструмент | Назначение |
|---|---|
color_splash | Раскрасить категорию по параметру |
clear_colors | Снять override |
list_category_parameters | Какие параметры есть у категории |
Удобно для проверки: «покажи стены по sx__Марка». Это визуальный QA, не замена фильтров вида.
Документ
| Инструмент | Назначение |
|---|---|
list_revit_installations | Год и путь установки |
launch_revit | Старт Revit, опционально файл, язык (ENU, …), timeout 120 с |
open_document | Открыть .rvt / .rfa / .rte; detach, audit |
close_document | Закрыть; save по умолчанию false |
save_document | Save / Save As |
sync_with_central | Синхронизация workshared; comment, compact, relinquish_all |
open_document с detach: true — правильный способ «посмотреть центральную, не привязываясь». Не просите агента Save As поверх центральной без явной команды.
Главный инструмент
execute_revit_code(code, description)
В коде уже есть:
doc— активный документuidoc— UI-документDB—Autodesk.Revit.DBrevit— модуль pyRevitprint— уходит в ответ инструмента
Транзакция не открывается сама. Для записи:
t = DB.Transaction(doc, "Rename sheets")
t.Start()
# ...
t.Commit()
Смена активного вида — вне транзакции:
uidoc.ActiveView = target_view
HTTP-таймаут вызова — 60 секунд. Тяжёлые проходы (все спецификации шаблона, все семейства штампов) дробите: сначала dump в JSON через print, потом правка пачками.
Как формулировать задачи, чтобы агент не «плыл»
Связка сильна на массовых, однозначных, проверяемых операциях. Слаба на том, чего нет в API, и на размытом «наведи красоту».
Шаблон хорошего запроса
- Где — файл уже открыт / имя документа / папка диспетчера.
- Что — конкретный параметр, категория, префикс.
- Критерий — «все спецификации с
sx__Группа вида1=02_РД». - Исключения — «лист
1 Условныене трогать». - Проверка — «выведи счётчик до/после».
Плохо: «почисти штампы».
Хорошо: «собери все Title Blocks: семейство, типы, на скольких листах instance, только витрина или рабочие альбомы. Потом предложи, что удалить».
Плохо: «переименуй листы как надо».
Хорошо: «у листов с sx__Группа вида1 = 01_ЭП системный номер 10.x → 01.x. Печатный sx__НомерЛиста не менять».
Скриншоты
Агент видит картинку диалога. Это отлично для спецификации желаемого (таблица Model Line Weights, переименованный фильтр стадий). Это не гарантия, что API позволит то же самое записать. Если после разведки агент говорит «в API этого нет» — не давите на UI-кликер: модальные окна Revit почти не автоматизируются из IronPython.
Сначала разведка, потом запись
Рабочий ритм из реальных сессий:
get_revit_status— тот ли файл.- Коллектор /
list_*— сколько объектов, какие имена. - Короткий план в чат (группы, исключения).
- Транзакция.
- Повторный коллектор — сверка счётчиков.
Не просите «сразу удаляй» на первом сообщении, если сами не видели инвентаризацию. И наоборот: после явного «удаляй лишние» агент должен удалять, а не согласовывать третий круг.
Примеры, которые хорошо ложатся на эту связку
Ниже — типы задач, которые на шаблоне выпуска отрабатываются часами вручную и минутами из Cursor. Формулировки можно копировать.
1. Инвентаризация семейств штампа
Запрос: «Посмотри семейства штампа. Я вижу sx__Лист_….rfa. Что ещё загружено, что стоит на листах, что только в проекте.»
Как делать: FilteredElementCollector по Family / FamilySymbol категории Title Blocks + collector экземпляров на ViewSheet. Свести таблицу: семейство, типы, «на листах / только витрина / нигде».
Почему MCP: руками это клик по каждому листу. Код за один проход отличает «лежит в проекте» от «вставлено».
2. Массовая нумерация листов
Запрос: «Все листы в 01_ЭП — номер с 10. на 01.. Печатный номер не трогать.»
Как делать: параметр sx__Группа вида1 на ViewSheet + Sheet Number (SHEET_NUMBER). Не путать с sx__НомерЛиста.
Типичная ловушка: после 10. → 1. понадобится второй проход 1. → 01., иначе сортировка диспетчера поедет. Просите сразу целевой формат: 01.x.
3. Шаблоны видов на все спецификации стадии
Запрос: «Для всех спецификаций 01_ЭП шаблон Спец_Manrope, для 02_РД — Спец_Arial.»
Как делать: сначала спросить агента, что включает шаблон (у этих двух в шаблоне было включено только Appearance — шрифт сетки, не поля/фильтры). Потом View.ViewTemplateId.
Зачем спрашивать состав шаблона: если в шаблоне включены Fields, вы затрёте структуру спецификации. Разведка через API дешевле, чем откат 140 спек.
4. Тематические папки диспетчера
Запрос: «Спецификации 01_ЭП и 02_РД: разобрать sx__Группа вида2 по темам 00_Название (полы, потолки, мебель…). Сводные со словом СВОДНАЯ — в отдельную группу.»
Как делать: dump имён → классификатор по подстрокам (Двери_, Потолок, СВОДНАЯ) → запись параметра. Префикс в имени сильнее случайного слова: Двери_плинтус всё равно проёмы, не полы.
Это лучший класс задач для агента: много однотипных элементов, правило можно сформулировать, результат проверяется списком.
5. Переименование по всему проекту
Запрос: «Везде ДП → РД: виды, шаблоны видов, легенды, листы, семейство штампа, сокращение стадии. ДП-РД и ДП/РД сначала в РД, потом голый ДП. Полное “ДИЗАЙН-ПРОЕКТ” не трогать.»
Как делать: явный порядок замен (иначе ДП-РД станет РД-РД). Отдельные сущности: View.Name, ViewFamilyType, project parameter sx__СтадияПроектаСокращенно, Family.Name. После прохода — поиск остатков ДП и отчёт «0 leftover».
6. Параметры: где Марка и куда назначить
Запрос: «Найди спецификации, где поле Марка. Список категорий. Добавь эти категории в параметр sx__Марка.»
Связка «спека использует поле → категория должна иметь параметр» — ручная дыра в шаблонах. Коллектор спецификаций + GetSchedulableFields / поля + CategorySet у параметра.
7. Документация шаблона
Запрос: «Глубоко разбери открытый шаблон и напиши инструкцию в .md в том же стиле, что существующий регламент по листам.»
Агент здесь — исследователь: Project Information, параметры шаблона, организация браузера, альбомы. Пишет не код в модель, а регламент для людей. Имеет смысл держать такие файлы в том же workspace, чтобы следующие чаты опирались на них, а не заново инвентаризировали 200 спецификаций.
8. Визуальная сверка
Запрос: «Переименуй фильтр стадий Show All → Показать все» + скриншот.
Имя фильтра — API. Скриншот нужен, чтобы агент не перепутал Phase Filter с Phase и с Phase Filter на виде.
IronPython 2.7: что ломает правки
Код в execute_revit_code — не тот Python, на котором вы пишете скрипты в Cursor.
| Нельзя | Вместо этого |
|---|---|
| f-строки | "%s" % x или "{}".format(x) |
| type hints в исполняемом фрагменте | без аннотаций |
print(f"{name}") | print(name) |
| Кириллица в литерале исходника MCP | \u0414\u041f или сравнение со строкой, уже прочитанной из Revit |
next(x for x in xs if …) иногда капризничает | обычный for |
Двойной t.Start(), если снаружи уже транзакция | по ошибке отката — убрать свою обёртку |
Кириллица — главная боль русскоязычного шаблона. Литерал "02_ДП" в коде, который едет JSON-ом через HTTP, часто не совпадает с именем параметра в документе. Надёжный приём:
- Прочитать значения из Revit (
p.AsString()). - Сравнивать с ними.
- Для новых имён собирать строку через
unichr/\uXXXX.
Имя элемента:
name = getattr(el, "Name", None)
if not name:
p = el.get_Parameter(DB.BuiltInParameter.VIEW_NAME)
name = p.AsString() if p else "?"
Проверка перед записью:
if element:
# ...
Чего ждать не стоит
Revit API — не полный UI. Если агент упёрся, это часто не «плохой промпт».
Нет публичного API на таблицу Model Line Weights (мм пера по масштабам). Category.SetLineWeight ставит номер пера 1–16, не толщину в мм. Внутренние PenWidthTable / PenInfoForScale — пустые managed-обёртки. Перенос — Transfer Project Standards вручную, с Overwrite, не New Only. Клики по сетке GXWND из скрипта ненадёжны.
PostCommand (открыть диалог Line Weights, Transfer…) ставится в очередь и плохо стыкуется с MCP: модальное окно блокирует Revit, UIA Revit-кнопок без InvokePattern, кастомный грид не отдаёт ячейки.
Не всё «переименовать уровень при копировании» чинится: внутренний seed имени уровня API не сбрасывает. Можно переименовать уже созданный уровень, нельзя заставить следующий Copy называться 2 этаж.
UI-only настройки (некоторые Extra Settings, часть Transfer Project Standards) остаются ручными. Честный ответ агента здесь ценнее, чем час SendInput.
Безопасность и worksharing
- Перед удалением семейств, purge, массовой заменой имён — Save As / локальная копия. Правило агента должно это спрашивать; человек подтверждает.
- Workshared: правки идут в открытую локальную.
sync_with_central— отдельная команда (comment,relinquish_all). execute_revit_code— полный доступ к API. Опечатка в фильтре коллектора может переименовать не те виды. Просите счётчики и список имён до Commit, если объём большой.- Routes без авторизации, только localhost. Для продакшена на общей машине это осознанный риск README проекта.
- Не путать активный документ: если открыты шаблон и чужой
.rte, коллекторы идут в active. Имеет смысл начинать сprint(doc.Title)/get_revit_status.
Мини-шпаргалка промптов
Проверка моста:
Проверь
get_revit_status: какой файл открыт, Routes healthy?
Разведка без записи:
Выведи все Title Block: семейство, типы, число экземпляров на листах. Ничего не удаляй.
Массовая запись с границей:
У видов и спецификаций с
sx__Группа вида1=02_ДПзамени группу на02_РД. Остальные группы не трогай. В конце — сколько изменено.
Шаблон вида:
Сначала покажи, какие вкладки включены у шаблонов
Спец_ArialиСпец_Manrope. Если только Appearance — примени Manrope ко всем спекам01_ЭП, Arial — ко всем02_РД.
Документ для команды:
По открытому шаблону напиши инструкцию: сведения о проекте, диспетчер, альбомы. В том же стиле, что уже принятый регламент по листам.
Чеклист, если «Cursor не видит Revit»
- Revit запущен, документ открыт, не только стартовый экран без файла.
- Вкладка pyRevit на ленте.
pyRevit_config.ini:[routes] enabled = true, порт 48884.- Браузер:
http://127.0.0.1:48884/revit_mcp/status/. - Extension
revit-mcp-pythonнеdisabled. - Cursor перезапущен после правки
mcp.json. - В MCP Settings сервер Revit не красный.
--directoryуказывает на папку сmain.py.uv.exeпо пути изcommandсуществует.- Нет второго коннектора (старый Nonica в
mcp.json), который перехватывает имяRevit.
Коротко: как работать эффективно
Держите в одном workspace клон MCP, правило .mdc, регламенты шаблона. Агент тогда не заново открывает Америку каждый чат.
Используйте готовые MCP-методы для «что открыто / какие уровни / покажи вид». Всё остальное — execute_revit_code с транзакцией, без f-строк, с \uXXXX для кириллицы.
Просите задачи, которые считаются: N листов, M спецификаций, 0 leftover ДП. Не просите закрыть дыры API кликами по диалогам.
Сначала инвентаризация и правило замены, потом Commit. На workshared-шаблоне это разница между «полезный проход по диспетчеру» и «сюрприз на синхронизации».