Skip to main content
Glama
nhantruong96

trimble-connect-mcp

by nhantruong96
README.md
# Trimble Connect MCP

A local (stdio) MCP server that gives Claude access to Trimble Connect:
projects, folder trees, files, versions, members, groups and permissions —
40 tools over the Core API v2.

## Contents

- [Requirements](#requirements)
- [Step 1 — Install](#step-1--install)
- [Step 2 — Register a Trimble application](#step-2--register-a-trimble-application)
- [Step 3 — Configure Claude Desktop](#step-3--configure-claude-desktop)
- [Step 4 — First run](#step-4--first-run)
- [Write mode](#write-mode)
- [Other MCP clients](#other-mcp-clients)
- [Environment variables](#environment-variables)
- [Tools](#tools)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [License](#license)

## Requirements

| Item | Requirement |
|---|---|
| OS | Windows 10/11 (macOS and Linux should work but are untested) |
| Host | Claude Desktop, Codex, or any MCP client that speaks stdio |
| Python | 3.10+ |
| uv | [Install uv](https://docs.astral.sh/uv/getting-started/installation/) |
| Account | A Trimble ID with access to your Trimble Connect projects |

## Step 1 — Install

```powershell
git clone https://github.com/nhantruong96/trimble-connect-mcp.git
cd trimble-connect-mcp
uv sync
```

Check that the server imports:

```powershell
uv run python -c "import server; print('OK')"
```

Run `uv sync` again after every `git pull`.

## Step 2 — Register a Trimble application

1. Go to the [Trimble Developer Console](https://console.trimble.com) and create
   an application.
2. Copy the **Client ID** and **Client Secret**.
3. Under **Callback URLs**, add exactly:

   ```
   http://localhost:8385/callback
   ```

4. If port 8385 is already taken, change it in **both** places: the Callback URL
   in the Developer Console and `TC_REDIRECT_URI` in your config (for example
   `http://localhost:8590/callback`).

The redirect URI must match character for character — `http://localhost` without
a port, `127.0.0.1` instead of `localhost`, or a missing `/callback` will all be
rejected.

## Step 3 — Configure Claude Desktop

Open `%APPDATA%\Claude\claude_desktop_config.json` (or Settings → Extensions)
and add the block below, replacing the paths and the client id/secret:

```json
{
  "mcpServers": {
    "trimble-connect": {
      "command": "C:\\path\\to\\trimble-connect-mcp\\.venv\\Scripts\\python.exe",
      "args": ["C:\\path\\to\\trimble-connect-mcp\\server.py"],
      "env": {
        "TC_CLIENT_ID": "<client id>",
        "TC_CLIENT_SECRET": "<client secret>",
        "TC_APP_NAME": "Trimble_Connect_MCP",
        "TC_REDIRECT_URI": "http://localhost:8385/callback",
        "TC_ENABLE_WRITE": "1"
      }
    }
  }
}
```

A ready-made template is in
[`claude_desktop_config.example.json`](claude_desktop_config.example.json).
Never commit your real config — it holds the client secret.

Quit Claude Desktop completely, then reopen it.

## Step 4 — First run

Ask in plain language:

> "Sign in to Trimble Connect, then list my projects."

- The browser opens the Trimble ID page; once you sign in the tools are ready.
- Tokens refresh automatically — you only sign in once.
- After 90 seconds `tc_login` returns `pending=true` plus an `auth_url`. Finish
  signing in in the browser, then ask Claude to call `tc_auth_status`.
- If you abandon a sign-in, call `tc_login_cancel` before starting a new one.
- To sign out, delete `%USERPROFILE%\.trimble_connect_mcp\tokens.json`.

The region (NA / EU / AP) is detected automatically and cached in
`%USERPROFILE%\.trimble_connect_mcp\`.

## Write mode

The server is **read-only** by default. Two gates protect every write:

1. Set `TC_ENABLE_WRITE=1` in the `env` block of your config and restart the
   host. Verify with `tc_write_status`.
2. Destructive tools (delete, overwrite a version, replace an ACL, remove a
   member) additionally require `confirm=true`.

There is no restore tool — Core API 2.0 has no undelete endpoint. Deleted items
can only be recovered by hand in the Trimble Connect web interface.

## Other MCP clients

1. Take the `.venv\Scripts\python.exe` and `server.py` paths from Step 3.
2. Register a **stdio** server using them as `command` and `args`.
3. Set the same environment variables as in Step 3.
4. Restart the client.

To check that the server starts at all:

```powershell
uv run python server.py
```

## Environment variables

| Variable | Default | Notes |
|---|---|---|
| `TC_CLIENT_ID` | — | required |
| `TC_CLIENT_SECRET` | — | required |
| `TC_APP_NAME` | `Trimble_Connect_MCP` | used in the OAuth scope (`openid <app name>`) |
| `TC_REDIRECT_URI` | `http://localhost:8385/callback` | must match the URL registered in the Developer Console |
| `TC_DOWNLOAD_DIR` | `~/Downloads/TrimbleConnect` | where downloaded files are saved |
| `TC_TOKEN_DIR` | `~/.trimble_connect_mcp` | where tokens and the region cache are stored |
| `TC_ENABLE_WRITE` | *(off)* | set to `1` to enable the write / delete / permission tools |

## Tools

### Read — always available

| Tool | What it does |
|---|---|
| `tc_login` | Sign in with Trimble ID in the browser (OAuth2 + PKCE), callback `http://localhost:8385/callback`. Non-blocking: past `wait_seconds` (default 90s) it returns `pending=true` and keeps listening in the background for up to 10 minutes |
| `tc_login_cancel` | Cancel a pending sign-in and release the callback port |
| `tc_auth_status` | Sign-in status, including `login_in_progress` |
| `tc_write_status` | Whether write mode is on, and how to turn it on |
| `tc_list_regions` | List the server regions (NA / EU / AP) |
| `tc_list_projects` | List projects across every region, filter by name, `refresh=true` to bypass the cache |
| `tc_get_project` | Details of one project |
| `tc_list_project_members` | Project members and their roles |
| `tc_list_project_roles` | The project's roles (ADMIN / USER) |
| `tc_list_folder` | Contents of a folder (defaults to the project root) |
| `tc_folder_tree` | Folder tree as text, bounded by depth and entry count |
| `tc_get_file` | File metadata |
| `tc_list_file_versions` | Version history of a file |
| `tc_download_file` | Download a file (default `~/Downloads/TrimbleConnect`) |
| `tc_search` | Keyword search |
| `tc_get_permissions` | Read the ACL of a folder or file |
| `tc_list_groups` / `tc_list_group_users` | Project groups and their members |
| `tc_api_get` | Raw GET against any Core API endpoint (todos, views, releases, activities…) |

### Write — folders and files (needs `TC_ENABLE_WRITE=1`)

| Tool | What it does | Gate |
|---|---|---|
| `tc_create_folder` | Create one folder | — |
| `tc_create_folder_structure` | Create a whole tree (e.g. a CDE) from paths like `01-WIP/01-ARC`; existing folders are skipped, so it is safe to re-run | — |
| `tc_rename_item` | Rename a folder or file | — |
| `tc_move_item` | Move a folder or file to another folder | — |
| `tc_copy_file` | Copy a file (server-side) | — |
| `tc_copy_folder` | Copy a folder with its contents (the server walks the tree; bounded by `max_items`) | — |
| `tc_upload_file` | Upload a NEW file (fails if the name already exists) | — |
| `tc_upload_new_version` | Upload a NEW VERSION of an existing file | `confirm=true` |
| `tc_delete_item` | Delete a folder or file (`force=true` for a non-empty folder) | `confirm=true` |

### Write — permissions

| Tool | What it does | Gate |
|---|---|---|
| `tc_grant_permissions` | Grant `READ` / `FULL_ACCESS` / `NO_ACCESS` to users or groups — merges safely by reading the current ACL and changing only the entries you name | — |
| `tc_remove_permissions` | Drop users or groups from the ACL (back to inherited access) | `confirm=true` |
| `tc_set_permissions` | Replace the ENTIRE ACL (advanced — wipes existing entries) | `confirm=true` |

Trimble Connect has only three levels: `READ`, `FULL_ACCESS`, `NO_ACCESS` (files
do not support `NO_ACCESS`). The special id `tc-groups:*` means every project
member. The underlying `PATCH .../permissions` overwrites the whole ACL, which
is why `tc_grant_permissions` / `tc_remove_permissions` are preferred over
`tc_set_permissions`.

### Write — members and groups

| Tool | What it does | Gate |
|---|---|---|
| `tc_add_project_user` | Invite a user to the project by email (`role`: USER/ADMIN) | — |
| `tc_update_project_user` | Change a member's role | — |
| `tc_remove_project_user` | Remove a member from the project | `confirm=true` |
| `tc_create_group` / `tc_rename_group` | Create or rename a group | — |
| `tc_add_group_users` | Add members to a group | — |
| `tc_remove_group_users` | Remove members from a group | `confirm=true` |
| `tc_delete_group` | Delete a group (any permission granted to it is lost) | `confirm=true` |
| `tc_api_write` | Raw POST/PATCH/PUT/DELETE for endpoints with no dedicated tool | `confirm=true` |

## Troubleshooting

| Symptom | Fix |
|---|---|
| `redirect_uri mismatch` on the sign-in page | The URL in the Developer Console must match `TC_REDIRECT_URI` character for character (Step 2) |
| `Cannot listen on localhost port 8385` | The port is taken — call `tc_login_cancel`, or change the port in both places (Step 2) |
| Browser shows `connection refused` on the callback page | The sign-in wait expired (10 minutes) — call `tc_login` again |
| `tc_login` returns `pending: true` | Not an error — finish signing in, then call `tc_auth_status` |
| `Writing to Trimble Connect is disabled` | `TC_ENABLE_WRITE=1` is not set, or the host was not restarted |
| `Refused: this would…` | A destructive tool needs `confirm=true` — check the target, then call again |
| HTTP 403 | Your Trimble account has no access to that project |
| HTTP 409 / 412 on create or upload | An item with that name exists — to overwrite, use `tc_upload_new_version` |
| No projects listed | Run `tc_list_projects` with `refresh=true`; check `tc_auth_status` shows the right account |
| `ImportError: cannot import name 'MCPServer'` | You are on `mcp` 1.x — run `uv sync` to get the 2.x version pinned in `uv.lock` |
| An endpoint has no dedicated tool (ToDos, Views, Releases, Activities…) | Use `tc_api_get`, e.g. `todos?projectId=…` or `projects/{id}/activities` |

## Contributing

Development setup, repository layout, and how to add a tool are in
[CONTRIBUTING.md](CONTRIBUTING.md).

The upstream API is `https://app.connect.trimble.com/tc/api/2.0` (master, North
America); other regions are discovered through the `/regions` endpoint.

## License

[MIT](LICENSE)

TDQS

A4.1/5.0

Scored across 40 tools

Disambiguation5/5

Each tool targets a distinct resource-action pair (e.g., list_projects vs get_project, upload_file vs upload_new_version). Even closely related tools like tc_list_folder and tc_folder_tree are explicitly differentiated by output format (raw items vs text tree), and permission tools have clear semantics (get, merge, replace, remove). No two tools appear to do the same thing.

Naming Consistency4/5

All tools share the `tc_` prefix and mostly follow a verb_noun pattern (get_project, create_folder, list_groups). A few exceptions like tc_folder_tree, tc_auth_status, and tc_write_status use noun-first naming, but the pattern remains predictable and readable.

Tool Count2/5

With 40 tools, the surface is very large. While the domain is broad, many tools are granular (e.g., 7 group tools, 6 permission tools) and there are two raw API escape hatches (tc_api_get/write) that add complexity. This exceeds the typical well-scoped range and could overwhelm agents.

Completeness5/5

The tool set provides comprehensive coverage of the Trimble Connect CDE: auth, project management, folder/file operations (create, read, update, delete, copy, move, versioning), permissions, groups, members, and search. Raw API tools fill any remaining gaps, so there are no obvious dead ends.

Maintenance

ActivitySlowing
ResponsivenessNo issues