印刷套件mcp
用于发布到Medium和Substack的Python FastMCP服务器和CLI。
稳定性警告:这两种集成都依赖于非官方/弃用的访问路径。 Medium的REST API已冻结(未颁发新令牌)。两个平台的内部 端点没有文档记录,可能会在不通知的情况下更改。
______________________________________________________________________
安装
pip install -e .这将安装两个命令:
presskit--CLI用于从终端直接发布publishing-mcp--与克劳德桌面/Claude代码一起使用的MCP服务器
______________________________________________________________________
CLI使用情况(presskit)
发布标记文件
# Publish to Medium as a draft
presskit publish medium --file docs/drafts/my-article.md
# Publish to Substack as a draft
presskit publish substack --file docs/drafts/my-article.md
# Publish to both platforms at once
presskit publish both --file docs/drafts/my-article.md
# Publish live (not draft)
presskit publish medium --file article.md --status public --tags "python,automation"
# Substack: publish to web only (no subscriber email)
presskit publish substack --file article.md --status public --no-emailCLI从markdown文件中读取YAML frontmatter:
---
title: "My Article Title"
subtitle: "Optional subtitle for Substack"
tags: [python, automation, infrastructure]
---
# My Article Title
Article body here...如果没有正面 title 存在,第一个 # Heading 使用。
列出帖子
# List your Medium posts
presskit list medium --username alexander.g.moore1
# List Substack posts
presskit list substack --subdomain alexgmoore
# List Substack drafts
presskit drafts substackCLI选项参考
presskit publish
[options]
--file, -f Markdown file to publish (required)
--status, -s draft | public | unlisted (default: draft)
--tags, -t Comma-separated tags, e.g. "python,devops" (Medium)
--subtitle Post subtitle (Substack)
--no-email Publish to web only, skip subscriber email (Substack)
presskit list
[options]
--username, -u Medium username without @ (Medium)
--subdomain, -d Substack subdomain (Substack)
--limit, -n Max results (default: 10)
presskit drafts substack______________________________________________________________________
MCP服务器使用情况
运行服务器
# Direct
python server.py
# Or via installed entry point
publishing-mcp添加到Claude代码(项目级)
创建 .claude/mcp.json 在您的项目中:
{
"mcpServers": {
"publishing": {
"command": "python3",
"args": ["/absolute/path/to/presskit-mcp/server.py"],
"env": {
"MEDIUM_SESSION_COOKIE": "your_sid_cookie",
"MEDIUM_AUTH_STATE_FILE": "/path/to/medium-auth.json",
"SUBSTACK_EMAIL": "you@example.com",
"SUBSTACK_PASSWORD": "your_substack_password",
"SUBSTACK_PUBLICATION_URL": "https://yourpub.substack.com"
}
}
}
}添加到克劳德桌面
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json (Mac):
{
"mcpServers": {
"publishing": {
"command": "python",
"args": ["/absolute/path/to/presskit-mcp/server.py"],
"env": {
"MEDIUM_SESSION_COOKIE": "your_sid",
"MEDIUM_AUTH_STATE_FILE": "/path/to/medium-auth.json",
"SUBSTACK_EMAIL": "you@example.com",
"SUBSTACK_PASSWORD": "your_password",
"SUBSTACK_PUBLICATION_URL": "https://yourpub.substack.com"
}
}
}
}添加配置后重新启动Claude Desktop/Code。
______________________________________________________________________
FastMCP开发与测试
presskit mcp是基于 FastMCP。以下是在开发过程中如何使用它。
交互式检查工具
MCP检查器打开一个浏览器UI,您可以在其中调用任何工具、查看输入/输出和调试:
# Using the mcp CLI (installed with mcp[cli])
mcp dev server.py这将启动服务器并在以下位置打开一个交互式检查器 http://localhost:5173。您可以:
- 浏览所有15个已注册的工具
- 填写参数并执行
- 实时查看JSON响应
- 测试错误处理
使用stdio传输运行服务器(默认)
# FastMCP defaults to stdio transport (what Claude Desktop/Code expects)
python server.py使用SSE传输运行(用于远程/HTTP访问)
# Start as an HTTP server on port 8000
mcp run server.py --transport sse --port 8000然后使用以下命令从任何MCP客户端连接 http://localhost:8000/sse.
直接通过调用工具 mcp call
# One-shot tool invocation without starting a persistent server
echo '{"username": "alexander.g.moore1", "limit": 5}' | \
mcp call server.py medium_list_posts列出所有已注册的工具
mcp tools server.py测试环境变量
# Medium (session-based — no integration token needed)
export MEDIUM_SESSION_COOKIE="your_sid_value"
export MEDIUM_AUTH_STATE_FILE="/path/to/medium-auth.json"
# Medium (REST API — only if you have an existing token)
export MEDIUM_INTEGRATION_TOKEN="your_token"
# Substack
export SUBSTACK_EMAIL="you@example.com"
export SUBSTACK_PASSWORD="your_password"
export SUBSTACK_PUBLICATION_URL="https://yourpub.substack.com"运行测试
python3 -m unittest discover -s tests -v测试使用 sys.modules 修补存根第三方deps——不需要外部服务。
______________________________________________________________________
工具参考
中等(6个工具)
| 工具 | 验证 | 方法 |
|---|---|---|
medium_get_current_user | 集成令牌 | REST API |
medium_get_publications | 集成令牌 | REST API |
medium_create_post | 集成令牌 | REST API |
medium_create_post_session | 会话cookie | GraphQL+Delta OT |
medium_list_posts | 会话cookie | 非官方GraphQL |
medium_get_post_stats | 会话cookie | 非官方GraphQL |
子工具包(9个工具)
| 工具 | 验证 | 方法 |
|---|---|---|
substack_get_publication_info | 电子邮件/密码或cookie | python子堆栈 |
substack_get_all_publications | 电子邮件/密码或cookie | python子堆栈 |
substack_list_posts | 无(公共) | 原始HTTP |
substack_get_post | 无(公共) | 原始HTTP |
substack_search_publications | 无(公共) | 原始HTTP |
substack_get_subscriber_count | 电子邮件/密码或cookie | python子堆栈 |
substack_list_drafts | 电子邮件/密码或cookie | python子堆栈 |
substack_create_draft | 电子邮件/密码或cookie | python子堆栈 |
substack_publish_post | 电子邮件/密码或cookie | python子堆栈 |
______________________________________________________________________
凭证
中期会话cookie
介质不再发布API令牌。基于会话的工具使用浏览器Cookie:
- 在浏览器中登录medium.com
- 提取
sid来自DevTools的cookie→ 应用→ Cookie - 要获得完整功能,请使用以下命令保存完整的浏览器状态
playwright-cli state-save medium-auth.json并设置MEDIUM_AUTH_STATE_FILE
子堆栈
直接使用您的Substack电子邮件和密码。如果您的帐户仅使用魔术链接:
- 退出Substack
- 点击“使用密码登录”
- 点击“设置新密码”
______________________________________________________________________
建筑
presskit-mcp/
├── server.py # FastMCP server entry point (15 tools)
├── cli.py # CLI entry point (presskit command)
├── medium/
│ ├── client.py # REST API + GraphQL + Delta OT HTTP layer
│ └── tools.py # 6 MCP tools with Pydantic input models
├── substack/
│ ├── client.py # python-substack wrapper + raw HTTP
│ └── tools.py # 9 MCP tools with Pydantic input models
├── tests/
│ └── test_static.py # Unit tests (no external deps needed)
├── pyproject.toml # pip installable, entry points
└── config.yaml # Credential reference (not loaded by code)Medium session发布的工作原理
Medium的web编辑器通过基于增量的Operational Transform系统保存内容,而不是GraphQL或REST medium_create_post_session 工具复制了这一点:
- 图查询语言
createPost→ 创建空草稿,返回post_id POST /p/{post_id}/deltas→ 将标题+段落作为OT增量- 图查询语言
setPostTags→ 最多设置5个标签 - 图查询语言
publishPost→ 发布(可选)
这是通过反编译Medium的Android APK并从网络编辑器中捕获网络流量而发现的。
______________________________________________________________________
已知限制
- 中期会话Cookie过期 --您需要刷新
medium-auth.json定期(通过浏览器重新登录) - 中等REST API --没有新的集成令牌。只有现有持有人可以使用
medium_create_post - 中等内联格式 -API中的粗体/斜体标记位置需要精确的字符偏移;当前的markdown解析器发送纯文本段落
- 子堆栈 -没有官方API。所有端点都经过逆向工程。将请求保持在1/秒以下
- 图像 --这两个平台都不支持通过这些工具进行程序化内联图像上传
