# Plugin Management MCP
Use the remote website MCP to query, create, and edit plugins, upload packages and description images, change prices, and list or unlist plugins.
Submission is not publication
Plugin creation, information edits, and package updates take effect after administrator approval. Price and listing changes take effect immediately. Only an approved, published plugin can be listed.
# Getting started
- Sign in to the BeikeShop website (opens new window) with an account that has developer access.
- Open User Center → My Plugins (opens new window) and click MCP Access (MCP 接入).
- In the credentials tab, enter a name, select an expiry period, and create a credential. The full Token is shown only once; save it in your AI client's secure configuration.
- Add the remote MCP URL and authorization header below to your AI client. Connect and confirm that the plugin management tools are available.
Credentials authorize all tools for plugins owned by the current developer. Calls fail if the credential expires, is revoked, or developer access is lost.
# Connection settings
- MCP URL:
https://beikeshop.cn/api/mcp/developer - Transport: Streamable HTTP with POST / JSON responses.
- Authorization header:
Authorization: Bearer <your MCP Token>.
Configuration example (field names depend on the AI client):
{
"mcpServers": {
"beikeshop": {
"url": "https://beikeshop.cn/api/mcp/developer",
"headers": {
"Authorization": "Bearer <your MCP Token>"
}
}
}
}
Use the dedicated MCP credential created on the website, rather than a store Token, administrator credential, or browser login Cookie. OAuth login, SSE, and server push are not currently available. The client must support a Bearer authorization header.
Package and description image uploads require local file processing and HTTPS upload capabilities. Remote MCP cannot read local files.
# Available tools
All tools are discovered and called through the same MCP endpoint.
| Tool | Main arguments | Function and result |
|---|---|---|
get_plugin_form_schema | None | Retrieve field rules, required fields, languages, plugin types, and compatible version options; call this before creating a plugin |
list_my_plugins | Optional keyword, page | Retrieve a paginated list of your plugins; keyword searches plugin codes, and results include published and pending information |
get_my_plugin | plugin_code | Retrieve a plugin's published information, pending changes, and latest review result |
prepare_plugin_description_image | operation, plugin_code | Prepare a description image upload URL and temporary credential; operation is create or update; a successful upload returns the image URL |
prepare_plugin_update | operation, plugin_code, expected_version, file_size, sha256 | Prepare a package upload session; operation is create or update; returns an update ID, upload URL, temporary credential, and expiry time |
get_plugin_update_status | update_id | Check validation, submission, and review status, including errors or rejection reasons |
create_plugin | plugin_code, update_id, idempotency_key, fields | Create a plugin from a validated package and submit it for review; the plugin is not automatically listed |
update_plugin | plugin_code, idempotency_key, fields; optional update_id | Submit specified information changes or a replacement package for review; omitted fields retain their existing values |
update_plugin_price | plugin_code, price; optional origin_price | Change the selling price and original price immediately; selling price must be at least CNY 5 |
set_plugin_active | plugin_code, boolean active | Use true to list or false to unlist a plugin immediately; this does not change its review status |
fields supports localized names, summaries, Markdown descriptions, cover images, compatible versions, service prices, tags, and subscription settings. Use get_plugin_form_schema for the current requirements. Compatible versions must use the returned version IDs, rather than version strings.
For a new plugin, the package can supply the default name, type, and icon. You still need to provide the selling price, descriptions in every required language, compatible versions, and any other required information. update_plugin does not accept selling price, original price, or listing status; use the separate tools instead.
There are no tools for deleting plugins, approving reviews, publishing new versions directly, or automatically syncing a README. You cannot manage another developer's plugins.
# How AI discovers and calls tools
The MCP client automatically runs initialize → tools/list and provides the tool definitions to the AI. The AI selects a tool and generates arguments; the client executes it through tools/call.
tools/list returns result.tools, filtered by credential permissions. Each entry includes:
| Field | Purpose |
|---|---|
name | Tool name used in calls |
description | Purpose, when to call, and business limits |
inputSchema | Argument types, required fields, and limits |
annotations | Behavior hints; these do not replace server permission checks |
# Inspecting the tool list manually
For a connection check, replace the Token and send this POST request. Opening the endpoint in a browser sends GET, which is unsupported:
curl 'https://beikeshop.cn/api/mcp/developer' \
--header 'Authorization: Bearer <your MCP Token>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
If tools cannot be discovered, check the MCP URL, transport, and authorization header. For 401 responses, see States and troubleshooting.
# Uploading a package and submitting it
# 1. Prepare a ZIP
The ZIP must contain config.json and an icon under Static/ at the package root or inside a single top-level plugin directory.
config.json.codemust match the targetplugin_code, and the package version must matchexpected_version.- A replacement package must have a different version from the current published version. Information-only edits do not require a version change.
config.json.iconspecifies an icon path relative toStatic/. The default isStatic/image/logo.pngwhen no path is specified.- Icons may be PNG, JPEG, GIF, or WebP, up to 5 MiB and 4096 × 4096 pixels.
- Default limits are 100 MiB per ZIP, 500 MiB of uncompressed data, and 10000 entries. The website's actual limits take precedence.
- Encrypted archives, symbolic links, and paths outside the package are rejected. The website validates the package without executing plugin code.
See Plugin Development for package structure and configuration.
# 2. Prepare an upload session
Calculate the ZIP's actual size in bytes and SHA-256, then call prepare_plugin_update:
{
"operation": "update",
"plugin_code": "example",
"expected_version": "2.0.0",
"file_size": 12345,
"sha256": "<the ZIP's 64-character lowercase SHA-256>"
}
Use operation: "create" for a new plugin. Replace the example file size and checksum with the actual values.
# 3. Upload the file and wait for validation
The response includes update_id, upload_url, method, headers, and expires_at. Send a multipart upload to the returned URL with the returned authorization header. The file field is named file:
curl --request POST "$UPLOAD_URL" \
--header "Authorization: $UPLOAD_AUTHORIZATION" \
--form "file=@$PLUGIN_ZIP"
UPLOAD_URL = returned upload_url; UPLOAD_AUTHORIZATION = complete returned headers.Authorization (including Bearer); PLUGIN_ZIP = local ZIP path.
Use the session's temporary upload credential, rather than your long-term MCP Token. Do not put Tokens in URLs or send local paths or Base64 file content as MCP arguments.
Call get_plugin_update_status with {"update_id":"<your update ID>"}. Wait until the state is ready before submitting for review.
# 4. Submit for review
To replace only the package, call update_plugin:
{
"plugin_code": "example",
"update_id": "<your update ID>",
"idempotency_key": "example-2.0.0-release-1",
"fields": {}
}
To create a plugin, retrieve the field requirements first, then call create_plugin, for example:
{
"plugin_code": "example",
"update_id": "<your update ID>",
"idempotency_key": "example-create-1",
"fields": {
"price": 99,
"description": {
"zh_cn": "插件的中文功能说明。",
"en": "Plugin features and usage instructions."
},
"versions": [1]
}
}
This example uses the name, type, and icon from the package as defaults. The 1 in versions is an example ID: replace it with an actual ID returned by the schema tool, and provide descriptions in the required languages it returns.
A successful submission returns pending_review. Continue querying get_plugin_update_status for the result. approved means the submission was approved; rejected means it was rejected. Read the reason, make corrections, and submit again.
# Editing information without a package
You do not need a package upload session or a new package. If the description includes local images, upload them as described below first. Omit update_id from update_plugin and provide only the fields you want to change:
{
"plugin_code": "example",
"idempotency_key": "example-description-1",
"fields": {
"description": {
"zh_cn": "更新后的中文说明,支持 Markdown。"
}
}
}
Changes to compatible versions and service prices also require review.
# Descriptions with images
Descriptions support Markdown image syntax. AI can upload local images, obtain public URLs, replace image paths in the description, and submit the complete description for review. Package icons are not automatically uploaded as description images, and README files are not automatically synced.
# 1. Prepare image upload credentials
Call prepare_plugin_description_image:
{
"operation": "update",
"plugin_code": "example"
}
Use update for an existing plugin or create for a new plugin. Images can be uploaded before the new plugin is created. This tool does not require a package, version, file size, or SHA-256.
The response includes upload_url, method, headers, multipart_field, expires_at, and format and size limits. Image upload credentials last 15 minutes and can be used for multiple images during that period. Developer access, operation permissions, and plugin ownership are checked both when preparing credentials and when uploading. Revoking the MCP credential also invalidates its image upload credentials.
# 2. Upload images and obtain URLs
Send a multipart request to the returned URL with the temporary authorization header and a file field named file:
curl --request POST "$IMAGE_UPLOAD_URL" \
--header "Authorization: $IMAGE_UPLOAD_AUTHORIZATION" \
--header 'Accept: application/json' \
--form "file=@$DESCRIPTION_IMAGE"
IMAGE_UPLOAD_URL = returned upload_url; IMAGE_UPLOAD_AUTHORIZATION = complete returned headers.Authorization (including Bearer); DESCRIPTION_IMAGE = local image path. Do not upload with your long-term MCP Token, put Tokens in URLs, or send local paths or Base64 image content as MCP arguments.
A successful upload synchronously returns HTTP 200, for example:
{
"url": "https://beikeshop.cn/storage/plugins/20261103/<random-filename>.png",
"value": "storage/plugins/20261103/<random-filename>.png",
"mime_type": "image/png",
"width": 1200,
"height": 800
}
Image uploads do not require polling get_plugin_update_status and do not modify descriptions or submit them for review. Uploaded images are public resources; do not upload sensitive content. Images and plugin logos use the same plugins/date/random-filename storage layout as website uploads. Each upload receives a new filename.
# 3. Replace image references and submit the description
Replace local image paths with the returned url, then call update_plugin:
{
"plugin_code": "example",
"idempotency_key": "example-description-images-1",
"fields": {
"description": {
"en": "## Features\n\n\n\nInstructions for the feature shown above."
}
}
}
Replace the example image URL with the actual returned URL. Upload each image and replace its corresponding reference. For localized descriptions, use the appropriate language fields. When creating a plugin, include the description in create_plugin under fields.description, along with a validated package and all other required information. Descriptions take effect after approval.
# Image limits and security checks
- PNG, JPEG, GIF, and WebP are supported. Script extensions such as PHP and SVG files are rejected. File content is checked independently of the client-provided MIME type.
- The default image file limit is 10 MiB. Returned tool limits and the website's actual limits take precedence.
- The server detects the MIME type and reads image information to check the actual image type. Renaming a script file or changing its client-provided MIME type is insufficient to pass validation.
- Validated files are saved with their original bytes, without decoding or re-encoding. Metadata and the original format are retained. Animated GIF and WebP images retain their animation. Storage filenames are randomly generated with an extension derived from the detected image type.
- Image uploads have an additional limit of 20 requests per minute per IP and also count toward the overall API rate limit. Image validation does not require GD.
# States and troubleshooting
| State | Meaning |
|---|---|
awaiting_upload | Waiting for a package upload |
validating | File received; validation is in progress |
ready | Validation passed; not yet submitted for review |
failed / expired | Processing failed or the upload session expired |
pending_review | Submitted and waiting for administrator review |
superseded | Replaced by a later submission; administrators review the latest draft |
approved / rejected / ban | Approved, rejected, or frozen |
applied | A separate price or listing change has taken effect immediately |
- Authentication fails: check the Token, expiry date, revocation status, and developer access.
- Local files cannot be uploaded: check local file processing and HTTPS upload capabilities.
- Validation fails: check the reported error, package structure, code, version, file size, and SHA-256. Fix the package and prepare a new upload session.
- A pending submission already exists: submit further changes using a new
idempotency_key. Unchanged draft information is preserved, and a new package replaces the previous package. Previous MCP submissions are markedsuperseded; administrators review the latest draft. - A connection is interrupted or a call needs retrying: query the status first. Keep the same
idempotency_keyfor retries of the same submission, and use a different key for each new submission to avoid duplicate creation or submission. - An upload session expires: sessions last one hour by default. Each developer can prepare up to 10 active package sessions at a time. Prepare a new session after expiry.
- Image upload fails: for 401, check that you used the temporary credential returned by the image upload tool; 410 means it expired, so prepare a new one; for 422, check the reported format, content, or size error; for 429, wait before retrying.