@drawpro/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 +89 -0
  2. package/dist/server.js +1545 -0
  3. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # @drawpro/mcp
2
+
3
+ Local MCP server for DrawPro. Lets Claude read and create diagrams in your
4
+ account from Claude Code, Claude Desktop, or any MCP client.
5
+
6
+ ## Setup
7
+
8
+ ```bash
9
+ claude mcp add drawpro -e DRAWPRO_TOKEN="dp_live_..." -- npx -y @drawpro/mcp
10
+ ```
11
+
12
+ Mint the token in DrawPro under **Connect to Claude Code**.
13
+
14
+ To read existing sheets, unlock the account once:
15
+
16
+ ```bash
17
+ DRAWPRO_TOKEN="dp_live_..." npx -y @drawpro/mcp login
18
+ ```
19
+
20
+ `login --forget` clears the stored key again.
21
+
22
+ ## Publishing
23
+
24
+ ```bash
25
+ npm run build --workspace @drawpro/mcp
26
+ npm publish --workspace @drawpro/mcp --access public
27
+ ```
28
+
29
+ `@drawpro/client` and `@drawpro/diagram` are workspace packages that are not
30
+ published; esbuild inlines them into `dist/server.js`. Everything else stays a
31
+ real dependency, which matters for `@phi-ag/argon2` — it loads its `.wasm` from
32
+ its own package directory, so bundling it would break unlocking.
33
+
34
+ ## Why it runs locally
35
+
36
+ DrawPro is end-to-end encrypted: content is sealed in the client, and the server
37
+ stores only ciphertext.
38
+
39
+ A hosted remote MCP server would have to receive plaintext diagrams to encrypt
40
+ them, which would hand the server exactly what the encryption exists to withhold.
41
+ Running locally keeps sealing and opening on your machine, the same as the
42
+ browser does. This is a constraint, not a preference — "make it a hosted remote
43
+ server, it's easier to onboard" would quietly undo the product's core property.
44
+
45
+ ## Why unlocking is a separate command
46
+
47
+ Writing needs only the account's public key, which the API hands out — so
48
+ creating a diagram never involves the passcode.
49
+
50
+ Reading needs the private key, which is wrapped with Argon2id over the passcode.
51
+ A stdio server cannot prompt for it, and routing it through a tool argument would
52
+ put the account's master secret into the model's context and the transcript.
53
+
54
+ So `login` handles it out of band: it prompts interactively, derives the key, and
55
+ stores **the key, not the passcode**, in the OS keychain (or a 0600 file under
56
+ `~/.drawpro` elsewhere — the same posture as `~/.ssh` private keys). The server
57
+ only reads from that store. When an account is locked, the read tools return an
58
+ instruction to run `login` and explicitly tell the model not to ask for the
59
+ passcode itself.
60
+
61
+ ## Tools
62
+
63
+ | Tool | Needs unlock | Notes |
64
+ |---|---|---|
65
+ | `list_workspaces` | for names | ids work locked; names are ciphertext |
66
+ | `list_sheets` | for names | same |
67
+ | `read_sheet` | yes | returns a readable outline, not raw scene JSON |
68
+ | `validate_spec` | no | no side effects; check before writing |
69
+ | `create_diagram` | no | returns a link to the new sheet |
70
+ | `update_diagram` | no | replaces the sheet wholesale |
71
+
72
+ `read_sheet` deliberately returns shapes and edges rather than Excalidraw JSON.
73
+ A real sheet's raw scene runs to tens of thousands of characters of coordinates,
74
+ seeds, and style; the outline is a few dozen lines carrying what the diagram
75
+ actually says.
76
+
77
+ Diagram specs describe *what connects to what*. Layout, sizing, text wrapping,
78
+ and arrow binding are derived by `@drawpro/diagram` — a spec never contains
79
+ coordinates.
80
+
81
+ ## Tests
82
+
83
+ ```bash
84
+ DRAWPRO_TOKEN=dp_live_... npx tsx packages/mcp/tests/smoke.ts
85
+ ```
86
+
87
+ Spawns the server as a subprocess and speaks MCP to it, because compiling proves
88
+ nothing about protocol behaviour. Read-only: it never creates or modifies a
89
+ sheet.