@ourroadmaps/mcp 0.24.1 → 0.25.1

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 +182 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -516,14 +516,92 @@ var updateScenarioSchema = z11.object({
516
516
  var scenarioListSchema = z11.array(scenarioSchema);
517
517
  // ../../packages/shared/src/schemas/slide.ts
518
518
  import { z as z12 } from "zod";
519
+ var SLIDE_TYPES = [
520
+ "title",
521
+ "section_header",
522
+ "bullets",
523
+ "two_column",
524
+ "comparison",
525
+ "timeline",
526
+ "image",
527
+ "quote",
528
+ "code",
529
+ "thank_you"
530
+ ];
531
+ var slideTypeSchema = z12.enum(SLIDE_TYPES);
532
+ var titleContentSchema = z12.object({
533
+ title: z12.string(),
534
+ subtitle: z12.string().optional()
535
+ });
536
+ var sectionHeaderContentSchema = z12.object({
537
+ title: z12.string(),
538
+ subtitle: z12.string().optional()
539
+ });
540
+ var bulletsContentSchema = z12.object({
541
+ title: z12.string().optional(),
542
+ items: z12.array(z12.string()).default([])
543
+ });
544
+ var twoColumnContentSchema = z12.object({
545
+ title: z12.string().optional(),
546
+ left: z12.string().default(""),
547
+ right: z12.string().default("")
548
+ });
549
+ var comparisonContentSchema = z12.object({
550
+ leftLabel: z12.string().default(""),
551
+ leftContent: z12.string().default(""),
552
+ rightLabel: z12.string().default(""),
553
+ rightContent: z12.string().default("")
554
+ });
555
+ var timelineStepSchema = z12.object({
556
+ title: z12.string(),
557
+ description: z12.string().optional()
558
+ });
559
+ var timelineContentSchema = z12.object({
560
+ title: z12.string().optional(),
561
+ steps: z12.array(timelineStepSchema).default([])
562
+ });
563
+ var imageContentSchema = z12.object({
564
+ title: z12.string().optional(),
565
+ imageUrl: z12.string().optional(),
566
+ caption: z12.string().optional()
567
+ });
568
+ var quoteContentSchema = z12.object({
569
+ quote: z12.string().default(""),
570
+ attribution: z12.string().optional()
571
+ });
572
+ var codeContentSchema = z12.object({
573
+ title: z12.string().optional(),
574
+ code: z12.string().default(""),
575
+ language: z12.string().optional(),
576
+ highlightLines: z12.array(z12.number()).optional()
577
+ });
578
+ var thankYouContentSchema = z12.object({
579
+ title: z12.string().default("Thank You"),
580
+ subtitle: z12.string().optional(),
581
+ ctaText: z12.string().optional(),
582
+ ctaUrl: z12.string().optional()
583
+ });
584
+ var typedSlideContentSchema = z12.discriminatedUnion("type", [
585
+ z12.object({ type: z12.literal("title"), ...titleContentSchema.shape }),
586
+ z12.object({ type: z12.literal("section_header"), ...sectionHeaderContentSchema.shape }),
587
+ z12.object({ type: z12.literal("bullets"), ...bulletsContentSchema.shape }),
588
+ z12.object({ type: z12.literal("two_column"), ...twoColumnContentSchema.shape }),
589
+ z12.object({ type: z12.literal("comparison"), ...comparisonContentSchema.shape }),
590
+ z12.object({ type: z12.literal("timeline"), ...timelineContentSchema.shape }),
591
+ z12.object({ type: z12.literal("image"), ...imageContentSchema.shape }),
592
+ z12.object({ type: z12.literal("quote"), ...quoteContentSchema.shape }),
593
+ z12.object({ type: z12.literal("code"), ...codeContentSchema.shape }),
594
+ z12.object({ type: z12.literal("thank_you"), ...thankYouContentSchema.shape })
595
+ ]);
519
596
  var slideContentSchema = z12.object({
520
597
  body: z12.string().optional()
521
598
  });
522
599
  var slideSchema = z12.object({
523
600
  id: z12.string().uuid(),
524
601
  variantId: z12.string().uuid(),
602
+ slideType: slideTypeSchema,
525
603
  title: z12.string(),
526
- content: slideContentSchema.nullable(),
604
+ content: z12.unknown().nullable(),
527
605
  speakerNotes: z12.string().nullable(),
528
606
  order: z12.number().int(),
529
607
  createdAt: z12.string(),
@@ -531,13 +609,12 @@ var slideSchema = z12.object({
531
609
  updatedAt: z12.string().nullable()
532
610
  });
533
611
  var createSlideSchema = z12.object({
534
- title: z12.string().optional(),
535
- content: slideContentSchema.nullable().optional(),
612
+ slideType: slideTypeSchema,
613
+ content: z12.unknown().optional(),
536
614
  speakerNotes: z12.string().nullable().optional()
537
615
  });
538
616
  var updateSlideSchema = z12.object({
539
- title: z12.string().optional(),
540
- content: slideContentSchema.nullable().optional(),
617
+ content: z12.unknown().optional(),
541
618
  speakerNotes: z12.string().nullable().optional()
542
619
  });
543
620
  var slideListSchema = z12.array(slideSchema);
@@ -1224,6 +1301,13 @@ class ApiClient {
1224
1301
  body: JSON.stringify({ items })
1225
1302
  });
1226
1303
  }
1304
+ async getSlideUploadUrl(presentationId, variantId, data) {
1305
+ const response = await this.request(`/v1/presentations/${presentationId}/variants/${variantId}/slides/upload-url`, {
1306
+ method: "POST",
1307
+ body: JSON.stringify(data)
1308
+ });
1309
+ return response.data;
1310
+ }
1227
1311
  async getVariantPresentationId(variantId) {
1228
1312
  const presentations = await this.listPresentations();
1229
1313
  for (const presentation2 of presentations.items) {
@@ -1344,6 +1428,7 @@ function registerAllTools(server) {
1344
1428
  registerUpdateSlide(server);
1345
1429
  registerDeleteSlide(server);
1346
1430
  registerReorderSlides(server);
1431
+ registerUploadSlideImage(server);
1347
1432
  }
1348
1433
  function registerGetWorkflows(server) {
1349
1434
  server.registerTool("get_workflows", {
@@ -4222,16 +4307,27 @@ function registerGetSlide(server) {
4222
4307
  }
4223
4308
  function registerCreateSlide(server) {
4224
4309
  server.registerTool("create_slide", {
4225
- description: "Create a new slide in a variant.",
4310
+ description: "Create a new slide in a variant. Slide types: title (title + subtitle), section_header (title + subtitle), bullets (title + items array), two_column (title + left/right text), comparison (leftLabel + leftContent + rightLabel + rightContent), timeline (title + steps array of {title, description}), image (title + imageUrl + caption), quote (quote + attribution), code (title + code + language), thank_you (title + subtitle).",
4226
4311
  inputSchema: {
4227
4312
  variantId: z15.string().describe("The UUID of the variant"),
4228
- title: z15.string().optional().describe("Title of the slide"),
4229
- content: z15.object({ body: z15.string().optional() }).nullable().optional().describe("Slide content with markdown body"),
4313
+ slideType: z15.enum([
4314
+ "title",
4315
+ "section_header",
4316
+ "bullets",
4317
+ "two_column",
4318
+ "comparison",
4319
+ "timeline",
4320
+ "image",
4321
+ "quote",
4322
+ "code",
4323
+ "thank_you"
4324
+ ]).default("bullets").describe("The type of slide to create"),
4325
+ content: z15.record(z15.unknown()).optional().describe('Type-specific content object. For bullets: {title, items: ["..."]}. For title: {title, subtitle}. For two_column: {title, left, right}. For quote: {quote, attribution}. Etc.'),
4230
4326
  speakerNotes: z15.string().nullable().optional().describe("Speaker notes for the slide")
4231
4327
  }
4232
4328
  }, async ({
4233
4329
  variantId,
4234
- title,
4330
+ slideType,
4235
4331
  content,
4236
4332
  speakerNotes
4237
4333
  }) => {
@@ -4248,7 +4344,7 @@ function registerCreateSlide(server) {
4248
4344
  };
4249
4345
  }
4250
4346
  const slide2 = await client2.createSlide(presentationId, variantId, {
4251
- title,
4347
+ slideType: slideType || "bullets",
4252
4348
  content,
4253
4349
  speakerNotes
4254
4350
  });
@@ -4377,6 +4473,82 @@ function registerReorderSlides(server) {
4377
4473
  };
4378
4474
  });
4379
4475
  }
4476
+ function registerUploadSlideImage(server) {
4477
+ server.registerTool("upload_slide_image", {
4478
+ description: 'Upload an image to a slide. Gets a presigned URL and returns a curl command to execute for the upload, then updates the slide content with the image URL. The slide must be of type "image".',
4479
+ inputSchema: {
4480
+ variantId: z15.string().describe("The UUID of the variant"),
4481
+ slideId: z15.string().describe("The UUID of the slide to add the image to"),
4482
+ filePath: z15.string().describe("Absolute path to the image file on disk")
4483
+ }
4484
+ }, async ({
4485
+ variantId,
4486
+ slideId,
4487
+ filePath
4488
+ }) => {
4489
+ const client2 = getApiClient();
4490
+ const presentationId = await client2.getVariantPresentationId(variantId);
4491
+ if (!presentationId) {
4492
+ return {
4493
+ content: [
4494
+ {
4495
+ type: "text",
4496
+ text: JSON.stringify({ error: "Variant not found" }, null, 2)
4497
+ }
4498
+ ]
4499
+ };
4500
+ }
4501
+ const filename = filePath.split("/").pop() || "image.png";
4502
+ const contentType = inferContentType(filename);
4503
+ if (!contentType || !contentType.startsWith("image/")) {
4504
+ return {
4505
+ content: [
4506
+ {
4507
+ type: "text",
4508
+ text: JSON.stringify({
4509
+ error: "Invalid file type. Slide images only accept image files (png, jpeg, gif, webp)."
4510
+ })
4511
+ }
4512
+ ]
4513
+ };
4514
+ }
4515
+ const slide2 = await client2.getSlide(presentationId, variantId, slideId);
4516
+ if (slide2.slideType !== "image") {
4517
+ return {
4518
+ content: [
4519
+ {
4520
+ type: "text",
4521
+ text: JSON.stringify({
4522
+ error: `Slide is type "${slide2.slideType}", not "image". Only image slides support image upload.`
4523
+ })
4524
+ }
4525
+ ]
4526
+ };
4527
+ }
4528
+ const { uploadUrl, imageUrl } = await client2.getSlideUploadUrl(presentationId, variantId, {
4529
+ filename,
4530
+ contentType
4531
+ });
4532
+ const existingContent = slide2.content || {};
4533
+ await client2.updateSlide(presentationId, variantId, slideId, {
4534
+ content: { ...existingContent, imageUrl }
4535
+ });
4536
+ const curlCommand = `curl -X PUT -H "Content-Type: ${contentType}" --data-binary @"${filePath}" "${uploadUrl}"`;
4537
+ return {
4538
+ content: [
4539
+ {
4540
+ type: "text",
4541
+ text: JSON.stringify({
4542
+ slideId,
4543
+ imageUrl,
4544
+ curlCommand,
4545
+ instructions: "Execute the curlCommand to upload the file. The slide has been updated and will display the image once uploaded."
4546
+ }, null, 2)
4547
+ }
4548
+ ]
4549
+ };
4550
+ });
4551
+ }
4380
4552
 
4381
4553
  // src/index.ts
4382
4554
  async function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ourroadmaps/mcp",
3
- "version": "0.24.1",
3
+ "version": "0.25.1",
4
4
  "description": "MCP server for OurRoadmaps - manage roadmaps, features, and ideas from Claude Code",
5
5
  "type": "module",
6
6
  "bin": {