# @rotifer/mcp-server [![npm](https://img.shields.io/npm/v/@rotifer/mcp-server)](https://www.npmjs.com/package/@rotifer/mcp-server) [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE) [![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org/) [![MCP](https://img.shields.io/badge/MCP-Compatible-indigo)](https://modelcontextprotocol.io) **Build, compose, and run AI agents — directly from your IDE.** Search genes, create agents with composable genomes, run pipelines in a WASM sandbox, and compete in the Arena. Zero config. Works with Cursor, Claude Desktop, Windsurf, and any MCP-compatible client.
--- ## Quick Start ### Cursor Add to `.cursor/mcp.json`: ```json { "mcpServers": { "rotifer": { "command": "npx", "args": ["@rotifer/mcp-server"] } } } ``` ### Claude Desktop Add to `claude_desktop_config.json`: ```json { "mcpServers": { "rotifer": { "command": "npx", "args": ["@rotifer/mcp-server"] } } } ``` ### Windsurf / Other MCP Clients Use the same `npx` command — any client that supports MCP stdio transport will work. ## What Can It Do? ### Create and run an agent in one conversation ``` You: "Build me an agent for code security scanning" AI: → create_agent({ agent_name: "sec-bot", gene_ids: ["security-scanner", "genesis-code-format"], composition: "Seq" }) Agent 'sec-bot' created with 2-gene Seq genome. You: "Run it on my project" AI: → agent_run({ agent_name: "sec-bot", input: "{\"path\":\"./src\"}" }) Pipeline complete — 3 findings, 0 critical. ``` ### Search, compare, and compose genes ``` You: "Find the best gene for web search" AI: → search_genes({ query: "web search" }) Found 8 genes. Top match: genesis-web-search (F(g) = 0.87, Native) You: "Compare it against the lite version" AI: → compare_genes({ gene_ids: ["...", "..."] }) Side-by-side: success rate, latency, fitness breakdown ``` ### Full gene lifecycle from your IDE ``` You: "Wrap my function as a gene" AI: → wrap_gene({ gene_name: "my-search", domain: "search.web", fidelity: "Wrapped" }) → compile_gene({ gene_name: "my-search" }) → test_gene({ gene_name: "my-search", compliance: true }) → publish_gene({ gene_name: "my-search", changelog: "Initial release" }) ``` ## Tools (31) ### Discovery & Analytics | Tool | Description | Key Parameters | |------|-------------|----------------| | `search_genes` | Search the Gene ecosystem by name, domain, or description | `query`, `domain`, `fidelity`, `sort` (`relevance`/`newest`/`popular`/`fitness`), `page`, `per_page` | | `get_gene_detail` | Get detailed info about a Gene (phenotype, fitness, metadata) | `gene_id`, `content_hash` (either identifies the gene) | | `get_arena_rankings` | Arena rankings for a domain, sorted by F(g) fitness | `domain`, `page`, `per_page` | | `compare_genes` | Side-by-side fitness comparison of 2–5 Genes | `gene_ids` (array) | | `get_gene_stats` | Download statistics (total, 7d, 30d, 90d) | `gene_id` | | `get_leaderboard` | Creator reputation leaderboard | `limit` | | `get_developer_profile` | Creator public profile and reputation | `username` | | `get_gene_reputation` | Detailed reputation breakdown (Arena, Usage, Stability) | `gene_id` | | `list_gene_versions` | Version history chain with changelogs | `owner`, `gene_name` | | `suggest_domain` | Suggest matching domains from the registry | `description` | ### Local Workspace | Tool | Description | Key Parameters | |------|-------------|----------------| | `list_local_genes` | Scan local workspace for installed Genes | `project_root`, `domain`, `fidelity` | | `list_local_agents` | List Agents in the local workspace | `project_root`, `state` | ### Gene Lifecycle | Tool | Description | Key Parameters | |------|-------------|----------------| | `init_gene` | Initialize a new Gene project with starter files | `gene_name`, `fidelity`, `domain`, `no_genesis` | | `scan_genes` | Scan for candidate functions or SKILL.md files | `path`, `skills`, `skills_path` | | `wrap_gene` | Wrap a function/skill as a Gene | `gene_name`, `domain`, `fidelity`, `from_skill`, `from_clawhub` | | `test_gene` | Test a Gene (schema validation + sandbox) | `gene_name`, `verbose`, `compliance` | | `compile_gene` | Compile a Gene to WASM IR | `gene_name`, `check`, `wasm_path`, `lang` | | `doctor` | Check the local TypeScript→WASM toolchain (esbuild / javy) and report what is missing — read-only; use when `compile_gene` fails | `project_root` | | `run_gene` | Execute a local Gene | `gene_name`, `input`, `verbose`, `no_sandbox`, `trust_unsigned` | | `publish_gene` | Publish to Rotifer Cloud | `gene_name`, `all`, `description`, `changelog`, `skip_arena`, `skip_security` | | `install_gene` | Install a Gene from Cloud Registry. `force` snapshots the copy it replaces | `gene_id`, `project_root`, `force` | | `rollback_gene` | Undo the last overwrite of a local Gene; call with no name to list what can be undone | `gene_name`, `project_root` | | `vg_scan` | V(g) security scan — static analysis for Gene/Skill code safety | `path`, `gene_id`, `all`, `project_root` | | `arena_submit` | Measure a local Gene in the sandbox and submit the measurement to the Arena. Scores are produced by running the Gene, never supplied by the caller | `gene_name`, `project_root` | ### Agent Composition | Tool | Description | Key Parameters | |------|-------------|----------------| | `create_agent` | Create an Agent composing multiple Genes | `agent_name`, `gene_ids`, `composition` (`Seq`/`Par`/`Cond`/`Try`/`TryPool`), `domain`, `top`, `strategy`, `par_merge` | | `agent_run` | Run a local Agent by name | `agent_name`, `input`, `verbose`, `no_sandbox` | ### Authentication & Analytics | Tool | Description | Key Parameters | |------|-------------|----------------| | `auth_status` | Check login status | — | | `login` | OAuth login (GitHub/GitLab) | `provider`, `endpoint` | | `logout` | Clear credentials | — | | `get_mcp_stats` | MCP call analytics | `days` | | `get_my_reputation` | Current user's reputation | — | ## Resources (7) MCP Resources let AI clients reference Rotifer data as context: | URI Template | Description | |---|---| | `rotifer://genes/{gene_id}/stats` | Gene download statistics | | `rotifer://genes/{gene_id}` | Gene detail + phenotype | | `rotifer://developers/{username}` | Creator profile + reputation | | `rotifer://leaderboard` | Top creators by reputation score | | `rotifer://local/genes` | Local Gene inventory | | `rotifer://local/agents` | Local Agent registry | | `rotifer://version` | MCP Server version and update availability | Each resource returns what the tool of the same job returns, so a declared tool set covers both: with `--tools=evolve`, `rotifer://genes/{gene_id}/stats`, `rotifer://developers/{username}` and `rotifer://leaderboard` disappear from the listing and are refused if read directly, because `get_gene_stats`, `get_developer_profile` and `get_leaderboard` were not asked for. `rotifer://version` always answers — it is the server describing itself, not a capability. Before 0.16.0 these were reachable whatever the tool set said. ## Prompts (4) MCP Prompts give AI clients guided workflows for common tasks: | Prompt | Description | Key Arguments | |--------|-------------|---------------| | `rotifer-hello` | Interactive agent creation — pick a template and run immediately | `template`, `input` | | `rotifer-guide` | Understand Rotifer Protocol — genes, agents, Arena, fidelity model | — | | `rotifer-architect` | Design an Agent — task-driven gene search + composition planning | `task` | | `rotifer-challenge` | Arena evaluation — submit a gene, compare with competitors | `gene` | Try asking your AI: *"Use the rotifer-hello prompt to build me an agent"* or *"Use rotifer-architect to design an agent for document Q&A"*. --- ## Architecture ``` ┌─────────────────────────────────────────────────┐ │ AI IDE (Cursor / Claude / Windsurf) │ │ │ │ "Find genes for code formatting" │ │ │ │ │ ▼ │ │ ┌─────────────────────┐ │ │ │ MCP Client │ │ │ │ (stdio transport) │ │ │ └────────┬────────────┘ │ └───────────┼─────────────────────────────────────┘ │ MCP Protocol ▼ ┌─────────────────────────────────────────────────┐ │ @rotifer/mcp-server │ │ │ │ 30 Tools 7 Resources 4 Prompts Local Scanner│ │ ┌──────────┐ ┌───────────┐ ┌────────────┐ │ │ │ discover │ │rotifer:// │ │ ./genes/ │ │ │ │ lifecycle│ │genes/stats│ │ phenotype │ │ │ │ agents │ │developers │ │ agents │ │ │ │ auth │ │leaderboard│ └────────────┘ │ │ └────┬─────┘ └─────┬─────┘ │ │ └───────┼──────────────┼────────────────┼─────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────────────────────────────────────┐ │ Rotifer Cloud API Local File System │ │ (Supabase) (genes/, .rotifer/) │ └─────────────────────────────────────────────────┘ ``` ## Configuration Zero-config by default — connects to the public Rotifer Cloud API. To use a custom endpoint, create `~/.rotifer/cloud.json`: ```json { "endpoint": "https://your-supabase-instance.supabase.co", "anonKey": "your-anon-key" } ``` Or set environment variables: ```bash ROTIFER_CLOUD_ENDPOINT=https://your-instance.supabase.co ROTIFER_CLOUD_ANON_KEY=your-anon-key ``` ### Choosing which tools to expose All thirty-one tools are available by default. `ROTIFER_MCP_TOOLS` narrows that to what a given integration actually needs — useful when the server is attached to an assistant that should not be able to publish or log in on your behalf: ```bash npx @rotifer/mcp-server --tools=evolve # the rank-and-swap preset (10 tools) npx @rotifer/mcp-server --tools=readonly # nothing that writes (14 tools) ROTIFER_MCP_TOOLS=search_genes,get_gene_detail # an exact list ROTIFER_MCP_TOOLS=evolve,vg_scan # a preset plus one ``` The flag and the variable do the same thing, and the flag wins if both are set. Both exist because callers differ in what they can reach: a shell user sets the variable, while something launching this server from a manifest controls only the command line. A declared set covers the whole surface, not just `tools/list`. Tools outside it are refused when called by name; [resources](#resources-7) that duplicate an excluded tool are dropped from the listing and refused when read; and the sandbox escape hatches below stay off unless separately declared. A restriction with an unlisted way around it is not a restriction. Tools outside the set disappear from `listTools` and are refused if called anyway. The refusal says how to add the tool back and, where one exists, the `rotifer` CLI command that does the same job — so a narrowed set is a boundary you can see and cross deliberately, not a dead end. Leave it unset and nothing changes. ### Switching off the sandbox `agent_run` and `run_gene` take `no_sandbox`, and `run_gene` also takes `trust_unsigned` — options that run Gene code as plain Node.js instead of inside the WASM sandbox. Narrowing the tool set would mean little if a tool inside the narrowed set could still do that, so these are refused unless declared at launch: ```bash npx @rotifer/mcp-server --allow=no-sandbox npx @rotifer/mcp-server --allow=no-sandbox,trust-unsigned ROTIFER_MCP_ALLOW=no-sandbox # same thing ``` Nothing is removed. The option moves from "any caller can set it" to "someone declared it at launch", and you can always do it yourself: ```bash rotifer agent run --no-sandbox rotifer run --trust-unsigned ``` What changes is that an assistant can no longer decide to unsandbox on its own. Passing `no_sandbox: false` is asking for the safe behaviour and is never refused. ### Undoing an install `install_gene` with `force` used to overwrite a Gene with no way back. It now moves the old copy into `/.snapshots/` first, and `rollback_gene` puts it back: ``` rollback_gene {} → what can be rolled back rollback_gene { gene_name: "formatter" } → restore the copy that was replaced ``` One snapshot per Gene: the next overwrite of that Gene supersedes it, and a rollback consumes it. This undoes the last upgrade rather than keeping a history — `list_gene_versions` already answers what versions exist upstream. ### Keeping the server up to date The server has always told you when it was behind — a line on stderr at startup, once a day. `self-update` is the other half: ```bash rotifer-mcp-server self-update # check, verify, install rotifer-mcp-server self-update --rollback # back to the version it replaced ``` It refuses any version npm has no [provenance attestation](https://docs.npmjs.com/generating-provenance-statements) for — this package publishes from CI with `--provenance`, so an unattested build is not one this project released. Two things worth knowing: - **A running server keeps serving the old code.** Installing replaces files on disk; it does not replace the process your editor is already talking to. Restart your MCP host afterwards. - **If you launch through `npx`, there is nothing to update.** An unpinned `npx @rotifer/mcp-server` re-resolves the latest published version on every run, so `self-update` says so and stops rather than installing a global copy that would shadow it. This is a command you run, not a tool the model can call. Updating means a global install, and a tool could not even report the result honestly — the model would say "updated" while still being served by the old process. ### Usage reporting When you are **signed in**, each tool call reports a usage record to Rotifer Cloud: the tool's name, the Gene id it acted on, whether it succeeded, how long it took, and your user id. That is what `get_mcp_stats` reads back. Running a Gene also records the invocation, which the protocol's anti-manipulation metrics depend on. It does **not** send the arguments you pass, the contents of any file, your environment variables, or your local configuration. **Signed out, no usage record is sent.** One request does go out either way: installing a Gene bumps that Gene's public install counter. It carries the Gene id and nothing else — no user id, no session, no arguments — and it is how the Arena counts installs. Until 0.15.1 nothing stopped it, and this section said "signed out, nothing is reported", which was not true of an install. `ROTIFER_TELEMETRY=0` now stops all three: ```bash ROTIFER_TELEMETRY=0 # also accepts false / off ``` The three are `logMcpCall`, `logGeneInvocation` and the `track_download` call inside `installGene`, all in [`src/cloud.ts`](src/cloud.ts) — short enough to read in full. Nothing else here reports anything on its own: every other outbound call in this server is a tool you invoked doing its job — a query, a publish, a sign-in — plus the WASM artifact download and one npm version check per day. ## Requirements - Node.js >= 20 ## Pair with the CLI This MCP server works best alongside the [Rotifer CLI](https://github.com/rotifer-protocol/rotifer-playground). The CLI provides the local runtime (WASM sandbox, Arena engine, IR compiler) while the MCP server exposes it all to your AI assistant: ```bash npm install -g @rotifer/playground rotifer init my-agent && cd my-agent rotifer hello --template quality-advisor # your first Agent workspace in seconds ``` ## Links - [Rotifer Protocol](https://rotifer.dev) — Main site - [MCP Setup Guide](https://rotifer.dev/docs/guides/mcp-setup) — Step-by-step setup - [Gene Marketplace](https://rotifer.ai) — Browse and discover Genes - [CLI Playground](https://github.com/rotifer-protocol/rotifer-playground) — Build and test Genes locally - [Protocol Specification](https://github.com/rotifer-protocol/rotifer-spec) — Formal spec ## License Apache-2.0