refactor: remove Douyin, Weibo and WeChat channels (#347)
All three had rotted past honest usability: - Douyin's upstream (yzfly/douyin-mcp-server) is archived and required a 4-step manual local-server setup nobody could complete - Weibo depended on an unmaintained personal fork (mcp-server-weibo) - WeChat full-article reading was increasingly blocked by anti-bot (#339) while doctor still advertised it as zero-config Removes the channel files, installers, skill routing/trigger entries, reference sections and README rows (zh+en). Honest counts: 13 platforms, 6 zero-config. They can return when maintained upstreams exist. Follows the v1.4.0 precedent of removing Discord/Toutiao (#234). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# CLAUDE.md
|
# CLAUDE.md
|
||||||
|
|
||||||
## Project
|
## Project
|
||||||
Agent Reach — Python CLI + library that gives AI agents read/search access to 14+ internet platforms.
|
Agent Reach — Python CLI + library that gives AI agents read/search access to 13 internet platforms.
|
||||||
Positioning: installer + doctor + config tool. NOT a wrapper — after install, agents call upstream tools directly.
|
Positioning: installer + doctor + config tool. NOT a wrapper — after install, agents call upstream tools directly.
|
||||||
Repo: github.com/Panniantong/Agent-Reach | License: MIT | Version: 1.4.1
|
Repo: github.com/Panniantong/Agent-Reach | License: MIT | Version: 1.4.1
|
||||||
|
|
||||||
|
|||||||
@@ -75,10 +75,7 @@ AI Agent 已经能帮你写代码、改文档、管项目——但你让它去
|
|||||||
| 📺 **B站** | 本地:字幕提取 + 搜索 | 服务器也能用 | 告诉 Agent「帮我配代理」 |
|
| 📺 **B站** | 本地:字幕提取 + 搜索 | 服务器也能用 | 告诉 Agent「帮我配代理」 |
|
||||||
| 📖 **Reddit** | 搜索 + 读帖子和评论(通过 rdt-cli) | Cookie | 需要登录认证(`rdt login`),详见 [rdt-cli](https://github.com/public-clis/rdt-cli) |
|
| 📖 **Reddit** | 搜索 + 读帖子和评论(通过 rdt-cli) | Cookie | 需要登录认证(`rdt login`),详见 [rdt-cli](https://github.com/public-clis/rdt-cli) |
|
||||||
| 📕 **小红书** | — | 阅读、搜索、发帖、评论、点赞 | 告诉 Agent「帮我配小红书」 |
|
| 📕 **小红书** | — | 阅读、搜索、发帖、评论、点赞 | 告诉 Agent「帮我配小红书」 |
|
||||||
| 🎵 **抖音** | — | 视频解析、无水印下载链接获取 | 告诉 Agent「帮我配抖音」 |
|
|
||||||
| 💼 **LinkedIn** | Jina Reader 读公开页面 | Profile 详情、公司页面、职位搜索 | 告诉 Agent「帮我配 LinkedIn」 |
|
| 💼 **LinkedIn** | Jina Reader 读公开页面 | Profile 详情、公司页面、职位搜索 | 告诉 Agent「帮我配 LinkedIn」 |
|
||||||
| 💬 **微信公众号** | 搜索 + 阅读公众号文章(全文 Markdown) | — | 无需配置 |
|
|
||||||
| 📰 **微博** | 热搜、搜索内容/用户/话题、用户动态、评论 | — | 无需配置 |
|
|
||||||
| 💻 **V2EX** | 热门帖子、节点帖子、帖子详情+回复、用户信息 | — | 无需配置 |
|
| 💻 **V2EX** | 热门帖子、节点帖子、帖子详情+回复、用户信息 | — | 无需配置 |
|
||||||
| 📈 **雪球** | 股票行情、搜索股票、热门帖子、热门股票排行 | — | 告诉 Agent「帮我配雪球」 |
|
| 📈 **雪球** | 股票行情、搜索股票、热门帖子、热门股票排行 | — | 告诉 Agent「帮我配雪球」 |
|
||||||
| 🎙️ **小宇宙播客** | — | 播客音频转文字(Whisper 转录,免费 Key) | 告诉 Agent「帮我配小宇宙播客」 |
|
| 🎙️ **小宇宙播客** | — | 播客音频转文字(Whisper 转录,免费 Key) | 告诉 Agent「帮我配小宇宙播客」 |
|
||||||
@@ -175,9 +172,7 @@ channels/
|
|||||||
├── bilibili.py → yt-dlp ← 可以换成 bilibili-api……
|
├── bilibili.py → yt-dlp ← 可以换成 bilibili-api……
|
||||||
├── reddit.py → rdt-cli ← 搜索+阅读,需 Cookie 认证
|
├── reddit.py → rdt-cli ← 搜索+阅读,需 Cookie 认证
|
||||||
├── xiaohongshu.py → mcporter MCP ← 可以换成其他 XHS 工具……
|
├── xiaohongshu.py → mcporter MCP ← 可以换成其他 XHS 工具……
|
||||||
├── douyin.py → mcporter MCP ← 可以换成其他抖音工具……
|
|
||||||
├── linkedin.py → linkedin-mcp ← 可以换成 LinkedIn API……
|
├── linkedin.py → linkedin-mcp ← 可以换成 LinkedIn API……
|
||||||
├── wechat.py → Exa (+ Camoufox) ← 搜索+阅读微信公众号文章
|
|
||||||
├── rss.py → feedparser ← 可以换成 atoma……
|
├── rss.py → feedparser ← 可以换成 atoma……
|
||||||
├── exa_search.py → mcporter MCP ← 可以换成 Tavily、SerpAPI……
|
├── exa_search.py → mcporter MCP ← 可以换成 Tavily、SerpAPI……
|
||||||
└── __init__.py → 渠道注册(doctor 检测用)
|
└── __init__.py → 渠道注册(doctor 检测用)
|
||||||
@@ -198,38 +193,10 @@ channels/
|
|||||||
| GitHub | [gh CLI](https://cli.github.com) | 官方工具,认证后完整 API 能力 |
|
| GitHub | [gh CLI](https://cli.github.com) | 官方工具,认证后完整 API 能力 |
|
||||||
| 读 RSS | [feedparser](https://github.com/kurtmckee/feedparser) | Python 生态标准选择,2.3K Star |
|
| 读 RSS | [feedparser](https://github.com/kurtmckee/feedparser) | Python 生态标准选择,2.3K Star |
|
||||||
| 小红书 | [xhs-cli](https://github.com/jackwener/xiaohongshu-cli) | 1.5K Star,pipx 一行安装,搜索/阅读/评论/发帖 |
|
| 小红书 | [xhs-cli](https://github.com/jackwener/xiaohongshu-cli) | 1.5K Star,pipx 一行安装,搜索/阅读/评论/发帖 |
|
||||||
| 抖音 | [douyin-mcp-server](https://github.com/yzfly/douyin-mcp-server) | MCP 服务,无需登录,视频解析 + 无水印下载 |
|
|
||||||
| LinkedIn | [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server) | ⭐1.2K,MCP 服务,浏览器自动化 |
|
| LinkedIn | [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server) | ⭐1.2K,MCP 服务,浏览器自动化 |
|
||||||
| 微信公众号 | [Exa](https://exa.ai)(搜索+阅读)+ [Camoufox](https://github.com/daijro/camoufox)(可选) | 零配置搜索+全文阅读,Camoufox 可选增强 |
|
|
||||||
|
|
||||||
> 📌 这些都是「当前选型」。不满意?换掉对应文件就行。这正是脚手架的意义。
|
> 📌 这些都是「当前选型」。不满意?换掉对应文件就行。这正是脚手架的意义。
|
||||||
|
|
||||||
### 抖音 / 小红书脚本提取的可选实现
|
|
||||||
|
|
||||||
如果你不只是想“解析抖音视频信息”,还想统一处理:
|
|
||||||
|
|
||||||
- 抖音视频脚本提取
|
|
||||||
- 小红书视频笔记脚本提取
|
|
||||||
- 小红书图文笔记正文 + 图片文字提取
|
|
||||||
- 固定输出 `script.md` 和 `info.json`
|
|
||||||
|
|
||||||
可以把 `douyin` 这个 mcporter alias 指向另一个兼容实现:
|
|
||||||
|
|
||||||
- [social-post-extractor-mcp](https://github.com/JNHFlow21/social-post-extractor-mcp)
|
|
||||||
|
|
||||||
这个实现保留了旧工具名兼容性:
|
|
||||||
|
|
||||||
- `parse_douyin_video_info`
|
|
||||||
- `get_douyin_download_link`
|
|
||||||
- `extract_douyin_text`
|
|
||||||
|
|
||||||
同时新增统一工具:
|
|
||||||
|
|
||||||
- `parse_social_post_info`
|
|
||||||
- `extract_social_post_script`
|
|
||||||
|
|
||||||
所以从 Agent Reach 的视角看,它依然只是一个 `mcporter` 里的 `douyin` server,只是能力更完整。
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 安全性
|
## 安全性
|
||||||
@@ -338,12 +305,6 @@ Agent Reach 使用 [rdt-cli](https://github.com/public-clis/rdt-cli) 访问 Redd
|
|||||||
安装 `pipx install xiaohongshu-cli`,然后 `xhs login`(自动从浏览器提取 Cookie)。之后 Agent 就能用 `xhs search "关键词"` 搜索笔记、`xhs read NOTE_ID` 阅读详情、`xhs comments NOTE_ID` 查看评论了。不需要 Docker。
|
安装 `pipx install xiaohongshu-cli`,然后 `xhs login`(自动从浏览器提取 Cookie)。之后 Agent 就能用 `xhs search "关键词"` 搜索笔记、`xhs read NOTE_ID` 阅读详情、`xhs comments NOTE_ID` 查看评论了。不需要 Docker。
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><strong>怎么让 AI Agent 解析抖音视频?</strong></summary>
|
|
||||||
|
|
||||||
安装 douyin-mcp-server 后,Agent 就能用 `mcporter call 'douyin.parse_douyin_video_info(share_link: "分享链接")'` 解析视频信息、获取无水印下载链接。不需要登录,把抖音分享链接发给 Agent 就行。详见 https://github.com/yzfly/douyin-mcp-server
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><strong>Compatible with Claude Code / Cursor / OpenClaw / Windsurf?</strong></summary>
|
<summary><strong>Compatible with Claude Code / Cursor / OpenClaw / Windsurf?</strong></summary>
|
||||||
|
|
||||||
@@ -362,7 +323,7 @@ Yes! Agent Reach is an installer + configuration tool — any AI coding agent th
|
|||||||
|
|
||||||
## 致谢
|
## 致谢
|
||||||
|
|
||||||
[twitter-cli](https://github.com/public-clis/twitter-cli) · [rdt-cli](https://github.com/public-clis/rdt-cli) · [xhs-cli](https://github.com/jackwener/xiaohongshu-cli) · [bili-cli](https://github.com/public-clis/bilibili-cli) · [yt-dlp](https://github.com/yt-dlp/yt-dlp) · [Jina Reader](https://github.com/jina-ai/reader) · [Exa](https://exa.ai) · [mcporter](https://github.com/nicobailon/mcporter) · [feedparser](https://github.com/kurtmckee/feedparser) · [douyin-mcp-server](https://github.com/yzfly/douyin-mcp-server) · [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server)
|
[twitter-cli](https://github.com/public-clis/twitter-cli) · [rdt-cli](https://github.com/public-clis/rdt-cli) · [xhs-cli](https://github.com/jackwener/xiaohongshu-cli) · [bili-cli](https://github.com/public-clis/bilibili-cli) · [yt-dlp](https://github.com/yt-dlp/yt-dlp) · [Jina Reader](https://github.com/jina-ai/reader) · [Exa](https://exa.ai) · [mcporter](https://github.com/nicobailon/mcporter) · [feedparser](https://github.com/kurtmckee/feedparser) · [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server)
|
||||||
|
|
||||||
## 联系
|
## 联系
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,7 @@ from .rss import RSSChannel
|
|||||||
from .bilibili import BilibiliChannel
|
from .bilibili import BilibiliChannel
|
||||||
from .exa_search import ExaSearchChannel
|
from .exa_search import ExaSearchChannel
|
||||||
from .xiaohongshu import XiaoHongShuChannel
|
from .xiaohongshu import XiaoHongShuChannel
|
||||||
from .douyin import DouyinChannel
|
|
||||||
from .linkedin import LinkedInChannel
|
from .linkedin import LinkedInChannel
|
||||||
from .wechat import WeChatChannel
|
|
||||||
from .weibo import WeiboChannel
|
|
||||||
from .xiaoyuzhou import XiaoyuzhouChannel
|
from .xiaoyuzhou import XiaoyuzhouChannel
|
||||||
from .v2ex import V2EXChannel
|
from .v2ex import V2EXChannel
|
||||||
from .xueqiu import XueqiuChannel
|
from .xueqiu import XueqiuChannel
|
||||||
@@ -32,10 +29,7 @@ ALL_CHANNELS: List[Channel] = [
|
|||||||
RedditChannel(),
|
RedditChannel(),
|
||||||
BilibiliChannel(),
|
BilibiliChannel(),
|
||||||
XiaoHongShuChannel(),
|
XiaoHongShuChannel(),
|
||||||
DouyinChannel(),
|
|
||||||
LinkedInChannel(),
|
LinkedInChannel(),
|
||||||
WeChatChannel(),
|
|
||||||
WeiboChannel(),
|
|
||||||
XiaoyuzhouChannel(),
|
XiaoyuzhouChannel(),
|
||||||
V2EXChannel(),
|
V2EXChannel(),
|
||||||
XueqiuChannel(),
|
XueqiuChannel(),
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""Douyin (抖音) — check if mcporter + douyin-mcp-server is available."""
|
|
||||||
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from agent_reach.utils.process import utf8_subprocess_env
|
|
||||||
|
|
||||||
from .base import Channel
|
|
||||||
|
|
||||||
|
|
||||||
class DouyinChannel(Channel):
|
|
||||||
name = "douyin"
|
|
||||||
description = "抖音短视频"
|
|
||||||
backends = ["douyin-mcp-server"]
|
|
||||||
tier = 2
|
|
||||||
|
|
||||||
def can_handle(self, url: str) -> bool:
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
d = urlparse(url).netloc.lower()
|
|
||||||
return "douyin.com" in d or "iesdouyin.com" in d
|
|
||||||
|
|
||||||
def check(self, config=None):
|
|
||||||
mcporter = shutil.which("mcporter")
|
|
||||||
if not mcporter:
|
|
||||||
return "off", (
|
|
||||||
"需要 mcporter + douyin-mcp-server。安装步骤:\n"
|
|
||||||
" 1. npm install -g mcporter\n"
|
|
||||||
" 2. pip install douyin-mcp-server\n"
|
|
||||||
" 3. 启动服务(见下方说明)\n"
|
|
||||||
" 4. mcporter config add douyin http://localhost:18070/mcp\n"
|
|
||||||
" 详见 https://github.com/yzfly/douyin-mcp-server"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
r = subprocess.run(
|
|
||||||
[mcporter, "config", "list"], capture_output=True,
|
|
||||||
encoding="utf-8", errors="replace", timeout=5,
|
|
||||||
env=utf8_subprocess_env(),
|
|
||||||
)
|
|
||||||
if "douyin" not in r.stdout:
|
|
||||||
return "off", (
|
|
||||||
"mcporter 已装但抖音 MCP 未配置。运行:\n"
|
|
||||||
" pip install douyin-mcp-server\n"
|
|
||||||
" # 启动服务后:\n"
|
|
||||||
" mcporter config add douyin http://localhost:18070/mcp"
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
return "off", "mcporter 连接异常"
|
|
||||||
# Verify MCP connectivity by listing available tools instead of
|
|
||||||
# calling with a hardcoded (invalid) share link that always fails.
|
|
||||||
try:
|
|
||||||
r = subprocess.run(
|
|
||||||
[mcporter, "list", "douyin"],
|
|
||||||
capture_output=True, encoding="utf-8", errors="replace", timeout=15,
|
|
||||||
env=utf8_subprocess_env(),
|
|
||||||
)
|
|
||||||
if r.returncode == 0 and r.stdout.strip():
|
|
||||||
return "ok", "完整可用(视频解析、下载链接获取)"
|
|
||||||
return "warn", "MCP 已连接但工具列表为空,检查 douyin-mcp-server 服务是否在运行"
|
|
||||||
except Exception:
|
|
||||||
return "warn", "MCP 连接异常,检查 douyin-mcp-server 服务是否在运行"
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""WeChat Official Account articles — read and search.
|
|
||||||
|
|
||||||
Read: Exa crawling (primary) / Camoufox stealth browser (optional)
|
|
||||||
Search: Exa web_search with includeDomains mp.weixin.qq.com
|
|
||||||
"""
|
|
||||||
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
from .base import Channel
|
|
||||||
|
|
||||||
|
|
||||||
def _exa_available() -> bool:
|
|
||||||
mcporter = shutil.which("mcporter")
|
|
||||||
if not mcporter:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
r = subprocess.run(
|
|
||||||
[mcporter, "config", "list"],
|
|
||||||
capture_output=True, encoding="utf-8", errors="replace", timeout=5,
|
|
||||||
)
|
|
||||||
return "exa" in r.stdout.lower()
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class WeChatChannel(Channel):
|
|
||||||
name = "wechat"
|
|
||||||
description = "微信公众号文章"
|
|
||||||
backends = ["Exa via mcporter (搜索+阅读)", "Camoufox (可选阅读)"]
|
|
||||||
tier = 0
|
|
||||||
|
|
||||||
def can_handle(self, url: str) -> bool:
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
d = urlparse(url).netloc.lower()
|
|
||||||
return "mp.weixin.qq.com" in d or "weixin.qq.com" in d
|
|
||||||
|
|
||||||
def check(self, config=None):
|
|
||||||
has_exa = _exa_available()
|
|
||||||
has_camoufox = False
|
|
||||||
try:
|
|
||||||
import camoufox # noqa: F401
|
|
||||||
has_camoufox = True
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if has_exa and has_camoufox:
|
|
||||||
return "ok", "完整可用(Exa 搜索 + Exa/Camoufox 阅读公众号文章)"
|
|
||||||
elif has_exa:
|
|
||||||
return "ok", (
|
|
||||||
"通过 Exa 搜索和阅读微信公众号文章(免费,无需额外配置)。"
|
|
||||||
"可选安装 Camoufox 获得更好的全文阅读效果。"
|
|
||||||
)
|
|
||||||
elif has_camoufox:
|
|
||||||
return "warn", (
|
|
||||||
"Camoufox 可阅读公众号文章,但搜索功能需要 Exa。"
|
|
||||||
"运行 `agent-reach install --env=auto` 安装 Exa。"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return "off", (
|
|
||||||
"需要 mcporter + Exa MCP 来搜索和阅读微信公众号文章。\n"
|
|
||||||
"运行 `agent-reach install --env=auto` 安装。"
|
|
||||||
)
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""Weibo (微博) — check if mcporter + mcp-server-weibo is available."""
|
|
||||||
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from agent_reach.utils.process import utf8_subprocess_env
|
|
||||||
|
|
||||||
from .base import Channel
|
|
||||||
|
|
||||||
|
|
||||||
class WeiboChannel(Channel):
|
|
||||||
name = "weibo"
|
|
||||||
description = "微博动态与热搜"
|
|
||||||
backends = ["mcp-server-weibo"]
|
|
||||||
tier = 1
|
|
||||||
|
|
||||||
def can_handle(self, url: str) -> bool:
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
d = urlparse(url).netloc.lower()
|
|
||||||
return "weibo.com" in d or "weibo.cn" in d
|
|
||||||
|
|
||||||
def check(self, config=None):
|
|
||||||
mcporter = shutil.which("mcporter")
|
|
||||||
if not mcporter:
|
|
||||||
return "off", (
|
|
||||||
"需要 mcporter + mcp-server-weibo。安装步骤:\n"
|
|
||||||
" 1. npm install -g mcporter\n"
|
|
||||||
" 2. pip install git+https://github.com/Panniantong/mcp-server-weibo.git\n"
|
|
||||||
" 3. mcporter config add weibo --command 'mcp-server-weibo' "
|
|
||||||
"--env PYTHONUTF8=1 --env PYTHONIOENCODING=utf-8\n"
|
|
||||||
" 详见 https://github.com/Panniantong/mcp-server-weibo"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
r = subprocess.run(
|
|
||||||
[mcporter, "config", "list"], capture_output=True,
|
|
||||||
encoding="utf-8", errors="replace", timeout=5,
|
|
||||||
env=utf8_subprocess_env(),
|
|
||||||
)
|
|
||||||
if "weibo" not in r.stdout:
|
|
||||||
return "off", (
|
|
||||||
"mcporter 已装但微博 MCP 未配置。运行:\n"
|
|
||||||
" pip install git+https://github.com/Panniantong/mcp-server-weibo.git\n"
|
|
||||||
" mcporter config add weibo --command 'mcp-server-weibo' "
|
|
||||||
"--env PYTHONUTF8=1 --env PYTHONIOENCODING=utf-8"
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
return "off", "mcporter 连接异常"
|
|
||||||
try:
|
|
||||||
r = subprocess.run(
|
|
||||||
[mcporter, "list", "weibo"], capture_output=True,
|
|
||||||
encoding="utf-8", errors="replace", timeout=15,
|
|
||||||
env=utf8_subprocess_env(),
|
|
||||||
)
|
|
||||||
if r.returncode == 0 and "search_users" in r.stdout:
|
|
||||||
return "ok", "完整可用(热搜、搜索、用户动态、评论)"
|
|
||||||
return "warn", "MCP 已配置但工具加载失败,检查 mcp-server-weibo 版本"
|
|
||||||
except Exception:
|
|
||||||
return "warn", "MCP 连接异常,检查 mcp-server-weibo 是否可用"
|
|
||||||
+6
-130
@@ -73,8 +73,8 @@ def main():
|
|||||||
help="Show what would be done without making any changes")
|
help="Show what would be done without making any changes")
|
||||||
p_install.add_argument("--channels", default="",
|
p_install.add_argument("--channels", default="",
|
||||||
help="Comma-separated optional channels to install "
|
help="Comma-separated optional channels to install "
|
||||||
"(twitter,weibo,wechat,xiaoyuzhou,xueqiu,xiaohongshu,"
|
"(twitter,xiaoyuzhou,xueqiu,xiaohongshu,"
|
||||||
"reddit,bilibili,douyin,linkedin,all)")
|
"reddit,bilibili,linkedin,all)")
|
||||||
|
|
||||||
# ── configure ──
|
# ── configure ──
|
||||||
p_conf = sub.add_parser("configure", help="Set a config value or auto-extract from browser")
|
p_conf = sub.add_parser("configure", help="Set a config value or auto-extract from browser")
|
||||||
@@ -193,14 +193,12 @@ def _cmd_install(args):
|
|||||||
# ── Parse --channels ──
|
# ── Parse --channels ──
|
||||||
CHANNEL_INSTALLERS = {
|
CHANNEL_INSTALLERS = {
|
||||||
"twitter": _install_twitter_deps,
|
"twitter": _install_twitter_deps,
|
||||||
"weibo": _install_weibo_deps,
|
|
||||||
"wechat": _install_wechat_deps,
|
|
||||||
"xiaoyuzhou": _install_xiaoyuzhou_deps,
|
"xiaoyuzhou": _install_xiaoyuzhou_deps,
|
||||||
"xiaohongshu": _install_xhs_deps,
|
"xiaohongshu": _install_xhs_deps,
|
||||||
"reddit": _install_reddit_deps,
|
"reddit": _install_reddit_deps,
|
||||||
"bilibili": _install_bili_deps,
|
"bilibili": _install_bili_deps,
|
||||||
# xueqiu: cookie-only, no install step
|
# xueqiu: cookie-only, no install step
|
||||||
# douyin/linkedin: manual setup, no auto-install
|
# linkedin: manual setup, no auto-install
|
||||||
}
|
}
|
||||||
COOKIE_CHANNELS = {"twitter", "xueqiu", "bilibili"}
|
COOKIE_CHANNELS = {"twitter", "xueqiu", "bilibili"}
|
||||||
|
|
||||||
@@ -208,7 +206,7 @@ def _cmd_install(args):
|
|||||||
if args.channels:
|
if args.channels:
|
||||||
raw = [c.strip().lower() for c in args.channels.split(",") if c.strip()]
|
raw = [c.strip().lower() for c in args.channels.split(",") if c.strip()]
|
||||||
if "all" in raw:
|
if "all" in raw:
|
||||||
requested_channels = set(CHANNEL_INSTALLERS.keys()) | {"xueqiu", "douyin", "linkedin"}
|
requested_channels = set(CHANNEL_INSTALLERS.keys()) | {"xueqiu", "linkedin"}
|
||||||
else:
|
else:
|
||||||
requested_channels = set(raw)
|
requested_channels = set(raw)
|
||||||
|
|
||||||
@@ -320,7 +318,7 @@ def _cmd_install(args):
|
|||||||
# First install — hint about optional channels
|
# First install — hint about optional channels
|
||||||
print()
|
print()
|
||||||
print("More channels available! Use --channels to install:")
|
print("More channels available! Use --channels to install:")
|
||||||
print(" agent-reach install --channels=twitter,weibo,xiaohongshu,...")
|
print(" agent-reach install --channels=twitter,xiaohongshu,reddit,...")
|
||||||
print(" agent-reach install --channels=all (install everything)")
|
print(" agent-reach install --channels=all (install everything)")
|
||||||
|
|
||||||
# Star reminder
|
# Star reminder
|
||||||
@@ -616,7 +614,7 @@ def _install_system_deps():
|
|||||||
except Exception:
|
except Exception:
|
||||||
print(" -- Could not configure yt-dlp JS runtime (YouTube may not work)")
|
print(" -- Could not configure yt-dlp JS runtime (YouTube may not work)")
|
||||||
|
|
||||||
# NOTE: twitter-cli, weibo, xiaoyuzhou, wechat, xhs-cli etc. are optional.
|
# NOTE: twitter-cli, xiaoyuzhou, xhs-cli etc. are optional.
|
||||||
# They are installed via --channels flag, not here.
|
# They are installed via --channels flag, not here.
|
||||||
# See CHANNEL_INSTALLERS in _cmd_install().
|
# See CHANNEL_INSTALLERS in _cmd_install().
|
||||||
|
|
||||||
@@ -758,128 +756,6 @@ def _install_bili_deps():
|
|||||||
print(" [!] bili-cli install failed. Run: pipx install bilibili-cli")
|
print(" [!] bili-cli install failed. Run: pipx install bilibili-cli")
|
||||||
|
|
||||||
|
|
||||||
def _install_weibo_deps():
|
|
||||||
"""Install Weibo MCP server (Panniantong fork with visitor passport auth)."""
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from agent_reach.utils.process import mcporter_utf8_env_args, utf8_subprocess_env
|
|
||||||
|
|
||||||
print("Setting up Weibo MCP server...")
|
|
||||||
|
|
||||||
# Check if already installed and working
|
|
||||||
mcporter = shutil.which("mcporter")
|
|
||||||
if mcporter:
|
|
||||||
try:
|
|
||||||
r = subprocess.run(
|
|
||||||
[mcporter, "config", "list"], capture_output=True,
|
|
||||||
encoding="utf-8", errors="replace", timeout=5,
|
|
||||||
env=utf8_subprocess_env(),
|
|
||||||
)
|
|
||||||
if "weibo" in r.stdout:
|
|
||||||
print(" ✅ Weibo MCP already configured")
|
|
||||||
return
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Install from our fork (has visitor passport auth fix)
|
|
||||||
try:
|
|
||||||
subprocess.run(
|
|
||||||
[sys.executable, "-m", "pip", "install", "-q",
|
|
||||||
"git+https://github.com/Panniantong/mcp-server-weibo.git"],
|
|
||||||
check=True, timeout=120, env=utf8_subprocess_env()
|
|
||||||
)
|
|
||||||
print(" ✅ mcp-server-weibo installed (Panniantong fork)")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" [!] mcp-server-weibo install failed: {e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Register with mcporter (force UTF-8 in the server's env — Windows GBK
|
|
||||||
# consoles otherwise corrupt the MCP server's Chinese output)
|
|
||||||
if mcporter:
|
|
||||||
try:
|
|
||||||
subprocess.run(
|
|
||||||
[mcporter, "config", "add", "weibo", "--command", "mcp-server-weibo",
|
|
||||||
*mcporter_utf8_env_args()],
|
|
||||||
check=True, capture_output=True, timeout=10
|
|
||||||
)
|
|
||||||
print(" ✅ Weibo MCP registered with mcporter")
|
|
||||||
except Exception:
|
|
||||||
print(" [!] mcporter config add failed. Run manually: mcporter config add weibo --command 'mcp-server-weibo' --env PYTHONUTF8=1 --env PYTHONIOENCODING=utf-8")
|
|
||||||
else:
|
|
||||||
print(" -- mcporter not found, skipping MCP registration. Install mcporter first, then run: mcporter config add weibo --command 'mcp-server-weibo' --env PYTHONUTF8=1 --env PYTHONIOENCODING=utf-8")
|
|
||||||
|
|
||||||
|
|
||||||
def _install_wechat_deps():
|
|
||||||
"""Install WeChat article reading and search dependencies."""
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
print("Setting up WeChat article tools...")
|
|
||||||
|
|
||||||
# Check if already installed
|
|
||||||
has_camoufox = False
|
|
||||||
has_miku = False
|
|
||||||
try:
|
|
||||||
import camoufox # noqa: F401
|
|
||||||
has_camoufox = True
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
import miku_ai # noqa: F401
|
|
||||||
has_miku = True
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Install Python packages
|
|
||||||
if has_camoufox and has_miku:
|
|
||||||
print(" ✅ WeChat Python packages already installed")
|
|
||||||
else:
|
|
||||||
pkgs = []
|
|
||||||
if not has_camoufox:
|
|
||||||
pkgs.extend(["camoufox[geoip]", "markdownify", "beautifulsoup4", "httpx"])
|
|
||||||
if not has_miku:
|
|
||||||
pkgs.append("miku_ai")
|
|
||||||
try:
|
|
||||||
cmd = [sys.executable, "-m", "pip", "install", "--break-system-packages", "-q"] + pkgs
|
|
||||||
subprocess.run(cmd, capture_output=True, encoding="utf-8", errors="replace", timeout=120)
|
|
||||||
# Verify
|
|
||||||
ok = True
|
|
||||||
try:
|
|
||||||
import importlib
|
|
||||||
if not has_camoufox:
|
|
||||||
importlib.import_module("camoufox")
|
|
||||||
if not has_miku:
|
|
||||||
importlib.import_module("miku_ai")
|
|
||||||
except ImportError:
|
|
||||||
ok = False
|
|
||||||
if ok:
|
|
||||||
print(f" ✅ WeChat Python packages installed ({', '.join(pkgs)})")
|
|
||||||
else:
|
|
||||||
print(f" [!] Some WeChat packages failed to install. Try: pip install {' '.join(pkgs)}")
|
|
||||||
except Exception:
|
|
||||||
print(f" [!] WeChat packages install failed. Try: pip install {' '.join(pkgs)}")
|
|
||||||
|
|
||||||
# Clone wechat-article-for-ai tool
|
|
||||||
tools_dir = os.path.expanduser("~/.agent-reach/tools")
|
|
||||||
wechat_dir = os.path.join(tools_dir, "wechat-article-for-ai")
|
|
||||||
if os.path.isfile(os.path.join(wechat_dir, "main.py")):
|
|
||||||
print(" ✅ wechat-article-for-ai tool already installed")
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
os.makedirs(tools_dir, exist_ok=True)
|
|
||||||
subprocess.run(
|
|
||||||
["git", "clone", "--depth", "1",
|
|
||||||
"https://github.com/Panniantong/wechat-article-for-ai.git", wechat_dir],
|
|
||||||
capture_output=True, encoding="utf-8", errors="replace", timeout=60,
|
|
||||||
)
|
|
||||||
if os.path.isfile(os.path.join(wechat_dir, "main.py")):
|
|
||||||
print(" ✅ wechat-article-for-ai tool installed")
|
|
||||||
else:
|
|
||||||
print(" [!] wechat-article-for-ai clone failed. Try: git clone https://github.com/Panniantong/wechat-article-for-ai.git " + wechat_dir)
|
|
||||||
except Exception:
|
|
||||||
print(" [!] wechat-article-for-ai clone failed. Try: git clone https://github.com/Panniantong/wechat-article-for-ai.git " + wechat_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def _install_system_deps_safe():
|
def _install_system_deps_safe():
|
||||||
"""Safe mode: check what's installed, print instructions for what's missing."""
|
"""Safe mode: check what's installed, print instructions for what's missing."""
|
||||||
import shutil
|
import shutil
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
# 微信公众号配置指南
|
|
||||||
|
|
||||||
## 功能说明
|
|
||||||
读取微信公众号文章。需要 Playwright 来处理微信的反爬机制。
|
|
||||||
|
|
||||||
## Agent 可自动完成的步骤
|
|
||||||
|
|
||||||
1. 检查 Playwright 是否安装:
|
|
||||||
```bash
|
|
||||||
python3 -c "import playwright; print('installed')" 2>&1
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 安装 Playwright + 浏览器:
|
|
||||||
```bash
|
|
||||||
pip install playwright
|
|
||||||
playwright install chromium
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 安装完成后测试:
|
|
||||||
```bash
|
|
||||||
curl -s "https://r.jina.ai/https://mp.weixin.qq.com/s/一个测试链接" -H "Accept: text/markdown"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 需要用户手动做的步骤
|
|
||||||
|
|
||||||
请告诉用户:
|
|
||||||
|
|
||||||
> 微信公众号的配置很简单,只需要安装一个浏览器组件(约 150MB)。
|
|
||||||
>
|
|
||||||
> 我来帮你安装,你不需要做任何事情。安装过程大约 1-2 分钟。
|
|
||||||
>
|
|
||||||
> 安装好之后就可以直接读取微信公众号文章了,不需要登录。
|
|
||||||
|
|
||||||
## Agent 操作流程
|
|
||||||
|
|
||||||
1. 安装 Playwright:`pip install playwright`
|
|
||||||
2. 安装 Chromium:`playwright install chromium`
|
|
||||||
3. 测试:读一篇微信文章
|
|
||||||
4. 反馈:"✅ 微信公众号已配置!发给我任何公众号文章链接,我都能读取。"
|
|
||||||
5. 如果安装失败(空间不足等):"❌ 浏览器组件安装失败。可能是磁盘空间不足(需要约 150MB)。"
|
|
||||||
+10
-12
@@ -2,29 +2,27 @@
|
|||||||
name: agent-reach
|
name: agent-reach
|
||||||
description: >
|
description: >
|
||||||
MUST USE when user asks to search, browse, read, or interact with content from any of these platforms:
|
MUST USE when user asks to search, browse, read, or interact with content from any of these platforms:
|
||||||
小红书/xiaohongshu/xhs, 抖音/douyin, Twitter/推特/X, 微博/weibo, B站/bilibili,
|
小红书/xiaohongshu/xhs, Twitter/推特/X, B站/bilibili,
|
||||||
V2EX, Reddit, LinkedIn/领英, YouTube, GitHub code search, 微信公众号/WeChat articles,
|
V2EX, Reddit, LinkedIn/领英, YouTube, GitHub code search,
|
||||||
小宇宙播客, 雪球/股票行情, RSS feeds, or any web URL.
|
小宇宙播客, 雪球/股票行情, RSS feeds, or any web URL.
|
||||||
|
|
||||||
Also MUST USE for: web搜索/搜/查/找/look up/research, 招聘/求职/jobs, 分享的链接/URL.
|
Also MUST USE for: web搜索/搜/查/找/look up/research, 招聘/求职/jobs, 分享的链接/URL.
|
||||||
Routes to CLI tools: xhs-cli, twitter-cli, rdt-cli, gh, yt-dlp, curl+Jina, mcporter.
|
Routes to CLI tools: xhs-cli, twitter-cli, rdt-cli, gh, yt-dlp, curl+Jina, mcporter.
|
||||||
17 platforms. Zero config for 8 channels.
|
13 platforms. Zero config for 6 channels.
|
||||||
|
|
||||||
【路由方式】SKILL.md 包含路由表和常用命令,复杂场景需按需阅读对应分类的 references/*.md。
|
【路由方式】SKILL.md 包含路由表和常用命令,复杂场景需按需阅读对应分类的 references/*.md。
|
||||||
分类:search / social (小红书/抖音/微博/推特/B站/V2EX/Reddit) / career(LinkedIn) / dev(github) / web(网页/文章/公众号/RSS) / video(YouTube/B站/播客)。
|
分类:search / social (小红书/推特/B站/V2EX/Reddit) / career(LinkedIn) / dev(github) / web(网页/文章/RSS) / video(YouTube/B站/播客)。
|
||||||
triggers:
|
triggers:
|
||||||
- search: 搜/查/找/search/搜索/查一下/帮我搜
|
- search: 搜/查/找/search/搜索/查一下/帮我搜
|
||||||
- social:
|
- social:
|
||||||
- 小红书: xiaohongshu/xhs/小红书/红书
|
- 小红书: xiaohongshu/xhs/小红书/红书
|
||||||
- 抖音: douyin/抖音
|
|
||||||
- Twitter: twitter/推特/x.com/推文
|
- Twitter: twitter/推特/x.com/推文
|
||||||
- 微博: weibo/微博
|
|
||||||
- B站: bilibili/b站/哔哩哔哩
|
- B站: bilibili/b站/哔哩哔哩
|
||||||
- V2EX: v2ex
|
- V2EX: v2ex
|
||||||
- Reddit: reddit
|
- Reddit: reddit
|
||||||
- career: 招聘/职位/求职/linkedin/领英/找工作
|
- career: 招聘/职位/求职/linkedin/领英/找工作
|
||||||
- dev: github/代码/仓库/gh/issue/pr/分支/commit
|
- dev: github/代码/仓库/gh/issue/pr/分支/commit
|
||||||
- web: 网页/链接/文章/公众号/微信文章/rss/读一下/打开这个
|
- web: 网页/链接/文章/rss/读一下/打开这个
|
||||||
- video: youtube/视频/播客/字幕/小宇宙/转录/yt
|
- video: youtube/视频/播客/字幕/小宇宙/转录/yt
|
||||||
- finance: 雪球/股票/stock/xueqiu/行情/基金
|
- finance: 雪球/股票/stock/xueqiu/行情/基金
|
||||||
metadata:
|
metadata:
|
||||||
@@ -34,17 +32,17 @@ metadata:
|
|||||||
|
|
||||||
# Agent Reach — 路由器
|
# Agent Reach — 路由器
|
||||||
|
|
||||||
17 平台工具集合。根据用户意图选择对应分类。
|
13 平台工具集合。根据用户意图选择对应分类。
|
||||||
|
|
||||||
## 路由表
|
## 路由表
|
||||||
|
|
||||||
| 用户意图 | 分类 | 详细文档 |
|
| 用户意图 | 分类 | 详细文档 |
|
||||||
|---------|------|---------|
|
|---------|------|---------|
|
||||||
| 网页搜索/代码搜索 | search | [references/search.md](references/search.md) |
|
| 网页搜索/代码搜索 | search | [references/search.md](references/search.md) |
|
||||||
| 小红书/抖音/微博/推特/B站/V2EX/Reddit | social | [references/social.md](references/social.md) |
|
| 小红书/推特/B站/V2EX/Reddit | social | [references/social.md](references/social.md) |
|
||||||
| 招聘/职位/LinkedIn | career | [references/career.md](references/career.md) |
|
| 招聘/职位/LinkedIn | career | [references/career.md](references/career.md) |
|
||||||
| GitHub/代码 | dev | [references/dev.md](references/dev.md) |
|
| GitHub/代码 | dev | [references/dev.md](references/dev.md) |
|
||||||
| 网页/文章/公众号/RSS | web | [references/web.md](references/web.md) |
|
| 网页/文章/RSS | web | [references/web.md](references/web.md) |
|
||||||
| YouTube/B站/播客字幕 | video | [references/video.md](references/video.md) |
|
| YouTube/B站/播客字幕 | video | [references/video.md](references/video.md) |
|
||||||
|
|
||||||
## 零配置快速命令
|
## 零配置快速命令
|
||||||
@@ -94,10 +92,10 @@ mcporter_list_servers()
|
|||||||
根据用户需求,阅读对应的详细文档:
|
根据用户需求,阅读对应的详细文档:
|
||||||
|
|
||||||
- [搜索工具](references/search.md) — Exa AI 搜索
|
- [搜索工具](references/search.md) — Exa AI 搜索
|
||||||
- [社交媒体](references/social.md) — 小红书, 抖音, Twitter, B站, V2EX, Reddit
|
- [社交媒体](references/social.md) — 小红书, Twitter, B站, V2EX, Reddit
|
||||||
- [职场招聘](references/career.md) — LinkedIn
|
- [职场招聘](references/career.md) — LinkedIn
|
||||||
- [开发工具](references/dev.md) — GitHub CLI
|
- [开发工具](references/dev.md) — GitHub CLI
|
||||||
- [网页阅读](references/web.md) — Jina Reader, 微信公众号, RSS
|
- [网页阅读](references/web.md) — Jina Reader, RSS
|
||||||
- [视频播客](references/video.md) — YouTube, B站, 小宇宙
|
- [视频播客](references/video.md) — YouTube, B站, 小宇宙
|
||||||
|
|
||||||
## 配置渠道
|
## 配置渠道
|
||||||
|
|||||||
@@ -2,17 +2,16 @@
|
|||||||
name: agent-reach
|
name: agent-reach
|
||||||
description: >
|
description: >
|
||||||
MUST USE when user asks to search, browse, read, or interact with content from any supported platform:
|
MUST USE when user asks to search, browse, read, or interact with content from any supported platform:
|
||||||
Twitter/X, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu, Douyin, Weibo,
|
Twitter/X, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu,
|
||||||
WeChat Articles, Xiaoyuzhou Podcast, LinkedIn, V2EX, Xueqiu (stocks), RSS, or any web URL.
|
Xiaoyuzhou Podcast, LinkedIn, V2EX, Xueqiu (stocks), RSS, or any web URL.
|
||||||
|
|
||||||
Also MUST USE for: web search, look up, research, find, share a URL/link, jobs/recruiting.
|
Also MUST USE for: web search, look up, research, find, share a URL/link, jobs/recruiting.
|
||||||
Routes to CLI tools: xhs-cli, twitter-cli, rdt-cli, gh, yt-dlp, curl+Jina, mcporter.
|
Routes to CLI tools: xhs-cli, twitter-cli, rdt-cli, gh, yt-dlp, curl+Jina, mcporter.
|
||||||
17 platforms, zero config for 8 channels.
|
13 platforms, zero config for 6 channels.
|
||||||
|
|
||||||
Triggers: "search twitter", "search xiaohongshu", "watch this video",
|
Triggers: "search twitter", "search xiaohongshu", "watch this video",
|
||||||
"search the web", "look this up", "research", "youtube transcript",
|
"search the web", "look this up", "research", "youtube transcript",
|
||||||
"search reddit", "read this link", "bilibili", "douyin video",
|
"search reddit", "read this link", "bilibili", "V2EX",
|
||||||
"wechat article", "wechat official account", "weibo", "V2EX",
|
|
||||||
"xiaoyuzhou", "podcast", "xueqiu", "stock quote", "雪球", "股票".
|
"xiaoyuzhou", "podcast", "xueqiu", "stock quote", "雪球", "股票".
|
||||||
metadata:
|
metadata:
|
||||||
openclaw:
|
openclaw:
|
||||||
@@ -21,7 +20,7 @@ metadata:
|
|||||||
|
|
||||||
# Agent Reach — Usage Guide
|
# Agent Reach — Usage Guide
|
||||||
|
|
||||||
Upstream tools for 17 platforms. Call them directly.
|
Upstream tools for 13 platforms. Call them directly.
|
||||||
|
|
||||||
Run `agent-reach doctor` to check which channels are available.
|
Run `agent-reach doctor` to check which channels are available.
|
||||||
|
|
||||||
@@ -109,75 +108,6 @@ mcporter call 'xiaohongshu.publish_content(title: "Title", content: "Body text",
|
|||||||
> ```
|
> ```
|
||||||
> This keeps only: title, content, author, engagement counts, image URLs, and tags.
|
> This keeps only: title, content, author, engagement counts, image URLs, and tags.
|
||||||
|
|
||||||
## Douyin (mcporter)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mcporter call 'douyin.parse_douyin_video_info(share_link: "https://v.douyin.com/xxx/")'
|
|
||||||
mcporter call 'douyin.get_douyin_download_link(share_link: "https://v.douyin.com/xxx/")'
|
|
||||||
```
|
|
||||||
|
|
||||||
> No login needed.
|
|
||||||
|
|
||||||
## WeChat Articles
|
|
||||||
|
|
||||||
**Search** (`miku_ai`):
|
|
||||||
```bash
|
|
||||||
# miku_ai is installed inside the agent-reach Python environment.
|
|
||||||
# Use the same interpreter that runs agent-reach (handles pipx / venv installs):
|
|
||||||
AGENT_REACH_PYTHON=$(python3 -c "import agent_reach, sys; print(sys.executable)" 2>/dev/null || echo python3)
|
|
||||||
$AGENT_REACH_PYTHON -c "
|
|
||||||
import asyncio
|
|
||||||
from miku_ai import get_wexin_article
|
|
||||||
async def s():
|
|
||||||
for a in await get_wexin_article('query', 5):
|
|
||||||
print(f'{a[\"title\"]} | {a[\"url\"]}')
|
|
||||||
asyncio.run(s())
|
|
||||||
"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Read** (Camoufox — bypasses WeChat anti-bot):
|
|
||||||
```bash
|
|
||||||
cd ~/.agent-reach/tools/wechat-article-for-ai && python3 main.py "https://mp.weixin.qq.com/s/ARTICLE_ID"
|
|
||||||
```
|
|
||||||
|
|
||||||
> WeChat articles cannot be read with Jina Reader or curl. Use Camoufox.
|
|
||||||
|
|
||||||
## Weibo (mcporter)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Trending topics
|
|
||||||
mcporter call 'weibo.get_trendings(limit: 20)'
|
|
||||||
|
|
||||||
# Search users
|
|
||||||
mcporter call 'weibo.search_users(keyword: "Lei Jun", limit: 10)'
|
|
||||||
|
|
||||||
# Get a user profile
|
|
||||||
mcporter call 'weibo.get_profile(uid: "1195230310")'
|
|
||||||
|
|
||||||
# Get a user's feed
|
|
||||||
mcporter call 'weibo.get_feeds(uid: "1195230310", limit: 20)'
|
|
||||||
|
|
||||||
# Get a user's hot posts
|
|
||||||
mcporter call 'weibo.get_hot_feeds(uid: "1195230310", limit: 10)'
|
|
||||||
|
|
||||||
# Search post content
|
|
||||||
mcporter call 'weibo.search_content(keyword: "artificial intelligence", limit: 20)'
|
|
||||||
|
|
||||||
# Search topics
|
|
||||||
mcporter call 'weibo.search_topics(keyword: "AI", limit: 10)'
|
|
||||||
|
|
||||||
# Get post comments
|
|
||||||
mcporter call 'weibo.get_comments(mid: "5099916367123456", limit: 50)'
|
|
||||||
|
|
||||||
# Get fans
|
|
||||||
mcporter call 'weibo.get_fans(uid: "1195230310", limit: 20)'
|
|
||||||
|
|
||||||
# Get followings
|
|
||||||
mcporter call 'weibo.get_followers(uid: "1195230310", limit: 20)'
|
|
||||||
```
|
|
||||||
|
|
||||||
> Zero config. No login needed. Uses the mobile API with auto-generated visitor cookies.
|
|
||||||
|
|
||||||
## Xiaoyuzhou Podcast (groq-whisper + ffmpeg)
|
## Xiaoyuzhou Podcast (groq-whisper + ffmpeg)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 社交媒体 & 社区
|
# 社交媒体 & 社区
|
||||||
|
|
||||||
小红书、抖音、Twitter/X、微博、B站、V2EX、Reddit。
|
小红书、Twitter/X、B站、V2EX、Reddit。
|
||||||
|
|
||||||
## 小红书 / XiaoHongShu (xhs-cli)
|
## 小红书 / XiaoHongShu (xhs-cli)
|
||||||
|
|
||||||
@@ -42,42 +42,6 @@ xhs favorites # 可能返回 API error
|
|||||||
>
|
>
|
||||||
> **POST 操作风险**: 发帖(post)、评论(comment)、点赞(like) 等写操作在 v0.6.x 可能因签名问题返回 406。如需使用,建议降级到 v0.3.5 (`pipx install xiaohongshu-cli==0.3.5`)。
|
> **POST 操作风险**: 发帖(post)、评论(comment)、点赞(like) 等写操作在 v0.6.x 可能因签名问题返回 406。如需使用,建议降级到 v0.3.5 (`pipx install xiaohongshu-cli==0.3.5`)。
|
||||||
|
|
||||||
## 抖音 / Douyin
|
|
||||||
|
|
||||||
### 安装与配置
|
|
||||||
|
|
||||||
`douyin-mcp-server` 是 **stdio 模式**的 MCP server,需先安装再注册到 mcporter:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 安装
|
|
||||||
pipx install douyin-mcp-server
|
|
||||||
|
|
||||||
# 2. 查找安装路径
|
|
||||||
pipx runpip douyin-mcp-server show -f 2>/dev/null | grep "Location" \
|
|
||||||
|| find ~/.local -name "douyin-mcp-server" 2>/dev/null | head -1
|
|
||||||
|
|
||||||
# 3. 注册到 mcporter(使用 stdio 模式,将路径替换为上一步的输出)
|
|
||||||
mcporter config add douyin --command "/path/to/douyin-mcp-server" --scope home
|
|
||||||
```
|
|
||||||
|
|
||||||
> **注意**:`agent-reach install --channels douyin` 暂不支持抖音渠道(抖音在"可选渠道待解锁"列表)。
|
|
||||||
> HTTP 模式(`mcporter config add douyin http://localhost:18070/mcp`)**无法正常工作**,请使用上方 stdio 方式。
|
|
||||||
|
|
||||||
### 用法
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 解析视频信息
|
|
||||||
mcporter call 'douyin.parse_douyin_video_info(share_link: "https://v.douyin.com/xxx/")'
|
|
||||||
|
|
||||||
# 获取无水印下载链接
|
|
||||||
mcporter call 'douyin.get_douyin_download_link(share_link: "https://v.douyin.com/xxx/")'
|
|
||||||
|
|
||||||
# 提取视频文案
|
|
||||||
mcporter call 'douyin.extract_douyin_text(share_link: "https://v.douyin.com/xxx/")'
|
|
||||||
```
|
|
||||||
|
|
||||||
> **需要登录**(`rdt login`,自动从浏览器提取 Cookie)。Reddit 自 2024 年起要求认证,未登录时所有请求返回 403。
|
|
||||||
|
|
||||||
## Twitter/X (twitter-cli)
|
## Twitter/X (twitter-cli)
|
||||||
|
|
||||||
### 稳定命令
|
### 稳定命令
|
||||||
@@ -122,15 +86,6 @@ twitter likes
|
|||||||
>
|
>
|
||||||
> **输出格式**: 建议用 `--yaml` 或 `--json` 获得结构化输出,对 AI agent 更友好。
|
> **输出格式**: 建议用 `--yaml` 或 `--json` 获得结构化输出,对 AI agent 更友好。
|
||||||
|
|
||||||
## 微博 / Weibo
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 使用 Jina Reader 读取
|
|
||||||
curl -s "https://r.jina.ai/https://weibo.com/USER_ID/POST_ID"
|
|
||||||
```
|
|
||||||
|
|
||||||
> 微博主要通过网页抓取,推荐使用通用网页读取方式。
|
|
||||||
|
|
||||||
## B站 / Bilibili
|
## B站 / Bilibili
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -106,18 +106,6 @@ agent-reach doctor
|
|||||||
|
|
||||||
> 输出 Markdown 文件默认保存到 `/tmp/`。
|
> 输出 Markdown 文件默认保存到 `/tmp/`。
|
||||||
|
|
||||||
## 抖音视频解析
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 解析视频信息
|
|
||||||
mcporter call 'douyin.parse_douyin_video_info(share_link: "https://v.douyin.com/xxx/")'
|
|
||||||
|
|
||||||
# 获取无水印下载链接
|
|
||||||
mcporter call 'douyin.get_douyin_download_link(share_link: "https://v.douyin.com/xxx/")'
|
|
||||||
```
|
|
||||||
|
|
||||||
> 详见 [social.md](social.md#抖音--douyin)
|
|
||||||
|
|
||||||
## 选择指南
|
## 选择指南
|
||||||
|
|
||||||
| 场景 | 推荐工具 |
|
| 场景 | 推荐工具 |
|
||||||
@@ -125,4 +113,4 @@ mcporter call 'douyin.get_douyin_download_link(share_link: "https://v.douyin.com
|
|||||||
| YouTube 字幕 | yt-dlp |
|
| YouTube 字幕 | yt-dlp |
|
||||||
| B站字幕 | yt-dlp |
|
| B站字幕 | yt-dlp |
|
||||||
| 播客转录 | 小宇宙 transcribe.sh |
|
| 播客转录 | 小宇宙 transcribe.sh |
|
||||||
| 抖音视频解析 | douyin MCP |
|
| 无字幕音视频 | agent-reach transcribe |
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 网页阅读
|
# 网页阅读
|
||||||
|
|
||||||
通用网页、微信公众号、RSS。
|
通用网页、RSS。
|
||||||
|
|
||||||
## 通用网页 (Jina Reader)
|
## 通用网页 (Jina Reader)
|
||||||
|
|
||||||
@@ -29,30 +29,6 @@ mcporter call 'web-reader.webReader(url: "https://example.com", return_format: "
|
|||||||
|
|
||||||
**适用场景**: 需要更精确控制输出格式时使用。
|
**适用场景**: 需要更精确控制输出格式时使用。
|
||||||
|
|
||||||
## 微信公众号 / WeChat Articles
|
|
||||||
|
|
||||||
### 搜索公众号文章(通过 Exa)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 搜索微信公众号文章
|
|
||||||
mcporter call 'exa.web_search_exa(query: "搜索关键词", numResults: 5, includeDomains: ["mp.weixin.qq.com"])'
|
|
||||||
```
|
|
||||||
|
|
||||||
### 阅读公众号文章全文(通过 Exa)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 抓取文章全文
|
|
||||||
mcporter call 'exa.crawling_exa(urls: ["https://mp.weixin.qq.com/s/ARTICLE_ID"], maxCharacters: 10000)'
|
|
||||||
```
|
|
||||||
|
|
||||||
### 可选:Camoufox 阅读(反爬更强)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ~/.agent-reach/tools/wechat-article-for-ai && python3 main.py "https://mp.weixin.qq.com/s/ARTICLE_ID"
|
|
||||||
```
|
|
||||||
|
|
||||||
> **注意**: Jina Reader 无法读取微信文章(被 CAPTCHA 拦截),推荐用 Exa。
|
|
||||||
|
|
||||||
## RSS (feedparser)
|
## RSS (feedparser)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@@ -71,6 +47,4 @@ for e in feedparser.parse('FEED_URL').entries[:5]:
|
|||||||
|-----|---------|
|
|-----|---------|
|
||||||
| 通用网页 | Jina Reader (`curl r.jina.ai`) |
|
| 通用网页 | Jina Reader (`curl r.jina.ai`) |
|
||||||
| 需要图片/格式控制 | web-reader MCP |
|
| 需要图片/格式控制 | web-reader MCP |
|
||||||
| 微信公众号 | Exa (搜索+阅读) / Camoufox (可选阅读) |
|
|
||||||
| RSS 订阅 | feedparser |
|
| RSS 订阅 | feedparser |
|
||||||
| 微博/知乎等 | Jina Reader |
|
|
||||||
|
|||||||
+1
-41
@@ -64,10 +64,7 @@ Update Agent Reach: https://raw.githubusercontent.com/Panniantong/agent-reach/ma
|
|||||||
| 🌐 **Web** | Read | Zero config | Any URL → clean Markdown ([Jina Reader](https://github.com/jina-ai/reader) ⭐9.8K) |
|
| 🌐 **Web** | Read | Zero config | Any URL → clean Markdown ([Jina Reader](https://github.com/jina-ai/reader) ⭐9.8K) |
|
||||||
| 🐦 **Twitter/X** | Read · Search | Cookie | Cookie unlocks search, timeline, tweet reading, articles ([twitter-cli](https://github.com/public-clis/twitter-cli)) |
|
| 🐦 **Twitter/X** | Read · Search | Cookie | Cookie unlocks search, timeline, tweet reading, articles ([twitter-cli](https://github.com/public-clis/twitter-cli)) |
|
||||||
| 📕 **XiaoHongShu** | Read · Search · **Post · Comment · Like** | Cookie | `pipx install xiaohongshu-cli` + `xhs login` ([xhs-cli](https://github.com/jackwener/xiaohongshu-cli)) |
|
| 📕 **XiaoHongShu** | Read · Search · **Post · Comment · Like** | Cookie | `pipx install xiaohongshu-cli` + `xhs login` ([xhs-cli](https://github.com/jackwener/xiaohongshu-cli)) |
|
||||||
| 🎵 **Douyin** | Video parsing · Watermark-free download | mcporter | Via [douyin-mcp-server](https://github.com/yzfly/douyin-mcp-server), no login needed |
|
|
||||||
| 💼 **LinkedIn** | Jina Reader (public pages) | Full profiles, companies, job search | Tell your Agent "help me set up LinkedIn" |
|
| 💼 **LinkedIn** | Jina Reader (public pages) | Full profiles, companies, job search | Tell your Agent "help me set up LinkedIn" |
|
||||||
| 💬 **WeChat Articles** | Search + Read | Zero config | Search + read WeChat Official Account articles via Exa (zero config) + optional [Camoufox](https://github.com/daijro/camoufox) |
|
|
||||||
| 📰 **Weibo** | Trending · Search · Feeds · Comments | Zero config | Hot search, content/user/topic search, feeds, comments ([mcp-server-weibo](https://github.com/Panniantong/mcp-server-weibo)) |
|
|
||||||
| 💻 **V2EX** | Hot topics · Node topics · Topic detail + replies · User profile | Zero config | Public JSON API, no auth required. Great for tech community content |
|
| 💻 **V2EX** | Hot topics · Node topics · Topic detail + replies · User profile | Zero config | Public JSON API, no auth required. Great for tech community content |
|
||||||
| 📈 **Xueqiu (雪球)** | Stock quotes · Search · Hot posts · Hot stocks | Browser cookie | Tell your Agent "help me set up Xueqiu" |
|
| 📈 **Xueqiu (雪球)** | Stock quotes · Search · Hot posts · Hot stocks | Browser cookie | Tell your Agent "help me set up Xueqiu" |
|
||||||
| 🎙️ **Xiaoyuzhou Podcast** | Transcription | Free API key | Podcast audio → full text transcript via Groq Whisper (free) |
|
| 🎙️ **Xiaoyuzhou Podcast** | Transcription | Free API key | Podcast audio → full text transcript via Groq Whisper (free) |
|
||||||
@@ -222,7 +219,6 @@ channels/
|
|||||||
├── bilibili.py → yt-dlp ← swap to bilibili-api…
|
├── bilibili.py → yt-dlp ← swap to bilibili-api…
|
||||||
├── reddit.py → rdt-cli ← search + read, cookie auth required
|
├── reddit.py → rdt-cli ← search + read, cookie auth required
|
||||||
├── xiaohongshu.py → mcporter MCP ← swap to other XHS tools…
|
├── xiaohongshu.py → mcporter MCP ← swap to other XHS tools…
|
||||||
├── douyin.py → mcporter MCP ← swap to other Douyin tools…
|
|
||||||
├── linkedin.py → linkedin-mcp ← swap to LinkedIn API…
|
├── linkedin.py → linkedin-mcp ← swap to LinkedIn API…
|
||||||
├── rss.py → feedparser ← swap to atoma…
|
├── rss.py → feedparser ← swap to atoma…
|
||||||
├── exa_search.py → mcporter MCP ← swap to Tavily, SerpAPI…
|
├── exa_search.py → mcporter MCP ← swap to Tavily, SerpAPI…
|
||||||
@@ -244,10 +240,7 @@ Each channel file only checks whether its upstream tool is installed and working
|
|||||||
| GitHub | [gh CLI](https://cli.github.com) | Official tool, full API after auth |
|
| GitHub | [gh CLI](https://cli.github.com) | Official tool, full API after auth |
|
||||||
| Read RSS | [feedparser](https://github.com/kurtmckee/feedparser) | Python ecosystem standard, 2.3K stars |
|
| Read RSS | [feedparser](https://github.com/kurtmckee/feedparser) | Python ecosystem standard, 2.3K stars |
|
||||||
| XiaoHongShu | [xhs-cli](https://github.com/jackwener/xiaohongshu-cli) | 1.5K stars, pipx install, search/read/comment/post |
|
| XiaoHongShu | [xhs-cli](https://github.com/jackwener/xiaohongshu-cli) | 1.5K stars, pipx install, search/read/comment/post |
|
||||||
| Douyin | [douyin-mcp-server](https://github.com/yzfly/douyin-mcp-server) | MCP server, no login needed, video parsing + watermark-free download |
|
|
||||||
| LinkedIn | [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server) | 1.2K stars, MCP server, browser automation |
|
| LinkedIn | [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server) | 1.2K stars, MCP server, browser automation |
|
||||||
| WeChat Articles | [Exa](https://exa.ai) (search + read) + [Camoufox](https://github.com/daijro/camoufox) (optional) | Zero-config search + full article reading |
|
|
||||||
| Weibo | `mcporter` | `mcporter call 'weibo.get_trendings(limit: 10)'` |
|
|
||||||
| Xiaoyuzhou Podcast | `transcribe.sh` | `bash ~/.agent-reach/tools/xiaoyuzhou/transcribe.sh <URL>` |
|
| Xiaoyuzhou Podcast | `transcribe.sh` | `bash ~/.agent-reach/tools/xiaoyuzhou/transcribe.sh <URL>` |
|
||||||
|
|
||||||
> 📌 These are the *current* choices. Don't like one? Swap out the file. That's the whole point of scaffolding.
|
> 📌 These are the *current* choices. Don't like one? Swap out the file. That's the whole point of scaffolding.
|
||||||
@@ -310,44 +303,11 @@ Agent Reach uses twitter-cli which accesses Twitter via cookie auth — same as
|
|||||||
Install `pipx install xiaohongshu-cli`, then `xhs login` (auto-extracts cookies from browser). Your agent can then use `xhs search "query"` to search notes, `xhs read NOTE_ID` to read details, `xhs comments NOTE_ID` to view comments. No Docker needed.
|
Install `pipx install xiaohongshu-cli`, then `xhs login` (auto-extracts cookies from browser). Your agent can then use `xhs search "query"` to search notes, `xhs read NOTE_ID` to read details, `xhs comments NOTE_ID` to view comments. No Docker needed.
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><strong>How to parse Douyin / 抖音 videos with AI agent?</strong></summary>
|
|
||||||
|
|
||||||
Install douyin-mcp-server, then your agent can use `mcporter call 'douyin.parse_douyin_video_info(share_link: "share_url")'` to parse video info and get watermark-free download links. No login required — just share the Douyin link. See https://github.com/yzfly/douyin-mcp-server
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><strong>How to extract scripts from both Douyin and XiaoHongShu with one MCP?</strong></summary>
|
|
||||||
|
|
||||||
If you want one MCP server that can handle:
|
|
||||||
|
|
||||||
- Douyin videos
|
|
||||||
- XiaoHongShu video notes
|
|
||||||
- XiaoHongShu image notes
|
|
||||||
|
|
||||||
and directly write `script.md` + `info.json`, you can point the existing `douyin` mcporter alias at:
|
|
||||||
|
|
||||||
- https://github.com/JNHFlow21/social-post-extractor-mcp
|
|
||||||
|
|
||||||
It keeps backward compatibility with:
|
|
||||||
|
|
||||||
- `parse_douyin_video_info`
|
|
||||||
- `get_douyin_download_link`
|
|
||||||
- `extract_douyin_text`
|
|
||||||
|
|
||||||
and adds unified tools:
|
|
||||||
|
|
||||||
- `parse_social_post_info`
|
|
||||||
- `extract_social_post_script`
|
|
||||||
|
|
||||||
This is useful when your agent workflow is “paste a link, get a script file”.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
[twitter-cli](https://github.com/public-clis/twitter-cli) · [rdt-cli](https://github.com/public-clis/rdt-cli) · [xhs-cli](https://github.com/jackwener/xiaohongshu-cli) · [bili-cli](https://github.com/public-clis/bilibili-cli) · [yt-dlp](https://github.com/yt-dlp/yt-dlp) · [Jina Reader](https://github.com/jina-ai/reader) · [Exa](https://exa.ai) · [mcporter](https://github.com/nicobailon/mcporter) · [feedparser](https://github.com/kurtmckee/feedparser) · [douyin-mcp-server](https://github.com/yzfly/douyin-mcp-server) · [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server)
|
[twitter-cli](https://github.com/public-clis/twitter-cli) · [rdt-cli](https://github.com/public-clis/rdt-cli) · [xhs-cli](https://github.com/jackwener/xiaohongshu-cli) · [bili-cli](https://github.com/public-clis/bilibili-cli) · [yt-dlp](https://github.com/yt-dlp/yt-dlp) · [Jina Reader](https://github.com/jina-ai/reader) · [Exa](https://exa.ai) · [mcporter](https://github.com/nicobailon/mcporter) · [feedparser](https://github.com/kurtmckee/feedparser) · [linkedin-scraper-mcp](https://github.com/stickerdaniel/linkedin-mcp-server)
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
|
|||||||
+5
-91
@@ -40,7 +40,7 @@ All Agent Reach files go in dedicated directories — **never in the agent works
|
|||||||
| Purpose | Directory | Example |
|
| Purpose | Directory | Example |
|
||||||
|---------|-----------|---------|
|
|---------|-----------|---------|
|
||||||
| Config & tokens | `~/.agent-reach/` | `~/.agent-reach/config.json` |
|
| Config & tokens | `~/.agent-reach/` | `~/.agent-reach/config.json` |
|
||||||
| Upstream tool repos | `~/.agent-reach/tools/` | `~/.agent-reach/tools/douyin-mcp-server/` |
|
| Upstream tool repos | `~/.agent-reach/tools/` | `~/.agent-reach/tools/xiaoyuzhou/` |
|
||||||
| Temporary files | `/tmp/` | `/tmp/yt-dlp-output/` |
|
| Temporary files | `/tmp/` | `/tmp/yt-dlp-output/` |
|
||||||
| Skills | `~/.openclaw/skills/agent-reach/` | SKILL.md |
|
| Skills | `~/.openclaw/skills/agent-reach/` | SKILL.md |
|
||||||
|
|
||||||
@@ -97,26 +97,23 @@ After installing the basics, **ask the user** which additional channels they nee
|
|||||||
> 还有这些可选渠道,你需要哪些?
|
> 还有这些可选渠道,你需要哪些?
|
||||||
>
|
>
|
||||||
> - 🐦 **Twitter/X** — 搜推文、看时间线(需要登录 Cookie)
|
> - 🐦 **Twitter/X** — 搜推文、看时间线(需要登录 Cookie)
|
||||||
> - 📰 **微博** — 热搜、搜索、用户动态
|
|
||||||
> - 💬 **微信公众号** — 搜索和阅读公众号文章
|
|
||||||
> - 📈 **雪球** — 股票行情、热门帖子(需要登录 Cookie)
|
> - 📈 **雪球** — 股票行情、热门帖子(需要登录 Cookie)
|
||||||
> - 🎙️ **小宇宙播客** — 音频转文字(需要免费 Groq Key)
|
> - 🎙️ **小宇宙播客** — 音频转文字(需要免费 Groq Key)
|
||||||
> - 📕 **小红书** — 阅读、搜索、发帖(需要登录)
|
> - 📕 **小红书** — 阅读、搜索、发帖(需要登录)
|
||||||
> - 📖 **Reddit** — 搜索和阅读帖子
|
> - 📖 **Reddit** — 搜索和阅读帖子
|
||||||
> - 📺 **B站完整版** — 热门、排行、搜索
|
> - 📺 **B站完整版** — 热门、排行、搜索
|
||||||
> - 🎵 **抖音** — 视频解析
|
|
||||||
> - 💼 **LinkedIn** — Profile、职位搜索
|
> - 💼 **LinkedIn** — Profile、职位搜索
|
||||||
>
|
>
|
||||||
> 告诉我你要哪些,比如"帮我装微博和 Twitter"。或者说"全部装"。
|
> 告诉我你要哪些,比如"帮我装小红书和 Twitter"。或者说"全部装"。
|
||||||
|
|
||||||
Based on the user's choice, run:
|
Based on the user's choice, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
agent-reach install --env=auto --channels=twitter,weibo # Example: user chose Twitter + Weibo
|
agent-reach install --env=auto --channels=twitter,xiaohongshu # Example: user chose Twitter + XHS
|
||||||
agent-reach install --env=auto --channels=all # User wants everything
|
agent-reach install --env=auto --channels=all # User wants everything
|
||||||
```
|
```
|
||||||
|
|
||||||
Supported channel names: `twitter`, `weibo`, `wechat`, `xiaoyuzhou`, `xueqiu`, `xiaohongshu`, `reddit`, `bilibili`, `douyin`, `linkedin`, `all`
|
Supported channel names: `twitter`, `xiaoyuzhou`, `xueqiu`, `xiaohongshu`, `reddit`, `bilibili`, `linkedin`, `all`
|
||||||
|
|
||||||
### Step 3: Fix what's broken
|
### Step 3: Fix what's broken
|
||||||
|
|
||||||
@@ -202,18 +199,6 @@ xhs login
|
|||||||
> mcporter config add xiaohongshu http://localhost:18060/mcp
|
> mcporter config add xiaohongshu http://localhost:18060/mcp
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
**微博 / Weibo (mcp-server-weibo):**
|
|
||||||
> "微博已默认安装,装好即用。可搜索微博内容、查看热搜、获取用户动态和评论。"
|
|
||||||
|
|
||||||
如果自动安装失败,手动安装:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install git+https://github.com/Panniantong/mcp-server-weibo.git
|
|
||||||
mcporter config add weibo --command 'mcp-server-weibo'
|
|
||||||
```
|
|
||||||
|
|
||||||
> 无需登录、无需 Cookie、无需代理。海外服务器也可以直接访问。
|
|
||||||
|
|
||||||
**雪球 / Xueqiu (股票行情 + 热门帖子):**
|
**雪球 / Xueqiu (股票行情 + 热门帖子):**
|
||||||
> "雪球需要登录后的 Cookie。请先在 Chrome 里登录 xueqiu.com,然后运行:"
|
> "雪球需要登录后的 Cookie。请先在 Chrome 里登录 xueqiu.com,然后运行:"
|
||||||
|
|
||||||
@@ -252,75 +237,6 @@ agent-reach configure groq-key gsk_xxxxx
|
|||||||
> - 转录质量高(Whisper large-v3),但不区分说话人
|
> - 转录质量高(Whisper large-v3),但不区分说话人
|
||||||
> - 2 小时以上的播客建议分批处理
|
> - 2 小时以上的播客建议分批处理
|
||||||
|
|
||||||
**抖音 / Douyin (douyin-mcp-server):**
|
|
||||||
> "抖音视频解析需要一个 MCP 服务。安装 douyin-mcp-server 后即可解析视频、获取无水印下载链接。"
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 安装
|
|
||||||
pip install douyin-mcp-server
|
|
||||||
|
|
||||||
# 2. 启动 HTTP 服务(端口 18070)
|
|
||||||
# 方式一:用 uv(推荐)
|
|
||||||
mkdir -p ~/.agent-reach/tools && cd ~/.agent-reach/tools
|
|
||||||
git clone https://github.com/yzfly/douyin-mcp-server.git && cd douyin-mcp-server
|
|
||||||
uv sync && uv run python run_http.py
|
|
||||||
|
|
||||||
# 方式二:直接用 Python 启动
|
|
||||||
python -c "
|
|
||||||
from douyin_mcp_server.server import mcp
|
|
||||||
mcp.settings.host = '127.0.0.1'
|
|
||||||
mcp.settings.port = 18070
|
|
||||||
mcp.run(transport='streamable-http')
|
|
||||||
"
|
|
||||||
|
|
||||||
# 3. 注册到 mcporter
|
|
||||||
mcporter config add douyin http://localhost:18070/mcp
|
|
||||||
```
|
|
||||||
|
|
||||||
> 无需认证即可解析视频信息和获取下载链接。
|
|
||||||
> 如需 AI 语音识别提取文案功能,需要配置硅基流动 API Key(`export API_KEY="sk-xxx"`)。
|
|
||||||
>
|
|
||||||
> 详见 https://github.com/yzfly/douyin-mcp-server
|
|
||||||
|
|
||||||
**可选实现:Douyin + XiaoHongShu unified extractor**
|
|
||||||
> "如果你想把抖音和小红书统一成一个 MCP,并直接输出 `script.md` 和 `info.json`,可以改用 social-post-extractor-mcp。"
|
|
||||||
|
|
||||||
适用场景:
|
|
||||||
|
|
||||||
- 抖音视频转文字稿
|
|
||||||
- 小红书视频笔记转文字稿
|
|
||||||
- 小红书图文笔记正文 + 图片文字提取
|
|
||||||
|
|
||||||
兼容性:
|
|
||||||
|
|
||||||
- 仍然可以注册成 `douyin` 这个 mcporter server 名称
|
|
||||||
- 兼容旧工具名 `parse_douyin_video_info` / `get_douyin_download_link` / `extract_douyin_text`
|
|
||||||
- 同时新增 `parse_social_post_info` / `extract_social_post_script`
|
|
||||||
|
|
||||||
示例配置:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/JNHFlow21/social-post-extractor-mcp.git
|
|
||||||
cd social-post-extractor-mcp
|
|
||||||
uv sync
|
|
||||||
|
|
||||||
mcporter config add douyin \
|
|
||||||
--command /bin/zsh \
|
|
||||||
--arg -lc \
|
|
||||||
--arg "cd '$PWD' && exec '.venv/bin/python' -m social_post_extractor_mcp" \
|
|
||||||
--env ASR_PROVIDER=bailian \
|
|
||||||
--env ASR_MODEL=paraformer-v2 \
|
|
||||||
--env VISION_PROVIDER=bailian \
|
|
||||||
--env VISION_MODEL=qwen3-vl-flash \
|
|
||||||
--env CLEAN_PROVIDER=bailian \
|
|
||||||
--env CLEAN_MODEL=qwen-flash \
|
|
||||||
--env BAILIAN_API_KEY=YOUR_BAILIAN_API_KEY
|
|
||||||
```
|
|
||||||
|
|
||||||
> 这个实现更适合“把链接直接交给 Agent,然后拿到脚本文件”的工作流。
|
|
||||||
>
|
|
||||||
> 详见 https://github.com/JNHFlow21/social-post-extractor-mcp
|
|
||||||
|
|
||||||
**LinkedIn (可选 — linkedin-scraper-mcp):**
|
**LinkedIn (可选 — linkedin-scraper-mcp):**
|
||||||
> "LinkedIn 基本内容可通过 Jina Reader 读取。完整功能(Profile 详情、职位搜索)需要 linkedin-scraper-mcp。"
|
> "LinkedIn 基本内容可通过 Jina Reader 读取。完整功能(Profile 详情、职位搜索)需要 linkedin-scraper-mcp。"
|
||||||
|
|
||||||
@@ -388,7 +304,7 @@ If the user wants a different agent to handle it, let them choose.
|
|||||||
| Command | What it does |
|
| Command | What it does |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| `agent-reach install --env=auto` | Install core channels (lightweight, zero-config) |
|
| `agent-reach install --env=auto` | Install core channels (lightweight, zero-config) |
|
||||||
| `agent-reach install --env=auto --channels=twitter,weibo` | Install core + optional channels |
|
| `agent-reach install --env=auto --channels=twitter,xiaohongshu` | Install core + optional channels |
|
||||||
| `agent-reach install --env=auto --channels=all` | Install everything |
|
| `agent-reach install --env=auto --channels=all` | Install everything |
|
||||||
| `agent-reach install --env=auto --safe` | Safe setup (no auto system changes) |
|
| `agent-reach install --env=auto --safe` | Safe setup (no auto system changes) |
|
||||||
| `agent-reach install --env=auto --dry-run` | Preview what would be done |
|
| `agent-reach install --env=auto --dry-run` | Preview what would be done |
|
||||||
@@ -411,8 +327,6 @@ After installation, use upstream tools directly. See SKILL.md for the full comma
|
|||||||
| Web | `curl` + Jina | `curl -s "https://r.jina.ai/URL"` |
|
| Web | `curl` + Jina | `curl -s "https://r.jina.ai/URL"` |
|
||||||
| Exa Search | `mcporter` | `mcporter call 'exa.web_search_exa(...)'` |
|
| Exa Search | `mcporter` | `mcporter call 'exa.web_search_exa(...)'` |
|
||||||
| 小红书 | `mcporter` | `mcporter call 'xiaohongshu.search_feeds(...)'` |
|
| 小红书 | `mcporter` | `mcporter call 'xiaohongshu.search_feeds(...)'` |
|
||||||
| 微博 | `mcporter` | `mcporter call 'weibo.get_trendings(limit: 10)'` |
|
|
||||||
| 小宇宙播客 | `transcribe.sh` | `bash ~/.agent-reach/tools/xiaoyuzhou/transcribe.sh <URL>` |
|
| 小宇宙播客 | `transcribe.sh` | `bash ~/.agent-reach/tools/xiaoyuzhou/transcribe.sh <URL>` |
|
||||||
| 抖音 | `mcporter` | `mcporter call 'douyin.parse_douyin_video_info(...)'` |
|
|
||||||
| LinkedIn | `mcporter` | `mcporter call 'linkedin.get_person_profile(...)'` |
|
| LinkedIn | `mcporter` | `mcporter call 'linkedin.get_person_profile(...)'` |
|
||||||
| RSS | `feedparser` | `python3 -c "import feedparser; ..."` |
|
| RSS | `feedparser` | `python3 -c "import feedparser; ..."` |
|
||||||
|
|||||||
@@ -90,49 +90,6 @@ def test_youtube_ok_when_deno_installed(monkeypatch):
|
|||||||
assert status == "ok"
|
assert status == "ok"
|
||||||
|
|
||||||
|
|
||||||
def test_douyin_check_does_not_call_with_invalid_url(monkeypatch, tmp_path):
|
|
||||||
"""Douyin check should use 'mcporter list' instead of calling with a hardcoded URL."""
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from agent_reach.channels.douyin import DouyinChannel
|
|
||||||
|
|
||||||
calls = []
|
|
||||||
original_run = subprocess.run
|
|
||||||
|
|
||||||
def tracking_run(cmd, **kwargs):
|
|
||||||
calls.append(cmd)
|
|
||||||
# Simulate mcporter config list returning douyin
|
|
||||||
if "config" in cmd and "list" in cmd:
|
|
||||||
|
|
||||||
class R:
|
|
||||||
stdout = "douyin http://localhost:18070/mcp"
|
|
||||||
returncode = 0
|
|
||||||
|
|
||||||
return R()
|
|
||||||
# Simulate mcporter list douyin returning tools
|
|
||||||
if "list" in cmd and "douyin" in cmd:
|
|
||||||
|
|
||||||
class R:
|
|
||||||
stdout = "parse_douyin_video_info"
|
|
||||||
returncode = 0
|
|
||||||
|
|
||||||
return R()
|
|
||||||
return original_run(cmd, **kwargs)
|
|
||||||
|
|
||||||
monkeypatch.setattr(
|
|
||||||
"shutil.which", lambda cmd: "/usr/bin/mcporter" if cmd == "mcporter" else None
|
|
||||||
)
|
|
||||||
monkeypatch.setattr("subprocess.run", tracking_run)
|
|
||||||
|
|
||||||
ch = DouyinChannel()
|
|
||||||
status, _msg = ch.check()
|
|
||||||
|
|
||||||
# Should NOT contain any hardcoded douyin.com URL in subprocess calls
|
|
||||||
for call in calls:
|
|
||||||
call_str = " ".join(call) if isinstance(call, list) else str(call)
|
|
||||||
assert "https://www.douyin.com" not in call_str
|
|
||||||
|
|
||||||
|
|
||||||
def test_channel_can_handle_contract():
|
def test_channel_can_handle_contract():
|
||||||
url_samples = {
|
url_samples = {
|
||||||
"github": "https://github.com/panniantong/agent-reach",
|
"github": "https://github.com/panniantong/agent-reach",
|
||||||
@@ -141,9 +98,7 @@ def test_channel_can_handle_contract():
|
|||||||
"reddit": "https://reddit.com/r/python",
|
"reddit": "https://reddit.com/r/python",
|
||||||
"bilibili": "https://www.bilibili.com/video/BV1xx411",
|
"bilibili": "https://www.bilibili.com/video/BV1xx411",
|
||||||
"xiaohongshu": "https://www.xiaohongshu.com/explore/123",
|
"xiaohongshu": "https://www.xiaohongshu.com/explore/123",
|
||||||
"douyin": "https://www.douyin.com/video/123",
|
|
||||||
"linkedin": "https://www.linkedin.com/in/test",
|
"linkedin": "https://www.linkedin.com/in/test",
|
||||||
"weibo": "https://weibo.com/u/1749127163",
|
|
||||||
"rss": "https://example.com/feed.xml",
|
"rss": "https://example.com/feed.xml",
|
||||||
"xueqiu": "https://xueqiu.com/S/SH600519",
|
"xueqiu": "https://xueqiu.com/S/SH600519",
|
||||||
"exa_search": "https://example.com",
|
"exa_search": "https://example.com",
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class TestSkillCommand(unittest.TestCase):
|
|||||||
with open(target, encoding="utf-8") as f:
|
with open(target, encoding="utf-8") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
self.assertTrue(content.strip())
|
self.assertTrue(content.strip())
|
||||||
self.assertIn("WeChat Articles, Xiaoyuzhou Podcast", content)
|
self.assertIn("Xiaoyuzhou Podcast, LinkedIn", content)
|
||||||
self.assertNotIn("搜推特", content)
|
self.assertNotIn("搜推特", content)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
os.path.exists(os.path.join(skill_parent, "agent-reach", "references"))
|
os.path.exists(os.path.join(skill_parent, "agent-reach", "references"))
|
||||||
|
|||||||
Reference in New Issue
Block a user