# Confluent — MCP: Ask Your Agent Whether the Kafka Schemas Drifted: Confluent Governance over MCP

"Did anything in the registry drift from what we agreed?" is a question a platform engineer answers with three terminal commands and a diff. It is also, increasingly, a question they type into a chat window - and the agent on the other end needs real tools, not guesses. CoreModels ships its Confluent Schema Registry governance as a set of MCP tools, so any MCP-capable agent - Claude, Claude Code, or anything speaking streamable HTTP - can run the same import, audit, generate, and status verbs the HTTP API exposes, with the same role enforcement and the same read-only guarantees.

# Ask Your Agent Whether the Kafka Schemas Drifted: Confluent Governance over MCP

"Did anything in the registry drift from what we agreed?" is a question a platform engineer answers with three terminal commands and a diff. It is also, increasingly, a question they type into a chat window - and the agent on the other end needs real tools, not guesses. CoreModels ships its Confluent Schema Registry governance as a set of MCP tools, so any MCP-capable agent - Claude, Claude Code, or anything speaking streamable HTTP - can run the same import, audit, generate, and status verbs the HTTP API exposes, with the same role enforcement and the same read-only guarantees.

This article drives the whole loop from an agent's seat: connect, discover, audit with inline artifacts, handle a registry too big to inline, import, and generate schemas back out.

## Connecting

The public MCP endpoint is `/mcp`, secured with OAuth 2.0 - dynamic client registration and PKCE, so there is no client id to pre-provision. Read-only tools live there. Write tools (including vendor import) are served only on the admin endpoint, `/mcp-admin`. In Claude Code:

```bash
claude mcp add --transport http coremodels https://coremodels.example.com/mcp
```

then complete the OAuth flow when prompted. For write access, add the admin endpoint the same way:

```bash
claude mcp add --transport http coremodels-admin https://coremodels.example.com/mcp-admin
```

In claude.ai or Claude Desktop it is Settings → Connectors → add a custom connector with the same URL. Either way, the enforced authorization boundary is the per-project role check: import requires Admin membership on the target project no matter which endpoint minted the token.

## Step 1 - Discover what's connected

`get_vendor_integration_status` is the orientation tool. Called with only a project id, it lists every registered connector with capabilities and expected artifacts. Called with a vendor, it returns that vendor's last-import state in the project:

```json
{ "graphProjectId": "0a1b2c3d4e5f60718293a4b5c6d7e8f9", "vendor": "confluent" }
```

The result says whether an import exists (`imported`), the recorded state (timestamps, artifact versions, fingerprint, counts - including how many subjects were Protobuf), and how many imported subjects currently resolve to governed Types. An agent that starts here never has to guess whether the estate is governed yet.

## Step 2 - Audit with inline artifacts

The audit tool, `audit_vendor_project`, is Viewer-role and read-only, so it is available on the public endpoint. The agent passes the registry export - the JSON array of `GET /subjects/{subject}/versions/latest` responses - as a string in the `artifacts` map:

```json
{ "graphProjectId": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
  "vendor": "confluent",
  "artifacts": { "subjects": "<contents of subjects.json>" } }
```

Back comes the full audit report: `errorCount`, `warningCount`, `infoCount`, structured findings with section, severity, code, subject, message, and detail, plus the same `markdown` report the HTTP surface returns. The semantics are identical to the CI gate: `errorCount > 0` means the estate violates governed meaning. An agent asked "is the registry clean?" has a precise, honest answer to relay - and because findings carry stable kebab-case codes (`field-type-drift`, `enum-narrowed`, `fields-no-doc`, `protobuf-unparsed`), it can group, filter, and explain them rather than paraphrase.

Who produces `subjects.json`? A human, a script, or the agent itself if it has shell access - the export is one credential-free loop against the registry's REST API, documented in the quickstart. The MCP server never talks to your registry; it only ever sees the file.

## Step 3 - The `artifactUrls` flow for large registries

MCP clients cannot always inline a multi-megabyte payload into a tool call. For that, every artifact-bearing integration tool accepts `artifactUrls` alongside (or instead of) `artifacts` - a name-to-URL map the server fetches for you. The same `audit_vendor_project` call becomes:

```json
{ "graphProjectId": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
  "vendor": "confluent",
  "artifactUrls": { "subjects": "https://artifacts.example.net/exports/subjects.json" } }
```

Stage the export wherever your pipeline already puts build outputs - an artifact store, a release asset - and pass the link. These are server-side fetches of caller-supplied URLs, so they are deliberately locked down: https only, redirects disabled, hosts resolving to loopback, link-local, or private ranges refused, and a hard response-size cap. Anything the server refuses or fails to fetch is itemized in a `fetchProblems` list in the tool result instead of vanishing - if no artifact was usable at all, the call errors rather than auditing nothing.

## Step 4 - Import, on the admin endpoint

Import is the one write in the set, and it is additive: datasets become Types, fields become Elements with Avro's own optionality, enums become Taxonomies, cross-subject record references become governed references, and vendor metadata rides alongside - but already-governed nodes are never mutated. The `import_vendor_project` tool requires Admin role and is served only on `/mcp-admin`:

```json
{ "graphProjectId": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
  "vendor": "confluent",
  "artifacts": { "subjects": "<subjects.json>" } }
```

The result mirrors the HTTP import: `datasetsAdded`, `datasetsSkippedExisting`, `fieldsAdded`, `nodesEnriched`, plus lossiness and errors. An agent on the public endpoint simply does not see this tool - a clean failure mode for governance: the read-only endpoint cannot be talked into writing.

## Step 5 - Generate schemas back out

`generate_vendor_artifacts` is Viewer-role and read-only (it writes nothing to the project - it returns files):

```json
{ "graphProjectId": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
  "vendor": "confluent",
  "typeNames": ["Order", "Customer"] }
```

For Confluent the output is one registry-ready `schemas/{Record}.avsc` per governed Type: required fields as bare Avro types, optional fields as `["null", T]` with `default: null`, taxonomies as sanitized Avro enums, DateTime as `timestamp-millis`. Omit `typeNames` to generate everything eligible. The practical agent workflow writes these files into a branch of the repo where schemas are authored and opens a pull request - governance proposes, humans merge.

## The rest of the toolbox

The integration tools do not live alone on the endpoint. The same MCP server exposes the general CoreModels read tools - `list_projects` to find the governing project in the first place, `get_project_summary` for the labels and ids of the Types, Elements, and Taxonomies the import created, and `search_nodes` to drill into any of them. A useful agent pattern chains these after an audit: a `field-type-drift` finding names its subject, the agent looks up the governed Element behind it, and the explanation it hands back cites the governed type, the taxonomy terms, and the description - the actual agreed meaning, not a guess reconstructed from the schema text. All artifact-bearing calls also accept an optional `spaces` array when the governed estate lives in specific spaces of the project rather than its main space.

## Why this shape works for agents

Three properties make these tools safe to hand to an autonomous caller. First, **the read/write split is structural**: audit, generate, and status are Viewer-role and available publicly; import is Admin-role on a separate endpoint. Second, **every answer is grounded**: findings carry codes and subjects an agent can quote verbatim, and the counts it reports are the same numbers a CI gate would enforce - no gap between what the agent says and what the pipeline does. Third, **honesty is in-band**: lossiness records, `fetchProblems`, and coverage findings like `protobuf-unparsed` mean the agent can tell you what is *not* governed with the same confidence it reports what is.

The result is a governance loop you can drive conversationally without weakening it: the agent audits on demand, explains drift by code, imports only when an Admin says so, and hands back schemas the registry will accept. For the export recipe and the HTTP equivalents of every call above, see the Confluent Schema Registry quickstart in the CoreModels docs.
