MCP server that reads C2PA Content Credentials: what an image declares about its own origin
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
An image can carry a signed Content Credential declaring how it was made.
This server reads it, checks the signature against the bytes, and hands both
back to your AI assistant, which cannot see either on its own.
An MCP server that reads the C2PA Content Credential embedded in an image and reports what the file declares about its own origin, plus whether that declaration still verifies against the bytes in front of you.
π Documentation: mcp.johannsenlum.com/is-it-ai Β· install guide Β· tool reference
π Try it without installing anything: ai.johannsenlum.com/is-it-ai runs the same checks in your browser, on your machine, with nothing uploaded.
It opens an image, looks for an embedded C2PA manifest (a Content Credential), and if one exists, reports two separate things: what the manifest claims about how the image was made, and whether the cryptographic signature over that manifest still matches the file's current bytes. It does not look at pixels and it does not guess. If there is no manifest, or the manifest exists but the signature is broken, it says so plainly instead of inventing an answer.
See docs/pass-fail.md for why "the signature verified" and "the claim is true" are two different questions, and why this server only ever answers the first one.
is-it-ai-mcp is published on PyPI. Run it with:
Install from source (contributors / unreleased main). Not part of the normal
install path above, only needed if you want the latest unreleased code instead of the
published PyPI release:
Or run from a local clone:
No account, API key, or environment variable is required. The server only reads local files you point it at.
~/.claude.jsonclaude_desktop_config.jsonmacOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Copy this JSON in via Settings β Developer β Edit Config:
check_image_provenanceGive it the path to one image file on disk. It returns:
verdict: one of the three states below (AI_DECLARED, NO_AI_DECLARED,
UNKNOWN).reason: the specific basis for that verdict, for example no-credential,
credential-invalid, ai-source-type, capture-source-type, or
credential-silent.what_this_does_not_mean: a plain-language caveat attached to every verdict, so
the result cannot be quietly upgraded into a stronger claim than the evidence
supports.signature: the raw validation_state, a verified boolean, and any
failure_codes the signature check produced.declared: what the manifest claims when one exists. signer, claim_generator,
and signed_at are free text pulled straight from the file, so each is guarded per
the Security section below before it reaches you. source_types (IPTC
digital-source-type URIs, drawn from a closed vocabulary) and watermark_declared (a
boolean) cannot carry attacker-authored text, so both are returned as-is and are
never fenced.A file that cannot be read (bad path, unsupported format) comes back as a distinct
error result rather than a fake UNKNOWN. It needs a real path on disk, not the image
bytes themselves. See Note on file paths.
scan_directoryGive it a folder. It walks the tree, runs every image it finds through the same check, and returns aggregate counts by verdict and by signer, plus a capped sample of the files that carried a credential, rather than a line per file. This is the tool that reproduces this project's own 401-image sweep (see below) against any directory you point it at.
| Verdict | Means | Reachable only when |
|---|---|---|
AI_DECLARED | The file's manifest asserts AI or algorithmic generation | A manifest is present, its signature verifies, and it carries an IPTC digital-source-type marking AI involvement |
NO_AI_DECLARED | The file's manifest asserts a real-world capture | A manifest is present, its signature verifies, and it carries an IPTC digital-source-type marking a capture (camera, film, print, minor edits) |
UNKNOWN | Nothing usable was established | Everything else, including no manifest, a broken signature, or a manifest that never recorded a source type |
UNKNOWN is the default and by far the most common answer. In a scan of 401 real
images, only 14 carried a Content Credential at all, and every one of those was from
OpenAI: about 96.5% had no credential whatsoever. Expect UNKNOWN on almost everything
you check. That is not a bug in this server, it is the current state of image
provenance in the wild.
UNKNOWN means "no usable record survived," never "no AI was involved."When you attach an image to a model, the image is decoded to pixels and re-encoded before the model ever sees it. Container metadata, including any C2PA manifest, never reaches the model: the model sees an RGB array, nothing more. Without a tool, it cannot read a manifest at all, and it will tend to guess whether an image is AI-generated from visual artefacts instead. Published benchmarks put that guess at roughly 18 to 31% accuracy, little better than chance. This server exists so the model reads the actual signed record on disk instead of pattern-matching on JPEG compression artefacts.
Every human-readable string returned by this server originated inside the file being inspected: signer name, claim-generator string, and any free-text reason or label. That text was written by whoever produced the file, not by you, and it lands in the same context window as your own instructions. A field labelled "signer" carries an air of verified authority, but the signature covers the asset's bytes, not the honesty of any string inside the manifest. Anyone can sign their own file with their own certificate and write anything they like in it.
Before any such string is returned, it is cleaned of control characters, length-capped, and wrapped in a fenced boundary that marks it explicitly as untrusted data rather than instructions, with a random nonce the file's author could not have pre-guessed. Structural values, the verdict itself, the validation state, and the IPTC source-type URIs are drawn from closed vocabularies this server controls and are never fenced, since they cannot carry attacker-authored text.
See src/is_it_ai_mcp/safety.py for the implementation
and the full threat model in its module docstring.
This tool takes a file path, not image bytes. In Claude Code, an image you paste into the conversation is written to disk first, so its path is reachable and this just works. In other clients, a pasted or attached image may exist only as inline data with no path on the filesystem the server can reach, in which case there is nothing for this tool to open. If a check comes back unable to find the file, save the image to disk first and point the tool at that path.
--extra dev matters: without it, pytest-asyncio (needed for asyncio_mode = "auto"
in pyproject.toml) is not installed, and pytest prints an "Unknown config option:
asyncio_mode" warning on every run.
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/is-it-ai-mcp)<a href="https://allmcps.com/mcp/is-it-ai-mcp"><img src="https://allmcps.com/api/badge/is-it-ai-mcp?style=directory" alt="Is It AI MCP on AllMCPs" /></a>