关于 Edge Case Museum
Edge Case Museum 是面向开发者的边界输入案例集,可按代码场景查找会触发隐蔽问题的输入。它提供已执行验证的 Python 和 JavaScript 复现,并可生成针对自有函数的测试文件。
主要功能
- 01按开发场景查找边界案例
- 02查看复现代码、输出与原因
- 03提供修复建议及相关案例
- 04生成 pytest 或 node:test 文件
- 05覆盖 Unicode、日期、解析等类别
适用场景
- 01为 CSV 解析器寻找易漏边界输入
- 02检查金额和货币精度处理
- 03测试用户名的 Unicode 规范化
- 04生成用于验证函数的边界测试
MCP 相关
向 MCP 客户端提供案例搜索、单例详情、分类浏览和测试文件生成工具。可连接 Pipeworx 网关,也可作为本地 stdio MCP 服务运行。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://gateway.pipeworx.io/edge-case-museum/mcpclaude mcp add --transport http pipeworx-io-edge-case-museum https://gateway.pipeworx.io/edge-case-museum/mcp{"mcpServers":{"pipeworx-io-edge-case-museum":{"type":"http","url":"https://gateway.pipeworx.io/edge-case-museum/mcp"}}}在 Cursor 中打开{"servers":{"pipeworx-io-edge-case-museum":{"type":"http","url":"https://gateway.pipeworx.io/edge-case-museum/mcp"}}}在 VS Code 中打开{"mcpServers":{"pipeworx-io-edge-case-museum":{"type":"http","url":"https://gateway.pipeworx.io/edge-case-museum/mcp"}}}{"mcpServers":{"pipeworx-io-edge-case-museum":{"serverUrl":"https://gateway.pipeworx.io/edge-case-museum/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
45| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| q | string | 否 | question 的别名。 |
| ask | string | 否 | question 的别名。 |
| text | string | 否 | question 的别名。 |
| input | string | 否 | question 的别名。 |
| packs | array | 否 | 可选。将路由限制为这些包的 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(绝不会返回空答案)。 |
| query | string | 否 | question 的别名。 |
| prompt | string | 否 | question 的别名。 |
| message | string | 否 | question 的别名。 |
| question | string | 是 | 用自然语言表达的问题或请求。支持 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 个案例,每个案例至少包含一个已执行的复现:
| 类别 | 案例数 | 示例 |
|---|---|---|
| Unicode | 15 | NFC 与 NFD 用户名、土耳其语带点 I、ß 大小写折叠、西里尔字母形似字符、零宽字符、Zalgo 文本 |
| 日期和时间 | 18 | 夏令时缺口和重叠、尼泊尔的 +05:45、萨摩亚消失的一天、闰秒、2038 年问题、ISO 周年 |
| 浮点数和金额 | 17 | round(2.675, 2)、(1.005).toFixed(2)、银行家舍入、货币最小单位、-0 余额 |
| 排序和比较 | 14 | 排序规则与码点、瑞典语 å 排在 z 之后、[10, 9, 1].sort()、布尔比较器 |
| 文件名和路径 | 15 | CON.txt、末尾的点、包含绝对路径部分的 os.path.join、NTFS 流、255 字节文件名 |
| 解析 | 15 | CSV 引号和 BOM、JSON 重复键和 64 位 ID、WHATWG 反斜杠、有效邮箱被拒绝 |
| 整数 | 14 | MAX_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
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。