@linktr.ee/arbor-mcp 0.1.0

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 (3) hide show
  1. package/README.md +163 -0
  2. package/dist/index.js +1208 -0
  3. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # @linktr.ee/arbor-mcp
2
+
3
+ A [Model Context Protocol](https://modelcontextprotocol.io) server that
4
+ exposes Arbor design system tools to MCP-connected AI agents (Claude Code,
5
+ Claude Desktop, Cursor, Zed, etc.).
6
+
7
+ ## What it does
8
+
9
+ Currently registers a single tool:
10
+
11
+ ### `arbor.open_in_playroom`
12
+
13
+ Resolves an Arbor PascalCase component name into a Playroom share URL with
14
+ the canonical default snippet pre-loaded.
15
+
16
+ **Input:**
17
+
18
+ ```json
19
+ { "componentName": "Button" }
20
+ ```
21
+
22
+ **Output:** a `text` content item containing a JSON-stringified
23
+ `CanonicalLookupResult`:
24
+
25
+ ```json
26
+ {
27
+ "coverage": "mapped",
28
+ "arborComponentName": "Button",
29
+ "snippet": "<Button>Save changes</Button>",
30
+ "url": "https://arbor.linktr.ee/playroom/#?code=PEJ1dHRvbj5TYXZlIGNoYW5nZXM8L0J1dHRvbj4="
31
+ }
32
+ ```
33
+
34
+ `coverage` is one of:
35
+
36
+ - `mapped` — the component appears in `figma-mappings.ts` AND has a
37
+ canonical entry in `compositions.ts`. High confidence.
38
+ - `fallback` — best-effort name matching (e.g. "Header Bar" → `HeaderBar`).
39
+ Used by the Figma plugin's selection-driven path; the by-name MCP tool
40
+ almost always returns `mapped` or `not_found`.
41
+ - `not_found` — the URL points at the Playroom homepage; agents should
42
+ surface this to the human rather than silently following the link.
43
+
44
+ ## Install
45
+
46
+ The package is published publicly to npm as `@linktr.ee/arbor-mcp`. The
47
+ expected use is `npx`-style spawning by an MCP client — see the wiring
48
+ section below. No global install required.
49
+
50
+ ```bash
51
+ # Smoke-check the latest release
52
+ npx -y @linktr.ee/arbor-mcp --help 2>&1 | head -5
53
+ ```
54
+
55
+ If you're working inside the Arbor monorepo, build the local source
56
+ instead so you're testing your changes:
57
+
58
+ ```bash
59
+ yarn install
60
+ yarn workspace @linktr.ee/arbor-mcp build
61
+ ```
62
+
63
+ That produces a single bundled ESM file at
64
+ `packages/arbor-mcp/dist/index.js` (with shebang) ready to be spawned by
65
+ any MCP client.
66
+
67
+ ## Wire it into an MCP client
68
+
69
+ ### Claude Code / Claude Desktop / Cursor (`.mcp.json` or equivalent)
70
+
71
+ The recommended setup uses the public npm package — no clone required:
72
+
73
+ ```jsonc
74
+ {
75
+ "mcpServers": {
76
+ "arbor": {
77
+ "command": "npx",
78
+ "args": ["-y", "@linktr.ee/arbor-mcp"]
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ If you're hacking on the server inside the Arbor workspace, point at the
85
+ local build instead so changes pick up without republishing:
86
+
87
+ ```jsonc
88
+ {
89
+ "mcpServers": {
90
+ "arbor": {
91
+ "command": "node",
92
+ "args": ["./packages/arbor-mcp/dist/index.js"]
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ For portability across clients that don't substitute path variables
99
+ (Claude Desktop, most CLI MCP clients), prefer absolute paths over
100
+ `${workspaceFolder}`.
101
+
102
+ ### Verify the connection
103
+
104
+ After restarting your MCP client, the `arbor.open_in_playroom` tool should
105
+ appear in the available-tools list. Ask the agent something like:
106
+
107
+ > Use the arbor MCP server to open Button in Playroom.
108
+
109
+ The agent will call the tool and return the URL.
110
+
111
+ ## Develop
112
+
113
+ ```bash
114
+ # Run the server against tsx directly (no build step) — useful for
115
+ # iterating on tool handlers.
116
+ yarn workspace @linktr.ee/arbor-mcp dev
117
+
118
+ # Run the unit tests (covers tool metadata, input validation, lookup
119
+ # happy/not-found paths, and the 9-of-9 figma-mappings coverage gate).
120
+ yarn workspace @linktr.ee/arbor-mcp test
121
+
122
+ # Smoke-test the full JSON-RPC handshake end-to-end.
123
+ printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"manual","version":"0.0.0"}}}\n{"jsonrpc":"2.0","id":2,"method":"tools/list"}\n' | node dist/index.js
124
+ ```
125
+
126
+ ## Architecture
127
+
128
+ ```
129
+ packages/arbor-mcp/
130
+ ├── src/
131
+ │ ├── index.ts # entrypoint: connects stdio transport
132
+ │ ├── server.ts # creates the Server + registers handlers
133
+ │ └── tools/
134
+ │ └── open-in-playroom.ts # tool metadata + dispatch function
135
+ ├── tests/
136
+ │ └── open-in-playroom.test.ts # node --test, validation + coverage
137
+ ├── build.mjs # esbuild bundle to dist/index.js
138
+ └── tsconfig.json # rootDir: ../.. for cross-package imports
139
+ ```
140
+
141
+ The `arbor.open_in_playroom` handler delegates to `lookupByArborName` in
142
+ `apps/playroom/src/canonical-snippet-lookup.ts` — the same module the
143
+ Figma plugin's "Open in Playroom" relaunch button uses. This keeps the
144
+ agent-facing surface and the designer-facing surface in lockstep.
145
+
146
+ ## Why bundle vs. emit `tsc` files?
147
+
148
+ `tsc` would emit one `.js` per `.ts` and preserve cross-package directory
149
+ structure under `dist/`. Node's ESM resolver doesn't add `.js` extensions
150
+ to extensionless imports (the workspace TS source uses extensionless
151
+ imports because `moduleResolution: bundler`), so the multi-file output
152
+ fails to resolve at runtime. Bundling with esbuild flattens the
153
+ dependency graph into a single self-contained file. `tsc --noEmit` still
154
+ runs in the build script for type checking.
155
+
156
+ ## Future tools
157
+
158
+ When adding a second tool, follow the existing pattern:
159
+
160
+ 1. New file under `src/tools/<name>.ts` exporting `TOOL_NAME`,
161
+ `TOOL_DESCRIPTION`, `TOOL_INPUT_SCHEMA`, and a `run<Name>` handler.
162
+ 2. Register it in `src/server.ts` alongside the existing entry.
163
+ 3. Mirror the test file shape under `tests/`.