Content
# Tool List
## MCP Server for Pinduoduo Merchant Backend
A local, read-only MCP Server for Agents. It saves the login state of Pinduoduo merchant backend through a dedicated, visible Chrome Profile and provides order and after-sales query tools.
> This project is not an official Pinduoduo product. It is only used for low-frequency, read-only operations authorized by the shop owner. Verification codes, SMS, scanning codes, identity verification, and risk control must be completed manually by the user; the project will not bypass security measures or call un公开 interfaces of the merchant backend.
## v1 Scope
- Only supports Windows 10/11, Node.js 24, Google Chrome, and domestic `mms.pinduoduo.com`.
- Each member runs on their own computer; only one Agent client is connected at a time.
- Supports multiple shops, but each shop uses a completely independent browser Profile, and only one shop is activated at a time.
- Only reads the information already displayed on the page, without clicking on additional disclosure buttons such as "Decrypt" or "View complete phone number".
- Does not provide shipping, refund, price change, listing/unlisting, chat, arbitrary clicks, script execution, Cookie export, or file download.
## Installation
```powershell
pnpm install
pnpm build
node dist/cli.js doctor
```
The default state directory is `%LOCALAPPDATA%\pdd-mcp`. It can be overridden in the MCP client configuration through `PDD_MCP_HOME`; this directory contains the browser state that can be used to log in to the shop, and should not be submitted to Git, cloud storage, or shared directories.
Example of general stdio configuration:
```json
{
"mcpServers": {
"pdd-merchant": {
"command": "node",
"args": [
"C:\\absolute\\path\\to\\pdd-merchant-mcp\\dist\\cli.js",
"serve"
],
"env": {
"PDD_MCP_HOME": "C:\\Users\\you\\AppData\\Local\\pdd-mcp"
}
}
}
}
```
stdout is exclusively used for MCP JSON-RPC; running logs are only written to stderr, and will not record tool input, order results, Cookies, Tokens, verification codes, or page screenshots.
## First Use
It is recommended to let the Agent call in the following order:
1. `pdd.profiles.create` to create a shop Profile.
2. `pdd.profile.use` to activate the Profile and open a dedicated Chrome.
3. `pdd.session.login_open` to open the official login page.
4. The user manually completes the scanning code, SMS, or verification in Chrome.
5. `pdd.session.status` to confirm the status is `authenticated`, and confirm that the returned Profile contains a trusted and stable `shopId`.
6. Call the order or after-sales query tool.
The active Profile is not saved across MCP processes; after MCP restarts, you need to call `pdd.profile.use` again, but as long as Pinduoduo does not expire the session, you do not need to log in again.
Order and after-sales queries must be bound to a trusted and stable `shopId`. The service only reads this identifier from the calibrated shop identity area and will not guess the shop identity from ordinary page text such as buyer reviews or order content; after the first binding, subsequent activations only verify and will not automatically overwrite. If the old Profile has not bound `shopId`, please call `pdd.profile.use` again. If the trusted area still cannot provide a stable identifier, the service will stop with `SHOP_MISMATCH` for security reasons and will not continue to query.
Deleting a Profile can only be done through the local CLI, and must be confirmed explicitly:
```powershell
node dist/cli.js profile remove <profileId> --confirm
```
## MCP Tools
| Tool | Purpose |
| --- | --- |
| `pdd.profiles.create` | Create an isolated local browser Profile |
| `pdd.profiles.list` | List Profiles and last known status |
| `pdd.profile.use` | Switch active shop |
| `pdd.session.status` | Real-time check login, verification, and risk control status |
| `pdd.session.login_open` | Open official login page for manual login by user |
| `pdd.orders.list` | Query orders by date, status, order number, and pagination |
| `pdd.orders.get` | Get current displayed order details |
| `pdd.after_sales.list` | Query after-sales records by pagination |
| `pdd.after_sales.get` | Get current displayed after-sales details |
Order and after-sales details may contain currently visible names, phone numbers, and addresses on the page, marked with `containsSensitiveData: true`. Before using a cloud Agent, you should confirm that your organization's data processing and privacy policy allows sending these fields.
### List Pagination and Truncation
The `pagination.nextCursor` returned by `pdd.orders.list` and `pdd.after_sales.list` is an opaque v2 cursor. It is recommended to use it as-is for the next call, without parsing or modifying:
```json
{
"cursor": "<previous pagination.nextCursor>"
}
```
- Only pass `cursor` to continue the same query; date, status, order number, and `limit` will be restored from the cursor.
- If you explicitly pass filtering conditions, these conditions must be identical to the original query, otherwise `VALIDATION_FAILED` will be returned.
- The cursor is bound to the specific tool, query conditions, active Profile, and stable `shopId`, and cannot be used across orders/after-sales or across shops.
- The cursor is issued and verified by the current MCP process; after MCP restarts, the old cursor will expire, and you need to start from the first query again.
- `limit` represents the maximum number of records returned this time (default 20, maximum 50), and will not forcibly modify the number of records per page on the Pinduoduo webpage. Even if there are still unread records on the same webpage, it will continue from the correct row through the next cursor, without skipping.
- Normally, reaching `limit` or webpage pagination does not mean data is truncated, and `truncated` will not be set to `true`. Only when the field exceeds 16 KiB or the response approaches the 512 KiB security budget and is truncated, `truncated: true` will be returned; if there are still unread records, the next page cursor will be returned as much as possible.
## Errors and Manual Intervention
The following situations will stop automation and will not retry automatically:
- Login expired or not logged in: `AUTH_REQUIRED`
- SMS, slider, scanning code, or identity verification: `USER_VERIFICATION_REQUIRED`
- 403, 429, or risk prompt: `PDD_RISK_CONTROL`
- Page structure no longer matches the verified landmark: `PAGE_CHANGED`
- Logged-in shop and Profile bound identity are different: `SHOP_MISMATCH`
- Another client occupies the same Profile: `PROFILE_IN_USE`
- Single browser operation exceeds 45 seconds: `TIMEOUT`, and returns `actionRequired.type: "reopen_browser"`
When encountering `reopen_browser`, the timed-out Chrome context has been closed to terminate the stuck page operation. Please call `pdd.profile.use` again to open the current Profile, and then retry the original query; do not submit the old call that is still waiting.
## Development and Verification
```powershell
pnpm typecheck
pnpm test
pnpm build
```
Ordinary tests only use synthetic pages and temporary Profiles, and do not connect to real Pinduoduo. Real read-only smoke tests must be enabled manually:
```powershell
$env:PDD_MCP_LIVE_TEST = "1"
$env:PDD_MCP_LIVE_PROFILE = "manually logged-in _profile_id"
pnpm test:live
```
Before being used for real shops, you must complete a read-only calibration in a minimum permission test shop according to [MMS Page Adaptation Calibration](docs/selector-calibration.md). Page routing, landmarks, and state mapping are concentrated in the MMS adaptation layer; after Pinduoduo page updates, you should recalibrate and supplement synthetic fixtures, and not use fuzzy coordinates to click and cover `PAGE_CHANGED`.
## Follow-up Official API Adaptation
Pinduoduo Open Platform provides official capabilities for merchant self-developed systems. v1 only implements browser `OrderSource` / `AfterSaleSource`, but retains a unified interface and `source: "browser"` field, so as to add API priority implementation after obtaining OAuth authorization.