@rolino/mcp 0.8.0 → 0.10.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.
package/dist/bin.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  resolveMcpConfiguration,
4
4
  startStdioServer
5
- } from "./chunk-SUHHBIE6.js";
5
+ } from "./chunk-OON7OE4T.js";
6
6
 
7
7
  // src/bin.ts
8
8
  async function main() {
@@ -1,4 +1,21 @@
1
1
  // src/index.ts
2
+ import { DraftDeletePreviewSchema, DraftDeleteResultSchema } from "@rolino/contracts";
3
+ import {
4
+ IntegrationDisconnectPreviewSchema,
5
+ IntegrationDisconnectResultSchema,
6
+ IntegrationDisconnectExecuteInputSchema,
7
+ MediaAssetUploadInputSchema,
8
+ MediaAssetUploadCompleteInputSchema,
9
+ MediaAssetUploadPreparationSchema,
10
+ PostScheduleCancelPreviewSchema,
11
+ PostScheduleCancelResultSchema,
12
+ PostDeliveryCheckInputSchema,
13
+ PostDeliveryCheckResultSchema,
14
+ PostRecoveryInputSchema,
15
+ PostRecoveryExecuteInputSchema,
16
+ PostRecoveryPreviewSchema,
17
+ PostRecoveryResultSchema
18
+ } from "@rolino/contracts";
2
19
  import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
3
20
  import { McpServer } from "@modelcontextprotocol/server";
4
21
  import { openAsBlob } from "fs";
@@ -102,7 +119,7 @@ import * as z from "zod/v4";
102
119
  // package.json
103
120
  var package_default = {
104
121
  name: "@rolino/mcp",
105
- version: "0.8.0",
122
+ version: "0.10.0",
106
123
  description: "Model Context Protocol server for Rolino",
107
124
  type: "module",
108
125
  license: "MIT",
@@ -161,9 +178,9 @@ var package_default = {
161
178
  dependencies: {
162
179
  "@hono/node-server": "2.0.12",
163
180
  "@modelcontextprotocol/server": "2.0.0",
164
- "@rolino/contracts": "0.8.0",
165
- "@rolino/local-auth": "0.8.0",
166
- "@rolino/sdk": "0.8.0",
181
+ "@rolino/contracts": "0.10.0",
182
+ "@rolino/local-auth": "0.10.0",
183
+ "@rolino/sdk": "0.10.0",
167
184
  zod: "^4.4.3"
168
185
  },
169
186
  devDependencies: {
@@ -258,6 +275,7 @@ var mcpDraftInputShape = {
258
275
  };
259
276
  var mcpDraftUpdateInputShape = {
260
277
  ...DraftPostUpdateInputSchema.shape,
278
+ mediaAltText: DraftPostUpdateInputSchema.shape.mediaAltText.describe("Alternative text keyed by selected asset ID or existing post media ID. Use null to clear. Maximum 1,000 characters. With replacement media, use asset IDs."),
261
279
  mediaAssetIds: DraftPostUpdateInputSchema.shape.mediaAssetIds.describe(
262
280
  "Replacement ordered media asset IDs. Omit to preserve current media; pass an empty array to remove all media."
263
281
  ),
@@ -584,6 +602,34 @@ function createRolinoMcpServer(options = {}) {
584
602
  return errorResult(error);
585
603
  }
586
604
  });
605
+ server.registerTool("prepare_media_asset_upload", {
606
+ title: "Prepare a media upload",
607
+ description: "Requires posts:write. Reserve one user-approved file in the exact project. Return a short-lived upload URL and required headers. Transfer the file bytes to that URL, then call complete_media_asset_upload with the returned storage identity. Keep the upload URL private. This does not create or publish a post and does not read local files on the server.",
608
+ inputSchema: MediaAssetUploadInputSchema.extend({ projectId: z.string().min(1) }),
609
+ outputSchema: MediaAssetUploadPreparationSchema,
610
+ annotations: uploadMediaAnnotations
611
+ }, async ({ projectId, ...input }) => {
612
+ try {
613
+ if (!api.media?.prepareUpload) throw new TypeError("Update the Rolino client for upload preparation.");
614
+ return jsonResult(await api.media.prepareUpload(projectId, input));
615
+ } catch (error) {
616
+ return errorResult(error);
617
+ }
618
+ });
619
+ server.registerTool("complete_media_asset_upload", {
620
+ title: "Verify an uploaded media asset",
621
+ description: "Requires posts:write. Call after transferring the approved file to the prepared URL. The server verifies stored bytes and media metadata. Use only the returned asset ID in a draft. Failed verification is not a ready asset. This does not create, schedule, or publish a post.",
622
+ inputSchema: MediaAssetUploadCompleteInputSchema.extend({ projectId: z.string().min(1) }),
623
+ outputSchema: MediaAssetSchema,
624
+ annotations: uploadMediaAnnotations
625
+ }, async ({ projectId, ...input }) => {
626
+ try {
627
+ if (!api.media?.completeUpload) throw new TypeError("Update the Rolino client for upload verification.");
628
+ return jsonResult(await api.media.completeUpload(projectId, input));
629
+ } catch (error) {
630
+ return errorResult(error);
631
+ }
632
+ });
587
633
  if ((options.toolProfile ?? "local") === "local") server.registerTool("upload_media_asset", {
588
634
  title: "Upload local media to Rolino",
589
635
  description: "Upload one explicitly approved local JPEG, PNG, WebP, MP4, or MOV file into an exact project's reusable media library. Read only the exact path supplied for this workflow. This changes Rolino data but never creates, schedules, or publishes a post. Return the asset ID for a later draft operation.",
@@ -719,6 +765,104 @@ function createRolinoMcpServer(options = {}) {
719
765
  return errorResult(error);
720
766
  }
721
767
  });
768
+ server.registerTool("check_post_delivery", {
769
+ title: "Check existing post delivery",
770
+ description: "Requires posts:write. Read the existing platform upload and update Rolino from that evidence. This never uploads, publishes, or changes visibility. UNKNOWN requires manual review. Missing IDs are not proof that an upload is absent.",
771
+ inputSchema: PostDeliveryCheckInputSchema.extend({ projectId: z.string().min(1), postId: z.string().min(1) }),
772
+ outputSchema: PostDeliveryCheckResultSchema,
773
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
774
+ }, async ({ projectId, postId, ...input }) => {
775
+ try {
776
+ if (!api.posts.checkDelivery) throw new TypeError("This server does not support delivery checks. Update the server before recovery.");
777
+ return jsonResult(await api.posts.checkDelivery(projectId, postId, input));
778
+ } catch (error) {
779
+ return errorResult(error);
780
+ }
781
+ });
782
+ server.registerTool("preview_post_recovery", {
783
+ title: "Preview existing video recovery",
784
+ description: "Verify one existing YouTube video and issue a five-minute confirmation. ATTACH links it without publishing. RESUME requires an explicit future publishAt, or null for public visibility now. Requires posts:write and, for RESUME, posts:schedule or posts:publish. Present the video, account, and consequence to the user before execution. No new upload is created.",
785
+ inputSchema: PostRecoveryInputSchema.safeExtend({ projectId: z.string().min(1), postId: z.string().min(1), expectedVersion: z.number().int().positive() }),
786
+ outputSchema: PostRecoveryPreviewSchema,
787
+ annotations: schedulePreviewAnnotations
788
+ }, async ({ projectId, postId, expectedVersion, ...input }) => {
789
+ try {
790
+ if (!api.posts.previewRecovery) throw new TypeError("This server does not support recovery previews. Update the server.");
791
+ return jsonResult(await api.posts.previewRecovery(projectId, postId, input, { expectedVersion }));
792
+ } catch (error) {
793
+ return errorResult(error);
794
+ }
795
+ });
796
+ server.registerTool("execute_post_recovery", {
797
+ title: "Execute confirmed video recovery",
798
+ description: "Execute only after the user approves preview_post_recovery. Send the unchanged video ID, action, publishAt, post version, and confirmation token. Reuse the same idempotency key on retry. ATTACH does not publish; check delivery afterward. QUEUED means a schedule or publication change is pending, not confirmed. Recovery reuses the existing video and affects only the selected destination.",
799
+ inputSchema: PostRecoveryExecuteInputSchema.safeExtend({ projectId: z.string().min(1), postId: z.string().min(1), expectedVersion: z.number().int().positive(), idempotencyKey: z.string().min(1).max(200) }),
800
+ outputSchema: PostRecoveryResultSchema,
801
+ annotations: scheduleExecuteAnnotations
802
+ }, async ({ projectId, postId, expectedVersion, idempotencyKey, ...input }) => {
803
+ try {
804
+ if (!api.posts.executeRecovery) throw new TypeError("This server does not support recovery execution. Update the server.");
805
+ return jsonResult(await api.posts.executeRecovery(projectId, postId, input, { expectedVersion, idempotencyKey }));
806
+ } catch (error) {
807
+ return errorResult(error);
808
+ }
809
+ });
810
+ server.registerTool("preview_draft_deletion", {
811
+ title: "Preview draft deletion",
812
+ description: "Requires posts:delete. Preview permanent deletion of one untouched draft. Show its caption, media count, and consequence to the user. Reusable Media Library originals remain.",
813
+ inputSchema: z.object({ projectId: z.string().min(1), postId: z.string().min(1), expectedVersion: z.number().int().positive() }),
814
+ outputSchema: DraftDeletePreviewSchema,
815
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
816
+ }, async ({ projectId, postId, expectedVersion }) => {
817
+ try {
818
+ if (!api.posts.previewDeletion) throw new TypeError("Update the Rolino client for draft deletion.");
819
+ return jsonResult(await api.posts.previewDeletion(projectId, postId, { expectedVersion }));
820
+ } catch (error) {
821
+ return errorResult(error);
822
+ }
823
+ });
824
+ server.registerTool("execute_draft_deletion", {
825
+ title: "Delete the confirmed draft",
826
+ description: "Requires posts:delete and user approval of the exact preview. Permanently delete the untouched draft using its version, confirmation, and stable retry key. Reusable media originals remain. Cannot delete a scheduled or published post.",
827
+ inputSchema: z.object({ projectId: z.string().min(1), postId: z.string().min(1), expectedVersion: z.number().int().positive(), confirmationToken: z.string().min(1), idempotencyKey: z.string().min(1) }),
828
+ outputSchema: DraftDeleteResultSchema,
829
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }
830
+ }, async ({ projectId, postId, expectedVersion, confirmationToken, idempotencyKey }) => {
831
+ try {
832
+ if (!api.posts.executeDeletion) throw new TypeError("Update the Rolino client for draft deletion.");
833
+ return jsonResult(await api.posts.executeDeletion(projectId, postId, { confirmationToken }, { expectedVersion, idempotencyKey }));
834
+ } catch (error) {
835
+ return errorResult(error);
836
+ }
837
+ });
838
+ server.registerTool("preview_post_schedule_cancellation", {
839
+ title: "Preview post schedule cancellation",
840
+ description: "Requires posts:schedule. Preview cancellation of all destinations on a future local schedule. Delivery must not have started. Show the post, time, destinations, and consequence to the user. Use check_post_delivery for uncertain delivery.",
841
+ inputSchema: z.object({ projectId: z.string().min(1), postId: z.string().min(1), expectedVersion: z.number().int().positive() }),
842
+ outputSchema: PostScheduleCancelPreviewSchema,
843
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
844
+ }, async ({ projectId, postId, expectedVersion }) => {
845
+ try {
846
+ if (!api.posts.previewScheduleCancellation) throw new TypeError("Update the Rolino client for schedule cancellation.");
847
+ return jsonResult(await api.posts.previewScheduleCancellation(projectId, postId, { expectedVersion }));
848
+ } catch (error) {
849
+ return errorResult(error);
850
+ }
851
+ });
852
+ server.registerTool("execute_post_schedule_cancellation", {
853
+ title: "Cancel a confirmed post schedule",
854
+ description: "Requires posts:schedule and user approval of the exact preview. Return a future local schedule to Draft with the unchanged post version and confirmation. Reuse the idempotency key on retry. Reject started or uncertain delivery; never delete a remote post.",
855
+ inputSchema: z.object({ projectId: z.string().min(1), postId: z.string().min(1), expectedVersion: z.number().int().positive(), confirmationToken: z.string().min(1), idempotencyKey: z.string().min(1) }),
856
+ outputSchema: PostScheduleCancelResultSchema,
857
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }
858
+ }, async ({ projectId, postId, expectedVersion, confirmationToken, idempotencyKey }) => {
859
+ try {
860
+ if (!api.posts.executeScheduleCancellation) throw new TypeError("Update the Rolino client for schedule cancellation.");
861
+ return jsonResult(await api.posts.executeScheduleCancellation(projectId, postId, { confirmationToken }, { expectedVersion, idempotencyKey }));
862
+ } catch (error) {
863
+ return errorResult(error);
864
+ }
865
+ });
722
866
  server.registerTool("preview_post_schedule", {
723
867
  title: "Preview a Rolino post schedule",
724
868
  description: "Validate one exact future schedule against the current post version and live provider health. A YouTube schedule must target Public. Its preview states that preparation uploads the video privately now; CONFIRMING_SCHEDULE means the upload is complete and YouTube is acknowledging the future Public publish time, not that the video is public. This contacts configured providers and creates a five-minute, single-use confirmation, but does not schedule or publish the post. Inspect the complete result before calling execute_post_schedule with identical values.",
@@ -781,16 +925,17 @@ function createRolinoMcpServer(options = {}) {
781
925
  projectId: z.string().min(1).describe("Exact Rolino project ID."),
782
926
  postId: z.string().min(1).describe("Exact Rolino post ID."),
783
927
  expectedVersion: z.number().int().positive().describe("Current version returned by get_post."),
928
+ destinationIds: PostPublishInputSchema.shape.destinationIds.describe("Exact saved destination IDs from get_post. Required when a network has several accounts. Do not combine with destinations."),
784
929
  destinations: PostPublishInputSchema.shape.destinations.describe("Exact Instagram, TikTok, YouTube, Bluesky, and/or LinkedIn destinations to publish now.")
785
930
  }),
786
931
  outputSchema: PostPublishPreviewSchema,
787
932
  annotations: publishPreviewAnnotations
788
- }, async ({ projectId, postId, expectedVersion, destinations }) => {
933
+ }, async ({ projectId, postId, expectedVersion, destinations, destinationIds }) => {
789
934
  try {
790
935
  return jsonResult(await api.posts.previewPublish(
791
936
  projectId,
792
937
  postId,
793
- { destinations },
938
+ { destinations, ...destinationIds ? { destinationIds } : {} },
794
939
  { expectedVersion }
795
940
  ));
796
941
  } catch (error) {
@@ -806,6 +951,7 @@ function createRolinoMcpServer(options = {}) {
806
951
  expectedVersion: z.number().int().positive().describe("Same post version used by preview_post_publish."),
807
952
  idempotencyKey: z.string().min(1).max(200).describe("Stable caller-generated retry key for this exact execution."),
808
953
  confirmationToken: z.string().min(1).max(200).describe("Single-use token returned by preview_post_publish."),
954
+ destinationIds: PostPublishInputSchema.shape.destinationIds.describe("Exact saved destination IDs from get_post. Required when a network has several accounts. Do not combine with destinations."),
809
955
  destinations: PostPublishInputSchema.shape.destinations.describe("Exact unchanged destinations returned by preview_post_publish.")
810
956
  }),
811
957
  outputSchema: PostSchema,
@@ -816,13 +962,14 @@ function createRolinoMcpServer(options = {}) {
816
962
  expectedVersion,
817
963
  idempotencyKey,
818
964
  confirmationToken,
819
- destinations
965
+ destinations,
966
+ destinationIds
820
967
  }) => {
821
968
  try {
822
969
  return jsonResult(await api.posts.executePublish(
823
970
  projectId,
824
971
  postId,
825
- { destinations, confirmationToken },
972
+ { destinations, ...destinationIds ? { destinationIds } : {}, confirmationToken },
826
973
  { expectedVersion, idempotencyKey }
827
974
  ));
828
975
  } catch (error) {
@@ -844,21 +991,50 @@ function createRolinoMcpServer(options = {}) {
844
991
  return errorResult(error);
845
992
  }
846
993
  });
994
+ server.registerTool("preview_integration_disconnection", {
995
+ title: "Preview Bluesky disconnection",
996
+ description: "Requires the separate integrations:disconnect capability. Preview the exact Bluesky account and pending deliveries before user approval. Does not disconnect or expose credentials.",
997
+ inputSchema: z.object({ projectId: z.string().min(1), integrationId: z.string().min(1).max(200).optional() }),
998
+ outputSchema: IntegrationDisconnectPreviewSchema,
999
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
1000
+ }, async ({ projectId, integrationId }) => {
1001
+ try {
1002
+ if (!api.integrations.previewDisconnection) throw new TypeError("Update the Rolino client for disconnection.");
1003
+ return jsonResult(await api.integrations.previewDisconnection(projectId, { integrationId }));
1004
+ } catch (error) {
1005
+ return errorResult(error);
1006
+ }
1007
+ });
1008
+ server.registerTool("execute_integration_disconnection", {
1009
+ title: "Disconnect the confirmed Bluesky account",
1010
+ description: "Requires integrations:disconnect and user approval of the exact preview. Use its unchanged expectedVersion and confirmation token with a stable idempotency key. Clears local authorization; published posts and saved schedules remain. In-flight delivery can finish. Remote revocation can remain unresolved.",
1011
+ inputSchema: IntegrationDisconnectExecuteInputSchema.extend({ projectId: z.string().min(1), idempotencyKey: z.string().min(1) }),
1012
+ outputSchema: IntegrationDisconnectResultSchema,
1013
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }
1014
+ }, async ({ projectId, idempotencyKey, ...input }) => {
1015
+ try {
1016
+ if (!api.integrations.executeDisconnection) throw new TypeError("Update the Rolino client for disconnection.");
1017
+ return jsonResult(await api.integrations.executeDisconnection(projectId, input, { idempotencyKey }));
1018
+ } catch (error) {
1019
+ return errorResult(error);
1020
+ }
1021
+ });
847
1022
  server.registerTool("refresh_delivery_options", {
848
1023
  title: "Refresh provider delivery options",
849
- description: "Contact one connected publishing provider and return secret-safe, account-specific choices needed to prepare a compliant draft. TikTok returns account-specific video choices; LinkedIn returns its verified member plus image and native-video policy. This refreshes cached provider health but never creates, schedules, or publishes a post.",
1024
+ description: "Contact one publishing provider and return safe account-specific choices. Bluesky returns text and image limits, connection health, and a human OAuth handoff path on this Rolino host. The owner must approve connection in the browser. TikTok returns video choices; LinkedIn returns member and media policy. This refreshes cached health but never creates, schedules, or publishes a post.",
850
1025
  inputSchema: z.object({
851
1026
  projectId: z.string().min(1).describe("Exact Rolino project ID."),
1027
+ integrationId: z.string().min(1).max(200).optional().describe("Exact connection ID returned by integration health."),
852
1028
  provider: ProviderDeliveryOptionsProviderSchema.describe("Provider whose delivery choices should be refreshed.")
853
1029
  }),
854
1030
  outputSchema: ProviderDeliveryOptionsToolSchema,
855
1031
  annotations: deliveryOptionsAnnotations
856
- }, async ({ projectId, provider }) => {
1032
+ }, async ({ projectId, provider, integrationId }) => {
857
1033
  try {
858
1034
  if (!api.integrations.deliveryOptions) {
859
1035
  throw new TypeError("This Rolino client does not support provider delivery options.");
860
1036
  }
861
- return jsonResult(await api.integrations.deliveryOptions(projectId, provider));
1037
+ return jsonResult(await api.integrations.deliveryOptions(projectId, provider, { integrationId }));
862
1038
  } catch (error) {
863
1039
  return errorResult(error);
864
1040
  }
@@ -1612,4 +1788,4 @@ export {
1612
1788
  createRolinoMcpServer,
1613
1789
  startStdioServer
1614
1790
  };
1615
- //# sourceMappingURL=chunk-SUHHBIE6.js.map
1791
+ //# sourceMappingURL=chunk-OON7OE4T.js.map