MCP-Server

DiffiCat

com.difficat/difficat
Entwicklertools Öffentlich und erreichbar MCP 2025-11-25

Was dieses MCP kann

Compares websites before and after migration for missing pages, content changes, screenshots, and visual regressions.

cancel_comparison
Cancel comparison
Stop a running job; the job reports cancelled within a minute, with the pages compared so far in its report. Free.
Destruktiv Idempotent
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['jobId'], 'properties': {'jobId': {'type': 'string', 'pattern': '^web-[a-z0-9-]+$', 'description': 'The jobId returned when the job was created, e.g. web-1a2b3c.'}, 'jobToken': {'type': 'string', 'maxLength': 200, 'minLength': 20, 'description': 'The jobToken returned when the job was created. Optional when the request carries the prepaid key that paid the job (Authorization: Bearer dck_…).'}}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'code': {'type': 'string'}, 'error': {'type': 'string'}, 'status': {'type': 'string', 'const': 'cancelling'}}, 'additionalProperties': False}
capture_screenshot
Capture screenshot
Full-page PNG of one URL. Returns the image (or, for a large one, links.file to fetch with the jobToken) plus a jobId/jobToken for get_screenshot. Paid in USDC (the 402 challenge names the network), or from a prepaid balance when the request carries Authorization: Bearer dck_…: 0.02 USD per call. Answers with jobId, jobToken, filename, url, dimensions, bytes and links.file.
Externer Zugriff
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['url'], 'properties': {'url': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Page to capture (full URL).'}, 'auth': {'type': 'object', 'required': ['username', 'password'], 'properties': {'password': {'type': 'string', 'maxLength': 512, 'description': 'Password for HTTP basic auth.'}, 'username': {'type': 'string', 'maxLength': 512, 'description': 'Username for HTTP basic auth.'}}, 'description': 'HTTP basic auth for the page.'}, 'viewportWidth': {'type': 'integer', 'maximum': 2560, 'minimum': 320, 'description': 'Capture width in px.'}}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'url': {'type': 'string'}, 'code': {'type': 'string'}, 'bytes': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991}, 'error': {'type': 'string'}, 'jobId': {'type': 'string'}, 'links': {'type': 'object', 'required': ['file'], 'properties': {'file': {'type': 'string'}}, 'additionalProperties': False}, 'payment': {'type': 'object', 'required': ['amount', 'currency', 'rail', 'balance'], 'properties': {'rail': {'type': 'string', 'const': 'prepaid'}, 'amount': {'type': 'string'}, 'balance': {'type': 'string'}, 'currency': {'type': 'string', 'const': 'USD'}}, 'additionalProperties': False}, 'filename': {'type': 'string'}, 'jobToken': {'type': 'string'}, 'dimensions': {'type': 'object', 'propertyNames': {'type': 'string'}, 'additionalProperties': {}}}, 'additionalProperties': False}
discover_pages
Discover pages
List the pages of Site A (sitemap, robots.txt, or crawl), mapped onto Site B when given. Paid in USDC (the 402 challenge names the network), or from a prepaid balance when the request carries Authorization: Bearer dck_…: 0.05 USD per call. Answers with pages (sourceUrl, targetUrl, path) and strategy.
Externer Zugriff
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['sourceUrl'], 'properties': {'maxPages': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': 1, 'description': 'Stop after this many pages.'}, 'sourceUrl': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Site A (full URL).'}, 'targetUrl': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Site B; pages are mapped onto it when given.'}, 'sitemapUrl': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Sitemap to read instead of the fallbacks.'}}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'code': {'type': 'string'}, 'error': {'type': 'string'}, 'pages': {'type': 'array', 'items': {'type': 'object', 'required': ['sourceUrl', 'path'], 'properties': {'path': {'type': 'string'}, 'sourceUrl': {'type': 'string'}, 'targetUrl': {'type': 'string'}}, 'additionalProperties': False}}, 'payment': {'type': 'object', 'required': ['amount', 'currency', 'rail', 'balance'], 'properties': {'rail': {'type': 'string', 'const': 'prepaid'}, 'amount': {'type': 'string'}, 'balance': {'type': 'string'}, 'currency': {'type': 'string', 'const': 'USD'}}, 'additionalProperties': False}, 'strategy': {'type': 'string'}}, 'additionalProperties': False}
get_balance
Get prepaid balance
The prepaid balance and the last 20 ledger entries of the key the request carries as Authorization: Bearer dck_… or X-DiffiCat-Key. Free.
Nur Lesen Idempotent
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'code': {'type': 'string'}, 'error': {'type': 'string'}, 'keyId': {'type': 'string'}, 'recent': {'type': 'array', 'items': {'type': 'object', 'required': ['at', 'type', 'amount'], 'properties': {'at': {'type': 'string'}, 'kind': {'type': 'string'}, 'type': {'type': 'string'}, 'jobId': {'type': 'string'}, 'amount': {'type': 'string'}}, 'additionalProperties': False}}, 'balance': {'type': 'string'}, 'currency': {'type': 'string', 'const': 'USD'}}, 'additionalProperties': False}
get_comparison
Get comparison status
Status and progress of a job and, once it is terminal, its summary: passed, failed and issuesBySeverity. To wait for the end, call wait_for_comparison instead. Free.
Nur Lesen Idempotent
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['jobId'], 'properties': {'jobId': {'type': 'string', 'pattern': '^web-[a-z0-9-]+$', 'description': 'The jobId returned when the job was created, e.g. web-1a2b3c.'}, 'jobToken': {'type': 'string', 'maxLength': 200, 'minLength': 20, 'description': 'The jobToken returned when the job was created. Optional when the request carries the prepaid key that paid the job (Authorization: Bearer dck_…).'}}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'code': {'type': 'string'}, 'error': {'type': 'string'}, 'jobId': {'type': 'string'}, 'status': {'type': 'string'}, 'summary': {'type': 'object', 'propertyNames': {'type': 'string'}, 'additionalProperties': {}}, 'progress': {'type': 'object', 'propertyNames': {'type': 'string'}, 'additionalProperties': {}}}, 'additionalProperties': False}
get_report
Get report
The finished report. Call it first with failedOnly: true: results, total and nextOffset then cover only the pages that failed, while summary still covers every page. Without it, a slice of every page's result (offset and limit, default 50 a call, at most 5000; nextOffset points at the next slice). The text block is the plain-text report over the slice; includeText: true also puts it in structuredContent.text. limit: 1 returns the summary with one result. Free.
Nur Lesen Idempotent
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['jobId'], 'properties': {'jobId': {'type': 'string', 'pattern': '^web-[a-z0-9-]+$', 'description': 'The jobId returned when the job was created, e.g. web-1a2b3c.'}, 'limit': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': 1, 'description': 'Page results to return (default 1000, at most 5000).'}, 'offset': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': 0, 'description': 'Index of the first page result to return (default 0).'}, 'jobToken': {'type': 'string', 'maxLength': 200, 'minLength': 20, 'description': 'The jobToken returned when the job was created. Optional when the request carries the prepaid key that paid the job (Authorization: Bearer dck_…).'}, 'failedOnly': {'type': 'boolean', 'description': 'Only pages whose status is fail: results, total, nextOffset and text then cover the failed pages alone, while summary still covers every page.'}, 'includeText': {'type': 'boolean', 'description': 'Also return the plain-text report over the slice as structuredContent.text; the text block carries it either way.'}}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'code': {'type': 'string'}, 'text': {'type': 'string'}, 'error': {'type': ['string', 'null']}, 'jobId': {'type': 'string'}, 'total': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991}, 'status': {'type': 'string'}, 'results': {'type': 'array', 'items': {'type': 'object', 'propertyNames': {'type': 'string'}, 'additionalProperties': {}}}, 'summary': {'type': 'object', 'propertyNames': {'type': 'string'}, 'additionalProperties': {}}, 'cancelled': {'type': 'boolean'}, 'nextOffset': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991}}, 'additionalProperties': False}
get_screenshot
Get screenshot
Fetch one screenshot PNG by filename. Call it when a get_report page result or a capture_screenshot result names a screenshot you want to see; a PNG over the inline cap comes back as links.file to fetch with the jobToken. Free.
Nur Lesen Idempotent
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['jobId', 'filename'], 'properties': {'jobId': {'type': 'string', 'pattern': '^web-[a-z0-9-]+$', 'description': 'The jobId returned when the job was created, e.g. web-1a2b3c.'}, 'filename': {'type': 'string', 'pattern': '^[a-zA-Z0-9_-]+\\.png$', 'description': 'A screenshot filename from the report.'}, 'jobToken': {'type': 'string', 'maxLength': 200, 'minLength': 20, 'description': 'The jobToken returned when the job was created. Optional when the request carries the prepaid key that paid the job (Authorization: Bearer dck_…).'}}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'url': {'type': 'string'}, 'code': {'type': 'string'}, 'bytes': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991}, 'error': {'type': 'string'}, 'jobId': {'type': 'string'}, 'links': {'type': 'object', 'required': ['file'], 'properties': {'file': {'type': 'string'}}, 'additionalProperties': False}, 'payment': {'type': 'object', 'required': ['amount', 'currency', 'rail', 'balance'], 'properties': {'rail': {'type': 'string', 'const': 'prepaid'}, 'amount': {'type': 'string'}, 'balance': {'type': 'string'}, 'currency': {'type': 'string', 'const': 'USD'}}, 'additionalProperties': False}, 'filename': {'type': 'string'}, 'jobToken': {'type': 'string'}, 'dimensions': {'type': 'object', 'propertyNames': {'type': 'string'}, 'additionalProperties': {}}}, 'additionalProperties': False}
recover_comparison
Recover a paid job
Returns the job or screenshot the payment credential in _meta paid for, with a new jobToken that replaces the old one. For a paid call whose result never arrived. Free.
Eingabeschema
{'type': 'object', 'properties': {}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'code': {'type': 'string'}, 'error': {'type': 'string'}, 'jobId': {'type': 'string'}, 'links': {'type': 'object', 'required': ['file'], 'properties': {'file': {'type': 'string'}}, 'additionalProperties': False}, 'status': {'type': 'string'}, 'filename': {'type': 'string'}, 'jobToken': {'type': 'string'}}, 'additionalProperties': False}
start_comparison
Start comparison
Compare Site A against Site B on page existence, content and visual regression. Charged upfront. Paid in USDC (the 402 challenge names the network), or from a prepaid balance when the request carries Authorization: Bearer dck_…: 0.02 USD per page for the first 1000 pages and 0.01 USD per page beyond. One single-page comparison per client address per day is free without a payment credential or prepaid key; sample report: https://difficat.com/agents/sample/report.json. dryRun: true answers the page count and exact amount without charging or starting a job. maxPriceUsd refuses a job priced above it before any challenge. A settled charge is final: cancelling, a failed job or partial results do not reduce it. Then wait_for_comparison holds until the job ends; its summary.issuesBySeverity is the verdict, and get_report with failedOnly: true lists the failed pages. Answers with jobId, jobToken, status and pagesCharged, plus sample on the free run.
Externer Zugriff
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'urls': {'type': 'array', 'items': {'type': 'object', 'required': ['source', 'target'], 'properties': {'source': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Page URL on Site A.'}, 'target': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': "The same page's URL on Site B."}}}, 'minItems': 1, 'description': 'Explicit page pairs to compare; skips discovery and is priced per pair. One pair is a single-page comparison and needs no sourceUrl.'}, 'dryRun': {'type': 'boolean', 'description': 'Quote only: runs every check and the pricing, then answers the page count and exact amount. Nothing is charged, the free sample is not used and no job starts; the same body without dryRun is priced from the retained result.'}, 'maxPages': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': 1, 'description': 'Optional ceiling on the pages compared and charged for. The job is priced on the pages it compares: the urls list, or the pages discovery finds, at most this many. There is no page limit.'}, 'sourceUrl': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Site A, the reference site (full URL). Required unless urls is given.'}, 'targetUrl': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Site B, the migrated site. Omit to capture screenshots of Site A only.'}, 'threshold': {'type': 'number', 'maximum': 1, 'minimum': 0, 'description': 'Visual diff tolerance as a fraction from 0 (exact) to 1: 0.05 means 5%. The web app takes a percentage; the API does not.'}, 'sitemapUrl': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Sitemap to discover pages from.'}, 'sourceAuth': {'type': 'object', 'required': ['username', 'password'], 'properties': {'password': {'type': 'string', 'maxLength': 512, 'description': 'Password for HTTP basic auth.'}, 'username': {'type': 'string', 'maxLength': 512, 'description': 'Username for HTTP basic auth.'}}, 'description': 'HTTP basic auth for Site A.'}, 'targetAuth': {'type': 'object', 'required': ['username', 'password'], 'properties': {'password': {'type': 'string', 'maxLength': 512, 'description': 'Password for HTTP basic auth.'}, 'username': {'type': 'string', 'maxLength': 512, 'description': 'Username for HTTP basic auth.'}}, 'description': 'HTTP basic auth for Site B.'}, 'callbackUrl': {'type': 'string', 'maxLength': 2048, 'minLength': 1, 'description': 'Optional https URL that receives one JSON POST when the job ends (jobId, status, summary, links; never the jobToken), a nudge to read the job. Public hosts only, no redirects followed, retried twice; delivery never affects the job.'}, 'maxPriceUsd': {'type': 'number', 'description': 'Optional spend cap in USD. A job priced above it is refused before any challenge, so an auto-paying client is never asked for more.', 'exclusiveMinimum': 0}, 'viewportWidth': {'type': 'integer', 'maximum': 2560, 'minimum': 320, 'description': 'Capture width in px.'}}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'code': {'type': 'string'}, 'error': {'type': 'string'}, 'jobId': {'type': 'string'}, 'amount': {'type': 'string'}, 'dryRun': {'type': 'boolean', 'const': True}, 'sample': {'type': 'boolean'}, 'status': {'type': 'string', 'const': 'running'}, 'payment': {'type': 'object', 'required': ['amount', 'currency', 'rail', 'balance'], 'properties': {'rail': {'type': 'string', 'const': 'prepaid'}, 'amount': {'type': 'string'}, 'balance': {'type': 'string'}, 'currency': {'type': 'string', 'const': 'USD'}}, 'additionalProperties': False}, 'currency': {'type': 'string', 'const': 'USD'}, 'jobToken': {'type': 'string'}, 'pagesPriced': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991}, 'pagesCharged': {'type': 'integer', 'maximum': 9007199254740991, 'minimum': -9007199254740991}}, 'additionalProperties': False}
wait_for_comparison
Wait for comparison
Waits until the job reaches a terminal status (completed, failed or cancelled) or timeoutSeconds pass (default 60, at most 300), then answers like get_comparison: status, progress and, once terminal, the summary with passed, failed and issuesBySeverity. A wait that runs out answers status "running"; call it again. Free.
Nur Lesen Idempotent
Eingabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['jobId'], 'properties': {'jobId': {'type': 'string', 'pattern': '^web-[a-z0-9-]+$', 'description': 'The jobId returned when the job was created, e.g. web-1a2b3c.'}, 'jobToken': {'type': 'string', 'maxLength': 200, 'minLength': 20, 'description': 'The jobToken returned when the job was created. Optional when the request carries the prepaid key that paid the job (Authorization: Bearer dck_…).'}, 'timeoutSeconds': {'type': 'integer', 'maximum': 300, 'minimum': 1, 'description': 'Seconds to wait for a terminal status before answering with the current one (default 60, at most 300).'}}}
Ausgabeschema
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'code': {'type': 'string'}, 'error': {'type': 'string'}, 'jobId': {'type': 'string'}, 'status': {'type': 'string'}, 'summary': {'type': 'object', 'propertyNames': {'type': 'string'}, 'additionalProperties': {}}, 'progress': {'type': 'object', 'propertyNames': {'type': 'string'}, 'additionalProperties': {}}}, 'additionalProperties': False}
Geändert
get_balance
2. October 2026 02:41
Geändert
get_screenshot
2. October 2026 02:41
Geändert
get_report
2. October 2026 02:41
Geändert
wait_for_comparison
2. October 2026 02:41
Geändert
cancel_comparison
2. October 2026 02:41
Geändert
get_comparison
2. October 2026 02:41
Geändert
recover_comparison
2. October 2026 02:41
Geändert
start_comparison
2. October 2026 02:41
Geändert
capture_screenshot
2. October 2026 02:41
Geändert
discover_pages
2. October 2026 02:41
Geändert
get_report
30. September 2026 02:40
Hinzugefügt
wait_for_comparison
30. September 2026 02:40
Geändert
get_comparison
30. September 2026 02:40
Geändert
start_comparison
30. September 2026 02:40
Geändert
capture_screenshot
30. September 2026 02:40
Geändert
discover_pages
30. September 2026 02:40
Hinzugefügt
get_balance
28. September 2026 02:40
Geändert
get_screenshot
28. September 2026 02:40
Geändert
get_report
28. September 2026 02:40
Geändert
cancel_comparison
28. September 2026 02:40
Geändert
get_comparison
28. September 2026 02:40
Hinzugefügt
recover_comparison
28. September 2026 02:40
Geändert
start_comparison
28. September 2026 02:40
Geändert
capture_screenshot
28. September 2026 02:40
Geändert
discover_pages
28. September 2026 02:40
Hinzugefügt
get_screenshot
26. September 2026 02:40
Hinzugefügt
get_report
26. September 2026 02:40
Hinzugefügt
cancel_comparison
26. September 2026 02:40
Hinzugefügt
get_comparison
26. September 2026 02:40
Hinzugefügt
start_comparison
26. September 2026 02:40