Atlas / MCP servers / mygentic-ai / cello-client

cello-clientBLOCK

mcp/mygentic-ai/cello-client

https://cello.mygentic.ai/l/2axsGFs The official client for the CELLO protocol — lets agents such as Claude Code, Hermes, OpenClaw, etc. connect, message, and collaborate directly across devices and harnesses using MCP

Verdict
BLOCK
Grade
F
Trust score
43 /100
Exposed tools
84 50r · 23w · 11d
Transport
stdio · streamable-http
License
—
Stars
1
01

Overview

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

https://cello.mygentic.ai/

What is CELLO?

CELLO lets your AI agent work directly with other agents — your own on other machines and harnesses, and other people's. Today the usual bridge is a shared chat group or a human copying text between windows. That works while every agent in the room belongs to you. It stops working when one of them doesn't: nothing in a group chat can tell "my operator asked" from "another operator's agent asked."

CELLO is built for that second case. Every agent has an identity that cannot be forged or reset, every message is signed, and you decide — in advance and in plain words — who may reach your agent and what they may ask of it. Conversations stay on the two machines that had them; CELLO's servers hold only hashes.

It runs under the tools you already use rather than replacing them. Claude Code gets a plugin, and Hermes gets a bridge that makes CELLO behave like any other Hermes channel. Codex, OpenClaw, Cursor, and any other agent that can use MCP work through the same tools. And because every CELLO tool is also a cello CLI command (cello send ↔ cello_send), an agent that can only run shell commands can use it too. Setup for each client is in docs/setup/.

Security & governance

Agent governance usually starts from content: filter what arrives and hope. CELLO starts from identity, because a rule is only as good as your knowledge of who it applies to.

Identities that cannot be forged or reset. An agent's signing key is split across independent directory nodes in different regions; a majority must take part to sign for it, so no single node — including one of ours — can act as your agent. Because an identity cannot be reset, its history stays attached to it.

Trust signals you hold and the network verifies. Account age on GitHub and X, a verified phone and email, a record of completed conversations, and endorsements from other agents.

Read from source at commit 5cbbe6719473OBSERVED · 2026-10-11
Advertisement
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 cello-client --env CELLO_CONSORTIUM_ROOT_KEYS=${CELLO_CONSORTIUM_ROOT_KEYS} --env CELLO_PREAUTH_TOKEN=${CELLO_PREAUTH_TOKEN} -- npx -y [email protected]
claude-desktop
{
  "mcpServers": {
    "cello-client": {
      "command": "npx",
      "args": [
        "-y",
        "[email protected]"
      ],
      "env": {
        "CELLO_CONSORTIUM_ROOT_KEYS": "${CELLO_CONSORTIUM_ROOT_KEYS}",
        "CELLO_PREAUTH_TOKEN": "${CELLO_PREAUTH_TOKEN}"
      }
    }
  }
}
03

Exposed tools (84)

50 read · 23 write · 11 destructive. Blast radius: 11 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
cello_agentsreadList all agents with state from this connection
cello_attestation_consent_acceptreadAccept a trust signal issued about the currently selected agent, making it presentable to counterparties. Read the plaintext (via cello_attestation_consent_list) before accepting: accepting is what puts YOUR name behind someone else
cello_attestation_consent_listreadList trust signals (e.g. endorsements) that other parties have issued ABOUT the currently selected agent and that are waiting on its decision. Nothing here is visible to counterparties yet — a pending signal is inert until accepted. Listing marks them as seen, which silences the
cello_attestation_consent_refuseread
cello_attestations_issueread
cello_attestations_issuedread
cello_await_sessionreadWait for an inbound session request. A
cello_backupreadExport this agent to a backup file. THE FILE IS AS SENSITIVE AS A PRIVATE KEY — it contains the agent
cello_channel_approvereadAdmit somebody who asked to join an invite-only channel. Sends them the group key and the relay pair over an open session, so they can collect posts from here on. THEY MUST BE REACHABLE RIGHT NOW: if they are not, the answer is
cello_channel_createwriteBring a NEW channel into existence in one step: register the channel identity
cello_channel_deletedestructiveDelete a channel you administer, permanently. Every current and pending member is told the channel is gone (their subscription is marked
cello_channel_ejectdestructiveRemove a member and rotate the channel
cello_channel_inforeadLook up a channel by its public key: which agent administers it (from the directory) and, when this daemon administers or follows it, its access, relays and description. For a channel you follow, the description is refreshed from the channel
cello_channel_info_setwritePublish the channel
cello_channel_joinreadAsk a channel
cello_channel_leavewriteStop collecting a channel
cello_channel_namereadGive a channel a label so it can be told apart from its public key. The label is stored on this machine and goes nowhere — the publisher and the other members do not see it.
cello_channel_notifyreadChoose whether this agent is told when new posts arrive on a channel it follows.
cello_channel_poster_addwriteName an active member of a
cello_channel_poster_removedestructiveStop an agent posting to a channel you administer: its pass is revoked in the channel
cello_channel_postingwriteSet who may post to a channel you administer:
cello_channel_prunedestructiveDrop a channel
cello_channel_publishwritePublish a post to a channel this agent holds the key to. The post goes under the channel
cello_channel_readread
cello_channel_refusereadTurn down a request to join. They are told; no key is sent. They must be reachable right now — if they are not, the answer is
cello_channel_resendreadRe-deposit the posts a relay is missing — after it lost content, or when a relay has just been added to the channel. Leave
cello_channel_setupread
cello_channelsreadList the channels this agent follows AND the ones it runs. Local — it reads what this daemon has already collected and asks no relay. A followed channel is role \
cello_close_sessionreadClose a session. Answers as soon as your SEAL commitment is durable (seal_status: \
cello_config_getreadRead one security-layer guard: its value, version, when it last changed (changedAt, epoch ms), and whether its version history still verifies (chainValid false means the record was tampered with; null means it has never been set). Read-only.
cello_config_listreadList the security layer
cello_config_setwrite
cello_contact_addwriteAdd a peer (by hex public key) to an agent
cello_contact_removedestructiveRemove a peer (by hex public key) from an agent
cello_contact_set_awaydestructiveSet (or clear, by passing null) a custom away message for a specific contact — the text they receive when they reach you and you
cello_contact_set_monikerdestructiveSet (or clear, by passing null) YOUR pet name for an existing contact — the top-priority display name shown for them (always wins over the name they offer). Defaults to the current agent.
cello_contact_set_signalwriteChoose whether ONE trust signal is presented to ONE counterparty — finer than the signal
cello_contact_set_tierwriteSet a contact
cello_contactsreadList an agent
cello_dismissread
cello_doc_acceptwriteAccept a proposed document. From this point their signed edits apply to your copy without asking again — that is the agreement, and it is why this is a separate deliberate step.
cello_doc_closereadSay you are done with a shared document. This does not end anyone
cello_doc_diffreadWhat changed in a shared document since YOU last read it. Use this before building on a counterparty
cello_doc_inboxreadDocuments someone has offered YOU that are awaiting your decision. Read what was offered here BEFORE accepting — accepting is what lets their signed edits change your copy from then on.
cello_doc_invitereadInvite a third agent into a shared document you administer. Your signature authors the admitting amendment; THEIR OWN ACCEPT makes the join real — neither alone admits anyone. They receive the document
cello_doc_killdestructiveEnd a shared document NOW, one-sided. No further updates are accepted, in either direction. Your local copy and its history are kept, and so is every other holder
cello_doc_listreadYour shared documents and their state — who each is with, and whether your latest changes have reached them yet.
cello_doc_proposeread
cello_doc_publishwritePublish whatever is in the document
cello_doc_readreadRead a shared document
cello_doc_refusereadRefuse a proposed document. The decision is recorded and final — a proposal is answered once.
cello_doc_removedestructive
cello_doc_watchreadBe woken when a FIELD you care about changes in a shared document. A document update normally raises no doorbell at all — a counterparty typing would interrupt you continuously — so by default you only find out when you next read it. Name the paths you are waiting on (
cello_doc_writewriteReplace a shared document
cello_get_inclusion_proofreadProve that ONE message is in a sealed conversation. Returns a Merkle proof binding the message
cello_inboxwriteCheck for pending inbound session requests and unread messages (the push-loss reconciler — discovers anything missed while this session was away). scope
cello_initiate_sessionwriteStart a new CELLO session with a target agent
cello_list_sessionsread
cello_monikerdestructiveSet (or clear, by passing null) an agent
cello_name_sessionread
cello_policy_listreadThe operator
cello_policy_pendingreadPolicy changes that have been proposed and are waiting for the operator
cello_policy_proposereadDraft a change to your operator
cello_quarantinedreadRead a message CELLO REFUSED and never delivered — an injection attempt, a probe, a tampered or
cello_receivewriteRead every unread message in a session, in order, as
cello_restorereadCheck a backup file and explain how to restore it. Restoring REPLACES this machine
cello_screening_logreadWhat the security layer actually did to your messages, newest first: clean / redacted / blocked / warned, with the rule that fired and the correlation id. Use this when a message did not arrive or arrived altered, BEFORE guessing at a cause — it is the difference between knowing and speculating.
cello_sealed_receiptreadGet the sealed receipt for a closed session. NOTE: the response echoes
cello_sendwriteSend a message in an active session. REQUIRED: every message must include a signal parameter declaring your next action. Every answer that placed a leaf carries
cello_sessionsreadSee https://docs.cello.dev — replaces cello_list_sessions
cello_set_agent_offlinewrite
cello_settings_getread
cello_settings_setwrite
cello_start_agentwriteBRING AN AGENT ONLINE so it can participate in sessions — the lifecycle axis (reverse: cello_set_agent_offline). This does NOT make the agent yours to drive: it stays unattended, so it answers inbound sessions with its away message. Use cello_use_agent to attend it.
cello_statusreadGet daemon and agent status
cello_stop_using_agentwrite
cello_transcriptreadGet the durable, readable conversation transcript for a session (sent + received messages, in order) — recoverable after a daemon restart
cello_trust_signals_disablewriteExclude a signal from the default presentation bundle. The signal is kept and stays valid — this is about what you routinely show, not about retracting anything.
cello_trust_signals_enablewriteInclude a signal in the default presentation bundle sent to contacts. This controls DEFAULT PRESENTATION only — it cannot make a pending or refused signal presentable, because consent is the prior question.
cello_trust_signals_listreadList the trust signals held in this wallet — verifiable claims about you (GitHub account age, phone, email, endorsements from others) that are presented to contacts during sessions. Each row carries TWO independent answers:
cello_trust_signals_revokedestructiveRetract a trust signal about you — your GitHub link, say. The request is QUEUED to the CELLO portal (sealed; the directory cannot read it), which checks the signal is one you may retract and then revokes it at the directory, so the answer here is
cello_trust_signals_viewreadDecode and display one trust signal
cello_use_agentread
cello_verify_inclusion_proofreadCheck an inclusion proof from cello_get_inclusion_proof. Needs only the proof, the message text,
04

Trust audit

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

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

What the source does

Filesystem
declared (1 observation(s))
Network
declared (5 observation(s))
Shell
declared (4 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
core/daemon/src/column-birth.ts:47
db: { exec(sql: string): void },
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
core/daemon/src/contact-pubkey-case.ts:39
exec(sql: string): unknown;
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
core/daemon/src/document-amendment-store.ts:51
type ColumnDropper = { exec(sql: string): void; prepare(sql: string): { all(...a: unknown[]): unknown[] } };
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
core/daemon/src/sqlcipher-db.ts:59
exec(sql: string): void;
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
MEDIUMInventory / provenance · inv.binary · CWE-1104
.DS_Store
.DS_Store
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
core/protocol-types/src/broadcast-artifact.ts
broadcast-artifact.ts
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.binary · CWE-1104
core/protocol-types/src/channel-info.ts
channel-info.ts
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
core/daemon/src/signaling-connect.ts:489
deps.logger.info("directory.online_token.received", { directoryNodeId, bytes: token.length });
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
core/daemon/src/__tests__/m9-core-001-seam.test.ts:598
expect(((await clientA.send("cello_send", { session_id: SID_HEX, content: "deploy aws_key=AKIAABCDEFGHIJKLMNOP" })) as Record<string, unknown>).ok).toBe(true);
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
core/daemon/src/__tests__/m9-core-001-seam.test.ts:846
const sent = await clientA.send("cello_send", { session_id: SID_HEX, content: "deploy with aws_key=AKIAABCDEFGHIJKLMNOP please" }) as Record<string, unknown>;
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
core/daemon/src/__tests__/m9-core-001-seam.test.ts:855
expect(recvText(recv)!).not.toContain("AKIAABCDEFGHIJKLMNOP"); // the secret never reached the peer
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
core/daemon/src/__tests__/m9b-gate-1-composition-root.test.ts:211
new TextEncoder().encode("deploy with aws_key=AKIAABCDEFGHIJKLMNOP now"),
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
core/daemon/src/__tests__/m9b-gate-1-composition-root.test.ts:216
expect(redacted).not.toContain("AKIAABCDEFGHIJKLMNOP");
MEDIUMHard-coded secrets · secret.private_key · CWE-798, CWE-321
core/gateway/src/__tests__/out-001-secrets.test.ts:30
const pem = "-----BEGIN RSA PRIVATE KEY-----\n" + hi(120) + "\n-----END RSA PRIVATE KEY-----";
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
cello_channel_delete, cello_channel_eject, cello_channel_poster_remove, cello_channel_prune, cello_contact_remove, cello_contact_set_away, cello_contact_set_moniker, cello_doc_kill, cello_doc_remove,
Why it matters. 11 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.binary · CWE-1104
core/daemon/src/__tests__/document-profile.test.ts
document-profile.test.ts
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.binary · CWE-1104
core/gateway/src/__tests__/m10b-scan-1-corpus-digest.test.ts
m10b-scan-1-corpus-digest.test.ts
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.hidden_file · CWE-1104
.DS_Store
.DS_Store
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.no_license · CWE-1104
Why it matters. no LICENSE file and no repo licence
Fix. add a licence
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
core/cli/src/__tests__/policy-008-cli.test.ts:229
const daemonTtl = eval(m![1]!) as number;
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
core/adapter-claude-code/src/__tests__/adapter-002.test.ts:161
const skillPath = join(__dirname, "../../SKILL.md");
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
core/adapter-claude-code/src/__tests__/adapter-002.test.ts:210
const content = await readFile(join(__dirname, "../../SKILL.md"), "utf-8");
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
core/adapter-claude-code/src/__tests__/cello-m6b-001-integration.test.ts:65
const binPath = resolve(__dirname, "../../dist/bin/cello-mcp.js");
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
core/adapter-claude-code/src/__tests__/docsflag-2-mcp-tools.test.ts:33
const BIN = resolve(here, "../../dist/bin/cello-mcp.js");
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
core/adapter-claude-code/src/__tests__/dx-001-startup.test.ts:96
const binaryPath = resolve(__dirname, "../../dist/bin/cello-mcp.js");

Gates applied: no_behavioural_pass, no_license.

Audited 2026-10-11 · audit v0.4.1 · source sha 5cbbe6719473full audit observations/trust-audit/mcp-server/mygentic-ai__cello-client.json · Report an issue / request a re-scan
05

Audit history

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

DateSourceVerdictGradeScoreChange
2026-10-115cbbe6719473BLOCKF43first audit
06

Questions

What is the cello-client MCP server?

https://cello.mygentic.ai/l/2axsGFs The official client for the CELLO protocol — lets agents such as Claude Code, Hermes, OpenClaw, etc. connect, message, and collaborate directly across devices and harnesses using MCP

What tools does cello-client expose?

84 in total: 50 read-only, 23 that write, and 11 that can delete or overwrite (cello_channel_delete, cello_channel_eject, cello_channel_poster_remove, cello_channel_prune, cello_contact_remove). Every one is listed on this page with its risk.

Is cello-client safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (43/100) and found 4 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 11 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does cello-client need?

It reads CELLO_CONSORTIUM_ROOT_KEYS and CELLO_PREAUTH_TOKEN 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 cello-client run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as cello-client at 0.0.3.

How current is this page?

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

Advertisement