@cello-protocol/connect 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SKILL.md ADDED
@@ -0,0 +1,135 @@
1
+ # CELLO — Claude Code MCP Adapter
2
+
3
+ Peer-to-peer signed messaging for Claude Code agents. Agents communicate
4
+ directly and tamper-evidently, without a central server in the message path.
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ claude mcp add cello npx @cello-protocol/connect
10
+ ```
11
+
12
+ This registers CELLO as an MCP server named `cello`. The package is
13
+ `@cello-protocol/connect`.
14
+
15
+ ## Launch with channels
16
+
17
+ ```bash
18
+ claude --channels server:cello
19
+ ```
20
+
21
+ The `--channels` flag enables push notifications. When a peer sends a message
22
+ or initiates a session, Claude Code starts a new turn automatically — no
23
+ polling required.
24
+
25
+ ## Verify
26
+
27
+ Call the `cello_status` tool. You should see:
28
+
29
+ ```json
30
+ {
31
+ "transport_started": true,
32
+ "own_pubkey": "<your 64-char hex pubkey>",
33
+ "listen_addresses": ["/ip4/..."],
34
+ "connected_peer_count": 0,
35
+ "uptime_seconds": 0,
36
+ "active_session_count": 0,
37
+ "directory_reachable": false
38
+ }
39
+ ```
40
+
41
+ Share your `own_pubkey` with the peer you want to communicate with.
42
+
43
+ ## Configuration
44
+
45
+ | Environment variable | Default | Description |
46
+ |---|---|---|
47
+ | `CELLO_KEY_FILE` | `~/.cello/key` | Path to your Ed25519 key file. Created on first run with `chmod 600`. |
48
+ | `CELLO_LISTEN_ADDR` | `/ip4/0.0.0.0/tcp/0` | libp2p listen address. Use a fixed port if you need a stable multiaddr. |
49
+ | `CELLO_DIRECTORY_URL` | *(required)* | Directory node multiaddr, e.g. `/dns4/directory-us1.cello.mygentic.ai/tcp/80/ws/p2p/<pubkey>` |
50
+
51
+ ## Usage — M6 tools
52
+
53
+ ### Register with the network
54
+
55
+ ```
56
+ cello_register()
57
+ → { ok: true, own_pubkey: "<hex>", primary_pubkey: "<hex>" }
58
+ ```
59
+
60
+ Register this agent with the CELLO directory. Required before you can send or
61
+ receive messages. Run once; credentials persist in `~/.cello/key`.
62
+
63
+ ### Send a message
64
+
65
+ ```
66
+ cello_send({ session_id: "<hex>", content: "hello" })
67
+ → { delivered: true }
68
+ ```
69
+
70
+ Send a signed message on an active session. Content is encrypted at rest on
71
+ the relay — the relay sees only the signed hash.
72
+
73
+ ### Receive a message
74
+
75
+ ```
76
+ cello_receive({ session_id: "<hex>", timeout_ms: 30000 })
77
+ → { type: "message", content: "hello back", session_id: "<hex>", sender_pubkey: "<hex>", seq: 1 }
78
+ ```
79
+
80
+ Block until a message arrives on the session (or timeout). Call immediately
81
+ after waking from a `cello_message` channel notification.
82
+
83
+ ### Check status
84
+
85
+ ```
86
+ cello_status()
87
+ → { transport_started: true, own_pubkey: "<hex>", active_session_count: 1, directory_reachable: true, ... }
88
+ ```
89
+
90
+ ### Full tool list (M6)
91
+
92
+ ```
93
+ cello_register() — register with the CELLO directory
94
+ cello_status() — connection and session status
95
+ cello_initiate_session({ target_pubkey }) — start a session with a peer
96
+ cello_await_session({ timeout_ms }) — wait for an inbound session request
97
+ cello_send({ session_id, content }) — send a message on a session
98
+ cello_receive({ session_id, timeout_ms }) — receive a message on a session
99
+ cello_list_sessions() — list all active sessions
100
+ cello_close_session({ session_id }) — close a session
101
+ cello_get_sealed_receipt({ session_id }) — get the tamper-evident seal after close
102
+ cello_get_inclusion_proof({ session_id, content_hash }) — Merkle proof for a message
103
+ cello_request_connection({ target_pubkey, message }) — request to connect to a peer
104
+ cello_list_connections() — list connection requests and their status
105
+ cello_get_policy() — get your current connection policy
106
+ cello_set_policy({ policy }) — set your connection policy
107
+ cello_backup() — export an encrypted key backup
108
+ cello_restore({ backup }) — restore from a backup
109
+ ```
110
+
111
+ ## Quick start — connect to a peer
112
+
113
+ ```
114
+ # Both agents run this first:
115
+ cello_register()
116
+
117
+ # Agent A shares their own_pubkey with Agent B.
118
+ # Agent A initiates the session:
119
+ cello_initiate_session({ target_pubkey: "<Agent B pubkey>" })
120
+ → { ok: true, session_id: "<hex>" }
121
+
122
+ # Agent B receives the session request:
123
+ cello_await_session({ timeout_ms: 30000 })
124
+ → { type: "new_session", session_id: "<hex>", counterparty_pubkey: "<hex>" }
125
+
126
+ # Agent A sends:
127
+ cello_send({ session_id: "<hex>", content: "hello from Agent A" })
128
+
129
+ # Agent B receives:
130
+ cello_receive({ session_id: "<hex>", timeout_ms: 30000 })
131
+ → { type: "message", content: "hello from Agent A", ... }
132
+ ```
133
+
134
+ When a message arrives, Claude Code wakes up automatically (via `--channels`)
135
+ and can call `cello_receive` immediately.
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cello-mcp — single-identity CELLO MCP server
4
+ *
5
+ * One key file. One libp2p node. One client. One MCP server.
6
+ * Two agents = two separate processes, each running this binary with their own CELLO_KEY_FILE.
7
+ *
8
+ * Environment variables:
9
+ * CELLO_KEY_FILE Path to Ed25519 key file (default: ~/.cello/key)
10
+ * CELLO_LISTEN_ADDR libp2p listen address (default: /ip4/0.0.0.0/tcp/0)
11
+ * CELLO_DIRECTORY_URL Production directory HTTP endpoint (default: https://directory-us1.cello.mygentic.ai)
12
+ * Overridable for local/staging deployments. Relay multiaddr is
13
+ * dynamically assigned per-session — no relay constant is baked in.
14
+ * CELLO_DIRECTORY_MULTIADDR Directory libp2p multiaddr (optional; used when dialing libp2p directly)
15
+ * NODE_ENV=test Enables FROST bootstrap (production will use real DKG)
16
+ * CELLO_ENV Deployment environment: local | dev | staging | production
17
+ * CELLO_DB_PATH Path to local SQLCipher database (default: ~/.cello/client.db)
18
+ * BACKUP_S3_BUCKET S3 bucket for encrypted backups (required for S3 backup)
19
+ * CELLO_AWS_REGION AWS region for S3 (default: eu-west-1; falls back to AWS_REGION)
20
+ *
21
+ * Backup selection (PERSIST-022):
22
+ * CELLO_ENV=local → LocalCloudStorageProvider (filesystem)
23
+ * CELLO_ENV != local + BACKUP_S3_BUCKET → S3CloudStorageProvider (uses CELLO_AWS_REGION or AWS_REGION)
24
+ * CELLO_ENV != local + no BACKUP_S3_BUCKET → null (no backup; client.backup.not.configured logged)
25
+ */
26
+ export {};
27
+ //# sourceMappingURL=cello-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cello-mcp.d.ts","sourceRoot":"","sources":["../../src/bin/cello-mcp.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cello-mcp — single-identity CELLO MCP server
4
+ *
5
+ * One key file. One libp2p node. One client. One MCP server.
6
+ * Two agents = two separate processes, each running this binary with their own CELLO_KEY_FILE.
7
+ *
8
+ * Environment variables:
9
+ * CELLO_KEY_FILE Path to Ed25519 key file (default: ~/.cello/key)
10
+ * CELLO_LISTEN_ADDR libp2p listen address (default: /ip4/0.0.0.0/tcp/0)
11
+ * CELLO_DIRECTORY_URL Production directory HTTP endpoint (default: https://directory-us1.cello.mygentic.ai)
12
+ * Overridable for local/staging deployments. Relay multiaddr is
13
+ * dynamically assigned per-session — no relay constant is baked in.
14
+ * CELLO_DIRECTORY_MULTIADDR Directory libp2p multiaddr (optional; used when dialing libp2p directly)
15
+ * NODE_ENV=test Enables FROST bootstrap (production will use real DKG)
16
+ * CELLO_ENV Deployment environment: local | dev | staging | production
17
+ * CELLO_DB_PATH Path to local SQLCipher database (default: ~/.cello/client.db)
18
+ * BACKUP_S3_BUCKET S3 bucket for encrypted backups (required for S3 backup)
19
+ * CELLO_AWS_REGION AWS region for S3 (default: eu-west-1; falls back to AWS_REGION)
20
+ *
21
+ * Backup selection (PERSIST-022):
22
+ * CELLO_ENV=local → LocalCloudStorageProvider (filesystem)
23
+ * CELLO_ENV != local + BACKUP_S3_BUCKET → S3CloudStorageProvider (uses CELLO_AWS_REGION or AWS_REGION)
24
+ * CELLO_ENV != local + no BACKUP_S3_BUCKET → null (no backup; client.backup.not.configured logged)
25
+ */
26
+ import { homedir } from "node:os";
27
+ import { createWriteStream, readFileSync } from "node:fs";
28
+ // Tee stderr to a log file for diagnostics (especially [sigstream] instrumentation)
29
+ const stderrLog = createWriteStream("/tmp/cello-mcp-stderr.log", { flags: "a" });
30
+ const origWrite = process.stderr.write.bind(process.stderr);
31
+ // Override stderr.write to tee output to the log file.
32
+ // We handle only the most common call signature (string/Buffer + optional encoding/callback).
33
+ process.stderr.write = (chunk, encodingOrCb, cb) => {
34
+ stderrLog.write(chunk);
35
+ if (typeof encodingOrCb === "function") {
36
+ return origWrite(chunk, encodingOrCb);
37
+ }
38
+ else if (encodingOrCb !== undefined) {
39
+ return origWrite(chunk, encodingOrCb, cb);
40
+ }
41
+ return origWrite(chunk);
42
+ };
43
+ import { join } from "node:path";
44
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
45
+ import { FileKeyProvider, FrostThresholdSigner } from "@cello-protocol/crypto";
46
+ import { bootstrapKeyShares } from "@cello-protocol/crypto/frost/frost-threshold-signer.js";
47
+ import { createInProcessStubs } from "@cello-protocol/crypto/frost/stubs.js";
48
+ import { createNode } from "@cello-protocol/transport";
49
+ import { createClient, createMcpSessionServer, NetworkDirectoryNode, bootstrapNetworkKeyShares, ClientBackup, S3CloudStorageProvider } from "@cello-protocol/client";
50
+ import { LocalCloudStorageProvider } from "@cello-protocol/interfaces/stubs";
51
+ import { pushChannelNotification } from "../notifications.js";
52
+ import { resolveDirectoryUrl } from "../config.js";
53
+ const keyPath = process.env["CELLO_KEY_FILE"] ?? join(homedir(), ".cello", "key");
54
+ const listenAddr = process.env["CELLO_LISTEN_ADDR"] ?? "/ip4/0.0.0.0/tcp/0";
55
+ // AC-003 (REPOSPLIT-002): production directory endpoint baked in as default; overridable by env.
56
+ // Relay multiaddr is dynamically assigned per-session — no relay constant is baked in.
57
+ const directoryUrl = resolveDirectoryUrl(process.env);
58
+ const directoryMultiaddr = process.env["CELLO_DIRECTORY_MULTIADDR"];
59
+ const celloEnv = process.env["CELLO_ENV"] ?? "local";
60
+ const dbPath = process.env["CELLO_DB_PATH"] ?? join(homedir(), ".cello", "client.db");
61
+ const backupS3Bucket = process.env["BACKUP_S3_BUCKET"];
62
+ // CELLO_AWS_REGION is the operator-settable variable (AWS_REGION is reserved by ECS/Lambda)
63
+ const awsRegion = process.env["CELLO_AWS_REGION"] ?? process.env["AWS_REGION"] ?? "eu-west-1";
64
+ // Load key
65
+ let kp;
66
+ try {
67
+ kp = await FileKeyProvider.load(keyPath);
68
+ }
69
+ catch (err) {
70
+ const msg = typeof err === "object" && err !== null && "message" in err
71
+ ? err.message
72
+ : String(err);
73
+ process.stderr.write(`cello-mcp: key file error: ${msg}\n`);
74
+ process.exit(1);
75
+ }
76
+ // PERSIST-022: Read identity key (Ed25519 seed) from the key file for backup derivation.
77
+ // Key file format (from packages/crypto/src/ed25519.ts):
78
+ // Magic[0..3] = [0xce, 0x11, 0x0e, 0x01] ("CELLO\x01" marker)
79
+ // version[4] = 0x01
80
+ // seed[5..36] = 32-byte Ed25519 seed
81
+ // Total: 37 bytes (KEY_FILE_SIZE)
82
+ // The seed is used only for HKDF derivation (backup_key and db_key).
83
+ // It is never stored, never logged, and is zeroed after ClientBackup construction.
84
+ const KEY_FILE_MAGIC = new Uint8Array([0xce, 0x11, 0x0e, 0x01]);
85
+ const KEY_FILE_VERSION = 0x01;
86
+ const KEY_FILE_SIZE = 37; // Magic(4) + version(1) + seed(32)
87
+ const SEED_OFFSET = 5; // KEY_FILE_MAGIC.length + 1
88
+ const SEED_LENGTH = 32;
89
+ let identityKeyBytes = null;
90
+ try {
91
+ const rawKeyFile = readFileSync(keyPath);
92
+ // Validate exact file size
93
+ if (rawKeyFile.length === KEY_FILE_SIZE) {
94
+ // Validate magic bytes to ensure this is a valid CELLO key file
95
+ const magicOk = KEY_FILE_MAGIC.every((b, i) => rawKeyFile[i] === b);
96
+ // Validate version byte
97
+ const versionOk = rawKeyFile[KEY_FILE_MAGIC.length] === KEY_FILE_VERSION;
98
+ if (magicOk && versionOk) {
99
+ identityKeyBytes = new Uint8Array(rawKeyFile.slice(SEED_OFFSET, SEED_OFFSET + SEED_LENGTH));
100
+ }
101
+ else {
102
+ process.stderr.write(`cello-mcp: key file has invalid magic bytes or version — backup disabled\n`);
103
+ }
104
+ }
105
+ else {
106
+ process.stderr.write(`cello-mcp: key file has unexpected size (${rawKeyFile.length} bytes, expected ${KEY_FILE_SIZE}) — backup disabled\n`);
107
+ }
108
+ }
109
+ catch {
110
+ // Non-fatal: if the key file can't be read for backup derivation, backup is disabled
111
+ process.stderr.write(`cello-mcp: could not read identity key for backup derivation — backup disabled\n`);
112
+ }
113
+ // PERSIST-022: Derive agentId from the public key
114
+ const ownPubkeyForBackup = await kp.getPublicKey();
115
+ const agentId = Buffer.from(ownPubkeyForBackup).toString("hex");
116
+ // PERSIST-022: Select CloudStorageProvider based on CELLO_ENV and BACKUP_S3_BUCKET
117
+ let cloudStorageForBackup = null;
118
+ if (celloEnv === "local") {
119
+ // Local: use filesystem-backed provider in ~/.cello/backups
120
+ const localBackupDir = join(homedir(), ".cello", "backups");
121
+ cloudStorageForBackup = new LocalCloudStorageProvider(localBackupDir);
122
+ process.stderr.write(`cello-mcp: backup: using LocalCloudStorageProvider at ${localBackupDir}\n`);
123
+ }
124
+ else if (backupS3Bucket) {
125
+ // Non-local with bucket configured: use S3
126
+ cloudStorageForBackup = new S3CloudStorageProvider({ bucket: backupS3Bucket, region: awsRegion });
127
+ process.stderr.write(`cello-mcp: backup: using S3CloudStorageProvider, bucket=${backupS3Bucket}, region=${awsRegion}\n`);
128
+ }
129
+ else {
130
+ // Non-local without bucket: no backup configured — ClientBackup will log client.backup.not.configured
131
+ process.stderr.write(`cello-mcp: backup: BACKUP_S3_BUCKET not set — backup not configured\n`);
132
+ }
133
+ // PERSIST-022: Construct ClientBackup (only if identity key is available)
134
+ // A minimal logger for the composition root backup instance that writes to stderr.
135
+ // In production deployments the full structured logger is wired in via server.ts.
136
+ const backupLogger = {
137
+ debug: (event, ctx) => process.stderr.write(`cello-mcp: [debug] ${event} ${JSON.stringify(ctx ?? {})}\n`),
138
+ info: (event, ctx) => process.stderr.write(`cello-mcp: [info] ${event} ${JSON.stringify(ctx ?? {})}\n`),
139
+ warn: (event, ctx) => process.stderr.write(`cello-mcp: [warn] ${event} ${JSON.stringify(ctx ?? {})}\n`),
140
+ error: (event, ctx) => process.stderr.write(`cello-mcp: [error] ${event} ${JSON.stringify(ctx ?? {})}\n`),
141
+ };
142
+ let clientBackupInstance;
143
+ if (identityKeyBytes) {
144
+ clientBackupInstance = new ClientBackup({
145
+ agentId,
146
+ identityKey: identityKeyBytes,
147
+ dbPath,
148
+ cloudStorage: cloudStorageForBackup,
149
+ logger: backupLogger,
150
+ destinationType: celloEnv === "local" ? "local" : (backupS3Bucket ? "s3" : "local"),
151
+ });
152
+ // Zero the identity key bytes immediately after construction — it must not linger in memory (SI-001)
153
+ identityKeyBytes.fill(0);
154
+ identityKeyBytes = null;
155
+ }
156
+ // Parse directory endpoint from CELLO_DIRECTORY_MULTIADDR (if set)
157
+ let directoryEndpoint = undefined;
158
+ if (directoryMultiaddr) {
159
+ const parts = directoryMultiaddr.split("/");
160
+ const p2pIndex = parts.findIndex((p) => p === "p2p");
161
+ const peerId = p2pIndex !== -1 ? parts[p2pIndex + 1] : null;
162
+ if (peerId) {
163
+ directoryEndpoint = { peer_id: peerId, multiaddrs: [directoryMultiaddr] };
164
+ }
165
+ else {
166
+ process.stderr.write("cello-mcp: CELLO_DIRECTORY_MULTIADDR must include /p2p/<peer-id>\n");
167
+ }
168
+ }
169
+ // Create and start single node
170
+ const node = await createNode({ keyProvider: kp, listenAddresses: [listenAddr] });
171
+ await node.start();
172
+ // Bootstrap FROST key shares (test-only shortcut)
173
+ // In production (M3+), real DKG ceremony replaces this.
174
+ let thresholdSigner;
175
+ let primaryPubkey;
176
+ process.stderr.write(`cello-mcp: NODE_ENV=${process.env.NODE_ENV ?? "(unset)"} CELLO_DIRECTORY_URL=${directoryUrl} CELLO_DIRECTORY_MULTIADDR=${directoryMultiaddr ?? "(unset)"}\n`);
177
+ if (process.env.NODE_ENV === "test") {
178
+ const ownPubkey = await kp.getPublicKey();
179
+ if (directoryMultiaddr && directoryEndpoint) {
180
+ process.stderr.write(`cello-mcp: bootstrapping FROST via network directory...\n`);
181
+ try {
182
+ await node.dial(directoryEndpoint.multiaddrs[0]);
183
+ process.stderr.write(`cello-mcp: node dialed directory OK\n`);
184
+ const networkNodes = [new NetworkDirectoryNode({
185
+ id: `cello-test-node-0000`,
186
+ node,
187
+ directoryPeerId: directoryEndpoint.peer_id,
188
+ directoryMultiaddrs: directoryEndpoint.multiaddrs,
189
+ })];
190
+ const bootstrap = await bootstrapNetworkKeyShares(ownPubkey, {
191
+ threshold: 2,
192
+ participants: 1,
193
+ directoryNodes: networkNodes,
194
+ });
195
+ thresholdSigner = bootstrap.signer;
196
+ primaryPubkey = bootstrap.primaryPubkey;
197
+ process.stderr.write(`cello-mcp: FROST bootstrap OK, primaryPubkey=${Buffer.from(primaryPubkey).toString("hex").slice(0, 16)}...\n`);
198
+ }
199
+ catch (err) {
200
+ const msg = err instanceof Error ? `${err.name}: ${err.message}\n${err.stack}` : JSON.stringify(err);
201
+ process.stderr.write(`cello-mcp: FROST bootstrap FAILED: ${msg}\n`);
202
+ process.stderr.write(`cello-mcp: falling back to in-process stubs\n`);
203
+ // Fall back to in-process stubs so the server starts but without directory FROST
204
+ const stubs = createInProcessStubs(3);
205
+ const ownPubkeyFresh = await kp.getPublicKey();
206
+ const bootstrapResult = await bootstrapKeyShares(ownPubkeyFresh, { threshold: 2, participants: 3, directoryNodeStubs: stubs });
207
+ thresholdSigner = new FrostThresholdSigner({ threshold: 2, participants: 3, directoryNodeStubs: stubs }, ownPubkeyFresh);
208
+ primaryPubkey = bootstrapResult.primaryPubkey;
209
+ }
210
+ }
211
+ else {
212
+ // Fallback: in-process stubs (no directory reachable)
213
+ const stubs = createInProcessStubs(3);
214
+ const ownPubkeyFresh = await kp.getPublicKey();
215
+ const bootstrapResult = await bootstrapKeyShares(ownPubkeyFresh, { threshold: 2, participants: 3, directoryNodeStubs: stubs });
216
+ thresholdSigner = new FrostThresholdSigner({ threshold: 2, participants: 3, directoryNodeStubs: stubs }, ownPubkeyFresh);
217
+ primaryPubkey = bootstrapResult.primaryPubkey;
218
+ }
219
+ }
220
+ // Late-bound server reference — set after createMcpServer returns.
221
+ // The closure captures the box; notifications fired before server is assigned are dropped.
222
+ let mcpServer;
223
+ // Create single client
224
+ const client = createClient(node, kp, {
225
+ thresholdSigner,
226
+ directoryEndpoint,
227
+ onMessageQueued: (senderHex) => {
228
+ if (mcpServer)
229
+ void pushChannelNotification(mcpServer, senderHex);
230
+ },
231
+ });
232
+ if (primaryPubkey) {
233
+ client.setPrimaryPubkey(primaryPubkey);
234
+ }
235
+ // Create server with single identity.
236
+ // PERSIST-017: checkpointStatusProvider is not available in the cello-mcp binary
237
+ // (the client binary has no access to the directory's MmrStore). The provider is
238
+ // wired in directory-facing deployments via the server.ts composition root.
239
+ // Passing undefined is a safe fallback — the tools return M1 stub responses.
240
+ // PERSIST-022: clientBackupInstance passed so cello_backup/cello_restore are registered
241
+ // inside createMcpSessionServer (single canonical registration path).
242
+ const server = createMcpSessionServer(node, client, kp, { clientBackup: clientBackupInstance });
243
+ mcpServer = server;
244
+ // Connect stdio transport and register handler
245
+ await server.connect(new StdioServerTransport());
246
+ await client.registerHandler();
247
+ //# sourceMappingURL=cello-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cello-mcp.js","sourceRoot":"","sources":["../../src/bin/cello-mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * CELLO adapter runtime configuration.
3
+ *
4
+ * AC-003 (REPOSPLIT-002): CELLO_DIRECTORY_URL defaults to the production directory
5
+ * ALB endpoint. No CELLO_RELAY_MULTIADDR constant exists — relay multiaddr is
6
+ * dynamically assigned per-session by the directory.
7
+ */
8
+ /** Production directory HTTPS endpoint (ALB / Route53). */
9
+ export declare const PRODUCTION_DIRECTORY_URL = "https://directory-us1.cello.mygentic.ai";
10
+ /**
11
+ * Resolve the directory URL from the environment, falling back to the
12
+ * production endpoint when CELLO_DIRECTORY_URL is not set.
13
+ *
14
+ * @param env - process.env or a test substitute
15
+ */
16
+ export declare function resolveDirectoryUrl(env?: Record<string, string | undefined>): string;
17
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2DAA2D;AAC3D,eAAO,MAAM,wBAAwB,4CAA4C,CAAC;AAElF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,MAAM,CAEjG"}
package/dist/config.js ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * CELLO adapter runtime configuration.
3
+ *
4
+ * AC-003 (REPOSPLIT-002): CELLO_DIRECTORY_URL defaults to the production directory
5
+ * ALB endpoint. No CELLO_RELAY_MULTIADDR constant exists — relay multiaddr is
6
+ * dynamically assigned per-session by the directory.
7
+ */
8
+ /** Production directory HTTPS endpoint (ALB / Route53). */
9
+ export const PRODUCTION_DIRECTORY_URL = "https://directory-us1.cello.mygentic.ai";
10
+ /**
11
+ * Resolve the directory URL from the environment, falling back to the
12
+ * production endpoint when CELLO_DIRECTORY_URL is not set.
13
+ *
14
+ * @param env - process.env or a test substitute
15
+ */
16
+ export function resolveDirectoryUrl(env = process.env) {
17
+ return env["CELLO_DIRECTORY_URL"] ?? PRODUCTION_DIRECTORY_URL;
18
+ }
19
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2DAA2D;AAC3D,MAAM,CAAC,MAAM,wBAAwB,GAAG,yCAAyC,CAAC;AAElF;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA0C,OAAO,CAAC,GAAG;IACvF,OAAO,GAAG,CAAC,qBAAqB,CAAC,IAAI,wBAAwB,CAAC;AAChE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
- export {};
1
+ export { createMcpServer } from "./server.js";
2
+ export { pushChannelNotification, pushSessionRequestNotification } from "./notifications.js";
3
+ export { resolveDirectoryUrl, PRODUCTION_DIRECTORY_URL } from "./config.js";
2
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
- export {};
2
- // placeholder code moves here during REPOSPLIT-002
1
+ export { createMcpServer } from "./server.js";
2
+ export { pushChannelNotification, pushSessionRequestNotification } from "./notifications.js";
3
+ export { resolveDirectoryUrl, PRODUCTION_DIRECTORY_URL } from "./config.js";
3
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,qDAAqD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Push a claude/channel wake-up notification to the connected Claude Code session.
4
+ * Content is never included — the agent calls cello_receive to retrieve the message.
5
+ * SI-001 (ADAPTER-001): notification payload contains only type and sender pubkey.
6
+ */
7
+ export declare function pushChannelNotification(server: McpServer, from: string): Promise<void>;
8
+ /**
9
+ * Push a cello_session_request claude/channel notification to the connected Claude Code session.
10
+ * Carries only counterparty pubkey and session_id — no content, no multiaddrs, no trust data.
11
+ * SI-001 (ADAPTER-002): notification payload contains exactly type, from, and session_id.
12
+ * The agent calls cello_await_session to retrieve the full session details.
13
+ */
14
+ export declare function pushSessionRequestNotification(server: McpServer, from: string, sessionId: string): Promise<void>;
15
+ //# sourceMappingURL=notifications.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS5F;AAED;;;;;GAKG;AACH,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Push a claude/channel wake-up notification to the connected Claude Code session.
3
+ * Content is never included — the agent calls cello_receive to retrieve the message.
4
+ * SI-001 (ADAPTER-001): notification payload contains only type and sender pubkey.
5
+ */
6
+ export async function pushChannelNotification(server, from) {
7
+ try {
8
+ await server.server.notification({
9
+ method: "notifications/claude/channel",
10
+ params: { type: "cello_message", from },
11
+ });
12
+ }
13
+ catch {
14
+ // Transport may not be connected or may have closed — silently swallow
15
+ }
16
+ }
17
+ /**
18
+ * Push a cello_session_request claude/channel notification to the connected Claude Code session.
19
+ * Carries only counterparty pubkey and session_id — no content, no multiaddrs, no trust data.
20
+ * SI-001 (ADAPTER-002): notification payload contains exactly type, from, and session_id.
21
+ * The agent calls cello_await_session to retrieve the full session details.
22
+ */
23
+ export async function pushSessionRequestNotification(server, from, sessionId) {
24
+ try {
25
+ await server.server.notification({
26
+ method: "notifications/claude/channel",
27
+ params: { type: "cello_session_request", from, session_id: sessionId },
28
+ });
29
+ }
30
+ catch {
31
+ // Transport may not be connected or may have closed — silently swallow
32
+ }
33
+ }
34
+ //# sourceMappingURL=notifications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAiB,EAAE,IAAY;IAC3E,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;YAC/B,MAAM,EAAE,8BAA8B;YACtC,MAAM,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE;SACxC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,MAAiB,EACjB,IAAY,EACZ,SAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;YAC/B,MAAM,EAAE,8BAA8B;YACtC,MAAM,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE;SACvE,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;AACH,CAAC"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * CELLO Adapter — server.ts (ADAPTER-002 / M1)
3
+ *
4
+ * createMcpServer(node, client, keyProvider): McpServer
5
+ * Registers the M1 tool set against a CelloClient.
6
+ * Transport-agnostic: identical tool names, schemas, and wiring under
7
+ * InMemoryTransport (tests) and stdio (production). AC-007.
8
+ *
9
+ * PSEUDOCODE (Phase P — ADAPTER-002):
10
+ *
11
+ * State held by the MCP server instance:
12
+ * sessionEventQueue: Array<InboundSessionEvent> FIFO; populated by onSessionAssignment handler
13
+ * sessionEventResolvers: Array<(event: InboundSessionEvent) => void> blocked cello_await_session waiters
14
+ * startedAt: number = Date.now()
15
+ *
16
+ * Session event enqueue (onSessionAssignment handler):
17
+ * Receives: SessionAssignmentEvent { sessionIdHex, counterpartyPubkeyHex, genesisPrevRootHex }
18
+ * (from CelloClient.onSessionAssignment per CELLO-MCP-002; fields are pre-encoded as hex)
19
+ * 1. Push cello_session_request notification via claude/channel (SI-001: only type, from, session_id)
20
+ * 2. If sessionEventResolvers.length > 0:
21
+ * - shift the first resolver and call it with the event (wake up blocked cello_await_session)
22
+ * 3. Else:
23
+ * - Push event to sessionEventQueue
24
+ *
25
+ * tool: cello_initiate_session({ target_pubkey: string })
26
+ * Delegates to CelloClient.initiateSession (added by MCP-002).
27
+ * Returns { ok: true, session_id: hex } or { ok: false, reason: string }.
28
+ * Stubbed if method not present on client.
29
+ *
30
+ * tool: cello_await_session({ timeout_ms: number })
31
+ * 1. If sessionEventQueue.length > 0:
32
+ * - shift first event
33
+ * - return { type: 'new_session', session_id, counterparty_pubkey, genesis_prev_root }
34
+ * 2. Else: block until event arrives or timeout expires:
35
+ * - Create a Promise that resolves when an event arrives or deadline fires
36
+ * - Push a resolver into sessionEventResolvers
37
+ * - Race: event arrival vs setTimeout(timeout_ms)
38
+ * - On arrival: return new_session
39
+ * - On timeout: remove resolver from array; return { type: 'timeout' }
40
+ *
41
+ * tool: cello_send({ session_id: string, content: string })
42
+ * 1. Guard: transport_not_started
43
+ * 2. UTF-8 encode content → contentBytes
44
+ * 3. client.sendMessage(session_id, contentBytes) → SendMessageResult
45
+ * 4. Map to MCP output:
46
+ * ok:true → { delivered: true }
47
+ * ok:false → { delivered: false, reason: result.reason }
48
+ *
49
+ * tool: cello_receive_session({ session_id: string, timeout_ms: number })
50
+ * 1. Guard: transport_not_started
51
+ * 2. deadline = Date.now() + timeout_ms
52
+ * 3. Poll every 20ms until deadline:
53
+ * a. msg = client.receiveMessage(session_id)
54
+ * b. if msg: return formatted message result
55
+ * c. await sleep(Math.min(20, remaining))
56
+ * 4. return { type: 'timeout' }
57
+ *
58
+ * tool: cello_close_session({ session_id: string })
59
+ * client.closeSession(session_id)
60
+ * return { closed: true }
61
+ *
62
+ * tool: cello_list_sessions()
63
+ * return client.listSessions() mapped to wire shape
64
+ *
65
+ * tool: cello_get_sealed_receipt({ session_id: string })
66
+ * Stubbed in M1: return { available: false, reason: 'not_yet_sealed' }
67
+ * (SESSION-003 implements real seals)
68
+ *
69
+ * tool: cello_get_inclusion_proof({ session_id: string, content_hash: string })
70
+ * Stubbed in M1: return { available: false, reason: 'not_yet_sealed' }
71
+ *
72
+ * tool: cello_status()
73
+ * 1. ownPubkey = Buffer.from(await keyProvider.getPublicKey()).toString('hex')
74
+ * 2. sessions = client.listSessions()
75
+ * 3. return {
76
+ * transport_started: transportStarted(),
77
+ * own_pubkey: ownPubkey,
78
+ * listen_addresses: node.listenAddresses(),
79
+ * connected_peer_count: node.getConnections().length,
80
+ * uptime_seconds: Math.floor((Date.now() - startedAt) / 1000),
81
+ * active_session_count: sessions.filter(s => s.status === 'active').length,
82
+ * directory_reachable: false // M1 stub — directory reachability check deferred
83
+ * }
84
+ */
85
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
86
+ import type { CelloClient, ClientBackup } from "@cello-protocol/client";
87
+ import type { CelloNode } from "@cello-protocol/transport";
88
+ import type { KeyProvider } from "@cello-protocol/crypto";
89
+ import type { CheckpointStatusProvider } from "@cello-protocol/interfaces";
90
+ export declare function createMcpServer(node: CelloNode, client: CelloClient, keyProvider: KeyProvider, opts?: {
91
+ checkpointStatusProvider?: CheckpointStatusProvider;
92
+ clientBackup?: ClientBackup;
93
+ }): McpServer;
94
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,WAAW,EAA0B,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAChG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAoB3E,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,WAAW,EACxB,IAAI,CAAC,EAAE;IAAE,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAA;CAAE,GAC1F,SAAS,CA0cX"}
package/dist/server.js ADDED
@@ -0,0 +1,483 @@
1
+ /**
2
+ * CELLO Adapter — server.ts (ADAPTER-002 / M1)
3
+ *
4
+ * createMcpServer(node, client, keyProvider): McpServer
5
+ * Registers the M1 tool set against a CelloClient.
6
+ * Transport-agnostic: identical tool names, schemas, and wiring under
7
+ * InMemoryTransport (tests) and stdio (production). AC-007.
8
+ *
9
+ * PSEUDOCODE (Phase P — ADAPTER-002):
10
+ *
11
+ * State held by the MCP server instance:
12
+ * sessionEventQueue: Array<InboundSessionEvent> FIFO; populated by onSessionAssignment handler
13
+ * sessionEventResolvers: Array<(event: InboundSessionEvent) => void> blocked cello_await_session waiters
14
+ * startedAt: number = Date.now()
15
+ *
16
+ * Session event enqueue (onSessionAssignment handler):
17
+ * Receives: SessionAssignmentEvent { sessionIdHex, counterpartyPubkeyHex, genesisPrevRootHex }
18
+ * (from CelloClient.onSessionAssignment per CELLO-MCP-002; fields are pre-encoded as hex)
19
+ * 1. Push cello_session_request notification via claude/channel (SI-001: only type, from, session_id)
20
+ * 2. If sessionEventResolvers.length > 0:
21
+ * - shift the first resolver and call it with the event (wake up blocked cello_await_session)
22
+ * 3. Else:
23
+ * - Push event to sessionEventQueue
24
+ *
25
+ * tool: cello_initiate_session({ target_pubkey: string })
26
+ * Delegates to CelloClient.initiateSession (added by MCP-002).
27
+ * Returns { ok: true, session_id: hex } or { ok: false, reason: string }.
28
+ * Stubbed if method not present on client.
29
+ *
30
+ * tool: cello_await_session({ timeout_ms: number })
31
+ * 1. If sessionEventQueue.length > 0:
32
+ * - shift first event
33
+ * - return { type: 'new_session', session_id, counterparty_pubkey, genesis_prev_root }
34
+ * 2. Else: block until event arrives or timeout expires:
35
+ * - Create a Promise that resolves when an event arrives or deadline fires
36
+ * - Push a resolver into sessionEventResolvers
37
+ * - Race: event arrival vs setTimeout(timeout_ms)
38
+ * - On arrival: return new_session
39
+ * - On timeout: remove resolver from array; return { type: 'timeout' }
40
+ *
41
+ * tool: cello_send({ session_id: string, content: string })
42
+ * 1. Guard: transport_not_started
43
+ * 2. UTF-8 encode content → contentBytes
44
+ * 3. client.sendMessage(session_id, contentBytes) → SendMessageResult
45
+ * 4. Map to MCP output:
46
+ * ok:true → { delivered: true }
47
+ * ok:false → { delivered: false, reason: result.reason }
48
+ *
49
+ * tool: cello_receive_session({ session_id: string, timeout_ms: number })
50
+ * 1. Guard: transport_not_started
51
+ * 2. deadline = Date.now() + timeout_ms
52
+ * 3. Poll every 20ms until deadline:
53
+ * a. msg = client.receiveMessage(session_id)
54
+ * b. if msg: return formatted message result
55
+ * c. await sleep(Math.min(20, remaining))
56
+ * 4. return { type: 'timeout' }
57
+ *
58
+ * tool: cello_close_session({ session_id: string })
59
+ * client.closeSession(session_id)
60
+ * return { closed: true }
61
+ *
62
+ * tool: cello_list_sessions()
63
+ * return client.listSessions() mapped to wire shape
64
+ *
65
+ * tool: cello_get_sealed_receipt({ session_id: string })
66
+ * Stubbed in M1: return { available: false, reason: 'not_yet_sealed' }
67
+ * (SESSION-003 implements real seals)
68
+ *
69
+ * tool: cello_get_inclusion_proof({ session_id: string, content_hash: string })
70
+ * Stubbed in M1: return { available: false, reason: 'not_yet_sealed' }
71
+ *
72
+ * tool: cello_status()
73
+ * 1. ownPubkey = Buffer.from(await keyProvider.getPublicKey()).toString('hex')
74
+ * 2. sessions = client.listSessions()
75
+ * 3. return {
76
+ * transport_started: transportStarted(),
77
+ * own_pubkey: ownPubkey,
78
+ * listen_addresses: node.listenAddresses(),
79
+ * connected_peer_count: node.getConnections().length,
80
+ * uptime_seconds: Math.floor((Date.now() - startedAt) / 1000),
81
+ * active_session_count: sessions.filter(s => s.status === 'active').length,
82
+ * directory_reachable: false // M1 stub — directory reachability check deferred
83
+ * }
84
+ */
85
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
86
+ import { z } from "zod";
87
+ import { pushSessionRequestNotification } from "./notifications.js";
88
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
89
+ function jsonText(value) {
90
+ return { content: [{ type: "text", text: JSON.stringify(value) }] };
91
+ }
92
+ const TRANSPORT_NOT_STARTED = jsonText({ error: { reason: "transport_not_started" } });
93
+ const CLIENT_NOT_INITIALIZED = jsonText({ error: { reason: "client_not_initialized" } });
94
+ // ─── createMcpServer ─────────────────────────────────────────────────────────
95
+ export function createMcpServer(node, client, keyProvider, opts) {
96
+ const checkpointStatusProvider = opts?.checkpointStatusProvider;
97
+ const clientBackup = opts?.clientBackup;
98
+ const startedAt = Date.now();
99
+ // ─── Session event queue ─────────────────────────────────────────────────
100
+ const sessionEventQueue = [];
101
+ const sessionEventResolvers = [];
102
+ function transportStarted() {
103
+ return node.listenAddresses().length > 0;
104
+ }
105
+ const server = new McpServer({ name: "cello", version: "0.1.0" }, { capabilities: { experimental: { "claude/channel": {} } } });
106
+ // ─── Register onSessionAssignment handler ───────────────────────────────
107
+ if (client != null && typeof client.onSessionAssignment === "function") {
108
+ client.onSessionAssignment((event) => {
109
+ void pushSessionRequestNotification(server, event.counterpartyPubkeyHex, event.sessionIdHex);
110
+ if (sessionEventResolvers.length > 0) {
111
+ const resolve = sessionEventResolvers.shift();
112
+ resolve(event);
113
+ }
114
+ else {
115
+ sessionEventQueue.push(event);
116
+ }
117
+ });
118
+ }
119
+ // ── cello_initiate_session ────────────────────────────────────────────────
120
+ server.registerTool("cello_initiate_session", {
121
+ description: "Initiate a CELLO session with a target agent identified by their public key.",
122
+ inputSchema: {
123
+ target_pubkey: z.string().describe("Target agent public key hex (K_local pubkey of the peer)"),
124
+ },
125
+ }, async ({ target_pubkey }) => {
126
+ if (!transportStarted())
127
+ return TRANSPORT_NOT_STARTED;
128
+ const result = await client.initiateSession(target_pubkey);
129
+ if (result.ok) {
130
+ return jsonText({
131
+ ok: true,
132
+ session_id: Buffer.from(result.sessionId).toString("hex"),
133
+ genesis_prev_root: Buffer.from(result.genesisPrevRoot).toString("hex"),
134
+ });
135
+ }
136
+ return jsonText({ ok: false, reason: result.reason });
137
+ });
138
+ // ── cello_await_session ───────────────────────────────────────────────────
139
+ server.registerTool("cello_await_session", {
140
+ description: "Wait for an inbound session request. Returns immediately if one is already queued, or blocks until one arrives or the timeout expires.",
141
+ inputSchema: {
142
+ timeout_ms: z.number().int().min(0).describe("Maximum wait time in milliseconds"),
143
+ },
144
+ }, async ({ timeout_ms }) => {
145
+ // If a queued event exists, return it immediately (FIFO)
146
+ if (sessionEventQueue.length > 0) {
147
+ const event = sessionEventQueue.shift();
148
+ return jsonText({
149
+ type: "new_session",
150
+ session_id: event.sessionIdHex,
151
+ counterparty_pubkey: event.counterpartyPubkeyHex,
152
+ genesis_prev_root: event.genesisPrevRootHex,
153
+ });
154
+ }
155
+ // Block until an event arrives or timeout fires
156
+ const result = await new Promise((resolve) => {
157
+ let timerId;
158
+ function resolveEvent(event) {
159
+ clearTimeout(timerId);
160
+ resolve(event);
161
+ }
162
+ sessionEventResolvers.push(resolveEvent);
163
+ timerId = setTimeout(() => {
164
+ const idx = sessionEventResolvers.indexOf(resolveEvent);
165
+ if (idx !== -1)
166
+ sessionEventResolvers.splice(idx, 1);
167
+ resolve(null);
168
+ }, timeout_ms);
169
+ });
170
+ if (result === null) {
171
+ return jsonText({ type: "timeout" });
172
+ }
173
+ return jsonText({
174
+ type: "new_session",
175
+ session_id: result.sessionIdHex,
176
+ counterparty_pubkey: result.counterpartyPubkeyHex,
177
+ genesis_prev_root: result.genesisPrevRootHex,
178
+ });
179
+ });
180
+ // ── cello_send (session-keyed, M1) ────────────────────────────────────────
181
+ server.registerTool("cello_send", {
182
+ description: "Send a UTF-8 message on an active CELLO session.",
183
+ inputSchema: {
184
+ session_id: z.string().describe("Session ID hex (from cello_initiate_session or cello_await_session)"),
185
+ content: z.string().describe("UTF-8 message content"),
186
+ },
187
+ }, async ({ session_id, content }) => {
188
+ if (client == null)
189
+ return CLIENT_NOT_INITIALIZED;
190
+ if (!transportStarted())
191
+ return TRANSPORT_NOT_STARTED;
192
+ const contentBytes = new TextEncoder().encode(content);
193
+ const result = await client.sendMessage(session_id, contentBytes);
194
+ if (result.ok) {
195
+ return jsonText({ delivered: true });
196
+ }
197
+ return jsonText({ delivered: false, reason: result.reason });
198
+ });
199
+ // ── cello_receive_session (session-keyed, M1) ────────────────────────────
200
+ server.registerTool("cello_receive_session", {
201
+ description: "Wait for a message on a specific CELLO session (session-locked). Blocks until a message arrives or the timeout expires.",
202
+ inputSchema: {
203
+ session_id: z
204
+ .string()
205
+ .describe("Session ID hex (from cello_initiate_session or cello_await_session)"),
206
+ timeout_ms: z.number().int().min(0).describe("Maximum wait time in milliseconds"),
207
+ },
208
+ }, async ({ session_id, timeout_ms }) => {
209
+ if (client == null)
210
+ return CLIENT_NOT_INITIALIZED;
211
+ if (!transportStarted())
212
+ return TRANSPORT_NOT_STARTED;
213
+ const deadline = Date.now() + timeout_ms;
214
+ while (Date.now() < deadline) {
215
+ const msg = client.receiveMessage(session_id);
216
+ if (msg) {
217
+ if (msg.type === "session_sealed") {
218
+ return jsonText({
219
+ type: "session_sealed",
220
+ session_id: msg.sessionIdHex,
221
+ sealed_root: Buffer.from(msg.sealedRoot).toString("hex"),
222
+ close_timestamp: msg.closeTimestamp,
223
+ checkpoint_status: msg.checkpointStatus,
224
+ });
225
+ }
226
+ return jsonText(formatSessionMessage(msg, session_id));
227
+ }
228
+ const remaining = deadline - Date.now();
229
+ if (remaining <= 0)
230
+ break;
231
+ await sleep(Math.min(20, remaining));
232
+ }
233
+ return jsonText({ type: "timeout" });
234
+ });
235
+ // ── cello_receive (any-session, default) ──────────────────────────────────
236
+ server.registerTool("cello_receive", {
237
+ description: "Wait for a message from any active CELLO session (default receive). Returns session_id so caller knows which session the message came from. Blocks until a message arrives or the timeout expires.",
238
+ inputSchema: {
239
+ timeout_ms: z.number().int().min(0).describe("Maximum wait time in milliseconds"),
240
+ },
241
+ }, async ({ timeout_ms }) => {
242
+ if (client == null)
243
+ return CLIENT_NOT_INITIALIZED;
244
+ if (!transportStarted())
245
+ return TRANSPORT_NOT_STARTED;
246
+ const result = await client.receiveMessageAsync(timeout_ms);
247
+ if (result.type === "timeout") {
248
+ return jsonText({ type: "timeout" });
249
+ }
250
+ if (result.type === "session_sealed") {
251
+ return jsonText({
252
+ type: "session_sealed",
253
+ session_id: result.sessionIdHex,
254
+ sealed_root: Buffer.from(result.sealedRoot).toString("hex"),
255
+ close_timestamp: result.closeTimestamp,
256
+ checkpoint_status: result.checkpointStatus,
257
+ ...(result.otherSessionsPending && result.otherSessionsPending.length > 0
258
+ ? { other_sessions_pending: result.otherSessionsPending }
259
+ : {}),
260
+ });
261
+ }
262
+ if (result.type === "message") {
263
+ let content;
264
+ try {
265
+ content = new TextDecoder("utf-8", { fatal: true }).decode(result.content);
266
+ }
267
+ catch {
268
+ content = Buffer.from(result.content).toString("hex");
269
+ }
270
+ return jsonText({
271
+ type: "message",
272
+ session_id: result.sessionIdHex,
273
+ content,
274
+ sender_pubkey: Buffer.from(result.senderPubkey).toString("hex"),
275
+ sequence_number: result.sequenceNumber,
276
+ leaf_hash: Buffer.from(result.leafHash).toString("hex"),
277
+ ...(result.otherSessionsPending && result.otherSessionsPending.length > 0
278
+ ? { other_sessions_pending: result.otherSessionsPending }
279
+ : {}),
280
+ });
281
+ }
282
+ return jsonText({ type: "unknown", raw: JSON.stringify(result) });
283
+ });
284
+ // ── cello_close_session ───────────────────────────────────────────────────
285
+ server.registerTool("cello_close_session", {
286
+ description: "Close and remove a CELLO session. Idempotent.",
287
+ inputSchema: {
288
+ session_id: z.string().describe("Session ID hex to close"),
289
+ },
290
+ }, async ({ session_id }) => {
291
+ if (client == null)
292
+ return CLIENT_NOT_INITIALIZED;
293
+ client.closeSession(session_id);
294
+ // PERSIST-017: include checkpoint_status if CheckpointStatusProvider is wired in.
295
+ // When not provided (M1 stubs, tests without DB), return closed: true only.
296
+ if (checkpointStatusProvider) {
297
+ const stagingStatus = await checkpointStatusProvider.getSealStagingStatus(session_id);
298
+ if (stagingStatus.status === "pending") {
299
+ return jsonText({ closed: true, checkpoint_status: "pending", staged_at: stagingStatus.staged_at });
300
+ }
301
+ if (stagingStatus.status === "confirmed") {
302
+ return jsonText({
303
+ closed: true,
304
+ checkpoint_status: "confirmed",
305
+ session_mmr_peak: stagingStatus.checkpoint_peak_hash,
306
+ leaf_index: stagingStatus.leaf_index,
307
+ });
308
+ }
309
+ }
310
+ return jsonText({ closed: true });
311
+ });
312
+ // ── cello_list_sessions ───────────────────────────────────────────────────
313
+ server.registerTool("cello_list_sessions", {
314
+ description: "List all current CELLO sessions and their status.",
315
+ inputSchema: {},
316
+ }, async () => {
317
+ if (client == null)
318
+ return CLIENT_NOT_INITIALIZED;
319
+ const sessions = client.listSessions().map((s) => ({
320
+ session_id: Buffer.from(s.session_id).toString("hex"),
321
+ counterparty_pubkey: Buffer.from(s.counterparty_pubkey).toString("hex"),
322
+ status: s.status,
323
+ }));
324
+ return jsonText(sessions);
325
+ });
326
+ // ── cello_get_sealed_receipt ──────────────────────────────────────────────
327
+ // PERSIST-017: returns checkpoint_status when CheckpointStatusProvider is wired.
328
+ // Falls back to the M1 stub response when no provider is configured.
329
+ server.registerTool("cello_get_sealed_receipt", {
330
+ description: "Retrieve the sealed receipt and MMR checkpoint status for a closed session.",
331
+ inputSchema: {
332
+ session_id: z.string().describe("Session ID hex"),
333
+ },
334
+ }, async ({ session_id }) => {
335
+ if (checkpointStatusProvider) {
336
+ const stagingStatus = await checkpointStatusProvider.getSealStagingStatus(session_id);
337
+ if (stagingStatus.status === "pending") {
338
+ return jsonText({
339
+ available: true,
340
+ checkpoint_status: "pending",
341
+ staged_at: stagingStatus.staged_at,
342
+ attestation_self: "PENDING",
343
+ attestation_self_reason: "MMR checkpoint not yet written",
344
+ });
345
+ }
346
+ if (stagingStatus.status === "confirmed") {
347
+ return jsonText({
348
+ available: true,
349
+ checkpoint_status: "confirmed",
350
+ session_mmr_peak: stagingStatus.checkpoint_peak_hash,
351
+ leaf_index: stagingStatus.leaf_index,
352
+ checkpoint_id: stagingStatus.checkpoint_id,
353
+ });
354
+ }
355
+ // not_staged: session was never sealed
356
+ return jsonText({ available: false, reason: "not_yet_sealed" });
357
+ }
358
+ return jsonText({ available: false, reason: "not_yet_sealed" });
359
+ });
360
+ // ── cello_get_inclusion_proof ─────────────────────────────────────────────
361
+ // PERSIST-017: returns pending/confirmed status when CheckpointStatusProvider is wired.
362
+ // Falls back to the M1 stub response when no provider is configured.
363
+ server.registerTool("cello_get_inclusion_proof", {
364
+ description: "Retrieve the MMR inclusion proof status for a sealed session.",
365
+ inputSchema: {
366
+ session_id: z.string().describe("Session ID hex"),
367
+ content_hash: z.string().describe("Content hash hex of the message"),
368
+ },
369
+ }, async ({ session_id }) => {
370
+ if (checkpointStatusProvider) {
371
+ const stagingStatus = await checkpointStatusProvider.getSealStagingStatus(session_id);
372
+ if (stagingStatus.status === "pending") {
373
+ return jsonText({
374
+ status: "pending",
375
+ staged_at: stagingStatus.staged_at,
376
+ message: "sealed_root staged; inclusion proof available after next MMR checkpoint",
377
+ });
378
+ }
379
+ if (stagingStatus.status === "confirmed") {
380
+ return jsonText({
381
+ status: "confirmed",
382
+ leaf_index: stagingStatus.leaf_index,
383
+ checkpoint_peak_hash: stagingStatus.checkpoint_peak_hash,
384
+ checkpoint_id: stagingStatus.checkpoint_id,
385
+ sibling_hashes: stagingStatus.sibling_hashes,
386
+ });
387
+ }
388
+ // not_staged: session was never sealed — error distinguishes from 'pending'
389
+ return jsonText({ status: "error", reason: "not_yet_sealed" });
390
+ }
391
+ return jsonText({ available: false, reason: "not_yet_sealed" });
392
+ });
393
+ // ── cello_status (extended with M1 fields) ────────────────────────────────
394
+ server.registerTool("cello_status", {
395
+ description: "Return transport status, own pubkey, connection info, and M1 session summary.",
396
+ inputSchema: {},
397
+ }, async () => {
398
+ const ownPubkey = Buffer.from(await keyProvider.getPublicKey()).toString("hex");
399
+ const sessions = client.listSessions();
400
+ const activeSessionCount = sessions.filter((s) => s.status === "active").length;
401
+ // directoryReachable check: any session with a directory_endpoint indicates reachability
402
+ const directoryReachable = sessions.some((s) => s.directory_endpoint && s.directory_endpoint.peer_id !== "");
403
+ return jsonText({
404
+ transport_started: transportStarted(),
405
+ own_pubkey: ownPubkey,
406
+ listen_addresses: node.listenAddresses(),
407
+ connected_peer_count: node.getConnections().length,
408
+ uptime_seconds: Math.floor((Date.now() - startedAt) / 1000),
409
+ active_session_count: activeSessionCount,
410
+ directory_reachable: directoryReachable,
411
+ });
412
+ });
413
+ // ── cello_backup ─────────────────────────────────────────────────────────────
414
+ // PERSIST-022: Trigger an immediate encrypted backup of the local database.
415
+ // If no backup is configured (cloudStorage=null), ClientBackup logs
416
+ // client.backup.not.configured at WARN and returns without error.
417
+ server.registerTool("cello_backup", {
418
+ description: "Trigger an immediate encrypted backup of the local CELLO database to cloud storage. " +
419
+ "Returns ok:true on success. Returns ok:false with reason if backup fails or is not configured.",
420
+ inputSchema: {},
421
+ }, async () => {
422
+ if (!clientBackup) {
423
+ return jsonText({ ok: false, reason: "not_configured" });
424
+ }
425
+ try {
426
+ const result = await clientBackup.backup();
427
+ return jsonText(result);
428
+ }
429
+ catch (err) {
430
+ const reason = err instanceof Error ? err.message : String(err);
431
+ return jsonText({ ok: false, reason });
432
+ }
433
+ });
434
+ // ── cello_restore ─────────────────────────────────────────────────────────────
435
+ // PERSIST-022: Download and decrypt the backup, replacing the local database file.
436
+ // On checksum mismatch or decrypt failure the local file is NOT overwritten and restore throws.
437
+ server.registerTool("cello_restore", {
438
+ description: "Restore the local CELLO database from the most recent cloud backup. " +
439
+ "Replaces the local database file only after checksum verification passes. " +
440
+ "Returns ok:true on success. If cloud storage is not configured, returns ok:false.",
441
+ inputSchema: {},
442
+ }, async () => {
443
+ if (!clientBackup) {
444
+ return jsonText({ ok: false, reason: "not_configured" });
445
+ }
446
+ try {
447
+ await clientBackup.restore();
448
+ return jsonText({ ok: true });
449
+ }
450
+ catch (err) {
451
+ const reason = err instanceof Error ? err.message : String(err);
452
+ return jsonText({ ok: false, reason });
453
+ }
454
+ });
455
+ return server;
456
+ }
457
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
458
+ function formatSessionMessage(msg, sessionIdHex) {
459
+ try {
460
+ const content = new TextDecoder("utf-8", { fatal: true }).decode(msg.content);
461
+ return {
462
+ type: "message",
463
+ content,
464
+ session_id: sessionIdHex,
465
+ sender_pubkey: Buffer.from(msg.senderPubkey).toString("hex"),
466
+ sequence_number: msg.sequenceNumber,
467
+ leaf_hash: Buffer.from(msg.leafHash).toString("hex"),
468
+ };
469
+ }
470
+ catch {
471
+ return {
472
+ type: "decode_error",
473
+ session_id: sessionIdHex,
474
+ sender_pubkey: Buffer.from(msg.senderPubkey).toString("hex"),
475
+ sequence_number: msg.sequenceNumber,
476
+ leaf_hash: Buffer.from(msg.leafHash).toString("hex"),
477
+ };
478
+ }
479
+ }
480
+ function sleep(ms) {
481
+ return new Promise((resolve) => setTimeout(resolve, ms));
482
+ }
483
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cello-protocol/connect",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -11,6 +11,9 @@
11
11
  },
12
12
  "main": "./dist/index.js",
13
13
  "types": "./dist/index.d.ts",
14
+ "bin": {
15
+ "cello-mcp": "./dist/bin/cello-mcp.js"
16
+ },
14
17
  "exports": {
15
18
  ".": {
16
19
  "import": "./dist/index.js",
@@ -23,12 +26,19 @@
23
26
  "SKILL.md"
24
27
  ],
25
28
  "dependencies": {
26
- "@cello-protocol/client": "0.0.1",
27
- "@cello-protocol/transport": "0.0.1",
28
- "@cello-protocol/crypto": "0.0.1"
29
+ "@cello-protocol/interfaces": "0.0.3",
30
+ "@libp2p/peer-id": "^6.0.8",
31
+ "@modelcontextprotocol/sdk": "^1.29.0",
32
+ "zod": "^4.4.2",
33
+ "@cello-protocol/client": "0.0.3",
34
+ "@cello-protocol/crypto": "0.0.3",
35
+ "@cello-protocol/transport": "0.0.3"
29
36
  },
30
37
  "devDependencies": {
31
- "@types/node": "^25.6.2"
38
+ "@claude-flow/testing": "3.0.0-alpha.6",
39
+ "@types/node": "^25.6.2",
40
+ "cbor-x": "^1.6.0",
41
+ "it-length-prefixed": "^10.0.1"
32
42
  },
33
43
  "scripts": {
34
44
  "typecheck": "tsc --build",