content-repurposer-mcp 1.0.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,89 @@
1
+ # content-repurposer-mcp
2
+
3
+ An MCP (Model Context Protocol) server that connects AI assistants to [ContentRepurposer](https://contentrepurposer.app) — turning any blog post, transcript, or article into platform-optimized content for Twitter/X, LinkedIn, Substack, email, and video.
4
+
5
+ ## What it does
6
+
7
+ This MCP server exposes two tools:
8
+
9
+ | Tool | Description |
10
+ |------|-------------|
11
+ | `repurpose_content` | Takes content and generates platform-specific versions |
12
+ | `list_formats` | Lists available output formats with descriptions |
13
+
14
+ ## Setup
15
+
16
+ ### 1. Get an API key
17
+
18
+ Sign up at [contentrepurposer.app](https://contentrepurposer.app) and generate an API key at **Settings → API Keys**.
19
+
20
+ ### 2. Install
21
+
22
+ ```bash
23
+ npm install -g content-repurposer-mcp
24
+ ```
25
+
26
+ ### 3. Configure your AI client
27
+
28
+ #### Claude Desktop
29
+
30
+ Add to your `claude_desktop_config.json`:
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "content-repurposer": {
36
+ "command": "content-repurposer-mcp",
37
+ "env": {
38
+ "CONTENT_REPURPOSER_API_KEY": "cr_sk_your_key_here"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ #### Claude Code
46
+
47
+ Add to your `.claude/settings.json`:
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "content-repurposer": {
53
+ "command": "content-repurposer-mcp",
54
+ "env": {
55
+ "CONTENT_REPURPOSER_API_KEY": "cr_sk_your_key_here"
56
+ }
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ ## Usage
63
+
64
+ Once configured, ask your AI assistant:
65
+
66
+ > "Repurpose this blog post into Twitter threads and LinkedIn posts"
67
+
68
+ > "Take this YouTube transcript and create content for all platforms"
69
+
70
+ > "What formats can ContentRepurposer generate?"
71
+
72
+ ## Environment Variables
73
+
74
+ | Variable | Required | Description |
75
+ |----------|----------|-------------|
76
+ | `CONTENT_REPURPOSER_API_KEY` | Yes | Your API key from contentrepurposer.app |
77
+ | `CONTENT_REPURPOSER_API_URL` | No | Custom API URL (defaults to https://contentrepurposer.app) |
78
+
79
+ ## Output Formats
80
+
81
+ - **twitter_thread** — 5-12 tweet threads with hooks and CTAs
82
+ - **linkedin_post** — Professional posts optimized for mobile
83
+ - **substack_notes** — 10-note campaigns across 5 categories
84
+ - **email_snippet** — Subject line, preview text, and body
85
+ - **video_script** — 60-second scripts for Shorts/Reels/TikTok
86
+
87
+ ## License
88
+
89
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ const API_BASE = process.env.CONTENT_REPURPOSER_API_URL ?? "https://contentrepurposer.app";
6
+ const API_KEY = process.env.CONTENT_REPURPOSER_API_KEY;
7
+ const OUTPUT_FORMATS = [
8
+ "twitter_thread",
9
+ "linkedin_post",
10
+ "substack_notes",
11
+ "email_snippet",
12
+ "video_script",
13
+ ];
14
+ const SOURCE_TYPES = [
15
+ "blog_post",
16
+ "youtube_transcript",
17
+ "podcast_transcript",
18
+ ];
19
+ const FORMAT_DESCRIPTIONS = {
20
+ twitter_thread: "Twitter/X thread (5-12 tweets with hooks and CTAs)",
21
+ linkedin_post: "LinkedIn post (professional, mobile-optimized)",
22
+ substack_notes: "Substack Notes (10-note campaign across 5 categories)",
23
+ email_snippet: "Email newsletter (subject, preview text, and body)",
24
+ video_script: "Video script (60-second Shorts/Reels/TikTok format)",
25
+ };
26
+ // Helper to call the ContentRepurposer API
27
+ async function callRepurposeAPI(body) {
28
+ if (!API_KEY) {
29
+ throw new Error("CONTENT_REPURPOSER_API_KEY is not set. " +
30
+ "Get your API key at https://contentrepurposer.app/settings/api-keys");
31
+ }
32
+ const response = await fetch(`${API_BASE}/api/v1/repurpose`, {
33
+ method: "POST",
34
+ headers: {
35
+ "Content-Type": "application/json",
36
+ Authorization: `Bearer ${API_KEY}`,
37
+ },
38
+ body: JSON.stringify(body),
39
+ });
40
+ if (!response.ok) {
41
+ const error = await response.json().catch(() => ({ error: { message: response.statusText } }));
42
+ const message = error?.error?.message ?? response.statusText;
43
+ throw new Error(`API error (${response.status}): ${message}`);
44
+ }
45
+ return response.json();
46
+ }
47
+ // Format the API response into readable text
48
+ function formatOutputs(data) {
49
+ const outputs = data.outputs;
50
+ if (!outputs || outputs.length === 0) {
51
+ return "No outputs were generated. The job may have failed.";
52
+ }
53
+ const sections = outputs.map((output) => {
54
+ const label = FORMAT_DESCRIPTIONS[output.format] ?? output.format;
55
+ return [
56
+ `## ${label}`,
57
+ "",
58
+ output.content,
59
+ "",
60
+ `(${output.wordCount} words, ${output.charCount} characters)`,
61
+ ].join("\n");
62
+ });
63
+ return sections.join("\n\n---\n\n");
64
+ }
65
+ // Create the MCP server
66
+ const server = new McpServer({
67
+ name: "content-repurposer",
68
+ version: "1.0.0",
69
+ });
70
+ // Tool 1: repurpose_content — the main tool
71
+ server.tool("repurpose_content", "Repurpose content into platform-specific formats. Takes a blog post, transcript, or article and generates optimized versions for Twitter/X, LinkedIn, Substack, email, and video. Requires a CONTENT_REPURPOSER_API_KEY.", {
72
+ content: z
73
+ .string()
74
+ .min(50)
75
+ .describe("The source content to repurpose (blog post, transcript, etc.). Minimum 50 characters."),
76
+ source_type: z
77
+ .enum(SOURCE_TYPES)
78
+ .default("blog_post")
79
+ .describe("Type of source content: blog_post, youtube_transcript, or podcast_transcript"),
80
+ source_url: z
81
+ .string()
82
+ .url()
83
+ .optional()
84
+ .describe("Optional URL of the original content for attribution"),
85
+ formats: z
86
+ .array(z.enum(OUTPUT_FORMATS))
87
+ .min(1)
88
+ .default([...OUTPUT_FORMATS])
89
+ .describe("Output formats to generate. Options: twitter_thread, linkedin_post, substack_notes, email_snippet, video_script. Defaults to all 5."),
90
+ }, async ({ content, source_type, source_url, formats }) => {
91
+ try {
92
+ const result = await callRepurposeAPI({
93
+ content,
94
+ sourceType: source_type,
95
+ sourceUrl: source_url,
96
+ formats,
97
+ });
98
+ const formatted = formatOutputs(result);
99
+ return {
100
+ content: [
101
+ {
102
+ type: "text",
103
+ text: formatted,
104
+ },
105
+ ],
106
+ };
107
+ }
108
+ catch (error) {
109
+ return {
110
+ content: [
111
+ {
112
+ type: "text",
113
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
114
+ },
115
+ ],
116
+ isError: true,
117
+ };
118
+ }
119
+ });
120
+ // Tool 2: list_formats — discover available formats
121
+ server.tool("list_formats", "List all available output formats for content repurposing, with descriptions of what each format produces.", {}, async () => {
122
+ const lines = OUTPUT_FORMATS.map((format) => `- **${format}**: ${FORMAT_DESCRIPTIONS[format]}`);
123
+ return {
124
+ content: [
125
+ {
126
+ type: "text",
127
+ text: [
128
+ "# Available Output Formats",
129
+ "",
130
+ "ContentRepurposer can generate the following formats from your content:",
131
+ "",
132
+ ...lines,
133
+ "",
134
+ "Use the `repurpose_content` tool with the `formats` parameter to select which formats to generate.",
135
+ "",
136
+ "Learn more at https://contentrepurposer.app/docs/api",
137
+ ].join("\n"),
138
+ },
139
+ ],
140
+ };
141
+ });
142
+ // Start the server
143
+ async function main() {
144
+ const transport = new StdioServerTransport();
145
+ await server.connect(transport);
146
+ }
147
+ main().catch((error) => {
148
+ console.error("Failed to start MCP server:", error);
149
+ process.exit(1);
150
+ });
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "content-repurposer-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for ContentRepurposer — turn any content into Twitter threads, LinkedIn posts, Substack notes, email newsletters, and video scripts",
5
+ "keywords": [
6
+ "mcp",
7
+ "mcp-server",
8
+ "content-repurposer",
9
+ "content-marketing",
10
+ "ai",
11
+ "social-media",
12
+ "repurpose"
13
+ ],
14
+ "author": "As The Geek Learns",
15
+ "license": "MIT",
16
+ "type": "module",
17
+ "bin": {
18
+ "content-repurposer-mcp": "dist/index.js"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "start": "node dist/index.js",
27
+ "dev": "tsx src/index.ts"
28
+ },
29
+ "dependencies": {
30
+ "@modelcontextprotocol/sdk": "^1.12.1",
31
+ "zod": "^3.25.67"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20",
35
+ "tsx": "^4.21.0",
36
+ "typescript": "^5"
37
+ }
38
+ }