mcp-server-autoshorts 1.0.0 → 2.3.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/README.md ADDED
@@ -0,0 +1,166 @@
1
+ # mcp-server-autoshorts
2
+
3
+ MCP server for [AutoShort.org](https://autoshort.org) — generate AI videos from Claude, Cursor, and other MCP clients.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx mcp-server-autoshorts --api-key sk_live_your_key_here
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ ### Claude Desktop
14
+
15
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "autoshort": {
21
+ "command": "npx",
22
+ "args": ["-y", "mcp-server-autoshorts", "--api-key", "sk_live_your_key_here"]
23
+ }
24
+ }
25
+ }
26
+ ```
27
+
28
+ ### Cursor
29
+
30
+ Add to `.cursor/mcp.json`:
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "autoshort": {
36
+ "command": "npx",
37
+ "args": ["-y", "mcp-server-autoshorts", "--api-key", "sk_live_your_key_here"]
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ### Environment Variable
44
+
45
+ Instead of `--api-key`, set `AUTOSHORT_API_KEY`:
46
+
47
+ ```bash
48
+ export AUTOSHORT_API_KEY=sk_live_your_key_here
49
+ npx mcp-server-autoshorts
50
+ ```
51
+
52
+ ## Recommended flow: Director mode
53
+
54
+ When the user cares about the script or the shots, agree the video with them in the chat first,
55
+ then let AutoShort render exactly that:
56
+
57
+ 1. Write the script with the user — narration per scene, and what each scene should show.
58
+ 2. `autoshort_draft_video` with `scenes: [{ narration, visual?, seconds? }]` — **free**, nothing is
59
+ rendered or charged. Narration is stored and read **verbatim**; `visual` becomes that scene's
60
+ image prompt as written (plus the art style).
61
+ 3. Show the user the draft: scenes, `estimatedDurationSeconds`, `estimatedCredits`, `warnings[]`
62
+ (for example: the words take ~22s to read but 30s was requested — the duration is never
63
+ silently changed). Apply their changes with `autoshort_update_draft`.
64
+ 4. Only after the user approves: `autoshort_render_draft`. Credits are charged at this moment,
65
+ before any rendering work, and refunded automatically if the render fails for good. A
66
+ repeated call charges nothing.
67
+ 5. Poll `autoshort_get_video` every 20-30 seconds until `COMPLETED`.
68
+ 6. To change a scene of the finished video: `autoshort_revise_scene` creates a NEW draft with the
69
+ change (the original is untouched); render it as a new video.
70
+
71
+ No script yet? `autoshort_draft_video` with a `brief` writes a draft for review (needs a positive
72
+ credit balance; at most 20 per hour).
73
+
74
+ ## The whole workflow, no website
75
+
76
+ An agent can run everything through MCP. A person does only three one-time steps:
77
+
78
+ 1. **Authorize the connector** (OAuth "Allow" in Claude/ChatGPT) or create an API key.
79
+ 2. **Platform consent once per platform**: `autoshort_get_connection_status` returns a short,
80
+ single-use `connectUrl` that opens YouTube/TikTok consent directly; the agent polls the same
81
+ tool until `connected: true` and carries on.
82
+ 3. **A payment method once**: pay one checkout link from `autoshort_get_buy_credits_url`, or
83
+ approve auto-recharge (`autoshort_setup_auto_recharge`: a pack and a monthly cap, then a card
84
+ saved on Whop) so later top-ups run through `autoshort_buy_credits` with no link.
85
+
86
+ Every error carries a machine-readable `code` and a `nextAction` (the tool to call next, or the
87
+ `connectUrl` / `checkoutUrl` for the human). Anything still running returns `pollAfterSeconds`;
88
+ webhooks are available instead of polling. Every paid tool takes `idempotencyKey`. Each API key /
89
+ connector has a daily credit cap (default 500) on everything it commits through MCP (and through
90
+ `POST /api/v1/videos/generate`), which an unattended agent cannot pass
91
+ (`autoshort_get_limits`; raising it needs the signed-in owner).
92
+
93
+ ## Available Tools
94
+
95
+ The tool list comes from the AutoShort server itself (`https://autoshort.org/api/mcp`), so this
96
+ package and the remote connector (claude.ai custom connector) always expose the same tools.
97
+
98
+ | Tool | Description | Cost |
99
+ |------|-------------|------|
100
+ | `autoshort_get_capabilities` | The end-to-end workflow, the human steps, limits | free |
101
+ | `autoshort_list_options` | Voices (premium + price), art styles, caption themes, ratios, durations per tool, motion prices | free |
102
+ | `autoshort_estimate_cost` | Price any paid call before making it | free |
103
+ | `autoshort_draft_video` | Create a draft from agreed `scenes[]` (or a `brief`) | free (brief: needs credits) |
104
+ | `autoshort_get_draft` | Read a draft with estimates and warnings | free |
105
+ | `autoshort_update_draft` | Edit / insert / remove / reorder scenes | free |
106
+ | `autoshort_render_draft` | Render an approved draft | charged here |
107
+ | `autoshort_revise_scene` | Change a scene of a finished video → new draft | free (render is charged) |
108
+ | `autoshort_generate_video` | One-shot video from a topic (AutoShort writes the script) | charged at render |
109
+ | `autoshort_generate_chat_video` | One-shot video from a creative brief | charged at render |
110
+ | `autoshort_generate_product_ad` | Product ad from a public product URL | charged at render |
111
+ | `autoshort_generate_image_to_video` | Animate one image (`imagePath` is read locally) | charged at submit |
112
+ | `autoshort_ugc_upload_recording` | App screen recording by `recordingUrl` / `recordingBase64` (`recordingPath` read locally) → `recordingAssetId` | free |
113
+ | `autoshort_ugc_create_campaign` … `autoshort_ugc_get_campaign` | Silent UGC: campaign, hooks, preview, batch render | see tool |
114
+ | `autoshort_get_video` | Video status and details | free |
115
+ | `autoshort_list_videos` | Your videos with pagination | free |
116
+ | `autoshort_cancel_video` | Cancel before rendering starts; refunded through the ledger | free |
117
+ | `autoshort_list_niches` | Niches, art styles, qualities | free |
118
+ | `autoshort_list_social_accounts` | Connected YouTube/TikTok accounts and today's limits (no tokens) | free |
119
+ | `autoshort_get_connection_status` | Connected? If not, a one-click `connectUrl`; poll until connected | free |
120
+ | `autoshort_publish_video` | YouTube upload or TikTok Drafts; idempotent per video + platform; AI disclosure set | free |
121
+ | `autoshort_list_series` / `autoshort_create_series` / `autoshort_update_series` | Autopilot series | free (each video is charged by the scheduler) |
122
+ | `autoshort_pause_series` / `autoshort_resume_series` | Stop / restart a series | free |
123
+ | `autoshort_create_webhook` / `autoshort_list_webhooks` / `autoshort_delete_webhook` | Signed `video.completed` / `video.failed` POSTs | free |
124
+ | `autoshort_get_credit_balance` | Credit balance and plan | free |
125
+ | `autoshort_get_usage_stats` | API usage statistics | free |
126
+ | `autoshort_get_subscription` | Subscription plan status | free |
127
+ | `autoshort_get_limits` / `autoshort_set_limits` | Daily agent spending cap, auto-recharge, platform caps | free |
128
+ | `autoshort_get_buy_credits_url` | Checkout link for a pack or plan (no email in the URL) | free |
129
+ | `autoshort_setup_auto_recharge` / `autoshort_buy_credits` / `autoshort_disable_auto_recharge` | Opt-in top-ups within an owner-approved monthly cap | the pack price |
130
+
131
+ Every call is authenticated with your API key, and a paid call is refused with 402 before any
132
+ work starts when the balance is short.
133
+
134
+ Webhooks: register once with `autoshort_create_webhook` (public https only); each POST is signed
135
+ with `X-Webhook-Signature` = hex HMAC-SHA256 of the raw body with the secret returned at creation.
136
+ Or poll `autoshort_get_video`; a PENDING video that cannot render returns `blockedReason` (for
137
+ example `INSUFFICIENT_CREDITS`) instead of a countdown.
138
+
139
+ API keys are managed in the dashboard (Developers → API keys); there is no tool for listing them.
140
+
141
+ New API keys include `credits:read` and `usage:read`. A key created earlier without them gets a
142
+ 403 from `autoshort_get_credit_balance` whose message links to the page where you create a key
143
+ with that scope.
144
+
145
+ ## Resources
146
+
147
+ | URI | Description |
148
+ |-----|-------------|
149
+ | `autoshort://credits/balance` | Current credit balance |
150
+ | `autoshort://usage/rate-limit` | API rate limit status |
151
+
152
+ ## Prompts
153
+
154
+ | Name | Description |
155
+ |------|-------------|
156
+ | `generate_video` | Step-by-step guide: make, approve, publish |
157
+
158
+ ## Get Your API Key
159
+
160
+ 1. Sign up at [autoshort.org](https://autoshort.org)
161
+ 2. Go to [Developers](https://autoshort.org/en/developers)
162
+ 3. Create an API key with desired scopes
163
+
164
+ ## License
165
+
166
+ MIT
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Values the AutoShort API accepts or charges, as this package advertises them to agents.
3
+ *
4
+ * This package is published on its own and cannot import the app, so these are copies.
5
+ * Each copy is pinned to its source by src/lib/__tests__/mcp-stdio-catalog-sync.test.ts in
6
+ * the app (VideoStatus enum, MOTION_LANGUAGE_CODES, CHAT_MESSAGE_MAX_CHARS, FEATURE_COSTS,
7
+ * VideoQuality). Change the source and that test names the line to change here. Hand-typed
8
+ * values are how the tools came to offer status GENERATING (rejected by the API), languages
9
+ * en/vi only (the API speaks nine) and "40-150 credits" (an API video costs 65).
10
+ */
11
+ /** Prisma VideoStatus, in schema order. */
12
+ export declare const VIDEO_STATUSES: readonly ["PENDING", "GENERATING_SCRIPT", "GENERATING_VOICE", "FETCHING_MEDIA", "RENDERING", "COMPLETED", "FAILED", "DRAFT"];
13
+ /** MOTION_LANGUAGE_CODES: what POST /api/videos/chat honours as an explicit language. */
14
+ export declare const CHAT_VIDEO_LANGUAGES: readonly ["en", "es", "pt", "fr", "de", "it", "id", "tr", "vi"];
15
+ /** CHAT_MESSAGE_MAX_CHARS. */
16
+ export declare const CHAT_MESSAGE_MAX_CHARS = 4000;
17
+ /** Prisma VideoQuality. */
18
+ export declare const VIDEO_QUALITIES: readonly ["HD_720", "FULL_HD_1080"];
19
+ /** FEATURE_COSTS.video_standard and FEATURE_COSTS.voice_over_premium. */
20
+ export declare const CREDIT_COSTS: {
21
+ readonly videoStandard: 40;
22
+ readonly elevenLabsVoice: 25;
23
+ };
24
+ /** Every /api/v1 video is narrated by ElevenLabs, so the render gate asks for both. */
25
+ export declare const API_VIDEO_CREDITS: number;
26
+ export declare const API_VIDEO_COST_TEXT: string;
27
+ export declare const POLL_HINT: string;
28
+ /**
29
+ * FEATURE_COSTS.video_image_motion.
30
+ *
31
+ * Hand-copied like every other number here, and this one is the figure an agent budgets
32
+ * against BEFORE it spends: image-to-video is the only tool whose endpoint charges at submit.
33
+ * Pinned to the app constant by src/lib/__tests__/mcp-stdio-catalog-sync.test.ts.
34
+ */
35
+ export declare const IMAGE_TO_VIDEO_CREDITS = 35;
36
+ /**
37
+ * No refund promise here, deliberately.
38
+ *
39
+ * This used to say the credits are "refunded if the clip is never produced". That is not an
40
+ * invariant the pipeline holds. The operator-timeout path in cron/process-videos does call
41
+ * refundIfChargedForFailedVideo, and so does the admin refuse route — but TWO cases still end
42
+ * FAILED with money taken: that helper's own `refund-failed` outcome, and
43
+ * cron/retry-stuck-videos' permanentlyStuck `updateMany`, which has no refund call (reachable
44
+ * for one of these rows only once the operator has delivered and the render has then stalled
45
+ * MAX_RETRIES times).
46
+ *
47
+ * A longer list was checked and NARROWED: admin/videos is a GET-only dashboard whose
48
+ * `status: "FAILED"` occurrences are `where` filters, admin/videos/[id]/operator refunds
49
+ * BEFORE calling failVideo, and videos/[id]/render cannot reach its unrefunded FAILED write
50
+ * for these rows at all — that write is gated on `claimedByRequest` while every
51
+ * VEO_3_1_OPERATOR row returns ~230 lines earlier. Two real cases, not five.
52
+ *
53
+ * So the usual case refunds and the edges do not, which makes "it is refunded" a promise we
54
+ * cannot keep. Say what is true and name the check instead, so an agent that was charged for
55
+ * nothing can find out.
56
+ */
57
+ export declare const IMAGE_TO_VIDEO_COST_TEXT: string;
58
+ /**
59
+ * What an agent actually gets if the clip is fulfilled in operator mode.
60
+ *
61
+ * Image-to-video always renders through VEO_3_1_OPERATOR, which is a human driving a browser
62
+ * (scripts/veo-operator/run.mjs) — not an automatic provider. If nobody fulfils it inside the
63
+ * wait window the video FAILS. The refund wording is hedged for the reason in
64
+ * IMAGE_TO_VIDEO_COST_TEXT above; it previously claimed "any charge is refunded" flatly.
65
+ */
66
+ export declare const OPERATOR_MODE_WARNING: string;
67
+ /**
68
+ * Image-to-video dedupes on a requestId this package derives from the image bytes and the
69
+ * motion prompt — not on an Idempotency-Key header. The id carries no time component on
70
+ * purpose; the 24h bound is a continuous window on the server's lookup, so no two
71
+ * near-simultaneous retries can fall on different sides of it.
72
+ */
73
+ export declare const IMAGE_TO_VIDEO_IDEMPOTENCY_HINT: string;
74
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,cAAc,8HASjB,CAAC;AAEX,yFAAyF;AACzF,eAAO,MAAM,oBAAoB,iEAAkE,CAAC;AAEpG,8BAA8B;AAC9B,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C,2BAA2B;AAC3B,eAAO,MAAM,eAAe,qCAAsC,CAAC;AAEnE,yEAAyE;AACzE,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,uFAAuF;AACvF,eAAO,MAAM,iBAAiB,QAA4D,CAAC;AAE3F,eAAO,MAAM,mBAAmB,QAE2D,CAAC;AAE5F,eAAO,MAAM,SAAS,QAEmE,CAAC;AAE1F;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,wBAAwB,QAI8D,CAAC;AAEpG;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,QAIe,CAAC;AAElD;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,QAMsB,CAAC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Values the AutoShort API accepts or charges, as this package advertises them to agents.
3
+ *
4
+ * This package is published on its own and cannot import the app, so these are copies.
5
+ * Each copy is pinned to its source by src/lib/__tests__/mcp-stdio-catalog-sync.test.ts in
6
+ * the app (VideoStatus enum, MOTION_LANGUAGE_CODES, CHAT_MESSAGE_MAX_CHARS, FEATURE_COSTS,
7
+ * VideoQuality). Change the source and that test names the line to change here. Hand-typed
8
+ * values are how the tools came to offer status GENERATING (rejected by the API), languages
9
+ * en/vi only (the API speaks nine) and "40-150 credits" (an API video costs 65).
10
+ */
11
+ /** Prisma VideoStatus, in schema order. */
12
+ export const VIDEO_STATUSES = [
13
+ 'PENDING',
14
+ 'GENERATING_SCRIPT',
15
+ 'GENERATING_VOICE',
16
+ 'FETCHING_MEDIA',
17
+ 'RENDERING',
18
+ 'COMPLETED',
19
+ 'FAILED',
20
+ 'DRAFT',
21
+ ];
22
+ /** MOTION_LANGUAGE_CODES: what POST /api/videos/chat honours as an explicit language. */
23
+ export const CHAT_VIDEO_LANGUAGES = ['en', 'es', 'pt', 'fr', 'de', 'it', 'id', 'tr', 'vi'];
24
+ /** CHAT_MESSAGE_MAX_CHARS. */
25
+ export const CHAT_MESSAGE_MAX_CHARS = 4000;
26
+ /** Prisma VideoQuality. */
27
+ export const VIDEO_QUALITIES = ['HD_720', 'FULL_HD_1080'];
28
+ /** FEATURE_COSTS.video_standard and FEATURE_COSTS.voice_over_premium. */
29
+ export const CREDIT_COSTS = {
30
+ videoStandard: 40,
31
+ elevenLabsVoice: 25,
32
+ };
33
+ /** Every /api/v1 video is narrated by ElevenLabs, so the render gate asks for both. */
34
+ export const API_VIDEO_CREDITS = CREDIT_COSTS.videoStandard + CREDIT_COSTS.elevenLabsVoice;
35
+ export const API_VIDEO_COST_TEXT = `Costs ${API_VIDEO_CREDITS} credits (${CREDIT_COSTS.videoStandard} render + ` +
36
+ `${CREDIT_COSTS.elevenLabsVoice} ElevenLabs voice); art style does not change the price.`;
37
+ export const POLL_HINT = 'Rendering is asynchronous: poll autoshort_get_video every 20-30 seconds until status is COMPLETED or FAILED. ' +
38
+ 'If get_video returns blockedReason, stop polling and act on it (e.g. top up credits).';
39
+ /**
40
+ * FEATURE_COSTS.video_image_motion.
41
+ *
42
+ * Hand-copied like every other number here, and this one is the figure an agent budgets
43
+ * against BEFORE it spends: image-to-video is the only tool whose endpoint charges at submit.
44
+ * Pinned to the app constant by src/lib/__tests__/mcp-stdio-catalog-sync.test.ts.
45
+ */
46
+ export const IMAGE_TO_VIDEO_CREDITS = 35;
47
+ /**
48
+ * No refund promise here, deliberately.
49
+ *
50
+ * This used to say the credits are "refunded if the clip is never produced". That is not an
51
+ * invariant the pipeline holds. The operator-timeout path in cron/process-videos does call
52
+ * refundIfChargedForFailedVideo, and so does the admin refuse route — but TWO cases still end
53
+ * FAILED with money taken: that helper's own `refund-failed` outcome, and
54
+ * cron/retry-stuck-videos' permanentlyStuck `updateMany`, which has no refund call (reachable
55
+ * for one of these rows only once the operator has delivered and the render has then stalled
56
+ * MAX_RETRIES times).
57
+ *
58
+ * A longer list was checked and NARROWED: admin/videos is a GET-only dashboard whose
59
+ * `status: "FAILED"` occurrences are `where` filters, admin/videos/[id]/operator refunds
60
+ * BEFORE calling failVideo, and videos/[id]/render cannot reach its unrefunded FAILED write
61
+ * for these rows at all — that write is gated on `claimedByRequest` while every
62
+ * VEO_3_1_OPERATOR row returns ~230 lines earlier. Two real cases, not five.
63
+ *
64
+ * So the usual case refunds and the edges do not, which makes "it is refunded" a promise we
65
+ * cannot keep. Say what is true and name the check instead, so an agent that was charged for
66
+ * nothing can find out.
67
+ */
68
+ export const IMAGE_TO_VIDEO_COST_TEXT = `Costs ${IMAGE_TO_VIDEO_CREDITS} credits, and unlike every other tool here it is charged ` +
69
+ 'the moment the job is accepted, not when the clip is delivered. A failed clip is normally ' +
70
+ 'refunded automatically, but that is not guaranteed on every failure path: if the video ends ' +
71
+ 'FAILED, check autoshort_get_credit_balance and report a missing refund rather than assuming it.';
72
+ /**
73
+ * What an agent actually gets if the clip is fulfilled in operator mode.
74
+ *
75
+ * Image-to-video always renders through VEO_3_1_OPERATOR, which is a human driving a browser
76
+ * (scripts/veo-operator/run.mjs) — not an automatic provider. If nobody fulfils it inside the
77
+ * wait window the video FAILS. The refund wording is hedged for the reason in
78
+ * IMAGE_TO_VIDEO_COST_TEXT above; it previously claimed "any charge is refunded" flatly.
79
+ */
80
+ export const OPERATOR_MODE_WARNING = 'Fulfilment is MANUAL: a human operator animates the image, it is not an automatic render. ' +
81
+ 'If nobody fulfils it within VEO_OPERATOR_WAIT_MINUTES (10 in production) the video FAILS ' +
82
+ 'with "could not be produced in time" and the charge is normally refunded automatically. ' +
83
+ 'Do not build an unattended loop on this tool.';
84
+ /**
85
+ * Image-to-video dedupes on a requestId this package derives from the image bytes and the
86
+ * motion prompt — not on an Idempotency-Key header. The id carries no time component on
87
+ * purpose; the 24h bound is a continuous window on the server's lookup, so no two
88
+ * near-simultaneous retries can fall on different sides of it.
89
+ */
90
+ export const IMAGE_TO_VIDEO_IDEMPOTENCY_HINT = 'Retry-safe: re-calling with the same image and motionPrompt returns the first job ' +
91
+ '(duplicate: true) for 24 hours instead of charging again. If that attempt FAILED, a retry ' +
92
+ 'refunds the dead attempt first and then makes a new clip, so one clip is never billed ' +
93
+ 'twice — whatever its age. In the one case where the old credits cannot be returned you get ' +
94
+ '409 STRANDED_CHARGE with the videoId and no new charge: report it, do not loop. Pass ' +
95
+ 'idempotencyKey to force a separate clip from identical inputs.';
96
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,2CAA2C;AAC3C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,SAAS;IACT,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;IAChB,WAAW;IACX,WAAW;IACX,QAAQ;IACR,OAAO;CACC,CAAC;AAEX,yFAAyF;AACzF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAEpG,8BAA8B;AAC9B,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAE3C,2BAA2B;AAC3B,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,cAAc,CAAU,CAAC;AAEnE,yEAAyE;AACzE,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,aAAa,EAAE,EAAE;IACjB,eAAe,EAAE,EAAE;CACX,CAAC;AAEX,uFAAuF;AACvF,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC,aAAa,GAAG,YAAY,CAAC,eAAe,CAAC;AAE3F,MAAM,CAAC,MAAM,mBAAmB,GAC9B,SAAS,iBAAiB,aAAa,YAAY,CAAC,aAAa,YAAY;IAC7E,GAAG,YAAY,CAAC,eAAe,0DAA0D,CAAC;AAE5F,MAAM,CAAC,MAAM,SAAS,GACpB,+GAA+G;IAC/G,uFAAuF,CAAC;AAE1F;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACnC,SAAS,sBAAsB,2DAA2D;IAC1F,4FAA4F;IAC5F,8FAA8F;IAC9F,iGAAiG,CAAC;AAEpG;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAChC,4FAA4F;IAC5F,2FAA2F;IAC3F,0FAA0F;IAC1F,+CAA+C,CAAC;AAElD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAC1C,oFAAoF;IACpF,4FAA4F;IAC5F,wFAAwF;IACxF,6FAA6F;IAC7F,uFAAuF;IACvF,gEAAgE,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * AutoShort API HTTP client, for the package's own resources (credit balance, rate limit).
3
+ * Tools do not use it: they are proxied to the remote /api/mcp registry (see proxy.ts).
4
+ */
5
+ import type { RateLimitInfo } from './types.js';
6
+ export declare class AutoShortClient {
7
+ private readonly apiKey;
8
+ private readonly baseUrl;
9
+ /** Last rate limit info from API response headers */
10
+ lastRateLimit: RateLimitInfo | null;
11
+ constructor(apiKey: string, baseUrl: string);
12
+ /** Generic API request with auth, error handling, rate limit capture */
13
+ request<T>(method: string, path: string, body?: unknown): Promise<T>;
14
+ getCreditBalance(): Promise<{
15
+ balance: number;
16
+ monthlyAllocation: number;
17
+ bonusCredits: number;
18
+ plan: string;
19
+ }>;
20
+ }
21
+ /** Typed API error with HTTP status and error code */
22
+ export declare class AutoShortApiError extends Error {
23
+ readonly status: number;
24
+ readonly code: string;
25
+ constructor(message: string, status: number, code: string);
26
+ }
27
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,qBAAa,eAAe;IAKxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,qDAAqD;IAC9C,aAAa,EAAE,aAAa,GAAG,IAAI,CAAQ;gBAG/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM;IAGlC,wEAAwE;IAClE,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAqCpE,gBAAgB;iBACW,MAAM;2BAAqB,MAAM;sBAAgB,MAAM;cAAQ,MAAM;;CAKvG;AAED,sDAAsD;AACtD,qBAAa,iBAAkB,SAAQ,KAAK;aAGxB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBAF5B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM;CAK/B"}
package/dist/client.js ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * AutoShort API HTTP client, for the package's own resources (credit balance, rate limit).
3
+ * Tools do not use it: they are proxied to the remote /api/mcp registry (see proxy.ts).
4
+ */
5
+ import { USER_AGENT } from './constants.js';
6
+ export class AutoShortClient {
7
+ apiKey;
8
+ baseUrl;
9
+ /** Last rate limit info from API response headers */
10
+ lastRateLimit = null;
11
+ constructor(apiKey, baseUrl) {
12
+ this.apiKey = apiKey;
13
+ this.baseUrl = baseUrl;
14
+ }
15
+ /** Generic API request with auth, error handling, rate limit capture */
16
+ async request(method, path, body) {
17
+ const url = `${this.baseUrl}${path}`;
18
+ const res = await fetch(url, {
19
+ method,
20
+ headers: {
21
+ 'Authorization': `Bearer ${this.apiKey}`,
22
+ 'Content-Type': 'application/json',
23
+ 'User-Agent': USER_AGENT,
24
+ },
25
+ body: body ? JSON.stringify(body) : undefined,
26
+ });
27
+ // Capture rate limit headers
28
+ const limit = res.headers.get('x-ratelimit-limit');
29
+ const remaining = res.headers.get('x-ratelimit-remaining');
30
+ const resetAt = res.headers.get('x-ratelimit-reset');
31
+ if (limit && remaining && resetAt) {
32
+ this.lastRateLimit = {
33
+ limit: parseInt(limit),
34
+ remaining: parseInt(remaining),
35
+ resetAt,
36
+ };
37
+ }
38
+ if (!res.ok) {
39
+ let errorBody = {};
40
+ try {
41
+ errorBody = await res.json();
42
+ }
43
+ catch { /* empty */ }
44
+ const msg = errorBody.error || `API error: ${res.status} ${res.statusText}`;
45
+ const code = errorBody.code || `HTTP_${res.status}`;
46
+ throw new AutoShortApiError(msg, res.status, code);
47
+ }
48
+ return res.json();
49
+ }
50
+ // ── Credits ──
51
+ async getCreditBalance() {
52
+ return this.request('GET', '/api/v1/credits/balance');
53
+ }
54
+ }
55
+ /** Typed API error with HTTP status and error code */
56
+ export class AutoShortApiError extends Error {
57
+ status;
58
+ code;
59
+ constructor(message, status, code) {
60
+ super(message);
61
+ this.status = status;
62
+ this.code = code;
63
+ this.name = 'AutoShortApiError';
64
+ }
65
+ }
66
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,MAAM,OAAO,eAAe;IAKP;IACA;IALnB,qDAAqD;IAC9C,aAAa,GAAyB,IAAI,CAAC;IAElD,YACmB,MAAc,EACd,OAAe;QADf,WAAM,GAAN,MAAM,CAAQ;QACd,YAAO,GAAP,OAAO,CAAQ;IAC/B,CAAC;IAEJ,wEAAwE;IACxE,KAAK,CAAC,OAAO,CAAI,MAAc,EAAE,IAAY,EAAE,IAAc;QAC3D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM;YACN,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACxC,cAAc,EAAE,kBAAkB;gBAClC,YAAY,EAAE,UAAU;aACzB;YACD,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC9C,CAAC,CAAC;QAEH,6BAA6B;QAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACrD,IAAI,KAAK,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC,aAAa,GAAG;gBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;gBACtB,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC;gBAC9B,OAAO;aACR,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,SAAS,GAAsC,EAAE,CAAC;YACtD,IAAI,CAAC;gBAAC,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,EAAsB,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC;YAC/E,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,IAAI,cAAc,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YAC5E,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;YACpD,MAAM,IAAI,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;IAClC,CAAC;IAED,gBAAgB;IAEhB,KAAK,CAAC,gBAAgB;QACpB,OAAO,IAAI,CAAC,OAAO,CACjB,KAAK,EAAE,yBAAyB,CACjC,CAAC;IACJ,CAAC;CAEF;AAED,sDAAsD;AACtD,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAGxB;IACA;IAHlB,YACE,OAAe,EACC,MAAc,EACd,IAAY;QAE5B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QAG5B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ /** Default AutoShort API base URL */
2
+ export declare const DEFAULT_BASE_URL = "https://autoshort.org";
3
+ /**
4
+ * Read from package.json so the version a client sees is the version that was published
5
+ * (it was hardcoded "2.0.0" while package.json said 2.1.0). `../package.json` resolves from
6
+ * both src/ (tests) and dist/ (the published build).
7
+ */
8
+ export declare const VERSION: string;
9
+ /** User-Agent header for API requests (the server tags videos made through it as MCP). */
10
+ export declare const USER_AGENT: string;
11
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,qCAAqC;AACrC,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,MAA2F,CAAC;AAElH,0FAA0F;AAC1F,eAAO,MAAM,UAAU,QAAoC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { createRequire } from 'node:module';
2
+ /** Default AutoShort API base URL */
3
+ export const DEFAULT_BASE_URL = 'https://autoshort.org';
4
+ /**
5
+ * Read from package.json so the version a client sees is the version that was published
6
+ * (it was hardcoded "2.0.0" while package.json said 2.1.0). `../package.json` resolves from
7
+ * both src/ (tests) and dist/ (the published build).
8
+ */
9
+ export const VERSION = createRequire(import.meta.url)('../package.json').version;
10
+ /** User-Agent header for API requests (the server tags videos made through it as MCP). */
11
+ export const USER_AGENT = `autoshort-mcp-server/${VERSION}`;
12
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,qCAAqC;AACrC,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAY,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAyB,CAAC,OAAO,CAAC;AAElH,0FAA0F;AAC1F,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,OAAO,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AutoShort MCP Server
4
+ *
5
+ * Enables AI agents (Claude, Cursor, etc.) to generate videos via AutoShort API.
6
+ * Usage: npx mcp-server-autoshorts --api-key sk_live_xxx
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
package/dist/index.js ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AutoShort MCP Server
4
+ *
5
+ * Enables AI agents (Claude, Cursor, etc.) to generate videos via AutoShort API.
6
+ * Usage: npx mcp-server-autoshorts --api-key sk_live_xxx
7
+ */
8
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { AutoShortClient } from './client.js';
11
+ import { DEFAULT_BASE_URL, VERSION } from './constants.js';
12
+ // ── Tools: proxied to the remote registry (src/app/api/mcp/tools.ts in the app) ──
13
+ import { ListToolsRequestSchema, CallToolRequestSchema, McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
14
+ import { RemoteToolProxy } from './proxy.js';
15
+ // ── Resources ──
16
+ import { registerCreditResource } from './resources/credits.js';
17
+ import { registerRateLimitResource } from './resources/rate-limit.js';
18
+ // ── Prompts ──
19
+ import { registerGenerateVideoPrompt } from './prompts/generate-video.js';
20
+ // ── CLI arg parsing ──
21
+ function parseArgs(argv) {
22
+ let apiKey = process.env.AUTOSHORT_API_KEY || '';
23
+ let baseUrl = DEFAULT_BASE_URL;
24
+ for (let i = 0; i < argv.length; i++) {
25
+ if (argv[i] === '--api-key' && argv[i + 1]) {
26
+ apiKey = argv[++i];
27
+ }
28
+ else if (argv[i] === '--base-url' && argv[i + 1]) {
29
+ baseUrl = argv[++i];
30
+ }
31
+ else if (argv[i] === '--help' || argv[i] === '-h') {
32
+ console.error(`autoshort-mcp-server v${VERSION}
33
+
34
+ Usage: autoshort-mcp --api-key <key> [--base-url <url>]
35
+
36
+ Options:
37
+ --api-key <key> AutoShort API key (or set AUTOSHORT_API_KEY env var)
38
+ --base-url <url> API base URL (default: ${DEFAULT_BASE_URL})
39
+ --help, -h Show this help message
40
+
41
+ Get your API key at: https://autoshort.org/en/developers`);
42
+ process.exit(0);
43
+ }
44
+ }
45
+ if (!apiKey) {
46
+ console.error('Error: API key required. Use --api-key <key> or set AUTOSHORT_API_KEY environment variable.');
47
+ console.error('Get your API key at: https://autoshort.org/en/developers');
48
+ process.exit(1);
49
+ }
50
+ return { apiKey, baseUrl };
51
+ }
52
+ // ── Main ──
53
+ async function main() {
54
+ const { apiKey, baseUrl } = parseArgs(process.argv.slice(2));
55
+ const client = new AutoShortClient(apiKey, baseUrl);
56
+ const server = new McpServer({
57
+ name: 'autoshort-mcp-server',
58
+ version: VERSION,
59
+ });
60
+ // Tools: the remote server's registry, so stdio and the remote connector list the same set.
61
+ const proxy = new RemoteToolProxy(apiKey, baseUrl);
62
+ server.server.registerCapabilities({ tools: { listChanged: false } });
63
+ server.server.setRequestHandler(ListToolsRequestSchema, async () => {
64
+ try {
65
+ return { tools: await proxy.listTools() };
66
+ }
67
+ catch (e) {
68
+ throw new McpError(ErrorCode.InternalError, `Could not load AutoShort tools: ${e instanceof Error ? e.message : String(e)}`);
69
+ }
70
+ });
71
+ server.server.setRequestHandler(CallToolRequestSchema, async (request) => proxy.callTool(request.params.name, (request.params.arguments ?? {})));
72
+ // Register resources
73
+ registerCreditResource(server, client);
74
+ registerRateLimitResource(server, client);
75
+ // Register prompts
76
+ registerGenerateVideoPrompt(server);
77
+ // Connect via stdio transport
78
+ const transport = new StdioServerTransport();
79
+ await server.connect(transport);
80
+ }
81
+ main().catch((error) => {
82
+ console.error('Fatal error:', error);
83
+ process.exit(1);
84
+ });
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Video generation prompt template
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function registerGenerateVideoPrompt(server: McpServer): void;
6
+ //# sourceMappingURL=generate-video.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-video.d.ts","sourceRoot":"","sources":["../../src/prompts/generate-video.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,QAoC5D"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Video generation prompt template
3
+ */
4
+ import { z } from 'zod';
5
+ import { API_VIDEO_COST_TEXT, CREDIT_COSTS } from '../catalog.js';
6
+ export function registerGenerateVideoPrompt(server) {
7
+ server.prompt('generate_video', 'Step-by-step guide to generate an AI video with AutoShort', { topic: z.string().optional().describe('Video topic (optional — will prompt if not provided)') }, ({ topic }) => ({
8
+ messages: [{
9
+ role: 'user',
10
+ content: {
11
+ type: 'text',
12
+ text: `Help me generate an AI video with AutoShort.${topic ? ` Topic: "${topic}"` : ''}
13
+
14
+ If I already have a script or specific shots in mind, use director mode instead: agree the scenes with me,
15
+ call autoshort_draft_video with scenes[] (free, narration read verbatim), show me the draft, and only call
16
+ autoshort_render_draft after I approve.
17
+
18
+ Steps for a quick video from a topic:
19
+ 1. First, check my credit balance with autoshort_get_credit_balance
20
+ 2. List available options with autoshort_list_niches (niches, art styles, qualities)
21
+ 3. Generate the video with autoshort_generate_video using:
22
+ - topic: ${topic ? `"${topic}"` : '(ask the user)'}
23
+ - niche: Choose the best match from available niches
24
+ - duration: 60 (default, good for most videos)
25
+ - artStyle: AUTOSHORTS (default cinematic style)
26
+ 4. Poll autoshort_get_video every 20-30 seconds until status is COMPLETED or FAILED.
27
+ If it returns blockedReason (e.g. INSUFFICIENT_CREDITS), stop polling and tell the user what it says.
28
+ 5. Share the video URL when done.
29
+ 6. If I want it posted: autoshort_publish_video (YouTube upload or TikTok Drafts). If the platform is not connected,
30
+ give me the connectUrl from autoshort_get_connection_status and poll that tool until it says connected.
31
+
32
+ Credit costs: autoshort_generate_video: ${API_VIDEO_COST_TEXT} Chat videos: ${CREDIT_COSTS.videoStandard} credits with the default voice, +${CREDIT_COSTS.elevenLabsVoice} with ElevenLabs.
33
+ If autoshort_get_credit_balance returns 403 INSUFFICIENT_SCOPE, the API key lacks "credits:read": the error says where to create a key that has it.`,
34
+ },
35
+ }],
36
+ }));
37
+ }
38
+ //# sourceMappingURL=generate-video.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-video.js","sourceRoot":"","sources":["../../src/prompts/generate-video.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElE,MAAM,UAAU,2BAA2B,CAAC,MAAiB;IAC3D,MAAM,CAAC,MAAM,CACX,gBAAgB,EAChB,2DAA2D,EAC3D,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC,EAAE,EACjG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC;gBACT,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,+CAA+C,KAAK,CAAC,CAAC,CAAC,YAAY,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;cAUlF,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,gBAAgB;;;;;;;;;;0CAUX,mBAAmB,iBAAiB,YAAY,CAAC,aAAa,qCAAqC,YAAY,CAAC,eAAe;oJACrB;iBAC3I;aACF,CAAC;KACH,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The stdio server's tools are the REMOTE server's tools.
3
+ *
4
+ * tools/list and tools/call are forwarded to `${baseUrl}/api/mcp` (JSON-RPC over HTTP) with the
5
+ * user's API key, so this package and the remote connector expose exactly the same tool names,
6
+ * descriptions and schemas — one registry, in the app (src/app/api/mcp/tools.ts). Before this,
7
+ * the package defined its own 12 tools and the remote server 5 differently named ones, and an
8
+ * agent saw different tools depending on how it connected.
9
+ *
10
+ * The one thing a remote server cannot do is read the user's disk, so image-to-video keeps a
11
+ * local convenience: `imagePath` is read here and sent as `imageBase64`.
12
+ *
13
+ * Auth and money are enforced by the server on every call (401 without a valid key, 402 before
14
+ * any paid work); nothing here can bypass them.
15
+ */
16
+ export declare const IMAGE_TO_VIDEO_TOOL = "autoshort_generate_image_to_video";
17
+ export declare const UPLOAD_RECORDING_TOOL = "autoshort_ugc_upload_recording";
18
+ /** The largest image /api/videos/image-to-video accepts (IMAGE_TO_VIDEO_MAX_IMAGE_BYTES there). */
19
+ export declare const MAX_IMAGE_BYTES: number;
20
+ /**
21
+ * The largest recording this package sends inline (MAX_RECORDING_INLINE_BYTES on the server: the
22
+ * /api/mcp body cap leaves room for 10 MB as base64). Larger files (up to 50 MB) go by recordingUrl.
23
+ */
24
+ export declare const MAX_RECORDING_BYTES: number;
25
+ export interface RemoteTool {
26
+ name: string;
27
+ description?: string;
28
+ inputSchema: {
29
+ type: 'object';
30
+ properties?: Record<string, unknown>;
31
+ required?: string[];
32
+ [k: string]: unknown;
33
+ };
34
+ annotations?: Record<string, unknown>;
35
+ }
36
+ export interface ToolCallResult {
37
+ content: Array<{
38
+ type: 'text';
39
+ text: string;
40
+ }>;
41
+ isError?: boolean;
42
+ [k: string]: unknown;
43
+ }
44
+ type FetchLike = (input: string, init: {
45
+ method: string;
46
+ headers: Record<string, string>;
47
+ body: string;
48
+ }) => Promise<{
49
+ ok: boolean;
50
+ status: number;
51
+ json: () => Promise<unknown>;
52
+ }>;
53
+ export declare class RemoteError extends Error {
54
+ readonly status: number;
55
+ constructor(message: string, status: number);
56
+ }
57
+ /**
58
+ * The remote schema, plus the stdio-only local-file alternatives: `imagePath` for image-to-video
59
+ * and `recordingPath` for the UGC screen recording (read here, sent as base64).
60
+ */
61
+ export declare function localizeTool(tool: RemoteTool): RemoteTool;
62
+ export declare class RemoteToolProxy {
63
+ private readonly apiKey;
64
+ private readonly baseUrl;
65
+ private readonly fetchImpl;
66
+ private readonly readLocalFile;
67
+ private readonly localFileSize;
68
+ private nextId;
69
+ constructor(apiKey: string, baseUrl: string, fetchImpl?: FetchLike, readLocalFile?: (path: string) => Promise<Uint8Array>, localFileSize?: (path: string) => Promise<number>);
70
+ private rpc;
71
+ listTools(): Promise<RemoteTool[]>;
72
+ callTool(name: string, rawArgs?: Record<string, unknown>): Promise<ToolCallResult>;
73
+ }
74
+ export {};
75
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,eAAO,MAAM,mBAAmB,sCAAsC,CAAC;AACvE,eAAO,MAAM,qBAAqB,mCAAmC,CAAC;AAEtE,mGAAmG;AACnG,eAAO,MAAM,eAAe,QAAmB,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAmB,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACjH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAED,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC;IACnH,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9B,CAAC,CAAC;AAEH,qBAAa,WAAY,SAAQ,KAAK;aACS,MAAM,EAAE,MAAM;gBAA/C,OAAO,EAAE,MAAM,EAAkB,MAAM,EAAE,MAAM;CAI5D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CA0BzD;AAID,qBAAa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAPhC,OAAO,CAAC,MAAM,CAAK;gBAGA,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,SAAyC,EACpD,aAAa,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAY,EAC/D,aAAa,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAqC;YAGzF,GAAG;IA2BX,SAAS,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAKlC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CA6C7F"}
package/dist/proxy.js ADDED
@@ -0,0 +1,162 @@
1
+ /**
2
+ * The stdio server's tools are the REMOTE server's tools.
3
+ *
4
+ * tools/list and tools/call are forwarded to `${baseUrl}/api/mcp` (JSON-RPC over HTTP) with the
5
+ * user's API key, so this package and the remote connector expose exactly the same tool names,
6
+ * descriptions and schemas — one registry, in the app (src/app/api/mcp/tools.ts). Before this,
7
+ * the package defined its own 12 tools and the remote server 5 differently named ones, and an
8
+ * agent saw different tools depending on how it connected.
9
+ *
10
+ * The one thing a remote server cannot do is read the user's disk, so image-to-video keeps a
11
+ * local convenience: `imagePath` is read here and sent as `imageBase64`.
12
+ *
13
+ * Auth and money are enforced by the server on every call (401 without a valid key, 402 before
14
+ * any paid work); nothing here can bypass them.
15
+ */
16
+ import { readFile, stat } from 'node:fs/promises';
17
+ import { basename } from 'node:path';
18
+ import { USER_AGENT } from './constants.js';
19
+ export const IMAGE_TO_VIDEO_TOOL = 'autoshort_generate_image_to_video';
20
+ export const UPLOAD_RECORDING_TOOL = 'autoshort_ugc_upload_recording';
21
+ /** The largest image /api/videos/image-to-video accepts (IMAGE_TO_VIDEO_MAX_IMAGE_BYTES there). */
22
+ export const MAX_IMAGE_BYTES = 10 * 1024 * 1024;
23
+ /**
24
+ * The largest recording this package sends inline (MAX_RECORDING_INLINE_BYTES on the server: the
25
+ * /api/mcp body cap leaves room for 10 MB as base64). Larger files (up to 50 MB) go by recordingUrl.
26
+ */
27
+ export const MAX_RECORDING_BYTES = 10 * 1024 * 1024;
28
+ export class RemoteError extends Error {
29
+ status;
30
+ constructor(message, status) {
31
+ super(message);
32
+ this.status = status;
33
+ this.name = 'RemoteError';
34
+ }
35
+ }
36
+ /**
37
+ * The remote schema, plus the stdio-only local-file alternatives: `imagePath` for image-to-video
38
+ * and `recordingPath` for the UGC screen recording (read here, sent as base64).
39
+ */
40
+ export function localizeTool(tool) {
41
+ if (tool.name === IMAGE_TO_VIDEO_TOOL) {
42
+ const properties = { ...(tool.inputSchema.properties ?? {}) };
43
+ properties.imagePath = {
44
+ type: 'string',
45
+ description: 'Absolute path to a local JPG, PNG or WebP file up to 10MB (read and uploaded by this local server). Use instead of imageBase64.',
46
+ };
47
+ return {
48
+ ...tool,
49
+ inputSchema: {
50
+ ...tool.inputSchema,
51
+ properties,
52
+ // Either imagePath or imageBase64 — the server checks that an image arrived.
53
+ required: (tool.inputSchema.required ?? []).filter((r) => r !== 'imageBase64'),
54
+ },
55
+ };
56
+ }
57
+ if (tool.name === UPLOAD_RECORDING_TOOL) {
58
+ const properties = { ...(tool.inputSchema.properties ?? {}) };
59
+ properties.recordingPath = {
60
+ type: 'string',
61
+ description: 'Absolute path to a local MP4/MOV screen recording up to 10MB (read and uploaded by this local server). Larger files: pass recordingUrl.',
62
+ };
63
+ return { ...tool, inputSchema: { ...tool.inputSchema, properties } };
64
+ }
65
+ return tool;
66
+ }
67
+ const mb = (n) => (n / (1024 * 1024)).toFixed(1);
68
+ export class RemoteToolProxy {
69
+ apiKey;
70
+ baseUrl;
71
+ fetchImpl;
72
+ readLocalFile;
73
+ localFileSize;
74
+ nextId = 1;
75
+ constructor(apiKey, baseUrl, fetchImpl = fetch, readLocalFile = readFile, localFileSize = async (p) => (await stat(p)).size) {
76
+ this.apiKey = apiKey;
77
+ this.baseUrl = baseUrl;
78
+ this.fetchImpl = fetchImpl;
79
+ this.readLocalFile = readLocalFile;
80
+ this.localFileSize = localFileSize;
81
+ }
82
+ async rpc(method, params) {
83
+ const res = await this.fetchImpl(`${this.baseUrl.replace(/\/+$/, '')}/api/mcp`, {
84
+ method: 'POST',
85
+ headers: {
86
+ Authorization: `Bearer ${this.apiKey}`,
87
+ 'Content-Type': 'application/json',
88
+ Accept: 'application/json',
89
+ 'User-Agent': USER_AGENT,
90
+ },
91
+ body: JSON.stringify({ jsonrpc: '2.0', id: this.nextId++, method, ...(params ? { params } : {}) }),
92
+ });
93
+ let body = {};
94
+ try {
95
+ body = (await res.json());
96
+ }
97
+ catch {
98
+ /* non-JSON */
99
+ }
100
+ if (!res.ok) {
101
+ const message = typeof body.error === 'string' ? body.error : body.error?.message;
102
+ throw new RemoteError(message || `AutoShort returned HTTP ${res.status}`, res.status);
103
+ }
104
+ if (body.error) {
105
+ throw new RemoteError(typeof body.error === 'string' ? body.error : body.error.message || 'AutoShort error', res.status);
106
+ }
107
+ return body.result;
108
+ }
109
+ async listTools() {
110
+ const result = await this.rpc('tools/list');
111
+ return (result?.tools ?? []).map(localizeTool);
112
+ }
113
+ async callTool(name, rawArgs = {}) {
114
+ try {
115
+ const args = { ...rawArgs };
116
+ if (name === UPLOAD_RECORDING_TOOL && typeof args.recordingPath === 'string' && args.recordingPath) {
117
+ const size = await this.localFileSize(args.recordingPath);
118
+ if (size > MAX_RECORDING_BYTES) {
119
+ return {
120
+ content: [{
121
+ type: 'text',
122
+ text: `Error: ${args.recordingPath} is ${mb(size)} MB; a local file can be sent up to ${mb(MAX_RECORDING_BYTES)} MB. Upload it somewhere public and pass recordingUrl instead (up to 50 MB). Nothing was uploaded.`,
123
+ }],
124
+ isError: true,
125
+ };
126
+ }
127
+ const bytes = await this.readLocalFile(args.recordingPath);
128
+ args.recordingBase64 = Buffer.from(bytes).toString('base64');
129
+ if (!args.fileName)
130
+ args.fileName = basename(args.recordingPath);
131
+ delete args.recordingPath;
132
+ }
133
+ if (name === IMAGE_TO_VIDEO_TOOL && typeof args.imagePath === 'string' && args.imagePath) {
134
+ // Checked before reading: a 2GB file must not be loaded into memory and base64'd only
135
+ // for the server to refuse it.
136
+ const size = await this.localFileSize(args.imagePath);
137
+ if (size > MAX_IMAGE_BYTES) {
138
+ return {
139
+ content: [{
140
+ type: 'text',
141
+ text: `Error: ${args.imagePath} is ${mb(size)} MB; AutoShort accepts images up to ${mb(MAX_IMAGE_BYTES)} MB. Nothing was uploaded or charged.`,
142
+ }],
143
+ isError: true,
144
+ };
145
+ }
146
+ const bytes = await this.readLocalFile(args.imagePath);
147
+ args.imageBase64 = Buffer.from(bytes).toString('base64');
148
+ if (!args.imageFileName)
149
+ args.imageFileName = basename(args.imagePath);
150
+ delete args.imagePath;
151
+ }
152
+ return await this.rpc('tools/call', { name, arguments: args });
153
+ }
154
+ catch (e) {
155
+ const msg = e instanceof RemoteError
156
+ ? `Error ${e.status}: ${e.message}`
157
+ : `Error: ${e instanceof Error ? e.message : String(e)}`;
158
+ return { content: [{ type: 'text', text: msg }], isError: true };
159
+ }
160
+ }
161
+ }
162
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Credit balance MCP resource
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { AutoShortClient } from '../client.js';
6
+ export declare function registerCreditResource(server: McpServer, client: AutoShortClient): void;
7
+ //# sourceMappingURL=credits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credits.d.ts","sourceRoot":"","sources":["../../src/resources/credits.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,QAgBhF"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Credit balance MCP resource
3
+ */
4
+ export function registerCreditResource(server, client) {
5
+ server.resource('credit-balance', 'autoshort://credits/balance', { description: 'Current credit balance, monthly allocation, and plan tier', mimeType: 'application/json' }, async () => {
6
+ const balance = await client.getCreditBalance();
7
+ return {
8
+ contents: [{
9
+ uri: 'autoshort://credits/balance',
10
+ mimeType: 'application/json',
11
+ text: JSON.stringify(balance, null, 2),
12
+ }],
13
+ };
14
+ });
15
+ }
16
+ //# sourceMappingURL=credits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credits.js","sourceRoot":"","sources":["../../src/resources/credits.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,UAAU,sBAAsB,CAAC,MAAiB,EAAE,MAAuB;IAC/E,MAAM,CAAC,QAAQ,CACb,gBAAgB,EAChB,6BAA6B,EAC7B,EAAE,WAAW,EAAE,2DAA2D,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EAC1G,KAAK,IAAI,EAAE;QACT,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAChD,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,6BAA6B;oBAClC,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Rate limit MCP resource — exposes last-seen rate limit headers
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { AutoShortClient } from '../client.js';
6
+ export declare function registerRateLimitResource(server: McpServer, client: AutoShortClient): void;
7
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/resources/rate-limit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,QAgBnF"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Rate limit MCP resource — exposes last-seen rate limit headers
3
+ */
4
+ export function registerRateLimitResource(server, client) {
5
+ server.resource('rate-limit', 'autoshort://usage/rate-limit', { description: 'Current API rate limit status from most recent request', mimeType: 'application/json' }, async () => {
6
+ const info = client.lastRateLimit ?? { limit: null, remaining: null, resetAt: null, note: 'No API requests made yet' };
7
+ return {
8
+ contents: [{
9
+ uri: 'autoshort://usage/rate-limit',
10
+ mimeType: 'application/json',
11
+ text: JSON.stringify(info, null, 2),
12
+ }],
13
+ };
14
+ });
15
+ }
16
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/resources/rate-limit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,UAAU,yBAAyB,CAAC,MAAiB,EAAE,MAAuB;IAClF,MAAM,CAAC,QAAQ,CACb,YAAY,EACZ,8BAA8B,EAC9B,EAAE,WAAW,EAAE,wDAAwD,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EACvG,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC;QACvH,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,8BAA8B;oBACnC,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,71 @@
1
+ /** Video object from API */
2
+ export interface Video {
3
+ id: string;
4
+ title: string;
5
+ slug: string | null;
6
+ status: string;
7
+ videoUrl: string | null;
8
+ thumbnailUrl: string | null;
9
+ duration: number | null;
10
+ targetDuration: number | null;
11
+ language: string | null;
12
+ artStyle: string;
13
+ createdAt: string;
14
+ updatedAt: string;
15
+ }
16
+ /** Credit balance response */
17
+ export interface CreditBalance {
18
+ balance: number;
19
+ monthlyAllocation: number;
20
+ bonusCredits: number;
21
+ plan: string;
22
+ }
23
+ /** Subscription status response */
24
+ export interface SubscriptionStatus {
25
+ plan: string;
26
+ hasActiveSubscription: boolean;
27
+ videosUsed: number;
28
+ videosLimit: number;
29
+ credits: {
30
+ balance: number;
31
+ monthlyAllocation: number;
32
+ lastResetAt: string | null;
33
+ };
34
+ }
35
+ /** Usage stats response */
36
+ export interface UsageStats {
37
+ credits: {
38
+ balance: number;
39
+ monthlyAllocation: number;
40
+ };
41
+ apiCalls: {
42
+ today: number;
43
+ total: number;
44
+ };
45
+ recentTransactions: Array<{
46
+ id: string;
47
+ type: string;
48
+ amount: number;
49
+ balance: number;
50
+ feature: string | null;
51
+ createdAt: string;
52
+ }>;
53
+ }
54
+ /** Niche/art style option */
55
+ export interface EnumOption {
56
+ value: string;
57
+ label: string;
58
+ }
59
+ /** Rate limit info from API response headers */
60
+ export interface RateLimitInfo {
61
+ limit: number;
62
+ remaining: number;
63
+ resetAt: string;
64
+ }
65
+ /** API error response */
66
+ export interface ApiError {
67
+ error: string;
68
+ code: string;
69
+ details?: unknown;
70
+ }
71
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,8BAA8B;AAC9B,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,mCAAmC;AACnC,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB,EAAE,OAAO,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACrF;AAED,2BAA2B;AAC3B,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,kBAAkB,EAAE,KAAK,CAAC;QACxB,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAC1D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;KAC3C,CAAC,CAAC;CACJ;AAED,6BAA6B;AAC7B,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,yBAAyB;AACzB,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,26 +1,50 @@
1
1
  {
2
2
  "name": "mcp-server-autoshorts",
3
- "version": "1.0.0",
4
- "description": "Official Model Context Protocol (MCP) server for AutoShorts — Automated faceless video generation & series management engine for AI agents",
5
- "main": "index.js",
3
+ "version": "2.3.0",
4
+ "description": "MCP server for AutoShort.org \u2014 AI video generation via Claude, Cursor, and other MCP clients",
5
+ "mcpName": "org.autoshort/autoshort",
6
+ "type": "module",
7
+ "main": "dist/index.js",
6
8
  "bin": {
7
- "mcp-server-autoshorts": "index.js"
9
+ "autoshort-mcp": "dist/index.js"
8
10
  },
9
11
  "scripts": {
10
- "start": "node index.js"
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "start": "node dist/index.js",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest"
11
17
  },
12
18
  "keywords": [
13
19
  "mcp",
14
- "model-context-protocol",
15
- "autoshorts",
16
- "faceless-video",
17
- "youtube-shorts",
18
- "tiktok-automation",
19
- "ai-agent"
20
+ "autoshort",
21
+ "ai-video",
22
+ "claude",
23
+ "cursor"
20
24
  ],
21
- "author": "Kien Phan <kien@autoshort.org>",
25
+ "author": "AutoShort (https://autoshort.org)",
22
26
  "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/airdropfi/autoshorts"
30
+ },
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ },
23
34
  "dependencies": {
24
- "@modelcontextprotocol/sdk": "^1.5.0"
25
- }
35
+ "@modelcontextprotocol/sdk": "^1.12.1",
36
+ "zod": "^3.24.4"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.0.0",
40
+ "@vitest/ui": "^4.1.0",
41
+ "typescript": "^5.7.0",
42
+ "vitest": "^4.1.0"
43
+ },
44
+ "files": [
45
+ "dist",
46
+ "README.md",
47
+ "LICENSE"
48
+ ],
49
+ "homepage": "https://autoshort.org/en/developers"
26
50
  }
package/index.js DELETED
@@ -1,85 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
- import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
6
- import https from 'https';
7
-
8
- const server = new Server(
9
- {
10
- name: 'mcp-server-autoshorts',
11
- version: '1.0.0',
12
- },
13
- {
14
- capabilities: {
15
- tools: {},
16
- },
17
- }
18
- );
19
-
20
- function fetchAutoShortsSeries(apiKey) {
21
- return new Promise((resolve) => {
22
- const req = https.request('https://autoshort.org/api/series', {
23
- method: 'GET',
24
- headers: {
25
- 'Authorization': `Bearer ${apiKey || process.env.AUTOSHORTS_API_KEY}`,
26
- 'User-Agent': 'mcp-server-autoshorts/1.0.0'
27
- }
28
- }, (res) => {
29
- let data = '';
30
- res.on('data', chunk => data += chunk);
31
- res.on('end', () => {
32
- try {
33
- resolve(JSON.parse(data));
34
- } catch {
35
- resolve({ error: 'Failed to parse AutoShorts API response' });
36
- }
37
- });
38
- });
39
- req.on('error', (err) => resolve({ error: err.message }));
40
- req.end();
41
- });
42
- }
43
-
44
- server.setRequestHandler(ListToolsRequestSchema, async () => {
45
- return {
46
- tools: [
47
- {
48
- name: 'autoshorts_list_series',
49
- description: 'List active video generation series, posting schedules, and queue statuses via AutoShorts API.',
50
- inputSchema: {
51
- type: 'object',
52
- properties: {
53
- apiKey: { type: 'string', description: 'AutoShorts API key (optional if AUTOSHORTS_API_KEY env is set)' }
54
- }
55
- }
56
- }
57
- ]
58
- };
59
- });
60
-
61
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
62
- if (request.params.name === 'autoshorts_list_series') {
63
- const apiKey = request.params.arguments?.apiKey || process.env.AUTOSHORTS_API_KEY;
64
- const result = await fetchAutoShortsSeries(apiKey);
65
- return {
66
- content: [
67
- {
68
- type: 'text',
69
- text: JSON.stringify(result, null, 2)
70
- }
71
- ]
72
- };
73
- }
74
- throw new Error(`Unknown tool: ${request.params.name}`);
75
- });
76
-
77
- async function run() {
78
- const transport = new StdioServerTransport();
79
- await server.connect(transport);
80
- }
81
-
82
- run().catch((err) => {
83
- console.error('Fatal MCP Server error:', err);
84
- process.exit(1);
85
- });