MCP Recipes
Pro+Build a Compliance Store From Public Regulations
The agent fetches one or more public regulatory documents, loads each into a compliance vector store end to end, and verifies ingestion -- so you can score your system against the actual regulation text. Supports versioned stores (e.g. GDPR 2024 vs GDPR 2026) for regulatory gap analysis.
Run it: paste into your MCP agent
Highlighted parts are placeholders. Replace them with your own values before (or after) copying.
Using the LLM Prover MCP tools PLUS your client's own web-fetch, filesystem, and HTTP tools,
build one or more COMPLIANCE stores from public regulatory documents. This spans three
surfaces: MCP (create/poll the store), your client's tools (fetch the doc, hold it locally,
HTTP PUT the bytes), and our REST API (presigned upload URL + confirm). It is configurable:
it takes a LIST of (regulation source, target store) items so you can build several stores
-- most importantly, separate stores per regulation VERSION so I can later A/B my system's
compliance across versions. Do NOT claim any store is ready until you have verified it.
READ FIRST -- two compliance-specific rules that override convenience:
- CHUNKING QUALITY IS CORRECTNESS HERE. A compliance verdict is only as good as the clause
the judge retrieves. A regulation that chunks into too few pieces will retrieve the wrong
clause and produce a confident, wrong verdict at real cost. Prefer DOCX or Markdown
sources over PDF/plain-text where I have a choice, and flag any store whose chunk_count
looks low for the document size -- loudly, before I rely on it.
- NOT LEGAL ADVICE. A compliance score from the judge is decision-support, not legal
advice. Say this plainly when you report, and never imply a "compliant" verdict is a
legal guarantee.
1. Confirm the LLM Prover MCP tools you need are available (list the tools): create_rag_store
and get_rag_store.
2. PREREQUISITE CHECK (fail fast). This recipe needs THREE capabilities FROM YOUR CLIENT:
- a web-fetch tool (to download the regulation document from a URL/source),
- a filesystem tool (to hold the fetched file locally), and
- an HTTP tool that can make a raw PUT with a request body.
Confirm ALL THREE are available in THIS client before anything else. If any is missing,
STOP and tell me which -- do not start building a store you cannot finish. Compliance
stores require a sufficient plan tier; if an MCP call reports a tier block, surface it
cleanly rather than guessing.
2b. SORT OUT A REST CREDENTIAL. The upload/confirm steps are REST calls, NOT MCP tools, so
they need an API key your MCP session does not give you (even over OAuth). FIRST ASK:
"Do you already have an LLM Prover API key?" Then branch:
- IF I HAVE A KEY: do not ask me to paste it. Ask how you should ACCESS it -- an env var
name or a local file path (e.g. .env), plus the API base URL -- and read it at call
time. Pasting into chat is the last resort; if I paste it, note I should rotate it.
- IF I DO NOT HAVE A KEY: guide me step by step: log in -> Developers / API Keys ->
create key (shown once) -> copy it and the API base URL -> put both in an env var or
local .env (e.g. LLMPROVER_API_KEY, LLMPROVER_API_BASE) and tell you the name/path.
Treat the key as a secret: use it only in the request header, NEVER echo/log/commit it.
3. GET THE LOADING PLAN FROM ME. Ask for a LIST of items, each being:
- the regulation document SOURCE (a URL the client can fetch, or a source you can reach),
- the target STORE: a name and, if versioned, the VERSION/effective-date label
(e.g. "GDPR 2024", "GDPR 2026").
Decide grouping with me: typically ONE store per regulation VERSION (so each store holds a
single coherent version of the text and the versions stay separable for A/B gap analysis).
For a first run, one document into one store is fine; structure the work to loop.
FOR EACH TARGET STORE (loop):
4. CREATE THE STORE over MCP: create_rag_store(name=<name, include the version label>,
store_type="compliance"). Capture the store_id. Tell me the exact name, version, and
store_id so I can tell the versioned stores apart later.
FOR EACH DOCUMENT bound for this store (inner loop):
5. FETCH IT with your client's web tool and SAVE IT LOCALLY. Note the local path, filename,
content type, and size in bytes. If the source offers DOCX or Markdown, prefer it over
PDF/plain-text (better clause chunking). If you cannot fetch it, STOP for that item and
tell me the source failed -- do not fabricate or substitute a document.
6. REQUEST A PRESIGNED UPLOAD URL from REST (client HTTP tool, key+base from step 2b):
POST <api-base>/files/upload-url
Header: X-Api-Key: <developer key>
Header: Content-Type: application/json
Body: {"filename": <filename>, "content_type": <content_type>,
"purpose": "rag_context", "size_bytes": <size>, "store_id": <this store_id>}
purpose MUST be "rag_context" and store_id MUST be this store's id. The response returns
an "upload_url", a file_id, and ingest_status. If no upload_url, STOP and report the body.
7. PUT THE RAW BYTES to upload_url (client HTTP tool): PUT with Content-Type matching step 6,
body = the raw bytes, NO auth header (the URL is signed). 200/204 means the object landed.
7a. CONFIRM (REST, client HTTP tool -- the PUT alone does NOT start ingest):
POST <api-base>/files/<file_id>/confirm
Header: X-Api-Key: <same developer key>
Body: {}
A 200 registers the file and triggers chunk + embed. Skip this and the store sits empty
while falsely reporting "ready".
8. POLL get_rag_store(store_id) every 5 seconds (stop at 5 min). Success for this store is
sync_status "ready" AND file_count >= (docs you loaded) AND chunk_count > 0. CRITICAL:
an EMPTY store reports "ready" with 0 chunks -- "ready" alone is NOT success. If
chunk_count stays 0 past the confirm, the confirm did not fire -- report it. If "dirty",
ingestion failed -- do not use the store. SANITY-CHECK chunk_count against the regulation
size: a long regulation that produced very few chunks ingested badly and WILL retrieve
the wrong clause -- flag it hard (compliance correctness depends on this).
9. (end inner loop / end store loop) Move to the next document, then the next store.
10. REPORT: for every store, its name + VERSION label + store_id, sync_status, file_count,
chunk_count, and your chunk-quality read. List the versioned stores side by side so I can
see the set I now have (e.g. GDPR-2024 vs GDPR-2026). Then:
- COST-SAFETY: do not run any compliance check against a store until it is ready.
- NOT LEGAL ADVICE: restate that scoring against these stores is decision-support.
- NEXT: suggest (once) proving retrieval on a store before trusting it (the "Prove a
RAG Store Actually Retrieves" recipe), then a compliance check; and if I built
multiple versions, note they are now ready for a version-to-version A/B gap analysis.
ON ANY FAILURE at any step for any item: tell me EXACTLY which store, which document, and
which step broke (fetch, store create, upload-url, PUT, confirm, or ingest), and the error.
Report which stores/docs DID succeed and which did not -- never present a partial corpus as
complete. Give me every store_id you created so I can clean up. Never claim a compliance
store is ready unless get_rag_store returned chunk_count > 0.
Goal
Build compliance stores from known regulatory documents without assembling them by hand. The agent fetches each regulation, loads it into a compliance vector store end to end (create -> fetch -> upload via API -> confirm -> verify ingest), and reports what it built. It is configurable: give it several documents or several versions and it loops, building a separate store per regulation version so you can A/B your system’s compliance across versions.
When to use
Reach for this to stand up the compliance corpus behind a compliance check – a privacy regulation, a safety code, a policy standard you hold as a public document. Its highest-value use is building versioned stores (e.g. “GDPR 2024” and “GDPR 2026” as separate stores) so you can later run the same responses against each and see exactly what a regulation change broke.
How it works
- Same three-surface upload as a general store, with a fetch front-end. MCP creates and
polls each store; the client fetches the document and PUTs the bytes; REST issues the
presigned URL and confirms the file (which triggers ingest – the PUT alone does not). It is
the “Load a File Into a RAG Store” choreography, looped, with a web-fetch step 5 and
store_type: compliance. - One store per version. Keeping each regulation version in its own store is what makes version-to-version gap analysis possible: run your responses against each store and diff the per-clause verdicts to see what a change in the regulation did to your compliance.
- Chunking quality is correctness, not polish. A compliance verdict is only as good as the clause the judge retrieves, so the recipe prefers well-structured sources (DOCX/Markdown) and flags any store that chunked too thinly before you spend on a verdict against it.
- Decision-support, not legal advice. A compliance score is a signal to act on, not a legal guarantee; the recipe says so in its report.
Verification
- Each store exists with
store_type: compliance, its regulation document(s) loaded,sync_status: ready, andchunk_count > 0(a “ready” store with 0 chunks is empty, not loaded – the confirm step was likely skipped). - Versioned stores are reported as a distinguishable set (name + version + store_id each), so the versions can be told apart for A/B gap analysis.
- Low chunk_count relative to the regulation size was flagged, not glossed over.
- The report states the “not legal advice” boundary and the cost-safety rule, and on any failure named the exact store/document/step that broke with every store_id for cleanup.
Where this leads
Natural next recipes once you are comfortable with this one.
Before trusting a compliance verdict, prove the store retrieves the right clauses -- run a grounded smoke-test against it.
Store built? Now score a response against it clause by clause with a compliance rubric.