Atlas / MCP servers / egoushka / chargehand

chargehandBLOCK

mcp/egoushka/chargehand

Runs your request on coding agents (Claude Code, OpenCode) and returns an answer whose every citation is checked against a pinned commit. CLI, HTTP and MCP.

Verdict
BLOCK
Grade
D
Trust score
64 /100
Exposed tools
—
Transport
stdio
License
Apache-2.0
Stars
0
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://github.com/Egoushka/chargehand/actions/workflows/ci.yml) [](https://scorecard.dev/viewer/?uri=github.com/Egoushka/chargehand) [](https://github.com/Egoushka/chargehand/releases) [](LICENSE)

chargehand turns a request into a typed Task Spec, runs it on one or more coding-agent sessions (OpenCode or Claude Code), and returns a result contract with evidence for every claim. People call it from a CLI; programs call it over HTTP or MCP.

Status: before 1.0 (the release badge shows the version). Workers are read-only by default; the code preset (since 0.8.0) makes one write a branch that passes its tests in a sandbox. See the changelog for what shipped, the roadmap for what comes next, and benchmarks for how it performs. The guide walks through using it, and what it does, and how we know gives each capability's status with its evidence.

Why

Coding agents answer in prose. A program that calls one needs something it can check: claims tied to files at a commit, diffs, session messages or caller inputs, plus a confidence and the exact prompt chain behind the answer.

chargehand keeps control flow (task graph, budgets, retries, parallelism) in code, not in a prompt. Each worker's context stays small, cached and disposable.

Non-goals: its own agent loop, direct calls to model providers, parallelism for its own sake.

How a run works

  1. Intake reads request/v1 and writes a Task Spec with one action.
  2. The action decides what happens next:
  3. answer runs one worker session.
  4. split
Read from source at commit e25fa847faf5OBSERVED · 2026-10-14
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add chargehand-console --env ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} --env CHARGEHAND_E2E_PUSH_KEY=${CHARGEHAND_E2E_PUSH_KEY} --env CHARGEHAND_SPIKE_OAUTH_ITEM=${CHARGEHAND_SPIKE_OAUTH_ITEM} --env CLAUDE_CODE_OAUTH_TOKEN=${CLAUDE_CODE_OAUTH_TOKEN} -- npx -y [email protected]
claude-desktop
{
  "mcpServers": {
    "chargehand-console": {
      "command": "npx",
      "args": [
        "-y",
        "[email protected]"
      ],
      "env": {
        "ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}",
        "CHARGEHAND_E2E_PUSH_KEY": "${CHARGEHAND_E2E_PUSH_KEY}",
        "CHARGEHAND_SPIKE_OAUTH_ITEM": "${CHARGEHAND_SPIKE_OAUTH_ITEM}",
        "CLAUDE_CODE_OAUTH_TOKEN": "${CLAUDE_CODE_OAUTH_TOKEN}"
      }
    }
  }
}
03

Trust audit

BLOCKgrade D · trust 64/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (9 observation(s))
Network
declared (10 observation(s))
Shell
declared (2 observation(s))
Dependencies
pinned
Secrets in source
none-found

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
scripts/driven-e2e.sh:288
field() { python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(eval(sys.argv[2]))" "$1" "$2" 2>/dev/null || echo ""; }
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
scripts/write-e2e.sh:44
field() { python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(eval(sys.argv[2]))" "$1" "$2" 2>/dev/null || echo ""; }
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
deploy/macos/run-runner.sh:70
curl -fsS "http://127.0.0.1:$DOCKER_PROXY_PORT/_ping" > /dev/null 2>&1 && break
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
deploy/macos/run-runner.sh:73
curl -fsS "http://127.0.0.1:$DOCKER_PROXY_PORT/_ping" > /dev/null 2>&1 || fail "the socket proxy does not answer on 127.0.0.1:$DOCKER_PROXY_PORT (is OrbStack running, and the chargehand-docker-proxy c
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
scripts/review-comment.sh:24
def q: gsub("@"; "@") | gsub("<"; "&lt;") | gsub("\r?\n|\r"; " ");
LOWInventory / provenance · inv.hidden_file · CWE-1104
.private-terms.example
.private-terms.example
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
web/console/src/screens/accounts/Accounts.tsx:3
import { accountsQuery } from '../../api/accounts';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
web/console/src/screens/accounts/Accounts.tsx:4
import type { AccountBody } from '../../api/common';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
web/console/src/screens/accounts/Accounts.tsx:5
import { formatDateTime, formatTime } from '../../lib/format';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
web/console/src/screens/accounts/Accounts.tsx:6
import { useIsPhone } from '../../shell/useIsPhone';
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
web/console/src/screens/accounts/Accounts.tsx:24
} from '../../ui';
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
tests/Chargehand.Modules.Gateway.Tests/AllowlistMatcherTests.cs:75
[InlineData("169.254.169.254", false)]                       // cloud metadata
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/adr/0034-memory-and-services-over-mcp.md:121
| C5 | Does an `http` entry with `headers` connect? | `<cfg>` = `{"mcpServers":{"ch":{"type":"http","url":"http://127.0.0.1:<port>/v1/mcp","headers":{"Authorization":"Bearer <key>"}}}}` against an own
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/adr/0034-memory-and-services-over-mcp.md:142
| O8 | Does a `remote` entry send `headers`? | `PUT` of `{"config":{"type":"remote","url":"http://127.0.0.1:<port>/v1/mcp","headers":{"Authorization":"Bearer <key>"}}}` against an own `chargehand serv
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/guide/benchmark.md:32
- A place to push the branches. Nothing is ever pushed to an upstream. Either **a fork you own of each repository**, named as in the set (`guard-clauses`, `commander-js`, `more-itertools`, `joda-money
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:25
- The operator console's **Analytics** and **Learning** screens (ADR 0056, CHARGEHAND-208), at `/console/analytics` and `/console/learning`. Analytics reads `GET /v1/analytics` (`analytics/v1`) and `G
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:27
- The operator console's **Start a batch** screen (ADR 0056, CHARGEHAND-208), at `/console/new`. A preset, a repository from `GET /v1/repositories` with the commit filled from its HEAD, and a list of
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:33
- Actions on pull requests and tasks for the console (CHARGEHAND-214, third change): `POST /v1/batches/{id}/tasks/{task}/cancel`, `.../retry` and `.../session/stop`, and `POST /v1/pulls/{owner}/{repo}
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:56
- Several runners (ADR 0058, CHARGEHAND-212), third change: a runner on another machine. A runner with `workspace: bundle` is sent the repository as a git bundle of the pinned commit (`git bundle crea
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:96
- A web UI at `/ui/` (ADR 0054, CHARGEHAND-203), off unless `http.ui` is `true`. Plain HTML, CSS and ES modules embedded in the server, no build step, no third-party code. Sign in by pasting an API ke
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWInventory / provenance · mcp.no_tools_extracted · CWE-1104
.mcp/server.json
Why it matters. the tool list is enumerated at runtime by tools/list, not declared in source
Fix. the page says so rather than showing an empty table
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
CHANGELOG.md:193
- The first deployment of driven sessions on a VPS is recorded (ADR 0039, the driven guide, the roadmap; CHARGEHAND-156): a draft pull request on the fourth attempt, the four defects each attempt foun
Why it matters. asks the agent to read credentials
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
CHANGELOG.md:281
- The sandbox a writing run's tests will execute in (ADR 0035): `sandbox-exec` on macOS, `bwrap` on Linux, behind one interface; profile field `sandbox` (`kind`, `network`, `env`). A command may write
Why it matters. asks the agent to read credentials
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
ROADMAP.md:34
in a draft pull request. Open is the substituted credential (a gateway; until then the model credential is in the
Why it matters. asks the agent to read credentials
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/adr/0006-presets.md:22
ask-before-reading-`.env` rules no longer apply: a worker read `*.env.*` files without asking (found during the
Why it matters. asks the agent to read credentials

Gates applied: no_behavioural_pass.

Audited 2026-10-14 · audit v0.4.1 · source sha e25fa847faf5full audit observations/trust-audit/mcp-server/egoushka__chargehand.json · Report an issue / request a re-scan
04

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-14e25fa847faf5BLOCKD64first audit
05

Questions

What is the chargehand MCP server?

Runs your request on coding agents (Claude Code, OpenCode) and returns an answer whose every citation is checked against a pinned commit. CLI, HTTP and MCP.

Is chargehand safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (64/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on.

What credentials does chargehand need?

It reads ANTHROPIC_API_KEY, CHARGEHAND_E2E_PUSH_KEY, CHARGEHAND_SPIKE_OAUTH_ITEM, CLAUDE_CODE_OAUTH_TOKEN and OPENCODE_SERVER_PASSWORD from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does chargehand run?

It speaks stdio, so it runs as a local process your client starts. It is published on npm as chargehand-console at 0.0.0.

How current is this page?

The grade is for one exact copy of the source (e25fa847faf5), read on 2026-10-14. The repository is watched and re-audited when it changes.

Advertisement