JidoSeal MCP server
Lets a host tool — Claude Code, Cursor, an OpenKnowledge workflow, any MCP client — run JidoSeal's free Self-Check and reach the paid certification from inside its own environment, without the customer leaving the host and without their files leaving the machine.
It exposes the website's model, unchanged:
| Tool | What it does | Network |
|---|---|---|
jidoseal_scan |
The free Self-Check over a folder on this machine: the corpus's tier (Bronze/Silver/Gold), the missing fields per file for the next tier, and coverage against each tier — the same tier, gap list and coverage jidoseal.com/app/run reports for the same folder. |
none |
jidoseal_certification_offer |
What certification would cost for this corpus and why that price, what the certificate includes, and exactly which facts a purchase would send. | none |
jidoseal_start_checkout |
Asks jidoseal.com to create a real Stripe Checkout session and returns its URL for the customer to open. Takes no payment. | jidoseal.com only |
On a scan, this is exactly what leaves your machine, in the tool's own words:
Exactly what leaves your machine: nothing — 100% local, zero content egress. Your files, their names, and their contents never leave your device.
The scan writes its own records (manifest.json, an appended progress.ndjson) under
<root>/.jidoseal/ and nowhere else.
Arm's length, by construction
This is a standalone process that speaks only the Model Context Protocol (JSON-RPC 2.0 over stdio). It contains, vendors, links and imports no OpenKnowledge source and takes no dependency on OpenKnowledge — or on any host. The only things crossing the boundary are MCP's own JSON envelopes and JidoSeal's own scan result; no host's internal data structures enter this process, and none of JidoSeal's leave it. Hosts under GPL-3.0 (OpenKnowledge is) can therefore call it exactly as any other MCP client would.
It also carries no MCP SDK: the protocol is implemented on the Python standard library alone
(jidoseal_mcp.py), so nothing it depends on can change that answer later. mcp_server/tests/ test_mcp_isolation.py enforces all of this mechanically.
Install
pip install jidoseal-mcp
That is everything. It pulls in jidoseal (the scan engine and its CLI) and puts a
jidoseal-mcp command on your PATH. Requires Python 3.9+.
No JidoSeal account, no API key, and no network access for the scan — not at install time and not at run time.
Running from a repo checkout instead
The server also runs straight from a clone, with engine/ beside mcp_server/:
pip install PyYAML # the engine's single dependency
python3 <repo>/mcp_server/jidoseal_mcp.py
Wherever the instructions below say "command": "jidoseal-mcp", use
"command": "python3", "args": ["<repo>/mcp_server/jidoseal_mcp.py"] instead.
Wiring it into a host
The server is one command — jidoseal-mcp — speaking MCP over stdio.
Claude Code
claude mcp add jidoseal -- jidoseal-mcp
…or commit a project-scoped .mcp.json in the repo your team works in:
{
"mcpServers": {
"jidoseal": {
"command": "jidoseal-mcp"
}
}
}
Cursor
~/.cursor/mcp.json (or .cursor/mcp.json inside a project) — same block:
{
"mcpServers": {
"jidoseal": {
"command": "jidoseal-mcp"
}
}
}
Any other MCP host
Every MCP host that supports stdio servers takes the same facts — a name and a command. Register it however that host spells it:
{
"mcpServers": {
"jidoseal": {
"command": "jidoseal-mcp",
"args": [],
"env": {}
}
}
}
If the host runs with a different interpreter than the one you installed into, point it at the module instead — same server, no PATH lookup:
{
"mcpServers": {
"jidoseal": {
"command": "/path/to/your/python",
"args": ["-m", "jidoseal_mcp"]
}
}
}
Optional environment:
| Variable | Default | Purpose |
|---|---|---|
JIDOSEAL_SITE_URL |
https://jidoseal.com |
Where jidoseal_start_checkout posts. Only ever read by that tool. |
Verify the wiring by hand, without any host:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"x","version":"0"}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| jidoseal-mcp
You should see an initialize result naming jidoseal, then the three tools.
The tools
jidoseal_scan
{ "root": "/path/to/your/docs", "include_machine": false }
Returns the /app/run result for that folder:
{
"corpus": { "file_count": 4, "tier": "none",
"coverage": { "bronze": 75.0, "silver": 50.0, "gold": 25.0 } },
"files": [
{ "name": "bronze.md", "tier": "bronze", "hash": "sha256:…",
"present": ["type"],
"missing": {
"silver": [ { "field": "title", "fix": "AUTO" },
{ "field": "owner", "fix": "NEEDS-CLIENT" } ],
"gold": [ { "field": "status", "fix": "AUTO", "default": "stable" } ] },
"frontmatter_ok": true }
],
"certified_eligible": false,
"score": 50,
"merkleRoot": "6533130d…",
"scan": { "manifest_path": "…/.jidoseal/manifest.json", "run_id": "scan-…" }
}
- Tier —
bronze= OKF v0.2 as written (a populatedtype);silver= Bronze + ISO 9001 §7.5.2 (title, description, timestamp, owner);gold= Silver + ISO 30401 (status,review_policy,reviewed_at,next_review_at). A corpus's tier is the lowest tier any one of its files reaches. - Gaps — per file, which fields are missing for each tier, each marked
AUTO(JidoSeal can propose the value) orNEEDS-CLIENT(only the owner can answer it). Close them for free and re-run; nothing is charged for scanning. frontmatter_ok: false— that file's frontmatter block exists but does not parse, so its gaps cannot be closed by writing fields into it. Fix it by hand.include_machine: trueignores the corpus's own machine/transient excludes from.jidoseal/config.yaml. Leave it false — the certified path scans without it.
jidoseal_certification_offer
{ "root": "/path/to/your/docs" }
Local computation only. Returns the corpus's tier, the price for it and why that price, the remaining gap counts, what the certificate includes, and the exhaustive list of what a purchase would send. It charges nothing and starts nothing.
jidoseal_start_checkout
{ "root": "/path/to/your/docs", "company": "Acme Ltd",
"submitter_name": "Jane Doe", "submitter_email": "jane@acme.example" }
Call it only on the customer's explicit go-ahead: it is the purchase step. It asks jidoseal.com to create a Stripe Checkout session and returns the link for the customer to open and pay. It takes no payment — JidoSeal never sees a card, Stripe hosts the checkout, and nothing is charged and no certificate is issued unless the customer completes it there. A corpus that is not yet at Bronze is refused rather than charged.
The tier, score and Merkle root it submits come from a fresh local scan run here — never from whatever the caller asserts.
Pricing (the site's own, in full)
| Price | When | |
|---|---|---|
| JidoSeal Self-Check | Free | Always. Unlimited, on your machine, no account. |
| Bronze — OKF v0.2, as written | $149 | if you already meet Bronze — certificate only |
| $199 | if you don't yet — corrections + certificate | |
| Silver — + ISO 9001 §7.5.2 fields | $349 | corrections + certificate |
| Gold — + ISO 30401 governance | $599 | corrections + certificate |
Each tier is a single flat price, however many files need correcting — no file-count tiering. Certification is point-in-time: the certificate attests your corpus as of its timestamp, and editing files afterwards does not void it.
Certification buys: guided corrections to your target tier, a human approval step (from the score and hash alone, never your files), a signed certificate bound to a Merkle root of your corpus, a verifiable tamper-evident badge, a public verification page, and a listing in the public JidoSeal registry.
What leaves the machine
A scan: nothing. Not the files, not their names, not their contents. That is a property of
the import graph, not a promise about which branches run — jidoseal_mcp.py, scan_result.py and
offer.py import no socket, no urllib, no HTTP client of any kind, and neither does anything
they pull in. checkout_client.py is the one module that can reach the network, and it is
imported only inside the checkout handler.
A purchase, if the customer chooses one: company, name and email as they typed them, the tier, a 0-100 score, the corpus's Merkle root, the local scan's id, and which Bronze price applies. No file contents, no file names, no per-file hashes, no paths. The Merkle root is a one-way digest — it binds the certificate to that exact corpus, and nothing can be read back out of it.
Reproduce the proof yourself, against the copy you installed:
# 1. Read the shipped artifact. The scan path is jidoseal_mcp/scan_result/offer/engine_path/
# attestation; none of them imports a network module. checkout_client.py is the one that
# does, and nothing on the scan path imports it.
python3 -c "import jidoseal_mcp, inspect, os; print(os.path.dirname(inspect.getfile(jidoseal_mcp)))"
# 2. No network syscall is made during a scan (the trace ends up empty but for the exit line)
strace -f -o /tmp/trace.txt -e trace=network jidoseal-mcp < your-jsonrpc-input
# 3. The scan works with no network at all
bwrap --unshare-net --dev-bind / / jidoseal-mcp < your-jsonrpc-input
Tests
The test suite ships with the source, not with the wheel. From a checkout:
python3 -m pytest mcp_server/tests/ -q
Covers the protocol surface, all three tools, the zero-egress guarantee (static import
inspection + the engine's own runtime assert_no_egress guard), and parity: the scan result is
diffed against both existing implementations of the same rubric — api/main.py's audit bridge
(byte for byte) and the real web/lib/tier1-scoring.ts that the browser runs at /app/run
(tier, coverage, score, Merkle root, and which fields are missing per file). See
tests/test_mcp_parity.py for the one annotation difference that comparison excludes, and why.
tests/test_mcp_packaging.py builds this wheel and asserts what the artifact itself contains:
exactly the six modules above, no duplicate of any engine module the jidoseal package already
installs, exactly one module able to reach the network, and a shipped attestation.py that is
byte-identical to the engine's.
Release files for jidoseal-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jidoseal_mcp-0.1.0.tar.gz | 30.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jidoseal_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.3 kB
Release files / jidoseal_mcp-0.1.0.tar.gz
| Download URL | jidoseal_mcp-0.1.0.tar.gz |
|---|---|
| Size | 30.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0f3359673afb835c9cea5761779780fd29d09889e5247110f8bcee91e3965ca7
|
|
BLAKE2b-256 checksum How to use checksums |
e0756d5be43d0afdc093410f81533ef941eb5b32d7ae55aff4ab327e9a6e7682
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / jidoseal_mcp-0.1.0-py3-none-any.whl
| Download URL | jidoseal_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 29.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e9e0253f05968b7f1f8ff17b6ca0809df0a0374906fd8f2fd03eedd7403e3db4
|
|
BLAKE2b-256 checksum How to use checksums |
20afaafdbfc105710319b7060c643a4612ea026fdec37c57f6058af193ee7092
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|