@contenthero/mcp 0.4.0 → 0.4.2
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/format.d.ts +27 -9
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +56 -27
- package/dist/format.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +58 -42
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
package/dist/server.js
CHANGED
|
@@ -37,8 +37,8 @@ import { z } from 'zod';
|
|
|
37
37
|
import { GenerationTimeoutError, pendingOutputId, } from '@contenthero/sdk';
|
|
38
38
|
import { getClient as defaultGetClient } from './client.js';
|
|
39
39
|
import { resolveModelEnums, BOARD_TYPES, BOARD_TYPE_GUIDANCE, IMAGE_MODEL_GUIDANCE, VIDEO_MODEL_GUIDANCE, AUDIO_MODEL_GUIDANCE, EDIT_AUDIO_MODEL_GUIDANCE, UPSCALE_MODEL_GUIDANCE, LIP_SYNC_MODEL_GUIDANCE, } from './models.js';
|
|
40
|
-
import { audioResult, avatarListResult, avatarResult, balanceResult, brandKitListResult, brandKitResult, brandKnowledgeListResult, brandKnowledgeDetailResult, brandKnowledgeSearchResult, brandKnowledgeItemResult, completedResult, connectedAccountListResult, connectedAccountResult, costResult, accountDetailResult, inspirationContentResult, mediaListResult, mediaSearchResult, folderListResult, folderContentsResult, mediaBatchResult, mediaUploadResult, uploadedMediaResult, tagListResult, tagResult, tagDeletedResult, modelListResult, modelResult, platformListResult, platformResult, elementListResult, elementResult, elementDeletedResult, errorResult, generationBatchResult, outlierListResult, enhanceClipsResult, pendingResult, stageListResult, spaceDeletedResult, spaceListResult, spaceResult, cardListResult, cardResult, postSummaryResult, publishResult, statusActionResult, editorOpsResult, text, projectDetailResult, liveContextResult, projectListResult, projectCreatedResult, projectDeletedResult, layerTypesResult, timelineTypesResult, editorTranscriptResult, exportJobResult, exportFormatsResult, trackedAccountListResult, transcriptResult, voiceListResult, voiceResult, } from './format.js';
|
|
41
|
-
/** Platforms a
|
|
40
|
+
import { audioResult, avatarListResult, avatarResult, balanceResult, brandKitListResult, brandKitResult, brandKnowledgeListResult, brandKnowledgeDetailResult, brandKnowledgeSearchResult, brandKnowledgeItemResult, completedResult, connectedAccountListResult, connectedAccountResult, costResult, accountDetailResult, inspirationContentResult, mediaListResult, mediaSearchResult, folderListResult, folderContentsResult, mediaBatchResult, mediaUploadResult, importedMediaResult, uploadedMediaResult, tagListResult, tagResult, tagDeletedResult, modelListResult, modelResult, platformListResult, platformResult, elementListResult, elementResult, elementDeletedResult, errorResult, generationBatchResult, outlierListResult, enhanceClipsResult, pendingResult, stageListResult, spaceDeletedResult, spaceListResult, spaceResult, cardListResult, cardResult, postSummaryResult, publishResult, statusActionResult, editorOpsResult, text, projectDetailResult, liveContextResult, projectListResult, projectCreatedResult, projectDeletedResult, layerTypesResult, timelineTypesResult, editorTranscriptResult, exportJobResult, exportFormatsResult, trackedAccountListResult, transcriptResult, voiceListResult, voiceResult, } from './format.js';
|
|
41
|
+
/** Platforms a card or one of its posts may target. */
|
|
42
42
|
const POST_PLATFORMS = [
|
|
43
43
|
'youtube',
|
|
44
44
|
'instagram',
|
|
@@ -247,11 +247,11 @@ export function registerTools(server, opts) {
|
|
|
247
247
|
handleOrUrl: z.string().describe('A profile url, or a handle when platform is given.'),
|
|
248
248
|
}),
|
|
249
249
|
]);
|
|
250
|
-
const
|
|
251
|
-
platform: z.enum(POST_PLATFORMS).describe('The platform. This is the KEY: one
|
|
250
|
+
const cardPostSchema = z.object({
|
|
251
|
+
platform: z.enum(POST_PLATFORMS).describe('The platform. This is the KEY: one post per platform.'),
|
|
252
252
|
format: z.string().optional(),
|
|
253
253
|
connectedAccountId: z.string().nullable().optional(),
|
|
254
|
-
scheduledAt: z.string().nullable().optional().describe("Per-
|
|
254
|
+
scheduledAt: z.string().nullable().optional().describe("Per-post override of the card's schedule."),
|
|
255
255
|
platformSpecificData: z.record(z.string(), z.unknown()).optional().describe('The publish payload for this platform.'),
|
|
256
256
|
status: z.string().optional(),
|
|
257
257
|
});
|
|
@@ -1357,7 +1357,7 @@ export function registerTools(server, opts) {
|
|
|
1357
1357
|
}, async (args, extra) => {
|
|
1358
1358
|
try {
|
|
1359
1359
|
const client = await getClient(extra);
|
|
1360
|
-
return
|
|
1360
|
+
return importedMediaResult(await client.importMedia({
|
|
1361
1361
|
url: args.url,
|
|
1362
1362
|
contentType: args.contentType,
|
|
1363
1363
|
fileName: args.fileName,
|
|
@@ -1423,7 +1423,7 @@ export function registerTools(server, opts) {
|
|
|
1423
1423
|
server.registerTool('get_platform', {
|
|
1424
1424
|
title: 'Get Platform',
|
|
1425
1425
|
annotations: READ,
|
|
1426
|
-
description: "Get one platform's full publishing shape: the fields, options (enums), and character limits a post requires per format (post, reel, short, story, thread). Ground a
|
|
1426
|
+
description: "Get one platform's full publishing shape: the fields, options (enums), and character limits a post requires per format (post, reel, short, story, thread). Ground a post's platformSettings against this instead of guessing the fields. Optionally pass a format to narrow the result.",
|
|
1427
1427
|
inputSchema: {
|
|
1428
1428
|
platform: z
|
|
1429
1429
|
.enum(POST_PLATFORMS)
|
|
@@ -1583,13 +1583,13 @@ export function registerTools(server, opts) {
|
|
|
1583
1583
|
});
|
|
1584
1584
|
// -- list_cards -----------------------------------------------------------
|
|
1585
1585
|
server.registerTool('list_cards', {
|
|
1586
|
-
title: 'List
|
|
1586
|
+
title: 'List Cards',
|
|
1587
1587
|
annotations: READ,
|
|
1588
|
-
description: "List the account's content-pipeline posts (newest-updated first). Filter by status, platform,
|
|
1588
|
+
description: "List the account's content-pipeline posts (newest-updated first). Filter by status, platform, stage (id/slug/name), folder, favorite, or a title search. Call get_card for one post's full detail (posts + assets).",
|
|
1589
1589
|
inputSchema: {
|
|
1590
1590
|
status: z.enum(['draft', 'active', 'completed', 'archived']).optional().describe('Filter by lifecycle status.'),
|
|
1591
1591
|
platform: z.enum(POST_PLATFORMS).optional().describe('Filter by the post platform.'),
|
|
1592
|
-
|
|
1592
|
+
stage: z.string().optional().describe('Filter by a stage id, slug, or name.'),
|
|
1593
1593
|
search: z.string().optional().describe('Case-insensitive title search.'),
|
|
1594
1594
|
limit: z.number().int().min(1).max(100).optional().describe('How many to return (default 50).'),
|
|
1595
1595
|
offset: z.number().int().min(0).optional().describe('Pagination offset.'),
|
|
@@ -1600,7 +1600,7 @@ export function registerTools(server, opts) {
|
|
|
1600
1600
|
return cardListResult(await client.listCards({
|
|
1601
1601
|
status: args.status,
|
|
1602
1602
|
platform: args.platform,
|
|
1603
|
-
|
|
1603
|
+
stage: args.stage,
|
|
1604
1604
|
search: args.search,
|
|
1605
1605
|
limit: args.limit,
|
|
1606
1606
|
offset: args.offset,
|
|
@@ -1612,16 +1612,16 @@ export function registerTools(server, opts) {
|
|
|
1612
1612
|
});
|
|
1613
1613
|
// -- get_card -------------------------------------------------------------
|
|
1614
1614
|
server.registerTool('get_card', {
|
|
1615
|
-
title: 'Get
|
|
1615
|
+
title: 'Get Card',
|
|
1616
1616
|
annotations: READ,
|
|
1617
|
-
description: "Get one post in full: its fields (title, description, script, notes, status, stage, schedule), plus its publish
|
|
1617
|
+
description: "Get one post in full: its fields (title, description, script, notes, status, stage, schedule), plus its publish posts and attached assets.",
|
|
1618
1618
|
inputSchema: {
|
|
1619
|
-
|
|
1619
|
+
cardId: z.string().describe('The card id from list_cards.'),
|
|
1620
1620
|
},
|
|
1621
1621
|
}, async (args, extra) => {
|
|
1622
1622
|
try {
|
|
1623
1623
|
const client = await getClient(extra);
|
|
1624
|
-
return cardResult(await client.getCard(args.
|
|
1624
|
+
return cardResult(await client.getCard(args.cardId));
|
|
1625
1625
|
}
|
|
1626
1626
|
catch (err) {
|
|
1627
1627
|
return errorResult(err);
|
|
@@ -1666,7 +1666,7 @@ export function registerTools(server, opts) {
|
|
|
1666
1666
|
server.registerTool('create_space', {
|
|
1667
1667
|
title: 'Create Space',
|
|
1668
1668
|
annotations: WRITE,
|
|
1669
|
-
description: "Create a space: a new planner board with its own stages. duplicateFrom copies another space's STAGES, never its cards, so the new board arrives with the columns and none of the work. Requires the
|
|
1669
|
+
description: "Create a space: a new planner board with its own stages. duplicateFrom copies another space's STAGES, never its cards, so the new board arrives with the columns and none of the work. Requires the planner:write scope.",
|
|
1670
1670
|
inputSchema: {
|
|
1671
1671
|
name: z.string().describe('The space name.'),
|
|
1672
1672
|
coverUrl: z.string().optional().describe('A cover image URL for the space tile.'),
|
|
@@ -1692,7 +1692,7 @@ export function registerTools(server, opts) {
|
|
|
1692
1692
|
server.registerTool('update_space', {
|
|
1693
1693
|
title: 'Update Space',
|
|
1694
1694
|
annotations: WRITE,
|
|
1695
|
-
description: "Rename a space or change its cover. This is a PATCH: a field you omit is left alone, so renaming does not disturb the cover. Pass coverUrl as an empty string to REMOVE the cover. To favorite or archive a space, use the `favorite` and `archive` tools with assetType 'space' instead. Requires the
|
|
1695
|
+
description: "Rename a space or change its cover. This is a PATCH: a field you omit is left alone, so renaming does not disturb the cover. Pass coverUrl as an empty string to REMOVE the cover. To favorite or archive a space, use the `favorite` and `archive` tools with assetType 'space' instead. Requires the planner:write scope.",
|
|
1696
1696
|
inputSchema: {
|
|
1697
1697
|
spaceId: z.string().describe('The space id to update.'),
|
|
1698
1698
|
name: z.string().optional().describe('A new name.'),
|
|
@@ -1717,7 +1717,7 @@ export function registerTools(server, opts) {
|
|
|
1717
1717
|
server.registerTool('delete_space', {
|
|
1718
1718
|
title: 'Delete Space',
|
|
1719
1719
|
annotations: WRITE,
|
|
1720
|
-
description: 'Delete a space. The server REFUSES a space that still holds cards and names the count, because the delete cascades to every card in it along with their covers, captions,
|
|
1720
|
+
description: 'Delete a space. The server REFUSES a space that still holds cards and names the count, because the delete cascades to every card in it along with their covers, captions, posts and schedules. Archive the space instead if you want it out of the way. Requires the planner:write scope.',
|
|
1721
1721
|
inputSchema: { spaceId: z.string().describe('The space id to delete.') },
|
|
1722
1722
|
}, async (args, extra) => {
|
|
1723
1723
|
try {
|
|
@@ -1733,7 +1733,7 @@ export function registerTools(server, opts) {
|
|
|
1733
1733
|
server.registerTool('list_stages', {
|
|
1734
1734
|
title: 'List Pipeline Stages',
|
|
1735
1735
|
annotations: READ,
|
|
1736
|
-
description: "List the account's
|
|
1736
|
+
description: "List the account's stages, in order. Stages are user-customizable (renamed, reordered, added, removed), so call this to discover the real stages before placing a post; pass a stage's id (most stable), slug, or name to create_card / update_card.",
|
|
1737
1737
|
}, async (extra) => {
|
|
1738
1738
|
try {
|
|
1739
1739
|
const client = await getClient(extra);
|
|
@@ -1745,9 +1745,9 @@ export function registerTools(server, opts) {
|
|
|
1745
1745
|
});
|
|
1746
1746
|
// -- create_card ----------------------------------------------------------
|
|
1747
1747
|
server.registerTool('create_card', {
|
|
1748
|
-
title: 'Create
|
|
1748
|
+
title: 'Create Card',
|
|
1749
1749
|
annotations: WRITE,
|
|
1750
|
-
description: "Create a content
|
|
1750
|
+
description: "Create a card, the container in the content pipeline. A card holds the work (title, script, notes, cover) and the posts that publish it. Attach posts and media by passing `posts` and `assets` to update_card, then publish with publish_post. `stage` accepts a stage id/slug/name (defaults to the first stage). Requires a key with the planner:write scope.",
|
|
1751
1751
|
inputSchema: {
|
|
1752
1752
|
title: z.string().describe('Post title (required).'),
|
|
1753
1753
|
platform: z.enum(POST_PLATFORMS).describe('Primary platform for the post.'),
|
|
@@ -1780,15 +1780,23 @@ export function registerTools(server, opts) {
|
|
|
1780
1780
|
});
|
|
1781
1781
|
// -- update_card ----------------------------------------------------------
|
|
1782
1782
|
server.registerTool('update_card', {
|
|
1783
|
-
title: 'Update
|
|
1783
|
+
title: 'Update Card',
|
|
1784
1784
|
annotations: WRITE,
|
|
1785
|
-
description: "Update a
|
|
1785
|
+
description: "Update a card: its fields (title, description, script, notes, status, platform, cover, stage), its POSTS (one per platform, which is how it publishes), its ASSETS (the media on it, in order), and its SCHEDULE. posts and assets are DECLARATIVE: pass the WHOLE set, because anything you leave out is removed. Posts key on platform. Assets key on id, and THE ARRAY ORDER IS THE carousel ORDER, so reordering is just sending the same ids in a different order; keep an existing asset by id, add a new one by assetUrl or outputId. scheduledAt sets the time on the card AND every post (pass null to clear); give a post its own scheduledAt to override it for that platform. To publish NOW, use publish_post. Pass spaceId to MOVE the card to another space; without a stage it lands in the target space's stage whose slug matches its current one, or that space's first stage. Pass cardIds to update several cards at once, which crossed with spaceId is how a selection moves in one call; fields that describe ONE card (title, notes, script, cover) still need exactly one. Requires the planner:write scope.",
|
|
1786
1786
|
inputSchema: {
|
|
1787
|
-
|
|
1787
|
+
cardId: z.string().describe('The card id.'),
|
|
1788
1788
|
title: z.string().optional(),
|
|
1789
1789
|
platform: z.enum(POST_PLATFORMS).optional(),
|
|
1790
1790
|
status: z.enum(['draft', 'active', 'completed', 'archived']).optional(),
|
|
1791
1791
|
stage: z.string().optional().describe('Move the post to this stage (id, slug, or name).'),
|
|
1792
|
+
spaceId: z
|
|
1793
|
+
.string()
|
|
1794
|
+
.optional()
|
|
1795
|
+
.describe("Move the card to a different space (id or slug). Without a stage, it lands in that space's stage whose slug matches its current one, or that space's first stage."),
|
|
1796
|
+
cardIds: z
|
|
1797
|
+
.array(z.string())
|
|
1798
|
+
.optional()
|
|
1799
|
+
.describe('Update several cards at once. Fields that describe ONE card (title, notes, script, cover) still require exactly one.'),
|
|
1792
1800
|
script: z.string().optional(),
|
|
1793
1801
|
notes: z.string().optional(),
|
|
1794
1802
|
coverUrl: z.string().optional().describe('Public URL for the post cover.'),
|
|
@@ -1804,11 +1812,11 @@ export function registerTools(server, opts) {
|
|
|
1804
1812
|
.string()
|
|
1805
1813
|
.nullable()
|
|
1806
1814
|
.optional()
|
|
1807
|
-
.describe('ISO time to publish. Sets the
|
|
1808
|
-
|
|
1809
|
-
.array(
|
|
1815
|
+
.describe('ISO time to publish. Sets the card AND every post. null clears the schedule.'),
|
|
1816
|
+
posts: z
|
|
1817
|
+
.array(cardPostSchema)
|
|
1810
1818
|
.optional()
|
|
1811
|
-
.describe("The
|
|
1819
|
+
.describe("The card's posts, each { platform, format?, connectedAccountId?, platformSpecificData?, scheduledAt?, status? }. REPLACES the set, keyed by platform; [] detaches all."),
|
|
1812
1820
|
assets: z
|
|
1813
1821
|
.array(postAssetSchema)
|
|
1814
1822
|
.optional()
|
|
@@ -1817,14 +1825,22 @@ export function registerTools(server, opts) {
|
|
|
1817
1825
|
}, async (args, extra) => {
|
|
1818
1826
|
try {
|
|
1819
1827
|
const client = await getClient(extra);
|
|
1820
|
-
const {
|
|
1828
|
+
const { cardId, cardIds, posts, assets, ...input } = args;
|
|
1821
1829
|
// The two declarative arrays are `unknown[]` in the schema (their entries are free-form objects the
|
|
1822
1830
|
// server validates), so they are cast at this one boundary rather than duplicating the shape in zod.
|
|
1823
|
-
|
|
1831
|
+
const patch = {
|
|
1824
1832
|
...input,
|
|
1825
|
-
...(
|
|
1833
|
+
...(posts !== undefined ? { posts: posts } : {}),
|
|
1826
1834
|
...(assets !== undefined ? { assets: assets } : {}),
|
|
1827
|
-
}
|
|
1835
|
+
};
|
|
1836
|
+
// `cardIds` widens the path id, matching update_folder's folder_id / folder_ids. One card still
|
|
1837
|
+
// goes through updateCard so the single-card response shape is unchanged for every caller.
|
|
1838
|
+
const targets = cardIds?.length ? cardIds : [cardId];
|
|
1839
|
+
if (targets.length > 1) {
|
|
1840
|
+
const cards = await client.updateCards(targets, patch);
|
|
1841
|
+
return text(`Updated ${cards.length} cards.`);
|
|
1842
|
+
}
|
|
1843
|
+
return postSummaryResult(await client.updateCard(targets[0], patch), 'Updated');
|
|
1828
1844
|
}
|
|
1829
1845
|
catch (err) {
|
|
1830
1846
|
return errorResult(err);
|
|
@@ -1849,7 +1865,7 @@ export function registerTools(server, opts) {
|
|
|
1849
1865
|
server.registerTool('create_tag', {
|
|
1850
1866
|
title: 'Create Tag',
|
|
1851
1867
|
annotations: WRITE,
|
|
1852
|
-
description: "Create a tag in the account's tag library (the name is lowercased). Tags organize posts; apply them with the `tags` field on create_card / update_card. Requires the
|
|
1868
|
+
description: "Create a tag in the account's tag library (the name is lowercased). Tags organize posts; apply them with the `tags` field on create_card / update_card. Requires the planner:write scope.",
|
|
1853
1869
|
inputSchema: {
|
|
1854
1870
|
name: z.string().describe('The tag name (lowercased on save).'),
|
|
1855
1871
|
},
|
|
@@ -1866,7 +1882,7 @@ export function registerTools(server, opts) {
|
|
|
1866
1882
|
server.registerTool('update_tag', {
|
|
1867
1883
|
title: 'Update Tag',
|
|
1868
1884
|
annotations: WRITE,
|
|
1869
|
-
description: 'Rename a tag (preserves its assignments on all posts). To detach a tag from one post, set that post\'s `tags` without it via update_card. Requires the
|
|
1885
|
+
description: 'Rename a tag (preserves its assignments on all posts). To detach a tag from one post, set that post\'s `tags` without it via update_card. Requires the planner:write scope.',
|
|
1870
1886
|
inputSchema: {
|
|
1871
1887
|
tagId: z.string().describe('The tag id (from list_tags).'),
|
|
1872
1888
|
name: z.string().describe('The new tag name (lowercased on save).'),
|
|
@@ -1884,7 +1900,7 @@ export function registerTools(server, opts) {
|
|
|
1884
1900
|
server.registerTool('delete_tag', {
|
|
1885
1901
|
title: 'Delete Tag',
|
|
1886
1902
|
annotations: WRITE,
|
|
1887
|
-
description: "Delete a tag from the account's library. This DESTROYS the tag and removes it from every post it was on. To just detach a tag from one post, set that post's `tags` without it via update_card instead. Requires the
|
|
1903
|
+
description: "Delete a tag from the account's library. This DESTROYS the tag and removes it from every post it was on. To just detach a tag from one post, set that post's `tags` without it via update_card instead. Requires the planner:write scope.",
|
|
1888
1904
|
inputSchema: {
|
|
1889
1905
|
tagId: z.string().describe('The tag id (from list_tags).'),
|
|
1890
1906
|
},
|
|
@@ -1897,19 +1913,19 @@ export function registerTools(server, opts) {
|
|
|
1897
1913
|
return errorResult(err);
|
|
1898
1914
|
}
|
|
1899
1915
|
});
|
|
1900
|
-
// --
|
|
1901
|
-
server.registerTool('
|
|
1916
|
+
// -- publish_post ---------------------------------------------------------
|
|
1917
|
+
server.registerTool('publish_post', {
|
|
1902
1918
|
title: 'Publish Post',
|
|
1903
1919
|
annotations: PUBLISH,
|
|
1904
|
-
description: "Publish a
|
|
1920
|
+
description: "Publish a card's posts NOW: every post on the card, or only the named platform's post when `platform` is given. Each post must have a connected account. Requires a key with the publish:write scope; holding that scope is the account owner's consent to autonomous publishing. Returns one result per post.",
|
|
1905
1921
|
inputSchema: {
|
|
1906
|
-
|
|
1907
|
-
platform: z.enum(POST_PLATFORMS).optional().describe('Publish only this platform. Omit to publish all
|
|
1922
|
+
cardId: z.string().describe('The card id to publish.'),
|
|
1923
|
+
platform: z.enum(POST_PLATFORMS).optional().describe('Publish only this platform. Omit to publish all posts.'),
|
|
1908
1924
|
},
|
|
1909
1925
|
}, async (args, extra) => {
|
|
1910
1926
|
try {
|
|
1911
1927
|
const client = await getClient(extra);
|
|
1912
|
-
return publishResult(await client.
|
|
1928
|
+
return publishResult(await client.publishPost(args.cardId, { platform: args.platform }));
|
|
1913
1929
|
}
|
|
1914
1930
|
catch (err) {
|
|
1915
1931
|
return errorResult(err);
|
|
@@ -2031,7 +2047,7 @@ export function registerTools(server, opts) {
|
|
|
2031
2047
|
server.registerTool('list_connected_accounts', {
|
|
2032
2048
|
title: 'List Connected Accounts',
|
|
2033
2049
|
annotations: READ,
|
|
2034
|
-
description: "List the social accounts the owner has connected (the publish targets), default first. Use an account's id as connectedAccountId on
|
|
2050
|
+
description: "List the social accounts the owner has connected (the publish targets), default first. Use an account's id as connectedAccountId on a post in update_card, then publish_post. Read-only: connecting an account is done in the ContentHero app.",
|
|
2035
2051
|
}, async (extra) => {
|
|
2036
2052
|
try {
|
|
2037
2053
|
const client = await getClient(extra);
|