wechatmp-mcp 0.0.1__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.
@@ -0,0 +1,148 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ share/python-wheels/
20
+ *.egg-info/
21
+ .installed.cfg
22
+ *.egg
23
+ MANIFEST
24
+
25
+ # PyInstaller
26
+ *.manifest
27
+ *.spec
28
+
29
+ # Installer logs
30
+ pip-log.txt
31
+ pip-delete-this-directory.txt
32
+
33
+ # Unit test / coverage reports
34
+ htmlcov/
35
+ .tox/
36
+ .nox/
37
+ .coverage
38
+ .coverage.*
39
+ .cache
40
+ nosetests.xml
41
+ coverage.xml
42
+ *.cover
43
+ *.py.cover
44
+ .hypothesis/
45
+ .pytest_cache/
46
+ cover/
47
+
48
+ # Translations
49
+ *.mo
50
+ *.pot
51
+
52
+ # Django
53
+ *.log
54
+ local_settings.py
55
+ db.sqlite3
56
+ db.sqlite3-journal
57
+
58
+ # Flask
59
+ instance/
60
+ .webassets-cache
61
+
62
+ # Scrapy
63
+ .scrapy
64
+
65
+ # Sphinx
66
+ docs/_build/
67
+
68
+ # PyBuilder
69
+ .pybuilder/
70
+ target/
71
+
72
+ # Jupyter Notebook
73
+ .ipynb_checkpoints
74
+
75
+ # IPython
76
+ profile_default/
77
+ ipython_config.py
78
+
79
+ # Virtual environments
80
+ .env
81
+ .envrc
82
+ .venv
83
+ env/
84
+ venv/
85
+ ENV/
86
+ env.bak/
87
+ venv.bak/
88
+
89
+ # Package managers
90
+ .pdm-python
91
+ .pdm-build/
92
+ .pixi
93
+ __pypackages__/
94
+
95
+ # Celery
96
+ celerybeat-schedule
97
+ celerybeat.pid
98
+
99
+ # SageMath
100
+ *.sage.py
101
+
102
+ # Type checkers
103
+ .mypy_cache/
104
+ .dmypy.json
105
+ dmypy.json
106
+ .pyre/
107
+ .pytype/
108
+ cython_debug/
109
+ .ruff_cache/
110
+
111
+ # Spyder / Rope
112
+ .spyderproject
113
+ .spyproject
114
+ .ropeproject
115
+
116
+ # mkdocs
117
+ /site
118
+
119
+ # Abstra
120
+ .abstra/
121
+
122
+ # Marimo
123
+ marimo/_static/
124
+ marimo/_lsp/
125
+ __marimo__/
126
+
127
+ # PyPI
128
+ .pypirc
129
+
130
+ # IDE
131
+ .idea/
132
+ .vscode/
133
+ *.swp
134
+ *.swo
135
+ *~
136
+
137
+ # Cursor
138
+ .cursorignore
139
+ .cursorindexingignore
140
+
141
+ # Project-specific
142
+ browser_data/
143
+ screenshots/
144
+ logs/
145
+
146
+ # OS
147
+ .DS_Store
148
+ Thumbs.db
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: wechatmp-mcp
3
+ Version: 0.0.1
4
+ Summary: MCP service for WeChat Official Account (微信公众号) content retrieval
5
+ Author: wechatmp-mcp
6
+ License-Expression: MIT
7
+ Keywords: mcp,playwright,wechat,weixin,公众号,微信
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: beautifulsoup4>=4.12.0
17
+ Requires-Dist: html2text>=2020.1.16
18
+ Requires-Dist: httpx>=0.25.0
19
+ Requires-Dist: mcp>=1.0.0
20
+ Requires-Dist: playwright>=1.40.0
21
+ Requires-Dist: pydantic-settings>=2.0.0
22
+ Requires-Dist: pydantic>=2.0.0
23
+ Requires-Dist: python-dotenv>=1.0.0
24
+ Requires-Dist: starlette>=0.37.0
25
+ Requires-Dist: uvicorn>=0.24.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
28
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # wechatmp-mcp
32
+
33
+ `wechatmp-mcp` 是一个面向 MCP 客户端使用者的微信公众号 MCP Server。它通过微信公众号后台接口,提供扫码登录、搜索公众号、获取文章列表、读取文章正文、批量抓取多账号近期文章等能力。
34
+
35
+ 你可以把它接入支持 MCP 的客户端,例如 Claude Code、Cline、MCP Inspector,或任何兼容 `stdio` 的 MCP 工具。
36
+
37
+ ## 它能做什么
38
+
39
+ - 获取微信公众号后台登录二维码,扫码完成登录,自动保存登录态到本地
40
+ - 登录态保存在 `~/.wechat-mcp/`,重启后无需重新登录
41
+ - 按关键词搜索公众号,获取 fakeid、昵称、简介等信息
42
+ - 获取指定公众号的文章列表(标题、链接、摘要、封面、发布时间)
43
+ - 读取指定文章 URL 的正文,以 Markdown 格式返回
44
+ - 批量获取多个公众号的近期文章摘要
45
+
46
+ 当前项目实际注册了 **7 个 MCP tools**。
47
+
48
+ ## 环境要求
49
+
50
+ - Python 3.10 或更高版本
51
+ - 能访问微信公众号网页(mp.weixin.qq.com)
52
+
53
+ ## 通过 uvx 使用(推荐)
54
+
55
+ 无需手动安装,uvx 会自动处理。
56
+
57
+ ### Claude Code 配置
58
+
59
+ ```bash
60
+ claude mcp add wechat -- uvx wechatmp-mcp
61
+ ```
62
+
63
+ ### 快速调试
64
+
65
+ ```sh
66
+ npx @modelcontextprotocol/inspector uvx wechatmp-mcp
67
+ ```
68
+
69
+ > ⚠️ **注意:** 请务必先使用 `get_login_qrcode` + `check_login_status` 完成登录后再使用其他工具!
70
+
71
+ ## MCP 客户端配置
72
+
73
+ ### Claude Code
74
+
75
+ ```bash
76
+ claude mcp add wechat -- uvx wechatmp-mcp
77
+ ```
78
+
79
+ ### Cline / JSON 配置
80
+
81
+ ```json
82
+ {
83
+ "mcpServers": {
84
+ "wechatmp-mcp": {
85
+ "command": "uvx",
86
+ "args": ["wechatmp-mcp"]
87
+ }
88
+ }
89
+ }
90
+ ```
91
+
92
+ ## Tools 一览
93
+
94
+ ### 账号登录
95
+
96
+ - `get_login_qrcode`:获取微信公众号后台登录二维码,图片保存到本地,返回文件路径
97
+ - `check_login_status`:检查登录状态;若用户已扫码则完成登录并保存 auth,否则验证已保存 auth 是否有效
98
+ - `logout`:清除本地保存的 auth(token + cookies),退出登录
99
+
100
+ ### 公众号搜索
101
+
102
+ - `search_account`:按关键词搜索公众号,返回 fakeid、nickname、alias、intro、avatar
103
+
104
+ ### 文章获取
105
+
106
+ - `get_account_articles`:获取指定公众号的文章列表(按发布时间倒序),支持按 fakeid 或公众号名称查询,支持翻页
107
+ - `get_article_content`:传入文章 URL,返回清洗后的 Markdown 正文
108
+ - `batch_get_articles`:传入公众号名称列表,批量获取近期文章摘要
109
+
110
+ ## 发布新版本到 PyPI
111
+
112
+ 修改代码后,更新 `src/wechat_mcp/__init__.py` 中的版本号,然后:
113
+
114
+ ```sh
115
+ # 安装构建工具(首次需要)
116
+ pip install hatch twine -i https://pypi.org/simple/
117
+
118
+ # 构建
119
+ hatch build
120
+
121
+ # 上传到 PyPI
122
+ # Username: __token__
123
+ # Password: 在 https://pypi.org/manage/account/ 的 API tokens 中创建
124
+ python -m twine upload dist/*
125
+
126
+ # 验证上传成功
127
+ uvx wechatmp-mcp==<新版本号> --help
128
+ ```
129
+
130
+ > 注意:上传后 PyPI 同步约需 1-2 分钟,验证前稍等片刻。
131
+
132
+ ## 使用建议
133
+
134
+ - 使用其他工具前,请先通过 `get_login_qrcode` 获取二维码并扫码,再调用 `check_login_status` 完成登录
135
+ - 登录态保存在 `~/.wechat-mcp/`,重启服务后无需重新登录
136
+ - `get_account_articles` 需要先通过 `search_account` 获取公众号的 `fakeid`
@@ -0,0 +1,106 @@
1
+ # wechatmp-mcp
2
+
3
+ `wechatmp-mcp` 是一个面向 MCP 客户端使用者的微信公众号 MCP Server。它通过微信公众号后台接口,提供扫码登录、搜索公众号、获取文章列表、读取文章正文、批量抓取多账号近期文章等能力。
4
+
5
+ 你可以把它接入支持 MCP 的客户端,例如 Claude Code、Cline、MCP Inspector,或任何兼容 `stdio` 的 MCP 工具。
6
+
7
+ ## 它能做什么
8
+
9
+ - 获取微信公众号后台登录二维码,扫码完成登录,自动保存登录态到本地
10
+ - 登录态保存在 `~/.wechat-mcp/`,重启后无需重新登录
11
+ - 按关键词搜索公众号,获取 fakeid、昵称、简介等信息
12
+ - 获取指定公众号的文章列表(标题、链接、摘要、封面、发布时间)
13
+ - 读取指定文章 URL 的正文,以 Markdown 格式返回
14
+ - 批量获取多个公众号的近期文章摘要
15
+
16
+ 当前项目实际注册了 **7 个 MCP tools**。
17
+
18
+ ## 环境要求
19
+
20
+ - Python 3.10 或更高版本
21
+ - 能访问微信公众号网页(mp.weixin.qq.com)
22
+
23
+ ## 通过 uvx 使用(推荐)
24
+
25
+ 无需手动安装,uvx 会自动处理。
26
+
27
+ ### Claude Code 配置
28
+
29
+ ```bash
30
+ claude mcp add wechat -- uvx wechatmp-mcp
31
+ ```
32
+
33
+ ### 快速调试
34
+
35
+ ```sh
36
+ npx @modelcontextprotocol/inspector uvx wechatmp-mcp
37
+ ```
38
+
39
+ > ⚠️ **注意:** 请务必先使用 `get_login_qrcode` + `check_login_status` 完成登录后再使用其他工具!
40
+
41
+ ## MCP 客户端配置
42
+
43
+ ### Claude Code
44
+
45
+ ```bash
46
+ claude mcp add wechat -- uvx wechatmp-mcp
47
+ ```
48
+
49
+ ### Cline / JSON 配置
50
+
51
+ ```json
52
+ {
53
+ "mcpServers": {
54
+ "wechatmp-mcp": {
55
+ "command": "uvx",
56
+ "args": ["wechatmp-mcp"]
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ ## Tools 一览
63
+
64
+ ### 账号登录
65
+
66
+ - `get_login_qrcode`:获取微信公众号后台登录二维码,图片保存到本地,返回文件路径
67
+ - `check_login_status`:检查登录状态;若用户已扫码则完成登录并保存 auth,否则验证已保存 auth 是否有效
68
+ - `logout`:清除本地保存的 auth(token + cookies),退出登录
69
+
70
+ ### 公众号搜索
71
+
72
+ - `search_account`:按关键词搜索公众号,返回 fakeid、nickname、alias、intro、avatar
73
+
74
+ ### 文章获取
75
+
76
+ - `get_account_articles`:获取指定公众号的文章列表(按发布时间倒序),支持按 fakeid 或公众号名称查询,支持翻页
77
+ - `get_article_content`:传入文章 URL,返回清洗后的 Markdown 正文
78
+ - `batch_get_articles`:传入公众号名称列表,批量获取近期文章摘要
79
+
80
+ ## 发布新版本到 PyPI
81
+
82
+ 修改代码后,更新 `src/wechat_mcp/__init__.py` 中的版本号,然后:
83
+
84
+ ```sh
85
+ # 安装构建工具(首次需要)
86
+ pip install hatch twine -i https://pypi.org/simple/
87
+
88
+ # 构建
89
+ hatch build
90
+
91
+ # 上传到 PyPI
92
+ # Username: __token__
93
+ # Password: 在 https://pypi.org/manage/account/ 的 API tokens 中创建
94
+ python -m twine upload dist/*
95
+
96
+ # 验证上传成功
97
+ uvx wechatmp-mcp==<新版本号> --help
98
+ ```
99
+
100
+ > 注意:上传后 PyPI 同步约需 1-2 分钟,验证前稍等片刻。
101
+
102
+ ## 使用建议
103
+
104
+ - 使用其他工具前,请先通过 `get_login_qrcode` 获取二维码并扫码,再调用 `check_login_status` 完成登录
105
+ - 登录态保存在 `~/.wechat-mcp/`,重启服务后无需重新登录
106
+ - `get_account_articles` 需要先通过 `search_account` 获取公众号的 `fakeid`
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "wechatmp-mcp"
7
+ dynamic = ["version"]
8
+ description = "MCP service for WeChat Official Account (微信公众号) content retrieval"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "wechatmp-mcp" }
14
+ ]
15
+ keywords = ["mcp", "wechat", "weixin", "微信", "公众号", "playwright"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ ]
25
+ dependencies = [
26
+ "mcp>=1.0.0",
27
+ "starlette>=0.37.0",
28
+ "uvicorn>=0.24.0",
29
+ "playwright>=1.40.0",
30
+ "httpx>=0.25.0",
31
+ "beautifulsoup4>=4.12.0",
32
+ "html2text>=2020.1.16",
33
+ "python-dotenv>=1.0.0",
34
+ "pydantic>=2.0.0",
35
+ "pydantic-settings>=2.0.0",
36
+ ]
37
+
38
+ [project.optional-dependencies]
39
+ dev = [
40
+ "pytest>=7.0.0",
41
+ "pytest-asyncio>=0.21.0",
42
+ ]
43
+
44
+ [project.scripts]
45
+ wechatmp-mcp = "wechat_mcp.server:main"
46
+
47
+ [tool.hatch.version]
48
+ path = "src/wechat_mcp/__init__.py"
49
+ validate-bump = false
50
+
51
+ [tool.hatch.build.targets.wheel]
52
+ packages = ["src/wechat_mcp"]
@@ -0,0 +1,3 @@
1
+ """WeChat MCP - MCP service for WeChat Official Account (微信公众号) content retrieval."""
2
+
3
+ __version__ = "0.0.1"
@@ -0,0 +1,3 @@
1
+ from wechat_mcp.server import main
2
+
3
+ main()
@@ -0,0 +1,53 @@
1
+ """Configuration management using pydantic-settings."""
2
+
3
+ from pathlib import Path
4
+ from typing import Literal, Optional
5
+
6
+ from pydantic import Field
7
+ from pydantic_settings import BaseSettings, SettingsConfigDict
8
+
9
+
10
+ class Settings(BaseSettings):
11
+ model_config = SettingsConfigDict(
12
+ env_file=".env",
13
+ env_file_encoding="utf-8",
14
+ extra="ignore",
15
+ )
16
+
17
+ # Browser (used only for login QR code)
18
+ headless: bool = Field(default=False, description="Run browser in headless mode (False to show QR code)")
19
+ page_timeout: int = Field(default=30000, description="Page timeout in milliseconds")
20
+
21
+ # Storage
22
+ data_dir: Path = Field(
23
+ default=Path.home() / ".wechat-mcp",
24
+ description="Directory for auth store and screenshots",
25
+ )
26
+
27
+ # Logging
28
+ log_level: str = Field(default="INFO", description="Logging level")
29
+
30
+ # MCP transport
31
+ mcp_transport: Literal["stdio", "streamable_http"] = Field(default="stdio")
32
+ mcp_tool_timeout_seconds: float = Field(default=60.0, gt=0)
33
+ mcp_http_host: str = Field(default="127.0.0.1")
34
+ mcp_http_port: int = Field(default=18001, ge=1, le=65535)
35
+ mcp_streamable_http_path: str = Field(default="/mcp")
36
+
37
+ @property
38
+ def screenshots_dir(self) -> Path:
39
+ return self.data_dir / "screenshots"
40
+
41
+ @property
42
+ def auth_file(self) -> Path:
43
+ return self.data_dir / "auth.json"
44
+
45
+
46
+ _settings: Optional[Settings] = None
47
+
48
+
49
+ def get_settings() -> Settings:
50
+ global _settings
51
+ if _settings is None:
52
+ _settings = Settings()
53
+ return _settings
@@ -0,0 +1,27 @@
1
+ """Constants for WeChat MCP."""
2
+
3
+ BASE_URL = "https://mp.weixin.qq.com"
4
+ LOGIN_URL = f"{BASE_URL}/"
5
+
6
+ USER_AGENTS = [
7
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
8
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
9
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/120.0",
10
+ ]
11
+
12
+ # API paths
13
+ SEARCHBIZ_URL = f"{BASE_URL}/cgi-bin/searchbiz"
14
+ APPMSG_URL = f"{BASE_URL}/cgi-bin/appmsg"
15
+ BIZLOGIN_START_URL = f"{BASE_URL}/cgi-bin/bizlogin?action=startlogin"
16
+ BIZLOGIN_URL = f"{BASE_URL}/cgi-bin/bizlogin?action=login"
17
+ SCANLOGIN_URL = f"{BASE_URL}/cgi-bin/scanloginqrcode"
18
+
19
+ # QR code status codes
20
+ QR_STATUS_WAITING = 0
21
+ QR_STATUS_SCANNED = 2
22
+ QR_STATUS_CONFIRMED = 4
23
+ QR_STATUS_SUCCESS_1 = 1
24
+ QR_STATUS_SUCCESS_3 = 3
25
+ QR_STATUS_SELECTING = 6
26
+ QR_STATUS_EXPIRED = 5
27
+ QR_STATUS_CANCELLED = -1
@@ -0,0 +1,41 @@
1
+ """Error definitions for WeChat MCP service."""
2
+
3
+ from enum import Enum
4
+ from typing import Optional
5
+
6
+
7
+ class ErrorCode(str, Enum):
8
+ UNKNOWN_ERROR = "UNKNOWN_ERROR"
9
+ INTERNAL_ERROR = "INTERNAL_ERROR"
10
+ BROWSER_START_FAILED = "BROWSER_START_FAILED"
11
+ NOT_LOGGED_IN = "NOT_LOGGED_IN"
12
+ LOGIN_FAILED = "LOGIN_FAILED"
13
+ LOGIN_TIMEOUT = "LOGIN_TIMEOUT"
14
+ QRCODE_NOT_FOUND = "QRCODE_NOT_FOUND"
15
+ API_ERROR = "API_ERROR"
16
+ RATE_LIMITED = "RATE_LIMITED"
17
+ INVALID_PARAMETER = "INVALID_PARAMETER"
18
+ ARTICLE_FETCH_FAILED = "ARTICLE_FETCH_FAILED"
19
+
20
+
21
+ class WechatMCPError(Exception):
22
+ def __init__(
23
+ self,
24
+ message: str,
25
+ code: ErrorCode = ErrorCode.UNKNOWN_ERROR,
26
+ details: Optional[dict] = None,
27
+ ):
28
+ super().__init__(message)
29
+ self.message = message
30
+ self.code = code
31
+ self.details = details or {}
32
+
33
+
34
+ class LoginError(WechatMCPError):
35
+ def __init__(self, message: str, code: ErrorCode = ErrorCode.LOGIN_FAILED, details: Optional[dict] = None):
36
+ super().__init__(message, code, details)
37
+
38
+
39
+ class ApiError(WechatMCPError):
40
+ def __init__(self, message: str, code: ErrorCode = ErrorCode.API_ERROR, details: Optional[dict] = None):
41
+ super().__init__(message, code, details)
@@ -0,0 +1 @@
1
+ # infrastructure package
@@ -0,0 +1,3 @@
1
+ from .wechat_client import WechatClient, get_wechat_client
2
+
3
+ __all__ = ["WechatClient", "get_wechat_client"]