diff --git a/README.md b/README.md index 86db9b1..03b1f84 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,12 @@ MCP (Model Context Protocol) is Anthropic's open standard that lets AI assistant With a Substack MCP connected to Claude Desktop or Claude Code, you can: - **Draft and publish posts** — "Draft a newsletter issue about [topic] and save it as a Substack draft" -- **Manage Notes** — "Write and schedule 5 Notes based on this week's newsletter" +- **Browse Notes** — "Show me recent Notes from publications I follow" - **Read your archive** — "Summarize the themes from my last 10 newsletters" -- **Analyze engagement** — "Which of my recent Notes got the most engagement?" -- **Bulk operations** — "Import these 20 Note drafts and schedule them across next month" +- **Analyze engagement** — "Which newsletter posts produced the most signups?" +- **Work with subscribers** — "Export subscribers who joined in the last 30 days" + +Capabilities vary by implementation; check the comparison below before choosing a server. --- @@ -24,7 +26,7 @@ There are currently **4 active Substack MCP implementations** on GitHub. They di | Server | Repo | Best For | Auth Method | Active? | |---|---|---|---|---| -| **marcomoauro/substack-mcp** | [GitHub](https://github.com/marcomoauro/substack-mcp) | Full post management, drafts, publishing | Substack API token | ✅ Yes | +| **marcomoauro/substack-mcp** | [GitHub](https://github.com/marcomoauro/substack-mcp) | Publishing, readers, subscribers, analytics | Browser session | ✅ Yes | | **arthurcolle/substack-mcp** | [GitHub](https://github.com/arthurcolle/substack-mcp) | Claude Code integration, live blogging | Cookie session | ✅ Yes | | **michalnaka/mcp-substack** | [GitHub](https://github.com/michalnaka/mcp-substack) | Reading/parsing posts for research | Public RSS | ✅ Yes | | **postcli/substack** | [GitHub](https://github.com/postcli) | Notes + social interactions | Session cookie | ✅ Yes | @@ -50,10 +52,11 @@ Add to your `claude_desktop_config.json`: "mcpServers": { "substack": { "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], + "args": ["-y", "substack-mcp@latest"], "env": { - "SUBSTACK_API_KEY": "your-api-key-here", - "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com" + "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com", + "SUBSTACK_SESSION_TOKEN": "your-session-token", + "SUBSTACK_USER_ID": "your-user-id" } } } @@ -67,9 +70,17 @@ Add to your `claude_desktop_config.json`: ### Step 3: Get your Substack credentials -1. Log into your Substack publication -2. Go to Settings → Publication Details → scroll to "API" -3. Copy your API key (or use cookie-based auth for servers that require it) +`marcomoauro/substack-mcp` uses your authenticated web session; Substack does not issue an API key +for these operations. Log into your publication and open the browser developer tools: + +1. In **Network**, filter to **Fetch/XHR** and reload the dashboard. +2. Open an authenticated request and find `substack.sid` or `connect.sid` in its `Cookie` request + header. Copy only that cookie's value as `SUBSTACK_SESSION_TOKEN`. +3. Find a successful `publication_user` request and copy the numeric `user.id` from its JSON + response as `SUBSTACK_USER_ID`. + +Treat the session token like a password. The upstream project has a more detailed +[credential guide](https://github.com/marcomoauro/substack-mcp#1-collect-your-substack-credentials). ### Step 4: Restart Claude Desktop and test @@ -83,19 +94,26 @@ Add to your `claude_desktop_config.json`: ## Quick Setup: Claude Code ```bash -claude mcp add substack-mcp -- npx -y @marcomoauro/substack-mcp +claude mcp add --scope user substack-mcp \ + -e SUBSTACK_PUBLICATION_URL=https://yourname.substack.com \ + -e SUBSTACK_SESSION_TOKEN=your-session-token \ + -e SUBSTACK_USER_ID=your-user-id \ + -- npx -y substack-mcp@latest ``` -Or add to your project's `.claude/mcp.json`: +Or add to your project's `.mcp.json`: ```json { - "substack": { - "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], - "env": { - "SUBSTACK_API_KEY": "your-api-key", - "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com" + "mcpServers": { + "substack": { + "command": "npx", + "args": ["-y", "substack-mcp@latest"], + "env": { + "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com", + "SUBSTACK_SESSION_TOKEN": "your-session-token", + "SUBSTACK_USER_ID": "your-user-id" + } } } } @@ -123,11 +141,13 @@ Substack MCP servers handle Substack content only. If you want to simultaneously ### 2. Session auth is fragile -Several Substack MCP servers use cookie/session authentication, which breaks when Substack rotates your session (typically every 30–90 days). You'll periodically need to re-authenticate manually. +Several Substack MCP servers use cookie/session authentication. When Substack rotates or invalidates +your session, you'll need to sign in again and update the token in your MCP configuration. -### 3. No built-in analytics or subscriber attribution +### 3. Analytics capabilities vary by server -MCP gives you publishing access. It doesn't tell you which Notes drove subscriber growth, which platform converted the most readers, or when your audience is most active. +`marcomoauro/substack-mcp` exposes publication analytics, post metrics, and subscriber exports. +Cross-platform attribution still requires a separate analytics or distribution system. ### 4. You're the maintainer @@ -180,7 +200,9 @@ Not as of 2026. All current Substack MCP servers are community-built. Substack h ### Can MCP schedule Substack Notes automatically? -With the right setup, yes. Claude can use the MCP to create and publish Notes on command — but scheduling ahead of time requires either prompting Claude at the right moment or setting up additional automation (n8n, cron jobs, etc.). [Narrareach](https://narrareach.com/features/substack-mcp-integration) handles reliable cloud scheduling natively. +Not with `marcomoauro/substack-mcp`: it can read Notes and restack them, but it does not create Notes +or schedule future publication. Other servers may expose different capabilities. [Narrareach](https://narrareach.com/features/substack-mcp-integration) +handles cloud scheduling natively. ### What's the difference between Substack MCP and the Narrareach API? diff --git a/docs/server-comparison.md b/docs/server-comparison.md index bfcefc7..d31d247 100644 --- a/docs/server-comparison.md +++ b/docs/server-comparison.md @@ -8,26 +8,30 @@ Detailed breakdown of every active Substack MCP server in 2026. **Repo:** https://github.com/marcomoauro/substack-mcp **Maintained:** Yes -**Install:** `npx -y @marcomoauro/substack-mcp` +**Install:** `npx -y substack-mcp@latest` ### What it does -The most complete Substack MCP server. Covers the full post management lifecycle: +Exposes 27 tools across publishing, readers, subscribers, and analytics: - Create, edit, and delete drafts - Publish posts (free and paid) -- Manage post metadata (title, subtitle, cover image, section) -- Schedule posts for future publication -- List and retrieve existing posts +- Manage post metadata (title, subtitle, audience, cover image, and URL slug) +- Upload images and work with structured post bodies +- List drafts, published posts, and already-scheduled posts +- Read feeds and Notes, restack Notes, and comment on posts +- Query subscribers, post metrics, and publication analytics ### Authentication -Uses Substack's API token. More stable than cookie-based auth — tokens don't rotate as frequently as sessions. +Uses an authenticated Substack browser session, plus the publication URL and numeric user ID. +Substack does not provide a public API or API token for these operations. ### Best for Writers who want to use Claude for drafting and publishing Substack newsletters. The primary use case is: "Claude, write my newsletter draft about [topic] and save it to Substack." ### Limitations -- Focuses on newsletter posts, not Notes specifically +- Can read and restack Notes, but cannot create Notes +- Can list already-scheduled posts, but cannot schedule future publication - No cross-posting to other platforms -- No analytics tools +- Session authentication must be refreshed if Substack invalidates it ### Config ```json @@ -35,10 +39,11 @@ Writers who want to use Claude for drafting and publishing Substack newsletters. "mcpServers": { "substack": { "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], + "args": ["-y", "substack-mcp@latest"], "env": { - "SUBSTACK_API_KEY": "YOUR_API_KEY", - "SUBSTACK_PUBLICATION_URL": "https://yourpublication.substack.com" + "SUBSTACK_PUBLICATION_URL": "https://yourpublication.substack.com", + "SUBSTACK_SESSION_TOKEN": "YOUR_SESSION_TOKEN", + "SUBSTACK_USER_ID": "YOUR_USER_ID" } } } @@ -67,8 +72,7 @@ Cookie/session-based. Requires periodic re-authentication when Substack rotates Developers using Claude Code who want to build newsletter automation into their coding workflow. Example: "As part of my project documentation workflow, save a summary as a Substack draft." ### Limitations -- Session auth breaks every 30–90 days -- Requires manual re-auth when session expires +- Requires manual re-auth when Substack invalidates the session - Not suited for long-running automated workflows without re-auth handling --- @@ -129,13 +133,12 @@ Writers who want Claude to manage their Notes feed and social interactions. Exam |---|---|---|---|---| | Create drafts | ✅ | ✅ | ❌ | ❌ | | Publish posts | ✅ | ✅ | ❌ | ❌ | -| Manage Notes | Limited | ❌ | ❌ | ✅ | +| Manage Notes | Read + restack | ❌ | ❌ | ✅ | | Read/parse posts | ✅ | ✅ | ✅ | ✅ | -| Social interactions | ❌ | ❌ | ❌ | ✅ | -| Upload images | ❌ | ✅ | ❌ | ❌ | +| Social interactions | Comments + restacks | ❌ | ❌ | ✅ | +| Upload images | ✅ | ✅ | ❌ | ❌ | | Live blogging | ❌ | ✅ | ❌ | ❌ | -| Auth type | API token | Session | Public/session | Session | -| Auth stability | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ | +| Auth type | Session | Session | Public/session | Session | | Cross-posting | ❌ | ❌ | ❌ | ❌ | --- @@ -143,7 +146,7 @@ Writers who want Claude to manage their Notes feed and social interactions. Exam ## Recommendation by Use Case **"I want Claude to write and publish my newsletters"** -→ `marcomoauro/substack-mcp` — most stable API token auth, full post management +→ `marcomoauro/substack-mcp` — full post management plus image uploads and analytics **"I'm a developer using Claude Code and want Substack integrated into my workflow"** → `arthurcolle/substack-mcp` — built for Claude Code, supports image uploads and live blogging diff --git a/docs/setup-guide.md b/docs/setup-guide.md index 883268d..8ba16c5 100644 --- a/docs/setup-guide.md +++ b/docs/setup-guide.md @@ -8,29 +8,34 @@ Step-by-step instructions for connecting a Substack MCP server to Claude Desktop Before starting: - Claude Desktop (Pro plan) or Claude Code installed -- Node.js 18+ installed (`node --version` to check) +- Node.js 22+ installed (`node --version` to check) - Your Substack publication URL -- Your Substack API key (or session cookie, depending on server) +- Your Substack session token and user ID --- -## Getting Your Substack API Key +## Getting Your Substack Credentials -1. Go to your Substack publication dashboard -2. Click **Settings** in the left sidebar -3. Scroll to the **Integrations** or **API** section -4. Copy the API key shown +`marcomoauro/substack-mcp` uses three values: your publication URL, a browser session token, and +your numeric Substack user ID. Substack does not provide an API key for the web operations this +server exposes. -If no API key is visible, your Substack plan may not expose one. In that case, use a session cookie-based server (arthurcolle or postcli). +1. Log into Substack and open your publication dashboard. +2. Open browser developer tools, select **Network**, filter to **Fetch/XHR**, and reload the page. +3. Open a successful authenticated request. Under **Request Headers**, locate the `Cookie` header + and copy only the value of `substack.sid` or `connect.sid`. This is + `SUBSTACK_SESSION_TOKEN`. +4. Find a successful `publication_user` request. In its JSON response, copy the numeric `id` inside + the `user` object. This is `SUBSTACK_USER_ID`. -### Getting a Session Cookie (for cookie-based servers) +If both cookie names appear with different values, test them separately with a read-only request +such as listing your drafts. Never paste a session token or a complete `Cookie` header into an +issue. See the upstream project's +[credential guide](https://github.com/marcomoauro/substack-mcp#1-collect-your-substack-credentials) +if your browser UI differs. -1. Log into Substack in Chrome -2. Open DevTools (F12) → Application tab → Cookies -3. Find `substack.sid` — this is your session token -4. Copy the value - -**Warning:** Session cookies expire every 30–90 days. You will need to update your config when they do. +**Warning:** Treat the session token like a password. If Substack rotates or invalidates the +session, sign in again and repeat these steps. --- @@ -53,10 +58,11 @@ Open the file (create it if it doesn't exist) and add: "mcpServers": { "substack": { "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], + "args": ["-y", "substack-mcp@latest"], "env": { - "SUBSTACK_API_KEY": "paste-your-api-key-here", - "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com" + "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com", + "SUBSTACK_SESSION_TOKEN": "your-session-token", + "SUBSTACK_USER_ID": "your-user-id" } } } @@ -73,7 +79,8 @@ In a new Claude conversation, type: > "List my recent Substack drafts" -If connected correctly, Claude will return your actual drafts. If you see an error, check your API key and restart. +If connected correctly, Claude will return your actual drafts. If you see an error, check all three +credential values and restart. --- @@ -82,23 +89,28 @@ If connected correctly, Claude will return your actual drafts. If you see an err ### Option A: One-line add ```bash -claude mcp add substack -- npx -y @marcomoauro/substack-mcp \ - SUBSTACK_API_KEY=your-key \ - SUBSTACK_PUBLICATION_URL=https://yourname.substack.com +claude mcp add --scope project substack \ + -e SUBSTACK_PUBLICATION_URL=https://yourname.substack.com \ + -e SUBSTACK_SESSION_TOKEN=your-session-token \ + -e SUBSTACK_USER_ID=your-user-id \ + -- npx -y substack-mcp@latest ``` ### Option B: Project config file -Create `.claude/mcp.json` in your project root: +Create `.mcp.json` in your project root: ```json { - "substack": { - "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], - "env": { - "SUBSTACK_API_KEY": "your-api-key", - "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com" + "mcpServers": { + "substack": { + "command": "npx", + "args": ["-y", "substack-mcp@latest"], + "env": { + "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com", + "SUBSTACK_SESSION_TOKEN": "your-session-token", + "SUBSTACK_USER_ID": "your-user-id" + } } } } @@ -133,13 +145,16 @@ Cursor uses the same config format as Claude Desktop. Node.js is not installed or not in your PATH. Install from nodejs.org and restart your terminal. ### "Authentication failed" -Your API key is wrong or expired. Get a fresh key from Substack settings. +One of the three configured values is missing or stale. Check the publication URL and user ID; if +the session has expired, sign in again and collect a fresh session token. ### "Cannot find module" -The npx package hasn't been downloaded yet. Run `npx -y @marcomoauro/substack-mcp` in your terminal first to cache it. +The npx package hasn't been downloaded yet. Run `npx -y substack-mcp@latest` in your terminal first +to cache it. ### "Session expired" (cookie-based servers) -Your `substack.sid` cookie has rotated. Get a fresh session cookie from your browser and update the config. +Your Substack session has been invalidated. Get a fresh session token from your browser and update +the config. --- @@ -152,10 +167,11 @@ You can run multiple servers simultaneously: "mcpServers": { "substack-publish": { "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], + "args": ["-y", "substack-mcp@latest"], "env": { - "SUBSTACK_API_KEY": "your-key", - "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com" + "SUBSTACK_PUBLICATION_URL": "https://yourname.substack.com", + "SUBSTACK_SESSION_TOKEN": "your-session-token", + "SUBSTACK_USER_ID": "your-user-id" } }, "substack-research": { @@ -173,10 +189,10 @@ This gives you both publishing tools and research/reading tools in one Claude se ## Security Notes -- **Never commit your API key or session cookie to a public repo** — use environment variables -- Store credentials in `.env` and reference them: `"SUBSTACK_API_KEY": "${SUBSTACK_API_KEY}"` -- If using `.env`, load it before running Claude: `source .env && claude` -- Rotate your Substack API key if you ever accidentally expose it +- **Never commit your session token to a public repo** — treat it like a password +- Prefer your MCP client's supported secret-management mechanism over putting credentials in a + project-level file +- If you accidentally expose a session token, sign out of Substack sessions and obtain a new one --- diff --git a/templates/mcp-config.json b/templates/mcp-config.json index 6d3fc23..b8901dd 100644 --- a/templates/mcp-config.json +++ b/templates/mcp-config.json @@ -1,6 +1,6 @@ { "_comment": "Substack MCP configurations for Claude Desktop, Claude Code, and Cursor.", - "_instructions": "Copy the relevant section into your claude_desktop_config.json or .claude/mcp.json. Replace placeholder values with your actual credentials.", + "_instructions": "Copy the relevant section into your claude_desktop_config.json or project-level .mcp.json. Replace placeholder values with your actual credentials.", "examples": { @@ -8,10 +8,11 @@ "mcpServers": { "substack": { "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], + "args": ["-y", "substack-mcp@latest"], "env": { - "SUBSTACK_API_KEY": "YOUR_SUBSTACK_API_KEY", - "SUBSTACK_PUBLICATION_URL": "https://yourpublication.substack.com" + "SUBSTACK_PUBLICATION_URL": "https://yourpublication.substack.com", + "SUBSTACK_SESSION_TOKEN": "YOUR_SUBSTACK_SESSION_TOKEN", + "SUBSTACK_USER_ID": "YOUR_SUBSTACK_USER_ID" } } } @@ -21,10 +22,11 @@ "mcpServers": { "substack-publish": { "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], + "args": ["-y", "substack-mcp@latest"], "env": { - "SUBSTACK_API_KEY": "YOUR_SUBSTACK_API_KEY", - "SUBSTACK_PUBLICATION_URL": "https://yourpublication.substack.com" + "SUBSTACK_PUBLICATION_URL": "https://yourpublication.substack.com", + "SUBSTACK_SESSION_TOKEN": "YOUR_SUBSTACK_SESSION_TOKEN", + "SUBSTACK_USER_ID": "YOUR_SUBSTACK_USER_ID" } }, "substack-research": { @@ -48,25 +50,29 @@ }, "claude_code_project_config": { - "substack": { - "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], - "env": { - "SUBSTACK_API_KEY": "YOUR_SUBSTACK_API_KEY", - "SUBSTACK_PUBLICATION_URL": "https://yourpublication.substack.com" + "mcpServers": { + "substack": { + "command": "npx", + "args": ["-y", "substack-mcp@latest"], + "env": { + "SUBSTACK_PUBLICATION_URL": "https://yourpublication.substack.com", + "SUBSTACK_SESSION_TOKEN": "YOUR_SUBSTACK_SESSION_TOKEN", + "SUBSTACK_USER_ID": "YOUR_SUBSTACK_USER_ID" + } } } }, "env_file_reference": { - "_note": "Best practice: store secrets in .env and reference them", + "_note": "Use only if your MCP client supports environment-variable expansion in JSON", "mcpServers": { "substack": { "command": "npx", - "args": ["-y", "@marcomoauro/substack-mcp"], + "args": ["-y", "substack-mcp@latest"], "env": { - "SUBSTACK_API_KEY": "${SUBSTACK_API_KEY}", - "SUBSTACK_PUBLICATION_URL": "${SUBSTACK_PUBLICATION_URL}" + "SUBSTACK_PUBLICATION_URL": "${SUBSTACK_PUBLICATION_URL}", + "SUBSTACK_SESSION_TOKEN": "${SUBSTACK_SESSION_TOKEN}", + "SUBSTACK_USER_ID": "${SUBSTACK_USER_ID}" } } }