@ourroadmaps/mcp 0.12.0 → 0.13.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 +30 -0
  2. package/dist/index.js +134 -5
  3. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # @ourroadmaps/mcp
2
+
3
+ MCP server for OurRoadmaps - manage roadmaps, features, and ideas from Claude Code.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ claude mcp add roadmaps \
9
+ --env ROADMAPS_API_URL=https://api.ourroadmaps.com \
10
+ --env ROADMAPS_API_KEY=your-key-here \
11
+ -- npx -y @ourroadmaps/mcp
12
+ ```
13
+
14
+ Get your API key from **Organization Settings → API Keys** in the web app.
15
+
16
+ ## Development
17
+
18
+ This package is published to npm. Changes require publishing:
19
+
20
+ ```bash
21
+ bun run build
22
+ # bump version in package.json
23
+ npm publish
24
+ ```
25
+
26
+ The server runs from npm, not local files. Users fetch via `npx -y @ourroadmaps/mcp`.
27
+
28
+ ## Available Tools
29
+
30
+ See the main [README](../../README.md#mcp-server) for the full list of tools.
package/dist/index.js CHANGED
@@ -794,6 +794,34 @@ class ApiClient {
794
794
  method: "DELETE"
795
795
  });
796
796
  }
797
+ async getDesignWalkthroughUploadUrl(data) {
798
+ const response = await this.request("/v1/designs/walkthrough/upload-url", {
799
+ method: "POST",
800
+ body: JSON.stringify(data)
801
+ });
802
+ return response.data;
803
+ }
804
+ async updateDesignWalkthrough(roadmapId, walkthroughVideoUrl) {
805
+ const response = await this.request(`/v1/designs/roadmaps/${roadmapId}/design`, {
806
+ method: "PATCH",
807
+ body: JSON.stringify({ walkthroughVideoUrl })
808
+ });
809
+ return response.data;
810
+ }
811
+ async getReleaseWalkthroughUploadUrl(data) {
812
+ const response = await this.request("/v1/releases/walkthrough/upload-url", {
813
+ method: "POST",
814
+ body: JSON.stringify(data)
815
+ });
816
+ return response.data;
817
+ }
818
+ async updateReleaseWalkthrough(roadmapId, walkthroughVideoUrl) {
819
+ const response = await this.request(`/v1/releases/roadmaps/${roadmapId}/release`, {
820
+ method: "PATCH",
821
+ body: JSON.stringify({ walkthroughVideoUrl })
822
+ });
823
+ return response.data;
824
+ }
797
825
  async getProductDesignUploadUrl(productId, data) {
798
826
  const response = await this.request(`/v1/products/${productId}/design-media/upload-url`, {
799
827
  method: "POST",
@@ -922,6 +950,8 @@ function registerAllTools(server) {
922
950
  registerUploadProductDesignMedia(server);
923
951
  registerUpdateProductDesignMedia(server);
924
952
  registerDeleteProductDesignMedia(server);
953
+ registerUploadDesignWalkthrough(server);
954
+ registerUploadReleaseWalkthrough(server);
925
955
  }
926
956
  function registerSearchRoadmaps(server) {
927
957
  server.registerTool("search_roadmaps", {
@@ -1290,7 +1320,8 @@ function registerUpdateRoadmapItem(server) {
1290
1320
  designDescription: z10.string().nullable().optional().describe("Description for the Design phase"),
1291
1321
  planDescription: z10.string().nullable().optional().describe("Description for the Planning phase"),
1292
1322
  buildDescription: z10.string().nullable().optional().describe("Description for the Build phase"),
1293
- releaseDescription: z10.string().nullable().optional().describe("Description for the Release phase")
1323
+ releaseDescription: z10.string().nullable().optional().describe("Description for the Release phase"),
1324
+ prompt: z10.string().nullable().optional().describe("Build prompt for the roadmap item")
1294
1325
  }
1295
1326
  }, async ({
1296
1327
  id,
@@ -1303,7 +1334,8 @@ function registerUpdateRoadmapItem(server) {
1303
1334
  designDescription,
1304
1335
  planDescription,
1305
1336
  buildDescription,
1306
- releaseDescription
1337
+ releaseDescription,
1338
+ prompt
1307
1339
  }) => {
1308
1340
  const client2 = getApiClient();
1309
1341
  const updates = {};
@@ -1329,9 +1361,17 @@ function registerUpdateRoadmapItem(server) {
1329
1361
  await client2.updatePlanDescription(id, planDescription);
1330
1362
  phaseUpdates.planDescription = planDescription;
1331
1363
  }
1332
- if (buildDescription !== undefined) {
1333
- await client2.updateBuildDescription(id, { description: buildDescription });
1334
- phaseUpdates.buildDescription = buildDescription;
1364
+ if (buildDescription !== undefined || prompt !== undefined) {
1365
+ const buildData = {};
1366
+ if (buildDescription !== undefined)
1367
+ buildData.description = buildDescription;
1368
+ if (prompt !== undefined)
1369
+ buildData.prompt = prompt;
1370
+ await client2.updateBuildDescription(id, buildData);
1371
+ if (buildDescription !== undefined)
1372
+ phaseUpdates.buildDescription = buildDescription;
1373
+ if (prompt !== undefined)
1374
+ phaseUpdates.prompt = prompt;
1335
1375
  }
1336
1376
  if (releaseDescription !== undefined) {
1337
1377
  await client2.updateReleaseDescription(id, releaseDescription);
@@ -2685,6 +2725,95 @@ function registerDeleteProductDesignMedia(server) {
2685
2725
  };
2686
2726
  });
2687
2727
  }
2728
+ function isVideoContentType(contentType) {
2729
+ return contentType?.startsWith("video/") ?? false;
2730
+ }
2731
+ function registerUploadDesignWalkthrough(server) {
2732
+ server.registerTool("upload_design_walkthrough", {
2733
+ description: "Upload a walkthrough video to a roadmap item's design phase. Returns a curl command to execute for the upload.",
2734
+ inputSchema: {
2735
+ roadmapId: z10.string().describe("The UUID of the roadmap item"),
2736
+ filePath: z10.string().describe("Absolute path to the video file on disk")
2737
+ }
2738
+ }, async ({ roadmapId, filePath }) => {
2739
+ const client2 = getApiClient();
2740
+ const filename = filePath.split("/").pop() || "video.mp4";
2741
+ const contentType = inferContentType(filename);
2742
+ if (!isVideoContentType(contentType)) {
2743
+ return {
2744
+ content: [
2745
+ {
2746
+ type: "text",
2747
+ text: JSON.stringify({
2748
+ error: "Unsupported video format. Use MP4, WebM, or MOV."
2749
+ })
2750
+ }
2751
+ ]
2752
+ };
2753
+ }
2754
+ const { uploadUrl, videoUrl } = await client2.getDesignWalkthroughUploadUrl({
2755
+ filename,
2756
+ contentType
2757
+ });
2758
+ await client2.updateDesignWalkthrough(roadmapId, videoUrl);
2759
+ const curlCommand = `curl -X PUT -H "Content-Type: ${contentType}" --data-binary @"${filePath}" "${uploadUrl}"`;
2760
+ return {
2761
+ content: [
2762
+ {
2763
+ type: "text",
2764
+ text: JSON.stringify({
2765
+ videoUrl,
2766
+ curlCommand,
2767
+ instructions: "Execute the curlCommand to upload the video. The design record has been updated and will display once uploaded."
2768
+ }, null, 2)
2769
+ }
2770
+ ]
2771
+ };
2772
+ });
2773
+ }
2774
+ function registerUploadReleaseWalkthrough(server) {
2775
+ server.registerTool("upload_release_walkthrough", {
2776
+ description: "Upload a walkthrough video to a roadmap item's release phase. Returns a curl command to execute for the upload.",
2777
+ inputSchema: {
2778
+ roadmapId: z10.string().describe("The UUID of the roadmap item"),
2779
+ filePath: z10.string().describe("Absolute path to the video file on disk")
2780
+ }
2781
+ }, async ({ roadmapId, filePath }) => {
2782
+ const client2 = getApiClient();
2783
+ const filename = filePath.split("/").pop() || "video.mp4";
2784
+ const contentType = inferContentType(filename);
2785
+ if (!isVideoContentType(contentType)) {
2786
+ return {
2787
+ content: [
2788
+ {
2789
+ type: "text",
2790
+ text: JSON.stringify({
2791
+ error: "Unsupported video format. Use MP4, WebM, or MOV."
2792
+ })
2793
+ }
2794
+ ]
2795
+ };
2796
+ }
2797
+ const { uploadUrl, videoUrl } = await client2.getReleaseWalkthroughUploadUrl({
2798
+ filename,
2799
+ contentType
2800
+ });
2801
+ await client2.updateReleaseWalkthrough(roadmapId, videoUrl);
2802
+ const curlCommand = `curl -X PUT -H "Content-Type: ${contentType}" --data-binary @"${filePath}" "${uploadUrl}"`;
2803
+ return {
2804
+ content: [
2805
+ {
2806
+ type: "text",
2807
+ text: JSON.stringify({
2808
+ videoUrl,
2809
+ curlCommand,
2810
+ instructions: "Execute the curlCommand to upload the video. The release record has been updated and will display once uploaded."
2811
+ }, null, 2)
2812
+ }
2813
+ ]
2814
+ };
2815
+ });
2816
+ }
2688
2817
 
2689
2818
  // src/index.ts
2690
2819
  async function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ourroadmaps/mcp",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "MCP server for OurRoadmaps - manage roadmaps, features, and ideas from Claude Code",
5
5
  "type": "module",
6
6
  "bin": {