Cursor + Revit

Cursor + Revit - AVRO

Cursor подключается к уже запущенному Revit и работает с живой моделью: читает коллекторы, меняет параметры, переименовывает виды, применяет шаблоны. Ниже — рабочая схема на Revit 2022 и pyRevit 6.5.5, проверенная на шаблоне выпуска (штампы, листы, спецификации, диспетчер): какие пакеты и файлы нужны, какие формулировки задач дают результат и где всё упирается в API.

Что изменилось к октябрю 2026:

  • Коннектор mcp-server-for-revit-python теперь требует сопряжения: в Revit MCP → Bridge → Connect. Без него запросы отклоняются, включая проверку статуса из браузера.
  • Изменения модели и выполнение Python коннектор показывает на подтверждение прямо в Revit.
  • В репозитории появился uv.lock, рекомендуемый запуск — uv run --frozen.
  • pyRevit 7.0 (вышел 6 октября 2026) получил встроенный agent runtime — свой MCP-сервер без Routes и без стороннего расширения. Он пока экспериментальный; сравнение — в разделе про архитектуру.

Зачем отдельный коннектор

Типичная ошибка: поставить коммерческий AI-коннектор, увидеть в Cursor список инструментов и начать править модель. В бесплатных редакциях запись часто отключена: чтение есть, set_* нет. Тогда Cursor честно отвечает «вижу штриховки, но переименовать не могу» и предлагает Dynamo.

Бесплатный путь с чтением и записью собирается из пяти частей:

СлойВерсия в этой связкеРоль
Autodesk Revit2022Модель и API
pyRevit6.5.5 (6.5.5.26237+2044)Расширение внутри процесса Revit, Routes API, IronPython 2.7
mcp-server-for-revit-pythonmaster, октябрь 2026MCP-сервер: Cursor говорит с ним, он ходит в Routes
Cursorтекущий desktopАгент, правила, чат
uvлюбая свежаяЗапускает MCP-сервер

Ключевой инструмент — не «кнопка переименовать лист», а execute_revit_code: произвольный IronPython 2.7 в контексте открытого документа. Готовые get_* и list_* удобны для разведки, любая нестандартная правка — это код.

Имена, которые встретятся дальше:

  • Репозиторий: mcp-servers-for-revit/mcp-server-for-revit-python.
  • MCP-сервер: main.py на FastMCP (пакет mcp[cli]).
  • pyRevit-расширение: revit-mcp-python (поле name в extension.json), Routes API — revit_mcp.
  • В Cursor сервер называется Revit, в логах инструментов — user-Revit.

Python-зависимости MCP-сервера зафиксированы в uv.lock репозитория, вручную их ставить не нужно. На стороне Revit отдельный venv тоже не нужен: код маршрутов исполняет IronPython 2.7 движка pyRevit, а не CPython 3.

Архитектура: два сервера, не один

Связка работает как цепочка из двух серверов, и они не конкурируют за порт. MCP-сервер main.py слушает Cursor по stdio — так прописано в mcp.json. pyRevit Routes живёт внутри Revit и слушает 127.0.0.1:48884; MCP-сервер переводит каждый вызов инструмента в HTTP-запрос к нему.

Исключение — launch_revit и list_revit_installations. Они работают целиком на стороне MCP (реестр Windows и subprocess), а потом опрашивают /status/, пока мост не ответит.

[embed: node/6de6537a-c3d4]

Слева — схема из этой статьи, справа — встроенный вариант pyRevit 7: вместо HTTP-моста он использует именованный канал и собственный хост внутри Revit.

Проверка моста

В старых версиях коннектора хватало открыть в браузере http://127.0.0.1:48884/revit_mcp/status/. В текущей версии браузерный запрос без заголовка сопряжения отклоняется. Сначала MCP → Bridge → Connect в Revit, потом из папки клона:

uv run --frozen python -c "import anyio; from main import revit_get; print(anyio.run(revit_get, '/status/'))"

Ожидаемый ответ:

{
  "status": "active",
  "health": "healthy",
  "revit_available": true,
  "document_title": "имя_открытого_файла",
  "api_name": "revit_mcp"
}

Если ответа нет — Cursor бесполезен, какой бы mcp.json ни был. Сначала Revit, pyRevit, открытая модель и сопряжение.

Альтернатива: agent runtime в pyRevit 7

В pyRevit 7.0 появился собственный MCP-сервер. Он не использует Routes: CLI pyrevit mcp говорит с хостом внутри Revit через именованный канал, доступный только текущему пользователю Windows. Подключение к Cursor — три команды:

pyrevit configs agent enable
pyrevit mcp install cursor
pyrevit agent status

Чем он отличается от стороннего коннектора:

  • Вместо одного execute_revit_code — раздельные run_query (изменения всегда откатываются) и run_modify, плюс inspect_elements, lookup_revit_api, capture_view.
  • По умолчанию (политика ask) каждая правка показывается в Revit с изолированными элементами: Keep фиксирует её одной записью отмены Agent: <название>, Discard откатывает.
  • Во время прогона блокируются сохранение, экспорт и синхронизация; таймаут скрипта — 300 секунд по умолчанию, до 3600.
  • Движок — IronPython или CPython; get_context сообщает, какой синтаксис доступен.

Оговорки: функция помечена как экспериментальная, в документации хост проверен на Revit 2024 и 2025 — на Revit 2022 его стоит проверить отдельно. Скрипты, запросы и результаты прогонов хранятся открытым текстом в %APPDATA%\pyRevit\agent до 14 дней. Остальная статья — про сторонний коннектор, но почти все приёмы формулировки задач переносятся на оба варианта.

Установка по шагам

1. pyRevit

  1. Поставить pyRevit и привязать его к нужной версии Revit (здесь — 2022).
  2. Открыть Revit: на ленте должна появиться вкладка pyRevit.
  3. Включить Routes: pyRevit → Settings → Routes → Routes Server, host 127.0.0.1, port 48884.

То же самое в %APPDATA%\pyRevit\pyRevit_config.ini:

[routes]
enabled = true
host = "127.0.0.1"
port = 48884

[revit-mcp-python.extension]
disabled = false

Явный host = "127.0.0.1" важен: без него Routes может слушать все интерфейсы.

2. Расширение MCP внутри Revit

Два способа из README проекта:

  1. pyRevit → Extensions → MCP Server for Revit Python → Install. Путь по умолчанию — %APPDATA%\pyRevit\Extensions.
  2. Вручную: клонировать репозиторий, добавить к имени папки суффикс .extension, указать путь в Settings → Custom Extensions, сохранить и перезагрузить pyRevit (иногда нужен полный рестарт Revit).

Внутри папки обязательны startup.py, extension.json и каталог revit_mcp\. После загрузки startup.py регистрирует маршруты: status, model_info, views, placement, colors, code_execution, document.

Две копии — ловушка. Cursor запускает main.py из папки клона, а Revit грузит маршруты из %APPDATA%\pyRevit\Extensions\.... Правка revit_mcp\code_execution.py только в клоне не попадёт в Revit, пока вы не синхронизируете расширение и не перезагрузите pyRevit.

3. Сопряжение

В Revit: MCP → Bridge → Connect. Коннектор создаёт зашифрованный секрет для вашего пользователя Windows; Disconnect его отзывает. Сопряжение общее для всех запущенных Revit этого пользователя, поэтому выберите правильный порт Routes до подключения.

4. Cursor

Файл %USERPROFILE%\.cursor\mcp.json (или .cursor\mcp.json в папке проекта):

{
  "mcpServers": {
    "Revit": {
      "command": "C:\\Users\\<user>\\.local\\bin\\uv.exe",
      "args": [
        "run",
        "--directory",
        "C:\\path\\to\\mcp-server-for-revit-python",
        "--frozen",
        "mcp",
        "run",
        "main.py"
      ],
      "timeout": 60000
    }
  }
}

Что здесь важно:

  • --directory — корень клона, чтобы находились main.py и пакет tools.
  • --frozen — uv берёт версии из uv.lock и не пересобирает окружение на лету.
  • command — полный путь к uv.exe. Установщик uv кладёт его в %USERPROFILE%\.local\bin; если Cursor не находит uv в PATH, полный путь решает проблему.
  • timeout: 60000 совпадает с HTTP-таймаутом execute_revit_code (60 с). Тяжёлые проходы дробите или поднимайте оба таймаута согласованно.

После правки mcp.json полностью перезапустите Cursor, не только окно чата. В Settings → MCP сервер Revit должен быть зелёным, когда Revit открыт и мост отвечает.

5. Правило агента

Готовые MCP-инструменты не покрывают BIM-шаблон. Без правила агент начнёт искать несуществующие set_* или чужие коннекторы. Файл .cursor/rules/revit-mcp.mdc в проекте:

---
description: Use pyRevit MCP Python as the primary Revit connection
alwaysApply: true
---

Revit is connected through **mcp-server-for-revit-python** (pyRevit Routes).

- Use `execute_revit_code` for any model change (rename, set parameters, apply templates).
- Ready-made tools (`get_revit_model_info`, `get_current_view_elements`, `list_levels`, ...) are fine for reads.
- Code runs on IronPython 2.7: no f-strings, no type hints.
- `execute_revit_code` does not open a transaction: wrap every edit in `DB.Transaction` and commit it.
- Every write is shown for review in Revit; wait for the user to approve it.
- After a timeout, do not retry a write: re-read the model first.
- Before destructive edits, ask the user to save a copy of the `.rvt`.
- Do not use write tools of other Revit connectors.

alwaysApply: true — правило подключается к каждому чату в этом workspace.

Порядок запуска в рабочий день

  1. Открыть Revit 2022.
  2. Открыть модель или шаблон — не пустой стартовый экран без документа.
  3. Убедиться, что на ленте есть pyRevit и вкладка MCP.
  4. Если сопряжение отозвано — MCP → Bridge → Connect.
  5. Открыть Cursor в папке проекта, где лежат правило и регламенты шаблона.
  6. В чате: «проверь доступ к Revit». Агент должен вызвать get_revit_status и назвать открытый файл.

На workshared-файле агент работает с локальной копией, которая сейчас открыта. sync_with_central есть, но это осознанный шаг, а не фоновое действие.

Каталог инструментов

Коннектор отдаёт Cursor 20 готовых инструментов. Ещё несколько (modify_element, delete_elements, get_selected_elements и др.) в README помечены как запланированные — не рассчитывайте на них.

ИнструментГруппаНазначение
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ВидыЭлементы текущего вида (по умолчанию до 5000)
list_family_categoriesСемействаКатегории семейств
list_familiesСемействаТипы с фильтром contains, по умолчанию до 50
place_familyСемействаПостановка экземпляра в точку
color_splashЦветРаскраска категории по параметру
clear_colorsЦветСнять переопределения
list_category_parametersЦветПараметры категории и примеры значений
list_revit_installationsДокументУстановленные версии Revit и пути
launch_revitДокументЗапуск Revit, опционально с файлом и языком
open_documentДокументОткрыть .rvt/.rfa/.rte, с detach и audit
close_documentДокументЗакрыть, по умолчанию без сохранения
save_documentДокументSave или Save As
sync_with_centralДокументСинхронизация: comment, compact, relinquish_all
execute_revit_codeКодПроизвольный IronPython в контексте документа

На что обратить внимание:

  • get_revit_view недооценён: можно попросить «открой лист 01.0.1 и покажи штамп», не гадая по именам параметров.
  • Для аудита штампов list_families с contains: "sx__Лист" быстрее коллектора. Но где реально стоят экземпляры, он не скажет — для этого нужен execute_revit_code.
  • color_splash — визуальный QA («покажи стены по sx__Марка»), а не замена фильтров вида.
  • open_document с detach: true — правильный способ посмотреть центральную модель, не привязываясь к ней. Не просите агента делать Save As поверх центральной без явной команды.

execute_revit_code

В контексте кода уже доступны doc (активный документ), uidoc, DB (Autodesk.Revit.DB), модуль revit из pyRevit, а print уходит в ответ инструмента.

Транзакцию инструмент сам не открывает. Для записи:

t = DB.Transaction(doc, "Rename sheets")
t.Start()
# ...
t.Commit()

Смена активного вида — вне транзакции: uidoc.ActiveView = target_view.

HTTP-таймаут вызова — 60 секунд. Тяжёлые проходы (все спецификации шаблона, все семейства штампов) дробите: сначала выгрузка в JSON через print, потом правка пачками.

Как формулировать задачи

Связка сильна на массовых, однозначных и проверяемых операциях. Слаба на том, чего нет в API, и на размытом «наведи красоту».

Хороший запрос отвечает на пять вопросов:

  1. Где — файл уже открыт, имя документа или папка диспетчера.
  2. Что — конкретный параметр, категория, префикс.
  3. Критерий — «все спецификации с sx__Группа вида1 = 02_РД».
  4. Исключения — «лист 1 Условные не трогать».
  5. Проверка — «выведи счётчик до и после».
ПлохоХорошо
«Почисти штампы»«Собери все Title Blocks: семейство, типы, на скольких листах стоят экземпляры, только витрина или рабочие альбомы. Потом предложи, что удалить»
«Переименуй листы как надо»«У листов с sx__Группа вида1 = 01_ЭП системный номер 10.x → 01.x. Печатный sx__НомерЛиста не менять»

Скриншоты

Агент видит картинку диалога. Это отличный способ задать желаемый результат: таблица Model Line Weights, переименованный фильтр стадий. Но это не гарантия, что API позволит записать то же самое. Если после разведки агент говорит «в API этого нет» — не давите на кликер по интерфейсу: модальные окна Revit из IronPython почти не автоматизируются.

Сначала разведка, потом запись

Рабочий ритм из реальных сессий:

  1. get_revit_status — тот ли файл.
  2. Коллектор или list_* — сколько объектов, какие имена.
  3. Короткий план в чат: группы, исключения.
  4. Транзакция, подтверждение в Revit.
  5. Повторный коллектор — сверка счётчиков.

Не просите «сразу удаляй» в первом сообщении, если сами не видели инвентаризацию. И наоборот: после явного «удаляй лишние» агент должен удалять, а не согласовывать третий круг.

Примеры, которые хорошо ложатся на связку

На шаблоне выпуска эти задачи вручную занимают часы, из Cursor — минуты. Формулировки можно копировать.

1. Инвентаризация семейств штампа. «Посмотри семейства штампа. Я вижу sx__Лист_….rfa. Что ещё загружено, что стоит на листах, что только в проекте». Агент проходит FilteredElementCollector по Family и FamilySymbol категории Title Blocks и по экземплярам на ViewSheet, затем сводит таблицу: семейство, типы, «на листах / только витрина / нигде». Руками это клик по каждому листу.

2. Массовая нумерация листов. «Все листы в 01_ЭП — номер с 10. на 01.. Печатный номер не трогать». Работают sx__Группа вида1 на ViewSheet и Sheet Number (SHEET_NUMBER); не путать с sx__НомерЛиста. Сразу просите целевой формат 01.x: после 10. → 1. понадобится второй проход, иначе сортировка в диспетчере поедет.

3. Шаблоны видов на все спецификации стадии. «Для всех спецификаций 01_ЭП — шаблон Спец_Manrope, для 02_РД — Спец_Arial». Сначала спросите, что включает шаблон: если в нём включены Fields, он затрёт структуру спецификаций. В нашем случае было включено только Appearance (шрифт сетки). Разведка через API дешевле, чем откат 140 спецификаций.

4. Тематические папки диспетчера. «Спецификации 01_ЭП и 02_РД: разложить sx__Группа вида2 по темам 00_Название (полы, потолки, мебель…). Сводные со словом СВОДНАЯ — в отдельную группу». Выгрузка имён → классификатор по подстрокам → запись параметра. Префикс в имени сильнее случайного слова: Двери_плинтус всё равно проёмы, а не полы. Это лучший класс задач для агента: много однотипных элементов, формулируемое правило, результат проверяется списком.

5. Переименование по всему проекту. «Везде ДП → РД: виды, шаблоны видов, легенды, листы, семейство штампа, сокращение стадии. ДП-РД и ДП/РД сначала в РД, потом голый ДП. Полное ДИЗАЙН-ПРОЕКТ не трогать». Порядок замен задавайте явно, иначе ДП-РД станет РД-РД. Отдельные сущности: View.Name, ViewFamilyType, параметр sx__СтадияПроектаСокращенно, Family.Name. В конце — поиск остатков ДП и отчёт «0 leftover».

6. Где Марка и куда назначить параметр. «Найди спецификации с полем Марка, дай список категорий и добавь эти категории в параметр sx__Марка». Связка «спецификация использует поле → у категории должен быть параметр» — типичная дыра в шаблонах. Коллектор спецификаций, их поля и CategorySet параметра закрывают её за один проход.

7. Документация шаблона. «Глубоко разбери открытый шаблон и напиши инструкцию в .md в стиле принятого регламента по листам». Здесь агент — исследователь: сведения о проекте, параметры, организация диспетчера, альбомы. Держите такие файлы в том же workspace, чтобы следующие чаты опирались на них, а не заново инвентаризировали 200 спецификаций.

8. Визуальная сверка. «Переименуй фильтр стадий Show All → Показать все» плюс скриншот. Имя фильтра меняется через API, а скриншот нужен, чтобы агент не перепутал Phase Filter, Phase и фильтр стадий на виде.

IronPython 2.7: что ломает правки

Код в execute_revit_code исполняется не тем Python, на котором вы пишете скрипты в Cursor.

НельзяВместо этого
f-строки"%s" % x или "{}".format(x)
Аннотации типовКод без аннотаций
Кириллица литералом в коде\uXXXX или сравнение со строкой, прочитанной из Revit
next(x for x in xs if …) — иногда капризничаетОбычный for
Второй t.Start() поверх открытой транзакцииОдна транзакция на логическое изменение

Кириллица — главная боль русскоязычного шаблона. Литерал "02_ДП", который едет в JSON через HTTP, часто не совпадает с именем параметра в документе. Надёжный приём:

  1. Прочитать значения из Revit (p.AsString()).
  2. Сравнивать с ними.
  3. Новые имена собирать через 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: ....

В agent runtime pyRevit 7 движок может быть другим (IronPython 3.4 поддерживает f-строки), поэтому там правило проще: пусть агент сначала вызовет get_context и посмотрит поле scripting.

Чего ждать не стоит

Revit API — не полный интерфейс. Если агент упёрся, чаще всего дело не в промпте.

  • Model Line Weights. Публичного API для таблицы толщин перьев по масштабам нет. Category.SetLineWeight ставит номер пера 1–16, а не толщину в мм; внутренние PenWidthTable и PenInfoForScale — пустые обёртки. Перенос — через Transfer Project Standards вручную, с Overwrite, а не New Only.
  • PostCommand (открыть Line Weights, Transfer…) ставится в очередь и плохо стыкуется с MCP: модальное окно блокирует Revit, а кастомная сетка диалога не отдаёт ячейки автоматизации.
  • Имя уровня при копировании. Уже созданный уровень переименовать можно, а заставить следующий Copy называться «2 этаж» — нет: внутренний счётчик имени API не сбрасывает.
  • UI-only настройки — часть Extra Settings и Transfer Project Standards — остаются ручными. Честный ответ агента здесь ценнее часа эмуляции кликов.

Безопасность и worksharing

  • Перед удалением семейств, purge и массовой заменой имён — Save As или локальная копия. Правило агента должно это спрашивать, человек подтверждает.
  • execute_revit_code — полный доступ к API и не песочница: подтверждение в Revit — это проверка человеком, а не ограничение на файлы, сеть или импорты. Опечатка в фильтре коллектора переименует не те виды, поэтому на больших объёмах просите счётчики и список имён до Commit.
  • Таймаут HTTP не доказывает, что операция остановилась. Не повторяйте запись автоматически — сначала перечитайте модель.
  • Мост принимает только loopback-адреса. Не выставляйте Routes и HTTP-режим MCP в локальную сеть, туннель или интернет. Сопряжение защищает от постороннего браузера, но не от других программ под вашей учётной записью Windows.
  • Всё, что агент читает из модели (имена, значения параметров), уходит провайдеру модели в Cursor. Сверьте это с требованиями проекта к конфиденциальности.
  • На workshared-модели правки идут в открытую локальную копию; sync_with_central — отдельная команда.
  • Не путайте активный документ: если открыты шаблон и чужой .rte, коллекторы идут в активный. Начинайте с get_revit_status или print(doc.Title).

Шпаргалка промптов

ЗадачаПромпт
Проверка моста«Проверь get_revit_status: какой файл открыт, Routes healthy?»
Разведка без записи«Выведи все Title Block: семейство, типы, число экземпляров на листах. Ничего не удаляй»
Массовая запись с границей«У видов и спецификаций с sx__Группа вида1 = 02_ДП замени группу на 02_РД. Остальные группы не трогай. В конце — сколько изменено»
Шаблон вида«Сначала покажи, какие вкладки включены у шаблонов Спец_Arial и Спец_Manrope. Если только Appearance — примени Manrope ко всем спецификациям 01_ЭП, Arial — ко всем 02_РД»
Документ для команды«По открытому шаблону напиши инструкцию: сведения о проекте, диспетчер, альбомы. В стиле принятого регламента по листам»

Если Cursor не видит Revit

  1. Revit запущен, документ открыт — не только стартовый экран.
  2. На ленте есть вкладки pyRevit и MCP.
  3. Сопряжение активно: MCP → Bridge → Connect.
  4. В pyRevit_config.ini: [routes] enabled = true, порт 48884.
  5. Расширение revit-mcp-python не отключено.
  6. Проверка статуса из папки клона отвечает healthy.
  7. Cursor перезапущен после правки mcp.json, сервер Revit в Settings → MCP не красный.
  8. --directory указывает на папку с main.py, а uv.exe по пути из command существует.
  9. В mcp.json нет второго коннектора, который перехватывает имя Revit.

Коротко

  • Держите в одном workspace клон MCP, правило .mdc и регламенты шаблона — тогда агент не открывает Америку в каждом чате.
  • Готовые инструменты — для «что открыто, какие уровни, покажи вид». Всё остальное — execute_revit_code с транзакцией, без f-строк, с \uXXXX для кириллицы.
  • Просите задачи, которые считаются: N листов, M спецификаций, 0 leftover ДП. Не просите закрывать дыры API кликами по диалогам.
  • Сначала инвентаризация и правило замены, потом Commit. На workshared-шаблоне это разница между полезным проходом по диспетчеру и сюрпризом при синхронизации.
  • Если ставите pyRevit 7 — попробуйте встроенный agent runtime: подтверждение правок и откат там встроены в сам pyRevit.

Источники