Skip to main content
Glama
sohampatwardhan

Claude Code MCP Server

Claude Code MCP Server

MCP server that lets AI agents with an always-on cloud computer (e.g. Muse by Meta, Grok Bot by SpaceXSI, ChatGPT Dots by OpenAI, etc) orchestrate Claude Code cloud sessions natively via the Claude Code CLI.

It exposes three tools over stdio: create a cloud session, queue a follow-up message into one, and check the CLI's sign-in state. Each tool maps to one fixed claude invocation, and each returns structured JSON. Agents call typed tools and get typed results back, so they never need to write shell commands.

Design

  • Strict input schemas. Every field is typed, required fields are listed explicitly, and every schema sets additionalProperties: false. Invalid input is rejected by schema validation before any process is spawned.

  • No escape hatch. The tool surface is exactly the three tools below. There is no "run any claude command" tool and no shell access.

  • Deterministic argv. Arguments are built from validated inputs in a fixed order and passed as an array (shell: false). Values are attached as --flag=value, or placed after --, so a value that starts with - can never be read as a flag. claude --cloud=<description> is executed on a pseudo-terminal because the CLI rejects that form when stdout is a pipe; the pty helper execs the same argv and never goes through a shell.

  • Structured outputs. Every tool declares an outputSchema and returns structuredContent with parsed fields, such as session_id and session_url. CLI stdout and stderr are returned in cli with terminal control sequences removed.

  • Cloud only. The session tools always pass --cloud. The server never starts a local Claude Code session.

  • No network of its own, no telemetry. It only runs the local claude binary.

Related MCP server: claude-cli-mcp

Prerequisites

  • Node.js 20 or later

  • The Claude Code CLI, installed and signed in (claude auth status should report "loggedIn": true), with cloud sessions available on your account

  • Python 3 (the standard library only: pty, fcntl, termios) for claude_create_cloud_session. No pip packages. Follow-ups and auth status do not need Python. On Debian/Ubuntu this is the python3 package, which is usually already installed.

Install and build

git clone <this repo> claude-code-mcp-server
cd claude-code-mcp-server
npm install
npm run build
npm test        # unit tests + stdio smoke test (uses a fake CLI; creates no sessions)

Run

npm start                       # same as: node dist/src/index.js

The server speaks MCP over stdin/stdout. Normally the MCP client launches it, so you don't run it by hand.

Environment variables

Variable

Default

Meaning

CLAUDE_BIN

claude

Path or name of the Claude Code CLI binary.

CLAUDE_CLOUD_ENVIRONMENT_ID

unset

Default cloud environment id (for example ccpool_...), passed as --environment when a call does not pass environment_id.

CLAUDE_MCP_TIMEOUT_MS

300000

Hard timeout for each spawned CLI process, in milliseconds (positive integer). On timeout the process gets SIGTERM, then SIGKILL 5 s later.

CLAUDE_MCP_TRUST_CWD

unset (off)

1, true, or yes lets create accept Claude Code's workspace-trust dialog for CLAUDE_MCP_CWD only (the process working directory when that is unset). 0, false, no, or unset leaves the dialog unanswered and the call fails with WORKSPACE_NOT_TRUSTED.

CLAUDE_MCP_PYTHON

python3

Python 3 interpreter used to allocate the pseudo-terminal for create.

CLAUDE_MCP_CWD

process working directory

Directory the CLI runs in. claude --cloud packages this tree, and workspace trust is resolved from it. A relative path is resolved at startup. The path must exist and be a directory.

If any of these values is invalid, the server exits at startup with code 2 and prints a message on stderr.

The CLI runs in CLAUDE_MCP_CWD, or in the server process's working directory when that variable is unset or blank. claude --cloud packages the repository in that directory for the new session. Set the client's cwd to the repository you want the cloud sessions to work on, or set CLAUDE_MCP_CWD when the host can pass environment variables but not a working directory. An invalid CLAUDE_MCP_CWD (missing path, or a path that is not a directory) makes the server exit at startup with code 2.

Workspace trust

claude --cloud <description> requires an interactive terminal. On a pseudo-terminal the CLI then stops at "Do you trust this folder?" until someone answers, because accepting trust lets that folder's project hooks, allow rules, and .mcp.json servers run.

This server does not answer that dialog on its own. Either:

  • Trust the folder yourself: run claude once in that directory and accept the dialog, or set projects["<path>"].hasTrustDialogAccepted to true in ~/.claude.json. <path> is the main git checkout when CLAUDE_MCP_CWD is a repository or worktree, and CLAUDE_MCP_CWD itself otherwise (the process working directory when the variable is unset). Claude Code documents this key under project allow rules and workspace trust.

  • Or set CLAUDE_MCP_TRUST_CWD=1. Create then writes that same key for the one directory above and, if the dialog still appears, sends Enter once. The opt-in covers that one directory. Create still runs with the CLI's normal permission prompts.

The trust edit holds ~/.claude.json.lock (exclusive create, treated as stale after 5 seconds) so two of these servers do not interleave. Inside the lock it re-reads ~/.claude.json immediately before an atomic rename, skips the write when hasTrustDialogAccepted is already true, and retries the merge when the file changed since the first read so other fields are kept.

Claude Code does not take that lock. A Claude process that saves ~/.claude.json after this server's second read can overwrite the trust flag, and a save that lands between that read and the rename can itself be overwritten. If the dialog comes back, set the flag again while no Claude process is writing the file.

A description that merely contains the words "Do you trust this folder?" is not treated as the dialog. The Created cloud session: title line is ignored when the server looks for the prompt.

Trust is stored in ~/.claude.json in the home directory (not under ~/.claude/). When ~/.claude.json is missing or is not a JSON object, the opt-in leaves it unchanged and answers the dialog on the pty instead. Claude Code treats the home directory itself as trusted for the current session only, so a server whose CLAUDE_MCP_CWD is $HOME still needs the opt-in for the pty to press Enter.

Tool reference

Every successful call returns structuredContent that matches the tool's outputSchema, and the same JSON as a text content block.

claude_create_cloud_session

Creates a new cloud session. Runs, on a pseudo-terminal: claude --cloud=<description> [--environment=<id>]

The CLI rejects --cloud with a task description when stdout is a pipe (--cloud requires an interactive terminal). There is a non-interactive create form, claude -p <task> --environment <ccpool>, but it only targets self-hosted environments and it omits --cloud. This server keeps --cloud= on every create so an older CLI cannot fall through to a local session. A pty has a single output stream, so the CLI's stdout and stderr are both returned in cli.stdout (cli.stderr is empty on this tool). cli.stdout and cli.stderr have terminal control sequences removed (cursor save and restore, CSI including private parameters, and other C0 controls) before they are returned.

Input schema:

{
  "type": "object",
  "properties": {
    "description": { "type": "string", "minLength": 1, "maxLength": 100000, "pattern": "\\S" },
    "environment_id": { "type": "string", "maxLength": 200, "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]*$" }
  },
  "required": ["description"],
  "additionalProperties": false
}

The environment id is chosen in this order: environment_id from the call, then CLAUDE_CLOUD_ENVIRONMENT_ID, then none (no --environment flag).

Output:

{
  "session_id": "session_01AbC...",
  "session_url": "https://claude.ai/code/session_01AbC...?from=cli&m=0",
  "title": "Fix flaky login test",
  "parsed": true,
  "environment_id": null,
  "args": ["--cloud=Fix flaky login test"],
  "cli": { "exit_code": 0, "stdout": "Created cloud session: ...", "stderr": "" }
}

parsed is true when both session_id and session_url were found in the CLI output. If the output can't be parsed, the call still succeeds with parsed: false, the unparsed fields set to null, and the cleaned output in cli.

claude_send_followup

Queues a message into an existing cloud session. Runs: claude --cloud=<session> -p -- <message>

Input schema:

{
  "type": "object",
  "properties": {
    "session": {
      "type": "string",
      "maxLength": 2000,
      "pattern": "^(?:(?:session|cse)_[A-Za-z0-9][A-Za-z0-9_-]*|https:\\/\\/claude\\.ai\\/code\\/[^\\s\"'<>]+)$"
    },
    "message": { "type": "string", "minLength": 1, "maxLength": 100000, "pattern": "\\S" }
  },
  "required": ["session", "message"],
  "additionalProperties": false
}

Output:

{
  "session": "session_01AbC...",
  "session_id": "session_01AbC...",
  "session_url": "https://claude.ai/code/session_01AbC...?from=cli&m=0",
  "sent": true,
  "parsed": true,
  "args": ["--cloud=session_01AbC...", "-p", "--", "Also update the docs"],
  "cli": { "exit_code": 0, "stdout": "Sent to cloud session.\n...", "stderr": "" }
}

sent is true when the CLI confirmed delivery (Sent to cloud session.).

Session progress

The CLI has no command that prints a cloud session's status or latest reply. claude -p --cloud <session> only queues a follow-up and exits; claude agents and claude logs talk to local background sessions, not claude.ai cloud sessions. Callers check progress by opening session_url. On a self-hosted environment a Stop hook on the runner can capture replies (see Test self-hosted environments); that hook is outside this server, and the server makes no network calls of its own.

claude_auth_status

Reports the CLI's sign-in state. Runs: claude auth status

Input schema:

{ "type": "object", "properties": {}, "additionalProperties": false }

Output (fields the CLI does not print are null):

{
  "loggedIn": true,
  "authMethod": "claude.ai",
  "email": "dev@example.com",
  "orgName": "Example Org",
  "subscriptionType": "max",
  "cli": { "exit_code": 0, "stdout": "{...}", "stderr": "" }
}

Errors

Failures come back as MCP tool errors (isError: true). The text content block holds JSON with this fixed shape:

{
  "error": {
    "code": "CLI_EXIT_NONZERO",
    "message": "claude exited with code 1: Error: Unable to create cloud session ...",
    "args": ["--cloud=..."],
    "cli": { "exit_code": 1, "stdout": "", "stderr": "Error: ..." }
  }
}

code

When

CLI_EXIT_NONZERO

The CLI exited non-zero or was killed by a signal. message includes the stderr text.

CLI_TIMEOUT

The CLI ran longer than CLAUDE_MCP_TIMEOUT_MS.

CLI_NOT_FOUND

CLAUDE_BIN could not be found. cli is null.

CLI_SPAWN_FAILED

The process could not be started for another reason. cli is null.

OUTPUT_PARSE_FAILED

claude auth status did not print JSON with a boolean loggedIn.

PTY_UNAVAILABLE

Create could not start the Python interpreter that allocates the pseudo-terminal (CLAUDE_MCP_PYTHON). cli is null.

WORKSPACE_NOT_TRUSTED

Create reached Claude Code's workspace-trust dialog and CLAUDE_MCP_TRUST_CWD is off, so the dialog was not answered.

Schema violations (a missing required field, an unknown property, a value that doesn't match a pattern) are rejected by the MCP SDK's input validation as tool errors, and the CLI is never run.

Client configuration

The server uses standard MCP stdio, so any client that accepts an mcpServers-style stdio entry can launch it. Use absolute paths, since clients usually launch servers from their own working directory.

Generic MCP stdio config

{
  "mcpServers": {
    "claude-code": {
      "command": "node",
      "args": ["/absolute/path/to/claude-code-mcp-server/dist/src/index.js"],
      "cwd": "/absolute/path/to/the/repo/sessions/should/work/on",
      "env": {
        "CLAUDE_BIN": "claude",
        "CLAUDE_MCP_TIMEOUT_MS": "300000"
      }
    }
  }
}

If you've installed the package globally (npm install -g . from this repo), you can use "command": "claude-code-mcp-server" with "args": [] instead.

Muse

Add the server as a stdio MCP server in Muse's MCP server configuration:

{
  "mcpServers": {
    "claude-code": {
      "command": "node",
      "args": ["/absolute/path/to/claude-code-mcp-server/dist/src/index.js"],
      "cwd": "/absolute/path/to/your/repo",
      "env": {
        "CLAUDE_CLOUD_ENVIRONMENT_ID": "ccpool_your_environment_id"
      }
    }
  }
}

Grok and other MCP clients

Any MCP client that can launch a local stdio server uses the command (node), the args (the path to dist/src/index.js), and optional env vars. When the client has no cwd field, set CLAUDE_MCP_CWD to the repository the cloud sessions should package. For example:

{
  "mcpServers": {
    "claude-code": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/claude-code-mcp-server/dist/src/index.js"],
      "env": {
        "CLAUDE_MCP_CWD": "/absolute/path/to/your/repo"
      }
    }
  }
}

Field names vary slightly between clients (some leave out type, and some call the map servers). Check your client's MCP documentation for the exact config file location and keys.

Development

src/
  index.ts    entry point (bin): loads config, starts the stdio server
  server.ts   tool definitions, input/output schemas, error shape
  argv.ts     deterministic argv construction for each tool
  parse.ts    CLI output parsing (session id / URL regexes, auth JSON)
  runner.ts   child_process spawn with timeout and output caps (follow-up and auth)
  pty.ts      pseudo-terminal spawn used by create (embedded Python helper)
  trust.ts    workspace-trust dialog detection and the opt-in ~/.claude.json edit
  config.ts   environment variable parsing and validation
test/
  parse.test.ts        parser unit tests against realistic CLI output
  argv-config.test.ts  argv and config unit tests
  trust.test.ts        trust-dialog detection, ~/.claude.json edits, worktree path
  smoke.test.ts        starts the built server over stdio and exercises every tool
  fixtures/fake-claude.mjs  stand-in CLI used by the smoke test (TTY and trust dialog)

License

MIT

Available Tools

3 tools
claude_auth_statusClaude Code auth statusA
Read-onlyIdempotent

Report whether the local Claude Code CLI is signed in, via claude auth status.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
cliYesCLI output with terminal control sequences removed.
emailYes
orgNameYes
loggedInYes
authMethodYes
subscriptionTypeYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, and closed-world behavior, so the safety profile is covered. The description adds genuinely useful context beyond that: it reports on the *local* CLI specifically and reveals it delegates to `claude auth status`, clarifying scope and failure surface.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler. The core action and target are stated first, with the implementation detail appended compactly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, annotations cover safety, and there are no parameters to document. For a simple read-only status probe, nothing further is required for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. The description correctly implies no inputs are needed, and there are no parameter semantics to misrepresent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (report) and resource (local Claude Code CLI sign-in state), and names the underlying command. It is clearly distinguishable from the sibling tools, which handle cloud sessions and follow-ups rather than local auth.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the name and by 'whether the local CLI is signed in' — an agent can infer this is a precondition check. However, there is no explicit statement of when to call it (e.g., before other Claude Code operations) and no mention of alternatives or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

claude_create_cloud_sessionCreate Claude Code cloud sessionA

Create a new Claude Code cloud session via claude --cloud on a pseudo-terminal (the CLI rejects this form when stdout is a pipe). Returns the parsed session_id and session_url. If parsing fails, parsed is false and the CLI output, with terminal controls removed, is in cli. The CLI runs in CLAUDE_MCP_CWD, or in the server process's working directory when that is unset. When Claude Code asks to trust that folder, the call fails with WORKSPACE_NOT_TRUSTED unless CLAUDE_MCP_TRUST_CWD=1.

ParametersJSON Schema
NameRequiredDescriptionDefault
descriptionYesTask description for the new cloud session.
environment_idNoCloud environment id (e.g. ccpool_...). Overrides CLAUDE_CLOUD_ENVIRONMENT_ID; omit to use that default.

Output Schema

ParametersJSON Schema
NameRequiredDescription
cliYesCLI output with terminal control sequences removed.
argsYes
titleYes
parsedYesTrue when both session_id and session_url were parsed from CLI output.
session_idYes
session_urlYes
environment_idYes

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite annotations already declaring readOnlyHint=false/openWorldHint=true/idempotentHint=false, the description adds substantial non-obvious behavior: the pseudo-terminal requirement (CLI rejects piped stdout), the parsed vs. `cli` fallback output shape, the CWD resolution rule, and the WORKSPACE_NOT_TRUSTED failure with the CLAUDE_MCP_TRUST_CWD=1 escape hatch. These are exactly the environment-specific behaviors an agent cannot get from the schema or annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the action, then output contract, then environment/failure behavior. Each sentence carries operational weight, though the parsing-failure sentence is somewhat dense and could be tightened without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a creation tool with an output schema, the description covers the action, the return contract, the runtime environment, and the one failure mode that blocks success. An agent has everything needed to invoke it correctly and to interpret a failed call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains both parameters including the CLAUDE_CLOUD_ENVIRONMENT_ID override, which the description does not restate or extend. Baseline 3 is appropriate since the description adds no format, constraint, or default detail beyond the structured fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Create a new Claude Code cloud session') and even names the underlying mechanism ('claude --cloud'). It is unambiguous, though it never explicitly contrasts itself with the sibling tools claude_send_followup or claude_auth_status, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: an agent can infer this is the entry point that precedes claude_send_followup, but there is no explicit when-to-use/when-not-to-use guidance or alternative routing. The operational preconditions it does give (PTY requirement, trust requirement) are about mechanics, not tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

claude_send_followupSend follow-up to Claude Code cloud sessionA

Queue a follow-up message into an existing Claude Code cloud session via claude --cloud <session> -p <message>.

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesMessage to queue into the session.
sessionYesTarget cloud session: a session id (session_... / cse_...) or a https://claude.ai/code/... URL.

Output Schema

ParametersJSON Schema
NameRequiredDescription
cliYesCLI output with terminal control sequences removed.
argsYes
sentYesTrue when the CLI confirmed the message was sent.
parsedYesTrue when both session_id and session_url were parsed from CLI output.
sessionYes
session_idYes
session_urlYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safety profile (readOnly=false, destructive=false, idempotent=false, openWorld=true), so the bar is lower. The description adds that the message is 'queued' (asynchronous delivery), which is useful behavior beyond the annotations, but says nothing about auth requirements, delivery guarantees, or whether an in-flight turn blocks the queue.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler; the scope ('existing') and mechanism are packed in without waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and the tool only has two well-documented params. The description is nearly sufficient, missing only prerequisites for obtaining a valid session and the async implications of queuing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%: both params are fully documented with patterns and length bounds. The CLI form `claude --cloud <session> -p <message>` maps role to argument, adding marginal clarity, but duplicates what the schema already conveys. Baseline 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (queue a follow-up message) and resource (an existing Claude Code cloud session). The word 'existing' implicitly distinguishes it from claude_create_cloud_session, but no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The word 'existing' implies a session must already be present, giving implied usage context. However, it never states when to prefer this over creating a session or how to obtain a session id, so guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.1.0
    • First observedclaude_auth_status
    • First observedclaude_create_cloud_session
    • First observedclaude_send_followup

TDQS

A3.9/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a distinct action: creating a cloud session, sending a follow-up message, and checking CLI auth. There is no plausible overlap or way an agent could confuse them.

Naming Consistency5/5

All three tools use the same claude_ prefix followed by a clear snake_case verb_noun form (create_cloud_session, send_followup, auth_status). The pattern is entirely predictable.

Tool Count4/5

Three tools is a lean but coherent set for driving Claude Code cloud sessions. It is slightly under-scoped, but no tool feels redundant or bloated.

Completeness3/5

The surface covers session creation, follow-ups, and auth, but has notable gaps: no way to list existing sessions, read a session's output/status, or terminate a session. Agents can partially work around this via the returned session_url, but the lifecycle is incomplete.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Wraps Claude Code as tools for MCP clients, enabling autonomous coding tasks via a 4-tool lifecycle with session management, async polling, and permission controls.
    4
    34 npm
    20
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI agents to interact programmatically with Claude Code CLI, managing sessions, streaming outputs, and handling permission requests.
    7
    7 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Delegates coding tasks to the local Claude Code CLI via MCP, offering run, review, and status tools for MCP-compatible agents.
    11 npm
    MIT