Skip to main content
Glama
MCP server for Revit - Python

MCP server for Revit - Python

by licorp

MCP server for Revit - Python

A pyRevit-oriented implementation of the Model Context Protocol (MCP) for Autodesk Revit

Related MCP server: Revit MCP Server

Local pairing and Autodesk Marketplace publication

This project is being prepared for Autodesk Marketplace review; it is not yet certified. The review candidate retains all 20 tools, including Python execution. See publication requirements and outstanding gates, privacy information, and security boundaries.

After installing the pyRevit extension, choose MCP > Bridge > Connect in Revit to consent and create an encrypted pairing secret for your Windows user. Choose Disconnect to revoke it. Requests that change models and Python execution show their payload for review in Revit before proceeding. Pairing also permits local Revit discovery and launch. Pairing is shared across Revit instances for the same Windows user; select the correct Routes port before connecting.

The MCP-to-Revit bridge accepts only loopback hosts. Remote VM/LAN HTTP bridges are rejected. Optional HTTP MCP transports require a paired bearer header; stdio is the recommended publication transport and needs no token in client configuration. Do not expose either listener to a network, tunnel or the internet.

How?

  • This minimal implementation leverages the Routes module inside pyRevit to create a bridge between Revit and Large Language Models (LLMs).

  • It provides a straightforward template to get started quickly, letting you prototype and iterate tools to give LLMs access to your Revit models.

  • These tools are designed to be expanded for your specific use cases. You're very welcome to fork the repo and make your own contributions.

  • Note: The pyRevit Routes API is currently in draft form and subject to change. This extension authenticates its own routes using Windows-user pairing. Other pyRevit routes/extensions remain outside this protection; review pyRevit server binding and the security document.

Batteries Included

This repo is aimed at:

  • Beginners to the Revit API

  • Python specialists who aren't versed in C#

  • Anyone wanting to prototype and iterate quickly with LLMs and Revit

It contains:

  • A complete Routes implementation for pyRevit

  • A minimal MCP server script to connect to any MCP-compatible client

  • Several test commands to get you started right away

Key Architecture Components

The system runs as two separate servers working together in a chain:

Claude / LLM Client
       |
       |  MCP Protocol (stdio or HTTP)
       v
  main.py  (MCP Server)
       |
       |  HTTP requests (localhost:48884)
       v
  pyRevit Routes  (REST API running inside Revit)
       |
       |  Revit API calls
       v
  Revit Application

main.py is the MCP server. It speaks the MCP protocol so that Claude (or any MCP-compatible client) can call tools. When a tool is called, main.py translates it into an HTTP request and forwards it to Revit.

pyRevit Routes is a lightweight REST API that runs inside the Revit process. It receives those HTTP requests, executes Revit API code (since it has direct access to the running instance), and returns JSON responses.

They never conflict because they serve different roles, speak different protocols, and listen on different ports.

Note: The Launch & Document tools (launch_revit, list_revit_installations) are the exception — they run entirely on the MCP side, using subprocess to start Revit and then polling the pyRevit Routes health endpoint until the bridge is ready.

  1. MCP Server (main.py):

  • Built with FastMCP

  • Handles HTTP communication with Revit Routes API

  • Registers tools from modular tool system

  • Provides helper functions for GET/POST/Image requests

  1. pyRevit Extension (revit-mcp-python.extension/):

  • Contains the Routes API that runs inside Revit

  • Modular route registration in startup.py

  • Individual route modules in revit_mcp/ directory

  1. Tool Registration System (tools/):

  • Modular tool organization by functionality

  • Central registration through tools/__init__.py

  • Each module registers its own tools with the MCP server


Supported Tools

Current Implementation Status

Tool Name

Status

Category

Description

get_revit_status

✅ Implemented

Status & Connectivity

Check if the Revit-MCP API is active and responding

get_revit_model_info

✅ Implemented

Model Information

Get comprehensive information about the current Revit model

list_levels

✅ Implemented

Model Information

Get all levels with elevation information

get_revit_view

✅ Implemented

View & Image

Export a specific Revit view as an image

list_revit_views

✅ Implemented

View & Image

Get a list of all exportable views organized by type

place_family

✅ Implemented

Family & Placement

Place a family instance at specified location with custom properties

list_families

✅ Implemented

Family & Placement

Get a flat list of available family types (with filtering)

list_family_categories

✅ Implemented

Family & Placement

Get a list of all family categories in the model

get_current_view_info

✅ Implemented

View Information

Get detailed information about the currently active view

get_current_view_elements

✅ Implemented

View Information

Get all elements visible in the current view

create_point_based_element

🔄 Pending

Element Creation

Create point-based elements (doors, windows, furniture)

color_splash

✅ Implemented

Visualization

Color elements based on parameter values

clear_colors

✅ Implemented

Visualization

Remove view color overrides

list_category_parameters

✅ Implemented

Visualization

List category parameters and sample values

execute_revit_code

✅ Implemented

Code Execution

Execute IronPython code directly in Revit context

list_revit_installations

✅ Implemented

Launch & Document

Discover all Revit versions installed on the system

launch_revit

✅ Implemented

Launch & Document

Launch Revit, optionally with a file, and poll for readiness

open_document

✅ Implemented

Launch & Document

Open a document in running Revit (supports detach and audit)

close_document

✅ Implemented

Launch & Document

Close the active document

save_document

✅ Implemented

Launch & Document

Save or Save As the active document

sync_with_central

✅ Implemented

Launch & Document

Synchronize a workshared document with central

get_selected_elements

🔄 Pending

Selection Management

Get information about currently selected elements

create_line_based_element

🔄 Pending

Element Creation

Create line-based elements (walls, beams, pipes)

create_surface_based_element

🔄 Pending

Element Creation

Create surface-based elements (floors, ceilings)

delete_elements

🔄 Pending

Element Management

Delete specified elements from the model

modify_element

🔄 Pending

Element Management

Modify element properties (instance parameters)

reset_model

🔄 Pending

Element Management

Reset model by deleting process model elements

tag_walls

🔄 Pending

Annotation

Tag all walls in the current view

search_modules

🔄 Pending

Integration

Search for available modules/addins

use_module

🔄 Pending

Integration

Execute functionality from external modules

Claude listing model elements in the Desktop interface

Claude getting a view in the Desktop interface

Getting Started

Installing uv:

Refer to ./README_UV.md

Installing the Extension on Revit

Activate pyRevit Routes

  1. In Revit, navigate to the pyRevit tab

  2. Open Settings

  3. Go to Routes > activate Routes Server pyRevit will start listening on port http://localhost:48884/

Install from pyRevit:

  1. In Revit, navigate to the pyRevit tab

  2. Open Extensions

  3. Select the MCP Server for Revit Python Extension > Install extension

  4. Select location, default is %APPDATA%\Roaming\pyRevit\Extensions

  5. Enable and wait for pyRevit to reload. Restart Revit if necessary.

Manual Installation on a custom directory:

  1. Clone the repo in a custom location:

    git clone https://github.com/mcp-servers-for-revit/mcp-server-for-revit-python
  2. Add .extension to the root folder name

  3. In Revit, navigate to the pyRevit tab

  4. Open Settings

  5. Under "Custom Extensions", add the path to the .extension folder

  6. Save settings and reload pyRevit (you might need to restart Revit entirely)

Testing Your Connection

Once installed, test that the Routes API is working:

  1. Choose MCP > Bridge > Connect in Revit, then run this authenticated check from the exact candidate directory (a browser request has no pairing header and is denied):

    uv run --frozen python -c "import anyio; from main import revit_get; print(anyio.run(revit_get, '/status/'))"
  2. If successful, you should see a response like:

    {"status": "active",
     "health": "healthy",
     "revit_available": true,
     "document_title": "your_revit_filename",
     "api_name": "revit_mcp"}

The Routes Service will now load automatically whenever you start Revit. To disable it, simply remove the extension path from the pyRevit settings.

Using the MCP Client

Testing with the MCP Inspector

The MCP SDK includes a handy inspector tool for debugging:

mcp dev main.py

Then access http://127.0.0.1:6274 in your browser to test your MCP server interactively.

Transport Modes

The MCP server supports multiple transport modes for different use cases:

Flag

Transport

Endpoints

Use Case

(none)

stdio

stdin/stdout

Claude Desktop / Claude Code default

--sse

SSE only

/sse, /messages/

Legacy clients

--streamable-http

HTTP only

/mcp

Modern HTTP clients

--combined

Both

All above

Maximum compatibility

Running with combined transport (recommended for HTTP):

uv run --frozen main.py --combined

After pairing, this starts the authenticated server on http://127.0.0.1:8000 with both SSE and streamable-HTTP endpoints available.

The following unpaired requests return HTTP 401. HTTP clients must include the header returned by revit_mcp.pairing.authorization_headers(); prefer stdio to avoid copying a secret into client configuration.

Testing the endpoints:

# Test streamable-http
curl -X POST http://localhost:8000/mcp

# Test SSE
curl http://localhost:8000/sse

Connecting to Claude Desktop

The simplest way to install your MCP server in Claude Desktop:

mcp install main.py

Or for manual installation:

  1. Open Claude Desktop → Settings → Developer → Edit Config

  2. Add this to the mcpServers section:

{
  "mcpServers": {
    "Revit Connector": {
      "command": "uv",
      "args": [
        "run",
        "--frozen",
        "mcp",
        "run",
        "/absolute/path/to/main.py"
      ]
    }
  }
}

For HTTP transport mode, the following URL-only example must also be accompanied by the paired Authorization header in a client that supports it:

{
  "mcpServers": {
    "Revit Connector": {
      "url": "http://localhost:8000/mcp"
    }
  }
}

Connecting to Claude Code

claude mcp add -s user "Revit-Connector" -- uv run --frozen mcp run /absolute/path/to/main.py

Creating Your Own Tools

The modular architecture of this project makes adding functionalities relatively simple. The provided LLM.txt file also gives your language model the necessary context to get started right away.

The process involves three main parts:

Part 1: Create the Route Module in Revit

Create a new Python file within the revit-mcp-python.extension/revit_mcp/ directory (e.g., revit_mcp/your_module.py). This module will contain all the related functions you want to expose.

# In revit-mcp-python.extension/revit_mcp/your_module.py

# -*- coding: UTF-8 -*-
"""
Your Module for Revit MCP
Handles your specific functionality.
"""
from pyrevit import routes, revit, DB
import json
import logging

# Standard logger setup
logger = logging.getLogger(__name__)

def register_your_routes(api):
    """Register all your routes with the API."""

    # ---- Example 1: A GET request for reading data ----
    @api.route('/your_endpoint/', methods=["GET"])
    def get_project_title(doc):
        """Gets the project title from the Revit model."""
        try:
            value = doc.Title
            return routes.make_response(data={"status": "success", "data": value})
        except Exception as e:
            logger.error("Get project title failed: {}".format(str(e)))
            return routes.make_response(data={"error": str(e)}, status=500)

    # ---- Example 2: A POST request for modifying the model ----
    @api.route('/modify_model/', methods=["POST"])
    def modify_model(doc, request):
        """Handles POST requests for modifying the Revit model."""
        try:
            data = json.loads(request.data) if isinstance(request.data, str) else request.data

            # Use a transaction for all model modifications
            t = DB.Transaction(doc, "Modify Model via MCP")
            t.Start()

            try:
                element_id = data.get("element_id")
                new_value = data.get("new_value")
                element = doc.GetElement(DB.ElementId(int(element_id)))
                param = element.LookupParameter("Comments")
                param.Set(new_value)

                t.Commit()
                return routes.make_response(data={"status": "success", "result": "Element modified."})

            except Exception as tx_error:
                if t.HasStarted() and not t.HasEnded():
                    t.RollBack()
                raise tx_error

        except Exception as e:
            logger.error("Modify model failed: {}".format(str(e)))
            return routes.make_response(data={"error": str(e)}, status=500)

    logger.info("Your custom routes were registered successfully.")

Part 2: Create the MCP Tool Module

Create the corresponding tools for the MCP server in the tools/ directory (e.g., tools/your_tools.py). This module will use the revit_get and revit_post helpers from main.py.

# In tools/your_tools.py
# -*- coding: utf-8 -*-
"""Your tools for the MCP server."""

from mcp.server.fastmcp import Context
from .utils import format_response

def register_your_tools(mcp, revit_get, revit_post, revit_image=None):
    """Register your tools with the MCP server."""

    # ---- Tool for the GET request ----
    @mcp.tool()
    async def get_revit_project_title(ctx: Context) -> str:
        """
        Retrieves the title of the currently open Revit project.
        """
        response = await revit_get("/your_endpoint/", ctx)
        return format_response(response)

    # ---- Tool for the POST request ----
    @mcp.tool()
    async def modify_revit_element_comment(
        element_id: int,
        new_value: str,
        ctx: Context = None
    ) -> str:
        """
        Modifies the 'Comments' parameter of a specific element.

        Args:
            element_id: The ID of the element to modify.
            new_value: The new comment to apply to the element.
        """
        payload = {"element_id": element_id, "new_value": new_value}
        response = await revit_post("/modify_model/", payload, ctx)
        return format_response(response)

Part 3: Register Your New Modules

1. Register the Route Module

Open revit-mcp-python.extension/startup.py and add your new route registration function.

# In revit-mcp-python.extension/startup.py

# ... (other imports)
# Import the registration function from your new module
from revit_mcp.your_module import register_your_routes

def register_routes():
    """Register all MCP route modules"""
    api = routes.API('revit_mcp')
    try:
        # ... (existing route registrations)

        # Register your new routes (this registers all functions inside)
        register_your_routes(api)

        logger.info("All MCP routes registered successfully")
    except Exception as e:
        logger.error("Failed to register MCP routes: {}".format(str(e)))
        raise

2. Register the Tool Module

Open tools/__init__.py and add your new tool registration function.

# In tools/__init__.py

# ... (other tool imports)
# Import the registration function from your new tool module
from .your_tools import register_your_tools

def register_tools(mcp_server, revit_get_func, revit_post_func, revit_image_func):
    """Register all tools with the MCP server"""

    # ... (existing tool registrations)
    # Register your new tools (this registers all tools inside)
    register_your_tools(mcp_server, revit_get_func, revit_post_func, revit_image_func)

    return mcp_server

Roadmap

This is a work in progress and more of a demonstration than a fully-featured product. Future improvements could include:

  • Creating a Client inside Revit

  • Implementing compatibilities with other language Models

  • Authentication and security enhancements

  • More advanced Revit tools and capabilities

  • Better error handling and debugging features

  • Benchmarking with local models

  • Documentation and examples for common use cases

  • ...

Contributing

Contributions are welcome! Feel free to submit pull requests or open issues for any bugs or feature requests. Feel free to reach out to me if you have any questions, ideas

Available Tools

33 tools
align_viewports_across_sheetsC
Destructive

Aligns viewports on target sheets to a reference sheet, ignoring annotation extents.

Inputs: main_sheet_number (required), align_legend, align_titleblock, apply_crop_scope_box, +1 more. Returns: result

auto_calibrate_gridsC
Destructive

Matches PDF drawing coordinates to Revit grids and returns calibration points, scale and error.

Inputs: page_number (required), method, pdf_path, level_name, +1 more. Returns: result

batch_create_footings_and_wallsC
Destructive

Creates footings, walls and strip footings from parsed foundation data using project types.

Inputs: level_name (required), walls, dry_run, source_tag, +8 more. Returns: result

batch_create_structural_framing_and_columnsC
Destructive

Creates structural columns then beams in one transaction after preflight checks.

Inputs: beams (required), columns (required), level_name (required), force, +8 more. Returns: result

batch_create_structural_slabsC
Destructive

Creates structural slabs and cuts openings in one transaction.

Inputs: slabs (required), level_name (required). Returns: result

batch_create_structural_walls_and_foundationsC
Destructive

Creates shear walls, pile caps and pad/strip footings in one transaction.

Inputs: level_name (required), pile_caps, shear_walls, pad_footings, +2 more. Returns: result

check_duplicatesC
Destructive

Scans columns, beams, walls, footings and slabs for duplicated or overlapping elements.

Inputs: no named parameters. Returns: result

clear_colorsB
Destructive

Removes view color overrides from elements in a category.

Inputs: category_name (required). Returns: result

close_documentA
Destructive

Closes the active Revit document, optionally saving changes.

Inputs: save. Returns: result

color_splashC
Destructive

Applies view color overrides to elements grouped by a parameter value.

Inputs: category_name (required), parameter_name (required), use_gradient, custom_colors. Returns: result

execute_revit_codeA
Destructive

Executes supplied IronPython code in Revit with the Windows user's permissions after review in Revit; code can access model data, files and network services.

Inputs: code (required), description. Returns: result

finalize_and_join_structureB
Destructive

Joins geometry of columns, walls, beams and slabs on a level in structural priority order.

Inputs: level_name (required). Returns: result

generate_visual_qa_overlayC
Destructive

Overlays modelled elements on the source PDF page and returns the image for visual QA.

Inputs: level_name (required), page_number (required), pdf_path, grid_step_mm, +5 more.

get_current_view_elementsB
Read-only

Lists elements visible in the active view, with optional level and location information.

Inputs: limit, include_levels, include_location. Returns: result

get_current_view_infoA
Read-only

Reads the active view's properties and settings.

Inputs: no named parameters. Returns: result

get_revit_model_infoA
Read-only

Reads project metadata, element counts, rooms, views, sheets, warnings and linked-model information.

Inputs: no named parameters. Returns: result

get_revit_statusA
Read-only

Reads bridge health and active document availability.

Inputs: no named parameters. Returns: result

get_revit_viewB
Read-only

Exports a named model view as a PNG image.

Inputs: view_name (required).

launch_revitB
Destructive

Starts an installed Revit version, optionally opens a model file, and checks bridge readiness.

Inputs: timeout, version, language, file_path. Returns: result

list_category_parametersB
Read-only

Lists element parameters and sample values for a category.

Inputs: category_name (required). Returns: result

list_familiesB
Read-only

Lists loaded family types with optional name filtering.

Inputs: limit, contains. Returns: result

list_family_categoriesA
Read-only

Lists categories of loaded families.

Inputs: no named parameters. Returns: result

list_levelsA
Read-only

Lists model levels and their elevations.

Inputs: no named parameters. Returns: result

list_revit_installationsA
Read-only

Lists installed Revit versions and their executable locations.

Inputs: no named parameters. Returns: result

list_revit_viewsA
Read-only

Lists exportable model views grouped by view type.

Inputs: no named parameters. Returns: result

modify_or_delete_elementsB
Destructive

Deletes or moves listed elements to fix issues found during visual QA.

Inputs: delete_ids, move_vectors_mm. Returns: result

open_documentB
Destructive

Opens a specified Revit document, optionally auditing or detaching it from central.

Inputs: file_path (required), audit, detach. Returns: result

parse_pdf_foundation_planC
Destructive

Extracts shear walls, pile caps, piles and pad/strip footings from a vector PDF plan in Revit coordinates (mm).

Inputs: page_number (required), pdf_path, level_name, pdf_grid_pt1, +6 more. Returns: result

parse_pdf_structural_planC
Destructive

Extracts columns, beams, slabs and openings from a vector PDF plan in Revit coordinates (mm).

Inputs: page_number (required), pdf_path, level_name, pdf_grid_pt1, +8 more. Returns: result

place_familyC
Destructive

Places a loaded family instance at specified coordinates and sets requested properties.

Inputs: family_name (required), x, y, z, +4 more. Returns: result

save_documentB
Destructive

Saves the active document in place or to a specified new file.

Inputs: file_path. Returns: result

sync_with_centralC
Destructive

Synchronizes the active workshared model with central using requested relinquish options.

Inputs: comment, compact, relinquish_all. Returns: result

undo_lastA
Destructive

Undoes the last committed action in the active Revit document.

Inputs: no named parameters. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.9/5.0

    Scored across 33 tools

    Disambiguation3/5

    Most tools target distinct Revit operations, but several boundaries are blurry: get_revit_status vs get_revit_model_info, list_revit_views vs get_revit_view, and especially multiple batch creation tools for walls, footings, and foundations. Descriptions help, but an agent could still misselect among the structural batch tools or between generic and specialized operations.

    Naming Consistency4/5

    Most tool names use snake_case with an action-oriented verb and clear object, such as open_document, save_document, list_levels, and batch_create_structural_slabs. There are minor deviations and long compound names like modify_or_delete_elements and finalize_and_join_structure, but the overall convention is readable and predictable.

    Tool Count2/5

    At 33 tools, the surface is heavy for a single MCP server and exceeds the typical well-scoped range. Several highly specialized batch creation and QA tools could likely be consolidated or parameterized, making the set harder for an agent to navigate.

    Completeness4/5

    The server covers a broad Revit structural workflow: launch, document lifecycle, model inspection, views, families, PDF parsing, batch creation, duplicate checking, visual QA, modification, and geometry joining. Minor gaps remain around broader editing operations such as parameter updates or sheet/view creation, but execute_revit_code provides an escape hatch.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      F
      maintenance
      Enables AI to interact with Revit via MCP, allowing data retrieval and element creation, modification, and deletion.
      13
      65 npm
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI clients to interact with Autodesk Revit for building design, editing, analysis, clash detection, MEP, interop, documentation, and model persistence via 48 tools.
      MIT