onshape-jamcp 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. onshape_jamcp-1.0.0/.gitignore +29 -0
  2. onshape_jamcp-1.0.0/CHANGELOG.md +46 -0
  3. onshape_jamcp-1.0.0/Dockerfile +26 -0
  4. onshape_jamcp-1.0.0/LICENSE +21 -0
  5. onshape_jamcp-1.0.0/PKG-INFO +156 -0
  6. onshape_jamcp-1.0.0/README.md +133 -0
  7. onshape_jamcp-1.0.0/docs/comparison.md +47 -0
  8. onshape_jamcp-1.0.0/docs/configuration.md +98 -0
  9. onshape_jamcp-1.0.0/docs/development.md +154 -0
  10. onshape_jamcp-1.0.0/docs/getting-started.md +165 -0
  11. onshape_jamcp-1.0.0/docs/how-to.md +128 -0
  12. onshape_jamcp-1.0.0/docs/index.md +18 -0
  13. onshape_jamcp-1.0.0/docs/publishing.md +199 -0
  14. onshape_jamcp-1.0.0/docs/screenshots.md +65 -0
  15. onshape_jamcp-1.0.0/docs/tools.md +326 -0
  16. onshape_jamcp-1.0.0/docs/troubleshooting.md +61 -0
  17. onshape_jamcp-1.0.0/glama.json +6 -0
  18. onshape_jamcp-1.0.0/pyproject.toml +63 -0
  19. onshape_jamcp-1.0.0/scripts/gen_tools_doc.py +190 -0
  20. onshape_jamcp-1.0.0/scripts/release.py +678 -0
  21. onshape_jamcp-1.0.0/scripts/smoke_test.py +367 -0
  22. onshape_jamcp-1.0.0/src/onshape_jamcp/__init__.py +3 -0
  23. onshape_jamcp-1.0.0/src/onshape_jamcp/__main__.py +84 -0
  24. onshape_jamcp-1.0.0/src/onshape_jamcp/app.py +115 -0
  25. onshape_jamcp-1.0.0/src/onshape_jamcp/client.py +283 -0
  26. onshape_jamcp-1.0.0/src/onshape_jamcp/config.py +180 -0
  27. onshape_jamcp-1.0.0/src/onshape_jamcp/errors.py +33 -0
  28. onshape_jamcp-1.0.0/src/onshape_jamcp/features.py +152 -0
  29. onshape_jamcp-1.0.0/src/onshape_jamcp/fs.py +61 -0
  30. onshape_jamcp-1.0.0/src/onshape_jamcp/server.py +59 -0
  31. onshape_jamcp-1.0.0/src/onshape_jamcp/sketch.py +316 -0
  32. onshape_jamcp-1.0.0/src/onshape_jamcp/tools/__init__.py +13 -0
  33. onshape_jamcp-1.0.0/src/onshape_jamcp/tools/common.py +96 -0
  34. onshape_jamcp-1.0.0/src/onshape_jamcp/tools/documents.py +147 -0
  35. onshape_jamcp-1.0.0/src/onshape_jamcp/tools/inspection.py +305 -0
  36. onshape_jamcp-1.0.0/src/onshape_jamcp/tools/modeling.py +266 -0
  37. onshape_jamcp-1.0.0/src/onshape_jamcp/tools/output.py +265 -0
  38. onshape_jamcp-1.0.0/src/onshape_jamcp/tools/raw.py +74 -0
  39. onshape_jamcp-1.0.0/src/onshape_jamcp/tools/system.py +40 -0
  40. onshape_jamcp-1.0.0/src/onshape_jamcp/units.py +171 -0
  41. onshape_jamcp-1.0.0/src/onshape_jamcp/views.py +31 -0
  42. onshape_jamcp-1.0.0/tests/conftest.py +26 -0
  43. onshape_jamcp-1.0.0/tests/fake_onshape.py +284 -0
  44. onshape_jamcp-1.0.0/tests/release_helpers.py +42 -0
  45. onshape_jamcp-1.0.0/tests/test_builders.py +273 -0
  46. onshape_jamcp-1.0.0/tests/test_client.py +197 -0
  47. onshape_jamcp-1.0.0/tests/test_docs.py +54 -0
  48. onshape_jamcp-1.0.0/tests/test_release.py +203 -0
  49. onshape_jamcp-1.0.0/tests/test_release_git.py +397 -0
  50. onshape_jamcp-1.0.0/tests/test_stdio.py +84 -0
  51. onshape_jamcp-1.0.0/tests/test_tools.py +475 -0
  52. onshape_jamcp-1.0.0/tests/test_units_config.py +119 -0
  53. onshape_jamcp-1.0.0/tests/test_vscode_tasks.py +67 -0
@@ -0,0 +1,29 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ .venv/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .coverage
11
+ htmlcov/
12
+
13
+ # Secrets - never commit API keys
14
+ .env
15
+ .env.*
16
+ !.env.example
17
+
18
+ # Local-only tooling, kept out of the repository
19
+ .claude/settings.json
20
+ .claude/settings.local.json
21
+ .github/hooks/
22
+ ai-helper-*.ps1
23
+
24
+ # Local output (screenshots / exports) and editor files
25
+ output/
26
+ .idea/
27
+ .vscode/*
28
+ !.vscode/tasks.json
29
+ *.log
@@ -0,0 +1,46 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [1.0.0] - 2026-11-14
10
+
11
+ ### Changed
12
+ - Initial Version
13
+
14
+ ## [0.1.0] - 2026-11-14
15
+
16
+ First release (alpha).
17
+
18
+ ### Added
19
+ - 22 MCP tools: documents, Part Studio inspection, sketch / extrude / fillet / chamfer modeling,
20
+ feature editing, assembly inspection, screenshots, export and a raw API escape hatch.
21
+ - **Metric by default**: all lengths are millimeters unless `ONSHAPE_UNITS=imperial` (inches).
22
+ - **Screenshot review toggle**: `ONSHAPE_SCREENSHOT_REVIEW` / `--[no-]screenshot-review` and a
23
+ per-call `review` flag decide whether images are sent to the LLM (token cost) or only saved.
24
+ - Read-only mode (`ONSHAPE_READ_ONLY`) that removes every write tool.
25
+ - HMAC-signed API-key authentication (HTTP Basic available as a fallback).
26
+ - Default-plane IDs are resolved at runtime via FeatureScript instead of being hard-coded.
27
+ - `scripts/smoke_test.py` for verifying a build against a real Onshape account.
28
+ - Generated tool reference (`docs/tools.md`), Dockerfile and `glama.json` for Glama.
29
+ - Release automation: tag-triggered `release.yml` (verify, build, PyPI Trusted Publishing, GitHub
30
+ Release) and `scripts/release.py` (`check`, `notes`, `bump`, `build`, `verify`, `preflight`,
31
+ guarded `commit` / `tag` / `push` / `publish`).
32
+ - One VS Code task, `Release` (`.vscode/tasks.json`), for the whole flow: it asks which version, an
33
+ optional note and Preview vs real, then bumps, verifies (restoring the files on failure), commits,
34
+ tags and pushes. Notes come from `## [Unreleased]` or a typed line.
35
+
36
+ ### Fixed during live verification
37
+ - `whoami` no longer reports success for an anonymous session (Onshape returns `200 {}`).
38
+ - `create_document` has a `public` option; free plans reject private documents (`409`).
39
+ - FeatureScript evaluation: `queries` is an object, and flat `BTFSValue*` results are decoded.
40
+ - STL export: the `units` query value must be lowercase (`millimeter` / `inch`).
41
+
42
+ ### Known limitations
43
+ - Verified live on an Onshape free plan (31/31 smoke-test checks); not yet verified live: chamfer,
44
+ assemblies with mates, paid-plan behavior. See `docs/development.md`.
45
+ - No revolve/pattern/hole helpers, variables or assembly mates yet (use `add_feature` or
46
+ `onshape_api_request`).
@@ -0,0 +1,26 @@
1
+ # onshape-jamcp - MCP server speaking stdio.
2
+ #
3
+ # docker build -t onshape-jamcp .
4
+ # docker run -i --rm -e ONSHAPE_ACCESS_KEY=... -e ONSHAPE_SECRET_KEY=... onshape-jamcp
5
+ #
6
+ # The server starts (and lists its tools) without credentials, so registries such as Glama can
7
+ # introspect the image; tool calls report a clear error until the keys are provided.
8
+ FROM python:3.12-slim
9
+
10
+ ENV PYTHONUNBUFFERED=1 \
11
+ PYTHONDONTWRITEBYTECODE=1 \
12
+ PIP_NO_CACHE_DIR=1 \
13
+ PIP_DISABLE_PIP_VERSION_CHECK=1
14
+
15
+ WORKDIR /build
16
+ COPY pyproject.toml README.md LICENSE ./
17
+ COPY src ./src
18
+ RUN pip install . && rm -rf /build
19
+
20
+ # Run as an unprivileged user; screenshots/exports go to a writable directory.
21
+ RUN useradd --create-home --uid 10001 jamcp
22
+ USER jamcp
23
+ WORKDIR /home/jamcp
24
+ ENV ONSHAPE_OUTPUT_DIR=/home/jamcp/output
25
+
26
+ ENTRYPOINT ["onshape-jamcp"]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 onshape-jamcp contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,156 @@
1
+ Metadata-Version: 2.5
2
+ Name: onshape-jamcp
3
+ Version: 1.0.0
4
+ Summary: Just Another MCP server for Onshape CAD - metric by default, with optional screenshot review by the LLM.
5
+ Author: onshape-jamcp contributors
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: 3d,cad,llm,mcp,model-context-protocol,onshape,parametric
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Manufacturing
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: httpx<1,>=0.27
21
+ Requires-Dist: mcp<3,>=2.3
22
+ Description-Content-Type: text/markdown
23
+
24
+ # onshape-jamcp
25
+
26
+ **J**ust **A**nother **MCP** server for [Onshape](https://www.onshape.com) CAD. It lets an AI
27
+ assistant (Claude, Cursor, VS Code, any [MCP](https://modelcontextprotocol.io) client) find your
28
+ documents, model parts, measure them, look at them and export them - in **millimeters by default**,
29
+ with a switch for **inches**, and a switch that decides whether the assistant gets to **see
30
+ screenshots** (which costs tokens) or not.
31
+
32
+ > **Status: alpha, verified live.** 140+ automated tests run against a simulated Onshape, and
33
+ > [`scripts/smoke_test.py`](scripts/smoke_test.py) passed **31/31 checks against a real Onshape
34
+ > account** (free plan, 2026-11-14): sketch → extrude → fillet → hole → edit → screenshot → STEP/STL
35
+ > export, with orientation and dimensions measured. Chamfer, assemblies with mates and paid-plan
36
+ > behavior are not yet verified live - see [what is verified](docs/development.md#verification-status-read-this-before-trusting-a-tool).
37
+ > Re-run the smoke test on your own account (see [below](#verify-it-works-against-your-account)).
38
+
39
+ ## Highlights
40
+
41
+ | | |
42
+ |---|---|
43
+ | 📏 **Metric by default** | Every length you send or receive is in **mm**. Set `ONSHAPE_UNITS=imperial` for inches. Angles are always degrees. |
44
+ | 👁️ **Screenshot review toggle** | `ONSHAPE_SCREENSHOT_REVIEW=true` sends renders to the model so it can *see* its work (≈ 640 tokens per 800×600 image). `false` only saves them to disk - zero image tokens. Override per call with `review`. |
45
+ | 🔒 **Read-only mode** | `ONSHAPE_READ_ONLY=true` removes every tool that can modify a document. |
46
+ | 🧰 **22 focused tools** | Documents, sketch → extrude → fillet/chamfer, edit parameters, measure, faces/edges, assemblies, screenshots, STEP/STL export - plus escape hatches (raw feature JSON, FeatureScript, any REST endpoint). |
47
+ | 🧪 **Honest feedback loop** | Every modeling tool reports the feature's health (`OK`/`WARNING`/`ERROR`) so the model notices failures instead of piling more features on top. |
48
+
49
+ ## Quick start
50
+
51
+ **1. Create API keys** at <https://dev-portal.onshape.com/keys> (tick *Read* and *Write*; *Delete*
52
+ only if you want `delete_feature`). Copy the secret immediately - Onshape shows it once.
53
+
54
+ **2. Add the server to your MCP client.** Claude Desktop (`claude_desktop_config.json`):
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "onshape": {
60
+ "command": "uvx",
61
+ "args": ["onshape-jamcp"],
62
+ "env": {
63
+ "ONSHAPE_ACCESS_KEY": "your-access-key",
64
+ "ONSHAPE_SECRET_KEY": "your-secret-key",
65
+ "ONSHAPE_UNITS": "metric",
66
+ "ONSHAPE_SCREENSHOT_REVIEW": "true"
67
+ }
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ Claude Code: `claude mcp add onshape -e ONSHAPE_ACCESS_KEY=... -e ONSHAPE_SECRET_KEY=... -- uvx onshape-jamcp`
74
+
75
+ > Until the package is published to PyPI, run it from a checkout instead: replace the command with
76
+ > `"command": "uv", "args": ["run", "--directory", "/path/to/onshape-jamcp", "onshape-jamcp"]`.
77
+ > More clients and details: [docs/getting-started.md](docs/getting-started.md).
78
+
79
+ **3. Ask for something:**
80
+
81
+ > *"Create a document called 'Bracket'. In a new Part Studio model a 60 × 40 mm plate, 8 mm thick,
82
+ > with four 5 mm holes 6 mm from the corners and 4 mm fillets on the vertical edges. Show me a
83
+ > screenshot when you're done."*
84
+
85
+ ## Verify it works against your account
86
+
87
+ ```bash
88
+ cp .env.example .env # fill in the two keys
89
+ uv run python scripts/smoke_test.py # on a free plan add --public (see below)
90
+ ```
91
+
92
+ It creates a throw-away document (private; on a free plan Onshape only allows public ones, so pass
93
+ `--public`), models a plate, checks the dimensions/orientation/hole volume/fillets/edit/screenshot/
94
+ STEP+STL export numerically, then moves the document to Onshape's trash.
95
+ It prints `PASS`/`FAIL` per check. This is the step that confirms the assumptions a simulated
96
+ Onshape cannot (plane orientation, face normals, extrude direction).
97
+
98
+ ## Settings
99
+
100
+ Set as environment variables (the `env` block of your MCP client) or CLI flags. The important ones:
101
+
102
+ | Variable | Default | Meaning |
103
+ |---|---|---|
104
+ | `ONSHAPE_ACCESS_KEY` / `ONSHAPE_SECRET_KEY` | - | **Required.** API keys. |
105
+ | `ONSHAPE_UNITS` | `metric` | `metric` = millimeters, `imperial` = inches. Flag: `--units`. |
106
+ | `ONSHAPE_SCREENSHOT_REVIEW` | `true` | Send screenshots to the LLM (`true`) or only save them (`false`). Flag: `--[no-]screenshot-review`. |
107
+ | `ONSHAPE_READ_ONLY` | `false` | Hide all write tools. Flag: `--read-only`. |
108
+ | `ONSHAPE_BASE_URL` | `https://cad.onshape.com` | Enterprise: `https://yourcompany.onshape.com`. |
109
+
110
+ Everything else (image size, output folder, timeout, auth mode, API version, log level) is in
111
+ [docs/configuration.md](docs/configuration.md).
112
+
113
+ ## Tools
114
+
115
+ | Group | Tools |
116
+ |---|---|
117
+ | Server | `get_settings`, `whoami` |
118
+ | Documents | `list_documents`, `get_document`, `create_document`, `create_element` |
119
+ | Inspect | `list_features`, `list_parts`, `get_part_properties`, `get_body_details`, `get_assembly`, `run_featurescript` |
120
+ | Model | `create_sketch`, `extrude`, `fillet`, `chamfer`, `update_feature`, `delete_feature`, `add_feature` |
121
+ | Look & export | `capture_screenshot`, `export_model` |
122
+ | Escape hatch | `onshape_api_request` |
123
+
124
+ Full parameter reference (generated from the code): [docs/tools.md](docs/tools.md).
125
+
126
+ ## Documentation
127
+
128
+ - [Getting started](docs/getting-started.md) - keys, installing in each client, first prompt
129
+ - [Configuration](docs/configuration.md) - every setting, units, precedence
130
+ - [How-to recipes](docs/how-to.md) - holes, fillets, edits, inches, export, read-only, advanced features
131
+ - [Screenshots & token cost](docs/screenshots.md) - what the review toggle does and when to use it
132
+ - [Tool reference](docs/tools.md) - all tools and parameters
133
+ - [Troubleshooting](docs/troubleshooting.md)
134
+ - [Development](docs/development.md) - architecture, tests, adding a tool
135
+ - [Publishing](docs/publishing.md) - PyPI and Glama
136
+ - [Comparison](docs/comparison.md) - how this relates to the other Onshape MCP servers
137
+
138
+ ## Security notes
139
+
140
+ - API keys stay in your MCP client's config / environment. They are never returned by any tool,
141
+ never logged, and requests are HMAC-signed so the secret is not even sent over the wire.
142
+ - **Onshape's free plan makes every document public.** Do not model confidential work there.
143
+ - Write tools act as *you* on your real documents. Use `ONSHAPE_READ_ONLY=true` when you only want
144
+ the assistant to look around, and rely on Onshape's version history as your undo.
145
+ - With screenshot review on, rendered images are sent to your LLM provider like any other message.
146
+
147
+ ## Acknowledgements
148
+
149
+ Prior art that shaped this project: [hedless/onshape-mcp](https://github.com/hedless/onshape-mcp)
150
+ (MIT; the Onshape feature JSON conventions were cross-checked against it) and
151
+ [altendky/onshape-mcp](https://github.com/altendky/onshape-mcp). See
152
+ [docs/comparison.md](docs/comparison.md).
153
+
154
+ ## License
155
+
156
+ [MIT](LICENSE). Not affiliated with or endorsed by PTC / Onshape.
@@ -0,0 +1,133 @@
1
+ # onshape-jamcp
2
+
3
+ **J**ust **A**nother **MCP** server for [Onshape](https://www.onshape.com) CAD. It lets an AI
4
+ assistant (Claude, Cursor, VS Code, any [MCP](https://modelcontextprotocol.io) client) find your
5
+ documents, model parts, measure them, look at them and export them - in **millimeters by default**,
6
+ with a switch for **inches**, and a switch that decides whether the assistant gets to **see
7
+ screenshots** (which costs tokens) or not.
8
+
9
+ > **Status: alpha, verified live.** 140+ automated tests run against a simulated Onshape, and
10
+ > [`scripts/smoke_test.py`](scripts/smoke_test.py) passed **31/31 checks against a real Onshape
11
+ > account** (free plan, 2026-11-14): sketch → extrude → fillet → hole → edit → screenshot → STEP/STL
12
+ > export, with orientation and dimensions measured. Chamfer, assemblies with mates and paid-plan
13
+ > behavior are not yet verified live - see [what is verified](docs/development.md#verification-status-read-this-before-trusting-a-tool).
14
+ > Re-run the smoke test on your own account (see [below](#verify-it-works-against-your-account)).
15
+
16
+ ## Highlights
17
+
18
+ | | |
19
+ |---|---|
20
+ | 📏 **Metric by default** | Every length you send or receive is in **mm**. Set `ONSHAPE_UNITS=imperial` for inches. Angles are always degrees. |
21
+ | 👁️ **Screenshot review toggle** | `ONSHAPE_SCREENSHOT_REVIEW=true` sends renders to the model so it can *see* its work (≈ 640 tokens per 800×600 image). `false` only saves them to disk - zero image tokens. Override per call with `review`. |
22
+ | 🔒 **Read-only mode** | `ONSHAPE_READ_ONLY=true` removes every tool that can modify a document. |
23
+ | 🧰 **22 focused tools** | Documents, sketch → extrude → fillet/chamfer, edit parameters, measure, faces/edges, assemblies, screenshots, STEP/STL export - plus escape hatches (raw feature JSON, FeatureScript, any REST endpoint). |
24
+ | 🧪 **Honest feedback loop** | Every modeling tool reports the feature's health (`OK`/`WARNING`/`ERROR`) so the model notices failures instead of piling more features on top. |
25
+
26
+ ## Quick start
27
+
28
+ **1. Create API keys** at <https://dev-portal.onshape.com/keys> (tick *Read* and *Write*; *Delete*
29
+ only if you want `delete_feature`). Copy the secret immediately - Onshape shows it once.
30
+
31
+ **2. Add the server to your MCP client.** Claude Desktop (`claude_desktop_config.json`):
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "onshape": {
37
+ "command": "uvx",
38
+ "args": ["onshape-jamcp"],
39
+ "env": {
40
+ "ONSHAPE_ACCESS_KEY": "your-access-key",
41
+ "ONSHAPE_SECRET_KEY": "your-secret-key",
42
+ "ONSHAPE_UNITS": "metric",
43
+ "ONSHAPE_SCREENSHOT_REVIEW": "true"
44
+ }
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ Claude Code: `claude mcp add onshape -e ONSHAPE_ACCESS_KEY=... -e ONSHAPE_SECRET_KEY=... -- uvx onshape-jamcp`
51
+
52
+ > Until the package is published to PyPI, run it from a checkout instead: replace the command with
53
+ > `"command": "uv", "args": ["run", "--directory", "/path/to/onshape-jamcp", "onshape-jamcp"]`.
54
+ > More clients and details: [docs/getting-started.md](docs/getting-started.md).
55
+
56
+ **3. Ask for something:**
57
+
58
+ > *"Create a document called 'Bracket'. In a new Part Studio model a 60 × 40 mm plate, 8 mm thick,
59
+ > with four 5 mm holes 6 mm from the corners and 4 mm fillets on the vertical edges. Show me a
60
+ > screenshot when you're done."*
61
+
62
+ ## Verify it works against your account
63
+
64
+ ```bash
65
+ cp .env.example .env # fill in the two keys
66
+ uv run python scripts/smoke_test.py # on a free plan add --public (see below)
67
+ ```
68
+
69
+ It creates a throw-away document (private; on a free plan Onshape only allows public ones, so pass
70
+ `--public`), models a plate, checks the dimensions/orientation/hole volume/fillets/edit/screenshot/
71
+ STEP+STL export numerically, then moves the document to Onshape's trash.
72
+ It prints `PASS`/`FAIL` per check. This is the step that confirms the assumptions a simulated
73
+ Onshape cannot (plane orientation, face normals, extrude direction).
74
+
75
+ ## Settings
76
+
77
+ Set as environment variables (the `env` block of your MCP client) or CLI flags. The important ones:
78
+
79
+ | Variable | Default | Meaning |
80
+ |---|---|---|
81
+ | `ONSHAPE_ACCESS_KEY` / `ONSHAPE_SECRET_KEY` | - | **Required.** API keys. |
82
+ | `ONSHAPE_UNITS` | `metric` | `metric` = millimeters, `imperial` = inches. Flag: `--units`. |
83
+ | `ONSHAPE_SCREENSHOT_REVIEW` | `true` | Send screenshots to the LLM (`true`) or only save them (`false`). Flag: `--[no-]screenshot-review`. |
84
+ | `ONSHAPE_READ_ONLY` | `false` | Hide all write tools. Flag: `--read-only`. |
85
+ | `ONSHAPE_BASE_URL` | `https://cad.onshape.com` | Enterprise: `https://yourcompany.onshape.com`. |
86
+
87
+ Everything else (image size, output folder, timeout, auth mode, API version, log level) is in
88
+ [docs/configuration.md](docs/configuration.md).
89
+
90
+ ## Tools
91
+
92
+ | Group | Tools |
93
+ |---|---|
94
+ | Server | `get_settings`, `whoami` |
95
+ | Documents | `list_documents`, `get_document`, `create_document`, `create_element` |
96
+ | Inspect | `list_features`, `list_parts`, `get_part_properties`, `get_body_details`, `get_assembly`, `run_featurescript` |
97
+ | Model | `create_sketch`, `extrude`, `fillet`, `chamfer`, `update_feature`, `delete_feature`, `add_feature` |
98
+ | Look & export | `capture_screenshot`, `export_model` |
99
+ | Escape hatch | `onshape_api_request` |
100
+
101
+ Full parameter reference (generated from the code): [docs/tools.md](docs/tools.md).
102
+
103
+ ## Documentation
104
+
105
+ - [Getting started](docs/getting-started.md) - keys, installing in each client, first prompt
106
+ - [Configuration](docs/configuration.md) - every setting, units, precedence
107
+ - [How-to recipes](docs/how-to.md) - holes, fillets, edits, inches, export, read-only, advanced features
108
+ - [Screenshots & token cost](docs/screenshots.md) - what the review toggle does and when to use it
109
+ - [Tool reference](docs/tools.md) - all tools and parameters
110
+ - [Troubleshooting](docs/troubleshooting.md)
111
+ - [Development](docs/development.md) - architecture, tests, adding a tool
112
+ - [Publishing](docs/publishing.md) - PyPI and Glama
113
+ - [Comparison](docs/comparison.md) - how this relates to the other Onshape MCP servers
114
+
115
+ ## Security notes
116
+
117
+ - API keys stay in your MCP client's config / environment. They are never returned by any tool,
118
+ never logged, and requests are HMAC-signed so the secret is not even sent over the wire.
119
+ - **Onshape's free plan makes every document public.** Do not model confidential work there.
120
+ - Write tools act as *you* on your real documents. Use `ONSHAPE_READ_ONLY=true` when you only want
121
+ the assistant to look around, and rely on Onshape's version history as your undo.
122
+ - With screenshot review on, rendered images are sent to your LLM provider like any other message.
123
+
124
+ ## Acknowledgements
125
+
126
+ Prior art that shaped this project: [hedless/onshape-mcp](https://github.com/hedless/onshape-mcp)
127
+ (MIT; the Onshape feature JSON conventions were cross-checked against it) and
128
+ [altendky/onshape-mcp](https://github.com/altendky/onshape-mcp). See
129
+ [docs/comparison.md](docs/comparison.md).
130
+
131
+ ## License
132
+
133
+ [MIT](LICENSE). Not affiliated with or endorsed by PTC / Onshape.
@@ -0,0 +1,47 @@
1
+ # How this compares
2
+
3
+ Several MCP servers touch Onshape. This table is based on each project's own README/listing as of
4
+ November 2026; check them for current details.
5
+
6
+ | | **onshape-jamcp** (this) | [hedless/onshape-mcp](https://github.com/hedless/onshape-mcp) | [altendky/onshape-mcp](https://github.com/altendky/onshape-mcp) | [Onshape Labs FeatureScript MCP](https://www.onshape.com/en/blog/featurescript-mcp-server-enables-text-code-cad) |
7
+ |---|---|---|---|---|
8
+ | Language / runs | Python, local stdio | Python, local stdio | Rust, local stdio (+ experimental HTTP) | Hosted by Onshape (HTTP) |
9
+ | Install | `uvx` / `pip` / Docker | clone + venv | `npx` or binary | Onshape App Store subscription |
10
+ | Auth | API keys (HMAC; Basic as fallback) | API keys (Basic) | OAuth (default) or API keys | Your Onshape sign-in |
11
+ | Default units | **millimeters**, inches via setting | inches only | not stated | n/a |
12
+ | Screenshots | yes, with a **token-saving review toggle** | no | yes | no |
13
+ | Read-only mode | yes | no | - | - |
14
+ | Scope | documents, sketch/extrude/fillet/chamfer, edit, measure, faces/edges, assembly view, export, raw API | very broad modeling + assemblies/mates (45+ tools) | broad, endpoints discovered dynamically; FeatureScript authoring | generate/debug FeatureScript custom features only |
15
+ | Tool count | 22 | 45-48 | - | - |
16
+
17
+ ## Where jamcp is deliberately different
18
+
19
+ - **Units are a first-class setting**, not an afterthought: millimeters by default, one switch to
20
+ inches, explicit units always honored, every output converted.
21
+ - **Screenshot cost is under your control**: review on/off globally and per call, with token
22
+ estimates reported.
23
+ - **Smaller tool surface.** Twenty-two well-described tools plus escape hatches, rather than 45+.
24
+ Fewer tools means less context spent on the tool list and fewer wrong choices by the model.
25
+ (Glama's quality scoring also penalizes very large tool counts.)
26
+ - **Nothing hard-coded that Onshape can tell us.** Origin-plane IDs are looked up with FeatureScript
27
+ at runtime instead of being baked in as constants. (One existing server hard-codes
28
+ Front/Top/Right as three-letter IDs; that mapping could not be confirmed independently, and a
29
+ wrong constant would silently put sketches on the wrong plane.)
30
+ - **Safe to explore**: read-only mode removes write tools entirely.
31
+
32
+ ## Where others are ahead (today)
33
+
34
+ - **hedless/onshape-mcp** has assembly mates, positioning, interference checks, patterns, revolve,
35
+ thicken, variables and a much larger test and example base. If you need to build assemblies with
36
+ an AI right now, it covers more. jamcp's `add_feature` and `onshape_api_request` can reach those
37
+ features but without the ergonomic helpers.
38
+ - **altendky/onshape-mcp** supports OAuth (no long-lived secret keys) and a hosted HTTP mode, and
39
+ it discovers API endpoints dynamically rather than shipping a fixed tool list.
40
+ - **Onshape's FeatureScript MCP** is the right tool for *authoring custom features*; it is
41
+ complementary to this server, not a replacement.
42
+
43
+ ## Acknowledgement
44
+
45
+ The Onshape feature JSON conventions (BTM types, sketch entity layout, sketch-region queries) were
46
+ cross-checked against hedless/onshape-mcp (MIT) and Onshape's public OpenAPI specification. No code
47
+ was copied.
@@ -0,0 +1,98 @@
1
+ # Configuration
2
+
3
+ onshape-jamcp is configured with **environment variables**. In an MCP client these go in the
4
+ server's `env` block. A few have **command-line flags** (set in the client's `args`), which
5
+ override the environment.
6
+
7
+ ```json
8
+ {
9
+ "command": "uvx",
10
+ "args": ["onshape-jamcp", "--units", "imperial", "--no-screenshot-review"],
11
+ "env": { "ONSHAPE_ACCESS_KEY": "...", "ONSHAPE_SECRET_KEY": "..." }
12
+ }
13
+ ```
14
+
15
+ Invalid values stop the server at startup with a message naming the variable (exit code 2). Missing
16
+ API keys do **not** stop it: the server starts and lists its tools, and each tool call that needs
17
+ Onshape reports what to set.
18
+
19
+ ## All settings
20
+
21
+ | Variable | Flag | Default | Description |
22
+ |---|---|---|---|
23
+ | `ONSHAPE_ACCESS_KEY` | | - | API access key (required for any tool that calls Onshape). |
24
+ | `ONSHAPE_SECRET_KEY` | | - | API secret key. |
25
+ | `ONSHAPE_UNITS` | `--units` | `metric` | `metric` (millimeters) or `imperial` (inches). Aliases: `mm`, `inch`, `inches`, `in`. |
26
+ | `ONSHAPE_SCREENSHOT_REVIEW` | `--screenshot-review` / `--no-screenshot-review` | `true` | Send screenshots to the LLM for review. See [screenshots](screenshots.md). |
27
+ | `ONSHAPE_SCREENSHOT_WIDTH` | | `800` | Default screenshot width in px (64-2000). |
28
+ | `ONSHAPE_SCREENSHOT_HEIGHT` | | `600` | Default screenshot height in px (64-2000). |
29
+ | `ONSHAPE_OUTPUT_DIR` | | system temp `/onshape-jamcp` | Where screenshots (`screenshots/`) and exports (`exports/`) are saved. |
30
+ | `ONSHAPE_READ_ONLY` | `--read-only` | `false` | Do not register any tool that modifies documents; block non-GET `onshape_api_request`. |
31
+ | `ONSHAPE_BASE_URL` | | `https://cad.onshape.com` | Onshape origin. Enterprise accounts: `https://yourcompany.onshape.com`. Must be `https` (plain `http` only for localhost). |
32
+ | `ONSHAPE_API_VERSION` | | `v17` | REST API version, `v` + number. The tools were written against v17. |
33
+ | `ONSHAPE_AUTH_MODE` | | `hmac` | `hmac` signs each request (the secret is never transmitted). `basic` sends `access:secret` as HTTP Basic over HTTPS; Onshape documents it as lowest-security, "for local testing only", so use it only as a fallback if signing misbehaves. |
34
+ | `ONSHAPE_TIMEOUT` | | `60` | Per-request timeout in seconds (1-600). Raise it for very large models. |
35
+ | `ONSHAPE_LOG_LEVEL` | | `WARNING` | `DEBUG`, `INFO`, `WARNING`, `ERROR`. Logs go to **stderr** (stdout is the MCP channel). `DEBUG` also logs HTTP requests (never credentials or bodies). |
36
+
37
+ Booleans accept `true/false`, `1/0`, `yes/no`, `on/off`.
38
+
39
+ ## Units
40
+
41
+ The unit system is a single global setting.
42
+
43
+ | | `metric` (default) | `imperial` |
44
+ |---|---|---|
45
+ | Lengths in and out | millimeters (`mm`) | inches (`in`) |
46
+ | Areas | `mm^2` | `in^2` |
47
+ | Volumes | `mm^3` | `in^3` |
48
+ | Angles | degrees | degrees |
49
+ | Mass | kilograms (always) | kilograms (always) |
50
+
51
+ How it works:
52
+
53
+ - **Plain numbers are in the configured unit.** With metric, `depth: 10` means 10 mm; with imperial
54
+ it means 10 in.
55
+ - **Explicit units always win.** Any length also accepts a string such as `"0.5 in"` or `"25 mm"`
56
+ (units: `mm`, `cm`, `m`, `in`, `ft`, `yd`), so you can mix systems in one request.
57
+ - **Onshape expressions** are accepted where Onshape evaluates them (`extrude.depth`, `fillet.radius`,
58
+ `chamfer.distance`, `update_feature` values): `"#width"`, `"#width / 2"`. Sketch geometry needs
59
+ concrete numbers because the API stores it in meters.
60
+ - **Everything the server returns is converted** to the configured unit: bounding boxes, volumes,
61
+ centroids, face origins, edge end points, assembly positions. `get_settings` tells the model which
62
+ unit is active.
63
+ - Two things stay in raw SI because they are pass-through: results of `run_featurescript` (meters)
64
+ and `onshape_api_request` (meters). Their tool descriptions say so.
65
+
66
+ Switching units never changes existing models - Onshape stores geometry in SI internally and only
67
+ the *input and output of this server* change.
68
+
69
+ ## Screenshots
70
+
71
+ - `ONSHAPE_SCREENSHOT_REVIEW=true` (default): `capture_screenshot` saves the PNG **and** returns it
72
+ to the model.
73
+ - `ONSHAPE_SCREENSHOT_REVIEW=false`: it saves the PNG and returns only the file path and metadata -
74
+ **no image tokens**.
75
+ - Per call: `capture_screenshot(review=true|false)` overrides the setting for that call.
76
+
77
+ Details, token numbers and strategy: [screenshots.md](screenshots.md).
78
+
79
+ ## Read-only mode
80
+
81
+ With `ONSHAPE_READ_ONLY=true` the modeling and document-creating tools (`create_document`,
82
+ `create_element`, `create_sketch`, `extrude`, `fillet`, `chamfer`, `update_feature`,
83
+ `delete_feature`, `add_feature`) are **not registered at all**, so the model cannot even try. Reading,
84
+ measuring, screenshots, export and `GET` requests through `onshape_api_request` keep working.
85
+ Note that export creates a temporary translation job on Onshape's side but does not change your
86
+ document.
87
+
88
+ ## Precedence
89
+
90
+ command-line flag → environment variable → built-in default.
91
+
92
+ ## Per-client notes
93
+
94
+ - **Claude Desktop** passes only the variables in `env` to the server - it does not inherit your
95
+ shell environment. Put the keys in `env`.
96
+ - **Windows paths** in JSON need escaped backslashes (`"D:\\source\\repos\\..."`) or forward slashes.
97
+ - For local development a `.env` file is read by `scripts/smoke_test.py` only; the server itself
98
+ reads the real process environment.