原型 · 预览版:收录官方注册中心里的全部服务器,每 30 分钟同步一次。评价和账户功能将在后续阶段推出。
PopNx MCP为使用 AI 的人准备的 MCP 服务器 · 用大白话讲清楚

CrawlCheck

作者:emmanuelorta版本 1.1.0i★ –i在云端运行
注册名称io.github.emmanuelorta/crawlcheck

安装

概览

作者提供的说明(英文原文)

Verification layer for the agentic web: a signed answer about any site before an agent acts.

PopNx MCP 的三大支柱

这三项永远不会合并成一个分数:意见、测量和人气是不同的东西。

它能帮你做什么

我们还没有为它写通俗的介绍。下面是我们从注册中心读取到的事实。

安装

选择你使用的 AI 应用,然后复制设置。

安装之前

你需要

你用的是哪个应用?

在上方选择你的应用。我们会记住它,下次按钮会显示“安装到 …”。

适用于网页版、桌面版和手机版 Claude:

  1. 打开 Settings → Connectors
  2. 点击 Add custom connector
  3. 粘贴下面的地址,然后点击 Add
  4. 如果要求登录,请登录作者的服务
SettingsConnectors1+ Add2https://…3
https://crawlcheck.io/mcp

在终端中运行这条命令

claude mcp add --transport http crawlcheck https://crawlcheck.io/mcp

在 Cursor 中打开

或者自己复制设置

粘贴到项目中的 .cursor/mcp.json,或 ~/.cursor/mcp.json

{
  "mcpServers": {
    "crawlcheck": {
      "url": "https://crawlcheck.io/mcp"
    }
  }
}

浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。

在 VS Code 中打开

或者自己复制设置

粘贴到项目中的 .vscode/mcp.json

{
  "servers": {
    "crawlcheck": {
      "type": "http",
      "url": "https://crawlcheck.io/mcp"
    }
  }
}

浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。

ChatGPT 只能连接互联网上的服务器:

  1. 打开网页版 ChatGPT → Settings → Connectors (Apps)
  2. 点击 Create 或 Add(部分套餐需要先在 Advanced 中开启 Developer mode)
  3. 粘贴下面的地址,起个名字,然后保存
  4. 如果要求登录,请登录作者的服务
SettingsConnectors1+ Create2https://…3
https://crawlcheck.io/mcp

菜单名称可能因套餐和版本不同而略有差异。

你的选择通过 Cookie 保存在这台设备上,无需账户。

这些设置是根据作者在注册中心的条目生成的。如果 README 的写法不同,请以 README 为准。

它能做什么

我们还没有读取这个服务器的工具列表;我们会轮流检查各个端点。

基础检查i

我们检查的是任何人都能看到的信息;我们没有阅读代码。不适用的检查项不计入总数。 · 检查于 2026年11月7日

  • ✓ 通过

    作者与仓库一致

    注册名称已通过 GitHub 账户 emmanuelorta 验证,该账户拥有此仓库

  • … 尚未检查

    仍在维护

    我们还没有从 GitHub 读取这个仓库

  • … 尚未检查

    有许可证

    我们还没有从 GitHub 读取这个仓库

  • … 尚未检查

    端点有响应

    尚未检查;我们会轮流检查各个端点

  • … 尚未检查

    使用 OAuth 登录

    尚未检查;我们会轮流检查各个端点

  • … 尚未检查

    工具描述中没有隐藏指令

    尚未检查;我们会在检查端点时读取工具列表

与“其他”中的其他服务器比较i

  • 星标数多于此分类中其他 32568 个服务器的 0%
  • 发布到注册中心的时间比此分类中其他 32568 个服务器的 64% 更新
  • 基础检查结果等于或优于此分类中其他 32568 个服务器的 100%

与注册中心里这个分类中所有活跃的服务器比较。只有当发布者拥有该仓库时,星标数才计入。

常见问题

CrawlCheck 安全吗?

它在 1 项适用的基础检查中通过了 1 项。我们没有阅读代码。在添加密钥或令牌之前,请先看看这个服务器要求哪些权限,并使用只具备所需权限的密钥。

它需要哪些密钥或代码?

注册中心没有列出必需的密钥,不过有些服务器会在首次使用时要求你登录。

它在我的电脑上运行还是在云端?

它在作者的云端运行。通过互联网连接,无需安装,但你发送的内容会经过作者的服务器。

它还在维护吗?

GitHub 仓库最后更新于–,最新版本(1.1.0)于21天前进入注册中心。

哪些应用可以使用它?

支持 MCP 的应用,例如 Claude Desktop、Claude Code、Cursor 和 VS Code。它通过 URL 连接,所以接受远程 MCP 服务器的应用也可以使用,例如开启开发者模式的 ChatGPT。

有什么可以替代它?

同一分类中有:Spec Driven Development, Remote Desktop Commander, FlyDocs

替代选择

同一分类中其他作者的服务器,按星标数排序。

如何看卡片:★ GitHub 星标i三大支柱:评价 · 检查 · 使用情况i更新 = 最新版本发布到注册中心的时间i

Spec Driven Development

作者:formulahendry

MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.

在你的电脑上运行★ 440MIT14个月前更新
安装

Remote Desktop Commander

作者:desktop-commander

Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.

在云端运行★ 211昨天更新
安装

FlyDocs

作者:flydocs.ai

Spec-driven development workflow: your agent works issues, sessions and the status lifecycle.

在你的电脑上运行今天更新
安装

作者的 README

打开 README

按原文从作者的仓库复制。PopNx MCP 没有审查或背书其内容。HTML、图片和脚本已被移除。链接会离开本站。

crawlcheck-core

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.

Also in this repository: the SDKs

  • `sdk/` — @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.
  • `sdk-python/` — 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.

Install

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.

robots — which crawlers your robots.txt actually admits

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.

The shadowing defect

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.

API
ExportWhat 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: /)
AGENTSThe 114-agent table: [token, label, role]
What it does not do

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.

agents — who fetched, and whether they are who they claim

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.

ExportWhat 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, ip6ToBigRange matching, IPv4 and IPv6 (including IPv4-mapped)
BOT_TOKENS, BOT_FEED_OF, BOT_IP_FEEDS, CRAWLERSThe 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.

quotable — what an answer engine can lift from the page

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.

ExportWhat 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/.

rows — the three-state row every reader returns

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.

surfaces — markdown negotiation, and the Accept header that made a site an F

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

只显示了开头部分;其余内容请在仓库中阅读

问 PopNx