Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .cursor/environment.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
"mcpServerAllowlist": [
{
"name": "diffusers-docs",
"command": "python3"
},
{
"name": "diffusers-docs-mcp",
"command": "diffusers-docs-mcp"
}
]
Expand Down
27 changes: 8 additions & 19 deletions .cursor/install-docs-mcp.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#!/usr/bin/env bash
# Put `diffusers-docs-mcp` on PATH and copy the relative launcher into Cloud
# workspace roots so `python3 -u .cursor/mcp-diffusers-docs.py` resolves when
# stdio is spawned from /agent or /workspace (not the git repo).
# Put `diffusers-docs-mcp` on PATH. Do not rely on copying into /agent/.cursor
# — that directory is root-owned on Cloud. mcp.json boots via python3 -c and
# globs /agent/repos/*/.cursor/mcp-diffusers-docs.py instead.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SRC="$ROOT/.cursor/mcp-diffusers-docs.py"
chmod +x "$SRC" "$ROOT/.cursor/mcp-diffusers-docs.sh" "$ROOT/.cursor/install-docs-mcp.sh"
chmod +x "$ROOT/.cursor/mcp_stdio_boot.py" 2>/dev/null || true

write_shim() {
local dest="$1"
Expand All @@ -15,13 +16,7 @@ write_shim() {
exec python3 -u "$SRC" --serve "\$@"
EOF
chmod +x "$dest"
}

copy_workspace_launcher() {
local dest_dir="$1"
mkdir -p "$dest_dir" 2>/dev/null || return 0
cp "$SRC" "$dest_dir/mcp-diffusers-docs.py" 2>/dev/null || return 0
chmod +x "$dest_dir/mcp-diffusers-docs.py" 2>/dev/null || true
echo "PATH shim: $dest"
}

write_shim "$HOME/.local/bin/diffusers-docs-mcp"
Expand All @@ -32,17 +27,11 @@ for rc in "$HOME/.profile" "$HOME/.bashrc"; do
fi
echo "$path_line" >> "$rc"
done
if mkdir -p /usr/local/bin 2>/dev/null && [ -w /usr/local/bin ]; then
if [ -d /usr/local/bin ] && [ -w /usr/local/bin ]; then
write_shim /usr/local/bin/diffusers-docs-mcp || true
fi

for ws in /agent /workspace "${CURSOR_WORKSPACE:-}" "${CURSOR_PROJECT_DIR:-}"; do
if [ -n "$ws" ] && [ -d "$ws" ]; then
copy_workspace_launcher "$ws/.cursor" || true
fi
done

echo "docs MCP launcher: $SRC"
echo "PATH command: ${HOME}/.local/bin/diffusers-docs-mcp"
echo "Cloud dropdown: diffusers-docs-mcp"
echo " (or: python3 -u .cursor/mcp-diffusers-docs.py)"
echo "Cloud dropdown: python3 (mcp.json -c glob) or diffusers-docs-mcp"
echo "Allowlist both python3 (mcp.json) and diffusers-docs-mcp (PATH shim)"
6 changes: 5 additions & 1 deletion .cursor/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
"diffusers-docs": {
"type": "stdio",
"command": "python3",
"args": ["-u", ".cursor/mcp-diffusers-docs.py"],
"args": [
"-u",
"-c",
"import os, sys; from pathlib import Path; opts = [Path('.cursor/mcp-diffusers-docs.py')]; repos = Path('/agent/repos');\nopts.extend(repos.glob('*/.cursor/mcp-diffusers-docs.py')) if repos.is_dir() else None; opts.extend(repos.glob('*/ramp-kit/.cursor/mcp-diffusers-docs.py')) if repos.is_dir() else None\nfor p in opts:\n if p.is_file():\n os.execv(sys.executable, [sys.executable, '-u', str(p.resolve()), '--serve'])\nsys.exit('diffusers-docs MCP: launcher not found')"
],
"env": {
"PYTHONUNBUFFERED": "1"
}
Expand Down
43 changes: 43 additions & 0 deletions .cursor/mcp_stdio_boot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python3
"""Cwd-independent stdio entry for diffusers-docs MCP.

Cloud Agent stdio is spawned from `/agent` (not the git repo) and cannot
create `/agent/.cursor`. Desktop Cursor uses the repo root as cwd. This
file is the `python3 -c` body in `.cursor/mcp.json` (keep them in sync)
and is also runnable as `python3 -u .cursor/mcp_stdio_boot.py`.
"""
from __future__ import annotations

import os
import sys
from pathlib import Path


def _launchers():
yield Path(".cursor") / "mcp-diffusers-docs.py"
repos = Path("/agent/repos")
if repos.is_dir():
yield from repos.glob("*/.cursor/mcp-diffusers-docs.py")
yield from repos.glob("*/ramp-kit/.cursor/mcp-diffusers-docs.py")
here = Path(__file__).resolve().parent / "mcp-diffusers-docs.py"
yield here


def main() -> int:
extra = [a for a in sys.argv[1:] if a != "--serve"]
for raw in _launchers():
path = Path(raw)
if path.is_file():
os.execv(
sys.executable,
[sys.executable, "-u", str(path.resolve()), "--serve", *extra],
)
sys.stderr.write(
"diffusers-docs MCP: launcher not found "
f"(cwd={Path.cwd()} file={Path(__file__).resolve() if '__file__' in dir() else 'stdin'}).\n"
)
return 1


if __name__ == "__main__":
raise SystemExit(main())
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ doctor:
@test -f tools/attach_library.py && test -f overlay/OVERLAY.md \
&& test -f overlay/mcp.json && test -f overlay/mcp.optional.json \
|| (echo "Missing overlay attach tooling"; exit 1)
@$(PYTHON) -c "import json, pathlib; c=json.loads(pathlib.Path('overlay/mcp.json').read_text()); s=c['mcpServers']; assert 'diffusers-docs' in s and 'huggingface' not in s, c; assert s['diffusers-docs']['args']==['-u','.cursor/mcp-diffusers-docs.py'], s" \
|| (echo "overlay/mcp.json must be stdio diffusers-docs only (no Hub HTTP)"; exit 1)
@$(PYTHON) -c "import json, pathlib; c=json.loads(pathlib.Path('overlay/mcp.json').read_text()); s=c['mcpServers']; assert 'diffusers-docs' in s and 'huggingface' not in s, c; d=s['diffusers-docs']; assert d['command']=='python3' and '-c' in d['args'] and 'mcp-diffusers-docs.py' in d['args'][-1], d" \
|| (echo "overlay/mcp.json must be cwd-independent python3 -c stdio (no Hub HTTP)"; exit 1)
@$(PYTHON) -c "import json, pathlib; s=json.loads(pathlib.Path('overlay/mcp.optional.json').read_text())['mcpServers']; assert 'diffusers-docs' in s and 'huggingface' in s, s" \
|| (echo "overlay/mcp.optional.json must list opt-in servers"; exit 1)
@$(PYTHON) -c "import json,pathlib; cmds={e['command'] for e in json.loads(pathlib.Path('.cursor/environment.json').read_text())['mcpServerAllowlist']}; assert {'python3','diffusers-docs-mcp'} <= cmds, cmds" \
|| (echo "kit environment.json allowlist must include python3 and diffusers-docs-mcp"; exit 1)
@$(PYTHON) -c "import json,pathlib; cmds={e['command'] for e in json.loads(pathlib.Path('overlay/environment.json').read_text())['mcpServerAllowlist']}; assert {'python3','diffusers-docs-mcp'} <= cmds, cmds" \
|| (echo "overlay environment.json allowlist must include python3 and diffusers-docs-mcp"; exit 1)
@$(PYTHON) tools/docs_mcp_server.py --selftest >/dev/null
@test -f tools/grokbot_sim.py && test -f tools/verify_scheduler_contract.py \
&& test -f agents/grokbot-profiles.md && test -f .cursor/agents/grokbot-qa.md \
Expand Down
2 changes: 1 addition & 1 deletion docs/LIVE_DEMO.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ Two files, two launch targets:

| Launch on | File | What install / start do |
|-----------|------|-------------------|
| **This kit** | `.cursor/environment.json` | `install`: `.cursor/cloud-install.sh` (pyyaml, CPU torch, diffusers, `diffusers-docs-mcp` PATH shim, MCP `--selftest`). `start`: re-run the shim only (snapshot boots skip `install`). Allowlist command: `diffusers-docs-mcp`. Declares the fork as a repo dependency. |
| **This kit** | `.cursor/environment.json` | `install`: `.cursor/cloud-install.sh` (pyyaml, CPU torch, diffusers, `diffusers-docs-mcp` PATH shim, MCP `--selftest`). `start`: re-run the shim only (snapshot boots skip `install`). Allowlist commands: `python3` (mcp.json) and `diffusers-docs-mcp`. Declares the fork as a repo dependency. |
| **The fork** | `overlay/environment.json` (copied to fork `.cursor/environment.json` by `make attach`) | Clones this kit to `ramp-kit/` if missing, then the same `cloud-install.sh`. `start` refreshes `diffusers-docs-mcp`. Fork `.cursor/mcp.json` is stdio `diffusers-docs` only (no Hub HTTP). |

Dry-run locally (does not boot a Cloud VM):
Expand Down
9 changes: 6 additions & 3 deletions overlay/OVERLAY.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ Do not copy `ramp-kit/examples/candidate_scheduler/`.

`.cursor/mcp.json` ships **stdio `diffusers-docs` only** (`python3 -u
.cursor/mcp-diffusers-docs.py`). Do not enable Hub HTTP MCP (OAuth). Cloud
dropdown: `diffusers-docs-mcp` (PATH shim from `install-docs-mcp.sh`) or the
same python3 command. The launcher finds `ramp-kit/tools/docs_mcp_server.py`
from `/agent` as well as the repo root.
dropdown: `diffusers-docs-mcp` (PATH shim from `install-docs-mcp.sh`) or
`python3 -u .cursor/mcp-diffusers-docs.py`. Cloud `mcpServerAllowlist` must
permit **both** `python3` (what `.cursor/mcp.json` spawns) and
`diffusers-docs-mcp`. The launcher finds `ramp-kit/tools/docs_mcp_server.py`
from `/agent` as well as the repo root. `start` copies the relative launcher
into `/agent/.cursor/` so that python3 spawn works.

Hub HTTP and extra servers stay in `.cursor/mcp.optional.json`.

Expand Down
4 changes: 4 additions & 0 deletions overlay/environment.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
"mcpServerAllowlist": [
{
"name": "diffusers-docs",
"command": "python3"
},
{
"name": "diffusers-docs-mcp",
"command": "diffusers-docs-mcp"
}
]
Expand Down
6 changes: 5 additions & 1 deletion overlay/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
"diffusers-docs": {
"type": "stdio",
"command": "python3",
"args": ["-u", ".cursor/mcp-diffusers-docs.py"],
"args": [
"-u",
"-c",
"import os, sys; from pathlib import Path; opts = [Path('.cursor/mcp-diffusers-docs.py')]; repos = Path('/agent/repos');\nopts.extend(repos.glob('*/.cursor/mcp-diffusers-docs.py')) if repos.is_dir() else None; opts.extend(repos.glob('*/ramp-kit/.cursor/mcp-diffusers-docs.py')) if repos.is_dir() else None\nfor p in opts:\n if p.is_file():\n os.execv(sys.executable, [sys.executable, '-u', str(p.resolve()), '--serve'])\nsys.exit('diffusers-docs MCP: launcher not found')"
],
"env": {
"PYTHONUNBUFFERED": "1"
}
Expand Down
6 changes: 5 additions & 1 deletion overlay/mcp.optional.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
"diffusers-docs": {
"type": "stdio",
"command": "python3",
"args": ["-u", ".cursor/mcp-diffusers-docs.py"],
"args": [
"-u",
"-c",
"import os, sys; from pathlib import Path; opts = [Path('.cursor/mcp-diffusers-docs.py')]; repos = Path('/agent/repos');\nopts.extend(repos.glob('*/.cursor/mcp-diffusers-docs.py')) if repos.is_dir() else None; opts.extend(repos.glob('*/ramp-kit/.cursor/mcp-diffusers-docs.py')) if repos.is_dir() else None\nfor p in opts:\n if p.is_file():\n os.execv(sys.executable, [sys.executable, '-u', str(p.resolve()), '--serve'])\nsys.exit('diffusers-docs MCP: launcher not found')"
],
"env": {
"PYTHONUNBUFFERED": "1"
}
Expand Down
78 changes: 72 additions & 6 deletions tests/test_tooling.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ def test_overlay_mcp_json_is_stdio_docs_only(self):
stdio = servers["diffusers-docs"]
self.assertEqual(stdio.get("type"), "stdio")
self.assertEqual(stdio["command"], "python3")
self.assertEqual(stdio["args"], ["-u", ".cursor/mcp-diffusers-docs.py"])
self.assertIn("-c", stdio["args"])
self.assertIn("mcp-diffusers-docs.py", stdio["args"][-1])
self.assertIn("/agent/repos", stdio["args"][-1])

def test_overlay_mcp_optional_lists_opt_in_servers(self):
raw = (ROOT / "overlay" / "mcp.optional.json").read_text()
Expand All @@ -149,7 +151,8 @@ def test_overlay_mcp_optional_lists_opt_in_servers(self):
stdio = servers["diffusers-docs"]
self.assertEqual(stdio.get("type"), "stdio")
self.assertEqual(stdio["command"], "python3")
self.assertEqual(stdio["args"], ["-u", ".cursor/mcp-diffusers-docs.py"])
self.assertIn("-c", stdio["args"])
self.assertIn("mcp-diffusers-docs.py", stdio["args"][-1])
self.assertEqual(servers["huggingface"].get("url"), "https://huggingface.co/mcp")

def test_attach_copies_stdio_default_and_optional(self):
Expand All @@ -161,6 +164,65 @@ def test_attach_copies_stdio_default_and_optional(self):
)


class TestCloudMcpAllowlist(unittest.TestCase):
"""Cloud spawn uses mcp.json's python3; allowlisting only the PATH shim blocks it."""

def _allowlist_commands(self, path: Path):
cfg = json.loads(path.read_text())
return [entry["command"] for entry in cfg["mcpServerAllowlist"]]

def test_kit_and_overlay_allowlist_match_mcp_json_command(self):
for path in (
ROOT / ".cursor" / "environment.json",
ROOT / "overlay" / "environment.json",
):
cmds = self._allowlist_commands(path)
self.assertIn("python3", cmds, path)
self.assertIn("diffusers-docs-mcp", cmds, path)

def test_install_script_writes_path_shim(self):
with tempfile.TemporaryDirectory() as td:
home = Path(td) / "home"
home.mkdir()
proc = subprocess.run(
["bash", str(ROOT / ".cursor" / "install-docs-mcp.sh")],
cwd=ROOT,
env={
**os.environ,
"HOME": str(home),
"PATH": "/usr/bin:/bin",
},
capture_output=True,
text=True,
check=False,
)
self.assertEqual(proc.returncode, 0, proc.stderr + proc.stdout)
self.assertTrue((home / ".local" / "bin" / "diffusers-docs-mcp").is_file())

def test_mcp_json_handshake_from_agent_cwd(self):
"""Cloud stdio cwd is /agent; relative .cursor/... must not be required."""
cfg = json.loads((ROOT / ".cursor" / "mcp.json").read_text())
server = cfg["mcpServers"]["diffusers-docs"]
reqs = [
{"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": {"protocolVersion": "2025-11-25", "capabilities": {}}},
{"jsonrpc": "2.0", "method": "notifications/initialized"},
{"jsonrpc": "2.0", "id": 2, "method": "tools/list"},
]
payload = "".join(json.dumps(r, separators=(",", ":")) + "\n" for r in reqs)
proc = subprocess.run(
[server["command"], *server["args"]],
cwd="/agent",
input=payload.encode("utf-8"),
capture_output=True,
timeout=10,
check=False,
)
self.assertEqual(proc.returncode, 0, proc.stderr.decode("utf-8", "replace"))
self.assertIn(b"search_docs", proc.stdout)
self.assertNotIn(b"Content-Length", proc.stdout)


class TestMcpLauncher(unittest.TestCase):
def test_project_mcp_json_has_no_workspace_folder_var(self):
raw = (ROOT / ".cursor" / "mcp.json").read_text()
Expand All @@ -170,9 +232,11 @@ def test_project_mcp_json_has_no_workspace_folder_var(self):
server = cfg["mcpServers"]["diffusers-docs"]
self.assertEqual(server.get("type"), "stdio")
self.assertEqual(server["command"], "python3")
self.assertEqual(server["args"], ["-u", ".cursor/mcp-diffusers-docs.py"])
self.assertIn("-c", server["args"])
self.assertIn("/agent/repos", server["args"][-1])
self.assertTrue((ROOT / ".cursor" / "mcp-diffusers-docs.py").is_file())
self.assertTrue((ROOT / ".cursor" / "mcp-diffusers-docs.sh").is_file())
self.assertTrue((ROOT / ".cursor" / "mcp_stdio_boot.py").is_file())
self.assertTrue((ROOT / ".cursor" / "commands" / "search-docs.md").is_file())
self.assertTrue((ROOT / ".cursor" / "skills" / "search-docs" / "SKILL.md").is_file())

Expand Down Expand Up @@ -683,11 +747,13 @@ def test_attach_writes_stdio_docs_mcp(self):
cfg = json.loads((fake / ".cursor" / "mcp.json").read_text())
self.assertIn("diffusers-docs", cfg.get("mcpServers", {}))
self.assertNotIn("huggingface", cfg.get("mcpServers", {}))
self.assertEqual(
cfg["mcpServers"]["diffusers-docs"]["args"],
["-u", ".cursor/mcp-diffusers-docs.py"],
self.assertIn("-c", cfg["mcpServers"]["diffusers-docs"]["args"])
self.assertIn(
"/agent/repos",
cfg["mcpServers"]["diffusers-docs"]["args"][-1],
)
self.assertTrue((fake / ".cursor" / "mcp.optional.json").is_file())
self.assertTrue((fake / ".cursor" / "mcp_stdio_boot.py").is_file())
self.assertNotIn("AGENTS.md", [p.name for p in fake.iterdir()])
wf = (fake / ".github" / "workflows" / "ramp-kit-overlay.yml").read_text()
self.assertIn("ramp-kit-overlay", wf)
Expand Down
7 changes: 6 additions & 1 deletion tools/attach_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ def copy_overlay(target: Path) -> None:

shutil.copy2(overlay / "mcp.json", cursor / "mcp.json")
shutil.copy2(overlay / "mcp.optional.json", cursor / "mcp.optional.json")
for name in ("hooks.json", "mcp-diffusers-docs.py", "mcp-diffusers-docs.sh"):
for name in (
"hooks.json",
"mcp-diffusers-docs.py",
"mcp-diffusers-docs.sh",
"mcp_stdio_boot.py",
):
src = KIT / ".cursor" / name
if src.exists():
shutil.copy2(src, cursor / name)
Expand Down
Loading