diff --git a/README.md b/README.md index b2669f2..5a78c1a 100644 --- a/README.md +++ b/README.md @@ -332,6 +332,19 @@ Run the MCP server: cfg-mcp ``` +`cfg-mcp` requires the `mcp` extra. If you installed cfgit without it (a plain +`pip install cfgit` / `pipx install cfgit`), `cfg-mcp` exits with +`ModuleNotFoundError` — which is what an MCP client (or a one-click install +deeplink) will surface as a failed connection. Install the extra: + +```bash +pip install 'cfgit[mcp]' # pip / venv +pipx inject cfgit 'mcp>=1.0,<2' # if cfgit was installed via pipx +``` + +The extra currently pins `mcp>=1.0,<2` — the cfgit MCP server targets the mcp 1.x +`FastMCP` API and is not yet ported to mcp 2.0. + ## Record syntax Records are addressed as: diff --git a/src/cfg/mcp/server.py b/src/cfg/mcp/server.py index 9c06e9d..afe7fff 100644 --- a/src/cfg/mcp/server.py +++ b/src/cfg/mcp/server.py @@ -14,9 +14,28 @@ FastMCP = None # type: ignore[assignment] +def _mcp_missing_message() -> str: + """Actionable install hint. `cfg-mcp` is commonly launched by an MCP client (e.g. via a + one-click deeplink) against a cfgit that was installed WITHOUT the mcp extra. For a pipx + install, `pip install cfgit[mcp]` is the wrong fix (it won't touch the pipx venv), so lead + with `pipx inject` when we detect we're running from one.""" + import sys + + base = ( + "The cfgit MCP server needs the 'mcp' package, which is not installed in this " + "environment. cfgit was installed without the [mcp] extra." + ) + if "/pipx/venvs/" in sys.prefix or "/pipx/venvs/" in sys.executable: + return ( + f"{base}\nFix (pipx): pipx inject cfgit 'mcp>=1.0,<2'\n" + "or reinstall with the extra: pipx install 'cfgit[mcp]' --force" + ) + return f"{base}\nFix: pip install 'cfgit[mcp]' (mcp 2.0 is not yet supported; the extra pins mcp<2)" + + def _mcp() -> Any: if FastMCP is None: - raise ModuleNotFoundError("install cfgit[mcp] to run the cfgit MCP server") + raise ModuleNotFoundError(_mcp_missing_message()) return FastMCP("cfgit")