substack-api-mcp 1.0.3__tar.gz → 1.0.4__tar.gz
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.
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/PKG-INFO +22 -22
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/README.md +21 -21
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/pyproject.toml +1 -1
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/__init__.py +1 -1
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/.github/workflows/ci.yml +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/.github/workflows/publish.yml +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/.gitignore +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/AGENTS.md +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/CLAUDE.md +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/LICENSE +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/assets/logo-white.svg +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/assets/logo.svg +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/add_subscribers.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/daily_stats.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/draft_from_markdown.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/export_subscribers.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/get_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/list_posts.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/list_subscribers.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/post_stats.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/publish_note.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/reply_to_comment.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/schedule_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/traffic_sources.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/unanswered_comments.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/examples/weekly_report.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/glama.json +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/mcp.json +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/api.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/app.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/cli.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/core/__init__.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/core/account_guard.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/core/context.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/core/errors.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/core/helpers.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/core/tools.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/mcp_context.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/mcp_server.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/runner.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/scripting.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/session.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/__init__.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/auth.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/client.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/feed.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/markdown.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/publishing.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/subscribers.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/__init__.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/add_subscriber.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/cancel_scheduled_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/create_draft.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/create_post_tag.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/create_subscriber_tag.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/delete_comment.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/delete_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/duplicate_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/export_subscribers.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/follow_user.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_audience_insights.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_conversation.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_daily_stats.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_feed.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_post_engagement.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_post_stats.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_post_traffic.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_publication_stats.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_unread_counts.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/like_comment.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/like_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_activity.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_comments.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_conversations.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_note_replies.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_notes.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_post_tags.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_posts.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_recommendations.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_sections.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_subscriber_tags.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_subscribers.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_subscriptions.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_traffic_sources.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/pin_comment.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/publish_note.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/publish_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/recommend_publication.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/remove_comment.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/remove_subscriber.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/reply_to_comment.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/reply_to_note.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/schedule_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/search_substack.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/send_message.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/tag_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/tag_subscribers.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/unpublish_post.py +0 -0
- {substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/update_draft.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: substack-api-mcp
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: Self-hosted Substack API and MCP server on your own Chrome session. Noncommercial use (PolyForm Noncommercial 1.0.0).
|
|
5
5
|
Project-URL: Homepage, https://cotlet.dev/integrations/substack-api-mcp-server
|
|
6
6
|
Project-URL: Source, https://github.com/cotletdev/substack-api-mcp-server
|
|
@@ -29,13 +29,13 @@ Substack has no public API to write posts, publish Notes or manage subscribers,
|
|
|
29
29
|
|
|
30
30
|
- **MCP server** for Claude Code, Claude Desktop, Cursor, Codex and any MCP client, over stdio or HTTP. [Setup](#mcp-server)
|
|
31
31
|
- **REST API** on `http://127.0.0.1:8787/api/v1/substack`, with OpenAPI docs at `/docs`. [Setup](#rest-api)
|
|
32
|
-
- **Python**: `call("list_posts", status="draft")`, plus 14 ready scripts in [`examples/`](examples/).
|
|
32
|
+
- **Python**: `call("list_posts", status="draft")`, plus 14 ready scripts in [`examples/`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/).
|
|
33
33
|
|
|
34
34
|
It is for technical people who want to run it themselves, **for noncommercial use only** ([license](#license)). If you want it running 24/7 on a server, kept working when Substack changes its site, for a team or a business, use the [hosted version at cotlet.dev](https://cotlet.dev/integrations/substack-api-mcp-server).
|
|
35
35
|
|
|
36
36
|
[](#all-50-tools)
|
|
37
37
|
[](#requirements)
|
|
38
|
-
[](LICENSE)
|
|
38
|
+
[](https://github.com/cotletdev/substack-api-mcp-server/blob/main/LICENSE)
|
|
39
39
|
[](https://lobehub.com/mcp/cotletdev-substack-api-mcp-server)
|
|
40
40
|
|
|
41
41
|
```bash
|
|
@@ -107,7 +107,7 @@ substack-mcp --version
|
|
|
107
107
|
|
|
108
108
|
With [uv](https://docs.astral.sh/uv/): `uv venv && uv pip install -e .`, then `uv run substack-mcp ...`.
|
|
109
109
|
|
|
110
|
-
Setting it up with an AI agent (Claude Code, Codex, Cursor)? Open it in this folder and ask it to set up the repo: [`AGENTS.md`](AGENTS.md) tells it every step, and it asks you only for the steps in Chrome.
|
|
110
|
+
Setting it up with an AI agent (Claude Code, Codex, Cursor)? Open it in this folder and ask it to set up the repo: [`AGENTS.md`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/AGENTS.md) tells it every step, and it asks you only for the steps in Chrome.
|
|
111
111
|
|
|
112
112
|
To update: `uv tool upgrade substack-api-mcp` (or `pip install -U substack-api-mcp`), from source `git pull && pip install -e .`. We copy every change of the hosted Substack tools into this repo.
|
|
113
113
|
|
|
@@ -198,7 +198,7 @@ claude mcp add substack -- uvx substack-api-mcp mcp --read-only
|
|
|
198
198
|
|
|
199
199
|
### Cursor
|
|
200
200
|
|
|
201
|
-
`~/.cursor/mcp.json`, the same block as Claude Desktop. A ready copy is in [`mcp.json`](mcp.json).
|
|
201
|
+
`~/.cursor/mcp.json`, the same block as Claude Desktop. A ready copy is in [`mcp.json`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/mcp.json).
|
|
202
202
|
|
|
203
203
|
### Codex
|
|
204
204
|
|
|
@@ -277,24 +277,24 @@ call("schedule_post", post_id=draft["post_id"], publish_at="2026-11-03T08:00:00-
|
|
|
277
277
|
|
|
278
278
|
Or one tool from the shell: `substack-mcp call get_post_stats post_id=148213977`, or with a JSON object.
|
|
279
279
|
|
|
280
|
-
Ready scripts in [`examples/`](examples/). Each prints JSON, takes `--out file.csv` or `--out file.json` where it makes sense, and `--help`:
|
|
280
|
+
Ready scripts in [`examples/`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/). Each prints JSON, takes `--out file.csv` or `--out file.json` where it makes sense, and `--help`:
|
|
281
281
|
|
|
282
282
|
| Script | What it does |
|
|
283
283
|
|---|---|
|
|
284
|
-
| [`draft_from_markdown.py`](examples/draft_from_markdown.py) | A `.md` file to a draft: the first heading is the title, headings, links and lists are kept. `--publish-at` schedules it. |
|
|
285
|
-
| [`schedule_post.py`](examples/schedule_post.py) | Schedules a draft for a set time, or `--cancel` takes it back to drafts. |
|
|
286
|
-
| [`publish_note.py`](examples/publish_note.py) | A Note now or at a set time, `--link-latest` adds a link card to your newest post. |
|
|
287
|
-
| [`list_posts.py`](examples/list_posts.py) | Published, draft or scheduled posts: title, audience, dates, URL. |
|
|
288
|
-
| [`get_post.py`](examples/get_post.py) | One post saved as a Markdown file. |
|
|
289
|
-
| [`weekly_report.py`](examples/weekly_report.py) | New and paid subscribers, cancellations, revenue, and each new post's opens and new subscribers. |
|
|
290
|
-
| [`post_stats.py`](examples/post_stats.py) | Opens, open rate, views, likes, restacks and new subscribers for your last N posts. |
|
|
291
|
-
| [`daily_stats.py`](examples/daily_stats.py) | Subscribers, paid subscribers, followers and views day by day. |
|
|
292
|
-
| [`traffic_sources.py`](examples/traffic_sources.py) | Where your visitors came from, most views first. |
|
|
293
|
-
| [`unanswered_comments.py`](examples/unanswered_comments.py) | Comments on your last N posts that you have not replied to. |
|
|
294
|
-
| [`reply_to_comment.py`](examples/reply_to_comment.py) | A reply under one comment. |
|
|
295
|
-
| [`list_subscribers.py`](examples/list_subscribers.py) | Subscribers by plan or join date, with activity rating. |
|
|
296
|
-
| [`export_subscribers.py`](examples/export_subscribers.py) | The full list as the CSV that Export gives in the dashboard. |
|
|
297
|
-
| [`add_subscribers.py`](examples/add_subscribers.py) | Adds emails from a text or CSV file as free subscribers, after asking you. |
|
|
284
|
+
| [`draft_from_markdown.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/draft_from_markdown.py) | A `.md` file to a draft: the first heading is the title, headings, links and lists are kept. `--publish-at` schedules it. |
|
|
285
|
+
| [`schedule_post.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/schedule_post.py) | Schedules a draft for a set time, or `--cancel` takes it back to drafts. |
|
|
286
|
+
| [`publish_note.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/publish_note.py) | A Note now or at a set time, `--link-latest` adds a link card to your newest post. |
|
|
287
|
+
| [`list_posts.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/list_posts.py) | Published, draft or scheduled posts: title, audience, dates, URL. |
|
|
288
|
+
| [`get_post.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/get_post.py) | One post saved as a Markdown file. |
|
|
289
|
+
| [`weekly_report.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/weekly_report.py) | New and paid subscribers, cancellations, revenue, and each new post's opens and new subscribers. |
|
|
290
|
+
| [`post_stats.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/post_stats.py) | Opens, open rate, views, likes, restacks and new subscribers for your last N posts. |
|
|
291
|
+
| [`daily_stats.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/daily_stats.py) | Subscribers, paid subscribers, followers and views day by day. |
|
|
292
|
+
| [`traffic_sources.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/traffic_sources.py) | Where your visitors came from, most views first. |
|
|
293
|
+
| [`unanswered_comments.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/unanswered_comments.py) | Comments on your last N posts that you have not replied to. |
|
|
294
|
+
| [`reply_to_comment.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/reply_to_comment.py) | A reply under one comment. |
|
|
295
|
+
| [`list_subscribers.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/list_subscribers.py) | Subscribers by plan or join date, with activity rating. |
|
|
296
|
+
| [`export_subscribers.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/export_subscribers.py) | The full list as the CSV that Export gives in the dashboard. |
|
|
297
|
+
| [`add_subscribers.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/add_subscribers.py) | Adds emails from a text or CSV file as free subscribers, after asking you. |
|
|
298
298
|
|
|
299
299
|
```bash
|
|
300
300
|
python examples/draft_from_markdown.py essay.md --publish-at 2026-11-03T08:00:00-05:00
|
|
@@ -507,7 +507,7 @@ The source is public, the license is not an open source license: noncommercial u
|
|
|
507
507
|
|
|
508
508
|
## License
|
|
509
509
|
|
|
510
|
-
[PolyForm Noncommercial License 1.0.0](LICENSE). In short:
|
|
510
|
+
[PolyForm Noncommercial License 1.0.0](https://github.com/cotletdev/substack-api-mcp-server/blob/main/LICENSE). In short:
|
|
511
511
|
|
|
512
512
|
- **Allowed:** noncommercial use: you, for your own personal purposes with your own Substack account, or a charity, school, public research or government body. Changing the code, and sharing it under the same license.
|
|
513
513
|
- **Not allowed:** any commercial use, your own business included; client work; selling or offering it, or a service built on it.
|
|
@@ -520,7 +520,7 @@ Earlier versions of this repo (the scripts for the hosted API, up to commit 4399
|
|
|
520
520
|
<a href="https://cotlet.dev">
|
|
521
521
|
<picture>
|
|
522
522
|
<source media="(prefers-color-scheme: dark)" srcset="assets/logo-white.svg">
|
|
523
|
-
<img src="assets/logo.svg" alt="Cotlet" width="120">
|
|
523
|
+
<img src="https://raw.githubusercontent.com/cotletdev/substack-api-mcp-server/main/assets/logo.svg" alt="Cotlet" width="120">
|
|
524
524
|
</picture>
|
|
525
525
|
</a>
|
|
526
526
|
</p>
|
|
@@ -8,13 +8,13 @@ Substack has no public API to write posts, publish Notes or manage subscribers,
|
|
|
8
8
|
|
|
9
9
|
- **MCP server** for Claude Code, Claude Desktop, Cursor, Codex and any MCP client, over stdio or HTTP. [Setup](#mcp-server)
|
|
10
10
|
- **REST API** on `http://127.0.0.1:8787/api/v1/substack`, with OpenAPI docs at `/docs`. [Setup](#rest-api)
|
|
11
|
-
- **Python**: `call("list_posts", status="draft")`, plus 14 ready scripts in [`examples/`](examples/).
|
|
11
|
+
- **Python**: `call("list_posts", status="draft")`, plus 14 ready scripts in [`examples/`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/).
|
|
12
12
|
|
|
13
13
|
It is for technical people who want to run it themselves, **for noncommercial use only** ([license](#license)). If you want it running 24/7 on a server, kept working when Substack changes its site, for a team or a business, use the [hosted version at cotlet.dev](https://cotlet.dev/integrations/substack-api-mcp-server).
|
|
14
14
|
|
|
15
15
|
[](#all-50-tools)
|
|
16
16
|
[](#requirements)
|
|
17
|
-
[](LICENSE)
|
|
17
|
+
[](https://github.com/cotletdev/substack-api-mcp-server/blob/main/LICENSE)
|
|
18
18
|
[](https://lobehub.com/mcp/cotletdev-substack-api-mcp-server)
|
|
19
19
|
|
|
20
20
|
```bash
|
|
@@ -86,7 +86,7 @@ substack-mcp --version
|
|
|
86
86
|
|
|
87
87
|
With [uv](https://docs.astral.sh/uv/): `uv venv && uv pip install -e .`, then `uv run substack-mcp ...`.
|
|
88
88
|
|
|
89
|
-
Setting it up with an AI agent (Claude Code, Codex, Cursor)? Open it in this folder and ask it to set up the repo: [`AGENTS.md`](AGENTS.md) tells it every step, and it asks you only for the steps in Chrome.
|
|
89
|
+
Setting it up with an AI agent (Claude Code, Codex, Cursor)? Open it in this folder and ask it to set up the repo: [`AGENTS.md`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/AGENTS.md) tells it every step, and it asks you only for the steps in Chrome.
|
|
90
90
|
|
|
91
91
|
To update: `uv tool upgrade substack-api-mcp` (or `pip install -U substack-api-mcp`), from source `git pull && pip install -e .`. We copy every change of the hosted Substack tools into this repo.
|
|
92
92
|
|
|
@@ -177,7 +177,7 @@ claude mcp add substack -- uvx substack-api-mcp mcp --read-only
|
|
|
177
177
|
|
|
178
178
|
### Cursor
|
|
179
179
|
|
|
180
|
-
`~/.cursor/mcp.json`, the same block as Claude Desktop. A ready copy is in [`mcp.json`](mcp.json).
|
|
180
|
+
`~/.cursor/mcp.json`, the same block as Claude Desktop. A ready copy is in [`mcp.json`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/mcp.json).
|
|
181
181
|
|
|
182
182
|
### Codex
|
|
183
183
|
|
|
@@ -256,24 +256,24 @@ call("schedule_post", post_id=draft["post_id"], publish_at="2026-11-03T08:00:00-
|
|
|
256
256
|
|
|
257
257
|
Or one tool from the shell: `substack-mcp call get_post_stats post_id=148213977`, or with a JSON object.
|
|
258
258
|
|
|
259
|
-
Ready scripts in [`examples/`](examples/). Each prints JSON, takes `--out file.csv` or `--out file.json` where it makes sense, and `--help`:
|
|
259
|
+
Ready scripts in [`examples/`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/). Each prints JSON, takes `--out file.csv` or `--out file.json` where it makes sense, and `--help`:
|
|
260
260
|
|
|
261
261
|
| Script | What it does |
|
|
262
262
|
|---|---|
|
|
263
|
-
| [`draft_from_markdown.py`](examples/draft_from_markdown.py) | A `.md` file to a draft: the first heading is the title, headings, links and lists are kept. `--publish-at` schedules it. |
|
|
264
|
-
| [`schedule_post.py`](examples/schedule_post.py) | Schedules a draft for a set time, or `--cancel` takes it back to drafts. |
|
|
265
|
-
| [`publish_note.py`](examples/publish_note.py) | A Note now or at a set time, `--link-latest` adds a link card to your newest post. |
|
|
266
|
-
| [`list_posts.py`](examples/list_posts.py) | Published, draft or scheduled posts: title, audience, dates, URL. |
|
|
267
|
-
| [`get_post.py`](examples/get_post.py) | One post saved as a Markdown file. |
|
|
268
|
-
| [`weekly_report.py`](examples/weekly_report.py) | New and paid subscribers, cancellations, revenue, and each new post's opens and new subscribers. |
|
|
269
|
-
| [`post_stats.py`](examples/post_stats.py) | Opens, open rate, views, likes, restacks and new subscribers for your last N posts. |
|
|
270
|
-
| [`daily_stats.py`](examples/daily_stats.py) | Subscribers, paid subscribers, followers and views day by day. |
|
|
271
|
-
| [`traffic_sources.py`](examples/traffic_sources.py) | Where your visitors came from, most views first. |
|
|
272
|
-
| [`unanswered_comments.py`](examples/unanswered_comments.py) | Comments on your last N posts that you have not replied to. |
|
|
273
|
-
| [`reply_to_comment.py`](examples/reply_to_comment.py) | A reply under one comment. |
|
|
274
|
-
| [`list_subscribers.py`](examples/list_subscribers.py) | Subscribers by plan or join date, with activity rating. |
|
|
275
|
-
| [`export_subscribers.py`](examples/export_subscribers.py) | The full list as the CSV that Export gives in the dashboard. |
|
|
276
|
-
| [`add_subscribers.py`](examples/add_subscribers.py) | Adds emails from a text or CSV file as free subscribers, after asking you. |
|
|
263
|
+
| [`draft_from_markdown.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/draft_from_markdown.py) | A `.md` file to a draft: the first heading is the title, headings, links and lists are kept. `--publish-at` schedules it. |
|
|
264
|
+
| [`schedule_post.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/schedule_post.py) | Schedules a draft for a set time, or `--cancel` takes it back to drafts. |
|
|
265
|
+
| [`publish_note.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/publish_note.py) | A Note now or at a set time, `--link-latest` adds a link card to your newest post. |
|
|
266
|
+
| [`list_posts.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/list_posts.py) | Published, draft or scheduled posts: title, audience, dates, URL. |
|
|
267
|
+
| [`get_post.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/get_post.py) | One post saved as a Markdown file. |
|
|
268
|
+
| [`weekly_report.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/weekly_report.py) | New and paid subscribers, cancellations, revenue, and each new post's opens and new subscribers. |
|
|
269
|
+
| [`post_stats.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/post_stats.py) | Opens, open rate, views, likes, restacks and new subscribers for your last N posts. |
|
|
270
|
+
| [`daily_stats.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/daily_stats.py) | Subscribers, paid subscribers, followers and views day by day. |
|
|
271
|
+
| [`traffic_sources.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/traffic_sources.py) | Where your visitors came from, most views first. |
|
|
272
|
+
| [`unanswered_comments.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/unanswered_comments.py) | Comments on your last N posts that you have not replied to. |
|
|
273
|
+
| [`reply_to_comment.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/reply_to_comment.py) | A reply under one comment. |
|
|
274
|
+
| [`list_subscribers.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/list_subscribers.py) | Subscribers by plan or join date, with activity rating. |
|
|
275
|
+
| [`export_subscribers.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/export_subscribers.py) | The full list as the CSV that Export gives in the dashboard. |
|
|
276
|
+
| [`add_subscribers.py`](https://github.com/cotletdev/substack-api-mcp-server/blob/main/examples/add_subscribers.py) | Adds emails from a text or CSV file as free subscribers, after asking you. |
|
|
277
277
|
|
|
278
278
|
```bash
|
|
279
279
|
python examples/draft_from_markdown.py essay.md --publish-at 2026-11-03T08:00:00-05:00
|
|
@@ -486,7 +486,7 @@ The source is public, the license is not an open source license: noncommercial u
|
|
|
486
486
|
|
|
487
487
|
## License
|
|
488
488
|
|
|
489
|
-
[PolyForm Noncommercial License 1.0.0](LICENSE). In short:
|
|
489
|
+
[PolyForm Noncommercial License 1.0.0](https://github.com/cotletdev/substack-api-mcp-server/blob/main/LICENSE). In short:
|
|
490
490
|
|
|
491
491
|
- **Allowed:** noncommercial use: you, for your own personal purposes with your own Substack account, or a charity, school, public research or government body. Changing the code, and sharing it under the same license.
|
|
492
492
|
- **Not allowed:** any commercial use, your own business included; client work; selling or offering it, or a service built on it.
|
|
@@ -499,7 +499,7 @@ Earlier versions of this repo (the scripts for the hosted API, up to commit 4399
|
|
|
499
499
|
<a href="https://cotlet.dev">
|
|
500
500
|
<picture>
|
|
501
501
|
<source media="(prefers-color-scheme: dark)" srcset="assets/logo-white.svg">
|
|
502
|
-
<img src="assets/logo.svg" alt="Cotlet" width="120">
|
|
502
|
+
<img src="https://raw.githubusercontent.com/cotletdev/substack-api-mcp-server/main/assets/logo.svg" alt="Cotlet" width="120">
|
|
503
503
|
</picture>
|
|
504
504
|
</a>
|
|
505
505
|
</p>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "substack-api-mcp"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.4"
|
|
4
4
|
description = "Self-hosted Substack API and MCP server on your own Chrome session. Noncommercial use (PolyForm Noncommercial 1.0.0)."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "PolyForm-Noncommercial-1.0.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/__init__.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/add_subscriber.py
RENAMED
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/create_draft.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/create_post_tag.py
RENAMED
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/delete_comment.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/delete_post.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/duplicate_post.py
RENAMED
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/follow_user.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_daily_stats.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_feed.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_post.py
RENAMED
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/get_post_stats.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/like_comment.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/like_post.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_activity.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_comments.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_notes.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_post_tags.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_posts.py
RENAMED
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/list_sections.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/pin_comment.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/publish_note.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/publish_post.py
RENAMED
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/remove_comment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/reply_to_note.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/schedule_post.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/search_substack.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/send_message.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/tag_post.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/tag_subscribers.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/unpublish_post.py
RENAMED
|
File without changes
|
{substack_api_mcp-1.0.3 → substack_api_mcp-1.0.4}/substack_api_mcp/substack/tools/update_draft.py
RENAMED
|
File without changes
|