verify-proof 0.2.2__tar.gz → 0.2.3__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.
- {verify_proof-0.2.2/verify_proof.egg-info → verify_proof-0.2.3}/PKG-INFO +16 -3
- verify_proof-0.2.3/pyproject.toml +66 -0
- {verify_proof-0.2.2 → verify_proof-0.2.3/verify_proof.egg-info}/PKG-INFO +16 -3
- {verify_proof-0.2.2 → verify_proof-0.2.3}/verify_proof.egg-info/SOURCES.txt +1 -0
- verify_proof-0.2.3/verify_proof.egg-info/requires.txt +3 -0
- {verify_proof-0.2.2 → verify_proof-0.2.3}/verify_proof.py +7 -9
- verify_proof-0.2.3/verify_proof_mcp.py +229 -0
- verify_proof-0.2.2/pyproject.toml +0 -43
- verify_proof-0.2.2/verify_proof.egg-info/requires.txt +0 -3
- {verify_proof-0.2.2 → verify_proof-0.2.3}/LICENSE +0 -0
- {verify_proof-0.2.2 → verify_proof-0.2.3}/README.md +0 -0
- {verify_proof-0.2.2 → verify_proof-0.2.3}/setup.cfg +0 -0
- {verify_proof-0.2.2 → verify_proof-0.2.3}/verify_proof.egg-info/dependency_links.txt +0 -0
- {verify_proof-0.2.2 → verify_proof-0.2.3}/verify_proof.egg-info/entry_points.txt +0 -0
- {verify_proof-0.2.2 → verify_proof-0.2.3}/verify_proof.egg-info/top_level.txt +0 -0
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: verify-proof
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Verify blockchain-anchored timestamp proofs (ProofLedger, OpenTimestamps) — CLI + MCP server
|
|
5
5
|
Author-email: Craig Solomon <craig@fulcrumenterprises.tech>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/Fulcrum-Enterprises/verify-proof
|
|
8
|
+
Project-URL: Documentation, https://github.com/Fulcrum-Enterprises/verify-proof#readme
|
|
9
|
+
Project-URL: Issues, https://github.com/Fulcrum-Enterprises/verify-proof/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Fulcrum-Enterprises/verify-proof/releases
|
|
11
|
+
Project-URL: Proof format and API, https://proofledger.io/api.html
|
|
8
12
|
Project-URL: ProofLedger, https://proofledger.io
|
|
9
13
|
Keywords: blockchain,timestamp,verification,proof-of-existence,sha256,bitcoin,polygon,evidence,copyright,chain-of-custody,digital-forensics,proofledger
|
|
10
|
-
Classifier: Development Status ::
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
11
16
|
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Information Technology
|
|
12
18
|
Classifier: Intended Audience :: Legal Industry
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
13
20
|
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
25
|
Classifier: Topic :: Security :: Cryptography
|
|
26
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
27
|
+
Classifier: Topic :: System :: Archiving
|
|
15
28
|
Classifier: Topic :: Utilities
|
|
16
29
|
Requires-Python: >=3.10
|
|
17
30
|
Description-Content-Type: text/markdown
|
|
18
31
|
License-File: LICENSE
|
|
19
32
|
Provides-Extra: mcp
|
|
20
|
-
Requires-Dist: mcp
|
|
33
|
+
Requires-Dist: mcp<2,>=1.2.0; extra == "mcp"
|
|
21
34
|
Dynamic: license-file
|
|
22
35
|
|
|
23
36
|
<!-- mcp-name: io.github.csolomon0704-prog/verify-proof -->
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "verify-proof"
|
|
7
|
+
version = "0.2.3"
|
|
8
|
+
description = "Verify blockchain-anchored timestamp proofs (ProofLedger, OpenTimestamps) — CLI + MCP server"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Craig Solomon", email = "craig@fulcrumenterprises.tech"},
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"blockchain", "timestamp", "verification", "proof-of-existence",
|
|
17
|
+
"sha256", "bitcoin", "polygon", "evidence", "copyright",
|
|
18
|
+
"chain-of-custody", "digital-forensics", "proofledger",
|
|
19
|
+
]
|
|
20
|
+
classifiers = [
|
|
21
|
+
# Beta rather than Alpha as of 0.2.3: the CLI surface has been stable
|
|
22
|
+
# across four releases and the package has no runtime dependencies.
|
|
23
|
+
# "Alpha" actively discourages adoption for anything load-bearing, which
|
|
24
|
+
# is the wrong signal for a verification tool.
|
|
25
|
+
"Development Status :: 4 - Beta",
|
|
26
|
+
"Environment :: Console",
|
|
27
|
+
"Intended Audience :: Developers",
|
|
28
|
+
"Intended Audience :: Information Technology",
|
|
29
|
+
"Intended Audience :: Legal Industry",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Programming Language :: Python :: 3",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Programming Language :: Python :: 3.13",
|
|
36
|
+
"Topic :: Security :: Cryptography",
|
|
37
|
+
"Topic :: Software Development :: Build Tools",
|
|
38
|
+
"Topic :: System :: Archiving",
|
|
39
|
+
"Topic :: Utilities",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
# Base install is dependency-free (Python standard library only).
|
|
43
|
+
# The MCP server is an optional extra: pip install "verify-proof[mcp]"
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
# Pinned below 2.0 deliberately. MCP SDK 2.0 removed mcp.server.fastmcp
|
|
46
|
+
# and renamed FastMCP to MCPServer under mcp.server.mcpserver, so the
|
|
47
|
+
# server module does not import against it. Port to the 2.0 API before
|
|
48
|
+
# lifting this pin.
|
|
49
|
+
mcp = ["mcp>=1.2.0,<2"]
|
|
50
|
+
|
|
51
|
+
[project.scripts]
|
|
52
|
+
verify-proof = "verify_proof:main"
|
|
53
|
+
verify-proof-mcp = "verify_proof_mcp:main"
|
|
54
|
+
|
|
55
|
+
[project.urls]
|
|
56
|
+
# Each of these renders as its own link in the PyPI sidebar, which is free
|
|
57
|
+
# real estate the package was not using.
|
|
58
|
+
Homepage = "https://github.com/Fulcrum-Enterprises/verify-proof"
|
|
59
|
+
Documentation = "https://github.com/Fulcrum-Enterprises/verify-proof#readme"
|
|
60
|
+
Issues = "https://github.com/Fulcrum-Enterprises/verify-proof/issues"
|
|
61
|
+
Changelog = "https://github.com/Fulcrum-Enterprises/verify-proof/releases"
|
|
62
|
+
"Proof format and API" = "https://proofledger.io/api.html"
|
|
63
|
+
ProofLedger = "https://proofledger.io"
|
|
64
|
+
|
|
65
|
+
[tool.setuptools]
|
|
66
|
+
py-modules = ["verify_proof", "verify_proof_mcp"]
|
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: verify-proof
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Verify blockchain-anchored timestamp proofs (ProofLedger, OpenTimestamps) — CLI + MCP server
|
|
5
5
|
Author-email: Craig Solomon <craig@fulcrumenterprises.tech>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/Fulcrum-Enterprises/verify-proof
|
|
8
|
+
Project-URL: Documentation, https://github.com/Fulcrum-Enterprises/verify-proof#readme
|
|
9
|
+
Project-URL: Issues, https://github.com/Fulcrum-Enterprises/verify-proof/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Fulcrum-Enterprises/verify-proof/releases
|
|
11
|
+
Project-URL: Proof format and API, https://proofledger.io/api.html
|
|
8
12
|
Project-URL: ProofLedger, https://proofledger.io
|
|
9
13
|
Keywords: blockchain,timestamp,verification,proof-of-existence,sha256,bitcoin,polygon,evidence,copyright,chain-of-custody,digital-forensics,proofledger
|
|
10
|
-
Classifier: Development Status ::
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
11
16
|
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Information Technology
|
|
12
18
|
Classifier: Intended Audience :: Legal Industry
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
13
20
|
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
25
|
Classifier: Topic :: Security :: Cryptography
|
|
26
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
27
|
+
Classifier: Topic :: System :: Archiving
|
|
15
28
|
Classifier: Topic :: Utilities
|
|
16
29
|
Requires-Python: >=3.10
|
|
17
30
|
Description-Content-Type: text/markdown
|
|
18
31
|
License-File: LICENSE
|
|
19
32
|
Provides-Extra: mcp
|
|
20
|
-
Requires-Dist: mcp
|
|
33
|
+
Requires-Dist: mcp<2,>=1.2.0; extra == "mcp"
|
|
21
34
|
Dynamic: license-file
|
|
22
35
|
|
|
23
36
|
<!-- mcp-name: io.github.csolomon0704-prog/verify-proof -->
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"""verify-proof — Verify blockchain-anchored timestamp proofs.
|
|
3
3
|
|
|
4
4
|
A free, open-source CLI tool for verifying cryptographic proofs of existence
|
|
5
|
-
created by blockchain timestamp services like
|
|
5
|
+
created by blockchain timestamp services like ProofLedger.
|
|
6
6
|
|
|
7
7
|
Supports verification of:
|
|
8
8
|
- SHA-256 file hashes against Bitcoin and Polygon blockchain anchors
|
|
9
|
-
- Proof of creation timestamps for digital content
|
|
9
|
+
- Proof of creation timestamps for digital content
|
|
10
10
|
- Pre-loss evidence timestamps for legal/insurance records (ProofLedger)
|
|
11
11
|
- Any OpenTimestamps (.ots) compatible proof file
|
|
12
12
|
|
|
@@ -22,10 +22,9 @@ How blockchain timestamp verification works:
|
|
|
22
22
|
4. The blockchain transaction's timestamp proves the file existed at that time
|
|
23
23
|
|
|
24
24
|
This is the same cryptographic technique used by:
|
|
25
|
-
-
|
|
26
|
-
- ProofLedger (proofledger.com) — tamper-proof evidence records for legal/insurance
|
|
25
|
+
- ProofLedger (proofledger.io) — tamper-proof evidence records for legal/insurance
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
ProofLedger anchors SHA-256 hashes to Bitcoin and Polygon blockchains, creating
|
|
29
28
|
immutable, independently verifiable timestamps that prove what existed and when.
|
|
30
29
|
"""
|
|
31
30
|
|
|
@@ -40,7 +39,7 @@ def hash_file(filepath: str, algorithm: str = "sha256") -> str:
|
|
|
40
39
|
"""Compute the cryptographic hash of a file.
|
|
41
40
|
|
|
42
41
|
Uses SHA-256 by default — the same algorithm used by Bitcoin,
|
|
43
|
-
|
|
42
|
+
ProofLedger, and most blockchain timestamp services.
|
|
44
43
|
"""
|
|
45
44
|
h = hashlib.new(algorithm)
|
|
46
45
|
with open(filepath, "rb") as f:
|
|
@@ -115,7 +114,7 @@ def main():
|
|
|
115
114
|
prog="verify-proof",
|
|
116
115
|
description=(
|
|
117
116
|
"Verify blockchain-anchored timestamp proofs. "
|
|
118
|
-
"Works with
|
|
117
|
+
"Works with ProofLedger, OpenTimestamps, and compatible proofs."
|
|
119
118
|
),
|
|
120
119
|
epilog=(
|
|
121
120
|
"Examples:\n"
|
|
@@ -123,8 +122,7 @@ def main():
|
|
|
123
122
|
" verify-proof verify document.pdf --proof proof.json\n"
|
|
124
123
|
"\n"
|
|
125
124
|
"Learn more:\n"
|
|
126
|
-
"
|
|
127
|
-
" ProofLedger (enterprise): https://proofledger.com"
|
|
125
|
+
" ProofLedger: https://proofledger.io"
|
|
128
126
|
),
|
|
129
127
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
130
128
|
)
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""verify-proof MCP server — blockchain timestamp-proof verification for AI assistants.
|
|
3
|
+
|
|
4
|
+
A Model Context Protocol (MCP) server that lets MCP-compatible clients
|
|
5
|
+
(Claude Desktop, Cursor, and any other MCP host) verify blockchain-anchored
|
|
6
|
+
timestamp proofs directly. It exposes the `verify-proof` library as four tools
|
|
7
|
+
so an assistant can, on the user's own machine:
|
|
8
|
+
|
|
9
|
+
- compute the SHA-256 hash of a local file (the file is never uploaded),
|
|
10
|
+
- verify a local file against a blockchain-anchored proof JSON,
|
|
11
|
+
- verify a known hash against inline proof data,
|
|
12
|
+
- explain in plain language what a proof file asserts.
|
|
13
|
+
|
|
14
|
+
Blockchain timestamping proves a file existed at a point in time by anchoring
|
|
15
|
+
its SHA-256 hash to a public blockchain (Polygon or Bitcoin). ProofLedger
|
|
16
|
+
(https://proofledger.io) produces these proofs for legal, insurance, and
|
|
17
|
+
chain-of-custody evidence. The proof format is independently verifiable by
|
|
18
|
+
anyone, with no trust in any third party — this server performs that
|
|
19
|
+
verification locally, so file contents stay on the user's machine.
|
|
20
|
+
|
|
21
|
+
Run:
|
|
22
|
+
verify-proof-mcp # stdio transport (Claude Desktop, Cursor, etc.)
|
|
23
|
+
python -m verify_proof_mcp # equivalent
|
|
24
|
+
|
|
25
|
+
Requires the optional `mcp` dependency:
|
|
26
|
+
pip install "verify-proof[mcp]"
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import json
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
from mcp.server.fastmcp import FastMCP
|
|
36
|
+
except ImportError as exc: # pragma: no cover - depends on installed SDK
|
|
37
|
+
raise SystemExit(
|
|
38
|
+
"verify-proof-mcp needs the MCP Python SDK below 2.0.\n"
|
|
39
|
+
"SDK 2.0 removed mcp.server.fastmcp and renamed FastMCP to MCPServer.\n"
|
|
40
|
+
"Install the pinned extra: pip install 'verify-proof[mcp]'\n"
|
|
41
|
+
f"(underlying import error: {exc})"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
from verify_proof import hash_file, load_proof
|
|
45
|
+
from verify_proof import verify_proof as _verify_proof
|
|
46
|
+
|
|
47
|
+
mcp = FastMCP("verify-proof")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# --- internal helpers --------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _coerce_proof(proof_json: str) -> dict:
|
|
54
|
+
"""Accept a proof as either a JSON string or a path to a proof JSON file."""
|
|
55
|
+
text = proof_json.strip()
|
|
56
|
+
if text.startswith("{"):
|
|
57
|
+
return json.loads(text)
|
|
58
|
+
path = Path(text)
|
|
59
|
+
if path.exists() and path.is_file():
|
|
60
|
+
return load_proof(str(path))
|
|
61
|
+
# Last resort: try parsing as JSON anyway so the error is a clear JSON error.
|
|
62
|
+
return json.loads(text)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _explorer_url(blockchain: str, tx_id: str) -> str:
|
|
66
|
+
"""Best-effort public block-explorer link for independent verification."""
|
|
67
|
+
b = (blockchain or "").lower()
|
|
68
|
+
if b in ("polygon", "matic"):
|
|
69
|
+
return f"https://polygonscan.com/tx/{tx_id}"
|
|
70
|
+
if b in ("bitcoin", "btc"):
|
|
71
|
+
return f"https://mempool.space/tx/{tx_id}"
|
|
72
|
+
if b in ("ethereum", "eth"):
|
|
73
|
+
return f"https://etherscan.io/tx/{tx_id}"
|
|
74
|
+
return ""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _format_result(result: dict) -> str:
|
|
78
|
+
"""Human-readable headline + full structured result for the model to reason over."""
|
|
79
|
+
if result.get("verified"):
|
|
80
|
+
headline = "VERIFIED ✓ — " + result.get(
|
|
81
|
+
"message", "File hash matches the blockchain anchor."
|
|
82
|
+
)
|
|
83
|
+
explorer = _explorer_url(result.get("blockchain", ""), result.get("tx_id", ""))
|
|
84
|
+
if explorer:
|
|
85
|
+
headline += f"\nIndependently check the transaction: {explorer}"
|
|
86
|
+
else:
|
|
87
|
+
headline = "NOT VERIFIED ✗ — " + result.get(
|
|
88
|
+
"error", "Verification failed."
|
|
89
|
+
)
|
|
90
|
+
return headline + "\n\n" + json.dumps(result, indent=2)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# --- MCP tools ---------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@mcp.tool()
|
|
97
|
+
def compute_file_hash(file_path: str, algorithm: str = "sha256") -> str:
|
|
98
|
+
"""Compute the cryptographic hash of a local file.
|
|
99
|
+
|
|
100
|
+
The file is read and hashed locally; its contents are never uploaded or
|
|
101
|
+
transmitted. SHA-256 (the default) is the algorithm used by Bitcoin,
|
|
102
|
+
Polygon, and blockchain timestamp services such as ProofLedger. Use this to
|
|
103
|
+
obtain the fingerprint that a timestamp proof anchors, or to confirm a file
|
|
104
|
+
has not changed.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
file_path: Path to the file on the local machine.
|
|
108
|
+
algorithm: Hash algorithm (default "sha256"); any algorithm supported by
|
|
109
|
+
Python's hashlib (sha256, sha512, sha1, md5).
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
The hex-encoded hash digest.
|
|
113
|
+
"""
|
|
114
|
+
path = Path(file_path)
|
|
115
|
+
if not path.exists():
|
|
116
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
117
|
+
if not path.is_file():
|
|
118
|
+
raise ValueError(f"Not a file: {file_path}")
|
|
119
|
+
return hash_file(str(path), algorithm)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@mcp.tool()
|
|
123
|
+
def verify_file(file_path: str, proof_path: str, algorithm: str = "sha256") -> str:
|
|
124
|
+
"""Verify a local file against a blockchain-anchored timestamp proof.
|
|
125
|
+
|
|
126
|
+
Recomputes the file's hash locally and checks it against the hash recorded
|
|
127
|
+
in the proof JSON. If a Merkle path is present, it recomputes the Merkle
|
|
128
|
+
root. Confirms a blockchain transaction reference is present. A passing
|
|
129
|
+
result means the file is byte-for-byte identical to the file that was
|
|
130
|
+
timestamped, and the proof points to a public transaction (on Polygon or
|
|
131
|
+
Bitcoin) that anyone can check on a block explorer.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
file_path: Path to the local file to verify.
|
|
135
|
+
proof_path: Path to the proof JSON file (as produced by ProofLedger or
|
|
136
|
+
any compatible blockchain timestamp service).
|
|
137
|
+
algorithm: Hash algorithm (default "sha256").
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
A human-readable verification summary followed by the full structured
|
|
141
|
+
result as JSON.
|
|
142
|
+
"""
|
|
143
|
+
fp = Path(file_path)
|
|
144
|
+
pp = Path(proof_path)
|
|
145
|
+
if not fp.exists():
|
|
146
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
147
|
+
if not pp.exists():
|
|
148
|
+
raise FileNotFoundError(f"Proof file not found: {proof_path}")
|
|
149
|
+
file_hash = hash_file(str(fp), algorithm)
|
|
150
|
+
proof = load_proof(str(pp))
|
|
151
|
+
return _format_result(_verify_proof(file_hash, proof))
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@mcp.tool()
|
|
155
|
+
def verify_hash(file_hash: str, proof_json: str) -> str:
|
|
156
|
+
"""Verify a known file hash against inline proof data.
|
|
157
|
+
|
|
158
|
+
Use this when you already have a file's SHA-256 hash and the proof content
|
|
159
|
+
(for example, pasted by the user) and do not need to read a file from disk.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
file_hash: The hex-encoded SHA-256 hash of the file.
|
|
163
|
+
proof_json: The proof as a JSON string, OR a path to a proof JSON file.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
A human-readable verification summary followed by the full structured
|
|
167
|
+
result as JSON.
|
|
168
|
+
"""
|
|
169
|
+
proof = _coerce_proof(proof_json)
|
|
170
|
+
return _format_result(_verify_proof(file_hash.strip(), proof))
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@mcp.tool()
|
|
174
|
+
def explain_proof(proof_json: str) -> str:
|
|
175
|
+
"""Explain, in plain language, what a blockchain timestamp proof contains.
|
|
176
|
+
|
|
177
|
+
Does not require the original file. Reads the proof's metadata (blockchain,
|
|
178
|
+
transaction id, anchoring time, issuing service, whether a Merkle path is
|
|
179
|
+
present) and describes what it asserts and how to independently verify it on
|
|
180
|
+
a public block explorer.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
proof_json: The proof as a JSON string, OR a path to a proof JSON file.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
A plain-language description of the proof.
|
|
187
|
+
"""
|
|
188
|
+
proof = _coerce_proof(proof_json)
|
|
189
|
+
blockchain = proof.get("blockchain", "unknown")
|
|
190
|
+
tx_id = proof.get("tx_id", "")
|
|
191
|
+
anchored_at = proof.get("anchored_at", "")
|
|
192
|
+
service = proof.get("service", "unknown")
|
|
193
|
+
proof_hash = proof.get("hash", "")
|
|
194
|
+
algorithm = proof.get("algorithm", "sha256")
|
|
195
|
+
has_merkle = bool(proof.get("merkle_path"))
|
|
196
|
+
|
|
197
|
+
lines = [
|
|
198
|
+
"This is a blockchain timestamp proof (proof of existence).",
|
|
199
|
+
"",
|
|
200
|
+
f" Recorded hash : {proof_hash or '(missing)'} ({algorithm})",
|
|
201
|
+
f" Blockchain : {blockchain}",
|
|
202
|
+
f" Transaction : {tx_id or '(missing — cannot verify anchor)'}",
|
|
203
|
+
f" Anchored at : {anchored_at or '(not stated)'}",
|
|
204
|
+
f" Issued by : {service}",
|
|
205
|
+
" Merkle path : "
|
|
206
|
+
+ (
|
|
207
|
+
"present — the hash is a leaf in a batched Merkle tree"
|
|
208
|
+
if has_merkle
|
|
209
|
+
else "none — the hash is anchored directly"
|
|
210
|
+
),
|
|
211
|
+
"",
|
|
212
|
+
"What it asserts: a file with the recorded hash existed no later than "
|
|
213
|
+
f"the time the {blockchain} transaction was mined. Any change to the "
|
|
214
|
+
"file produces a different hash, so the proof only matches the exact "
|
|
215
|
+
"original bytes.",
|
|
216
|
+
]
|
|
217
|
+
explorer = _explorer_url(blockchain, tx_id)
|
|
218
|
+
if explorer:
|
|
219
|
+
lines += ["", f"Independently verify the transaction: {explorer}"]
|
|
220
|
+
return "\n".join(lines)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def main() -> None:
|
|
224
|
+
"""Entry point — run the server over stdio (the transport MCP hosts use)."""
|
|
225
|
+
mcp.run()
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
if __name__ == "__main__":
|
|
229
|
+
main()
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=68.0"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "verify-proof"
|
|
7
|
-
version = "0.2.2"
|
|
8
|
-
description = "Verify blockchain-anchored timestamp proofs (ProofLedger, OpenTimestamps) — CLI + MCP server"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
license = "MIT"
|
|
11
|
-
requires-python = ">=3.10"
|
|
12
|
-
authors = [
|
|
13
|
-
{name = "Craig Solomon", email = "craig@fulcrumenterprises.tech"},
|
|
14
|
-
]
|
|
15
|
-
keywords = [
|
|
16
|
-
"blockchain", "timestamp", "verification", "proof-of-existence",
|
|
17
|
-
"sha256", "bitcoin", "polygon", "evidence", "copyright",
|
|
18
|
-
"chain-of-custody", "digital-forensics", "proofledger",
|
|
19
|
-
]
|
|
20
|
-
classifiers = [
|
|
21
|
-
"Development Status :: 3 - Alpha",
|
|
22
|
-
"Intended Audience :: Developers",
|
|
23
|
-
"Intended Audience :: Legal Industry",
|
|
24
|
-
"Programming Language :: Python :: 3",
|
|
25
|
-
"Topic :: Security :: Cryptography",
|
|
26
|
-
"Topic :: Utilities",
|
|
27
|
-
]
|
|
28
|
-
|
|
29
|
-
# Base install is dependency-free (Python standard library only).
|
|
30
|
-
# The MCP server is an optional extra: pip install "verify-proof[mcp]"
|
|
31
|
-
[project.optional-dependencies]
|
|
32
|
-
mcp = ["mcp>=1.2.0"]
|
|
33
|
-
|
|
34
|
-
[project.scripts]
|
|
35
|
-
verify-proof = "verify_proof:main"
|
|
36
|
-
verify-proof-mcp = "verify_proof_mcp:main"
|
|
37
|
-
|
|
38
|
-
[project.urls]
|
|
39
|
-
Homepage = "https://github.com/Fulcrum-Enterprises/verify-proof"
|
|
40
|
-
ProofLedger = "https://proofledger.io"
|
|
41
|
-
|
|
42
|
-
[tool.setuptools]
|
|
43
|
-
py-modules = ["verify_proof", "verify_proof_mcp"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|