diff --git a/README.md b/README.md index a06a7b2..f2681ef 100644 --- a/README.md +++ b/README.md @@ -115,14 +115,40 @@ growmos status · growmos context · growmos doctor · growmos eval · growmos s | **Any file** | `growmos integrate file --file path/to/instructions.md` | append the protocol block anywhere | | **git** | `growmos integrate hooks` → `post-commit`, `post-merge`, `post-checkout` | queue changed docs automatically | | **CI** | `growmos integrate ci` → `.github/workflows/growmos.yml` | doctor + eval on every PR | +| **MCP** | `growmos integrate mcp` → `.mcp.json` (+ `.cursor/mcp.json`) | tools for any MCP client (below) | `growmos init --agent all` does all of the above. Everything is idempotent (marker blocks, JSON merges). -**MCP** — `growmos mcp` is a zero-dependency MCP stdio server exposing `growmos_context`, -`growmos_query`, `growmos_remember`, `growmos_link`, `growmos_journal`, `growmos_check`, -`growmos_next`, `growmos_apply`, `growmos_entity`, `growmos_search`, `growmos_status`, -`growmos_sample`. Add `{"mcpServers": {"growmos": {"command": "growmos", "args": ["mcp"]}}}` -to your CLI's MCP config. +### MCP server (any MCP-capable client) + +`growmos mcp` is a zero-dependency MCP stdio server. Register it the same way you register any +MCP server — `growmos integrate mcp` writes this for you, or paste it yourself: + +```json +{ + "mcpServers": { + "growmos": { + "command": "growmos", + "args": ["mcp"] + } + } +} +``` + +| Client | Where | +|---|---| +| Claude Code | `.mcp.json` in the repo (written by `growmos init` / `integrate claude`), or `claude mcp add growmos -- growmos mcp` | +| Cursor | `.cursor/mcp.json` (written by `integrate cursor` / `integrate mcp`) | +| Codex CLI | `~/.codex/config.toml`: `[mcp_servers.growmos]` `command = "growmos"` `args = ["mcp"]` | +| Gemini CLI | `~/.gemini/settings.json` → `mcpServers.growmos` as above | +| Grok CLI / others | their MCP config, same JSON | + +Tools exposed: `growmos_context`, `growmos_query`, `growmos_entity`, `growmos_search`, +`growmos_remember`, `growmos_link`, `growmos_journal`, `growmos_check`, `growmos_next`, +`growmos_apply`, `growmos_status`, `growmos_sample`. Once registered, the agent calls them +directly instead of shelling out — e.g. *"what depends on the Store?"* → `growmos_query`; *"remember +that Scheduler now uses Kafka"* → `growmos_remember` + `growmos_link`; *"grow the graph"* → +`growmos_next` / `growmos_apply` in a loop. ## What lives in `.growmos/` (commit it) diff --git a/docs/agents.md b/docs/agents.md index 06d9698..41331f1 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -62,6 +62,17 @@ growmos init --agent cursor # .cursor/rules/growmos.mdc, alwaysApply: true growmos init --agent gemini # GEMINI.md block ``` +## MCP (any client) + +```bash +growmos integrate mcp # writes .mcp.json (and .cursor/mcp.json if .cursor/ exists) +``` +```json +{"mcpServers": {"growmos": {"command": "growmos", "args": ["mcp"]}}} +``` +Claude Code also accepts `claude mcp add growmos -- growmos mcp`. Codex: `~/.codex/config.toml` +(`[mcp_servers.growmos] command = "growmos" args = ["mcp"]`). Gemini: `~/.gemini/settings.json`. + ## Everything at once ```bash diff --git a/src/growmos/cli.py b/src/growmos/cli.py index e429b36..3132fce 100644 --- a/src/growmos/cli.py +++ b/src/growmos/cli.py @@ -904,7 +904,7 @@ def build_parser() -> argparse.ArgumentParser: sp.set_defaults(fn=cmd_init) sp = sub.add_parser("integrate", help="wire growmos into an agent CLI / git hooks / CI") - sp.add_argument("target", help="claude|codex|gemini|cursor|grok|generic|file|hooks|ci|all") + sp.add_argument("target", help="claude|codex|gemini|cursor|grok|generic|mcp|file|hooks|ci|all") sp.add_argument("--file", help="instructions file to append the growmos block to (target=file)") sp.set_defaults(fn=cmd_integrate) diff --git a/src/growmos/integrate.py b/src/growmos/integrate.py index c5f7907..a01b457 100644 --- a/src/growmos/integrate.py +++ b/src/growmos/integrate.py @@ -28,7 +28,7 @@ TPL = Path(__file__).parent / "templates" / "integrations" START = "" -TARGETS = ["claude", "codex", "gemini", "cursor", "grok", "generic", "hooks", "ci", "all"] +TARGETS = ["claude", "codex", "gemini", "cursor", "grok", "generic", "mcp", "hooks", "ci", "all"] def _block() -> str: @@ -80,8 +80,8 @@ def _merge_hooks(settings: Dict[str, Any]) -> bool: return changed -def _merge_mcp(root: Path) -> str: - path = root / ".mcp.json" +def _merge_mcp(root: Path, path: Path = None) -> str: + path = path or (root / ".mcp.json") data = read_json(path, {}) or {} servers = data.setdefault("mcpServers", {}) if "growmos" in servers: @@ -126,6 +126,12 @@ def integrate(root: Path, target: str, file: str = "") -> List[str]: p.write_text("---\ndescription: growmos living knowledge graph protocol\nalwaysApply: true\n---\n\n" + block, encoding="utf-8") out.append(".cursor/rules/growmos.mdc: written") + out.append(f".cursor/mcp.json: {_merge_mcp(root, root / '.cursor' / 'mcp.json')} (growmos MCP server)") + elif t == "mcp": + out.append(f".mcp.json: {_merge_mcp(root)} (Claude Code / Codex / Grok / any MCP client)") + if (root / ".cursor").exists(): + out.append(f".cursor/mcp.json: {_merge_mcp(root, root / '.cursor' / 'mcp.json')}") + out.append(' other clients: add {"mcpServers": {"growmos": {"command": "growmos", "args": ["mcp"]}}} to their MCP config') elif t == "file": if not file: raise ValueError("--file PATH is required for target 'file'")