Marketplace clone loads `.mcp.json` over documented `mcp.json` when both exist in a dual Cursor + Claude Code plugin repo
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 8.2k
- Forks
- 751
- Avg merge
- 12h 1m
- Merged PRs (30d)
- 43
Description
Summary
A repository that is both a Cursor plugin and a Claude Code plugin often ships two MCP config filenames:
mcp.json— Cursor’s documented plugin default (Plugins reference: auto-discovermcp.json;mcpServersin.cursor-plugin/plugin.jsononly for a custom path or inline config).mcp.json— Claude Code’s documented plugin default
The Marketplace scan already looks for both names (see #43: “.mcp.json or mcp.json”). The runtime on a Marketplace clone is not documented when both files exist and contain different servers. In our case the clone started the Claude Code file (local stdio / uvx) instead of the Cursor file (hosted HTTP + OAuth).
That is a different failure from #43 (scanner ignoring manifest paths / inline mcpServers). This issue is precedence when both files are present.
Why we ship both (adoption, not a quirk)
We publish one git repository as two first-class plugins:
- a Cursor Marketplace plugin (
.cursor-plugin/), and - a Claude Code plugin (
.claude-plugin/).
That is deliberate distribution: the same skills + hosted MCP for whoever the user already lives in, without a second repo or a second source of truth. Cursor’s public contract puts MCP in mcp.json. Claude Code’s public contract puts MCP in .mcp.json. Following both docs in one repo is how dual-client vendors will keep packaging this — Figma’s mcp-server-guide is the same shape (Cursor + Claude in one git tree).
Anyone else aiming for adoption on both IDEs will hit the same filename pair. If those two files ever diverge (hosted vs local stdio, different env, a leftover uvx on the Claude side), the Cursor Marketplace clone can start the wrong server while the listing still describes the hosted one. This is not unique to us; it is the default layout two public plugin specs produce when they share a repo.
Expected
Per the plugins reference:
- Default discovery for a Cursor plugin is
mcp.jsonat the plugin root. .mcp.jsonis not the Cursor plugin contract (it is Claude Code’s).- If both files exist, Cursor should either:
- load
mcp.jsononly, or - document a deterministic precedence (and warn when the two payloads differ).
- load
The submit scanner and the authoring docs should name the same files and the same precedence.
Actual
Installing from the Marketplace cloned the entire GitHub repo into the plugin cache. Both files sat at the plugin root. With no mcpServers pin (we followed the docs: omit the field so mcp.json is auto-discovered), Cursor connected to the server in .mcp.json, not mcp.json.
A local plugin copy that only included mcp.json behaved as documented (hosted URL). The Marketplace clone did not.
Reproduction
Minimal dual-client plugin root (the layout two marketplaces independently document):
.cursor-plugin/plugin.json — no mcpServers (rely on default discovery):
{
"name": "example",
"displayName": "Example",
"version": "0.1.0"
}
.claude-plugin/plugin.json — Claude Code plugin in the same repo (MCP is not inlined; it auto-discovers .mcp.json).
mcp.json (Cursor / hosted — what the listing should run):
{
"mcpServers": {
"example": {
"url": "https://mcp.example.com/mcp",
"auth": { "CLIENT_ID": "example-mcp" }
}
}
}
.mcp.json (Claude Code / local stdio — different payload on purpose):
{
"mcpServers": {
"example": {
"command": "uvx",
"args": ["example-mcp-server"]
}
}
}
Steps:
- Submit or install this repo as a Cursor Marketplace plugin (clone of the GitHub root).
- Open the installed plugin’s MCP server.
- Observe which config was used.
Result: the clone started uvx example-mcp-server from .mcp.json.
Expected: hosted https://mcp.example.com/mcp from mcp.json.
Workaround that unblocked us
- One hosted payload in
.mcp.jsononly (same file Claude Code auto-discovers). - Explicit pin:
"mcpServers": "./.mcp.json"in.cursor-plugin/plugin.json. - Do not leave a sibling
mcp.jsonwith a different server.
This matches the documented custom-path override, and is what figma/mcp-server-guide does (single .mcp.json + pin; no root mcp.json).
Request
- Document precedence when
mcp.jsonand.mcp.jsonboth exist at the plugin root. - Align the Marketplace scanner text (#43) with the plugins reference (today the scanner lists both names; the reference only documents
mcp.json). - In the authoring / submit docs, warn dual Cursor + Claude Code authors: shipping both filenames is the natural adoption layout; different payloads can make the Marketplace clone start the wrong server. Pin
mcpServersor keep a single shared file.
Related
- #43 — scanner looks for
.mcp.jsonormcp.jsonand does not use the manifest for custom paths / inline MCP
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the plugins reference and the Marketplace scanner behavior described in #43, then reproduce the dual-client layout with .cursor-plugin/plugin.json, mcp.json, and .mcp.json. Trace which root configuration the Marketplace clone selects when both files differ. Done means the precedence is deterministic, the scanner and authoring docs agree, and dual Cursor plus Claude Code repositories receive a clear warning or documented configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- documentation
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100