@ourroadmaps/mcp 0.7.5 → 0.9.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 (2) hide show
  1. package/dist/index.js +147 -34
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -380,6 +380,23 @@ var featureLinkSchema = z8.object({
380
380
  }),
381
381
  createdAt: z8.string()
382
382
  });
383
+ var phaseDesignSchema = z8.object({
384
+ id: z8.string().uuid(),
385
+ description: z8.string().nullable()
386
+ });
387
+ var phasePlanSchema = z8.object({
388
+ id: z8.string().uuid(),
389
+ description: z8.string().nullable()
390
+ });
391
+ var phaseBuildSchema = z8.object({
392
+ id: z8.string().uuid(),
393
+ description: z8.string().nullable(),
394
+ prompt: z8.string().nullable()
395
+ });
396
+ var phaseReleaseSchema = z8.object({
397
+ id: z8.string().uuid(),
398
+ description: z8.string().nullable()
399
+ });
383
400
  var roadmapDetailSchema = roadmapSchema.extend({
384
401
  prd: prdSchema.nullable(),
385
402
  wireframes: z8.array(wireframeSchema),
@@ -387,7 +404,11 @@ var roadmapDetailSchema = roadmapSchema.extend({
387
404
  brainstormNotes: z8.string().nullable(),
388
405
  featureLinks: z8.array(featureLinkSchema),
389
406
  epics: z8.array(epicWithStoriesSchema),
390
- stories: z8.array(storySchema)
407
+ stories: z8.array(storySchema),
408
+ design: phaseDesignSchema.nullable(),
409
+ plan: phasePlanSchema.nullable(),
410
+ build: phaseBuildSchema.nullable(),
411
+ release: phaseReleaseSchema.nullable()
391
412
  });
392
413
  var roadmapListSchema = z8.array(roadmapSchema);
393
414
  // ../../packages/shared/src/schemas/scenario.ts
@@ -461,9 +482,15 @@ class ApiClient {
461
482
  }
462
483
  return await response.json();
463
484
  }
464
- async listRoadmaps() {
465
- const response = await this.request("/v1/roadmaps");
466
- return response.data;
485
+ async listRoadmaps(params) {
486
+ const searchParams = new URLSearchParams;
487
+ if (params?.limit)
488
+ searchParams.set("limit", String(params.limit));
489
+ if (params?.offset)
490
+ searchParams.set("offset", String(params.offset));
491
+ const query = searchParams.toString();
492
+ const path = query ? `/v1/roadmaps?${query}` : "/v1/roadmaps";
493
+ return await this.request(path);
467
494
  }
468
495
  async getRoadmap(id) {
469
496
  const response = await this.request(`/v1/roadmaps/${id}`);
@@ -692,6 +719,14 @@ class ApiClient {
692
719
  const response = await this.request(`/v1/history?${searchParams.toString()}`);
693
720
  return response.data;
694
721
  }
722
+ async getHistorySummary(params) {
723
+ const searchParams = new URLSearchParams({
724
+ startDate: params.startDate,
725
+ endDate: params.endDate
726
+ });
727
+ const response = await this.request(`/v1/history/summary?${searchParams}`);
728
+ return response.data;
729
+ }
695
730
  async saveStories(roadmapId, data) {
696
731
  const response = await this.request(`/v1/roadmaps/${roadmapId}/stories`, {
697
732
  method: "POST",
@@ -699,6 +734,34 @@ class ApiClient {
699
734
  });
700
735
  return response.data;
701
736
  }
737
+ async updateDesignDescription(roadmapId, description) {
738
+ const response = await this.request(`/v1/designs/roadmaps/${roadmapId}/design`, {
739
+ method: "PATCH",
740
+ body: JSON.stringify({ description })
741
+ });
742
+ return response.data;
743
+ }
744
+ async updatePlanDescription(roadmapId, description) {
745
+ const response = await this.request(`/v1/plans/roadmaps/${roadmapId}/plan`, {
746
+ method: "PATCH",
747
+ body: JSON.stringify({ description })
748
+ });
749
+ return response.data;
750
+ }
751
+ async updateBuildDescription(roadmapId, data) {
752
+ const response = await this.request(`/v1/builds/roadmaps/${roadmapId}/build`, {
753
+ method: "PATCH",
754
+ body: JSON.stringify(data)
755
+ });
756
+ return response.data;
757
+ }
758
+ async updateReleaseDescription(roadmapId, description) {
759
+ const response = await this.request(`/v1/releases/roadmaps/${roadmapId}/release`, {
760
+ method: "PATCH",
761
+ body: JSON.stringify({ description })
762
+ });
763
+ return response.data;
764
+ }
702
765
  }
703
766
  var client = null;
704
767
  function getApiClient() {
@@ -747,6 +810,7 @@ function registerAllTools(server) {
747
810
  registerDeleteAudience(server);
748
811
  registerListStatusUpdates(server);
749
812
  registerGetHistory(server);
813
+ registerGetHistorySummary(server);
750
814
  registerCreateStatusUpdate(server);
751
815
  registerSaveStories(server);
752
816
  }
@@ -756,15 +820,20 @@ function registerSearchRoadmaps(server) {
756
820
  inputSchema: {
757
821
  query: z10.string().optional().describe("Search query to match against title or description"),
758
822
  status: roadmapStatusSchema.optional().describe("Filter by status"),
759
- horizon: horizonSchema.optional().describe("Filter by planning horizon")
823
+ horizon: horizonSchema.optional().describe("Filter by planning horizon"),
824
+ limit: z10.number().int().min(1).max(100).optional().describe("Max items to return (default 10)"),
825
+ offset: z10.number().int().min(0).optional().describe("Number of items to skip (default 0)")
760
826
  }
761
827
  }, async ({
762
828
  query,
763
829
  status,
764
- horizon
830
+ horizon,
831
+ limit,
832
+ offset
765
833
  }) => {
766
834
  const client2 = getApiClient();
767
- let roadmaps = await client2.listRoadmaps();
835
+ const response = await client2.listRoadmaps({ limit, offset });
836
+ let roadmaps = response.items;
768
837
  if (query) {
769
838
  const q = query.toLowerCase();
770
839
  roadmaps = roadmaps.filter((r) => r.title.toLowerCase().includes(q));
@@ -779,15 +848,18 @@ function registerSearchRoadmaps(server) {
779
848
  content: [
780
849
  {
781
850
  type: "text",
782
- text: JSON.stringify(roadmaps.map((r) => ({
783
- id: r.id,
784
- title: r.title,
785
- status: r.status,
786
- horizon: r.horizon,
787
- value: r.value,
788
- effort: r.effort,
789
- order: r.order
790
- })), null, 2)
851
+ text: JSON.stringify({
852
+ items: roadmaps.map((r) => ({
853
+ id: r.id,
854
+ title: r.title,
855
+ status: r.status,
856
+ horizon: r.horizon,
857
+ value: r.value,
858
+ effort: r.effort,
859
+ order: r.order
860
+ })),
861
+ pagination: response.pagination
862
+ }, null, 2)
791
863
  }
792
864
  ]
793
865
  };
@@ -835,6 +907,11 @@ function registerGetRoadmap(server) {
835
907
  })),
836
908
  epics: roadmap2.epics,
837
909
  stories: roadmap2.stories,
910
+ designDescription: roadmap2.design?.description ?? null,
911
+ planDescription: roadmap2.plan?.description ?? null,
912
+ buildDescription: roadmap2.build?.description ?? null,
913
+ releaseDescription: roadmap2.release?.description ?? null,
914
+ prompt: roadmap2.build?.prompt ?? roadmap2.prompt ?? null,
838
915
  createdAt: roadmap2.createdAt
839
916
  }, null, 2)
840
917
  }
@@ -954,28 +1031,20 @@ function registerGetContext(server) {
954
1031
  - Audiences: Who the product serves (stakeholders and user personas) with their preferences
955
1032
  - Scenarios: User workflows and how they accomplish goals
956
1033
  - Features: Capabilities and functionality areas organized hierarchically
957
- - Roadmap Summary: Count of items by status and horizon for planning overview
1034
+ - Roadmap Summary: Total count of roadmap items
958
1035
 
959
1036
  Use this as your FIRST call when starting work on a roadmap to understand the full context.`,
960
1037
  inputSchema: {}
961
1038
  }, async () => {
962
1039
  const client2 = getApiClient();
963
- const [strategy, products, audiences, scenarios, features, roadmaps] = await Promise.all([
1040
+ const [strategy, products, audiences, scenarios, features, roadmapsResponse] = await Promise.all([
964
1041
  client2.getStrategy(),
965
1042
  client2.listProducts(),
966
1043
  client2.listAudiences(),
967
1044
  client2.listScenarios(),
968
1045
  client2.listFeatures(),
969
- client2.listRoadmaps()
1046
+ client2.listRoadmaps({ limit: 1 })
970
1047
  ]);
971
- const statusCounts = {};
972
- const horizonCounts = {};
973
- for (const r of roadmaps) {
974
- const status = r.status ?? "unknown";
975
- const horizon = r.horizon ?? "unknown";
976
- statusCounts[status] = (statusCounts[status] || 0) + 1;
977
- horizonCounts[horizon] = (horizonCounts[horizon] || 0) + 1;
978
- }
979
1048
  return {
980
1049
  content: [
981
1050
  {
@@ -1013,9 +1082,7 @@ Use this as your FIRST call when starting work on a roadmap to understand the fu
1013
1082
  parentId: f.parentId
1014
1083
  })),
1015
1084
  roadmapSummary: {
1016
- total: roadmaps.length,
1017
- byStatus: statusCounts,
1018
- byHorizon: horizonCounts
1085
+ total: roadmapsResponse.pagination.total
1019
1086
  }
1020
1087
  }, null, 2)
1021
1088
  }
@@ -1110,7 +1177,11 @@ function registerUpdateRoadmapItem(server) {
1110
1177
  horizon: horizonSchema.optional().describe("New planning horizon"),
1111
1178
  value: z10.number().int().min(1).max(3).nullable().optional().describe("Value rating (1-3 stars, where 3 is highest value)"),
1112
1179
  effort: effortSizeSchema.nullable().optional().describe("Effort estimate (xs=extra small, s=small, m=medium, l=large, xl=extra large)"),
1113
- order: z10.number().int().min(0).optional().describe("Sort order for prioritization (lower numbers appear first)")
1180
+ order: z10.number().int().min(0).optional().describe("Sort order for prioritization (lower numbers appear first)"),
1181
+ designDescription: z10.string().nullable().optional().describe("Description for the Design phase"),
1182
+ planDescription: z10.string().nullable().optional().describe("Description for the Planning phase"),
1183
+ buildDescription: z10.string().nullable().optional().describe("Description for the Build phase"),
1184
+ releaseDescription: z10.string().nullable().optional().describe("Description for the Release phase")
1114
1185
  }
1115
1186
  }, async ({
1116
1187
  id,
@@ -1119,7 +1190,11 @@ function registerUpdateRoadmapItem(server) {
1119
1190
  horizon,
1120
1191
  value,
1121
1192
  effort,
1122
- order
1193
+ order,
1194
+ designDescription,
1195
+ planDescription,
1196
+ buildDescription,
1197
+ releaseDescription
1123
1198
  }) => {
1124
1199
  const client2 = getApiClient();
1125
1200
  const updates = {};
@@ -1136,6 +1211,23 @@ function registerUpdateRoadmapItem(server) {
1136
1211
  if (order !== undefined)
1137
1212
  updates.order = order;
1138
1213
  const roadmap2 = await client2.updateRoadmap(id, updates);
1214
+ const phaseUpdates = {};
1215
+ if (designDescription !== undefined) {
1216
+ await client2.updateDesignDescription(id, designDescription);
1217
+ phaseUpdates.designDescription = designDescription;
1218
+ }
1219
+ if (planDescription !== undefined) {
1220
+ await client2.updatePlanDescription(id, planDescription);
1221
+ phaseUpdates.planDescription = planDescription;
1222
+ }
1223
+ if (buildDescription !== undefined) {
1224
+ await client2.updateBuildDescription(id, { description: buildDescription });
1225
+ phaseUpdates.buildDescription = buildDescription;
1226
+ }
1227
+ if (releaseDescription !== undefined) {
1228
+ await client2.updateReleaseDescription(id, releaseDescription);
1229
+ phaseUpdates.releaseDescription = releaseDescription;
1230
+ }
1139
1231
  return {
1140
1232
  content: [
1141
1233
  {
@@ -1150,7 +1242,8 @@ function registerUpdateRoadmapItem(server) {
1150
1242
  value: roadmap2.value,
1151
1243
  effort: roadmap2.effort,
1152
1244
  order: roadmap2.order
1153
- }
1245
+ },
1246
+ phaseDescriptionsUpdated: phaseUpdates
1154
1247
  }, null, 2)
1155
1248
  }
1156
1249
  ]
@@ -2030,7 +2123,7 @@ function registerListStatusUpdates(server) {
2030
2123
  }
2031
2124
  function registerGetHistory(server) {
2032
2125
  server.registerTool("get_history", {
2033
- description: "Get history events for a date range. Returns all changes (created, updated, deleted) to roadmaps, features, ideas, etc. Use this to gather data for generating status reports.",
2126
+ description: "Get raw history events for a date range. Returns full event details including payloads. " + "Use entityType or entityId filters to narrow results. For status reports, prefer " + "get_history_summary to avoid context overflow.",
2034
2127
  inputSchema: {
2035
2128
  startDate: z10.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Start date in YYYY-MM-DD format"),
2036
2129
  endDate: z10.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("End date in YYYY-MM-DD format"),
@@ -2062,6 +2155,26 @@ function registerGetHistory(server) {
2062
2155
  };
2063
2156
  });
2064
2157
  }
2158
+ function registerGetHistorySummary(server) {
2159
+ server.registerTool("get_history_summary", {
2160
+ description: "Get a summary of history events for a date range. Returns counts by entity type, " + "list of changed entities with titles, and total event count. Use this for status " + "report generation instead of get_history to avoid context overflow.",
2161
+ inputSchema: {
2162
+ startDate: z10.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("Start date in YYYY-MM-DD format"),
2163
+ endDate: z10.string().regex(/^\d{4}-\d{2}-\d{2}$/).describe("End date in YYYY-MM-DD format")
2164
+ }
2165
+ }, async ({ startDate, endDate }) => {
2166
+ const client2 = getApiClient();
2167
+ const summary = await client2.getHistorySummary({ startDate, endDate });
2168
+ return {
2169
+ content: [
2170
+ {
2171
+ type: "text",
2172
+ text: JSON.stringify(summary, null, 2)
2173
+ }
2174
+ ]
2175
+ };
2176
+ });
2177
+ }
2065
2178
  function registerCreateStatusUpdate(server) {
2066
2179
  server.registerTool("create_status_update", {
2067
2180
  description: "Create a new status report. Use this after generating the report content from history events.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ourroadmaps/mcp",
3
- "version": "0.7.5",
3
+ "version": "0.9.0",
4
4
  "description": "MCP server for OurRoadmaps - manage roadmaps, features, and ideas from Claude Code",
5
5
  "type": "module",
6
6
  "bin": {