devtools::install_github("devOpifex/mcpr")19 MCP Server
AI assistants are increasingly useful not just for answering questions but for doing things, calling APIs, reading files, running analyses. The Model Context Protocol (MCP) is the open standard that makes that possible. It defines how an AI assistant discovers and calls external tools during a conversation, in the same way a web browser discovers and calls REST APIs.
AutoDeskR functions are exactly the kind of tools an AI agent would want to call. “Summarise the layers in this DWG.” “Translate this file and give me the bounding box.” “Fetch the last 24 hours of HVAC sensor readings.” Each of those is a handful of AutoDeskR function calls, and with an MCP server in front of them, an AI assistant can make those calls itself, without you writing a single line of R.
This chapter shows how to expose AutoDeskR as an MCP server so that Claude Desktop, VS Code Copilot, or any other MCP-compatible client can query BIM models directly.
19.1 Proposed Tools
The table below maps ten useful MCP tools to their underlying AutoDeskR functions. Each tool is a thin wrapper. It handles authentication, calls the relevant function(s), and returns a structured JSON result.
| MCP Tool | Wraps | Description |
|---|---|---|
get_token |
getToken() |
Authenticate and return a bearer token |
upload_file |
makeBucket() + uploadFile() |
Create a bucket and upload a local file |
translate_file |
translateObj() / translateSvf() + checkFile() |
Translate a file and poll until complete |
get_layer_summary |
translateSvf() + getData() |
Layer-level object count and area for a DWG |
get_object_tree |
getObjectTree() |
Model hierarchy as a JSON tree |
get_metadata |
getMetadata() |
List available metadata GUIDs for a translated model |
download_mesh |
getOutputUrn() + downloadFile() |
Download the translated OBJ/STL to a local path |
make_pdf |
makePdf() + checkPdf() |
Convert a DWG to PDF via Design Automation |
get_sensor_streams |
Tandem REST API | List sensor streams for a Tandem facility |
get_stream_readings |
Tandem REST API | Fetch time-series readings for a stream |
19.2 Setting Up a Local MCP Server
The mcpr package provides the MCP transport layer for R. Install it from GitHub:
A minimal server registers tools and starts listening. Here’s a working example for the get_layer_summary tool:
library(mcpr)
library(AutoDeskR)
# Authenticate once at startup using environment variables
.token <- local({
resp <- getToken(
id = Sys.getenv("client_id"),
secret = Sys.getenv("client_secret"),
scope = "data:read data:write bucket:create"
)
resp$content$access_token
})
# Register the tool
mcp_tool(
name = "get_layer_summary",
description = "Return object count and total area by layer for a translated DWG URN.",
params = list(
urn = mcp_param("string", "The raw objectId URN returned by uploadFile()")
),
handler = function(urn) {
encoded <- jsonlite::base64_enc(urn)
resp <- getData(urn = encoded, token = .token)
objects <- resp$content$data$objects
layer_counts <- table(sapply(objects, `[[`, "name"))
data.frame(layer = names(layer_counts),
n_objects = as.integer(layer_counts))
}
)
# Start the server (stdio transport for Claude Desktop)
mcp_serve()#> MCP server listening on stdio
#> Registered tools: get_layer_summary
Add more tools by repeating the mcp_tool() pattern before calling mcp_serve().
19.3 Connecting to Claude Desktop
Claude Desktop reads its MCP server list from a JSON config file. On macOS, open or create ~/Library/Application Support/Claude/claude_desktop_config.json and add an entry for the AutoDeskR server:
{
"mcpServers": {
"autodeskr": {
"command": "Rscript",
"args": ["/path/to/autodeskr-mcp-server.R"],
"env": {
"client_id": "your_aps_client_id",
"client_secret": "your_aps_client_secret"
}
}
}
}Restart Claude Desktop. The AutoDeskR tools will appear in the tool palette and Claude will call them automatically when relevant.
19.4 Example Agent Conversations
Once connected, you can have conversations like:
You: I’ve uploaded
aerial.dwgto bucketacmecorp-dev. The objectId isurn:adsk.objects:os.object:acmecorp-dev/aerial.dwg. Summarise the layers.
Claude: (calls
get_layer_summary) The drawing has 8 layers. The largest by object count isA-DIMSwith 62 objects, followed byA-TEXTwith 47. The largest by area isA-SITEat 156,823 square units.
You: Compare the layer sets in
floor_plan_v1.dwgandfloor_plan_v2.dwg.
Claude: (calls
get_layer_summarytwice, compares results) Version 2 addsA-FURN(34 objects) andA-FURN-NEW(12 objects).A-TEMP-SITEwas present in v1 but has been removed.
You: Fetch the last 24 hours of temperature readings from the HVAC sensor on level 2.
Claude: (calls
get_stream_readings) The streamstrm:temp-hvac-l2shows a mean of 22.1 °C over the last 24 hours, ranging from 21.4 °C to 23.0 °C. Peak temperature was at 14:30 UTC.
19.5 Security Considerations
A few things to keep in mind before deploying:
- Credentials: Pass
client_idandclient_secretvia environment variables (as shown in the config above), never hardcoded in the script. The server reads them at startup viaSys.getenv(). - Token expiry: APS tokens expire after 3600 seconds. For long-running servers, refresh the token periodically. Add a
Sys.time()check in the handler and re-callgetToken()if more than 50 minutes have elapsed. - Rate limits: APS enforces per-app rate limits. If the agent calls tools rapidly (e.g. in a loop over many files), add
Sys.sleep(0.5)between calls. HTTP 429 responses should trigger a backoff, not a crash. - Scope: Request only the scopes the server actually needs. A read-only analysis server only needs
data:read; it doesn’t needdata:writeorbucket:create.