forma-dsl-mcp 0.1.4

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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/package.json +52 -0
  4. package/src/bin.js +30 -0
  5. package/src/catalogue.js +703 -0
  6. package/src/document.js +285 -0
  7. package/src/examples.js +212 -0
  8. package/src/guide.js +313 -0
  9. package/src/reference/README.md +153 -0
  10. package/src/reference/api/describe-parameters.md +167 -0
  11. package/src/reference/api/evaluation-context.md +221 -0
  12. package/src/reference/api/export.md +185 -0
  13. package/src/reference/api/geometry-node.md +215 -0
  14. package/src/reference/api/kernel.md +182 -0
  15. package/src/reference/api/low-level.md +239 -0
  16. package/src/reference/api/render.md +217 -0
  17. package/src/reference/api/values.md +223 -0
  18. package/src/reference/errors.md +253 -0
  19. package/src/reference/language/control-flow.md +160 -0
  20. package/src/reference/language/expressions.md +206 -0
  21. package/src/reference/language/overview.md +156 -0
  22. package/src/reference/language/scope.md +184 -0
  23. package/src/reference/language/syntax.md +210 -0
  24. package/src/reference/reference/align.md +189 -0
  25. package/src/reference/reference/booleans.md +231 -0
  26. package/src/reference/reference/component.md +248 -0
  27. package/src/reference/reference/conversions.md +269 -0
  28. package/src/reference/reference/functions.md +314 -0
  29. package/src/reference/reference/local.md +197 -0
  30. package/src/reference/reference/model.md +213 -0
  31. package/src/reference/reference/param.md +230 -0
  32. package/src/reference/reference/part.md +229 -0
  33. package/src/reference/reference/refinement.md +284 -0
  34. package/src/reference/reference/shapes-2d.md +309 -0
  35. package/src/reference/reference/shapes-3d.md +279 -0
  36. package/src/reference/reference/transforms.md +246 -0
  37. package/src/reference.js +160 -0
  38. package/src/server.js +219 -0
  39. package/src/tools.js +523 -0
  40. package/src/workspace.js +204 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kalpak44
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.
package/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # forma-dsl-mcp
2
+
3
+ [![Release](https://github.com/kalpak44/forma-dsl/actions/workflows/release.yml/badge.svg)](https://github.com/kalpak44/forma-dsl/actions/workflows/release.yml)
4
+ [![npm](https://img.shields.io/npm/v/forma-dsl-mcp.svg)](https://www.npmjs.com/package/forma-dsl-mcp)
5
+
6
+ A [Model Context Protocol](https://modelcontextprotocol.io) server that knows
7
+ [forma](https://www.npmjs.com/package/forma-dsl) — the declarative DSL for 3D solids — and
8
+ writes `.forma` documents that render.
9
+
10
+ It speaks over stdio, so any MCP client can launch it:
11
+
12
+ ```json
13
+ {
14
+ "mcpServers": {
15
+ "forma": {
16
+ "command": "npx",
17
+ "args": ["-y", "forma-dsl-mcp"],
18
+ "env": { "FORMA_MCP_ROOT": "/absolute/path/to/your/models" }
19
+ }
20
+ }
21
+ }
22
+ ```
23
+
24
+ `FORMA_MCP_ROOT` is the only configuration. It defaults to the working directory the client
25
+ launches the server in, and **every path the file tools accept is confined to it** — an
26
+ absolute path, a `..` that climbs out, or a symlink pointing out of the tree is refused
27
+ rather than followed.
28
+
29
+ ## Why it is not just a prompt
30
+
31
+ A model that has read the language's documentation still writes forma that does not build.
32
+ The difference this server makes is that it **runs the geometry kernel**. `forma_check`
33
+ compiles the document, solves it with [Manifold](https://github.com/elalish/manifold) and
34
+ reports back the bounding box, the volume, the triangle count and the genus of every part —
35
+ so the question "is this the size that was asked for, and is it actually a solid?" is
36
+ answered before anyone is told the work is done. A part that silently solved to nothing is
37
+ called out by name.
38
+
39
+ `forma_write` runs that same check and **refuses to write a document that does not render**.
40
+
41
+ Everything the server says about the language is answerable to the language. The block and
42
+ function catalogue is merged with the library's own registries at load time, and the tests
43
+ assert that the two agree: a block added, renamed or given a new dimensionality in
44
+ `forma-dsl` fails this package's build rather than becoming a confident wrong answer. Every
45
+ worked example is rendered by the test suite, at both ends of every parameter's declared
46
+ range.
47
+
48
+ ## Tools
49
+
50
+ | Tool | What it does |
51
+ | --- | --- |
52
+ | `forma_guide` | The language in one page: structure, nesting, dimensionality, units, syntax, the mistakes that cost the most time |
53
+ | `forma_blocks` | Every block with its attributes, defaults, dimensionality and caveats |
54
+ | `forma_functions` | Every builtin function and constant, with arity |
55
+ | `forma_reference` | The full reference manual, searchable and readable page by page |
56
+ | `forma_examples` | Complete documents that render, each showing one way of building a real part |
57
+ | `forma_check` | Parse, build and **measure** — errors with a line, a column and an excerpt with a caret; parts with their boxes, volumes and triangle counts |
58
+ | `forma_write` | Check, then write a `.forma` file into the workspace |
59
+ | `forma_read` | Read a document back, checked |
60
+ | `forma_list` | Every `.forma` file under the root |
61
+ | `forma_export_stl` | Render and write a binary STL |
62
+
63
+ ## Resources and prompts
64
+
65
+ Resources carry the same knowledge in a form a person can attach by hand:
66
+
67
+ - `forma://guide` — the language in brief
68
+ - `forma://catalogue` — every block and function, as JSON
69
+ - `forma://reference/{path}` — one page of the manual
70
+ - `forma://example/{name}` — one worked document
71
+
72
+ Two prompts name the workflows worth having a name for: `model_a_part`, which walks from a
73
+ description of a physical object to a checked document, and `review_a_document`, which reads
74
+ an existing one and looks for the failures that are silent.
75
+
76
+ ## Running it from source
77
+
78
+ ```bash
79
+ npm install
80
+ npm test -w forma-dsl-mcp # 140+ tests, including the protocol end to end
81
+ node packages/forma-dsl-mcp/src/bin.js # the server, on stdio
82
+ ```
83
+
84
+ Point a client at `node /absolute/path/to/packages/forma-dsl-mcp/src/bin.js` to use the
85
+ working tree rather than the published package.
86
+
87
+ ## The bundled manual
88
+
89
+ `src/reference/` is a copy of [`apps/docs/content`](../../apps/docs/content/README.md), which
90
+ is a private workspace and cannot be depended on from something that ships to npm. The copy
91
+ is what lets the server answer offline. It is made by `npm run sync:reference -w
92
+ forma-dsl-mcp` and compared byte for byte against the original by the tests, so it cannot
93
+ drift: edit the manual, re-run the sync, and the test passes again.
94
+
95
+ ## License
96
+
97
+ MIT — see [LICENSE](LICENSE).
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "forma-dsl-mcp",
3
+ "version": "0.1.4",
4
+ "description": "A stdio MCP server that knows the forma DSL and writes .forma documents that render.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "forma",
9
+ "forma-dsl",
10
+ "cad",
11
+ "csg",
12
+ "3d",
13
+ "parametric",
14
+ "stl"
15
+ ],
16
+ "homepage": "https://github.com/kalpak44/forma-dsl/tree/main/packages/forma-dsl-mcp#readme",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/kalpak44/forma-dsl.git",
20
+ "directory": "packages/forma-dsl-mcp"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/kalpak44/forma-dsl/issues"
24
+ },
25
+ "author": "Pavel Usanli",
26
+ "license": "MIT",
27
+ "type": "module",
28
+ "bin": {
29
+ "forma-dsl-mcp": "./src/bin.js"
30
+ },
31
+ "exports": {
32
+ ".": "./src/server.js",
33
+ "./package.json": "./package.json"
34
+ },
35
+ "files": [
36
+ "src"
37
+ ],
38
+ "engines": {
39
+ "node": ">=22.13.0"
40
+ },
41
+ "scripts": {
42
+ "start": "node src/bin.js",
43
+ "test": "node --test",
44
+ "sync:reference": "node scripts/sync-reference.mjs",
45
+ "check:package": "node scripts/check-package.mjs"
46
+ },
47
+ "dependencies": {
48
+ "@modelcontextprotocol/sdk": "^1.31.0",
49
+ "forma-dsl": "^0.1.4",
50
+ "zod": "^4.1.13"
51
+ }
52
+ }
package/src/bin.js ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * The executable: one MCP server, speaking over stdin and stdout.
4
+ *
5
+ * Nothing may be written to stdout but the protocol — a stray `console.log` corrupts the
6
+ * JSON-RPC stream and the client disconnects with an error that names nothing. Everything
7
+ * this file has to say goes to stderr, which clients collect as the server's log.
8
+ */
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+
11
+ import { Workspace } from './workspace.js';
12
+ import { VERSION, createServer } from './server.js';
13
+
14
+ /**
15
+ * Where the file tools are allowed to read and write.
16
+ *
17
+ * Defaults to the working directory, which is what a client that launches the server inside
18
+ * a project gives it. `FORMA_MCP_ROOT` overrides it.
19
+ */
20
+ const root = process.env.FORMA_MCP_ROOT ?? process.cwd();
21
+
22
+ try {
23
+ const workspace = await Workspace.open(root);
24
+ const server = createServer(workspace);
25
+ await server.connect(new StdioServerTransport());
26
+ console.error(`forma-dsl-mcp ${VERSION} ready — workspace ${workspace.root}`);
27
+ } catch (error) {
28
+ console.error(`forma-dsl-mcp failed to start: ${error?.message ?? error}`);
29
+ process.exit(1);
30
+ }