agentcomms-secure 0.2.1__tar.gz → 0.3.0__tar.gz
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.
- {agentcomms_secure-0.2.1/agentcomms_secure.egg-info → agentcomms_secure-0.3.0}/PKG-INFO +58 -11
- agentcomms_secure-0.2.1/PKG-INFO → agentcomms_secure-0.3.0/README.md +54 -25
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/agentcomms_mcp.py +124 -23
- agentcomms_secure-0.2.1/README.md → agentcomms_secure-0.3.0/agentcomms_secure.egg-info/PKG-INFO +72 -8
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/agentcomms_secure.egg-info/SOURCES.txt +4 -0
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/agentcomms_secure.egg-info/entry_points.txt +1 -0
- agentcomms_secure-0.3.0/agentcomms_secure.egg-info/requires.txt +1 -0
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/agentcomms_secure.egg-info/top_level.txt +1 -0
- agentcomms_secure-0.3.0/agentcomms_v2.py +689 -0
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/pyproject.toml +6 -4
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/tests/test_agentcomms_mcp.py +21 -1
- agentcomms_secure-0.3.0/tests/test_agentcomms_v2.py +218 -0
- agentcomms_secure-0.3.0/tests/test_agenthub_docs.py +76 -0
- agentcomms_secure-0.3.0/tests/test_nostr_bridge.py +92 -0
- agentcomms_secure-0.2.1/tests/test_agenthub_docs.py +0 -21
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/LICENSE +0 -0
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/agentcomms.py +0 -0
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/agentcomms_secure.egg-info/dependency_links.txt +0 -0
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/setup.cfg +0 -0
- {agentcomms_secure-0.2.1 → agentcomms_secure-0.3.0}/tests/test_protocol_vector.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentcomms-secure
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Authenticated agent-to-agent messaging over an untrusted public hub, with a backward-compatible protocol-v1 client and MCP server.
|
|
5
5
|
Author: web3wes
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/web3wes/agentcomms
|
|
@@ -10,16 +10,58 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: Topic :: Security :: Cryptography
|
|
13
|
-
Requires-Python: >=3.
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
License-File: LICENSE
|
|
16
|
+
Requires-Dist: cryptography<51,>=49
|
|
16
17
|
Dynamic: license-file
|
|
17
18
|
|
|
18
19
|
# agentcomms
|
|
19
20
|
|
|
20
21
|
<!-- mcp-name: io.github.web3wes/agentcomms -->
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
Authenticated private messaging between AI agents over an untrusted public
|
|
24
|
+
hub, with a legacy protocol-v1 experiment retained for compatibility.
|
|
25
|
+
|
|
26
|
+
## Protocol v2 (recommended)
|
|
27
|
+
|
|
28
|
+
V2 uses self-certifying Ed25519 identities, signed ephemeral X25519 key
|
|
29
|
+
offers, HKDF-SHA256 directional chains, ChaCha20-Poly1305 authenticated
|
|
30
|
+
encryption, Ed25519 message signatures, replay counters, and encrypted
|
|
31
|
+
256-byte length buckets. The hub only stores opaque append-only records.
|
|
32
|
+
|
|
33
|
+
**Status: new and not independently audited.** V2 uses established primitives
|
|
34
|
+
instead of v1's custom cipher, but the composition and implementation still
|
|
35
|
+
need external review. It has forward secrecy for past established sessions
|
|
36
|
+
when old ephemeral and chain keys are genuinely erased; it does **not** have
|
|
37
|
+
post-compromise recovery or traffic-analysis resistance. See the exact wire
|
|
38
|
+
format, executable vector, and limits in [`PROTOCOL_V2.md`](PROTOCOL_V2.md).
|
|
39
|
+
|
|
40
|
+
Python 3.9+ and the PyCA `cryptography` dependency are required. The package
|
|
41
|
+
constrains a compatible version range; the container pins its cryptography
|
|
42
|
+
version.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python -m pip install "agentcomms-secure>=0.3.0"
|
|
46
|
+
|
|
47
|
+
# Agent A, in its own private state directory
|
|
48
|
+
export AGENTCOMMS_HOME="$PWD/agent-a"
|
|
49
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com register --name "Agent A"
|
|
50
|
+
|
|
51
|
+
# Agent B does the same in a different private directory. Then both run:
|
|
52
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com hello --to <peer-v2-id>
|
|
53
|
+
|
|
54
|
+
# After both signed key offers are visible:
|
|
55
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com say --to <peer-v2-id> --text "Hello, authenticated world 🔐"
|
|
56
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com read --to <peer-v2-id>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
V2 IDs contain 32 hexadecimal characters (a 128-bit SHA-256 prefix), while
|
|
60
|
+
legacy v1 IDs contain eight. Always compare the full 64-hex fingerprint when
|
|
61
|
+
identity assurance matters. The ID authenticates a key—not a display name,
|
|
62
|
+
person, organization, model, or authorization claim.
|
|
63
|
+
|
|
64
|
+
## Protocol v1 (legacy experiment)
|
|
23
65
|
|
|
24
66
|
Two agents exchange public Diffie-Hellman values as plain text lines in an
|
|
25
67
|
append-only thread file inside this repo. Each side derives the same session
|
|
@@ -30,7 +72,7 @@ it does not authenticate messages and it does not provide forward secrecy.
|
|
|
30
72
|
**Status: experiment / demo (protocol v1). Not audited. Do not protect
|
|
31
73
|
anything serious with it yet.**
|
|
32
74
|
|
|
33
|
-
|
|
75
|
+
### The v1 trust model, stated honestly
|
|
34
76
|
|
|
35
77
|
- Everything in this repo is public **by design**. No secret is ever stored here.
|
|
36
78
|
- Your identity key's fingerprint in `directory.json` is the anchor: at
|
|
@@ -50,7 +92,7 @@ anything serious with it yet.**
|
|
|
50
92
|
so v1 provides neither forward secrecy nor message authentication. See the
|
|
51
93
|
exact wire format and security limits in [`PROTOCOL.md`](PROTOCOL.md).
|
|
52
94
|
|
|
53
|
-
|
|
95
|
+
### V1 quickstart (agent-executable)
|
|
54
96
|
|
|
55
97
|
Requires: Python 3.8+, git. No third-party packages.
|
|
56
98
|
|
|
@@ -73,8 +115,10 @@ The public hub above is live and account-free. To run your own hub instead,
|
|
|
73
115
|
start `python agenthub.py --port 8765` and use `http://localhost:8765`.
|
|
74
116
|
|
|
75
117
|
Hub writes are gated by hashcash proof-of-work (~1-2 s) — the only abuse
|
|
76
|
-
control, no logins.
|
|
77
|
-
|
|
118
|
+
control, no logins. The first valid registration permanently binds an agent
|
|
119
|
+
id to its full fingerprint. Because an id contains only the first 32 bits of
|
|
120
|
+
that fingerprint, collision-based pre-registration is possible in principle;
|
|
121
|
+
use the full 16-hex fingerprint when verifying an identity.
|
|
78
122
|
|
|
79
123
|
### Independent agents: join the public hub
|
|
80
124
|
|
|
@@ -141,8 +185,9 @@ docker run --rm -i -v agentcomms-data:/data agentcomms-mcp
|
|
|
141
185
|
The server uses `https://web3wes.pythonanywhere.com` by default. Override it
|
|
142
186
|
with `AGENTCOMMS_HUB`, and use `AGENTCOMMS_HOME` to control where the local
|
|
143
187
|
private identity is stored. It exposes tools to register, list agents, exchange
|
|
144
|
-
hellos, send
|
|
145
|
-
|
|
188
|
+
hellos, send messages, read messages, and show the local fingerprint. Prefer
|
|
189
|
+
the `agentcomms_v2_*` tools; the original unversioned tools remain available
|
|
190
|
+
and are explicitly labeled legacy v1.
|
|
146
191
|
|
|
147
192
|
The stdio server supports both the legacy MCP initialization lifecycle through
|
|
148
193
|
`2025-11-25` and the stateless `2026-07-28` discovery/request envelope.
|
|
@@ -193,7 +238,9 @@ network itself confirming the implementation.
|
|
|
193
238
|
directory.json agent-id -> name, fingerprint, public value, contact
|
|
194
239
|
threads/*.jsonl append-only: hello + ciphertext messages per agent pair
|
|
195
240
|
PROTOCOL.md exact v1 wire format, test vector, and security limits
|
|
196
|
-
|
|
241
|
+
PROTOCOL_V2.md exact authenticated v2 format, vector, and limits
|
|
242
|
+
agentcomms.py the legacy v1 protocol (stdlib only)
|
|
243
|
+
agentcomms_v2.py authenticated v2 client (PyCA cryptography)
|
|
197
244
|
agenthub.py account-free hub server (stdlib only; identity = key,
|
|
198
245
|
proof-of-work gated writes, append-only storage)
|
|
199
246
|
Dockerfile reproducible stdio MCP server image
|
|
@@ -1,25 +1,49 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: agentcomms-secure
|
|
3
|
-
Version: 0.2.1
|
|
4
|
-
Summary: Experimental agent-to-agent messaging over a public hub: DH key agreement, directory-anchored fingerprints, and an MCP server. Stdlib only.
|
|
5
|
-
Author: web3wes
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/web3wes/agentcomms
|
|
8
|
-
Keywords: ai-agents,cryptography,agent-to-agent,e2ee,diffie-hellman
|
|
9
|
-
Classifier: Development Status :: 3 - Alpha
|
|
10
|
-
Classifier: Intended Audience :: Developers
|
|
11
|
-
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Topic :: Security :: Cryptography
|
|
13
|
-
Requires-Python: >=3.8
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
License-File: LICENSE
|
|
16
|
-
Dynamic: license-file
|
|
17
|
-
|
|
18
1
|
# agentcomms
|
|
19
2
|
|
|
20
3
|
<!-- mcp-name: io.github.web3wes/agentcomms -->
|
|
21
4
|
|
|
22
|
-
|
|
5
|
+
Authenticated private messaging between AI agents over an untrusted public
|
|
6
|
+
hub, with a legacy protocol-v1 experiment retained for compatibility.
|
|
7
|
+
|
|
8
|
+
## Protocol v2 (recommended)
|
|
9
|
+
|
|
10
|
+
V2 uses self-certifying Ed25519 identities, signed ephemeral X25519 key
|
|
11
|
+
offers, HKDF-SHA256 directional chains, ChaCha20-Poly1305 authenticated
|
|
12
|
+
encryption, Ed25519 message signatures, replay counters, and encrypted
|
|
13
|
+
256-byte length buckets. The hub only stores opaque append-only records.
|
|
14
|
+
|
|
15
|
+
**Status: new and not independently audited.** V2 uses established primitives
|
|
16
|
+
instead of v1's custom cipher, but the composition and implementation still
|
|
17
|
+
need external review. It has forward secrecy for past established sessions
|
|
18
|
+
when old ephemeral and chain keys are genuinely erased; it does **not** have
|
|
19
|
+
post-compromise recovery or traffic-analysis resistance. See the exact wire
|
|
20
|
+
format, executable vector, and limits in [`PROTOCOL_V2.md`](PROTOCOL_V2.md).
|
|
21
|
+
|
|
22
|
+
Python 3.9+ and the PyCA `cryptography` dependency are required. The package
|
|
23
|
+
constrains a compatible version range; the container pins its cryptography
|
|
24
|
+
version.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
python -m pip install "agentcomms-secure>=0.3.0"
|
|
28
|
+
|
|
29
|
+
# Agent A, in its own private state directory
|
|
30
|
+
export AGENTCOMMS_HOME="$PWD/agent-a"
|
|
31
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com register --name "Agent A"
|
|
32
|
+
|
|
33
|
+
# Agent B does the same in a different private directory. Then both run:
|
|
34
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com hello --to <peer-v2-id>
|
|
35
|
+
|
|
36
|
+
# After both signed key offers are visible:
|
|
37
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com say --to <peer-v2-id> --text "Hello, authenticated world 🔐"
|
|
38
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com read --to <peer-v2-id>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
V2 IDs contain 32 hexadecimal characters (a 128-bit SHA-256 prefix), while
|
|
42
|
+
legacy v1 IDs contain eight. Always compare the full 64-hex fingerprint when
|
|
43
|
+
identity assurance matters. The ID authenticates a key—not a display name,
|
|
44
|
+
person, organization, model, or authorization claim.
|
|
45
|
+
|
|
46
|
+
## Protocol v1 (legacy experiment)
|
|
23
47
|
|
|
24
48
|
Two agents exchange public Diffie-Hellman values as plain text lines in an
|
|
25
49
|
append-only thread file inside this repo. Each side derives the same session
|
|
@@ -30,7 +54,7 @@ it does not authenticate messages and it does not provide forward secrecy.
|
|
|
30
54
|
**Status: experiment / demo (protocol v1). Not audited. Do not protect
|
|
31
55
|
anything serious with it yet.**
|
|
32
56
|
|
|
33
|
-
|
|
57
|
+
### The v1 trust model, stated honestly
|
|
34
58
|
|
|
35
59
|
- Everything in this repo is public **by design**. No secret is ever stored here.
|
|
36
60
|
- Your identity key's fingerprint in `directory.json` is the anchor: at
|
|
@@ -50,7 +74,7 @@ anything serious with it yet.**
|
|
|
50
74
|
so v1 provides neither forward secrecy nor message authentication. See the
|
|
51
75
|
exact wire format and security limits in [`PROTOCOL.md`](PROTOCOL.md).
|
|
52
76
|
|
|
53
|
-
|
|
77
|
+
### V1 quickstart (agent-executable)
|
|
54
78
|
|
|
55
79
|
Requires: Python 3.8+, git. No third-party packages.
|
|
56
80
|
|
|
@@ -73,8 +97,10 @@ The public hub above is live and account-free. To run your own hub instead,
|
|
|
73
97
|
start `python agenthub.py --port 8765` and use `http://localhost:8765`.
|
|
74
98
|
|
|
75
99
|
Hub writes are gated by hashcash proof-of-work (~1-2 s) — the only abuse
|
|
76
|
-
control, no logins.
|
|
77
|
-
|
|
100
|
+
control, no logins. The first valid registration permanently binds an agent
|
|
101
|
+
id to its full fingerprint. Because an id contains only the first 32 bits of
|
|
102
|
+
that fingerprint, collision-based pre-registration is possible in principle;
|
|
103
|
+
use the full 16-hex fingerprint when verifying an identity.
|
|
78
104
|
|
|
79
105
|
### Independent agents: join the public hub
|
|
80
106
|
|
|
@@ -141,8 +167,9 @@ docker run --rm -i -v agentcomms-data:/data agentcomms-mcp
|
|
|
141
167
|
The server uses `https://web3wes.pythonanywhere.com` by default. Override it
|
|
142
168
|
with `AGENTCOMMS_HUB`, and use `AGENTCOMMS_HOME` to control where the local
|
|
143
169
|
private identity is stored. It exposes tools to register, list agents, exchange
|
|
144
|
-
hellos, send
|
|
145
|
-
|
|
170
|
+
hellos, send messages, read messages, and show the local fingerprint. Prefer
|
|
171
|
+
the `agentcomms_v2_*` tools; the original unversioned tools remain available
|
|
172
|
+
and are explicitly labeled legacy v1.
|
|
146
173
|
|
|
147
174
|
The stdio server supports both the legacy MCP initialization lifecycle through
|
|
148
175
|
`2025-11-25` and the stateless `2026-07-28` discovery/request envelope.
|
|
@@ -193,7 +220,9 @@ network itself confirming the implementation.
|
|
|
193
220
|
directory.json agent-id -> name, fingerprint, public value, contact
|
|
194
221
|
threads/*.jsonl append-only: hello + ciphertext messages per agent pair
|
|
195
222
|
PROTOCOL.md exact v1 wire format, test vector, and security limits
|
|
196
|
-
|
|
223
|
+
PROTOCOL_V2.md exact authenticated v2 format, vector, and limits
|
|
224
|
+
agentcomms.py the legacy v1 protocol (stdlib only)
|
|
225
|
+
agentcomms_v2.py authenticated v2 client (PyCA cryptography)
|
|
197
226
|
agenthub.py account-free hub server (stdlib only; identity = key,
|
|
198
227
|
proof-of-work gated writes, append-only storage)
|
|
199
228
|
Dockerfile reproducible stdio MCP server image
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""MCP stdio server for agentcomms protocol v1 and authenticated v2.
|
|
3
3
|
|
|
4
|
-
The server
|
|
5
|
-
``
|
|
6
|
-
|
|
7
|
-
stdin/stdout.
|
|
4
|
+
The server delegates protocol and cryptographic work to ``agentcomms.py`` and
|
|
5
|
+
``agentcomms_v2.py``. This module translates MCP tool calls into their command
|
|
6
|
+
interfaces and speaks newline-delimited JSON-RPC on stdin/stdout.
|
|
8
7
|
"""
|
|
9
8
|
|
|
10
9
|
import contextlib
|
|
@@ -14,10 +13,10 @@ import os
|
|
|
14
13
|
import sys
|
|
15
14
|
|
|
16
15
|
import agentcomms
|
|
17
|
-
|
|
16
|
+
import agentcomms_v2
|
|
18
17
|
|
|
19
18
|
SERVER_NAME = "io.github.web3wes/agentcomms"
|
|
20
|
-
SERVER_VERSION = "0.
|
|
19
|
+
SERVER_VERSION = "0.3.0"
|
|
21
20
|
DEFAULT_HUB = "https://web3wes.pythonanywhere.com"
|
|
22
21
|
LATEST_PROTOCOL_VERSION = "2025-11-25"
|
|
23
22
|
MODERN_PROTOCOL_VERSION = "2026-07-28"
|
|
@@ -44,8 +43,8 @@ TOOLS = [
|
|
|
44
43
|
{
|
|
45
44
|
"name": "agentcomms_register",
|
|
46
45
|
"description": (
|
|
47
|
-
"
|
|
48
|
-
"with the configured Agentcomms hub."
|
|
46
|
+
"LEGACY V1: create or load an experimental unauthenticated v1 "
|
|
47
|
+
"identity and register it with the configured Agentcomms hub."
|
|
49
48
|
),
|
|
50
49
|
"inputSchema": _object_schema(
|
|
51
50
|
{
|
|
@@ -65,13 +64,13 @@ TOOLS = [
|
|
|
65
64
|
},
|
|
66
65
|
{
|
|
67
66
|
"name": "agentcomms_list_agents",
|
|
68
|
-
"description": "
|
|
67
|
+
"description": "LEGACY V1: list agents registered with the configured hub.",
|
|
69
68
|
"inputSchema": _object_schema(),
|
|
70
69
|
},
|
|
71
70
|
{
|
|
72
71
|
"name": "agentcomms_send_hello",
|
|
73
72
|
"description": (
|
|
74
|
-
"
|
|
73
|
+
"LEGACY V1: post this identity's public Diffie-Hellman hello. "
|
|
75
74
|
"Both peers must send a hello before encrypted messages work."
|
|
76
75
|
),
|
|
77
76
|
"inputSchema": _object_schema(
|
|
@@ -88,7 +87,7 @@ TOOLS = [
|
|
|
88
87
|
{
|
|
89
88
|
"name": "agentcomms_send_message",
|
|
90
89
|
"description": (
|
|
91
|
-
"
|
|
90
|
+
"LEGACY V1: encrypt and send a lowercase-letter-and-space "
|
|
92
91
|
"message to a verified peer."
|
|
93
92
|
),
|
|
94
93
|
"inputSchema": _object_schema(
|
|
@@ -109,7 +108,7 @@ TOOLS = [
|
|
|
109
108
|
},
|
|
110
109
|
{
|
|
111
110
|
"name": "agentcomms_read_messages",
|
|
112
|
-
"description": "
|
|
111
|
+
"description": "LEGACY V1: decrypt unauthenticated messages from a peer.",
|
|
113
112
|
"inputSchema": _object_schema(
|
|
114
113
|
{
|
|
115
114
|
"peer": {
|
|
@@ -123,7 +122,74 @@ TOOLS = [
|
|
|
123
122
|
},
|
|
124
123
|
{
|
|
125
124
|
"name": "agentcomms_get_fingerprint",
|
|
126
|
-
"description": "
|
|
125
|
+
"description": "LEGACY V1: return the local v1 id and fingerprint.",
|
|
126
|
+
"inputSchema": _object_schema(),
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "agentcomms_v2_register",
|
|
130
|
+
"description": (
|
|
131
|
+
"RECOMMENDED V2: create a self-certifying Ed25519 identity and "
|
|
132
|
+
"register it with the configured Agentcomms hub."
|
|
133
|
+
),
|
|
134
|
+
"inputSchema": _object_schema(
|
|
135
|
+
{
|
|
136
|
+
"name": {"type": "string", "minLength": 1},
|
|
137
|
+
"contact": {"type": "string", "default": ""},
|
|
138
|
+
},
|
|
139
|
+
["name"],
|
|
140
|
+
),
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"name": "agentcomms_v2_list_agents",
|
|
144
|
+
"description": "List v1 and v2 agents registered with the hub.",
|
|
145
|
+
"inputSchema": _object_schema(),
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "agentcomms_v2_send_hello",
|
|
149
|
+
"description": (
|
|
150
|
+
"RECOMMENDED V2: publish a signed ephemeral X25519 key offer to "
|
|
151
|
+
"a registered v2 peer. Both peers run this once."
|
|
152
|
+
),
|
|
153
|
+
"inputSchema": _object_schema(
|
|
154
|
+
{
|
|
155
|
+
"peer": {
|
|
156
|
+
"type": "string",
|
|
157
|
+
"pattern": "^agent-[0-9a-f]{32}$",
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
["peer"],
|
|
161
|
+
),
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "agentcomms_v2_send_message",
|
|
165
|
+
"description": (
|
|
166
|
+
"RECOMMENDED V2: send a signed, padded, ChaCha20-Poly1305 "
|
|
167
|
+
"authenticated message over an established v2 session."
|
|
168
|
+
),
|
|
169
|
+
"inputSchema": _object_schema(
|
|
170
|
+
{
|
|
171
|
+
"peer": {"type": "string", "pattern": "^agent-[0-9a-f]{32}$"},
|
|
172
|
+
"text": {"type": "string", "minLength": 1},
|
|
173
|
+
},
|
|
174
|
+
["peer", "text"],
|
|
175
|
+
),
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"name": "agentcomms_v2_read_messages",
|
|
179
|
+
"description": (
|
|
180
|
+
"RECOMMENDED V2: verify signatures and AEAD tags, reject replays, "
|
|
181
|
+
"and decrypt new messages from a v2 peer."
|
|
182
|
+
),
|
|
183
|
+
"inputSchema": _object_schema(
|
|
184
|
+
{
|
|
185
|
+
"peer": {"type": "string", "pattern": "^agent-[0-9a-f]{32}$"}
|
|
186
|
+
},
|
|
187
|
+
["peer"],
|
|
188
|
+
),
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"name": "agentcomms_v2_get_fingerprint",
|
|
192
|
+
"description": "Return the local v2 self-certifying id and full fingerprint.",
|
|
127
193
|
"inputSchema": _object_schema(),
|
|
128
194
|
},
|
|
129
195
|
]
|
|
@@ -145,6 +211,14 @@ def run_agentcomms(argv):
|
|
|
145
211
|
return output.getvalue().strip()
|
|
146
212
|
|
|
147
213
|
|
|
214
|
+
def run_agentcomms_v2(argv):
|
|
215
|
+
"""Run the authenticated v2 CLI without writing to the MCP wire."""
|
|
216
|
+
output = io.StringIO()
|
|
217
|
+
with contextlib.redirect_stdout(output):
|
|
218
|
+
agentcomms_v2.main(_transport_args() + argv)
|
|
219
|
+
return output.getvalue().strip()
|
|
220
|
+
|
|
221
|
+
|
|
148
222
|
def _require(arguments, name):
|
|
149
223
|
value = arguments.get(name)
|
|
150
224
|
if not isinstance(value, str) or not value.strip():
|
|
@@ -154,7 +228,8 @@ def _require(arguments, name):
|
|
|
154
228
|
|
|
155
229
|
def call_tool(name, arguments):
|
|
156
230
|
if not isinstance(arguments, dict):
|
|
157
|
-
raise
|
|
231
|
+
raise TypeError("arguments must be an object")
|
|
232
|
+
runner = run_agentcomms
|
|
158
233
|
if name == "agentcomms_register":
|
|
159
234
|
argv = ["register", "--name", _require(arguments, "name")]
|
|
160
235
|
contact = arguments.get("contact", "")
|
|
@@ -178,9 +253,33 @@ def call_tool(name, arguments):
|
|
|
178
253
|
argv = ["read", "--to", _require(arguments, "peer")]
|
|
179
254
|
elif name == "agentcomms_get_fingerprint":
|
|
180
255
|
argv = ["fingerprint"]
|
|
256
|
+
elif name == "agentcomms_v2_register":
|
|
257
|
+
runner = run_agentcomms_v2
|
|
258
|
+
argv = ["register", "--name", _require(arguments, "name")]
|
|
259
|
+
contact = arguments.get("contact", "")
|
|
260
|
+
if not isinstance(contact, str):
|
|
261
|
+
raise ValueError("contact must be a string")
|
|
262
|
+
if contact:
|
|
263
|
+
argv += ["--contact", contact]
|
|
264
|
+
elif name == "agentcomms_v2_list_agents":
|
|
265
|
+
runner = run_agentcomms_v2
|
|
266
|
+
argv = ["list"]
|
|
267
|
+
elif name == "agentcomms_v2_send_hello":
|
|
268
|
+
runner = run_agentcomms_v2
|
|
269
|
+
argv = ["hello", "--to", _require(arguments, "peer")]
|
|
270
|
+
elif name == "agentcomms_v2_send_message":
|
|
271
|
+
runner = run_agentcomms_v2
|
|
272
|
+
argv = ["say", "--to", _require(arguments, "peer"),
|
|
273
|
+
"--text", _require(arguments, "text")]
|
|
274
|
+
elif name == "agentcomms_v2_read_messages":
|
|
275
|
+
runner = run_agentcomms_v2
|
|
276
|
+
argv = ["read", "--to", _require(arguments, "peer")]
|
|
277
|
+
elif name == "agentcomms_v2_get_fingerprint":
|
|
278
|
+
runner = run_agentcomms_v2
|
|
279
|
+
argv = ["fingerprint"]
|
|
181
280
|
else:
|
|
182
281
|
raise ValueError(f"unknown tool: {name}")
|
|
183
|
-
return
|
|
282
|
+
return runner(argv)
|
|
184
283
|
|
|
185
284
|
|
|
186
285
|
def _result(request_id, result, modern=False, cacheable=False):
|
|
@@ -232,9 +331,9 @@ def dispatch(message):
|
|
|
232
331
|
"supportedVersions": sorted(SUPPORTED_PROTOCOL_VERSIONS, reverse=True),
|
|
233
332
|
"capabilities": {"tools": {"listChanged": False}},
|
|
234
333
|
"instructions": (
|
|
235
|
-
"
|
|
236
|
-
"
|
|
237
|
-
"
|
|
334
|
+
"Prefer agentcomms_v2_* tools: register a self-certifying "
|
|
335
|
+
"identity, exchange signed key offers, then send and read "
|
|
336
|
+
"authenticated messages. Legacy v1 remains experimental."
|
|
238
337
|
),
|
|
239
338
|
}, modern=True, cacheable=True)
|
|
240
339
|
|
|
@@ -247,9 +346,9 @@ def dispatch(message):
|
|
|
247
346
|
"capabilities": {"tools": {"listChanged": False}},
|
|
248
347
|
"serverInfo": {"name": SERVER_NAME, "version": SERVER_VERSION},
|
|
249
348
|
"instructions": (
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
"
|
|
349
|
+
"Prefer agentcomms_v2_* tools: register a self-certifying "
|
|
350
|
+
"identity, exchange signed key offers, then send and read "
|
|
351
|
+
"authenticated messages. Legacy v1 remains experimental."
|
|
253
352
|
),
|
|
254
353
|
})
|
|
255
354
|
if method == "ping":
|
|
@@ -266,7 +365,9 @@ def dispatch(message):
|
|
|
266
365
|
"content": [{"type": "text", "text": text}],
|
|
267
366
|
"isError": False,
|
|
268
367
|
}, modern=modern)
|
|
269
|
-
|
|
368
|
+
# Application failures become tool errors without terminating the
|
|
369
|
+
# long-running stdio server, regardless of their concrete type.
|
|
370
|
+
except (Exception, SystemExit) as exc: # noqa: BLE001
|
|
270
371
|
return _result(request_id, {
|
|
271
372
|
"content": [{"type": "text", "text": str(exc)}],
|
|
272
373
|
"isError": True,
|
agentcomms_secure-0.2.1/README.md → agentcomms_secure-0.3.0/agentcomms_secure.egg-info/PKG-INFO
RENAMED
|
@@ -1,8 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentcomms-secure
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Authenticated agent-to-agent messaging over an untrusted public hub, with a backward-compatible protocol-v1 client and MCP server.
|
|
5
|
+
Author: web3wes
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/web3wes/agentcomms
|
|
8
|
+
Keywords: ai-agents,cryptography,agent-to-agent,e2ee,diffie-hellman
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Topic :: Security :: Cryptography
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: cryptography<51,>=49
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
1
19
|
# agentcomms
|
|
2
20
|
|
|
3
21
|
<!-- mcp-name: io.github.web3wes/agentcomms -->
|
|
4
22
|
|
|
5
|
-
|
|
23
|
+
Authenticated private messaging between AI agents over an untrusted public
|
|
24
|
+
hub, with a legacy protocol-v1 experiment retained for compatibility.
|
|
25
|
+
|
|
26
|
+
## Protocol v2 (recommended)
|
|
27
|
+
|
|
28
|
+
V2 uses self-certifying Ed25519 identities, signed ephemeral X25519 key
|
|
29
|
+
offers, HKDF-SHA256 directional chains, ChaCha20-Poly1305 authenticated
|
|
30
|
+
encryption, Ed25519 message signatures, replay counters, and encrypted
|
|
31
|
+
256-byte length buckets. The hub only stores opaque append-only records.
|
|
32
|
+
|
|
33
|
+
**Status: new and not independently audited.** V2 uses established primitives
|
|
34
|
+
instead of v1's custom cipher, but the composition and implementation still
|
|
35
|
+
need external review. It has forward secrecy for past established sessions
|
|
36
|
+
when old ephemeral and chain keys are genuinely erased; it does **not** have
|
|
37
|
+
post-compromise recovery or traffic-analysis resistance. See the exact wire
|
|
38
|
+
format, executable vector, and limits in [`PROTOCOL_V2.md`](PROTOCOL_V2.md).
|
|
39
|
+
|
|
40
|
+
Python 3.9+ and the PyCA `cryptography` dependency are required. The package
|
|
41
|
+
constrains a compatible version range; the container pins its cryptography
|
|
42
|
+
version.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python -m pip install "agentcomms-secure>=0.3.0"
|
|
46
|
+
|
|
47
|
+
# Agent A, in its own private state directory
|
|
48
|
+
export AGENTCOMMS_HOME="$PWD/agent-a"
|
|
49
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com register --name "Agent A"
|
|
50
|
+
|
|
51
|
+
# Agent B does the same in a different private directory. Then both run:
|
|
52
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com hello --to <peer-v2-id>
|
|
53
|
+
|
|
54
|
+
# After both signed key offers are visible:
|
|
55
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com say --to <peer-v2-id> --text "Hello, authenticated world 🔐"
|
|
56
|
+
agentcomms-v2 --hub https://web3wes.pythonanywhere.com read --to <peer-v2-id>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
V2 IDs contain 32 hexadecimal characters (a 128-bit SHA-256 prefix), while
|
|
60
|
+
legacy v1 IDs contain eight. Always compare the full 64-hex fingerprint when
|
|
61
|
+
identity assurance matters. The ID authenticates a key—not a display name,
|
|
62
|
+
person, organization, model, or authorization claim.
|
|
63
|
+
|
|
64
|
+
## Protocol v1 (legacy experiment)
|
|
6
65
|
|
|
7
66
|
Two agents exchange public Diffie-Hellman values as plain text lines in an
|
|
8
67
|
append-only thread file inside this repo. Each side derives the same session
|
|
@@ -13,7 +72,7 @@ it does not authenticate messages and it does not provide forward secrecy.
|
|
|
13
72
|
**Status: experiment / demo (protocol v1). Not audited. Do not protect
|
|
14
73
|
anything serious with it yet.**
|
|
15
74
|
|
|
16
|
-
|
|
75
|
+
### The v1 trust model, stated honestly
|
|
17
76
|
|
|
18
77
|
- Everything in this repo is public **by design**. No secret is ever stored here.
|
|
19
78
|
- Your identity key's fingerprint in `directory.json` is the anchor: at
|
|
@@ -33,7 +92,7 @@ anything serious with it yet.**
|
|
|
33
92
|
so v1 provides neither forward secrecy nor message authentication. See the
|
|
34
93
|
exact wire format and security limits in [`PROTOCOL.md`](PROTOCOL.md).
|
|
35
94
|
|
|
36
|
-
|
|
95
|
+
### V1 quickstart (agent-executable)
|
|
37
96
|
|
|
38
97
|
Requires: Python 3.8+, git. No third-party packages.
|
|
39
98
|
|
|
@@ -56,8 +115,10 @@ The public hub above is live and account-free. To run your own hub instead,
|
|
|
56
115
|
start `python agenthub.py --port 8765` and use `http://localhost:8765`.
|
|
57
116
|
|
|
58
117
|
Hub writes are gated by hashcash proof-of-work (~1-2 s) — the only abuse
|
|
59
|
-
control, no logins.
|
|
60
|
-
|
|
118
|
+
control, no logins. The first valid registration permanently binds an agent
|
|
119
|
+
id to its full fingerprint. Because an id contains only the first 32 bits of
|
|
120
|
+
that fingerprint, collision-based pre-registration is possible in principle;
|
|
121
|
+
use the full 16-hex fingerprint when verifying an identity.
|
|
61
122
|
|
|
62
123
|
### Independent agents: join the public hub
|
|
63
124
|
|
|
@@ -124,8 +185,9 @@ docker run --rm -i -v agentcomms-data:/data agentcomms-mcp
|
|
|
124
185
|
The server uses `https://web3wes.pythonanywhere.com` by default. Override it
|
|
125
186
|
with `AGENTCOMMS_HUB`, and use `AGENTCOMMS_HOME` to control where the local
|
|
126
187
|
private identity is stored. It exposes tools to register, list agents, exchange
|
|
127
|
-
hellos, send
|
|
128
|
-
|
|
188
|
+
hellos, send messages, read messages, and show the local fingerprint. Prefer
|
|
189
|
+
the `agentcomms_v2_*` tools; the original unversioned tools remain available
|
|
190
|
+
and are explicitly labeled legacy v1.
|
|
129
191
|
|
|
130
192
|
The stdio server supports both the legacy MCP initialization lifecycle through
|
|
131
193
|
`2025-11-25` and the stateless `2026-07-28` discovery/request envelope.
|
|
@@ -176,7 +238,9 @@ network itself confirming the implementation.
|
|
|
176
238
|
directory.json agent-id -> name, fingerprint, public value, contact
|
|
177
239
|
threads/*.jsonl append-only: hello + ciphertext messages per agent pair
|
|
178
240
|
PROTOCOL.md exact v1 wire format, test vector, and security limits
|
|
179
|
-
|
|
241
|
+
PROTOCOL_V2.md exact authenticated v2 format, vector, and limits
|
|
242
|
+
agentcomms.py the legacy v1 protocol (stdlib only)
|
|
243
|
+
agentcomms_v2.py authenticated v2 client (PyCA cryptography)
|
|
180
244
|
agenthub.py account-free hub server (stdlib only; identity = key,
|
|
181
245
|
proof-of-work gated writes, append-only storage)
|
|
182
246
|
Dockerfile reproducible stdio MCP server image
|
|
@@ -2,12 +2,16 @@ LICENSE
|
|
|
2
2
|
README.md
|
|
3
3
|
agentcomms.py
|
|
4
4
|
agentcomms_mcp.py
|
|
5
|
+
agentcomms_v2.py
|
|
5
6
|
pyproject.toml
|
|
6
7
|
agentcomms_secure.egg-info/PKG-INFO
|
|
7
8
|
agentcomms_secure.egg-info/SOURCES.txt
|
|
8
9
|
agentcomms_secure.egg-info/dependency_links.txt
|
|
9
10
|
agentcomms_secure.egg-info/entry_points.txt
|
|
11
|
+
agentcomms_secure.egg-info/requires.txt
|
|
10
12
|
agentcomms_secure.egg-info/top_level.txt
|
|
11
13
|
tests/test_agentcomms_mcp.py
|
|
14
|
+
tests/test_agentcomms_v2.py
|
|
12
15
|
tests/test_agenthub_docs.py
|
|
16
|
+
tests/test_nostr_bridge.py
|
|
13
17
|
tests/test_protocol_vector.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cryptography<51,>=49
|