dokimo-mcp 0.1.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.
- dokimo_mcp-0.1.0/LICENSE +21 -0
- dokimo_mcp-0.1.0/PKG-INFO +133 -0
- dokimo_mcp-0.1.0/README.md +113 -0
- dokimo_mcp-0.1.0/dokimo_mcp.egg-info/PKG-INFO +133 -0
- dokimo_mcp-0.1.0/dokimo_mcp.egg-info/SOURCES.txt +10 -0
- dokimo_mcp-0.1.0/dokimo_mcp.egg-info/dependency_links.txt +1 -0
- dokimo_mcp-0.1.0/dokimo_mcp.egg-info/entry_points.txt +2 -0
- dokimo_mcp-0.1.0/dokimo_mcp.egg-info/requires.txt +2 -0
- dokimo_mcp-0.1.0/dokimo_mcp.egg-info/top_level.txt +1 -0
- dokimo_mcp-0.1.0/dokimo_mcp.py +198 -0
- dokimo_mcp-0.1.0/pyproject.toml +37 -0
- dokimo_mcp-0.1.0/setup.cfg +4 -0
dokimo_mcp-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Augaster Technologies
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dokimo-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server to verify AI-agent revenue claims: recompute a Merkle proof and check it against an on-chain anchor.
|
|
5
|
+
Author: Augaster Technologies
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://dokimo.augaster.com
|
|
8
|
+
Project-URL: Demo, https://dokimo.augaster.com/agent-audits-agents.html
|
|
9
|
+
Project-URL: Repository, https://github.com/ypratap11/dokimo-mcp
|
|
10
|
+
Project-URL: Issues, https://github.com/ypratap11/dokimo-mcp/issues
|
|
11
|
+
Keywords: mcp,model-context-protocol,x402,agentic-payments,merkle,verification,agents
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Security
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: mcp<2,>=1.2
|
|
18
|
+
Requires-Dist: uvicorn>=0.30
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
# dokimo-mcp
|
|
22
|
+
|
|
23
|
+
<!-- mcp-name: io.github.ypratap11/dokimo-mcp -->
|
|
24
|
+
|
|
25
|
+
**Give an AI agent the ability to verify another agent's revenue claims.**
|
|
26
|
+
|
|
27
|
+
An [MCP](https://modelcontextprotocol.io) server exposing [Dokimo's](https://dokimo.augaster.com)
|
|
28
|
+
trustless evidence verification as tools any MCP client (Claude Desktop, IDE
|
|
29
|
+
agents, custom agents) can call. It's the "agent that audits agents" — as tools.
|
|
30
|
+
|
|
31
|
+
Live, clickable version of what these tools do:
|
|
32
|
+
**https://dokimo.augaster.com/agent-audits-agents.html**
|
|
33
|
+
|
|
34
|
+
> This is a thin, self-contained **client**: it calls Dokimo's public endpoints and
|
|
35
|
+
> implements the public `dokimo-merkle-v1` hashing scheme. It contains no proprietary
|
|
36
|
+
> code. MIT-licensed.
|
|
37
|
+
|
|
38
|
+
## Tools
|
|
39
|
+
|
|
40
|
+
| Tool | What it does | Network? |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `recompute_merkle_root(leaf, proof_path)` | **Trustless local recompute** — hash a leaf under `dokimo-merkle-v1` and replay the proof path to a root, with **no network and no trust in anyone**. Compare it to a package's claimed `root` yourself. | none |
|
|
43
|
+
| `verify_evidence_package(package)` | **Full verification** via Dokimo's public A2A endpoint: recompute **and** check the compound commitment (root + rule version) against the **on-chain anchor on Base**. Returns `verified: true` only if both hold. | Dokimo A2A |
|
|
44
|
+
| `dokimo_agent_card()` | Fetch Dokimo's public A2A agent card — what it can verify. | Dokimo |
|
|
45
|
+
|
|
46
|
+
**Verification model:** there is no path to `verified: true` without (1) the
|
|
47
|
+
caller's `(leaf, proof_path)` recomputing to the claimed `root`, **and** (2) the
|
|
48
|
+
compound commitment of `(root, rule_version_commitment)` being anchored on-chain.
|
|
49
|
+
Tamper one byte → recompute fails. Swap the rule version → the commitment changes
|
|
50
|
+
→ not anchored.
|
|
51
|
+
|
|
52
|
+
**Honest scope:** attests that a *reported* figure is reproducible and
|
|
53
|
+
tamper-evident against an on-chain anchor — not that any underlying business
|
|
54
|
+
number is "good." Non-custodial; reads public on-chain state only.
|
|
55
|
+
|
|
56
|
+
## Install & run
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install dokimo-mcp
|
|
60
|
+
dokimo-mcp # runs over stdio
|
|
61
|
+
# or, from a clone:
|
|
62
|
+
pip install .
|
|
63
|
+
python -m dokimo_mcp
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Add to an MCP client
|
|
67
|
+
|
|
68
|
+
**Claude Desktop** — add to `claude_desktop_config.json`:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"dokimo": {
|
|
74
|
+
"command": "dokimo-mcp"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If `dokimo-mcp` isn't on `PATH`, use the module form:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"mcpServers": {
|
|
85
|
+
"dokimo": {
|
|
86
|
+
"command": "python",
|
|
87
|
+
"args": ["-m", "dokimo_mcp"]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Then ask the agent: *"Use Dokimo to verify this evidence package"* (paste one), or
|
|
94
|
+
*"recompute this Merkle root and tell me if it matches."*
|
|
95
|
+
|
|
96
|
+
## Try it
|
|
97
|
+
|
|
98
|
+
The live demo page embeds a real, anchored evidence package. Fetch it and verify:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
import re, json, urllib.request
|
|
102
|
+
import dokimo_mcp as d
|
|
103
|
+
html = urllib.request.urlopen(urllib.request.Request(
|
|
104
|
+
"https://dokimo.augaster.com/agent-audits-agents.html",
|
|
105
|
+
headers={"User-Agent": d._UA})).read().decode()
|
|
106
|
+
pkg = json.loads(re.search(r"const PKG\s*=\s*(\{.*?\})\s*;", html, re.S).group(1))
|
|
107
|
+
print(d.verify_evidence_package(pkg)["verified"]) # True
|
|
108
|
+
# tamper one unit -> False
|
|
109
|
+
pkg["leaf"] = pkg["leaf"].replace("1001190933933115", "1001190933933116")
|
|
110
|
+
print(d.verify_evidence_package(pkg)["verified"]) # False
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Hosted / HTTP mode
|
|
114
|
+
|
|
115
|
+
The default transport is **stdio** (local use). Set `MCP_TRANSPORT=http` to serve
|
|
116
|
+
**MCP Streamable HTTP at `/mcp`** on `$PORT` (default 8081) with CORS — the shape
|
|
117
|
+
hosted platforms like [Smithery](https://smithery.ai) require. The included
|
|
118
|
+
`Dockerfile` + `smithery.yaml` (`runtime: container`) are set up for exactly this,
|
|
119
|
+
so Smithery can build and host it from this repo.
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
MCP_TRANSPORT=http PORT=8081 dokimo-mcp # or: docker run -p 8081:8081 <image>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## What is Dokimo?
|
|
126
|
+
|
|
127
|
+
Verifiable revenue infrastructure for autonomous commerce — audit-ready, independently
|
|
128
|
+
reproducible books for AI-agent machine payments (x402 / AP2 / Stripe), with each figure
|
|
129
|
+
tamper-evidently committed and anchored on-chain. https://dokimo.augaster.com
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# dokimo-mcp
|
|
2
|
+
|
|
3
|
+
<!-- mcp-name: io.github.ypratap11/dokimo-mcp -->
|
|
4
|
+
|
|
5
|
+
**Give an AI agent the ability to verify another agent's revenue claims.**
|
|
6
|
+
|
|
7
|
+
An [MCP](https://modelcontextprotocol.io) server exposing [Dokimo's](https://dokimo.augaster.com)
|
|
8
|
+
trustless evidence verification as tools any MCP client (Claude Desktop, IDE
|
|
9
|
+
agents, custom agents) can call. It's the "agent that audits agents" — as tools.
|
|
10
|
+
|
|
11
|
+
Live, clickable version of what these tools do:
|
|
12
|
+
**https://dokimo.augaster.com/agent-audits-agents.html**
|
|
13
|
+
|
|
14
|
+
> This is a thin, self-contained **client**: it calls Dokimo's public endpoints and
|
|
15
|
+
> implements the public `dokimo-merkle-v1` hashing scheme. It contains no proprietary
|
|
16
|
+
> code. MIT-licensed.
|
|
17
|
+
|
|
18
|
+
## Tools
|
|
19
|
+
|
|
20
|
+
| Tool | What it does | Network? |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `recompute_merkle_root(leaf, proof_path)` | **Trustless local recompute** — hash a leaf under `dokimo-merkle-v1` and replay the proof path to a root, with **no network and no trust in anyone**. Compare it to a package's claimed `root` yourself. | none |
|
|
23
|
+
| `verify_evidence_package(package)` | **Full verification** via Dokimo's public A2A endpoint: recompute **and** check the compound commitment (root + rule version) against the **on-chain anchor on Base**. Returns `verified: true` only if both hold. | Dokimo A2A |
|
|
24
|
+
| `dokimo_agent_card()` | Fetch Dokimo's public A2A agent card — what it can verify. | Dokimo |
|
|
25
|
+
|
|
26
|
+
**Verification model:** there is no path to `verified: true` without (1) the
|
|
27
|
+
caller's `(leaf, proof_path)` recomputing to the claimed `root`, **and** (2) the
|
|
28
|
+
compound commitment of `(root, rule_version_commitment)` being anchored on-chain.
|
|
29
|
+
Tamper one byte → recompute fails. Swap the rule version → the commitment changes
|
|
30
|
+
→ not anchored.
|
|
31
|
+
|
|
32
|
+
**Honest scope:** attests that a *reported* figure is reproducible and
|
|
33
|
+
tamper-evident against an on-chain anchor — not that any underlying business
|
|
34
|
+
number is "good." Non-custodial; reads public on-chain state only.
|
|
35
|
+
|
|
36
|
+
## Install & run
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install dokimo-mcp
|
|
40
|
+
dokimo-mcp # runs over stdio
|
|
41
|
+
# or, from a clone:
|
|
42
|
+
pip install .
|
|
43
|
+
python -m dokimo_mcp
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Add to an MCP client
|
|
47
|
+
|
|
48
|
+
**Claude Desktop** — add to `claude_desktop_config.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"dokimo": {
|
|
54
|
+
"command": "dokimo-mcp"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
If `dokimo-mcp` isn't on `PATH`, use the module form:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mcpServers": {
|
|
65
|
+
"dokimo": {
|
|
66
|
+
"command": "python",
|
|
67
|
+
"args": ["-m", "dokimo_mcp"]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then ask the agent: *"Use Dokimo to verify this evidence package"* (paste one), or
|
|
74
|
+
*"recompute this Merkle root and tell me if it matches."*
|
|
75
|
+
|
|
76
|
+
## Try it
|
|
77
|
+
|
|
78
|
+
The live demo page embeds a real, anchored evidence package. Fetch it and verify:
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import re, json, urllib.request
|
|
82
|
+
import dokimo_mcp as d
|
|
83
|
+
html = urllib.request.urlopen(urllib.request.Request(
|
|
84
|
+
"https://dokimo.augaster.com/agent-audits-agents.html",
|
|
85
|
+
headers={"User-Agent": d._UA})).read().decode()
|
|
86
|
+
pkg = json.loads(re.search(r"const PKG\s*=\s*(\{.*?\})\s*;", html, re.S).group(1))
|
|
87
|
+
print(d.verify_evidence_package(pkg)["verified"]) # True
|
|
88
|
+
# tamper one unit -> False
|
|
89
|
+
pkg["leaf"] = pkg["leaf"].replace("1001190933933115", "1001190933933116")
|
|
90
|
+
print(d.verify_evidence_package(pkg)["verified"]) # False
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Hosted / HTTP mode
|
|
94
|
+
|
|
95
|
+
The default transport is **stdio** (local use). Set `MCP_TRANSPORT=http` to serve
|
|
96
|
+
**MCP Streamable HTTP at `/mcp`** on `$PORT` (default 8081) with CORS — the shape
|
|
97
|
+
hosted platforms like [Smithery](https://smithery.ai) require. The included
|
|
98
|
+
`Dockerfile` + `smithery.yaml` (`runtime: container`) are set up for exactly this,
|
|
99
|
+
so Smithery can build and host it from this repo.
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
MCP_TRANSPORT=http PORT=8081 dokimo-mcp # or: docker run -p 8081:8081 <image>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## What is Dokimo?
|
|
106
|
+
|
|
107
|
+
Verifiable revenue infrastructure for autonomous commerce — audit-ready, independently
|
|
108
|
+
reproducible books for AI-agent machine payments (x402 / AP2 / Stripe), with each figure
|
|
109
|
+
tamper-evidently committed and anchored on-chain. https://dokimo.augaster.com
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dokimo-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server to verify AI-agent revenue claims: recompute a Merkle proof and check it against an on-chain anchor.
|
|
5
|
+
Author: Augaster Technologies
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://dokimo.augaster.com
|
|
8
|
+
Project-URL: Demo, https://dokimo.augaster.com/agent-audits-agents.html
|
|
9
|
+
Project-URL: Repository, https://github.com/ypratap11/dokimo-mcp
|
|
10
|
+
Project-URL: Issues, https://github.com/ypratap11/dokimo-mcp/issues
|
|
11
|
+
Keywords: mcp,model-context-protocol,x402,agentic-payments,merkle,verification,agents
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Security
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: mcp<2,>=1.2
|
|
18
|
+
Requires-Dist: uvicorn>=0.30
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
# dokimo-mcp
|
|
22
|
+
|
|
23
|
+
<!-- mcp-name: io.github.ypratap11/dokimo-mcp -->
|
|
24
|
+
|
|
25
|
+
**Give an AI agent the ability to verify another agent's revenue claims.**
|
|
26
|
+
|
|
27
|
+
An [MCP](https://modelcontextprotocol.io) server exposing [Dokimo's](https://dokimo.augaster.com)
|
|
28
|
+
trustless evidence verification as tools any MCP client (Claude Desktop, IDE
|
|
29
|
+
agents, custom agents) can call. It's the "agent that audits agents" — as tools.
|
|
30
|
+
|
|
31
|
+
Live, clickable version of what these tools do:
|
|
32
|
+
**https://dokimo.augaster.com/agent-audits-agents.html**
|
|
33
|
+
|
|
34
|
+
> This is a thin, self-contained **client**: it calls Dokimo's public endpoints and
|
|
35
|
+
> implements the public `dokimo-merkle-v1` hashing scheme. It contains no proprietary
|
|
36
|
+
> code. MIT-licensed.
|
|
37
|
+
|
|
38
|
+
## Tools
|
|
39
|
+
|
|
40
|
+
| Tool | What it does | Network? |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `recompute_merkle_root(leaf, proof_path)` | **Trustless local recompute** — hash a leaf under `dokimo-merkle-v1` and replay the proof path to a root, with **no network and no trust in anyone**. Compare it to a package's claimed `root` yourself. | none |
|
|
43
|
+
| `verify_evidence_package(package)` | **Full verification** via Dokimo's public A2A endpoint: recompute **and** check the compound commitment (root + rule version) against the **on-chain anchor on Base**. Returns `verified: true` only if both hold. | Dokimo A2A |
|
|
44
|
+
| `dokimo_agent_card()` | Fetch Dokimo's public A2A agent card — what it can verify. | Dokimo |
|
|
45
|
+
|
|
46
|
+
**Verification model:** there is no path to `verified: true` without (1) the
|
|
47
|
+
caller's `(leaf, proof_path)` recomputing to the claimed `root`, **and** (2) the
|
|
48
|
+
compound commitment of `(root, rule_version_commitment)` being anchored on-chain.
|
|
49
|
+
Tamper one byte → recompute fails. Swap the rule version → the commitment changes
|
|
50
|
+
→ not anchored.
|
|
51
|
+
|
|
52
|
+
**Honest scope:** attests that a *reported* figure is reproducible and
|
|
53
|
+
tamper-evident against an on-chain anchor — not that any underlying business
|
|
54
|
+
number is "good." Non-custodial; reads public on-chain state only.
|
|
55
|
+
|
|
56
|
+
## Install & run
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install dokimo-mcp
|
|
60
|
+
dokimo-mcp # runs over stdio
|
|
61
|
+
# or, from a clone:
|
|
62
|
+
pip install .
|
|
63
|
+
python -m dokimo_mcp
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Add to an MCP client
|
|
67
|
+
|
|
68
|
+
**Claude Desktop** — add to `claude_desktop_config.json`:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mcpServers": {
|
|
73
|
+
"dokimo": {
|
|
74
|
+
"command": "dokimo-mcp"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If `dokimo-mcp` isn't on `PATH`, use the module form:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"mcpServers": {
|
|
85
|
+
"dokimo": {
|
|
86
|
+
"command": "python",
|
|
87
|
+
"args": ["-m", "dokimo_mcp"]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Then ask the agent: *"Use Dokimo to verify this evidence package"* (paste one), or
|
|
94
|
+
*"recompute this Merkle root and tell me if it matches."*
|
|
95
|
+
|
|
96
|
+
## Try it
|
|
97
|
+
|
|
98
|
+
The live demo page embeds a real, anchored evidence package. Fetch it and verify:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
import re, json, urllib.request
|
|
102
|
+
import dokimo_mcp as d
|
|
103
|
+
html = urllib.request.urlopen(urllib.request.Request(
|
|
104
|
+
"https://dokimo.augaster.com/agent-audits-agents.html",
|
|
105
|
+
headers={"User-Agent": d._UA})).read().decode()
|
|
106
|
+
pkg = json.loads(re.search(r"const PKG\s*=\s*(\{.*?\})\s*;", html, re.S).group(1))
|
|
107
|
+
print(d.verify_evidence_package(pkg)["verified"]) # True
|
|
108
|
+
# tamper one unit -> False
|
|
109
|
+
pkg["leaf"] = pkg["leaf"].replace("1001190933933115", "1001190933933116")
|
|
110
|
+
print(d.verify_evidence_package(pkg)["verified"]) # False
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Hosted / HTTP mode
|
|
114
|
+
|
|
115
|
+
The default transport is **stdio** (local use). Set `MCP_TRANSPORT=http` to serve
|
|
116
|
+
**MCP Streamable HTTP at `/mcp`** on `$PORT` (default 8081) with CORS — the shape
|
|
117
|
+
hosted platforms like [Smithery](https://smithery.ai) require. The included
|
|
118
|
+
`Dockerfile` + `smithery.yaml` (`runtime: container`) are set up for exactly this,
|
|
119
|
+
so Smithery can build and host it from this repo.
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
MCP_TRANSPORT=http PORT=8081 dokimo-mcp # or: docker run -p 8081:8081 <image>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## What is Dokimo?
|
|
126
|
+
|
|
127
|
+
Verifiable revenue infrastructure for autonomous commerce — audit-ready, independently
|
|
128
|
+
reproducible books for AI-agent machine payments (x402 / AP2 / Stripe), with each figure
|
|
129
|
+
tamper-evidently committed and anchored on-chain. https://dokimo.augaster.com
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
dokimo_mcp.py
|
|
4
|
+
pyproject.toml
|
|
5
|
+
dokimo_mcp.egg-info/PKG-INFO
|
|
6
|
+
dokimo_mcp.egg-info/SOURCES.txt
|
|
7
|
+
dokimo_mcp.egg-info/dependency_links.txt
|
|
8
|
+
dokimo_mcp.egg-info/entry_points.txt
|
|
9
|
+
dokimo_mcp.egg-info/requires.txt
|
|
10
|
+
dokimo_mcp.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dokimo_mcp
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""Dokimo MCP server — give an AI agent the ability to verify another agent's
|
|
2
|
+
revenue claims.
|
|
3
|
+
|
|
4
|
+
A self-contained Model Context Protocol server exposing three tools:
|
|
5
|
+
|
|
6
|
+
- ``recompute_merkle_root`` — PURE, LOCAL, trustless: recompute a
|
|
7
|
+
``dokimo-merkle-v1`` root from a leaf + proof path, with no network and no
|
|
8
|
+
trust in anyone. The "check the math yourself" primitive.
|
|
9
|
+
- ``verify_evidence_package`` — full verification via Dokimo's public A2A
|
|
10
|
+
endpoint: recompute + on-chain anchor check, returning a signed-off verdict.
|
|
11
|
+
- ``dokimo_agent_card`` — fetch Dokimo's public A2A agent card.
|
|
12
|
+
|
|
13
|
+
This is a thin CLIENT: it talks to Dokimo's public endpoints and implements the
|
|
14
|
+
public ``dokimo-merkle-v1`` hashing scheme (RFC-6962-style, domain-separated).
|
|
15
|
+
It contains no proprietary code.
|
|
16
|
+
|
|
17
|
+
Verification model: there is NO path to ``verified: true`` without BOTH
|
|
18
|
+
(1) the caller's ``(leaf, proof_path)`` recomputing to the claimed root, AND
|
|
19
|
+
(2) the compound commitment of ``(root, rule_version_commitment)`` being anchored
|
|
20
|
+
on-chain. Tamper one byte → recompute fails. Swap the rule version → the compound
|
|
21
|
+
commitment changes → not anchored.
|
|
22
|
+
|
|
23
|
+
Honest scope: attests that a *reported* figure is reproducible and tamper-evident
|
|
24
|
+
against an on-chain anchor — not that any underlying business number is "good."
|
|
25
|
+
|
|
26
|
+
Run: ``dokimo-mcp`` (after ``pip install dokimo-mcp``), or ``python -m dokimo_mcp``.
|
|
27
|
+
Live demo the tools mirror: https://dokimo.augaster.com/agent-audits-agents.html
|
|
28
|
+
"""
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import hashlib
|
|
32
|
+
import json
|
|
33
|
+
import os
|
|
34
|
+
import urllib.request
|
|
35
|
+
from typing import Annotated, Any
|
|
36
|
+
|
|
37
|
+
from mcp.server.fastmcp import FastMCP
|
|
38
|
+
from mcp.types import ToolAnnotations
|
|
39
|
+
from pydantic import Field
|
|
40
|
+
|
|
41
|
+
# Public Dokimo endpoints by default. Override (e.g. a self-hosted deploy pointing
|
|
42
|
+
# at an internal address to avoid a hairpin) via DOKIMO_A2A_URL / DOKIMO_AGENT_CARD_URL.
|
|
43
|
+
DOKIMO_A2A = os.environ.get("DOKIMO_A2A_URL", "https://dokimo.augaster.com/a2a")
|
|
44
|
+
DOKIMO_AGENT_CARD = os.environ.get(
|
|
45
|
+
"DOKIMO_AGENT_CARD_URL", "https://dokimo.augaster.com/.well-known/agent-card.json")
|
|
46
|
+
|
|
47
|
+
# A real User-Agent — the default Python-urllib UA is 403'd by the CDN's bot filter.
|
|
48
|
+
_UA = "dokimo-mcp/0.1 (+https://dokimo.augaster.com)"
|
|
49
|
+
|
|
50
|
+
# --- the public dokimo-merkle-v1 scheme (documented on the public site/demo) ----
|
|
51
|
+
# Domain separation: leaves H(0x00 ‖ leaf), internal nodes H(0x01 ‖ left ‖ right),
|
|
52
|
+
# over the hex-string representations. No proprietary logic — the published scheme.
|
|
53
|
+
MERKLE_SCHEME = "dokimo-merkle-v1"
|
|
54
|
+
_LEAF_PREFIX = b"\x00"
|
|
55
|
+
_NODE_PREFIX = b"\x01"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _hash_leaf(leaf: str) -> str:
|
|
59
|
+
return hashlib.sha256(_LEAF_PREFIX + leaf.encode()).hexdigest()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _hash_node(a: str, b: str) -> str:
|
|
63
|
+
return hashlib.sha256(_NODE_PREFIX + a.encode() + b.encode()).hexdigest()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
mcp = FastMCP("dokimo")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _post_json(url: str, payload: dict, timeout: float = 25.0) -> Any:
|
|
70
|
+
data = json.dumps(payload).encode()
|
|
71
|
+
req = urllib.request.Request(
|
|
72
|
+
url, data=data,
|
|
73
|
+
headers={"Content-Type": "application/json", "User-Agent": _UA})
|
|
74
|
+
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
75
|
+
return json.loads(resp.read())
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _get_json(url: str, timeout: float = 25.0) -> Any:
|
|
79
|
+
req = urllib.request.Request(url, headers={"User-Agent": _UA})
|
|
80
|
+
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
81
|
+
return json.loads(resp.read())
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
85
|
+
title="Recompute Merkle root (local)",
|
|
86
|
+
readOnlyHint=True, idempotentHint=True, openWorldHint=False))
|
|
87
|
+
def recompute_merkle_root(
|
|
88
|
+
leaf: Annotated[str, Field(description=(
|
|
89
|
+
"The raw leaf value (e.g. a JSON string like '{\"k\":\"total_assets\",\"v\":\"...\"}'). "
|
|
90
|
+
"Hashed in the leaf domain as H(0x00 ‖ leaf)."))],
|
|
91
|
+
proof_path: Annotated[list, Field(description=(
|
|
92
|
+
"Ordered Merkle proof path: a list of [sibling_hash_hex, side] pairs, where side is "
|
|
93
|
+
"\"L\" if the sibling is on the left or \"R\" if on the right. Empty list for a single-leaf tree."))],
|
|
94
|
+
) -> dict:
|
|
95
|
+
"""Trustlessly recompute a dokimo-merkle-v1 root — LOCAL, no network, no trust.
|
|
96
|
+
|
|
97
|
+
Hash ``leaf`` in the leaf domain (H(0x00 ‖ leaf)) and replay ``proof_path`` —
|
|
98
|
+
a list of ``[sibling_hash, side]`` where side is "L" or "R" — hashing internal
|
|
99
|
+
nodes as H(0x01 ‖ left ‖ right). Compare the returned root to the ``root`` in an
|
|
100
|
+
evidence package yourself; if it differs, the package was tampered with.
|
|
101
|
+
|
|
102
|
+
Returns ``{recomputed_root, merkle_scheme, steps}``.
|
|
103
|
+
"""
|
|
104
|
+
path = [(str(h), str(s)) for h, s in proof_path]
|
|
105
|
+
for _, side in path:
|
|
106
|
+
if side not in ("L", "R"):
|
|
107
|
+
raise ValueError("each proof_path side must be 'L' or 'R'")
|
|
108
|
+
acc = _hash_leaf(leaf)
|
|
109
|
+
for sibling, side in path:
|
|
110
|
+
acc = _hash_node(sibling, acc) if side == "L" else _hash_node(acc, sibling)
|
|
111
|
+
return {"recomputed_root": acc, "merkle_scheme": MERKLE_SCHEME, "steps": len(path)}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
115
|
+
title="Verify evidence package (on-chain)",
|
|
116
|
+
readOnlyHint=True, idempotentHint=True, openWorldHint=True))
|
|
117
|
+
def verify_evidence_package(
|
|
118
|
+
package: Annotated[dict, Field(description=(
|
|
119
|
+
"The Dokimo evidence package to verify. Required keys: 'leaf' (str), 'root' (str), "
|
|
120
|
+
"'proof_path' (list of [sibling_hash, \"L\"|\"R\"]), and 'rule_version_commitment' (str). "
|
|
121
|
+
"'close_id' (str) is optional and echoed back."))],
|
|
122
|
+
) -> dict:
|
|
123
|
+
"""Fully verify a Dokimo evidence package against the LIVE on-chain anchor.
|
|
124
|
+
|
|
125
|
+
Sends the package to Dokimo's public A2A endpoint, which recomputes the Merkle
|
|
126
|
+
proof AND checks the compound commitment (root + rule version) against the
|
|
127
|
+
anchor on Base. ``package`` must contain: ``leaf`` (str), ``root`` (str),
|
|
128
|
+
``proof_path`` (list of [sibling_hash, "L"|"R"]), and
|
|
129
|
+
``rule_version_commitment`` (str); ``close_id`` is optional/echoed.
|
|
130
|
+
|
|
131
|
+
Returns the verdict: ``{verified, checks:{recompute, onchain_anchor,
|
|
132
|
+
rule_version_bound}, ...}``. ``verified`` is true only if the proof recomputes
|
|
133
|
+
AND the commitment is anchored on-chain.
|
|
134
|
+
"""
|
|
135
|
+
payload = {
|
|
136
|
+
"jsonrpc": "2.0", "id": "dokimo-mcp", "method": "SendMessage",
|
|
137
|
+
"params": {"message": {"role": "user", "parts": [{"data": package}]}},
|
|
138
|
+
}
|
|
139
|
+
resp = _post_json(DOKIMO_A2A, payload)
|
|
140
|
+
if isinstance(resp, dict) and resp.get("error"):
|
|
141
|
+
return {"verified": False, "error": resp["error"]}
|
|
142
|
+
result = resp.get("result", {}) if isinstance(resp, dict) else {}
|
|
143
|
+
task = result.get("task", result) # v1.0.1 wraps in {task:...}; legacy is bare
|
|
144
|
+
for artifact in (task.get("artifacts") or []):
|
|
145
|
+
for part in (artifact.get("parts") or []):
|
|
146
|
+
if isinstance(part.get("data"), dict):
|
|
147
|
+
return part["data"]
|
|
148
|
+
return {"verified": False, "error": "no verdict artifact in A2A response", "raw": resp}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@mcp.tool(annotations=ToolAnnotations(
|
|
152
|
+
title="Fetch Dokimo agent card",
|
|
153
|
+
readOnlyHint=True, idempotentHint=True, openWorldHint=True))
|
|
154
|
+
def dokimo_agent_card() -> dict:
|
|
155
|
+
"""Fetch Dokimo's public A2A agent card — the discovery document describing what
|
|
156
|
+
it can verify (skills, endpoints, supported A2A versions)."""
|
|
157
|
+
return _get_json(DOKIMO_AGENT_CARD)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def main() -> None:
|
|
161
|
+
"""Console-script entry point (``dokimo-mcp``).
|
|
162
|
+
|
|
163
|
+
Default transport is **stdio** (local use — Claude Desktop, IDE agents).
|
|
164
|
+
Set ``MCP_TRANSPORT=http`` (as the container image does) to serve **Streamable
|
|
165
|
+
HTTP at /mcp** on ``$PORT`` (default 8081) with CORS — the shape Smithery's
|
|
166
|
+
hosted deployments require.
|
|
167
|
+
"""
|
|
168
|
+
transport = os.environ.get("MCP_TRANSPORT", "stdio").lower()
|
|
169
|
+
if transport in ("http", "streamable-http", "shttp"):
|
|
170
|
+
import uvicorn
|
|
171
|
+
from starlette.middleware.cors import CORSMiddleware
|
|
172
|
+
from mcp.server.transport_security import TransportSecuritySettings
|
|
173
|
+
|
|
174
|
+
port = int(os.environ.get("PORT", "8081"))
|
|
175
|
+
mcp.settings.host = "0.0.0.0"
|
|
176
|
+
mcp.settings.port = port
|
|
177
|
+
# DNS-rebinding protection defaults to localhost-only hosts/origins; that
|
|
178
|
+
# protects *local* servers from malicious sites. This is a public, hosted,
|
|
179
|
+
# read-only verifier (calls only public endpoints), and it sits behind a
|
|
180
|
+
# host (Smithery) that sets its own Host/Origin — so allow any.
|
|
181
|
+
mcp.settings.transport_security = TransportSecuritySettings(
|
|
182
|
+
enable_dns_rebinding_protection=False,
|
|
183
|
+
)
|
|
184
|
+
app = mcp.streamable_http_app() # serves MCP at /mcp
|
|
185
|
+
app.add_middleware(
|
|
186
|
+
CORSMiddleware,
|
|
187
|
+
allow_origins=["*"],
|
|
188
|
+
allow_methods=["*"],
|
|
189
|
+
allow_headers=["*"],
|
|
190
|
+
expose_headers=["mcp-session-id"], # Smithery/browser clients need this
|
|
191
|
+
)
|
|
192
|
+
uvicorn.run(app, host="0.0.0.0", port=port)
|
|
193
|
+
else:
|
|
194
|
+
mcp.run() # stdio
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
if __name__ == "__main__":
|
|
198
|
+
main()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "dokimo-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MCP server to verify AI-agent revenue claims: recompute a Merkle proof and check it against an on-chain anchor."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Augaster Technologies" }]
|
|
14
|
+
keywords = ["mcp", "model-context-protocol", "x402", "agentic-payments", "merkle", "verification", "agents"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Topic :: Security",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
# Pinned to the 1.x line: this server uses the FastMCP API, which mcp 2.x
|
|
21
|
+
# renamed to MCPServer. Keeps a fresh container install (Smithery) on the API
|
|
22
|
+
# this code targets.
|
|
23
|
+
"mcp>=1.2,<2",
|
|
24
|
+
"uvicorn>=0.30", # serving Streamable HTTP at /mcp for hosted (Smithery) deploys
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.scripts]
|
|
28
|
+
dokimo-mcp = "dokimo_mcp:main"
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://dokimo.augaster.com"
|
|
32
|
+
Demo = "https://dokimo.augaster.com/agent-audits-agents.html"
|
|
33
|
+
Repository = "https://github.com/ypratap11/dokimo-mcp"
|
|
34
|
+
Issues = "https://github.com/ypratap11/dokimo-mcp/issues"
|
|
35
|
+
|
|
36
|
+
[tool.setuptools]
|
|
37
|
+
py-modules = ["dokimo_mcp"]
|