diff --git a/README.md b/README.md index c5e1b4c..cac2267 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,41 @@ npm run dev - API文档(默认): http://localhost:10392/docs - 也可在应用内“设置 -> 后端端口”修改(支持“恢复默认”一键回到 10392):网页端会尝试重启本机后端到新端口并刷新(并写入 `output/runtime_settings.json`,开发模式下也会写入项目根目录 `.env` 供 `uv run` 下次启动使用);桌面端会重启内置后端并刷新 +## MCP 服务 + +后端提供 MCP JSON-RPC over HTTP 服务,默认只监听 `127.0.0.1`。手机接入局域网时,在应用内打开 **设置 -> MCP 接入 -> 允许手机局域网接入 MCP**,后端会切换为监听 `0.0.0.0` 并重启。 + +MCP 入口需要 token 鉴权。设置页提供 **MCP Token**、**AI 接入提示词** 和 **Skill Markdown** 三个独立复制区;token 可一键复制或重置,重置后旧 token 立即失效。手机端或外部 AI 客户端访问 `/mcp`、`/mcp/skill/bundle`、`/mcp/skill` 时,都应带上 `Authorization: Bearer `。兼容客户端也可以使用 `X-MCP-Token` 请求头或 `?token=` 查询参数,但推荐使用 Bearer token。 + +通用客户端可以通过 `GET /mcp/skill/bundle` 读取同一份 bundle,通过 `GET /mcp/skill` 读取 markdown 版本,这两个 skill 入口同样需要 MCP token。 + +工具调用成功时,客户端优先读取 `result.structuredContent`,`content[0].text` 只是给通用 MCP 客户端展示的 JSON 文本副本。业务未就绪时仍可能返回 JSON-RPC success,但 `result.isError=true`;协议错误或参数错误则返回 JSON-RPC `error`。 + +工具按包分层: + +- `wechat.core`: 状态、工具目录、账号列表、账号信息 +- `wechat.setup`: 密钥读取、数据库解密、已解密目录导入、媒体密钥保存、批量媒体处理入口 +- `wechat.system`: 健康检查、后端端口、日志路径、大图辅助插件状态等系统能力 +- `wechat.mobile`: 面向手机和外部代理的聚合入口,默认返回小结果和下一步建议 +- `wechat.contacts`: 联系人列表、模糊解析、联系人导出 +- `wechat.chat`: 会话、消息、搜索、发送者筛选、上下文、锚点、合并转发/AppMsg 解析、统计 +- `wechat.moments`: 朋友圈时间线、用户、同步、图片/视频/文章封面 URL +- `wechat.media`: 聊天/朋友圈图片、视频、表情、头像、语音文件 URL、远程图片代理与资源辅助 +- `wechat.biz`: 公众号/服务号与微信支付记录 +- `wechat.analytics`: 年度总结与卡片懒加载 +- `wechat.export`: 聊天、朋友圈、账号归档导出任务、下载 URL 与进度 SSE URL +- `wechat.admin`: 微信检测、索引、实时同步等管理能力 +- `wechat.editing`: 消息编辑、修复、恢复与审计 + +媒体、视频、SSE 进度和 ZIP 导出不会直接塞进 MCP JSON 响应;相关工具返回可访问 URL、`streamUrl`、任务状态或资源参数。 + +配套 skill 可通过 HTTP 加载,访问时需要带 MCP token: + +- JSON bundle: `http://<电脑局域网IP>:10392/mcp/skill/bundle` +- Markdown bundle: `http://<电脑局域网IP>:10392/mcp/skill` + +手机端或外部 AI 客户端应先拉取 skill bundle,将 `bundleText` 注入模型上下文,再按 `initialize`、`tools/list`、`tools/call` 使用 MCP。设置页中的“AI 接入提示词”会包含 endpoint 和 Bearer token,可直接复制给客户端作为接入指令。 + ## 打包为 EXE(Windows 桌面端) 本项目提供基于 Electron 的桌面端安装包(NSIS `Setup.exe`)。 diff --git a/skills/wechat-mcp-copilot/SKILL.md b/skills/wechat-mcp-copilot/SKILL.md new file mode 100644 index 0000000..bbfc8ef --- /dev/null +++ b/skills/wechat-mcp-copilot/SKILL.md @@ -0,0 +1,32 @@ +--- +name: wechat-mcp-copilot +version: "1.0.0" +description: Use WeChatDataAnalysis MCP to inspect local WeChat accounts, contacts, sessions, messages, Moments, media, exports, and analytics through a small routed playbook. Trigger when the user asks to search, summarize, export, diagnose, or reason over local WeChat data. +--- + +# WeChat MCP Copilot + +Use WeChatDataAnalysis MCP like an investigator: start broad, resolve fuzzy targets, then fetch only the context needed to answer. + +## Core Rules + +1. Start with `references/routing.md`. +2. Load only one domain reference after routing. +3. Load `references/pagination-budget.md` before broad searches, exports, or multi-page scans. +4. Use `references/failure-recovery.md` when MCP, database readiness, or empty results are unclear. +5. For phone, ScreenMemo, or external MCP clients, prefer `wechat.mobile.*` facade tools before low-level tools. +6. Do not load the full tool catalog unless the user asks about available tools. + +## References + +- `references/routing.md`: first-hop intent routing. +- `references/mobile.md`: phone-friendly facade tools and compact response rules. +- `references/setup-system.md`: setup, keys, decrypt, import, health, and system operations. +- `references/target-resolution.md`: fuzzy contact/session resolution. +- `references/chats.md`: chat sessions, messages, search, and context. +- `references/moments.md`: Moments timeline, posters, likes, comments, media. +- `references/media.md`: images, videos, emoji, files, voice resources without transcription. +- `references/export.md`: chat, Moments, and account archive export jobs. +- `references/analytics.md`: wrapped cards, counts, rankings, and aggregate analysis. +- `references/pagination-budget.md`: limits, cursors, result clipping, stopping rules. +- `references/failure-recovery.md`: empty result, not-ready database, ambiguous targets, retries. diff --git a/skills/wechat-mcp-copilot/references/analytics.md b/skills/wechat-mcp-copilot/references/analytics.md new file mode 100644 index 0000000..1d46163 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/analytics.md @@ -0,0 +1,19 @@ +# Analytics + +Use this for annual summaries, rankings, counts, and aggregate questions. + +## Tools + +- `wechat.analytics.get_wrapped_meta` +- `wechat.analytics.get_wrapped_card` +- `wechat.analytics.get_wrapped_annual` +- `wechat.chat.get_daily_message_counts` +- `wechat.biz.get_pay_records` + +## Rules + +- Prefer `get_wrapped_meta` then `get_wrapped_card` for mobile or constrained contexts. +- Use `get_wrapped_annual` only when the user needs the whole annual dataset. +- For broad statistics, prefer aggregate tools or targeted searches over full message pagination. +- Always state the account, time range, and metric basis when answering. + diff --git a/skills/wechat-mcp-copilot/references/chats.md b/skills/wechat-mcp-copilot/references/chats.md new file mode 100644 index 0000000..9143bd9 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/chats.md @@ -0,0 +1,28 @@ +# Chats + +Use this for chat sessions, message search, and message context. + +## Flow + +1. Resolve fuzzy target with `wechat.chat.resolve_session`. +2. For recent messages, call `wechat.chat.get_messages` with a small `limit`. +3. For keywords, call `wechat.chat.search_messages`. +4. Use `wechat.chat.list_search_senders` when the user needs sender facets for a broad search. +5. For a hit that needs context, call `wechat.chat.get_message_around`. +6. For merged-forward chat history or AppMsg cards that only expose `server_id`, call `wechat.chat.resolve_chat_history` or `wechat.chat.resolve_app_message`. +7. Use `wechat.chat.get_message_raw` only for debugging or missing structured fields. + +## Useful Tools + +- `wechat.chat.list_sessions` +- `wechat.chat.resolve_session` +- `wechat.chat.get_messages` +- `wechat.chat.search_messages` +- `wechat.chat.list_search_senders` +- `wechat.chat.get_message_around` +- `wechat.chat.get_message_anchor` +- `wechat.chat.get_daily_message_counts` +- `wechat.chat.resolve_chat_history` +- `wechat.chat.resolve_app_message` + +Do not scan full histories by pagination when an aggregate or search tool can answer. diff --git a/skills/wechat-mcp-copilot/references/export.md b/skills/wechat-mcp-copilot/references/export.md new file mode 100644 index 0000000..1d61466 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/export.md @@ -0,0 +1,29 @@ +# Export + +Use export only when the user asks for an artifact. + +## Chat Export + +1. Resolve target session if `scope=selected`. +2. Confirm time range, format, media options, and output directory when needed. +3. Preview targets with `wechat.export.preview_chat_targets`. +4. Create job with `wechat.export.create_chat_export`. +5. Poll `wechat.export.get_chat_export`. +6. Return `wechat.export.get_chat_export_download` when ready. +7. Use `wechat.export.get_chat_export_events_url` when the client can consume SSE progress. + +## Moments Export + +Use `wechat.export.create_moments_export`, `wechat.export.get_moments_export`, `wechat.export.get_moments_export_download`, and `wechat.export.get_moments_export_events_url`. + +## Account Archive + +Use `wechat.export.create_account_archive`, `wechat.export.get_account_archive`, `wechat.export.get_account_archive_download`, and `wechat.export.cancel_account_archive`. + +## Contacts Export + +Use `wechat.contacts.export_contacts` only when the user asks for a contacts file. It writes JSON or CSV to a local output directory. + +Do not silently export all history and all media unless the user explicitly asked for that scope. + +For phone clients, prefer `wechat.mobile.export_job` unless exact low-level export options are required. diff --git a/skills/wechat-mcp-copilot/references/failure-recovery.md b/skills/wechat-mcp-copilot/references/failure-recovery.md new file mode 100644 index 0000000..b702d1d --- /dev/null +++ b/skills/wechat-mcp-copilot/references/failure-recovery.md @@ -0,0 +1,21 @@ +# Failure Recovery + +Use this when MCP status, DB readiness, or results are suspicious. + +## Checks + +1. Phone clients: `wechat.mobile.get_overview` +2. `wechat.core.get_status` +3. `wechat.core.list_accounts` +4. `wechat.core.get_account_info` +5. Search index status with `wechat.chat.get_search_index_status` when message search fails. +6. Moments availability by checking account info and `wechat.moments.list_users`. +7. Setup readiness: load `setup-system.md` for keys, decrypt, import, health, or media-key problems. + +## Empty Results + +- Do not conclude "no data" after one failed query. +- Try contact/session resolution with a simpler keyword. +- Try session search before global message search when a target is known. +- For Moments, resolve poster identity before timeline filtering. +- If setup is not ready, stop content tools and explain the missing readiness condition. diff --git a/skills/wechat-mcp-copilot/references/media.md b/skills/wechat-mcp-copilot/references/media.md new file mode 100644 index 0000000..b136682 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/media.md @@ -0,0 +1,30 @@ +# Media + +Use this for image, video, emoji, file, link, and voice resources. + +## Tools + +- `wechat.media.get_avatar_url` +- `wechat.media.get_chat_image_url` +- `wechat.media.get_chat_emoji_url` +- `wechat.media.get_chat_video_thumb_url` +- `wechat.media.get_chat_video_url` +- `wechat.media.get_chat_voice_url` +- `wechat.media.get_decrypted_resource_url` +- `wechat.media.get_proxy_image_url` +- `wechat.media.get_favicon_url` +- `wechat.media.open_chat_media_folder` +- `wechat.biz.get_proxy_image_url` +- `wechat.moments.get_media_url` +- `wechat.moments.get_article_thumb_url` +- `wechat.moments.get_remote_video_url` +- `wechat.moments.get_local_video_url` + +## Rules + +- Media tools return URLs or resource metadata; they do not inline large binary payloads. +- Voice resources are files only. Do not transcribe voice messages. +- For phone clients, prefer `wechat.mobile.get_media_links` first. +- `open_chat_media_folder` is a desktop-host action; do not use it for phone-only flows. +- Locate the message first, then fetch media URL by message fields such as `server_id`, `username`, `md5`, or returned media references. +- For Moments, prefer local media URL fields from timeline records. Use remote video/article helpers only when the timeline record has a remote URL or article URL. diff --git a/skills/wechat-mcp-copilot/references/mobile.md b/skills/wechat-mcp-copilot/references/mobile.md new file mode 100644 index 0000000..d34e1cd --- /dev/null +++ b/skills/wechat-mcp-copilot/references/mobile.md @@ -0,0 +1,30 @@ +# Mobile Facade + +Use this for phone, ScreenMemo, and external MCP clients unless the user needs a low-level operation. + +## Default Tools + +- `wechat.mobile.get_overview`: first call after initialize. Returns readiness, accounts, health, and suggested next tools. +- `wechat.mobile.get_home_snapshot`: small account/session/Moments snapshot for a home screen. +- `wechat.mobile.resolve_target`: resolve fuzzy people, groups, sessions, Moments users, or official accounts. +- `wechat.mobile.search_chat`: message search with optional tiny context windows. +- `wechat.mobile.get_chat_context`: recent, day, or around-anchor chat context. +- `wechat.mobile.get_session_bundle`: session metadata plus a page of messages. +- `wechat.mobile.search_moments`: compact Moments search. +- `wechat.mobile.get_media_links`: URL-only media lookup. +- `wechat.mobile.get_analytics`: compact analytics by metric. +- `wechat.mobile.export_job`: preview/create/status/download/cancel export jobs. + +## Budget Rules + +- Keep `limit` at 10-20 for first calls. +- Use `offset` or returned cursor fields for paging. +- Do not call full annual analytics by default; use `metric=digest` or a single card. +- Do not fetch binary media through MCP. Use returned URLs in the app. +- Use low-level tools only for debugging, editing, raw fields, unusual media, or exact export control. + +## Recovery + +- If `ready=false`, load `setup-system.md`. +- If target resolution is ambiguous, ask for one clarifying clue or show top candidates. +- If search returns nothing, try `resolve_target` and then `get_chat_context` before declaring no data. diff --git a/skills/wechat-mcp-copilot/references/moments.md b/skills/wechat-mcp-copilot/references/moments.md new file mode 100644 index 0000000..85cbaf1 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/moments.md @@ -0,0 +1,18 @@ +# Moments + +Use this for 朋友圈, posts, likes, comments, shared links, and Moments media. + +## Flow + +1. If the clue is a person, resolve with `wechat.contacts.resolve_contact`. +2. Use `wechat.moments.list_users` when you need poster candidates. +3. Use `wechat.moments.list_timeline` or `wechat.moments.search_moments`. +4. Use `wechat.moments.get_media_url` only when the user needs a media resource. + +## Rules + +- Person names must be resolved to username before filtering timeline by `usernames`. +- Keyword search is for post content/topic, not poster identity. +- Do not request raw XML by default. +- Use `wechat.moments.sync_latest` only when the user explicitly wants fresh local sync or status indicates data is stale. + diff --git a/skills/wechat-mcp-copilot/references/pagination-budget.md b/skills/wechat-mcp-copilot/references/pagination-budget.md new file mode 100644 index 0000000..9e5ec65 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/pagination-budget.md @@ -0,0 +1,20 @@ +# Pagination And Budget + +Default limits: + +- Contact/session candidates: 10 +- Recent messages: 20 +- Message search: 20 +- Moments timeline: 10 +- Media references: 20 +- Ranking/analytics rows: 20 + +Hard rules: + +- Keep single message/Moments pages at or below 50 unless user asks for more. +- Stop paging when enough evidence exists. +- Stop after two empty or low-value pages. +- Do not cross 500 raw messages without user confirmation. +- List responses should use ids, names, timestamps, preview, and evidence. +- Fetch full details only after a candidate or hit is selected. + diff --git a/skills/wechat-mcp-copilot/references/routing.md b/skills/wechat-mcp-copilot/references/routing.md new file mode 100644 index 0000000..55116c0 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/routing.md @@ -0,0 +1,24 @@ +# Routing + +Use this first for every WeChatDataAnalysis MCP task. + +## First Calls + +- Phone, ScreenMemo, mobile app, or compact external client: load `mobile.md` and start with `wechat.mobile.get_overview`. +- Status, readiness, "why can't I find anything": `wechat.core.get_status`, or `wechat.mobile.get_overview` for phone clients. +- Available tools or packages: `wechat.core.list_tools`. +- Account selection: `wechat.core.list_accounts`, then `wechat.core.get_account_info`. +- Key/decrypt/import/backend health problems: load `setup-system.md`. +- Fuzzy person/group/official account: load `target-resolution.md`. +- Chat content, recent messages, keyword search: load `chats.md`. +- Moments / 朋友圈 / likes / comments / post media: load `moments.md`. +- Images, videos, emoji, files, voice resources: load `media.md`. +- Export requests: load `export.md`. +- Rankings, yearly summary, activity stats: load `analytics.md`. +- Empty results or setup errors: load `failure-recovery.md`. + +## Mixed Intent + +Resolve the target first, then load only the main domain reference. Do not load chats, moments, media, export, and analytics together unless the user explicitly asks for a broad audit. + +For phone clients, keep using `mobile.md` until the user needs a low-level fallback such as editing, raw fields, special media URL construction, or exact export options. diff --git a/skills/wechat-mcp-copilot/references/setup-system.md b/skills/wechat-mcp-copilot/references/setup-system.md new file mode 100644 index 0000000..65b3c56 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/setup-system.md @@ -0,0 +1,41 @@ +# Setup And System + +Use this when the database is not ready, keys are needed, decrypted data must be imported, or the backend itself needs inspection. + +## Setup Tools + +- `wechat.setup.get_saved_keys`: read saved DB/media keys for an account or wxid directory. +- `wechat.setup.get_database_key`: desktop workflow to extract the DB key from local WeChat. +- `wechat.setup.get_image_key`: fetch and save image AES/XOR keys. +- `wechat.setup.decrypt_databases`: decrypt databases from `db_storage_path` and a DB key. +- `wechat.setup.get_decrypt_stream_url`: SSE URL for decrypt progress. +- `wechat.setup.preview_import_decrypted`: validate an already-decrypted account directory. +- `wechat.setup.get_import_decrypted_stream_url`: SSE URL for import progress. +- `wechat.setup.cancel_import_decrypted`: cancel an import job by `job_id`. +- `wechat.setup.save_media_keys`: save media XOR/AES keys. +- `wechat.setup.decrypt_all_media`: decrypt all local `.dat` image resources. +- `wechat.setup.get_decrypt_all_media_stream_url`: SSE URL for bulk media decrypt progress. +- `wechat.setup.get_download_all_emojis_stream_url`: SSE URL for bulk emoji download progress. + +## System Tools + +- `wechat.system.health_check` +- `wechat.system.api_root` +- `wechat.system.get_backend_log_file` +- `wechat.system.open_backend_log_file` +- `wechat.system.get_backend_port` +- `wechat.system.set_backend_port_setting` +- `wechat.system.set_backend_port_and_restart` +- `wechat.system.get_img_helper_status` +- `wechat.system.toggle_img_helper` +- `wechat.system.pick_directory` +- `wechat.system.log_frontend_server_error` + +## Rules + +- Stream tools return `streamUrl`; the client consumes SSE outside the MCP JSON response. +- `set_backend_port_setting` persists the setting and may require backend restart by the user/client flow. +- `set_backend_port_and_restart` changes the port through the desktop restart flow and will disrupt the current backend connection. +- `open_backend_log_file` and `pick_directory` are desktop-host GUI actions; do not use them for phone-only flows. +- DB key extraction and image helper toggling depend on the local desktop WeChat state. +- Import/decrypt/media bulk operations write local files; summarize expected impact before running them. diff --git a/skills/wechat-mcp-copilot/references/target-resolution.md b/skills/wechat-mcp-copilot/references/target-resolution.md new file mode 100644 index 0000000..54c2818 --- /dev/null +++ b/skills/wechat-mcp-copilot/references/target-resolution.md @@ -0,0 +1,21 @@ +# Target Resolution + +Use target resolution whenever the user gives a loose name, nickname, group name, remark, official account name, or "the person/group who...". + +## Tools + +- Contacts: `wechat.contacts.resolve_contact` +- Sessions: `wechat.chat.resolve_session` +- Fallback list: `wechat.contacts.list_contacts`, `wechat.chat.list_sessions` + +## Rules + +- Prefer exact username/wxid match, then remark, nickname, display name, alias, recent session evidence. +- If a chat task mentions a person, resolve both contact and session when needed. +- If several candidates remain plausible, inspect recent session previews before choosing. +- If ambiguity survives after reasonable evidence, ask a short clarification. + +## Evidence Fields + +Use username/session id, display name, remark/nickname/alias, session type, recent timestamp, recent preview, and confidence. +