Security whitepaper¶
This paper describes how Model MCP is built, what data it touches, which controls exist, and which risks remain. It is written for security reviewers. Statements describe the code of the release you install; the questionnaire answers give short answers to common review questions.
Model MCP is an open-source project (MIT). It is not a hosted service. The maintainer operates no server that receives customer data.
Architecture¶
Two components work together.
| Component | Where it runs | Role |
|---|---|---|
| Add-in | Inside Revit on Windows, as the Revit user | Receives requests, runs them on the Revit API thread, returns results. Opens no transaction for reads. Wraps every change in one named undo entry. |
| Server | Python process started by the MCP client, usually on the same machine | Speaks MCP to the client over stdio. Translates tool calls into add-in requests. Applies read-only mode and path redaction to outgoing responses. |
The server never calls an AI service. The MCP client the user chose receives tool results and may forward them to its own model provider. That step is outside this project.
Trust boundaries and data flow¶
flowchart LR
subgraph Client machine
LLM["AI model provider\n(chosen by the user)"]
C["MCP client"]
S["Model MCP server\n(Python, stdio)"]
end
subgraph Revit workstation
A["Model MCP add-in\n(in Revit, as the Revit user)"]
M[("Open Revit models")]
F[("Channel folder\nand logs")]
end
GH["github.com / pypi.org\n(update and package hosts)"]
C <-->|"MCP over stdio"| S
C <-.->|"outside this project"| LLM
S <-->|"named pipe, file channel,\nloopback HTTP, SSH or HTTP(S)"| A
A <--> M
A --> F
A -.->|"optional update check\n(no model data)"| GH
S -.->|"optional version check\n(no model data)"| GH
Trust boundaries:
- MCP client to server: the client is trusted by the user. Whatever the client is told, it can ask for.
- Server to add-in: protected by the transport, see below.
- Add-in to Revit: the add-in runs with the Revit user's rights. It can do whatever that user can do in Revit.
- Workstation to the internet: only the optional update and package requests in Outbound network.
Model data classes returned to the client depend on the tool: model and document names, file paths, element parameters, geometry summaries, warnings and exported view images. Exports can also write PDF, DWG, IFC, NWC and CSV files to disk.
Transports and authentication¶
| Transport | Binding | Authentication | Notes |
|---|---|---|---|
| Named pipe | \\.\pipe\RevitModelMcp.<pid> |
Windows ACL: only the user who runs Revit | Remote pipe clients are dropped. Requests are limited to 1 MiB. No token is needed because the same user already owns the model. |
| File channel | Per-user folder under %LOCALAPPDATA%\RevitModelMcp |
Folder ACL for the current user; the add-in refuses a folder that others can write | Used by the local host and by SSH. |
| HTTP | Off by default. 127.0.0.1:53110 when on |
32-byte random bearer token in settings.json with a user-only ACL. The client verifies a nonce proof from the add-in before it sends the token. |
No TLS. Redirects are refused. Requests are limited to 1 MiB. Put remote access behind a tunnel or a TLS proxy. /health needs no token and exposes the active document name and process information. |
| SSH | No extra port | Local OpenSSH configuration and agent | The server stores no credentials. A forced command can restrict a key, see security. |
Not provided: single sign-on, per-client identities, token rotation, rate limiting of failed HTTP logins, TLS termination. All HTTP callers share one token.
Controls¶
Read-only mode¶
Read-only mode refuses every action tool and keeps read tools. It can come from the server variable REVIT_MCP_READ_ONLY, from the workstation file %LOCALAPPDATA%\RevitModelMcp\read-only, and, with the machine policy, from the ReadOnly value that a user cannot change. The user file and the server variable can be removed by the user who owns them, so they are a safety switch and not an enforcement control. Use the machine policy for enforcement.
Machine policy¶
An administrator can set read-only mode, allow and deny lists for tools, whether C# execution is available, the update mode, trusted network roots, log location and retention, path redaction and the HTTP listener. Registry values win over the policy file, and policy wins over user settings. A blocked call returns a message that starts with Blocked by organization policy:. See the policy reference.
Confirmations, dry runs and undo¶
- Every change is one named Revit undo entry, listed in the activity pane.
revit_undo_lastreverts the last MCP action while it is still the latest change in Revit. - Save, synchronize, close with possible loss, link removal, overwriting exports, C# execution, in-place saves in multi-model runs and deletion of more than 500 elements need a single-use confirmation token. It expires after five minutes and is bound to the call it describes.
- Tools that change data accept
dry_runwhere it makes sense. - A central model opened through MCP is detached by default. Saving an open central model is refused.
- Confirmation tokens guard against mistakes and against instructions injected through model data or tool output. They do not stop an MCP client that confirms on its own, because the client receives the token. Use read-only mode or policy for unattended runs.
Code execution¶
revit_execute_code compiles and runs C# with the Revit user's rights. It is not sandboxed and can read and write files and call network APIs. Controls: refused in read-only mode, token bound to the code hash, transaction mode and document, transaction="none" refused, source saved for audit. The machine policy can turn the tool off. Treat enabling it as granting the Revit user's rights to the MCP client.
Network paths¶
UNC shares are denied by default for export, save, open, shared parameter files and NWC settings. Approved roots are allowed through trustedNetworkRoots. RSN:// paths use Revit Server and are not restricted by that list.
Outbound network¶
Every network call in the shipped code is in this table. The project has no telemetry, analytics, crash reporting or AI provider call. The same list is declared in the tool manifest.
| Component | Destination | When | Data sent | How to turn off |
|---|---|---|---|---|
| Add-in update check | api.github.com (/repos/sharafutdinovdi/revit-model-mcp/releases/latest) |
At most every 24 hours after Revit starts | A plain HTTPS request with the user agent RevitModelMcp updater |
UPDATECHECK=0, updateCheck:false, REVIT_MCP_NO_UPDATE_CHECK=1, managed bundle, UpdateMode=off |
| Add-in update download (per-user installs only) | github.com and release-assets.githubusercontent.com |
When a newer stable release exists | A plain HTTPS request for the MSI and SHA256SUMS.txt |
Same as above |
| Server update check | pypi.org |
At most every 24 hours at server start | A plain HTTPS request | REVIT_MCP_NO_UPDATE_CHECK=1 |
| Server package download | pypi.org, files.pythonhosted.org |
When uv installs or refreshes the package, and at first launcher start | A plain HTTPS request | Pin the version and install from a wheelhouse |
| Install script | api.github.com, github.com |
When install.ps1 is run |
A plain HTTPS request | Do not run it |
| User-configured | The HTTP(S) host in REVIT_MCP_HOST, an SSH host, the Revit Server REST base |
Per use | MCP requests and results | Do not configure |
| Local only | Loopback /health self-probe |
When HTTP is on | None leaves the machine | httpEnabled=false |
GitHub and PyPI see the network address of a request as for any web request. The add-in's Revit Server client sends the Windows user name and the machine name in request headers when a multi-model run uses Revit Server REST.
[INFERENCE] GitHub can redirect release assets to other githubusercontent.com hosts; allow the host family if you permit per-user updates.
Storage and retention¶
| Data | Location | Retention |
|---|---|---|
| Settings and HTTP token | %LOCALAPPDATA%\RevitModelMcp\settings.json |
Until removed. Created at first start, also when HTTP is off. |
| Requests, responses, exported PNG files | Channel folder, %LOCALAPPDATA%\RevitModelMcp |
Removed after retrieval. Read results expire after 10 minutes and action results after 24 hours. Files left by interrupted work have no age limit. |
| Activity log | Activity log file in the same folder | JSON lines, 5 MiB with one rotated copy |
| Add-in log | Documents\RevitModelMcp\Logs, fallback %TEMP%\RevitModelMcp\Logs |
Rotates at 10 MiB, newest 14 files kept. This is a count, not a number of days. |
| C# audit files | %LOCALAPPDATA%\RevitModelMcp\code |
Newest 500 files |
| Files you ask for | The path you or the client gives | Not managed by the project |
Data is stored in plain files. Use disk encryption such as BitLocker for protection at rest. The project adds no encryption of its own.
With the LogDir, LogRetentionDays and RedactPaths policy values an administrator can move logs, bound their age and redact paths.
Logging and redaction¶
- The activity pane and activity log record each request and action with the command and client name. They do not record all arguments.
- The add-in log records jobs received, errors and lifecycle events. The HTTP token is never logged.
- Revit's undo list carries one entry named
MCP (<client>): <summary>for every change. - Path redaction (
REVIT_MCP_REDACT_PATHS=1) shortens paths in Python responses. For add-in logs and audit files, the variable must be set in the Revit process environment, or by theRedactPathspolicy. Model names and parameter values stay visible. - There is no Windows Event Log or SIEM sink and no tamper protection for the files. Forward the log folders with your own agent if you need that.
Supply chain¶
| Item | Status |
|---|---|
| Source | Public repository, release-please changelog, pull request checks, CODEOWNERS |
| CI security | CodeQL, OpenSSF Scorecard, Dependabot, GitHub Actions pinned by commit SHA, hash-pinned tooling requirements |
| Build provenance | GitHub build provenance attestations on release assets built after provenance was enabled. Verify with gh attestation verify, see verify downloads. |
| Checksums | SHA256SUMS.txt on every release |
| Code signing | Not in place. Release MSI, DLL and EXE files are not Authenticode-signed. Signing through SignPath is prepared and starts after the application is approved; see code signing. The Claude Desktop bundle has no MCPB signature. |
| SBOM | Every release attaches two CycloneDX files, revit-model-mcp-addin-<version>.cdx.json (NuGet dependencies) and revit-model-mcp-python-<version>.cdx.json (Python dependencies). Lock files exist too (NuGet lock files, server/uv.lock, hash-pinned requirements for the container image). |
| Dependency scanning gates | Dependabot only. No vulnerability scan blocks a release today. |
| Third-party licenses | Third-party notices list direct dependencies. Transitive Python dependencies are not listed. |
| Autodesk code | No Autodesk binaries are shipped; Revit API assemblies are referenced only. |
Because the binaries are unsigned, application allow-listing that needs a publisher rule (AppLocker, WDAC) has to use a path or hash rule until signing starts. The per-user updater runs from a user-writable folder, which is one reason to use the per-machine MSI.
Vulnerability handling¶
Report vulnerabilities through the private advisory form or the email address in the security policy. 0.x releases are previews: report against the latest release or main. The policy page does not promise response times or a disclosure schedule.
Residual risks¶
| Risk | Why it remains | Mitigation |
|---|---|---|
| An MCP client that confirms its own tokens | The client receives every token | Read-only mode or policy for unattended use |
revit_execute_code |
Unsandboxed C# with user rights | Turn it off by policy; review the preview |
| Prompt injection through model data | Model text reaches the AI client | Tokens, read-only mode, tool deny list |
| Plain HTTP | No TLS in the listener | Keep HTTP off, loopback only, or use a tunnel or TLS proxy |
| Shared HTTP token | One token for all callers | Per-user token, loopback bind |
| Unsigned binaries | Signing not yet in place | Verify checksums and attestation; sign with an organization certificate |
| Local files are plain text | No encryption by the project | Disk encryption, policy for log location |
| Server dependencies float at first install | uvx resolves from PyPI |
Pin the version; install from a wheelhouse |