Use without AI — web apps & local processes
No assistant required. The same public MCP endpoint is a plain Streamable HTTP JSON-RPC service. Embed it in a web application (browser fetch), call it from a desktop/CLI process, a backend worker, or a mobile app. AI connectors are optional. Endpoint: https://mcp.verae.ai/mcp. Hash on the device; send only the hex digest. Never upload file bytes.
Web page / SPA
Hash with WASM in the browser, then fetch /mcp (CORS *). Live: app.html, register.html, and sample.html.
Local program
CLI, daemon, or any language with HTTP: official Python client, curl JSON-RPC, or an MCP SDK. Runs on your machine with no chat UI.
Optional: AI hosts
Same URL works in Claude.ai, ChatGPT, Grok, Claude Desktop, and Cursor when you want an assistant to call stamp / verify for you.
Local process (Python CLI / scripts)
Official client for scripts and desktop tools — no AI involved. Hash locally, stamp via MCP, write receipts under ~/.verae/receipts/.
# install hasher (or let the client auto-fetch)
DIGEST=$(verae-sha256 ./document.pdf)
# stamp against the public server (digest only — file stays local)
uvx verae-mcp-timestamping-client \
--url https://mcp.verae.ai/mcp \
--scope global \
./document.pdf
# hash only (no network)
uvx verae-mcp-timestamping-client --hash-only ./document.pdf
Optional machine OAuth: set VERAE_OAUTH_CLIENT_ID / VERAE_OAUTH_CLIENT_SECRET (and usually VERAE_OAUTH_ISSUER). Tokens land under ~/.verae/oauth/, not in chat.
Any language (MCP SDK or raw JSON-RPC)
Transport is Streamable HTTP at /mcp. Session id comes back in the Mcp-Session-Id response header — send it on later requests. Tools: stamp (create), hash_report (lookup by digest), verify (check one receipt id), plus account helpers.
Lookup receipts for an existing hash
hash_report returns the JSON receipt history for one SHA-256 (Carfax-style). Optional want_scope=global asks api.veraetime.net as the central source of truth. verify checks a single receipt_id from a prior stamp.
# after initialize + notifications/initialized (same session as above):
curl -sS -X POST https://mcp.verae.ai/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Mcp-Session-Id: SESSION' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"hash_report","arguments":{"sha256":"DIGEST_HEX","want_scope":"global"}}}'
# verify one receipt id from a previous stamp:
curl -sS -X POST https://mcp.verae.ai/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Mcp-Session-Id: SESSION' \
-d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"verify","arguments":{"receipt_id":"RECEIPT_ID","want_scope":"global"}}}'
In the browser sample, pick tool hash_report or verify. In JS, use the same tools/call shape with name: "hash_report" and { sha256, want_scope }.
# 1) initialize
curl -sS -D - -X POST https://mcp.verae.ai/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-app","version":"1.0.0"}}}'
# 2) notifications/initialized (include Mcp-Session-Id from step 1)
# 3) tools/call stamp
curl -sS -X POST https://mcp.verae.ai/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Mcp-Session-Id: SESSION' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"stamp","arguments":{"sha256":"DIGEST_HEX","scope":"global"}}}'
Python SDK shape (same as the official client): Client(url) then await client.call_tool("stamp", {"sha256": digest, "scope": "global"}).
Embed in a web page (browser JavaScript)
Drop this into any web app — not an AI product. Same-origin pages on this host (and CORS * on /mcp) can fetch the endpoint. Live demos: full browser app, multi-doc registration, raw MCP sample. Hash in-page with WASM (or Web Crypto), then stamp the digest only.
const url = "https://mcp.verae.ai/mcp";
async function post(body, session) {
const headers = {
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream"
};
if (session) headers["Mcp-Session-Id"] = session;
const res = await fetch(url, { method: "POST", headers, body: JSON.stringify(body) });
const text = await res.text();
const sessionId = res.headers.get("mcp-session-id") || session;
let parsed; try { parsed = JSON.parse(text); } catch { parsed = text; }
if (!res.ok) throw new Error(res.status + " " + text);
return { parsed, sessionId };
}
const init = await post({
jsonrpc: "2.0", id: 1, method: "initialize",
params: {
protocolVersion: "2025-03-26",
capabilities: {},
clientInfo: { name: "browser-app", version: "0.1.0" }
}
});
await post({ jsonrpc: "2.0", method: "notifications/initialized" }, init.sessionId);
const call = await post({
jsonrpc: "2.0", id: 2, method: "tools/call",
params: { name: "stamp", arguments: { sha256: DIGEST_HEX, scope: "global" } }
}, init.sessionId);
console.log(call.parsed);
For hashing in the browser, use the WASM module from Get the local hasher (sha256_hex_js / Sha256Stream). Do not POST file contents to /mcp.