@rolino/mcp 0.4.0 → 0.5.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/CHANGELOG.md +79 -0
- package/README.md +87 -12
- package/dist/bin.cjs +587 -9
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/chunk-ERTLKCCC.js +1337 -0
- package/dist/chunk-ERTLKCCC.js.map +1 -0
- package/dist/index.cjs +587 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -1
- package/dist/index.d.ts +116 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-SMMHU6JG.js +0 -719
- package/dist/chunk-SMMHU6JG.js.map +0 -1
package/dist/bin.cjs
CHANGED
|
@@ -52,7 +52,7 @@ var z = __toESM(require("zod/v4"), 1);
|
|
|
52
52
|
// package.json
|
|
53
53
|
var package_default = {
|
|
54
54
|
name: "@rolino/mcp",
|
|
55
|
-
version: "0.
|
|
55
|
+
version: "0.5.0",
|
|
56
56
|
description: "Model Context Protocol server for Rolino",
|
|
57
57
|
type: "module",
|
|
58
58
|
license: "MIT",
|
|
@@ -111,9 +111,9 @@ var package_default = {
|
|
|
111
111
|
dependencies: {
|
|
112
112
|
"@hono/node-server": "2.0.12",
|
|
113
113
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
114
|
-
"@rolino/contracts": "0.
|
|
115
|
-
"@rolino/local-auth": "0.
|
|
116
|
-
"@rolino/sdk": "0.
|
|
114
|
+
"@rolino/contracts": "0.5.0",
|
|
115
|
+
"@rolino/local-auth": "0.5.0",
|
|
116
|
+
"@rolino/sdk": "0.5.0",
|
|
117
117
|
zod: "^4.4.3"
|
|
118
118
|
},
|
|
119
119
|
devDependencies: {
|
|
@@ -183,7 +183,7 @@ var mcpDraftInputShape = {
|
|
|
183
183
|
"TikTok delivery choices. First call refresh_delivery_options, then supply an explicit mode. Direct publishing requires an exact returned visibility plus yes/no choices for comments, duet, stitch, commercial content, own-brand promotion, third-party promotion, and AI-generated content. Set reviewed only after reviewing the account-specific options; this is distinct from draft mutation consent."
|
|
184
184
|
),
|
|
185
185
|
youtubeSettings: import_contracts.DraftPostInputSchema.shape.youtubeSettings.describe(
|
|
186
|
-
"Required with YOUTUBE: explicit title, numeric categoryId, privacyStatus, madeForKids declaration, synthetic-media disclosure, subscriber-notification choice, and tags. Unaudited Google API projects may be restricted to Private uploads."
|
|
186
|
+
"Required with YOUTUBE: explicit title, numeric categoryId, privacyStatus, madeForKids declaration, synthetic-media disclosure, subscriber-notification choice, and tags. Immediate publishing uses the exact PUBLIC, UNLISTED, or PRIVATE visibility and creates no schedule. Future scheduling requires PUBLIC, while Rolino uploads privately for preparation. Unaudited Google API projects may be restricted to Private uploads."
|
|
187
187
|
)
|
|
188
188
|
};
|
|
189
189
|
var mcpDraftUpdateInputShape = {
|
|
@@ -205,6 +205,8 @@ var mcpScheduleExecuteOutputSchema = z.object({
|
|
|
205
205
|
provider: import_contracts.PostSchedulePendingSchema.shape.provider.optional(),
|
|
206
206
|
mutationId: import_contracts.PostSchedulePendingSchema.shape.mutationId.optional(),
|
|
207
207
|
operation: import_contracts.PostSchedulePendingSchema.shape.operation.optional(),
|
|
208
|
+
phase: import_contracts.PostSchedulePendingSchema.shape.phase.optional(),
|
|
209
|
+
videoUploaded: import_contracts.PostSchedulePendingSchema.shape.videoUploaded.optional(),
|
|
208
210
|
message: import_contracts.PostSchedulePendingSchema.shape.message.optional()
|
|
209
211
|
}).passthrough();
|
|
210
212
|
function jsonResult(structuredContent) {
|
|
@@ -304,6 +306,42 @@ var publishExecuteAnnotations = {
|
|
|
304
306
|
idempotentHint: true,
|
|
305
307
|
openWorldHint: true
|
|
306
308
|
};
|
|
309
|
+
var destructiveIdempotentAnnotations = {
|
|
310
|
+
readOnlyHint: false,
|
|
311
|
+
destructiveHint: true,
|
|
312
|
+
idempotentHint: true,
|
|
313
|
+
openWorldHint: false
|
|
314
|
+
};
|
|
315
|
+
var revalidationTestAnnotations = {
|
|
316
|
+
readOnlyHint: false,
|
|
317
|
+
destructiveHint: false,
|
|
318
|
+
idempotentHint: true,
|
|
319
|
+
openWorldHint: true
|
|
320
|
+
};
|
|
321
|
+
var blogImageWriteAnnotations = {
|
|
322
|
+
readOnlyHint: false,
|
|
323
|
+
destructiveHint: false,
|
|
324
|
+
idempotentHint: true,
|
|
325
|
+
openWorldHint: false
|
|
326
|
+
};
|
|
327
|
+
var blogConfirmationPreviewAnnotations = {
|
|
328
|
+
readOnlyHint: false,
|
|
329
|
+
destructiveHint: false,
|
|
330
|
+
idempotentHint: false,
|
|
331
|
+
openWorldHint: false
|
|
332
|
+
};
|
|
333
|
+
var blogConfirmedWriteAnnotations = {
|
|
334
|
+
readOnlyHint: false,
|
|
335
|
+
destructiveHint: false,
|
|
336
|
+
idempotentHint: true,
|
|
337
|
+
openWorldHint: false
|
|
338
|
+
};
|
|
339
|
+
var blogScheduleExecuteAnnotations = {
|
|
340
|
+
readOnlyHint: false,
|
|
341
|
+
destructiveHint: false,
|
|
342
|
+
idempotentHint: true,
|
|
343
|
+
openWorldHint: true
|
|
344
|
+
};
|
|
307
345
|
function defaultClient(options) {
|
|
308
346
|
return new import_sdk2.RolinoClient({
|
|
309
347
|
baseUrl: options.baseUrl ?? "https://getrolino.com",
|
|
@@ -314,6 +352,10 @@ function defaultClient(options) {
|
|
|
314
352
|
}
|
|
315
353
|
function createRolinoMcpServer(options = {}) {
|
|
316
354
|
const api = options.client ?? defaultClient(options);
|
|
355
|
+
const blogApi = () => {
|
|
356
|
+
if (!api.blog) throw new TypeError("This Rolino client does not support Blog Studio.");
|
|
357
|
+
return api.blog;
|
|
358
|
+
};
|
|
317
359
|
const server = new import_mcp.McpServer({
|
|
318
360
|
name: "rolino",
|
|
319
361
|
version: ROLINO_MCP_VERSION,
|
|
@@ -535,7 +577,7 @@ function createRolinoMcpServer(options = {}) {
|
|
|
535
577
|
});
|
|
536
578
|
server.registerTool("preview_post_schedule", {
|
|
537
579
|
title: "Preview a Rolino post schedule",
|
|
538
|
-
description: "Validate one exact future schedule against the current post version and live provider health. A YouTube schedule must target Public
|
|
580
|
+
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.",
|
|
539
581
|
inputSchema: {
|
|
540
582
|
projectId: z.string().min(1).describe("Exact Rolino project ID."),
|
|
541
583
|
postId: z.string().min(1).describe("Exact Rolino post ID."),
|
|
@@ -558,7 +600,7 @@ function createRolinoMcpServer(options = {}) {
|
|
|
558
600
|
});
|
|
559
601
|
server.registerTool("execute_post_schedule", {
|
|
560
602
|
title: "Execute a confirmed Rolino post schedule",
|
|
561
|
-
description: "Schedule a post only after preview_post_schedule. Pass the unchanged time, timezone, post version, and returned one-time confirmation token. For YouTube, confirmed execution begins or resumes
|
|
603
|
+
description: "Schedule a post only after preview_post_schedule. Pass the unchanged time, timezone, post version, and returned one-time confirmation token. For YouTube, confirmed execution begins or resumes a private upload immediately and may return PENDING with phase REMOTE_SCHEDULE_CONFIRMATION after upload while YouTube acknowledges the future Public publish time. PENDING never means the video is public. Rolino rechecks readiness and provider health, rejects stale or mismatched confirmation, and uses the stable idempotency key for safe retries. Scheduling causes future external publishing and is consequential.",
|
|
562
604
|
inputSchema: {
|
|
563
605
|
projectId: z.string().min(1).describe("Exact Rolino project ID."),
|
|
564
606
|
postId: z.string().min(1).describe("Exact Rolino post ID."),
|
|
@@ -590,7 +632,7 @@ function createRolinoMcpServer(options = {}) {
|
|
|
590
632
|
});
|
|
591
633
|
server.registerTool("preview_post_publish", {
|
|
592
634
|
title: "Preview immediate Rolino post publishing",
|
|
593
|
-
description: "Validate exact destinations against the current post version, safe retry state, readiness, and live provider health. YouTube readiness requires one stored video and explicit metadata
|
|
635
|
+
description: "Validate exact destinations for immediate publishing against the current post version, safe retry state, readiness, and live provider health. YouTube readiness requires one stored video and explicit metadata. Immediate YouTube publishing uses the configured PUBLIC, UNLISTED, or PRIVATE visibility and never creates a schedule; the preview exposes this as deliveryMode IMMEDIATE. Unaudited Google API projects may be restricted to Private. This contacts configured providers and creates a five-minute, single-use confirmation, but does not publish. Inspect the complete result before calling execute_post_publish with identical destinations.",
|
|
594
636
|
inputSchema: {
|
|
595
637
|
projectId: z.string().min(1).describe("Exact Rolino project ID."),
|
|
596
638
|
postId: z.string().min(1).describe("Exact Rolino post ID."),
|
|
@@ -613,7 +655,7 @@ function createRolinoMcpServer(options = {}) {
|
|
|
613
655
|
});
|
|
614
656
|
server.registerTool("execute_post_publish", {
|
|
615
657
|
title: "Execute confirmed immediate Rolino post publishing",
|
|
616
|
-
description: "Begin external publishing only after preview_post_publish. Pass the unchanged destinations, post version, and returned one-time confirmation token. Video execution remains PREPARING for YouTube and LinkedIn until provider-confirmed upload and processing complete; no queued or local state is reported as published. Rolino rechecks readiness and safe retry state, durably queues the exact destinations, rejects ambiguous prior outcomes, and uses the stable idempotency key to prevent duplicate execution. This is immediately consequential.",
|
|
658
|
+
description: "Begin external publishing only after preview_post_publish. Pass the unchanged destinations, post version, and returned one-time confirmation token. Immediate YouTube publishing preserves the previewed PUBLIC, UNLISTED, or PRIVATE visibility and never creates or confirms a schedule. Video execution remains PREPARING for YouTube and LinkedIn until provider-confirmed upload and processing complete; no queued or local state is reported as published. Rolino rechecks readiness and safe retry state, durably queues the exact destinations, rejects ambiguous prior outcomes, and uses the stable idempotency key to prevent duplicate execution. This is immediately consequential.",
|
|
617
659
|
inputSchema: {
|
|
618
660
|
projectId: z.string().min(1).describe("Exact Rolino project ID."),
|
|
619
661
|
postId: z.string().min(1).describe("Exact Rolino post ID."),
|
|
@@ -677,6 +719,542 @@ function createRolinoMcpServer(options = {}) {
|
|
|
677
719
|
return errorResult(error);
|
|
678
720
|
}
|
|
679
721
|
});
|
|
722
|
+
server.registerTool("list_seo_opportunities", {
|
|
723
|
+
title: "List active SEO tasks",
|
|
724
|
+
description: "Read a bounded list of active Ready and Research SEO tasks for one exact project. Each result contains one complete versioned task, decision, format, deliverables, evidence, provenance, separate topic-relevance and action-readiness confidence, limits, and no-publish rules. Rejected findings are never active tasks. This closed-world tool cannot run analysis, change settings, delete data, enable reports, send email, publish, generate media, or call an external provider.",
|
|
725
|
+
inputSchema: {
|
|
726
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
727
|
+
limit: z.number().int().min(1).max(50).default(20).describe("Maximum opportunities to return, from 1 to 50."),
|
|
728
|
+
cursor: z.string().min(1).max(512).regex(/^[A-Za-z0-9_-]+$/).optional().describe("Opaque cursor returned by a previous list_seo_opportunities call."),
|
|
729
|
+
kind: import_contracts.SeoOpportunityKindSchema.optional().describe("Optional exact opportunity kind."),
|
|
730
|
+
expectedImpact: import_contracts.SeoExpectedImpactSchema.optional().describe("Optional HIGH, MEDIUM, or LOW impact filter.")
|
|
731
|
+
},
|
|
732
|
+
outputSchema: import_contracts.SeoOpportunityListDataSchema,
|
|
733
|
+
annotations: readOnlyAnnotations
|
|
734
|
+
}, async ({ projectId, limit, cursor, kind, expectedImpact }) => {
|
|
735
|
+
try {
|
|
736
|
+
if (!api.seo) throw new TypeError("This Rolino client does not support SEO reading.");
|
|
737
|
+
return jsonResult(await api.seo.opportunities.list(projectId, { limit, cursor, kind, expectedImpact }));
|
|
738
|
+
} catch (error) {
|
|
739
|
+
return errorResult(error);
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
server.registerTool("get_seo_opportunity", {
|
|
743
|
+
title: "Read one complete SEO task",
|
|
744
|
+
description: "Read one canonical versioned SEO task by exact project and opportunity ID. It includes the Ready or Research decision, selected format, exact deliverables, safe evidence, provenance, separate topic-relevance and action-readiness confidence, targeting, source dates, limitations, success metric, and no-publish rules. This closed-world tool is read-only and cannot generate content, publish, or call an external provider.",
|
|
745
|
+
inputSchema: {
|
|
746
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
747
|
+
opportunityId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino SEO opportunity ID.")
|
|
748
|
+
},
|
|
749
|
+
outputSchema: import_contracts.SeoOpportunitySchema,
|
|
750
|
+
annotations: readOnlyAnnotations
|
|
751
|
+
}, async ({ projectId, opportunityId }) => {
|
|
752
|
+
try {
|
|
753
|
+
if (!api.seo) throw new TypeError("This Rolino client does not support SEO reading.");
|
|
754
|
+
return jsonResult(await api.seo.opportunities.get(projectId, opportunityId));
|
|
755
|
+
} catch (error) {
|
|
756
|
+
return errorResult(error);
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
server.registerTool("list_seo_reports", {
|
|
760
|
+
title: "List weekly SEO reports",
|
|
761
|
+
description: "Read a bounded list of stored weekly SEO report summaries for one exact project. This closed-world tool is read-only and cannot generate or deliver reports.",
|
|
762
|
+
inputSchema: {
|
|
763
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
764
|
+
limit: z.number().int().min(1).max(26).default(10).describe("Maximum reports to return, from 1 to 26."),
|
|
765
|
+
cursor: z.string().min(1).max(512).regex(/^[A-Za-z0-9_-]+$/).optional().describe("Opaque cursor returned by a previous list_seo_reports call."),
|
|
766
|
+
completeness: import_contracts.SeoReportCompletenessSchema.optional().describe("Optional COMPLETE or PARTIAL filter.")
|
|
767
|
+
},
|
|
768
|
+
outputSchema: import_contracts.SeoReportListDataSchema,
|
|
769
|
+
annotations: readOnlyAnnotations
|
|
770
|
+
}, async ({ projectId, limit, cursor, completeness }) => {
|
|
771
|
+
try {
|
|
772
|
+
if (!api.seo) throw new TypeError("This Rolino client does not support SEO reading.");
|
|
773
|
+
return jsonResult(await api.seo.reports.list(projectId, { limit, cursor, completeness }));
|
|
774
|
+
} catch (error) {
|
|
775
|
+
return errorResult(error);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
server.registerTool("get_seo_report", {
|
|
779
|
+
title: "Read one weekly SEO report",
|
|
780
|
+
description: "Read one unchanged weekly SEO report snapshot by exact project and report ID. It groups complete Ready tasks, Research tasks, and bounded rejected findings. This closed-world tool is read-only and cannot generate content, change, or deliver a report.",
|
|
781
|
+
inputSchema: {
|
|
782
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
783
|
+
reportId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino weekly SEO report ID.")
|
|
784
|
+
},
|
|
785
|
+
outputSchema: import_contracts.SeoReportSchema,
|
|
786
|
+
annotations: readOnlyAnnotations
|
|
787
|
+
}, async ({ projectId, reportId }) => {
|
|
788
|
+
try {
|
|
789
|
+
if (!api.seo) throw new TypeError("This Rolino client does not support SEO reading.");
|
|
790
|
+
return jsonResult(await api.seo.reports.get(projectId, reportId));
|
|
791
|
+
} catch (error) {
|
|
792
|
+
return errorResult(error);
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
server.registerTool("list_blog_plans", {
|
|
796
|
+
title: "List Blog Studio plans",
|
|
797
|
+
description: "Read the bounded 30-day Blog Studio plans for one exact project. This does not read the social calendar.",
|
|
798
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID.") },
|
|
799
|
+
outputSchema: z.object({ plans: z.array(import_contracts.AgentBlogPlanSchema) }),
|
|
800
|
+
annotations: readOnlyAnnotations
|
|
801
|
+
}, async ({ projectId }) => {
|
|
802
|
+
try {
|
|
803
|
+
return jsonResult(await blogApi().plans.list(projectId));
|
|
804
|
+
} catch (error) {
|
|
805
|
+
return errorResult(error);
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
server.registerTool("get_blog_setup_status", {
|
|
809
|
+
title: "Get Blog setup status",
|
|
810
|
+
description: "Requires blog:read. Call first to inspect action-oriented website, import, plan, delivery, and revalidation readiness. This never returns credentials, secrets, prompts, or draft content.",
|
|
811
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema },
|
|
812
|
+
outputSchema: import_contracts.AgentBlogSetupStatusSchema,
|
|
813
|
+
annotations: readOnlyAnnotations
|
|
814
|
+
}, async ({ projectId }) => {
|
|
815
|
+
try {
|
|
816
|
+
return jsonResult(await blogApi().setup.status(projectId));
|
|
817
|
+
} catch (error) {
|
|
818
|
+
return errorResult(error);
|
|
819
|
+
}
|
|
820
|
+
});
|
|
821
|
+
server.registerTool("initialize_blog_site", {
|
|
822
|
+
title: "Initialize and import Blog site",
|
|
823
|
+
description: "Requires blog:manage. Initialize the exact project website from Brand Settings and queue a bounded import. Poll the returned job; do not retry blindly. This cannot publish.",
|
|
824
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, idempotencyKey: z.string().min(8).max(200) },
|
|
825
|
+
outputSchema: import_contracts.AgentBlogJobSchema,
|
|
826
|
+
annotations: createDraftAnnotations
|
|
827
|
+
}, async ({ projectId, idempotencyKey }) => {
|
|
828
|
+
try {
|
|
829
|
+
return jsonResult(await blogApi().site.import(projectId, idempotencyKey));
|
|
830
|
+
} catch (error) {
|
|
831
|
+
return errorResult(error);
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
server.registerTool("retry_blog_site_import", {
|
|
835
|
+
title: "Retry Blog site import",
|
|
836
|
+
description: "Requires blog:manage. Requeue only a failed bounded website import with a stable idempotency key. Poll the returned job.",
|
|
837
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, idempotencyKey: z.string().min(8).max(200) },
|
|
838
|
+
outputSchema: import_contracts.AgentBlogJobSchema,
|
|
839
|
+
annotations: createDraftAnnotations
|
|
840
|
+
}, async ({ projectId, idempotencyKey }) => {
|
|
841
|
+
try {
|
|
842
|
+
return jsonResult(await blogApi().site.retry(projectId, idempotencyKey));
|
|
843
|
+
} catch (error) {
|
|
844
|
+
return errorResult(error);
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
server.registerTool("create_blog_plan", {
|
|
848
|
+
title: "Create Blog cadence plan",
|
|
849
|
+
description: "Requires blog:manage. Queue an evidence-backed 30-day plan only after import is ready. Ask the user for cadence first and poll the returned job. This never accepts items or publishes.",
|
|
850
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, startsOn: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), weekdays: z.array(z.number().int().min(0).max(6)).min(1).max(7), timeZone: z.string().min(1), idempotencyKey: z.string().min(8).max(200) },
|
|
851
|
+
outputSchema: z.object({ planId: z.string(), job: import_contracts.AgentBlogJobSchema }),
|
|
852
|
+
annotations: createDraftAnnotations
|
|
853
|
+
}, async ({ projectId, startsOn, weekdays, timeZone, idempotencyKey }) => {
|
|
854
|
+
try {
|
|
855
|
+
return jsonResult(await blogApi().plans.create(projectId, { startsOn, weekdays, timeZone }, idempotencyKey));
|
|
856
|
+
} catch (error) {
|
|
857
|
+
return errorResult(error);
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
server.registerTool("retry_blog_plan", {
|
|
861
|
+
title: "Retry failed Blog plan",
|
|
862
|
+
description: "Requires blog:manage. Retry one exact failed plan generation with idempotency and poll the returned job.",
|
|
863
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, planId: import_contracts.SeoEntityIdSchema, idempotencyKey: z.string().min(8).max(200) },
|
|
864
|
+
outputSchema: import_contracts.AgentBlogJobSchema,
|
|
865
|
+
annotations: createDraftAnnotations
|
|
866
|
+
}, async ({ projectId, planId, idempotencyKey }) => {
|
|
867
|
+
try {
|
|
868
|
+
return jsonResult(await blogApi().plans.retry(projectId, planId, idempotencyKey));
|
|
869
|
+
} catch (error) {
|
|
870
|
+
return errorResult(error);
|
|
871
|
+
}
|
|
872
|
+
});
|
|
873
|
+
server.registerTool("list_blog_plan_items", {
|
|
874
|
+
title: "List Blog plan items and evidence",
|
|
875
|
+
description: "Requires blog:read. Present this safe frozen evidence to the user before accepting or dismissing any item. Provider payloads and prompts are excluded.",
|
|
876
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, planId: import_contracts.SeoEntityIdSchema },
|
|
877
|
+
outputSchema: z.object({ items: z.array(import_contracts.AgentBlogPlanItemSchema) }),
|
|
878
|
+
annotations: readOnlyAnnotations
|
|
879
|
+
}, async ({ projectId, planId }) => {
|
|
880
|
+
try {
|
|
881
|
+
return jsonResult(await blogApi().plans.items.list(projectId, planId));
|
|
882
|
+
} catch (error) {
|
|
883
|
+
return errorResult(error);
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
server.registerTool("set_blog_plan_item_state", {
|
|
887
|
+
title: "Accept or dismiss Blog plan item",
|
|
888
|
+
description: "Requires blog:write. Apply an optimistic, idempotent ACCEPTED or DISMISSED transition only after showing the evidence. Dismissal is marked destructive. This cannot publish.",
|
|
889
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, planId: import_contracts.SeoEntityIdSchema, itemId: import_contracts.SeoEntityIdSchema, state: z.enum(["ACCEPTED", "DISMISSED"]), expectedState: z.string().min(1), expectedVersion: z.number().int().positive(), idempotencyKey: z.string().min(8).max(200) },
|
|
890
|
+
outputSchema: import_contracts.AgentBlogPlanItemSchema,
|
|
891
|
+
annotations: destructiveIdempotentAnnotations
|
|
892
|
+
}, async ({ projectId, planId, itemId, ...input }) => {
|
|
893
|
+
try {
|
|
894
|
+
return jsonResult(await blogApi().plans.items.setState(projectId, planId, itemId, input));
|
|
895
|
+
} catch (error) {
|
|
896
|
+
return errorResult(error);
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
server.registerTool("create_blog_article_from_plan_item", {
|
|
900
|
+
title: "Create editable Blog article",
|
|
901
|
+
description: "Requires blog:write. Create an editable draft from one accepted plan item and queue generation. Publication remains a separate approved-revision preview and execute operation.",
|
|
902
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, planId: import_contracts.SeoEntityIdSchema, itemId: import_contracts.SeoEntityIdSchema, expectedVersion: z.number().int().positive(), idempotencyKey: z.string().min(8).max(200) },
|
|
903
|
+
outputSchema: z.object({ articleId: z.string(), job: import_contracts.AgentBlogJobSchema.nullable() }),
|
|
904
|
+
annotations: createDraftAnnotations
|
|
905
|
+
}, async ({ projectId, planId, itemId, expectedVersion, idempotencyKey }) => {
|
|
906
|
+
try {
|
|
907
|
+
return jsonResult(await blogApi().plans.items.createArticle(projectId, planId, itemId, { expectedState: "ACCEPTED", expectedVersion, idempotencyKey }));
|
|
908
|
+
} catch (error) {
|
|
909
|
+
return errorResult(error);
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
server.registerTool("get_blog_connection_status", {
|
|
913
|
+
title: "Get Blog delivery connection status",
|
|
914
|
+
description: "Requires blog:read. Read configured and honestly verified delivery/revalidation readiness. It never returns stored tokens or secrets.",
|
|
915
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema },
|
|
916
|
+
outputSchema: import_contracts.AgentBlogConnectionStatusSchema,
|
|
917
|
+
annotations: readOnlyAnnotations
|
|
918
|
+
}, async ({ projectId }) => {
|
|
919
|
+
try {
|
|
920
|
+
return jsonResult(await blogApi().connection.status(projectId));
|
|
921
|
+
} catch (error) {
|
|
922
|
+
return errorResult(error);
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
const connectionInputSchema = { projectId: import_contracts.SeoEntityIdSchema, endpoint: z.string().url().nullable(), credentialAction: z.enum(["KEEP", "CREATE", "ROTATE", "REVOKE"]), credentialId: z.string().min(1).nullable(), secretAction: z.enum(["KEEP", "CREATE", "ROTATE"]) };
|
|
926
|
+
server.registerTool("preview_blog_connection_setup", {
|
|
927
|
+
title: "Preview Blog connection setup",
|
|
928
|
+
description: "Requires blog:manage. Preview the exact site, endpoint, credential action, secret action, and effects before provisioning. No delivery token or webhook secret is returned by preview.",
|
|
929
|
+
inputSchema: connectionInputSchema,
|
|
930
|
+
outputSchema: import_contracts.AgentBlogConnectionPreviewSchema,
|
|
931
|
+
annotations: createDraftAnnotations
|
|
932
|
+
}, async ({ projectId, ...input }) => {
|
|
933
|
+
try {
|
|
934
|
+
return jsonResult(await blogApi().connection.preview(projectId, input));
|
|
935
|
+
} catch (error) {
|
|
936
|
+
return errorResult(error);
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
server.registerTool("execute_blog_connection_setup", {
|
|
940
|
+
title: "Execute confirmed Blog connection setup",
|
|
941
|
+
description: "Requires blog:manage, the exact preview confirmation, and idempotency. A successful first response can return a delivery token or webhook secret once; write them only to server-side environment configuration. A replay never reveals them again. This cannot publish.",
|
|
942
|
+
inputSchema: { ...connectionInputSchema, confirmationToken: z.string().min(1), idempotencyKey: z.string().min(8).max(200) },
|
|
943
|
+
outputSchema: import_contracts.AgentBlogConnectionExecuteSchema,
|
|
944
|
+
annotations: destructiveIdempotentAnnotations
|
|
945
|
+
}, async ({ projectId, ...input }) => {
|
|
946
|
+
try {
|
|
947
|
+
return jsonResult(await blogApi().connection.execute(projectId, input));
|
|
948
|
+
} catch (error) {
|
|
949
|
+
return errorResult(error);
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
server.registerTool("test_blog_revalidation", {
|
|
953
|
+
title: "Test signed Blog revalidation",
|
|
954
|
+
description: "Requires blog:manage. Make one explicit, SSRF-protected open-world signed request to the configured same-host endpoint and persist only a safe status code.",
|
|
955
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, idempotencyKey: z.string().min(8).max(200) },
|
|
956
|
+
outputSchema: import_contracts.AgentBlogRevalidationTestSchema,
|
|
957
|
+
annotations: revalidationTestAnnotations
|
|
958
|
+
}, async ({ projectId, idempotencyKey }) => {
|
|
959
|
+
try {
|
|
960
|
+
return jsonResult(await blogApi().connection.test(projectId, idempotencyKey));
|
|
961
|
+
} catch (error) {
|
|
962
|
+
return errorResult(error);
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
server.registerTool("list_blog_publishing_providers", {
|
|
966
|
+
title: "List Blog publishing providers",
|
|
967
|
+
description: "List only providers available to this rollout with safe capabilities and official documentation. Requires blog:manage.",
|
|
968
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema },
|
|
969
|
+
outputSchema: z.object({ providers: z.array(import_contracts.AgentBlogPublishingProviderSchema) }),
|
|
970
|
+
annotations: readOnlyAnnotations
|
|
971
|
+
}, async ({ projectId }) => {
|
|
972
|
+
try {
|
|
973
|
+
return jsonResult(await blogApi().publishing.providers(projectId));
|
|
974
|
+
} catch (error) {
|
|
975
|
+
return errorResult(error);
|
|
976
|
+
}
|
|
977
|
+
});
|
|
978
|
+
server.registerTool("list_blog_publishing_destinations", {
|
|
979
|
+
title: "List Blog publishing destinations",
|
|
980
|
+
description: "List safe destination readiness without credentials or private provider data.",
|
|
981
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema },
|
|
982
|
+
outputSchema: z.object({ destinations: z.array(import_contracts.AgentBlogPublishingDestinationSchema) }),
|
|
983
|
+
annotations: readOnlyAnnotations
|
|
984
|
+
}, async ({ projectId }) => {
|
|
985
|
+
try {
|
|
986
|
+
return jsonResult(await blogApi().publishing.destinations(projectId));
|
|
987
|
+
} catch (error) {
|
|
988
|
+
return errorResult(error);
|
|
989
|
+
}
|
|
990
|
+
});
|
|
991
|
+
server.registerTool("list_blog_delivery_attempts", {
|
|
992
|
+
title: "List Blog delivery attempts",
|
|
993
|
+
description: "List safe per-destination delivery states and remote URLs. Draft content and provider responses are not returned.",
|
|
994
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, articleId: import_contracts.SeoEntityIdSchema.optional() },
|
|
995
|
+
outputSchema: z.object({ deliveries: z.array(import_contracts.AgentBlogDeliveryAttemptSchema) }),
|
|
996
|
+
annotations: readOnlyAnnotations
|
|
997
|
+
}, async ({ projectId, articleId }) => {
|
|
998
|
+
try {
|
|
999
|
+
return jsonResult(await blogApi().publishing.deliveries(projectId, articleId));
|
|
1000
|
+
} catch (error) {
|
|
1001
|
+
return errorResult(error);
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
server.registerTool("list_blog_articles", {
|
|
1005
|
+
title: "List Blog Studio articles",
|
|
1006
|
+
description: "Read Blog Studio article workflow state for one exact project. Draft content requires blog:read.",
|
|
1007
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID.") },
|
|
1008
|
+
outputSchema: z.object({ articles: z.array(import_contracts.AgentBlogArticleSchema) }),
|
|
1009
|
+
annotations: readOnlyAnnotations
|
|
1010
|
+
}, async ({ projectId }) => {
|
|
1011
|
+
try {
|
|
1012
|
+
return jsonResult(await blogApi().articles.list(projectId));
|
|
1013
|
+
} catch (error) {
|
|
1014
|
+
return errorResult(error);
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
server.registerTool("get_blog_article", {
|
|
1018
|
+
title: "Read one Blog Studio article",
|
|
1019
|
+
description: "Read one exact Blog Studio draft and its immutable revision history.",
|
|
1020
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, articleId: import_contracts.SeoEntityIdSchema },
|
|
1021
|
+
outputSchema: import_contracts.AgentBlogArticleDetailSchema,
|
|
1022
|
+
annotations: readOnlyAnnotations
|
|
1023
|
+
}, async ({ projectId, articleId }) => {
|
|
1024
|
+
try {
|
|
1025
|
+
return jsonResult(await blogApi().articles.get(projectId, articleId));
|
|
1026
|
+
} catch (error) {
|
|
1027
|
+
return errorResult(error);
|
|
1028
|
+
}
|
|
1029
|
+
});
|
|
1030
|
+
server.registerTool("update_blog_draft", {
|
|
1031
|
+
title: "Update one Blog Studio draft",
|
|
1032
|
+
description: "Save a complete Blog draft with optimistic conflict protection. This creates a new immutable revision and cannot publish.",
|
|
1033
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, articleId: import_contracts.SeoEntityIdSchema, draft: import_contracts.AgentBlogDraftUpdateSchema },
|
|
1034
|
+
outputSchema: import_contracts.AgentBlogArticleDetailSchema,
|
|
1035
|
+
annotations: createDraftAnnotations
|
|
1036
|
+
}, async ({ projectId, articleId, draft }) => {
|
|
1037
|
+
try {
|
|
1038
|
+
return jsonResult(await blogApi().articles.updateDraft(projectId, articleId, draft));
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
return errorResult(error);
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
1043
|
+
server.registerTool("generate_blog_article", {
|
|
1044
|
+
title: "Request Blog article generation",
|
|
1045
|
+
description: "Queue durable generation for one Blog article. It returns a job and never waits for provider work in the request.",
|
|
1046
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, articleId: import_contracts.SeoEntityIdSchema, idempotencyKey: z.string().min(8).max(200) },
|
|
1047
|
+
outputSchema: import_contracts.AgentBlogJobSchema,
|
|
1048
|
+
annotations: createDraftAnnotations
|
|
1049
|
+
}, async ({ projectId, articleId, idempotencyKey }) => {
|
|
1050
|
+
try {
|
|
1051
|
+
return jsonResult(await blogApi().articles.generate(projectId, articleId, idempotencyKey));
|
|
1052
|
+
} catch (error) {
|
|
1053
|
+
return errorResult(error);
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
server.registerTool("generate_blog_image", {
|
|
1057
|
+
title: "Generate a Blog image candidate",
|
|
1058
|
+
description: "Requires blog:write. Queue a bounded featured-image candidate for one exact article revision. This cannot approve an image or article and cannot publish.",
|
|
1059
|
+
inputSchema: {
|
|
1060
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1061
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID."),
|
|
1062
|
+
...import_contracts.AgentBlogImageGenerateRequestSchema.shape
|
|
1063
|
+
},
|
|
1064
|
+
outputSchema: import_contracts.AgentBlogImageGenerationResponseSchema.shape.data,
|
|
1065
|
+
annotations: blogImageWriteAnnotations
|
|
1066
|
+
}, async ({ projectId, articleId, ...input }) => {
|
|
1067
|
+
try {
|
|
1068
|
+
return jsonResult(await blogApi().articles.generateImage(projectId, articleId, input));
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
return errorResult(error);
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
server.registerTool("upload_blog_image", {
|
|
1074
|
+
title: "Upload a local Blog image candidate",
|
|
1075
|
+
description: "Requires blog:write. Read only one exact caller-supplied local JPEG, PNG, or WebP path and upload it for one exact article revision. This cannot approve an image or article and cannot publish.",
|
|
1076
|
+
inputSchema: {
|
|
1077
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1078
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID."),
|
|
1079
|
+
revisionId: import_contracts.AgentBlogImageUploadPrepareRequestSchema.shape.revisionId,
|
|
1080
|
+
filePath: z.string().min(1).describe("Exact local path of the user-approved Blog image."),
|
|
1081
|
+
altText: import_contracts.AgentBlogImageUploadCompleteRequestSchema.shape.altText
|
|
1082
|
+
},
|
|
1083
|
+
outputSchema: import_contracts.AgentBlogImageSchema,
|
|
1084
|
+
annotations: blogImageWriteAnnotations
|
|
1085
|
+
}, async ({ projectId, articleId, revisionId, filePath, altText }) => {
|
|
1086
|
+
try {
|
|
1087
|
+
const absolutePath = (0, import_node_path.resolve)(filePath);
|
|
1088
|
+
const details = await (0, import_promises.stat)(absolutePath).catch(() => null);
|
|
1089
|
+
if (!details?.isFile()) throw new TypeError("The Blog image path must point to a readable file.");
|
|
1090
|
+
const contentTypes = { ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png", ".webp": "image/webp" };
|
|
1091
|
+
const extension = (0, import_node_path.extname)(absolutePath).toLowerCase();
|
|
1092
|
+
const contentType = contentTypes[extension];
|
|
1093
|
+
if (!contentType) throw new TypeError("Use a JPEG, PNG, or WebP Blog image.");
|
|
1094
|
+
const body = await (0, import_node_fs.openAsBlob)(absolutePath, { type: contentType });
|
|
1095
|
+
return jsonResult(await blogApi().articles.uploadImage(projectId, articleId, { revisionId, fileName: (0, import_node_path.basename)(absolutePath), contentType, fileSize: details.size, altText, body }));
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
return errorResult(error);
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
server.registerTool("review_blog_image", {
|
|
1101
|
+
title: "Review a Blog image candidate",
|
|
1102
|
+
description: "Requires blog:write. Approve or reject one exact image version with reviewable alt text and idempotency. This does not approve the article and cannot publish.",
|
|
1103
|
+
inputSchema: {
|
|
1104
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1105
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID."),
|
|
1106
|
+
imageId: import_contracts.SeoEntityIdSchema.describe("Exact Blog image ID."),
|
|
1107
|
+
...import_contracts.AgentBlogImageReviewRequestSchema.shape
|
|
1108
|
+
},
|
|
1109
|
+
outputSchema: import_contracts.AgentBlogImageSchema,
|
|
1110
|
+
annotations: blogImageWriteAnnotations
|
|
1111
|
+
}, async ({ projectId, articleId, imageId, ...input }) => {
|
|
1112
|
+
try {
|
|
1113
|
+
return jsonResult(await blogApi().articles.reviewImage(projectId, articleId, imageId, input));
|
|
1114
|
+
} catch (error) {
|
|
1115
|
+
return errorResult(error);
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
server.registerTool("preview_blog_revision_approval", {
|
|
1119
|
+
title: "Preview exact Blog revision approval",
|
|
1120
|
+
description: "Requires blog:approve. Validate one exact revision, its approved image bundle, live links, warnings, and bundle hash, then create a short-lived confirmation. This cannot publish.",
|
|
1121
|
+
inputSchema: {
|
|
1122
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1123
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID."),
|
|
1124
|
+
...import_contracts.AgentBlogApprovalPreviewRequestSchema.shape
|
|
1125
|
+
},
|
|
1126
|
+
outputSchema: import_contracts.AgentBlogApprovalPreviewSchema,
|
|
1127
|
+
annotations: blogConfirmationPreviewAnnotations
|
|
1128
|
+
}, async ({ projectId, articleId, ...input }) => {
|
|
1129
|
+
try {
|
|
1130
|
+
return jsonResult(await blogApi().articles.previewApproval(projectId, articleId, input));
|
|
1131
|
+
} catch (error) {
|
|
1132
|
+
return errorResult(error);
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1135
|
+
server.registerTool("execute_blog_revision_approval", {
|
|
1136
|
+
title: "Approve an exact Blog revision bundle",
|
|
1137
|
+
description: "Requires blog:approve. Consume the matching confirmation and idempotently approve the exact revision and image bundle, which makes that bundle eligible for a separate publication operation. This cannot publish.",
|
|
1138
|
+
inputSchema: {
|
|
1139
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1140
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID."),
|
|
1141
|
+
...import_contracts.AgentBlogApprovalExecuteRequestSchema.shape
|
|
1142
|
+
},
|
|
1143
|
+
outputSchema: import_contracts.AgentBlogApprovalExecuteSchema,
|
|
1144
|
+
annotations: blogConfirmedWriteAnnotations
|
|
1145
|
+
}, async ({ projectId, articleId, ...input }) => {
|
|
1146
|
+
try {
|
|
1147
|
+
return jsonResult(await blogApi().articles.executeApproval(projectId, articleId, input));
|
|
1148
|
+
} catch (error) {
|
|
1149
|
+
return errorResult(error);
|
|
1150
|
+
}
|
|
1151
|
+
});
|
|
1152
|
+
server.registerTool("preview_blog_schedule", {
|
|
1153
|
+
title: "Preview an exact Blog schedule",
|
|
1154
|
+
description: "Requires blog:publish. Bind one already-approved exact bundle, future instant, IANA timezone, and destination set to a short-lived confirmation. This does not grant approval or publish now.",
|
|
1155
|
+
inputSchema: {
|
|
1156
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1157
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID."),
|
|
1158
|
+
...import_contracts.AgentBlogSchedulePreviewRequestSchema.shape
|
|
1159
|
+
},
|
|
1160
|
+
outputSchema: import_contracts.AgentBlogSchedulePreviewSchema,
|
|
1161
|
+
annotations: blogConfirmationPreviewAnnotations
|
|
1162
|
+
}, async ({ projectId, articleId, ...input }) => {
|
|
1163
|
+
try {
|
|
1164
|
+
return jsonResult(await blogApi().articles.previewSchedule(projectId, articleId, input));
|
|
1165
|
+
} catch (error) {
|
|
1166
|
+
return errorResult(error);
|
|
1167
|
+
}
|
|
1168
|
+
});
|
|
1169
|
+
server.registerTool("execute_blog_schedule", {
|
|
1170
|
+
title: "Schedule an exact approved Blog bundle",
|
|
1171
|
+
description: "Requires blog:publish. Consume the matching confirmation and idempotently schedule or reschedule one already-approved exact bundle for future external publication. This does not grant approval.",
|
|
1172
|
+
inputSchema: {
|
|
1173
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1174
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID."),
|
|
1175
|
+
...import_contracts.AgentBlogScheduleExecuteRequestSchema.shape
|
|
1176
|
+
},
|
|
1177
|
+
outputSchema: import_contracts.AgentBlogScheduleExecuteSchema,
|
|
1178
|
+
annotations: blogScheduleExecuteAnnotations
|
|
1179
|
+
}, async ({ projectId, articleId, ...input }) => {
|
|
1180
|
+
try {
|
|
1181
|
+
return jsonResult(await blogApi().articles.executeSchedule(projectId, articleId, input));
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
return errorResult(error);
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
server.registerTool("preview_blog_schedule_cancellation", {
|
|
1187
|
+
title: "Preview Blog schedule cancellation",
|
|
1188
|
+
description: "Requires blog:publish. Bind the exact current future schedule to a short-lived cancellation confirmation. This does not unpublish a live article and does not grant approval.",
|
|
1189
|
+
inputSchema: {
|
|
1190
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1191
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID.")
|
|
1192
|
+
},
|
|
1193
|
+
outputSchema: import_contracts.AgentBlogScheduleCancelPreviewSchema,
|
|
1194
|
+
annotations: blogConfirmationPreviewAnnotations
|
|
1195
|
+
}, async ({ projectId, articleId }) => {
|
|
1196
|
+
try {
|
|
1197
|
+
return jsonResult(await blogApi().articles.previewScheduleCancellation(projectId, articleId));
|
|
1198
|
+
} catch (error) {
|
|
1199
|
+
return errorResult(error);
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
server.registerTool("execute_blog_schedule_cancellation", {
|
|
1203
|
+
title: "Cancel an exact future Blog schedule",
|
|
1204
|
+
description: "Requires blog:publish. Consume the matching confirmation and idempotently cancel the exact future schedule. This is destructive, but it never unpublishes a live article and does not grant approval.",
|
|
1205
|
+
inputSchema: {
|
|
1206
|
+
projectId: import_contracts.SeoEntityIdSchema.describe("Exact Rolino project ID."),
|
|
1207
|
+
articleId: import_contracts.SeoEntityIdSchema.describe("Exact Blog article ID."),
|
|
1208
|
+
...import_contracts.AgentBlogScheduleCancelExecuteRequestSchema.shape
|
|
1209
|
+
},
|
|
1210
|
+
outputSchema: import_contracts.AgentBlogScheduleCancelExecuteSchema,
|
|
1211
|
+
annotations: destructiveIdempotentAnnotations
|
|
1212
|
+
}, async ({ projectId, articleId, ...input }) => {
|
|
1213
|
+
try {
|
|
1214
|
+
return jsonResult(await blogApi().articles.executeScheduleCancellation(projectId, articleId, input));
|
|
1215
|
+
} catch (error) {
|
|
1216
|
+
return errorResult(error);
|
|
1217
|
+
}
|
|
1218
|
+
});
|
|
1219
|
+
server.registerTool("get_blog_job", {
|
|
1220
|
+
title: "Read one Blog job",
|
|
1221
|
+
description: "Read truthful durable job state without exposing prompts, provider details, or secrets.",
|
|
1222
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, jobId: import_contracts.SeoEntityIdSchema },
|
|
1223
|
+
outputSchema: import_contracts.AgentBlogJobSchema,
|
|
1224
|
+
annotations: readOnlyAnnotations
|
|
1225
|
+
}, async ({ projectId, jobId }) => {
|
|
1226
|
+
try {
|
|
1227
|
+
return jsonResult(await blogApi().jobs.get(projectId, jobId));
|
|
1228
|
+
} catch (error) {
|
|
1229
|
+
return errorResult(error);
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
server.registerTool("preview_blog_publish", {
|
|
1233
|
+
title: "Preview approved Blog publication",
|
|
1234
|
+
description: "Preview an exact user-approved revision and issue a short-lived bound confirmation. This does not publish.",
|
|
1235
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, articleId: import_contracts.SeoEntityIdSchema, revisionId: import_contracts.SeoEntityIdSchema, destinationIds: z.array(import_contracts.SeoEntityIdSchema).min(1).max(20).optional() },
|
|
1236
|
+
outputSchema: import_contracts.AgentBlogPublishPreviewSchema,
|
|
1237
|
+
annotations: publishPreviewAnnotations
|
|
1238
|
+
}, async ({ projectId, articleId, revisionId, destinationIds }) => {
|
|
1239
|
+
try {
|
|
1240
|
+
return jsonResult(await blogApi().articles.previewPublish(projectId, articleId, revisionId, void 0, destinationIds));
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
return errorResult(error);
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1245
|
+
server.registerTool("execute_blog_publish", {
|
|
1246
|
+
title: "Publish approved Blog revision",
|
|
1247
|
+
description: "Publish only the same exact user-approved revision from preview. Requires blog:publish, a confirmation token, and an idempotency key.",
|
|
1248
|
+
inputSchema: { projectId: import_contracts.SeoEntityIdSchema, articleId: import_contracts.SeoEntityIdSchema, revisionId: import_contracts.SeoEntityIdSchema, destinationIds: z.array(import_contracts.SeoEntityIdSchema).min(1).max(20).optional(), confirmationToken: z.string().min(1), idempotencyKey: z.string().min(8).max(200) },
|
|
1249
|
+
outputSchema: z.object({ publicationId: z.string(), articleId: z.string(), revisionId: z.string(), publicUrl: z.string().url(), publishedAt: z.string().datetime() }),
|
|
1250
|
+
annotations: publishExecuteAnnotations
|
|
1251
|
+
}, async ({ projectId, articleId, revisionId, destinationIds, confirmationToken, idempotencyKey }) => {
|
|
1252
|
+
try {
|
|
1253
|
+
return jsonResult(await blogApi().articles.executePublish(projectId, articleId, { revisionId, destinationIds, confirmationToken, idempotencyKey }));
|
|
1254
|
+
} catch (error) {
|
|
1255
|
+
return errorResult(error);
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
680
1258
|
server.registerTool("list_calendar_events", {
|
|
681
1259
|
title: "List Rolino calendar events",
|
|
682
1260
|
description: "List scheduled posts and their enabled destinations in one exact project, including YouTube posts whose private early preparation has started. By default the bounded window spans 30 days in the past through 90 days ahead; provide both from and to for another range and paginate with nextCursor.",
|