Skip to main content
Glama

cloudroom-mcp

English | 한국어

Version 0.1.0 — initial release. Distributed through GitHub; not published to npm.

Licensed under the MIT License.

A Cloud-only stdio MCP server wrapping room-cli. Local Pi/Devin clients submit instructions and inspect results; agents and workspaces run on Cloudroom Cloud VMs.

  • Exactly four tools: thread_spawn, thread_tell, thread_get, and thread_stop.

  • Node.js 22+, no build step. Uses MCP SDK v2; legacy 2025-11-25 stdio connections are also tested.

  • The Cloudroom control server must be running locally. A local control server does not mean local agent execution.

  • Configure Cloud authentication and the chosen provider's authentication/runtime in Cloudroom beforehand. GitHub access is needed for repository-backed projects, not Personal.

  • This repository provides the MCP server only. It does not create a SKILL or modify global MCP configuration.

Upstream project

Cloudroom and room-cli: davidondrej/cloudroom-core. This repository is a separate MCP adapter that invokes room-cli. GitHub-only project registration uses one internal Cloudroom HTTP endpoint because the CLI does not expose that operation.

Related MCP server: claude-bridge

Install and run

cd ~/orca/projects/cloudroom-mcp
npm ci
node server.mjs

No project configuration is required: the default is Personal (proj_personal), with no repository or base branch. To override defaults, optionally copy .env.example to .env and run node --env-file=.env server.mjs.

When launched directly, a stdio server normally waits for input. Only MCP JSON-RPC is written to stdout; logs and startup errors go to stderr. npm start does not automatically load .env; use it with an already configured environment.

To allow a GitHub repository while keeping Personal as the default, put this in .env:

CLOUDROOM_ALLOWED_GITHUB_REPOS=owner/repository

Or set CLOUDROOM_GITHUB_REPO=owner/repository to make that repository the default and automatically allow it. No local clone, machine source connection, project ID lookup, or manual project creation is needed.

Defaults and options

Setting

Default

How to override

machine

cloud

Cloud only; Local/native execution is intentionally excluded

base_branch

Omitted

Repository projects only: spawn input or CLOUDROOM_DEFAULT_BASE_BRANCH; never sent for Personal

provider

acp-devin

Spawn/tell input or CLOUDROOM_DEFAULT_PROVIDER

model

gpt-6-1-sol-high

Spawn/tell input or CLOUDROOM_DEFAULT_MODEL

reasoning_level

high

Spawn/tell input or CLOUDROOM_DEFAULT_REASONING_LEVEL

github_repo

Omitted → Personal (proj_personal internally)

Optional CLOUDROOM_GITHUB_REPO; tool overrides must be allowlisted GitHub owner/repository identifiers

An unset or blank CLOUDROOM_GITHUB_REPO selects Personal. The default repository is automatically allowlisted; additional repositories use the comma-separated CLOUDROOM_ALLOWED_GITHUB_REPOS setting. With neither setting, only Personal is allowed. The get/tell/stop tools verify the Cloud target and the project's current GitHub remote, not its display name or a remembered project ID.

Only owner/repository is accepted as repository input. URLs, SSH clone strings, .git suffixes, project IDs, project names, and local paths are rejected. Identifiers are compared case-insensitively. Invalid or inaccessible repository selections never fall back to Personal or local execution. The old project tool argument and nonblank CLOUDROOM_PROJECT_ID / CLOUDROOM_ALLOWED_PROJECT_IDS settings are rejected; migrate to GitHub identifiers.

Personal has no repository: server-level branch defaults are ignored, and explicitly supplying base_branch for Personal is rejected before any CLI call. For repository projects, an omitted branch uses Cloudroom's own default unless CLOUDROOM_DEFAULT_BASE_BRANCH is configured.

The controlling LLM can specify options according to the user's instructions. Defaults are also provided in tool descriptions and server instructions. Omitted execution options use server defaults, not the thread's existing settings. When choosing another provider, also supply a compatible model and reasoning_level. Cloudroom and the provider perform final model validation; this adapter does not guess or rewrite model IDs.

Devin's CLI provider ID is acp-devin, including for Cloud execution. This differs from its internal harness name, devin. In testing, gpt-6.1-sol was rejected, while gpt-6-1-sol-high completed a response. Reasoning is always passed explicitly with --reasoning-level, independently of a model ID's high suffix.

Cloud execution uses full permissions. Input validation in this server does not give the remote agent a restricted permission mode. Executing requests may consume your account's model and Cloud usage.

Tools

thread_spawn

{
  "request_id": "b8f7774e-6e7c-42d8-bd16-35b2a3adc22e",
  "prompt": "Inspect the repository and summarize its tests.",
  "title": "GitHub repository check",
  "github_repo": "owner/repository",
  "machine": "cloud",
  "provider": "acp-devin",
  "model": "gpt-6-1-sol-high",
  "reasoning_level": "high"
}

Required: request_id (UUID), prompt. Optional: title, github_repo, and the execution options above. Omit github_repo with no server default repository to work in Personal.

For a GitHub repository, the server:

  1. Checks the repository allowlist and looks up Cloudroom projects by GitHub remote metadata.

  2. Reuses a matching project; duplicate matches fail rather than selecting arbitrarily.

  3. If missing, registers the repository with POST /api/v1/cloudroom/account/repo-suggestions/github, body {"repo":"owner/repository"}.

  4. Verifies that the returned project's GitHub remote matches, then supplies its internal ID to Cloud thread spawn.

The registration endpoint is internal and may change between Cloudroom versions. It can create a remote-only project or reuse/unhide an existing one. No project create --root, project source add, or local clone/attachment command is used. repository_registration_used reports whether the HTTP registration path was needed, not whether a new project was definitely created. Registration success is not proof that Cloud can access/clone the repository; inspect later thread errors as well. If a later step fails, registration is not rolled back; errors identify the phase and known partial changes.

Generate a UUID once per logical creation. If the outcome is uncertain because of a lost response or timeout, reuse the same UUID, options, and prompt. Do not blindly create another thread with a new UUID. The adapter uses Cloudroom's request ID handling and never retries automatically. ID conflicts and recovery of an already-created thread follow Cloudroom's behavior.

Returns the thread ID and submission status without waiting for completion. Successful creation does not mean initialization or the task has completed.

thread_tell

{
  "thread_id": "thr_example",
  "prompt": "Print the output of pwd && ls -la.",
  "model": "gpt-6-1-sol-high",
  "reasoning_level": "high",
  "mode": "queue"
}

Required: thread_id, prompt. Optional: provider, model, reasoning_level, and mode (queue by default, steer, or auto).

Execution order:

  1. Verify the Cloud target, allowed GitHub remote (or Personal), and current execution settings. If settings must change, inspect the interaction list directly and block pending/resolving interactions.

  2. Run thread update only if settings differ and the thread is idle/error with no queued messages or pending interactions.

  3. Confirm the updated settings with thread show.

  4. Send thread tell with explicit model and reasoning options.

A provider/model change may replace the native agent session while retaining the Cloudroom thread and history. Check settings_updated and native_session_may_have_changed in the result. Another controller or the GUI may change settings concurrently, resulting in HTTP 409 or another error. The adapter reports these errors instead of silently resending.

The CLI does not expose an idempotency key for tell. Blindly resending after a timeout may duplicate an instruction. A sent or queued result is not proof of task completion. If submission fails after a settings change, the error includes phase and settings_updated. There is no automatic rollback.

thread_get

{ "thread_id": "thr_example", "after_seq": 0, "event_limit": 20 }

Returns thread status, resolved github_repo (null for Personal), CLI execution settings, latest available output, errors, and an event page. event_limit is 1–100, default 20. Pass next_after_seq as the next call's after_seq. Continue paging while possibly_more_events=true. This conservatively indicates a full page, so one additional empty page is possible.

latest_available_output may belong to an earlier turn. After submitting a prompt, correlate event request_id values with actual terminal/error events. Event types and data come from the CLI. completion_verified is always false: the adapter does not guarantee that a particular request succeeded merely because the thread is idle or output exists.

Observations are not an atomic snapshot. snapshot_changed=true indicates that the observed state changed between reads. Check CLI execution settings together with actual responses/errors instead of trusting GUI labels alone. An agent's self-reported model identity is not independent proof of the model used, either.

Output is limited to 16,000 characters; output errors and the last error are each limited to 8,000 characters. Truncation is explicitly marked. Large event data is returned as a bounded JSON string preview with data_truncated=true. Event sequence numbers and request IDs are preserved even when event data is truncated.

thread_stop

{ "thread_id": "thr_example" }

Requests a stop only. It does not archive/delete the thread or destroy the VM. Errors such as process unavailable are not converted into success. Disconnecting MCP or cancelling an MCP call also does not automatically stop remote work.

Safeguards

  • Execute an absolute executable path with an argv array, without a shell. Prompts are passed so they cannot become CLI options.

  • Default CLI path: ~/.local/bin/room-cli. CLOUDROOM_CLI_PATH accepts an absolute path only.

  • CLOUDROOM_SERVER_URL accepts loopback HTTP origins only. Default: http://127.0.0.1:39886.

  • Strip the calling Pi/Devin's ROOM_* and automation context, and use the configured control server.

  • No Local fallback, file uploads, local checkout transfer, arbitrary CLI flags, automatic approvals, or archive/delete tools.

  • GitHub registration sends JSON only to the configured loopback control server, without cookies, redirect following, or automatic retries. Its response is limited to 64 KiB.

  • Default total operation deadline: 45 seconds, including repository lookup/registration and CLI calls. Configure 100–120000ms with CLOUDROOM_TIMEOUT_MS. Set the client's MCP timeout higher than this value, for example 60 seconds with the default deadline.

  • CLI stdout/stderr are limited to 1 MiB per stream. Failures are returned as structured MCP errors. outcome_unknown=true means the absence of remote side effects cannot be guaranteed.

  • No automatic write retries. Treat stderr and remote agent output as untrusted data.

  • Exclusive OS file locks prevent simultaneous mutations of the same thread/request and competing registration of the same GitHub repository across separate MCP processes. A competing request fails with operation_locked instead of waiting or retrying. Independent GUI/CLI actions do not participate in these locks; Cloudroom's final errors are still reported.

  • Prompts and remote output may be stored in Cloudroom, and prompts can also appear in process argv. Do not place credentials in prompts/options; use Cloudroom's authentication/secret mechanisms.

Recovering locks

The default lock directory is ~/.local/state/cloudroom-mcp/locks. Use the same directory for Pi and Devin. Override it with an absolute CLOUDROOM_LOCK_DIR if needed.

A forcibly terminated process can leave a lock behind. Locks are deliberately not stolen automatically. Inspect the pid, key, and creation time in the error's lock_path file. Remove that specific file manually only after confirming the process has exited and checking whether the remote instruction was accepted. Do not blindly empty the directory or delete a live process's lock.

Add to a coding agent's MCP configuration

1. Install the server dependencies

In your local clone of this repository:

cd /absolute/path/to/cloudroom-mcp
npm ci
node --version
room-cli --version

Use Node.js 22 or later and keep the repository at a stable path. No build, global npm installation, separate background service, or Pi extension package is required. The coding agent launches this stdio server as its child process. The local Cloudroom control server must still be running, with Cloud/provider authentication ready.

2. Register a local stdio MCP server

For clients using the mcpServers JSON format, merge this entry into the client's MCP settings:

{
  "mcpServers": {
    "room": {
      "command": "node",
      "args": [
        "/absolute/path/to/cloudroom-mcp/server.mjs"
      ]
    }
  }
}

Replace the placeholder path with the actual location of server.mjs; do not overwrite other servers. command is one executable, and args is an array—not a shell command. If a GUI client cannot find node on PATH, set command to your Node executable's absolute path. Register server.mjs, not room-cli directly: the CLI itself does not speak MCP. This server uses stdio, so do not configure it as an HTTP MCP server or use the Cloudroom control URL as its MCP URL.

Configuration locations and formats differ by agent. For example, some use a servers object or TOML instead of mcpServers. Use the same executable, arguments, and environment with that client's documented format. The common example deliberately omits Pi-specific exposure and client-specific timeout fields.

3. Optionally allow GitHub repositories

The minimal configuration above uses Personal and needs no environment variables. To permit a repository while retaining Personal as the default, add an env object to the room entry with these values:

{
  "CLOUDROOM_ALLOWED_GITHUB_REPOS": "owner/repository"
}

Use comma-separated owner/repository values to allow more than one repository. Alternatively, set CLOUDROOM_GITHUB_REPO=owner/repository to select a default repository and automatically allow it.

If you prefer an .env file, copy .env.example to .env, edit it, then use this server entry:

{
  "command": "node",
  "args": [
    "--env-file=/absolute/path/to/cloudroom-mcp/.env",
    "/absolute/path/to/cloudroom-mcp/server.mjs"
  ]
}

An .env file is not loaded unless you pass --env-file (or otherwise supply its values to the process). Restart/reload the coding agent's MCP connections after editing the configuration. If the client supports request timeouts, use more than the server's default 45-second deadline, for example 60 seconds; follow that client's timeout units. Confirm that it discovers thread_spawn, thread_tell, thread_get, and thread_stop. Discovery alone does not create a Cloud task.

Install and connect in Pi

This is an external MCP server, not a Pi extension/package. Use Pi's built-in MCP support; pi install is not needed for this repository.

1. Install dependencies and register

Run npm ci in the server repository once, as shown above. For Personal-only use:

pi mcp add room --exposure direct -- node /absolute/path/to/cloudroom-mcp/server.mjs
pi mcp list
pi

--exposure direct makes the four tools directly available to the model. Pi writes the registration to ~/.pi/agent/mcp.json and launches the server when needed; do not run a separate copy manually. If room already exists, pi mcp add room replaces that entry, so inspect existing settings before re-registering. It does not replace other named servers.

To allow a GitHub repository while keeping Personal as the default, use this registration instead:

pi mcp add room --exposure direct \
  --env CLOUDROOM_ALLOWED_GITHUB_REPOS=owner/repository \
  -- node /absolute/path/to/cloudroom-mcp/server.mjs
pi mcp list

To make that repository the default, use --env CLOUDROOM_GITHUB_REPO=owner/repository instead. --env is repeatable for other server settings. You can also pass --env-file=/absolute/path/to/cloudroom-mcp/.env after node and before the script path.

2. Check an existing Pi session

After registering or changing the server outside Pi:

/reload
/mcp

Check that room is connected and lists all four tools. Pi exposes their names as mcp__room__thread_spawn, mcp__room__thread_tell, mcp__room__thread_get, and mcp__room__thread_stop. pi mcp list checks all configured servers and prints connection errors; it does not run an agent task.

3. Manual or project-local configuration

Alternatively, merge the Pi-specific entry from mcp.example.json into ~/.pi/agent/mcp.json, replace the server path, and run /reload. That sample includes Pi's exposure: "direct" and a 60-second timeout.

For project-local registration, run pi mcp add room --local ... from the coding project's directory. This writes .pi/mcp.json there, not in the MCP server's installation directory. Pi loads project-local MCP configuration only after the coding project is trusted.

Troubleshooting

  • node not found: use an absolute Node executable path in the registration.

  • room-cli not found/not executable: set CLOUDROOM_CLI_PATH to the actual absolute executable path.

  • Cannot reach Cloudroom: start its local control server and check CLOUDROOM_SERVER_URL.

  • repository_not_allowed: configure CLOUDROOM_ALLOWED_GITHUB_REPOS or CLOUDROOM_GITHUB_REPO, then reload.

  • pi mcp add is unavailable: check pi mcp add --help and use a Pi version with built-in MCP support.

GitHub sources and non-goals

This adapter does not send local cloned repositories or uncommitted files to Cloud. Personal needs no repository or branch. For repository-backed projects, the observed Cloud initialization clones GitHub, and an optional base_branch selects a remote ref. Pushing to GitHub is needed only when you want local changes to be available to the Cloud workspace; you do not need to push for every follow-up sent to an existing Cloud thread. Local execution and local source synchronization are deferred features.

Verification

npm run check
npm test
npm audit --omit=dev

Tests use a fake room-cli and do not automatically create paid Cloud workloads. They cover argv/context isolation, strict GitHub identifiers, repository lookup/registration and allowlists, settings update ordering, errors/timeouts/cancellation, redirect refusal, prevention of automatic duplicate retries, locks, event pagination, a real stdio MCP client, and the legacy handshake. Registration integration tests use a local mock HTTP server, not the real Cloudroom API.

A live Cloud read was verified through MCP client → server → room-cli during the initial implementation. The GitHub registration path is validated with a mock HTTP server, not a live registration POST. Implementation verification does not create remote workloads or modify real projects/threads.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Terminal multiplexer MCP server for orchestrating parallel AI agents. Manages workspaces, panes, surfaces with send_input/read_screen/spawn_agent/stop_agent tools. Supports Claude Code, Codex, Gemini, Cursor CLI agents with lifecycle management, browser automation, and agent status push via Claude --channels.
    10
    30
    Apache 2.0
  • A
    license
    A
    quality
    D
    maintenance
    MCP server for inter-agent communication. Gives multiple Claude Code sessions a shared message board, agent registry, and orchestration layer — backed by a cloud relay so agents can coordinate across machines, repos, and teams.
    8
    20 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    An MCP server for orchestrating a fleet of CLI coding agents in isolated git worktrees. It exposes tools for spawning workers, sending instructions, reviewing diffs, and merging changes, with full terminal visibility.
    6 npm
    4
    MIT