{
  "markdown": "# xojo-mcp\n\nAn MCP (Model Context Protocol) server that gives AI assistants direct control\nover the Xojo IDE. Communicates via stdin/stdout JSON-RPC and forwards IDE\ncommands via a Unix domain socket to the running Xojo IDE process.\n\n> **Note on the name.** This crate was previously published as `xmcp`. It was\n> renamed to `xojo-mcp` to avoid confusion with X's (formerly Twitter)\n> unrelated `xmcp` framework. The installed **binary is still `xmcp`**, so\n> existing configs keep working.\n\n> **macOS only.** xojo-mcp talks to the Xojo IDE over its macOS-specific Unix\n> domain socket (`/tmp/XojoIDE`, or `/tmp/$XOJO_IPCPATH` — see\n> [Choosing which IDE to talk to](#choosing-which-ide-to-talk-to)). Windows and\n> Linux are not supported and there is no plan to add support — the underlying\n> IDE IPC mechanism doesn't exist on those platforms.\n\n## Attribution\n\nThis is a Rust port of [XMCP](https://github.com/o3jvind/XMCP) by\nØjvind Søgaard Andersen, originally written in Xojo. The original project\nis licensed under the MIT License.\n\n## Quick start\n\n### 1. Build and install\n\n```sh\ngit clone https://codeberg.org/brechanbech/xojo-mcp.git\ncd xojo-mcp\ncargo install --path .\n```\n\nThis installs the `xmcp` binary to `~/.cargo/bin/xmcp`. If `~/.cargo/bin`\nis already on your `PATH` (the Rust installer adds it by default), you're\ndone. Verify with:\n\n```sh\nxmcp --help\n```\n\n**Optional:** `usage-guide.md` is embedded into the binary at compile\ntime, so the MCP resource is always available out of the box. If you\nwant to tweak the guide without rebuilding, drop a copy next to the\nbinary — xmcp will prefer the file on disk over the embedded fallback:\n\n```sh\ncp usage-guide.md ~/.cargo/bin/\n```\n\n### 2. Add to Claude Code\n\nRun this from any terminal:\n\n```sh\nclaude mcp add xmcp -- xmcp\n```\n\nOr add it manually to your Claude Code settings. Open the MCP config file\n(on macOS: `~/.claude/settings.json` or the project-level\n`.claude/settings.json`) and add:\n\n```json\n{\n  \"mcpServers\": {\n    \"xmcp\": {\n      \"command\": \"xmcp\",\n      \"args\": []\n    }\n  }\n}\n```\n\nTo enable verbose logging (written to stderr, visible in the Claude Code\nMCP log):\n\n```json\n{\n  \"mcpServers\": {\n    \"xmcp\": {\n      \"command\": \"xmcp\",\n      \"args\": [\"-v\"]\n    }\n  }\n}\n```\n\n### 3. Use it\n\n1. Start the Xojo IDE and open your project\n2. Start a Claude Code session in the project directory\n3. Claude will automatically discover the 26 xmcp tools and the usage guide\n\n### 4. Download Xojo documentation (recommended)\n\nThe documentation tools (`search_docs`, `lookup_class`, `list_doc_topics`) need\na local copy of the Xojo docs. A script is included to download them from\n`docs.xojo.com`:\n\n```sh\nscripts/update-xojo-docs.sh\n```\n\nThis downloads `llms.txt` and `llms-full.txt` from `docs.xojo.com` and splits\nthe full documentation into individual class files under `_sources/`. Everything\ngoes into `~/Library/Application Support/Xojo/Xojo/<version>/Documentation/`,\nwhich xmcp auto-detects at startup. Re-run the script periodically to pick up\ndocumentation updates — Xojo refreshes these files when new releases are\npublished.\n\nTo use a custom location instead:\n\n```sh\nscripts/update-xojo-docs.sh /path/to/docs\nxmcp --docs-path /path/to/docs\n```\n\n## Read-only mode\n\nBy default, an assistant connected to xmcp can change your project: it can\nrewrite code, create new items, save, and revert. That is the point of the tool\n— but it is not always what you want. If you only want an assistant to *look\nat* a project — read the code, build it, run it, analyse it, answer questions,\nconsult the documentation — without any possibility of it modifying or\noverwriting your source, start the server in **read-only mode**.\n\nRead-only mode is enforced by the server itself, not by asking the assistant to\nbehave. It is the single most important safety control in xmcp, so it is worth\nunderstanding exactly how it works.\n\n### Enabling it\n\nThe simplest way is the `--read-only` flag on the launch command. In Claude\nCode:\n\n```sh\nclaude mcp add xmcp -- xmcp --read-only\n```\n\nOr, in a Claude Code settings file (`~/.claude/settings.json`, or the\nproject-level `.claude/settings.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"xmcp\": {\n      \"command\": \"xmcp\",\n      \"args\": [\"--read-only\"]\n    }\n  }\n}\n```\n\nIf your MCP client prefers environment variables to command-line arguments, the\nvariable `XMCP_READ_ONLY=1` does exactly the same thing. Accepted truthy values\nare `1`, `true`, `yes`, and `on` (case-insensitive):\n\n```json\n{\n  \"mcpServers\": {\n    \"xmcp\": {\n      \"command\": \"xmcp\",\n      \"args\": [],\n      \"env\": { \"XMCP_READ_ONLY\": \"1\" }\n    }\n  }\n}\n```\n\nIf both the flag and the environment variable are present, either one enabling\nread-only mode is enough — there is no way to *disable* it from the other.\n\n### It is set at launch, not in the conversation\n\nThis is the part newcomers most often get wrong. **You do not put the assistant\ninto read-only mode by telling it to \"stick to reading\" in the chat.** A prompt\nis a request the model can forget, misinterpret, or be argued out of — and it\ndoes nothing at all if the model simply calls a write tool anyway. That is the\nweakness read-only mode exists to remove.\n\nRead-only mode is a property of *how the server was started*. You set it once,\nin your MCP client's configuration, before the session begins. From that point\non, for the entire lifetime of that server process, the restriction holds\nregardless of anything typed into the conversation. Neither you nor the\nassistant can toggle it mid-session; to change modes you change the\nconfiguration and reconnect the server. (Restarting the server is required for a\nchange to take effect — a server that is already running will not pick up a new\nflag or environment variable.)\n\n### What it actually blocks\n\nRead-only mode disables the six tools that modify the project:\n\n| Tool | What it would otherwise do |\n| --- | --- |\n| `set_code` | Overwrite the code of a method, property, or other item |\n| `edit_code` | Replace an exact substring within an item's code |\n| `set_selected_text` | Replace the current text selection in the code editor |\n| `create_project_item` | Add a new class, module, window, or other item |\n| `revert_project` | Discard unsaved changes back to the last save |\n| `save_project` | Write the project's current in-memory state to disk |\n\nEverything else remains fully available — navigating and listing items, reading\ncode (`get_code`), building (`build_project`), running (`run_project`),\nstopping, compile-checking (`analyze_project`), inspecting descriptions and\nconstants, the debug log tools, and all three documentation tools. In short:\nbrowse, build, run, and analyse — just no writing.\n\nNote that build and run are deliberately *not* blocked. They do not alter your\nsource; they exercise it. `build_project` writes a compiled app into the build\nfolder and `run_project` launches a debug session, but neither touches the\nproject itself, so both are considered read-only-safe.\n\n### How the enforcement works\n\nThe restriction is applied in two independent layers, so it holds even if a\nclient or model misbehaves:\n\n1. **The blocked tools are removed from the tool list.** When the assistant asks\n   the server what tools exist (`tools/list`), the six mutating tools are\n   filtered out. The model never sees them, so it cannot choose to call\n   something it does not know exists. This is what makes the mode effective in\n   practice rather than merely defensive.\n2. **Any call to a blocked tool is rejected.** If a request to one of the six\n   arrives anyway — a stale tool list, a hand-crafted call, a buggy client — the\n   server refuses it before the request ever reaches the IDE, returning a clear\n   error explaining that the tool is disabled in read-only mode.\n\nThe assistant is also told, via the embedded usage guide, that when it sees a\nreduced tool set the project is intentionally read-only and it should work\nwithin the available tools rather than trying to route around the restriction.\n\n### Running both modes at once\n\nBecause the mode is fixed per server, you can register xmcp twice under\ndifferent names and choose per task which one to point the assistant at — for\nexample a normal `xmcp` for editing sessions and a separate `xmcp-ro` for\nreview-only sessions:\n\n```sh\nclaude mcp add xmcp    -- xmcp\nclaude mcp add xmcp-ro -- xmcp --read-only\n```\n\n## Choosing which IDE to talk to\n\nThe IDE listens on a socket whose path is a temporary directory plus the name\n`XojoIDE` — or the value of `XOJO_IPCPATH`, when that variable is set in the\nIDE's environment. Setting it to a unique name per instance is Xojo's supported\nway of running several IDEs (say, two releases side by side) and addressing each\none independently:\n\n```sh\nenv XOJO_IPCPATH=Xojo2026r2_1 \"/Applications/Xojo 2026 Release 2.1/Xojo.app/Contents/MacOS/Xojo\" &\n```\n\nxmcp must be given the same value, otherwise it connects to whichever instance\nowns the default `XojoIDE` socket:\n\n```json\n{\n  \"mcpServers\": {\n    \"xmcp-2026r2-1\": {\n      \"command\": \"xmcp\",\n      \"args\": [],\n      \"env\": { \"XOJO_IPCPATH\": \"Xojo2026r2_1\" }\n    }\n  }\n}\n```\n\nOnly `a-z`, `A-Z`, `0-9` and `_` are valid in the name; xmcp ignores a value\ncontaining anything else (with a warning on stderr) and falls back to `XojoIDE`.\nCandidate directories are `/tmp` first — what the IDE itself prefers — then\n`$TMPDIR`, which is where the IDE falls back when `/tmp` is not writable.\n\nIf you only ever run one IDE at a time, ignore all of this: the default works.\n\n## Requirements\n\n- macOS (the Xojo IDE IPC socket is macOS-specific)\n- Rust toolchain (`rustup` — https://rustup.rs)\n- Xojo IDE must be running with a project open before using any tools\n\n## Options\n\n```\nxmcp [OPTIONS]\n```\n\n- `--read-only` — Read-only mode: hide and reject every tool that modifies the\n  project. Can also be enabled with `XMCP_READ_ONLY=1`. See\n  [Read-only mode](#read-only-mode) for the full description.\n- `-v`, `--verbose` — Enable verbose logging to stderr\n- `-d`, `--docs-path <PATH>` — Path to Xojo documentation directory (auto-detected if omitted)\n- `-V`, `--version` — Print version\n- `-h`, `--help` — Print help\n\nEnvironment: `XMCP_READ_ONLY` (see above) and `XOJO_IPCPATH`, which selects the\nIDE instance to connect to — see\n[Choosing which IDE to talk to](#choosing-which-ide-to-talk-to).\n\n## Differences from the original\n\nThis is a drop-in replacement — it exposes all 25 tools from the original with\nidentical names and parameters (`analyze_project` and `debug_control` were the\nlast two ported, bringing it to full parity), plus one new tool, `edit_code`,\nfor 26 in total. Same IDE Communicator Protocol v2 over the Unix domain socket,\nupdated to MCP protocol version `2025-11-25`.\n\nNotable differences:\n\n- **Binary name** is `xmcp`\n- **`edit_code` — targeted str_replace-style editing** — replaces an exact\n  substring within an item's code in one call (read → replace → write, all\n  server-side), instead of resending the whole item via `set_code`. The\n  original has no such tool, forcing whole-item rewrites or shell-based text\n  munging for small edits.\n- **Writes code directly — no shell/base64 marshalling** — `set_code` and\n  `edit_code` send source straight through the IPC, with all IDE-script string\n  escaping (quotes, newlines, special characters) handled server-side. There is\n  no need to smuggle code across the bridge by hand — the base64\n  encode-on-agent / decode-on-Mac / run-via-shell workflow the original forces\n  for file edits simply does not exist here.\n- **Enforced read-only mode** — `--read-only` / `XMCP_READ_ONLY` removes and\n  rejects the mutating tools at the server. The original has no built-in\n  enforcement; it can only be asked, via the prompt, not to write. See\n  [Read-only mode](#read-only-mode).\n- **No Xojo license required** — builds with the standard Rust toolchain\n- **usage-guide.md has a compiled-in fallback** — the original fails silently\n  if the file is missing next to the binary; the Rust version embeds a copy\n  at compile time so the MCP resource is always available. A file on disk\n  still takes priority, so you can edit it without rebuilding.\n- **CLI parsing** uses [clap](https://crates.io/crates/clap) rather than the\n  original's custom OptionParser. The flags are the same.\n\n## Tools\n\nxmcp exposes 26 tools across four categories:\n\n**IDE tools (20):** list_project_items, get_current_location, select_project_item,\nget_code, set_code, edit_code, get_selected_text, set_selected_text, build_project,\nrun_project, stop_project, create_project_item, run_ide_script, get_project_info,\nrevert_project, save_project, get_item_description, constant_value,\nanalyze_project, debug_control\n\n**Documentation tools (3):** search_docs, lookup_class, list_doc_topics\n\n**Debug tools (2):** get_debug_log, get_system_log\n\n**Cost awareness (1):** estimate_request_cost\n\n## License\n\nMIT — see [LICENSE.md](LICENSE.md) for details.\n\n## MCP registry\n\nOwnership-verification token for the [MCP registry](https://registry.modelcontextprotocol.io)\n(read from this crate's rendered README on crates.io):\n\n> Registry ownership token: `mcp-name: io.github.brechanbech/xojo-mcp`\n",
  "bytes": 13153,
  "sha": "5c35bae73af25cf8e89a788aa677e4f5c56b9204efac9f9a822d932ed070cc0d",
  "repo_slug": "brechanbech/xojo-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_brechanbech_xojo_mcp_786ede47/readme"
}