🏷️ 出售MCP服务器(Cloudflare Worker)
轻量级 模型上下文协议(MCP) 允许客户端检查域名是否作为 出售 使用标准化 _for-sale DNS TXT记录.
服务器完全运行在 Cloudflare Workers,使其在全球范围内可用,无服务器,并且可以大规模免费运行。
______________________________________________________________________
✨ 新增内容
- 内置的故障关闭验证器(服务器端):
现在每个解析器工具 总是 运行严格的验证器 _for-sale TXT记录并返回一个标准化的 验证器报告不需要客户端/系统提示;逻辑在Worker中强制执行。
- 确定性JSON模式:
验证器输出一个固定的JSON形状 valid, errors[], record_info, parsed,以及 explanations (按规则通过/失败)。它应用单字符串TXT、精确版本前缀、精确一个标签、解码策略、URI分配列表、IDNA和特定于标签的规则。
- IDNA(punycode)支持
furi主机:
验证器报告Unicode和punycode主机形式。
- 新工具:
- validate_for_sale_txt (低级:验证您已经解析的单个TXT RDATA) - resolve_and_validate_for_sale (一次:解决+验证)
所有现有工具(check_for_sale, check_for_sale_structured, natural_language_check)现在 返回验证结果 在解析器输出旁边。
______________________________________________________________________
✨ 特性
- 实施
_for-sale草案规范
解析 v=FORSALE1; TXT记录并提取结构化内容字段(furi, ftxt, fval, fcod).
- 严格的、失败关闭的验证
- 确切前缀: v=FORSALE1; - 正好有一个标签来自 {fcod, ftxt, furi, fval} - TXT RDATA必须是 单个字符串≤255个八位字节 (无连接) - 未知/附加标签(包括通过解码)→ 拒绝 - 解码策略: 最多一个 解码通过百分比 仅 为了 furi - furi 必须 绝对的 方案必须得到批准(https,可选 http, mailto, tel),解码后长度≤2048 - 中的主机名 furi:应用了IDNA,并报告了Unicode和punycode - fcod: ^[A-Z0-9_-]+$,≤32个字符 - ftxt:不透明,≤2048个字符,从未解码或链接 - fval: ^[A-Z]{3}[0-9]+(?:\.[0-9]{1,18})?$ → 被规范化为 "CUR amount" - 别名/通配符:跨区域启发式,包括注释 - 退货 只有JSON;值被污染,必须在下游进行HTML转义
- 公共MCP接口(SSE+流式HTTP)
适用于任何MCP客户端(Claude Desktop、Cursor、Windsurf、MCP Inspector)。
- 自然语言查询
提供诸如“example.nl是否出售?”之类的提示--域被提取、解析和 已验证 自动。
- 双解析器支持
- 违约: Cloudflare DoH JSON - 可选:自定义JSON解析器端点(resolver.j78workers.workers.dev)
- 在Cloudflare Workers上无服务器运行 --不需要后端。
______________________________________________________________________
🧠 背景
本项目实施了以下所述的操作惯例:
戴维斯,M.(2025) — *这_for-sale核心不足和全球范围的DNS节点名称* --IETF互联网草案:draft-davids-forsalereg-11
它使域名持有人能够通过DNS本身发出销售可用性信号,而无需第三方市场或WHOIS抓取。
______________________________________________________________________
🧰 暴露的工具
每个解析器工具现在都返回 两者 经典解析器数据和数组 验证器报告:
顶级(解析器)字段:
domain:查询到的可注册名称queried_name:_for-sale.method:"doh"或"resolver"is_for_sale:基本在场检查(任何v=FORSALE1;找到TXT)records:以开头的原始TXT字符串v=FORSALE1;all_txt:在节点下找到的所有TXT有效载荷structured:宽松提取摘要(预验证器)raw:完整的DNS/解析器负载validations:验证器输出数组(每个输出一个records[i])
1) 工具: check_for_sale
说明: 解决 _for-sale. 和 总是 验证任何发现 v=FORSALE1; 记录。 例子: {"domain": "example.nl", "method": "doh"}
2) 工具: check_for_sale_structured
说明: 与上述相同;返回相同的解析器数据+ validations (以及 structured 摘要)。 例子: {"domain": "example.nl"}
3) 工具: natural_language_check
说明: 接受自由文本提示,提取域,解析和 验证. 例子: {"prompt": "Is example.nl for sale?"}
4) 工具: resolve_and_validate_for_sale
说明: 一次性“解决+验证”便利端点。 例子: {"domain": "example.nl", "method": "doh"}
5) 工具: validate_for_sale_txt
说明: 低级验证器 单 您已经拥有的TXT RDATA(例如,来自您自己的解析器)。 输入形状示例:
{
"input": {
"query_fqdn": "_for-sale.example.org.",
"final_fqdn": "_for-sale.example.org.",
"alias_chain": [],
"is_wildcard": false,
"rdata_len_bytes": 96,
"txt": "v=FORSALE1;furi=https://broker.example/offer?id=123%2D456"
}
}______________________________________________________________________
✅ 验证器输出架构
验证器返回 仅 JSON格式如下:
{
"valid": true,
"errors": [],
"record_info": {
"query_fqdn": "string",
"final_fqdn": "string",
"cross_zone": false,
"is_wildcard": false,
"alias_chain": ["string"]
},
"parsed": {
"tag": "fcod|ftxt|furi|fval",
"value_raw": "string",
"value_norm": "string|null",
"extras": {
"uri": {
"scheme": "string|null",
"host_unicode": "string|null",
"host_punycode": "string|null",
"path": "string|null",
"query": "string|null"
},
"price": {
"currency": "string|null",
"amount_decimal": "string|null"
}
}
},
"explanations": {
"summary": "string",
"rule_evaluations": [
{
"rule": "string",
"status": "pass|fail|not_applicable",
"why": "string"
}
]
}
}示例A——有效 furi (https)
{
"valid": true,
"errors": [],
"record_info": {
"query_fqdn": "_for-sale.example.org.",
"final_fqdn": "_for-sale.example.org.",
"cross_zone": false,
"is_wildcard": false,
"alias_chain": []
},
"parsed": {
"tag": "furi",
"value_raw": "https://broker.example/offer?id=123%2D456",
"value_norm": "https://broker.example/offer?id=123-456",
"extras": {
"uri": {
"scheme": "https",
"host_unicode": "broker.example",
"host_punycode": "broker.example",
"path": "/offer",
"query": "id=123-456"
},
"price": { "currency": null, "amount_decimal": null }
}
},
"explanations": {
"summary": "Record is valid: correct version prefix, exactly one allowed tag, absolute https URI with single percent-decoding, and no aliasing concerns.",
"rule_evaluations": [
{"rule": "prefix v=FORSALE1;", "status": "pass", "why": "String begins with exact prefix."},
{"rule": "exactly one tag", "status": "pass", "why": "Only 'furi=' found after prefix."},
{"rule": "single-string ≤255 octets", "status": "pass", "why": "Length within limit; single character-string."},
{"rule": "URI scheme allowlist", "status": "pass", "why": "Scheme is https (allowlisted)."},
{"rule": "at most one percent-decoding (furi only)", "status": "pass", "why": "Decoded %2D to '-' once; no further decoding applied."},
{"rule": "absolute URL required", "status": "pass", "why": "URI includes scheme and authority."},
{"rule": "aliases/wildcards cross-zone check", "status": "pass", "why": "No cross-zone detected."}
]
}
}示例B——无效:不允许的方案
{
"valid": false,
"errors": ["furi scheme not allowed"],
"record_info": {
"query_fqdn": "_for-sale.example.org.",
"final_fqdn": "_for-sale.example.org.",
"cross_zone": false,
"is_wildcard": false,
"alias_chain": []
},
"parsed": null,
"explanations": {
"summary": "Invalid: the URI uses a non-allowlisted scheme which is explicitly rejected for security.",
"rule_evaluations": [
{"rule": "prefix v=FORSALE1;", "status": "pass", "why": "Prefix is present."},
{"rule": "URI scheme allowlist", "status": "fail", "why": "Scheme 'javascript' is excluded."}
]
}
}______________________________________________________________________
🧪 解析器输出示例(现在有验证)
{
"domain": "example.nl",
"queried_name": "_for-sale.example.nl",
"method": "doh",
"is_for_sale": true,
"records": [
"v=FORSALE1;furi=https://broker.example/offer?id=123%2D456"
],
"structured": {
"furi": ["https://broker.example/offer?id=123%2D456"]
},
"validations": [
{
"valid": true,
"errors": [],
"record_info": {
"query_fqdn": "_for-sale.example.nl.",
"final_fqdn": "_for-sale.example.nl.",
"cross_zone": false,
"is_wildcard": false,
"alias_chain": []
},
"parsed": {
"tag": "furi",
"value_raw": "https://broker.example/offer?id=123%2D456",
"value_norm": "https://broker.example/offer?id=123-456",
"extras": {
"uri": {
"scheme": "https",
"host_unicode": "broker.example",
"host_punycode": "broker.example",
"path": "/offer",
"query": "id=123-456"
},
"price": { "currency": null, "amount_decimal": null }
}
},
"explanations": { "summary": "Record is valid...", "rule_evaluations": [/* … */] }
}
]
}______________________________________________________________________
🚀 部署
1) 克隆并安装
git clone https://github.com//mcp-forsale-server.git
cd mcp-forsale-server
npm install
# If you forked: ensure dependency "punycode" is present (used by validator for IDNA)2) 在当地发展
npm start这将运行Worker http://127.0.0.1:8788.
MCP端点:
- 上海证券交易所
http://127.0.0.1:8788/sse - HTTP:
http://127.0.0.1:8788/mcp
使用MCP检查器进行本地测试:
npx @modelcontextprotocol/inspector
# → open http://localhost:5173, connect to http://127.0.0.1:8788/sse3) 部署到Cloudflare
npx wrangler deploy公共端点:
- 上海证券交易所
https://my-mcp-forsale.j78workers.workers.dev/sse - HTTP:
https://my-mcp-forsale.j78workers.workers.dev/mcp
🔍 测试公共端点
基本可用性:
curl -i https://my-mcp-forsale.j78workers.workers.dev/sse互动(推荐):
npx @modelcontextprotocol/inspector
# connect → https://my-mcp-forsale.j78workers.workers.dev/sseCLI(轻量级适配器):
npx mcp-remote https://my-mcp-forsale.j78workers.workers.dev/sseREPL内部:
/tools
/call check_for_sale_structured {"domain":"example.nl"}______________________________________________________________________
⚙️ 配置
*(这些可以添加到 wrangler.toml 或工人秘密(如果需要)。)*
1) 环境: FORSALE_QUERY_METHOD
- 目的: 首选解析器:
"doh"或"resolver" - 违约:
"doh"
2) 环境: CORS_ALLOWED_ORIGINS
- 目的: 浏览器MCP客户端允许的来源的可选列表
- 违约:
*
______________________________________________________________________
🧩 MCP客户备注
- 你 不能 将系统提示从MCP服务器推送到客户端的LLM中。
此Worker强制验证 服务器端 并返回确定性JSON,因此客户端不需要信任提示。
Claude桌面示例
创建或编辑 ~/.config/Claude/claude_desktop_config.json (macOS/Linux)或 %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"forSaleChecker": {
"command": "npx",
"args": ["mcp-remote", "https://my-mcp-forsale.j78workers.workers.dev/sse"]
}
}
}重新启动克劳德桌面。您将看到工具: check_for_sale, check_for_sale_structured, natural_language_check, resolve_and_validate_for_sale, validate_for_sale_txt.
如果您以后使用令牌或Cloudflare Access保护您的Worker,请在代理中添加相应的标头,或使用客户端的本地远程MCP配置来提供 Authorization.
______________________________________________________________________
🛡️ 安全/隐私
- 不存储用户数据。
- 所有DNS查询都是通过卫生部或您配置的解析器公开的。
- Worker可以由Cloudflare Access代理或要求
Authorization: Bearer.
______________________________________________________________________
🧑💻 作者
杰西 --奈梅亨,荷兰
______________________________________________________________________
📄 许可证
麻省理工学院许可证©2025 Jesse
本项目建立在IETF互联网公共草案中描述的概念之上 draft-davids-forsalereg-11.
______________________________________________________________________
实时实例示例
https://my-mcp-forsale.j78workers.workers.dev/sse
*可从任何兼容的MCP客户端访问。祝你黑客行为愉快,愿你的域名迅速销售! 🪩*
