Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Beschreibung vom Entwickler (englisches Original)
Verification layer for the agentic web: a signed answer about any site before an agent acts.
Diese drei werden nie zu einer Punktzahl zusammengefasst: Meinungen, Messungen und Beliebtheit sind verschiedene Dinge.
Für diesen Server haben wir noch keine Zusammenfassung in einfacher Sprache geschrieben. Unten stehen die Fakten, die wir aus der Registry gelesen haben.
Wähle die KI-App, die du nutzt, und kopiere die Einstellungen.
Du brauchst
Welche App nutzt du?
Wähle oben deine App. Wir merken sie uns, damit der Button beim nächsten Mal „In … installieren“ anzeigt.
Funktioniert in Claude im Web, auf dem Desktop und auf dem Handy:
https://crawlcheck.io/mcpFühre das in deinem Terminal aus
claude mcp add --transport http crawlcheck https://crawlcheck.io/mcpIn .cursor/mcp.json in deinem Projekt oder in ~/.cursor/mcp.json einfügen
{
"mcpServers": {
"crawlcheck": {
"url": "https://crawlcheck.io/mcp"
}
}
}Dein Browser fragt, ob er die App öffnen darf, dann zeigt die App die Einstellungen und bittet dich um Bestätigung. Schlüsselwerte bleiben leer, damit du sie selbst einträgst.
In .vscode/mcp.json in deinem Projekt einfügen
{
"servers": {
"crawlcheck": {
"type": "http",
"url": "https://crawlcheck.io/mcp"
}
}
}Dein Browser fragt, ob er die App öffnen darf, dann zeigt die App die Einstellungen und bittet dich um Bestätigung. Schlüsselwerte bleiben leer, damit du sie selbst einträgst.
ChatGPT verbindet sich nur mit Servern im Internet:
https://crawlcheck.io/mcpMenünamen können sich je nach Tarif und mit der Zeit leicht unterscheiden.
Deine Auswahl bleibt in einem Cookie auf diesem Gerät; kein Konto nötig.
Diese Einstellungen werden aus dem Registry-Eintrag des Entwicklers erzeugt. Wenn in der README etwas anderes steht, folge der README.
Die Tool-Liste dieses Servers haben wir noch nicht gelesen; wir prüfen die Endpunkte reihum.
Wir prüfen Informationen, die jeder sehen kann; den Code haben wir nicht gelesen. Checks, die nicht zutreffen, werden nicht mitgezählt. · Geprüft am 7. Nov. 2026
Der Registry-Name wurde mit dem GitHub-Konto emmanuelorta bestätigt, dem das Repo gehört
Dieses Repo haben wir noch nicht von GitHub gelesen
Dieses Repo haben wir noch nicht von GitHub gelesen
Noch nicht geprüft; wir prüfen die Endpunkte reihum
Noch nicht geprüft; wir prüfen die Endpunkte reihum
Noch nicht geprüft; wir lesen die Tool-Liste, wenn wir den Endpunkt prüfen
Verglichen mit allen aktiven Servern dieser Kategorie in der Registry. Sterne zählen nur, wenn dem Herausgeber das Repo gehört.
Er hat 1 von 1 zutreffenden Basischecks bestanden. Den Code haben wir nicht gelesen. Bevor du einen Schlüssel oder Token hinzufügst, sieh nach, welche Zugriffe der Server verlangt, und nutze einen Schlüssel, der nur die Berechtigungen hat, die du brauchst.
Die Registry nennt keinen erforderlichen Schlüssel, manche Server bitten dich aber bei der ersten Nutzung, dich anzumelden.
Er läuft in der Cloud des Entwicklers. Du verbindest dich übers Internet, ohne etwas zu installieren, aber was du sendest, läuft über die Server des Entwicklers.
Das GitHub-Repo wurde zuletzt – geändert, und die neueste Version (1.1.0) kam vor 21 Tagen in die Registry.
Apps, die MCP unterstützen, etwa Claude Desktop, Claude Code, Cursor und VS Code. Er verbindet sich per URL, also funktionieren auch Apps, die Remote-MCP-Server akzeptieren, zum Beispiel ChatGPT im Entwicklermodus.
In derselben Kategorie: Spec Driven Development, Remote Desktop Commander, TF Rooms
Server derselben Kategorie von anderen Entwicklern, sortiert nach Sternen.
So liest du eine Karte:★ GitHub-SterneiDrei Säulen: Bewertungen · Checks · NutzungiAktualisiert = neueste Version in der Registry veröffentlichti
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Live room availability, rates and stay quotes for 12 New Leaf motels in Twin Falls, Idaho.
Unverändert aus dem Repo des Entwicklers übernommen. PopNx MCP hat den Inhalt weder geprüft noch empfiehlt es ihn. HTML, Bilder und Skripte wurden entfernt. Links führen von dieser Website weg.
The dependency-free modules of CrawlCheck, the verification layer for the agentic web, extracted from the production service. These are the readers behind its signed answer about what a site permits and serves to AI crawlers and agents. No build step, no dependencies, ESM, Node 20+.
The hosted service fetches a site as 12 crawler identities (plus a browser and two control requests) and measures 47 sections across three stages — reach (can the crawler get in), read (what it actually receives), quote (can an answer engine lift it). This repository is the open core: the readers and checks that need no network, no store and no key, published so the measurements can be reproduced.
What is here today: the robots.txt policy reader, the crawler identifier / log-line forgery verifier, the quotable-content reader, the image-signal reader, and the markdown-negotiation and agent-surface probes. What stays in the service: the scoring — the thresholds each reading is judged against, the weight every section carries in the grade, and the corpus calibration those numbers were set from — plus fetching as those crawler identities, the record over time, monitoring, the dataset, and billing. The rule is simple: a reading of your page is a fact you are entitled to check, and the calibration is the product.
@crawlcheck/sdk (npm): the typed client for the CrawlCheck API and the zero-dependency offline verifier for signed answers, evidence bundles and receipts. npm test runs its suite against production.crawlcheck (PyPI): the same client and verifier for Python 3.9+, no dependencies.Both are published from the private service repository by a workflow that refuses to publish unless the directory here is byte-identical to what it ships, so this copy is the source the package pages point at, not a mirror that can drift.
npm install github:emmanuelorta/crawlcheck-core
Not on the npm registry yet, so install it from the repository. Every subpath below resolves from that install.
import { crawlerPolicy } from "crawlcheck-core/robots";
const policy = crawlerPolicy(robotsTxt, /* unreadable */ false, "/wp-admin/"); policy.agents.find(a => a.ua === "GPTBot"); // { ua:"GPTBot", label:"OpenAI training corpus", role:"train", // allowed:true, allowed_root:true, named:true, rules_shadowed:true } policy.shadowed; // [{ uas:["gptbot"], missing:["/wp-admin/","/feed/"], missing_count:2 }]
For each of 114 named agents (answer engines, search indexes, training crawlers, SEO tools, social unfurlers, regional engines) it reports: which user-agent group applies (named), whether the given path and the root are allowed under that group, and whether the group shadows the * rules.
A crawler obeys only its most specific group. The moment you write
User-agent: *
Disallow: /wp-admin/
User-agent: GPTBot Allow: /
GPTBot no longer sees Disallow: /wp-admin/ — the * group stops applying to it entirely. Sites that add an allowlist for AI agents routinely void every rule they thought still held. shadowedGroups() lists each named group and the * disallows it lost. This was found on our own sites first: how to block AI crawlers and the glossary entry for user-agent group.
| Export | What it does |
|---|---|
crawlerPolicy(txt, unreadable, path) | Full per-agent policy for one file. measured:false with a reason when the file is empty or unreadable — an absence is never reported as a policy |
parseGroups(txt) | RFC 9309 groups: consecutive User-agent lines share one group; Allow/Disallow rules in order |
groupFor(groups, ua) | The group that applies to an agent, per RFC 9309: the most specific matching token wins (version suffix ignored), every group naming that token is combined, a group for a more specific token (Googlebot-News) never applies to the general crawler, Google's documented fallbacks (Google-InspectionTool obeys Googlebot) apply, and * is the last resort |
pathAllowed(group, path) / rootAllowed(group) | RFC 9309 matching (* anywhere, trailing $ anchors the end); longest rule wins; Allow beats Disallow at equal length |
ruleMatches(rule, path) / decide(rules, path) | The matcher itself, and the decision with the rule that made it |
shadowedGroups(groups) | Named groups for which a * disallow is lost (not covered by one of the group's own rules, e.g. its own Disallow: /) |
AGENTS | The 114-agent table: [token, label, role] |
Crawl-delay, Sitemap and unknown fields are ignored, and percent-encoding is not normalised (rules and paths are compared as written). Path matching follows RFC 9309: * matches any run of characters and a trailing $ anchors the end, so Disallow: / + Allow: /$ opens the homepage and nothing else. Versions before 0.6.0 stripped * and ignored $; production changed on 2026-09-30, and 0.6.0 brings this module back to the service's reading. The tests check parity on real robots.txt files, including paths decided by * rules.
import { identifyBot, loadRanges, verifyLines } from "crawlcheck-core/agents";
identifyBot("Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)"); // "GPTBot"
const ranges = await loadRanges(fetch); // the operators' published IP feeds (cache this for a day) const r = verifyLines(accessLogText, ranges); r.tally; // { verified, spoofed, unverifiable, no_bot } r.forged_rate_pct; // spoofed / (verified + spoofed), or null when nothing is checkable r.rows[0]; // { line, bot, ip, verdict, why }
Three verdicts, never two. Verified: the address is inside a range the claimed operator publishes. Spoofed: it is outside every range that operator publishes. Unverifiable: the operator publishes no feed (Common Crawl, ByteDance, Meta) or the feed could not be read — and that is reported as unverifiable, not as forgery. The forged rate divides by verified + spoofed only; counting unverifiable hits as forged would inflate it and counting them as genuine would understate it.
| Export | What it does |
|---|---|
identifyBot(ua) | The named crawler token in a user-agent, longest match wins; null for browsers |
verifyLines(lines, ranges) | The verifier behind /api/tool/verify: string or array of log lines → tally, rate, per-line verdicts |
verifyBotIP(bot, ip, ranges) | true / false / null for one hit |
loadRanges(fetch) | Fetches the 10 operator feeds (OpenAI ×3, Anthropic, Perplexity ×2, Google ×2, Bing, Apple) into the shape the verifier reads. The only network call in the package; absent feeds make their operator unverifiable |
ipInCidr(ip, cidr), ip4ToInt, ip6ToBig | Range matching, IPv4 and IPv6 (including IPv4-mapped) |
BOT_TOKENS, BOT_FEED_OF, BOT_IP_FEEDS, CRAWLERS | The tables: tokens, token → feed family, feed URLs, and the 18-row operator/role/purpose table |
Why this exists: CrawlCheck's own telemetry once counted 78 of 85 "GPTBot" hits as forged — they were our own test requests. Reverse DNS is the older check the feeds replace; a user-agent is a self-assertion and proves nothing on its own.
import { quotable } from "crawlcheck-core/quotable";
const { signals } = quotable(html, "Acme Fencing LLC");
signals.lead_defines; // does the first sentence say what this IS signals.answer_units; // paragraphs of 15-70 words that carry a fact signals.quotable_share; // % of sentences an engine could attribute unedited signals.faq_questions; // declared in FAQPage markup signals.faq_visible; // ...and actually readable on the page
The question is not whether the copy is good. It is whether, when an answer engine wants to state a fact about this page, there is a sentence on it that can be lifted as it stands — or whether the engine has to assemble one, in which case the answer carries the engine's wording rather than yours.
This module publishes the reading, not the scoring. Every count and share the production service records for a page is produced here and is reproducible byte-for-byte against a live scan — that is what the parity test does, and it refuses to compare unless the page bytes still match the ones the fixture was captured from. What the service keeps is what those readings are judged against: the thresholds, the weight the section carries in the overall grade, and the multi-hundred-site corpus pass the numbers were calibrated from.
The distinction is not a marketing line, it is the one that keeps the product honest. Anyone can check that we read their page correctly; nobody has to take our word for a number. What they cannot lift is the calibration, which is the part that took a corpus to earn.
Two details that are easy to get wrong and are settled here. FAQ parity is checked against the whole visible page, not the stripped body — an FAQ accordion inside a is still text a reader can see. And counts come from body paragraphs and list items with navigation, header, footer and forms removed, because a nav menu is not prose and counting it inflates every ratio on the page.
| Export | What it does |
|---|---|
quotable(html, nameHint) | The production call site in one call: parses the JSON-LD graph and returns { signals } |
quoteSignals(html, nodes, nameHint) | The reader. nodes comes from ldGraphNodes(html); null when the input has no |
Scoring the reading — quoteRows, quoteBlock, the section weight and the score version — is in the service, not this package. Point the free scan at a URL to see the rows: https://crawlcheck.io/.
import { tgt, pctScore } from "crawlcheck-core/rows";
A row is { k, cur, opt, ok, why }: the check, what this page currently does, what it should do, the verdict, and why it matters. `ok: null` is the third state and it is load-bearing — it means *measured but not scored*. A signal too rare to judge on, one that does not apply to this kind of site, or one that is purely informational is shown to the reader and deliberately left out of the arithmetic. pctScore() divides by the scored rows only and returns null, never 0, for a section with none: an unmeasured section is not a failing one.
That rule is why a service-area business is not marked down for having no street address, and why a brand-new site with no field performance data is not reported as slow. Most audit tools have two states, and every gap in their own measurement becomes your zero.
import { agentSurfaces, grab } from "crawlcheck-core/surfaces";
const root = await grab("https://example.com/"); const out = await agentSurfaces("https://example.com", root);
out.found.markdown; // Accept: text/markdown got a text/markdown answer out.found.agents_md; // an authored /agents.md, not a 200 of HTML out.found.link_header; // read off the root response — no extra request out.evidence.markdown; // { content_type: "text/markdown; charset=utf-8" }
A scanner's Accept header is part of its identity, and getting it wrong makes the whole grade a measuremen
Nur der Anfang wird gezeigt; den Rest findest du im Repo