mcpField
E
Edge Case Museum

Edge Case Museum

远程服务
pipeworx.io开发工具02 周前更新

关于 Edge Case Museum

Edge Case Museum 是面向开发者的边界输入案例集,可按代码场景查找会触发隐蔽问题的输入。它提供已执行验证的 Python 和 JavaScript 复现,并可生成针对自有函数的测试文件。

主要功能

  1. 01按开发场景查找边界案例
  2. 02查看复现代码、输出与原因
  3. 03提供修复建议及相关案例
  4. 04生成 pytest 或 node:test 文件
  5. 05覆盖 Unicode、日期、解析等类别

适用场景

  1. 01为 CSV 解析器寻找易漏边界输入
  2. 02检查金额和货币精度处理
  3. 03测试用户名的 Unicode 规范化
  4. 04生成用于验证函数的边界测试

MCP 相关

向 MCP 客户端提供案例搜索、单例详情、分类浏览和测试文件生成工具。可连接 Pipeworx 网关,也可作为本地 stdio MCP 服务运行。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://gateway.pipeworx.io/edge-case-museum/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

45
参数类型必填说明
qstring否question 的别名。
askstring否question 的别名。
textstring否question 的别名。
inputstring否question 的别名。
packsarray否可选。将路由限制为这些包的 slug(例如 ["sec-form-d","sec-13f"]),路由器随后只会从这些包中的工具进行选择。省略则使用默认的完整目录路由。Slug 可从 list_packs / search_packs / https://pipeworx.io/directory 获取;未列出或未知的 slug 会被忽略,并在 _meta.pack_scope.ignored 中列出。如果没有任何 slug 能匹配问题,则会在整个目录中路由,并设置 _meta.pack_scope.full_catalog:true(绝不会返回空答案)。
querystring否question 的别名。
promptstring否question 的别名。
messagestring否question 的别名。
questionstring是用自然语言表达的问题或请求。支持 query、q、prompt、text、input、ask、message 作为别名。

详细介绍

edge-case-museum

你的代码能正常工作。除了遇上这些妙不可言的糟糕输入。

属于 Pipeworx —— 一个将 AI Agent 连接到 1808+ 个实时数据源的 MCP 网关。这是一个独立的非官方集成,与上游提供方无关联、未经其认可,也非由其发布。

由 Mojibake 提供,他们是 Pipeworx 的创建者。

告诉它你正在构建什么(“用户名唯一性”“解析 CSV 上传文件”“存储并汇总金额”“按用户所在时区安排提醒”),它就会给出那些悄悄破坏这类代码的输入:每种输入会破坏什么假设、确切字节、出了什么问题、原因是什么、更安全的写法,以及 Python 和 JavaScript 复现示例——示例输出均来自实际运行。然后,它会为你生成一个包含这些输入、针对你自己函数的测试文件。

三个案例

以下每个输出都由运行代码生成,使用的正是用于检查整个集合的同一套测试工具(Python 3.14.2,Node.js v22.22.2)。

1. 一个 NaN 就能让列表其余部分也无法排序

edge_case_get({ id: "nan-in-sort" })

nan = float("nan")
print(sorted([3, nan, 1]))
[3, nan, 1]
console.log([3, NaN, 1].sort((a, b) => a - b));
[ 3, NaN, 1 ]

这可不是“NaN 出现在了奇怪的位置”。3 和 1 的顺序也颠倒了。所有与 NaN 的比较结果都是 false,因此排序会把 NaN 视为与所有值相等。这会破坏传递性(3“等于”NaN,NaN“等于”1,所以 3“等于”1),算法便认定列表已经排好序。Python 对比较结果不一致的情况不作保证。ECMAScript 则规定排序顺序由实现决定。

2. Python 将 "01/01/68" 解析为 2068 年,而 Node.js 将其解析为 1968 年

edge_case_get({ id: "two-digit-year-century-pivot-mismatch" })

for s in ("01/01/49", "01/01/50", "01/01/68", "01/01/69"):
    print(s, "->", datetime.strptime(s, "%m/%d/%y").year)
01/01/49 -> 2049
01/01/50 -> 2050
01/01/68 -> 2068
01/01/69 -> 1969
for (const s of ['01/01/49', '01/01/50', '01/01/68', '01/01/69'])
  console.log(s, '->', new Date(s).getFullYear());
01/01/49 -> 2049
01/01/50 -> 1950
01/01/68 -> 1968
01/01/69 -> 1969

Python 遵循 69 这一 POSIX 分界点。V8 的分界点是 50。除了 50 到 68 这段范围内的两位数年份会相差一个世纪外,两者对所有两位数年份的解析都一致。随便测试几个日期,很可能永远碰不到这种情况。

3. Intl 表示伊拉克第纳尔没有小数位。ISO 4217 则规定它有三位。

edge_cases_find({ context: "store and add up money amounts", language: "javascript" })

for (const c of ["USD", "JPY", "BHD", "KWD", "CLF", "IQD", "HUF"]) {
  const digits = new Intl.NumberFormat("en-US", { style: "currency", currency: c })
    .resolvedOptions().maximumFractionDigits;
  console.log(c, digits);
}
USD 2
JPY 0
BHD 3
KWD 3
CLF 4
IQD 0
HUF 0

首先,amount * 100 对 JPY 来说是错误的(会多收 100 倍),对 BHD 也不对(会少收 10 倍)。另一个更隐蔽的问题是,看似显而易见的解决办法——询问 Intl 某种货币有多少位小数——返回的是 CLDR 显示数据,而非 ISO 4217 数据。ISO 4217 规定 IQD 有 3 位小数、HUF 有 2 位,而 Intl 对两者都报告为 0。应存储支付处理方使用的指数,不要从格式化工具推导。

然后它会编写测试

edge_cases_test_file({ context: "parse a CSV upload", language: "python" }) 会返回一个包含七个 CSV 案例、共八个测试用例的 pytest 文件。测试对象是我们大多数人最先会写的解析器:list(csv.reader(io.StringIO(text))):

PASSED test_edge_case[csv-formula-injection-excel]
PASSED test_edge_case[csv-crlf-trailing-blank-line0]
PASSED test_edge_case[csv-crlf-trailing-blank-line1]
PASSED test_edge_case[csv-quoted-field-with-newline]
PASSED test_edge_case[csv-doubled-quote-escaping]
PASSED test_edge_case[csv-quoted-field-with-comma]
FAILED test_edge_case[csv-utf8-bom-first-header]
FAILED test_edge_case[csv-semicolon-delimited-european-excel]
2 failed, 6 passed

有两个真实的缺陷:对于以 Excel 的“CSV UTF-8”格式保存的文件,读回来的第一个表头是 "name";而使用小数逗号区域设置导出的分号分隔文件会被解析成一列。每个失败都会指出解释该问题的案例。

内容

122 个案例,每个案例至少包含一个已执行的复现:

类别案例数示例
Unicode15NFC 与 NFD 用户名、土耳其语带点 I、ß 大小写折叠、西里尔字母形似字符、零宽字符、Zalgo 文本
日期和时间18夏令时缺口和重叠、尼泊尔的 +05:45、萨摩亚消失的一天、闰秒、2038 年问题、ISO 周年
浮点数和金额17round(2.675, 2)、(1.005).toFixed(2)、银行家舍入、货币最小单位、-0 余额
排序和比较14排序规则与码点、瑞典语 å 排在 z 之后、[10, 9, 1].sort()、布尔比较器
文件名和路径15CON.txt、末尾的点、包含绝对路径部分的 os.path.join、NTFS 流、255 字节文件名
解析15CSV 引号和 BOM、JSON 重复键和 64 位 ID、WHATWG 反斜杠、有效邮箱被拒绝
整数14MAX_SAFE_INTEGER + 1 === MAX_SAFE_INTEGER + 2、parseInt(null, 36)、-7 % 2
姓名和地址14姓氏中的姓名成分、单名、作为姓氏的 "Null"、带前导零的邮政编码

工具

  • edge_cases_find({ context, language?, limit? }) — 将你要实现的功能用通俗语言描述,即可找到相关案例。每个案例都附有适用于你所用语言的复现,以及用于进一步筛选的 refine_tags 列表。
  • edge_case_get({ id }) — 完整查看一个案例:每个复现及其捕获的输出和运行时版本、原因、修复方法、相关案例和来源。
  • edge_cases_browse({ category?, tag? }) — 按类别(unicode、datetime、float-money、sorting、filenames、parsing、integers、names-addresses)或标签(username、csv、money、timezone 等)浏览集合。
  • edge_cases_test_file({ context, language }) — 生成一个可运行的 pytest 或 node:test 文件,其中将相关输入整合为测试用例。文件生成后会针对桩代码运行;将标记为 TODO 的桩代码替换为你的函数,测试失败会告诉你该查看哪个案例。

安装

远程(无需设置)
{
  "mcpServers": {
    "edge-case-museum": {
      "url": "https://gateway.pipeworx.io/edge-case-museum/mcp"
    }
  }
}

此端点还提供共享的 Pipeworx 工具(ask_pipeworx、discover_tools 等)。

本地
{
  "mcpServers": {
    "edge-case-museum": {
      "command": "npx",
      "args": ["-y", "@pipeworx/mcp-edge-case-museum"]
    }
  }
}

整个集合都随软件包一并提供。无需网络调用,也无需账户。

身份验证

无需密钥。

值得信赖的原因

  • 没有任何输出是凭记忆填写的。 每个 Python 和 JavaScript 复现都由已提交的测试框架执行,其 expected_output 就是运行时打印的结果。verified_with 会注明运行时(例如 Python 3.14.2、Node.js v22.22.2),因为其中一些行为会随版本变化,你应该知道我们使用的版本。
  • 测试框架可能失败,而且确实失败过。 只要改动预期输出中的一个字符,测试就会因差异而失败。未重新运行就编辑代码或输出的复现,根本无法打包:打包过程会检查测试框架记录的哈希值。
  • 未实际运行的环境会明确标注。 Postgres、Windows 和 macOS 的文件系统行为会标记为 documented,并附上相关来源,绝不会标为已验证。
  • 每个案例都引用其规范或文档。 包括 Unicode 附录、RFC 章节、ECMAScript 规范、IEEE 754 参考资料、ISO 4217、IANA 时区数据库和语言文档。内容均由我们用自己的话撰写。

数据来源

  • 由 Mojibake 为本集合撰写的案例,每个案例都注明了所依据的标准或文档。
  • 部分输入来自 Max Woolf 编写的 Big List of Naughty Strings(MIT 许可证);使用了该列表内容的案例会在来源中注明。
  • 所有内容中均不含任何真实人物的姓名、地址或联系方式。姓名和地址案例使用虚构示例,并说明命名与地址系统的相关事实。

贡献一个展项

添加一个文件,src/exhibits/CATEGORY/ID.json(复制任意一个现有展项作为格式参考),其中包含你的复现用例的 code,但不包含 expected_output。运行 node src/harness.mjs --only ID --capture:该命令会执行 每个复现用例,将实际输出写入你的文件,并记录下来。查看捕获的内容;如果输出与你的说明不符, 说明就是错的。然后运行 node src/bake.mjs 并提交拉取 请求。尚未由测试框架运行过复现用例的展项 不会被构建。

快速开始

添加到你的 MCP 客户端(Claude Desktop、Cursor、Windsurf 等):

{
  "mcpServers": {
    "edge-case-museum": {
      "url": "https://gateway.pipeworx.io/edge-case-museum/mcp"
    }
  }
}
此端点实际提供的内容

https://gateway.pipeworx.io/edge-case-museum/mcp 上的 tools/list 会返回上表中的工具, 以及共享的 Pipeworx 元工具——ask_pipeworx、 discover_tools、search_within、remember/recall 和其余 网关全局工具集。因此,你看到的工具数量会多于这张表:单个工具包端点目前会列出约 30 个共享工具,以及该工具包自己的工具。连接的 initialize 响应会说明其确切范围,是 当天情况的权威答案。

这是有意为之,并非意外的多路复用。元工具让限定范围的连接也能回答此工具包无法涵盖的问题——通过 ask_pipeworx 路由到整个目录——无需添加第二个 MCP 服务。目前无法挂载不包含这些元工具的工具包端点;如果额外的架构定义带来的上下文开销超过路由的价值,请连接一次完整网关,而不是连接多个工具包端点。

或者连接完整的 Pipeworx 网关,直接列出每个工具包的工具, 而不只是当前工具包的工具:

{
  "mcpServers": {
    "pipeworx": {
      "url": "https://gateway.pipeworx.io/mcp"
    }
  }
}

两个 URL 都连接到同一个网关和相同的 1808+ 个数据源。唯一的区别是哪些工具包的工具会被直接列出;无论连接哪一个,ask_pipeworx 都能访问所有工具包。

没有 MCP 客户端?通过 HTTP 调用

curl -X POST https://gateway.pipeworx.io/v1/tools/edge_cases_find \
  -H 'Content-Type: application/json' \
  -d '{"context":"username uniqueness","language":"python"}'

首次调用无需账户。查看任意工具:GET https://gateway.pipeworx.io/v1/tools/edge_cases_find。查找工具:使用 {"query":"..."} 调用 POST https://gateway.pipeworx.io/v1/tools/search_packs。

独立运行(无需网关账户)

此软件包也可以作为本地 stdio MCP 服务运行——无需 Pipeworx 账户,也无需经过 网关往返:

{
  "mcpServers": {
    "edge-case-museum": {
      "command": "npx",
      "args": ["-y", "@pipeworx/mcp-edge-case-museum"]
    }
  }
}

或者直接运行,以确认服务能够启动:

npx -y @pipeworx/mcp-edge-case-museum

它通过 stdin/stdout 使用 MCP 通信,并通过 initialize/tools/list/tools/call 响应仅属于此工具包的工具——不包含上方网关连接所提供的共享元工具。代码相同,工具相同,但没有 ask_pipeworx 路由。

使用 ask_pipeworx

你也可以用通俗英语提问,而不是直接调用工具——这不仅适用于上方的工具包端点,也适用于完整网关:

ask_pipeworx({ question: "your question about Edge Case Museum data" })

网关会选择合适的工具并自动填入参数。

更多内容

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。