cello-clientBLOCK
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
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
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.
5cbbe6719473OBSERVED · 2026-10-11Connect
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 mcp add cello-client --env CELLO_CONSORTIUM_ROOT_KEYS=${CELLO_CONSORTIUM_ROOT_KEYS} --env CELLO_PREAUTH_TOKEN=${CELLO_PREAUTH_TOKEN} -- npx -y [email protected]{
"mcpServers": {
"cello-client": {
"command": "npx",
"args": [
"-y",
"[email protected]"
],
"env": {
"CELLO_CONSORTIUM_ROOT_KEYS": "${CELLO_CONSORTIUM_ROOT_KEYS}",
"CELLO_PREAUTH_TOKEN": "${CELLO_PREAUTH_TOKEN}"
}
}
}
}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.
| Tool | Risk | Description |
|---|---|---|
cello_agents | read | List all agents with state from this connection |
cello_attestation_consent_accept | read | Accept 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_list | read | List 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_refuse | read | |
cello_attestations_issue | read | |
cello_attestations_issued | read | |
cello_await_session | read | Wait for an inbound session request. A |
cello_backup | read | Export this agent to a backup file. THE FILE IS AS SENSITIVE AS A PRIVATE KEY — it contains the agent |
cello_channel_approve | read | Admit 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_create | write | Bring a NEW channel into existence in one step: register the channel identity |
cello_channel_delete | destructive | Delete a channel you administer, permanently. Every current and pending member is told the channel is gone (their subscription is marked |
cello_channel_eject | destructive | Remove a member and rotate the channel |
cello_channel_info | read | Look 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_set | write | Publish the channel |
cello_channel_join | read | Ask a channel |
cello_channel_leave | write | Stop collecting a channel |
cello_channel_name | read | Give 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_notify | read | Choose whether this agent is told when new posts arrive on a channel it follows. |
cello_channel_poster_add | write | Name an active member of a |
cello_channel_poster_remove | destructive | Stop an agent posting to a channel you administer: its pass is revoked in the channel |
cello_channel_posting | write | Set who may post to a channel you administer: |
cello_channel_prune | destructive | Drop a channel |
cello_channel_publish | write | Publish a post to a channel this agent holds the key to. The post goes under the channel |
cello_channel_read | read | |
cello_channel_refuse | read | Turn 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_resend | read | Re-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_setup | read | |
cello_channels | read | List 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_session | read | Close a session. Answers as soon as your SEAL commitment is durable (seal_status: \ |
cello_config_get | read | Read 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_list | read | List the security layer |
cello_config_set | write | |
cello_contact_add | write | Add a peer (by hex public key) to an agent |
cello_contact_remove | destructive | Remove a peer (by hex public key) from an agent |
cello_contact_set_away | destructive | Set (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_moniker | destructive | Set (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_signal | write | Choose whether ONE trust signal is presented to ONE counterparty — finer than the signal |
cello_contact_set_tier | write | Set a contact |
cello_contacts | read | List an agent |
cello_dismiss | read | |
cello_doc_accept | write | Accept 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_close | read | Say you are done with a shared document. This does not end anyone |
cello_doc_diff | read | What changed in a shared document since YOU last read it. Use this before building on a counterparty |
cello_doc_inbox | read | Documents 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_invite | read | Invite 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_kill | destructive | End 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_list | read | Your shared documents and their state — who each is with, and whether your latest changes have reached them yet. |
cello_doc_propose | read | |
cello_doc_publish | write | Publish whatever is in the document |
cello_doc_read | read | Read a shared document |
cello_doc_refuse | read | Refuse a proposed document. The decision is recorded and final — a proposal is answered once. |
cello_doc_remove | destructive | |
cello_doc_watch | read | Be 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_write | write | Replace a shared document |
cello_get_inclusion_proof | read | Prove that ONE message is in a sealed conversation. Returns a Merkle proof binding the message |
cello_inbox | write | Check for pending inbound session requests and unread messages (the push-loss reconciler — discovers anything missed while this session was away). scope |
cello_initiate_session | write | Start a new CELLO session with a target agent |
cello_list_sessions | read | |
cello_moniker | destructive | Set (or clear, by passing null) an agent |
cello_name_session | read | |
cello_policy_list | read | The operator |
cello_policy_pending | read | Policy changes that have been proposed and are waiting for the operator |
cello_policy_propose | read | Draft a change to your operator |
cello_quarantined | read | Read a message CELLO REFUSED and never delivered — an injection attempt, a probe, a tampered or |
cello_receive | write | Read every unread message in a session, in order, as |
cello_restore | read | Check a backup file and explain how to restore it. Restoring REPLACES this machine |
cello_screening_log | read | What 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_receipt | read | Get the sealed receipt for a closed session. NOTE: the response echoes |
cello_send | write | Send 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_sessions | read | See https://docs.cello.dev — replaces cello_list_sessions |
cello_set_agent_offline | write | |
cello_settings_get | read | |
cello_settings_set | write | |
cello_start_agent | write | BRING 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_status | read | Get daemon and agent status |
cello_stop_using_agent | write | |
cello_transcript | read | Get the durable, readable conversation transcript for a session (sent + received messages, in order) — recoverable after a daemon restart |
cello_trust_signals_disable | write | Exclude 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_enable | write | Include 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_list | read | List 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_revoke | destructive | Retract 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_view | read | Decode and display one trust signal |
cello_use_agent | read | |
cello_verify_inclusion_proof | read | Check an inclusion proof from cello_get_inclusion_proof. Needs only the proof, the message text, |
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.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (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)
db: { exec(sql: string): void },exec(sql: string): unknown;
type ColumnDropper = { exec(sql: string): void; prepare(sql: string): { all(...a: unknown[]): unknown[] } };exec(sql: string): void;
.DS_Store
broadcast-artifact.ts
channel-info.ts
deps.logger.info("directory.online_token.received", { directoryNodeId, bytes: token.length });expect(((await clientA.send("cello_send", { session_id: SID_HEX, content: "deploy aws_key=AKIAABCDEFGHIJKLMNOP" })) as Record<string, unknown>).ok).toBe(true);const sent = await clientA.send("cello_send", { session_id: SID_HEX, content: "deploy with aws_key=AKIAABCDEFGHIJKLMNOP please" }) as Record<string, unknown>;expect(recvText(recv)!).not.toContain("AKIAABCDEFGHIJKLMNOP"); // the secret never reached the peernew TextEncoder().encode("deploy with aws_key=AKIAABCDEFGHIJKLMNOP now"),expect(redacted).not.toContain("AKIAABCDEFGHIJKLMNOP");const pem = "-----BEGIN RSA PRIVATE KEY-----\n" + hi(120) + "\n-----END RSA PRIVATE KEY-----";
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,
document-profile.test.ts
m10b-scan-1-corpus-digest.test.ts
.DS_Store
const daemonTtl = eval(m![1]!) as number;
const skillPath = join(__dirname, "../../SKILL.md");
const content = await readFile(join(__dirname, "../../SKILL.md"), "utf-8");
const binPath = resolve(__dirname, "../../dist/bin/cello-mcp.js");
const BIN = resolve(here, "../../dist/bin/cello-mcp.js");
const binaryPath = resolve(__dirname, "../../dist/bin/cello-mcp.js");
Gates applied: no_behavioural_pass, no_license.
5cbbe6719473full audit observations/trust-audit/mcp-server/mygentic-ai__cello-client.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-11 | 5cbbe6719473 | BLOCK | F | 43 | first audit |
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.