@roadmapperai/mcp 0.3.0 → 0.4.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 +9 -3
  2. package/package.json +1 -1
  3. package/server.mjs +70 -38
package/README.md CHANGED
@@ -31,15 +31,21 @@ Add to your `~/.config/claude-code/config.json` (or the equivalent
31
31
  "command": "npx",
32
32
  "args": ["-y", "@roadmapperai/mcp"],
33
33
  "env": {
34
- "SUPABASE_URL": "https://tqfhcpoblluegsbkcaqq.supabase.co",
35
- "SUPABASE_PUBLISHABLE_KEY": "sb_publishable_oT9...",
36
- "SUPABASE_WORKSPACE_ID": "<your workspace id>"
34
+ "ROADMAPPER_BACKEND_URL": "https://api.roadmapperai.com",
35
+ "ROADMAPPER_PUBLISHABLE_KEY": "sb_publishable_...",
36
+ "ROADMAPPER_WORKSPACE_ID": "<your workspace id>",
37
+ "ROADMAPPER_API_KEY": "<rmpr_... — optional, enables writes>"
37
38
  }
38
39
  }
39
40
  }
40
41
  }
41
42
  ```
42
43
 
44
+ The `ROADMAPPER_API_KEY` env var is optional. Without it, the install runs
45
+ read-only (list/get/suggest tools). Mint a key in the dashboard at Settings →
46
+ MCP activity → API keys and add it to the `env` block to unlock write tools
47
+ (propose / link / grade).
48
+
43
49
  Get your workspace ID from the dashboard's URL bar
44
50
  (`dashboard.roadmapperai.com/settings` → workspace section) or from the
45
51
  generated config block in Settings → Connect.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roadmapperai/mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Roadmapper AI MCP server — exposes a planning surface (themes, capabilities, tasks, sprints, PRs) to coding agents via stdio JSON-RPC. Pairs with the Roadmapper AI workspace at dashboard.roadmapperai.com.",
5
5
  "keywords": [
6
6
  "mcp",
package/server.mjs CHANGED
@@ -3,42 +3,50 @@
3
3
  * Roadmapper MCP server — zero-dependency stdio JSON-RPC.
4
4
  *
5
5
  * Exposes a planning surface so an agent can read the roadmap and
6
- * (when authorized) propose tasks or stamp acceptance grades:
6
+ * (when authorized) propose tasks or stamp acceptance grades.
7
7
  *
8
- * list_themes read
9
- * list_capabilities read (optionally filtered by themeId)
10
- * list_tasks read (optionally filtered by capabilityId / status)
11
- * get_task read (full task detail, including acceptance + deps)
12
- * get_agents_md read (the planning contract)
13
- * propose_task write (requires SUPABASE_SERVICE_ROLE_KEY)
14
- * submit_acceptance_grades write (requires SUPABASE_SERVICE_ROLE_KEY)
8
+ * Customer-facing env vars (brand-named, no backend disclosure):
9
+ * ROADMAPPER_BACKEND_URL — backend project URL
10
+ * ROADMAPPER_PUBLISHABLE_KEY public client key (RLS-scoped)
11
+ * ROADMAPPER_WORKSPACE_ID — target workspace
12
+ * ROADMAPPER_API_KEY — write auth (rmpr_… token from
13
+ * Settings → MCP activity → API keys)
14
+ * ROADMAPPER_BROKER_URL — optional override for the write
15
+ * broker; defaults to BACKEND_URL/
16
+ * functions/v1/mcp-broker
15
17
  *
16
- * Data sources, in order:
17
- * 1. Local seed at src/data/roadmap.json (always read).
18
- * 2. Workspace edits via Supabase REST, when SUPABASE_URL,
19
- * SUPABASE_WORKSPACE_ID, and either SUPABASE_PUBLISHABLE_KEY or
20
- * the legacy SUPABASE_ANON_KEY are set. Edits override / extend
21
- * the seed exactly like the app does.
22
- * 3. Writes require SUPABASE_SERVICE_ROLE_KEY (bypasses RLS). Without
23
- * it the write tools return an error result and the read tools
24
- * still work.
18
+ * Legacy operator-only env vars (still accepted for CI / maintainer
19
+ * local installs; not part of the customer-facing config):
20
+ * SUPABASE_URL / SUPABASE_PUBLISHABLE_KEY / SUPABASE_ANON_KEY /
21
+ * SUPABASE_WORKSPACE_ID / SUPABASE_SERVICE_ROLE_KEY ← operator
22
+ * ROADMAPPER_ADMIN_KEY brand-named alias for SERVICE_ROLE_KEY
25
23
  *
26
- * Wire-up (Claude Code / Claude Desktop / any MCP client):
24
+ * Customer wire-up (Claude Code / Claude Desktop / Cursor):
27
25
  * {
28
26
  * "mcpServers": {
29
27
  * "roadmapper": {
30
- * "command": "node",
31
- * "args": ["/absolute/path/to/roadmap/mcp/server.mjs"],
28
+ * "command": "npx",
29
+ * "args": ["-y", "@roadmapperai/mcp"],
32
30
  * "env": {
33
- * "SUPABASE_URL": "...",
34
- * "SUPABASE_PUBLISHABLE_KEY": "sb_publishable_...",
35
- * "SUPABASE_WORKSPACE_ID": "...",
36
- * "SUPABASE_SERVICE_ROLE_KEY": "..."
31
+ * "ROADMAPPER_BACKEND_URL": "...",
32
+ * "ROADMAPPER_PUBLISHABLE_KEY": "sb_publishable_...",
33
+ * "ROADMAPPER_WORKSPACE_ID": "...",
34
+ * "ROADMAPPER_API_KEY": "rmpr_..." ← optional, enables writes
37
35
  * }
38
36
  * }
39
37
  * }
40
38
  * }
41
39
  *
40
+ * Data sources, in order:
41
+ * 1. Local seed at src/data/roadmap.json (dev only; absent in npm
42
+ * installs, where readSeed() falls back to an empty roadmap and
43
+ * data loads from the backend).
44
+ * 2. Workspace edits via REST, when BACKEND_URL + PUBLISHABLE_KEY
45
+ * + WORKSPACE_ID are set.
46
+ * 3. Writes route through ROADMAPPER_API_KEY (customer path,
47
+ * validated server-side at the broker) or ROADMAPPER_ADMIN_KEY
48
+ * (operator path, bypasses RLS).
49
+ *
42
50
  * Self-test: `node mcp/server.mjs --selftest` exercises every tool
43
51
  * against the local seed and exits 0 on success, 1 on failure. Useful
44
52
  * for verifying the install without an MCP client.
@@ -152,36 +160,60 @@ async function readAgentsMdForWorkspace() {
152
160
  return readAgentsMd();
153
161
  }
154
162
 
163
+ /**
164
+ * Resolve a config value from a primary `ROADMAPPER_*` env var,
165
+ * falling back to a legacy `SUPABASE_*` alias when the primary
166
+ * isn't set. The brand-facing customer config block ships with
167
+ * the ROADMAPPER_* names so customers never see "supabase" in
168
+ * their MCP config; the SUPABASE_* aliases stay supported so
169
+ * existing operator / CI installs don't break on upgrade.
170
+ */
171
+ function envEither(primary, ...fallbacks) {
172
+ for (const k of [primary, ...fallbacks]) {
173
+ const v = process.env[k];
174
+ if (v) return v;
175
+ }
176
+ return null;
177
+ }
178
+
155
179
  /**
156
180
  * The read key used to fetch the workspace row. Accepts the new
157
181
  * publishable key (`sb_publishable_…`) or the legacy `anon`/JWT key.
158
182
  */
159
183
  function readKey() {
160
- return (
161
- process.env.SUPABASE_PUBLISHABLE_KEY ||
162
- process.env.SUPABASE_ANON_KEY ||
163
- null
184
+ return envEither(
185
+ "ROADMAPPER_PUBLISHABLE_KEY",
186
+ "SUPABASE_PUBLISHABLE_KEY",
187
+ "SUPABASE_ANON_KEY"
164
188
  );
165
189
  }
166
190
 
167
191
  function supabaseConfig() {
192
+ const url = envEither("ROADMAPPER_BACKEND_URL", "SUPABASE_URL");
168
193
  return {
169
- url: process.env.SUPABASE_URL || null,
194
+ url,
170
195
  readKey: readKey(),
171
- writeKey: process.env.SUPABASE_SERVICE_ROLE_KEY || null,
172
- workspaceId: process.env.SUPABASE_WORKSPACE_ID || null,
196
+ // Operator path: a service-role-equivalent key. ROADMAPPER_ADMIN_KEY
197
+ // is the brand-facing name; SUPABASE_SERVICE_ROLE_KEY is the legacy
198
+ // alias used by CI and the maintainer's local workspace.
199
+ writeKey: envEither(
200
+ "ROADMAPPER_ADMIN_KEY",
201
+ "SUPABASE_SERVICE_ROLE_KEY"
202
+ ),
203
+ workspaceId: envEither(
204
+ "ROADMAPPER_WORKSPACE_ID",
205
+ "SUPABASE_WORKSPACE_ID"
206
+ ),
173
207
  // ROADMAPPER_API_KEY is the customer-facing path: a per-workspace
174
208
  // token (rmpr_…) minted from the dashboard. When set, write tools
175
209
  // route through the mcp-broker Edge Function instead of needing
176
210
  // a service-role key on the customer's machine. The broker URL
177
- // defaults to the public Supabase project's edge endpoint but is
178
- // overridable for self-hosted deployments / staging.
211
+ // defaults to the project's edge endpoint but is overridable for
212
+ // self-hosted deployments / staging.
179
213
  apiKey: process.env.ROADMAPPER_API_KEY || null,
180
214
  brokerUrl:
181
215
  process.env.ROADMAPPER_BROKER_URL ||
182
- (process.env.SUPABASE_URL
183
- ? `${process.env.SUPABASE_URL.replace(/\/$/, "")}/functions/v1/mcp-broker`
184
- : null),
216
+ (url ? `${url.replace(/\/$/, "")}/functions/v1/mcp-broker` : null),
185
217
  };
186
218
  }
187
219
 
@@ -408,7 +440,7 @@ async function rpcCall(fn, body) {
408
440
  // injects it before calling rpcCall so the override path works.
409
441
  if (!url || !body?.p_workspace_id) {
410
442
  throw new Error(
411
- "Write tools require SUPABASE_URL in env and a resolvable workspaceId (either SUPABASE_WORKSPACE_ID env or workspaceId arg)."
443
+ "Write tools require ROADMAPPER_BACKEND_URL in env and a resolvable workspaceId (either ROADMAPPER_WORKSPACE_ID env or workspaceId arg)."
412
444
  );
413
445
  }
414
446
 
@@ -442,7 +474,7 @@ async function rpcCall(fn, body) {
442
474
  // workspace; not what customers should ever configure.
443
475
  if (!writeKey) {
444
476
  throw new Error(
445
- "Write tools require either ROADMAPPER_API_KEY (customer path) or SUPABASE_SERVICE_ROLE_KEY (operator path)."
477
+ "Write tools require either ROADMAPPER_API_KEY (customer path) or ROADMAPPER_ADMIN_KEY (operator path)."
446
478
  );
447
479
  }
448
480
  const res = await fetch(`${url}/rest/v1/rpc/${fn}`, {