Give Your Agent the Dictionary: REDCap Governance over MCP
When the caller is an AI agent rather than a shell script, the interesting question stops being "what's the route?" and becomes "what is the agent allowed to know, and what is it allowed to do?" CoreModels answers that with an MCP server whose vendor-integration tools mirror our HTTP surface exactly — same audit engine, same additive import, same read-only posture — but packaged as typed tools an agent can discover, reason about, and chain. This article walks the four tools that matter for REDCap, with the real arguments, and shows the pattern we recommend for agents that govern clinical research schemas: discover, audit, and only then (with a human's admin endpoint) import.
Give Your Agent the Dictionary: REDCap Governance over MCP
When the caller is an AI agent rather than a shell script, the interesting question stops being "what's the route?" and becomes "what is the agent allowed to know, and what is it allowed to do?" CoreModels answers that with an MCP server whose vendor-integration tools mirror our HTTP surface exactly — same audit engine, same additive import, same read-only posture — but packaged as typed tools an agent can discover, reason about, and chain. This article walks the four tools that matter for REDCap, with the real arguments, and shows the pattern we recommend for agents that govern clinical research schemas: discover, audit, and only then (with a human's admin endpoint) import.
Two endpoints, one role model
The CoreModels MCP server is streamable HTTP with OAuth 2.0 (dynamic client registration and PKCE — no pre-registered client id needed), and it comes in two flavors:
/mcp— the public endpoint, serving read-only tools only (everything that runs at Viewer role)./mcp-admin— the admin endpoint, additionally serving the write tools.
The split is enforced server-side: a client on /mcp cannot see or execute a write tool. And independently of the endpoint, every tool call is checked against the caller's actual role on the target project — write tools require Editor/Admin membership regardless of which endpoint minted the token. For REDCap that means audit_vendor_project, generate_vendor_artifacts, and get_vendor_integration_status are available everywhere, while import_vendor_project exists only on /mcp-admin and only works for project admins.
Connecting from Claude Code:
claude mcp add --transport http coremodels https://coremodels.example.com/mcp
Or for any JSON-configured MCP client:
{
"mcpServers": {
"coremodels": { "type": "http", "url": "https://coremodels.example.com/mcp" }
}
}
In Claude's UI it's Settings → Connectors → Add custom connector with the same URL; the OAuth flow runs automatically.
Tool 1 — discover what exists: get_vendor_integration_status
An agent shouldn't hardcode vendor knowledge; it should ask. Called with just a project id, the tool lists every registered connector with its capabilities and expected artifacts:
{ "graphProjectId": "0f3a9c81b7de4c22a5e6d90417f8b3aa" }
The REDCap row comes back with key redcap, capabilities Import, Audit, Generate, and the artifact note telling the agent exactly what to supply: data_dictionary — the data dictionary CSV. Called with a vendor, it returns the project's last-import state instead:
{ "graphProjectId": "0f3a9c81b7de4c22a5e6d90417f8b3aa", "vendor": "redcap" }
The result carries imported (has this project ever imported a REDCap estate?), the recorded state (timestamps, artifact fingerprint, counts, facts), and the number of governed datasets. This is the agent's orientation step: it learns whether it is auditing against a governed model or talking to an empty project, without touching anything.
Tool 2 — the workhorse: audit_vendor_project
This is the free Schema Audit as a tool call — coverage, drift, and conformance of a fresh dictionary against the governed graph, strictly read-only, available on the public endpoint. Inline form:
{
"graphProjectId": "0f3a9c81b7de4c22a5e6d90417f8b3aa",
"vendor": "redcap",
"artifacts": {
"data_dictionary": "\"Variable / Field Name\",\"Form Name\",\"Field Type\",…"
}
}
graphProjectId must match ^[a-f0-9]{32}$; vendor is the connector key; artifacts maps artifact name to raw content. The result gives the agent everything it needs to self-gate: errorCount, warningCount, infoCount, the structured findings array (section, severity, code, subject, message, detail), a markdown report ready to paste into a PR or a chat reply, and metrics. The rule an agent should internalize is the same one CI uses: errorCount > 0 means the dictionary violates governed meaning — stop and escalate.
For REDCap specifically, the conformance findings are where an agent earns its keep. The phi-fields finding is an aggregated PHI inventory — one finding per instrument, with the flagged variable names in detail. An agent asked to "pull some example records" or "draft an export script" can and should run this audit first and treat every field named in a phi-fields finding as off-limits until a human says otherwise. text-no-validation flags free-text fields that will resist harmonization, and duplicate-choice-codes (a Warning) flags choice lists whose exported data is ambiguous — both useful raw material for an agent proposing dictionary improvements.
The artifactUrls flow — when the CSV won't fit in a prompt
MCP clients can't always inline a large artifact into a tool call. Both artifact-bearing tools therefore accept artifactUrls alongside (or instead of) artifacts — a map of artifact name to a URL the server fetches:
{
"graphProjectId": "0f3a9c81b7de4c22a5e6d90417f8b3aa",
"vendor": "redcap",
"artifactUrls": {
"data_dictionary": "https://artifacts.example.org/study-42/data_dictionary.csv"
}
}
Because these are server-side GETs to caller-supplied URLs, the fetch is SSRF-guarded: only https is allowed, redirects are disabled, hosts that resolve to loopback, link-local (cloud metadata), or private ranges are refused, and the response size is capped at 256 MB. A refused or failed fetch doesn't fail the whole call silently — problems come back in a fetchProblems list on the result, so the agent can see exactly which artifact couldn't be retrieved and why. If neither artifacts nor artifactUrls yields anything usable, the tool errors with a message naming both options.
One practical pattern: have your pipeline drop the freshly exported dictionary onto an https-reachable artifact store, then let the agent audit by URL. The agent never handles megabytes of CSV, and the REDCap API token that produced the export never appears anywhere near the agent or CoreModels.
Tool 3 — the write path: import_vendor_project
Import is the one REDCap tool that writes, so it lives on /mcp-admin only and requires the Admin role on the project. The arguments are identical to the audit tool — same graphProjectId/vendor/artifacts/artifactUrls/spaces schema — which makes the safe agent workflow symmetrical: audit with one tool, review, then import with the same payload on the admin endpoint.
The import is additive. Instruments become Types, variables become Elements, choice lists become Taxonomies, Required Field? = y becomes a NotNull check, and the PHI marks and branching logic ride vendor metadata — but already-governed nodes are never mutated. The result reports datasetsAdded, fieldsAdded, nodesEnriched, lossiness, and errors, and the tool's description says out loud what an agent should already assume: to see what changed, don't re-import — run audit_vendor_project.
This division is deliberate agent ergonomics. A read-only agent on /mcp can monitor, report, and recommend forever without any risk of writing. Granting it the admin endpoint is a separate, human decision.
Tool 4 — closing the loop: generate_vendor_artifacts
{ "graphProjectId": "0f3a9c81b7de4c22a5e6d90417f8b3aa", "vendor": "redcap",
"typeNames": ["demographics"] }
Read-only, Viewer role, both endpoints. For REDCap it generates coremodels_data_dictionary.csv — an upload-ready data dictionary built from the governed model, with taxonomies rendered as dropdowns (minted codes), NotNull rendered as required, and governed types rendered as validation types. typeNames restricts generation to specific instruments; empty means everything eligible. An agent can use this to answer "what would our governed model look like as a REDCap instrument?" and hand a reviewable CSV to the data manager — the artifact comes back as tool-result content, and nothing is written to REDCap or to the graph.
What the agent workflow looks like end to end
get_vendor_integration_status(no vendor) — learn what connectors and artifacts exist.get_vendor_integration_statuswithvendor: "redcap"— is anything governed yet?audit_vendor_projectwith the dictionary (inline or by URL) — get counts, findings, and the PHI inventory; gate onerrorCount.- Escalate drift findings to a human with the
markdownreport; propose fixes from the conformance findings. - Only with admin access and human intent:
import_vendor_projectto govern a new estate, orgenerate_vendor_artifactsto propose the round trip.
Every step except the explicit import is read-only, and the server enforces that — not the prompt. That's the property we care about most when the operator is an LLM: the safe subset isn't a convention, it's the API.
One boundary worth stating plainly: the drift-loop bookkeeping verbs — reaudit, the rolling history, and the SVG badge — are HTTP-surface features, not MCP tools. An agent that needs them can ask a human (or a script) to call those routes; over MCP it audits fresh artifacts, reads status, and generates. That keeps the MCP tool set small, typed, and easy for an agent to hold in its head.
For the artifact extraction recipe and the HTTP equivalents of each tool, see the REDCap quickstart in the CoreModels docs (docs/quickstarts/redcap).