Atlas / MCP servers / cotal-ai / Cotal

CotalBLOCK

mcp/cotal-ai/cotal

The open standard for agent coordination

Verdict
BLOCK
Grade
F
Trust score
37 /100
Exposed tools
23 14r · 8w · 1d
Transport
stdio · streamable-http
License
Apache-2.0
Stars
324
01

Overview

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

The open pub/sub standard for AI agents.

Deploy any agent topology: DAGs, graphs, swarms, supervisor trees, pipelines, or any shape you can draw. Distributed programming for agents.

[](https://github.com/Cotal-AI/Cotal/actions/workflows/ci.yml) [](https://www.npmjs.com/package/@cotal-ai/core) [](https://docs.cotal.ai) [](https://discord.gg/fhPqe3b4qu) [](LICENSE) [](https://nodejs.org)

Live demo · Examples · Supported agents · FAQ

What is Cotal

Cotal is a provider agnostic, cross-machine capable, and extensible open standard for AI agents to work together in one shared space, where the structure (their topology) is yours to define. Every agent sees who else is there and messages anyone directly.

Most

Read from source at commit 3da7d0c9bb30OBSERVED · 2026-10-12
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 website --env COTAL_ACCEPTED_TOKEN=${COTAL_ACCEPTED_TOKEN} --env COTAL_CONTROL_TOKEN=${COTAL_CONTROL_TOKEN} --env COTAL_DETACH_KEY=${COTAL_DETACH_KEY} --env COTAL_FEEDBACK_KEY=${COTAL_FEEDBACK_KEY} -- npx -y @cotal-ai/[email protected]
claude-desktop
{
  "mcpServers": {
    "website": {
      "command": "npx",
      "args": [
        "-y",
        "@cotal-ai/[email protected]"
      ],
      "env": {
        "COTAL_ACCEPTED_TOKEN": "${COTAL_ACCEPTED_TOKEN}",
        "COTAL_CONTROL_TOKEN": "${COTAL_CONTROL_TOKEN}",
        "COTAL_DETACH_KEY": "${COTAL_DETACH_KEY}",
        "COTAL_FEEDBACK_KEY": "${COTAL_FEEDBACK_KEY}"
      }
    }
  }
}
03

Exposed tools (23)

14 read · 8 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
cotal_anycastwriteSend a request to ANY one available agent of a given role (load-balanced). Use when you need
cotal_channel_inforeadLook up a channel
cotal_channel_modewriteSet how a single channel interrupts you: your per-channel attention, more specific than cotal_status.
cotal_channelsreadDiscover the channels in your space: name, one-line description, whether you
cotal_connection_statusreadReport this session
cotal_describereadList the commands a registered endpoint serves, as this session
cotal_despawnreadAsk the manager to tear a teammate down: it leaves the mesh and its process/tab is closed. Graceful by default (the session exits cleanly first); pass graceful:false for a hard, immediate kill. The inverse of cotal_spawn. Omit
cotal_dmwriteSend a private message to one specific peer, by name (or instance id).
cotal_docsreadRead the authoritative Cotal docs bundled with this installed version: the wire spec, the
cotal_feedbackwriteSend feedback about Cotal to its developers. With a configured feedback key it goes to the keyed beta intake; without one it goes to the public cotal.ai intake, which requires a contact email.
cotal_how_to_joinread
cotal_inboxdestructivePull and clear quiet-channel ambient waiting for you. Connector-managed automatic traffic stays queued; in focus mode, normal channel recall is also shown read-only.
cotal_invokewriteCall one command on a registered endpoint with JSON arguments, over this session
cotal_joinreadSubscribe to a channel mid-session. Returns its registry info; if the channel replays, recent history is delivered to your inbox marked as catch-up (it pre-dates your join, so don
cotal_orientationreadYour orientation card: who you are (name/role/space), the recorded model pin if one was set, the channels you can read and post to,
cotal_personawriteDefine a new persona and save it as config (the manager writes .cotal/agents/<name>.md). It stays silent unless you pass
cotal_personasreadRead the workspace persona catalog the manager owns (.cotal/agents). Omit
cotal_reconnectreadTear down and rebuild this session
cotal_sendwriteBroadcast a message to everyone on a channel in your space.
cotal_statuswriteSet your presence status (what you
cotal_yieldreadReport the outcome of a workflow turn assigned to you. Use this only when your context contains a pending run turn; it does not start a workflow or resolve a checkpoint/ask.\n\nUsually finish your session turn normally: that yields
reviewreadreads diffs
widereadx
04

Trust audit

BLOCKgrade F · trust 37/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 surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (16 observation(s))
Network
declared (15 observation(s))
Shell
declared (9 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
bin/smoke/no-npx-tsx.smoke.ts:117
["backtick exec shell string", "exec(`npx tsx BIN attach`, { cwd: root }, () => {})"],
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
implementations/web/smoke/harness.smoke.ts:35
new Function("window", src)(win);
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
packages/lang/smoke/differential.smoke.ts:109
const evaluate = (module: string) => new Function(`return (${module})`)() as never;
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
packages/lang/smoke/pins.smoke.ts:102
const r = await exec(EPOCH_PROGRAM, {
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
packages/lang/smoke/pins.smoke.ts:121
const first = await exec(CLOCK_PROGRAM, {
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHNetwork egress · net.env_exfil · CWE-200, CWE-319
bin/cotal.ts:45
Object.entries(process.env ... curl
Why it matters. reads secrets in the same file that sends data out
HIGHNetwork egress · net.env_exfil · CWE-200, CWE-319
extensions/connector-codex/src/app-server.ts:324
Object.entries(process.env ... websocket
Why it matters. reads secrets in the same file that sends data out
HIGHNetwork egress · net.tls_off · CWE-200, CWE-319
packages/core/src/broker-tls.ts:218
{ socket, servername: opts.servername ?? opts.host, rejectUnauthorized: false },
Why it matters. certificate verification is disabled
Fix. leave verification on
MEDIUMInsecure crypto · crypto.weak_random · CWE-327, CWE-338
claude-plugin/cotal/dist/hook.cjs:588
let n = Math.floor(Math.random() * tokenSpace);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
bin/smoke/shard-stability.ts:107
* Printing the message first removed one window; `console.log(token)` and
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
bin/smoke/shard-stability.ts:124
console.log(`shard-stability: ${token}=${code}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
implementations/cli/src/commands/down-manifest.ts:327
console.log(c.yellow(`  ~ ${cp.name}: a different live agent holds this name - its secret files are left in place (our grant row is revoked)`));
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
implementations/cli/src/commands/down-manifest.ts:334
console.log(c.dim(`  • removed user-mode authority for ${cp.name} (grant row + token + sentinel)`));
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
implementations/runtime/smoke/mesh-ask.smoke.ts:447
console.log(`  ! answer failed: no pause token to answer (${String(tok)})`);
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
implementations/auth/smoke/barrier-plane.smoke.ts:204
enc.encode(JSON.stringify({ stream_name: authStream, config: { name: exploitName, durable_name: exploitName, filter_subject: exploitFilter, deliver_subject: `attacker.exfil.${space}`, deliver_policy:
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
implementations/auth/smoke/mediator-confinement.smoke.ts:182
() => medNc!.request(`$JS.API.CONSUMER.CREATE.${recordsKvStreamName(SPACE)}.${exploitName}.${exploitFilter}`, enc.encode(JSON.stringify({ stream_name: recordsKvStreamName(SPACE), config: { name: explo
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
bin/smoke/backup-usermode-live.smoke.ts:108
const origin = `http://127.0.0.1:${(idpSrv.address() as AddressInfo).port}`;
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
bin/smoke/discovery-bundle-consumable.smoke.ts:173
const origin = `http://127.0.0.1:${(idpSrv.address() as AddressInfo).port}`;
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
bin/smoke/discovery-bundle-consumable.smoke.ts:223
const PUBLIC = `http://127.0.0.1:${publicPort}`;
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
bin/smoke/dogfood-live.smoke.ts:126
const unauthenticated = await fetch(`http://127.0.0.1:${WEB_PORT}/`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
bin/smoke/dogfood-live.smoke.ts:134
const page = await fetch(`http://127.0.0.1:${WEB_PORT}/`, { headers: authed });
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
implementations/auth/src/session-ledger.ts:282
throw new EpEnvelopeError("failed-precondition", `credential id ${JSON.stringify(id)} names neither session party (....c | ....s); nothing routes (SPEC 13.6)`);
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
bin/smoke/backup-usermode-live.smoke.ts:112
secret: "smoke-only-better-auth-secret-0123456789",
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
bin/smoke/discovery-bundle-consumable.smoke.ts:177
secret: "smoke-only-better-auth-secret-0123456789",
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
bin/smoke/npm-publish-preflight.smoke.ts:129
res.end(JSON.stringify({ token: "opaque-exchange-token" }));

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha 3da7d0c9bb30full audit observations/trust-audit/mcp-server/cotal-ai__cotal.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-123da7d0c9bb30BLOCKF37first audit
06

Questions

What is the @cotal-ai/core MCP server?

The open standard for agent coordination

What tools does @cotal-ai/core expose?

23 in total: 14 read-only, 8 that write, and 1 that can delete or overwrite (cotal_inbox). Every one is listed on this page with its risk.

Is @cotal-ai/core safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (37/100) and found 8 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: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does @cotal-ai/core need?

It reads COTAL_ACCEPTED_TOKEN, COTAL_CONTROL_TOKEN, COTAL_DETACH_KEY, COTAL_FEEDBACK_KEY, COTAL_FEEDBACK_KEYS, COTAL_JCODE_MCP_TOKEN, COTAL_MCP_TOKEN, COTAL_NATIVE_HTTPS_KEY, COTAL_PRIVACY_HOST_TOKENS, COTAL_PRODUCER_HTTPS_KEY, COTAL_SECRETFS_INTERLEAVE_DIST and COTAL_SECRETFS_INTERLEAVE_TARGET 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 @cotal-ai/core run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as @cotal-ai/website at 0.0.0.

How current is this page?

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

Advertisement