fix: use relative path in .mcp.json to silence CLAUDE_PLUGIN_ROOT warning (#253)

* ci: update install stats

* ci: update install stats

* ci: update install stats

* ci: update install stats

* ci: update install stats

* ci: update install stats

* ci: update install stats

* ci: update install stats

* ci: update install stats

* ci: update install stats

* ci: update install stats

* fix: use relative path in .mcp.json to avoid CLAUDE_PLUGIN_ROOT warning

${CLAUDE_PLUGIN_ROOT} is only defined when the repo is loaded as an installed
Claude Code plugin. When contributors open the repo as a regular project, the
variable is undefined and Claude Code prints:

  [Warning] mcpServers.context-mode: Missing environment variables: CLAUDE_PLUGIN_ROOT

Use a relative path so the MCP entry works for repo-as-project usage. Plugin
install path is unaffected — it still uses .claude-plugin/plugin.json.

Closes #251

Co-authored-by: Ercan Ermis <eposta@ercanermis.com>

* test(.mcp.json): assert CLAUDE_PLUGIN_ROOT stays in plugin manifest, not repo-root

The prior assertion required `${CLAUDE_PLUGIN_ROOT}` in repo-root
`.mcp.json`, but that file is only read when contributors open the repo
as a regular project — marketplace installs resolve paths from
`.claude-plugin/plugin.json` instead. The repo-root file now uses a
relative path to silence the "Missing environment variable" warning.

Split the original test into two:
- Plugin manifest must keep the placeholder (real marketplace contract).
- Repo-root .mcp.json must use a relative path (this PR's behavior).

Co-authored-by: Ercan Ermis <eposta@ercanermis.com>

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Ercan
2026-04-13 22:50:22 +03:00
committed by GitHub
co-authored by Ercan Ermis github-actions[bot]
parent 4e9baedc95
commit aea633c0dd
3 changed files with 21 additions and 6 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
"mcpServers": {
"context-mode": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/start.mjs"]
"args": ["./start.mjs"]
}
}
}
+3 -3
View File
@@ -1,8 +1,8 @@
{
"schemaVersion": 1,
"label": "users",
"message": "66.4k+",
"message": "75.1k+",
"color": "brightgreen",
"npm": "56.1k+",
"marketplace": "10.3k+"
"npm": "64.4k+",
"marketplace": "10.7k+"
}
+17 -2
View File
@@ -142,10 +142,25 @@ describe(".mcp.json — MCP server config", () => {
expect(upgradeSrc).toContain('resolve(pluginRoot, ".mcp.json")');
});
it("template .mcp.json keeps ${CLAUDE_PLUGIN_ROOT} for marketplace compatibility", () => {
it("plugin manifest keeps ${CLAUDE_PLUGIN_ROOT} for marketplace compatibility", () => {
// Marketplace installs read .claude-plugin/plugin.json, not repo-root
// .mcp.json. The plugin manifest is the one that must retain the
// ${CLAUDE_PLUGIN_ROOT} placeholder so installed plugins resolve their
// bundled server path. Repo-root .mcp.json is for contributors opening
// the repo as a regular project and uses a relative path to avoid the
// "Missing environment variable: CLAUDE_PLUGIN_ROOT" warning.
const plugin = JSON.parse(
readFileSync(resolve(ROOT, ".claude-plugin", "plugin.json"), "utf-8"),
);
const args = plugin.mcpServers["context-mode"].args;
expect(args[0]).toContain("CLAUDE_PLUGIN_ROOT");
});
it("repo-root .mcp.json uses relative path to silence CLAUDE_PLUGIN_ROOT warning", () => {
const mcp = JSON.parse(readFileSync(resolve(ROOT, ".mcp.json"), "utf-8"));
const args = mcp.mcpServers["context-mode"].args;
expect(args[0]).toContain("CLAUDE_PLUGIN_ROOT");
expect(args[0]).not.toContain("CLAUDE_PLUGIN_ROOT");
expect(args[0]).toMatch(/^\.\/|^start\.mjs$/);
});
});