20 道麦门情境题,测出你在麦当劳里是哪一种人格;再把这份人格档案交给 WorkBuddy + 麦当劳 MCP, 用你附近门店的实时菜单生成一份能真正下单的「今日人格套餐」。
参赛作品 · 麦当劳程序员创意开发大赛(M-CODE)· 基于麦当劳 MCP 构建的 Agent Skill 非官方产品,与麦当劳及其关联公司不存在商业合作、授权或隶属关系。
不想装环境?点开就能玩(无需 Token、无需登录):
https://tuffy666.github.io/Mcdonalds-mbti/
首次部署需要在仓库 Settings → Pages → Source 选择 GitHub Actions,
之后每次推送到 main 都会由 .github/workflows/deploy-pages.yml 自动构建发布。
三条玩法路线,按门槛从低到高:
| 玩法 | 需要什么 | 怎么做 |
|---|---|---|
| ① 玩 H5 | 一个浏览器 | 打开上面的链接(或本地 npm run dev)→ 答题 → 看结果 / 图鉴 / 导出结果卡 |
| ② 命令行算人格 | Node.js ≥ 18 | node scripts/score.mjs --answers "D,C,D,..." 直接出人格档案与套餐方案 |
| ③ 真实下单链路 | WorkBuddy + 麦当劳 MCP Token | 把结果页「复制人格档案」的内容粘贴给 Agent,见 使用示例 4 |
只玩 ① 和 ② 完全不需要任何 Token,也不联网调用任何 AI 接口 —— 计分与选品都是本地确定性引擎。
人格测试类内容有一个共同的断点:测完就结束。用户笑一句“还挺准”,然后关掉页面,什么都没发生。
本项目把这条链路补完了:
20 道麦门情境题
↓
四维计分 → 16 种主人格之一(+ 最多 1 个隐藏人格彩蛋)
↓
生成结构化「麦门人格档案」(PersonalityProfile)
↓
WorkBuddy + 麦当劳 MCP:实时门店 → 实时菜单 → 先算无券价 → 授权后领券算到手价 → 确认后下单
↓
一份「今日人格套餐」吃到嘴里
两个可独立使用的部分:
| 部分 | 是什么 | 需要 MCP Token 吗 |
|---|---|---|
| H5 小游戏 | React + TypeScript + Vite 的纯前端测试,无后端、无登录、无 AI 接口 | 不需要,完全离线可玩 |
| Agent Skill | SKILL.md + 确定性选品引擎,把人格档案翻译成可下单的菜单 |
需要(麦当劳 MCP) |
- 喜欢 MBTI / 人格测试 / 谐音梗的轻社交用户 —— 想测完能截图、能发群、能对号入座。
- 到了麦当劳但不知道吃什么的打工人和学生 —— 想直接拿到一份“有理由的”点单方案,而不是再刷十分钟菜单。
- 使用 WorkBuddy / Cursor 等 MCP 客户端的开发者 —— 想看一个“内容型 Skill 如何接上真实业务能力”的完整参考实现。
- 一起点餐的小团队 —— 多人场景下有分享装、套餐组合与取餐分工的明确建议。
主要使用手机浏览器访问(设计基准 390 × 844),兼容桌面端。
| 页面 | 路由 | 干什么 |
|---|---|---|
| 首页 | / |
介绍、开始测试、继续上次测试、进入图鉴 |
| 答题页 | /quiz |
4 个大选项、自动进下一题、可返回修改、刷新可恢复 |
| 计算页 | /calculating |
1.5~2 秒结果动画(4 段文案) |
| 结果页 | /result |
主人格、四维、隐藏人格、分享金句、结果卡导出、人格档案复制 |
| 人格图鉴 | /gallery |
16 型人格总览,按 NT / NF / SJ / SP 分组 |
| 人格详情 | /gallery/:type |
单个人格完整文案与最佳饭搭子互链 |
| 测试说明 | /about |
计分说明、数据说明、完整免责声明、版本信息 |
| 开发调试器 | /debug |
仅开发环境,强制预览 16+8 种结果、导出 JSON、模拟同分 |
环境要求:Node.js ≥ 18(本项目在 Node 22.22.2 上验证通过)。
git clone <你的仓库地址>
cd maimen-personality-mcp
npm install # 安装依赖
npm run dev # 启动开发服务器,默认 http://localhost:5173其他命令:
npm test # 运行计分引擎单元测试(12 项)
npm run validate # 校验人格配置(题量/选项数/分值/产品唯一性/文案完整性…)
npm run e2e # 无头 Chrome 端到端冒烟测试(需先 npm run build && npm run preview)
npm run build # 类型检查 + 生产构建,产物在 dist/
npm run preview # 本地预览生产构建
node scripts/generate-assets.mjs # 重新生成 16 张原创占位插画如果
npm install之后vite报找不到@esbuild/win32-x64或@rollup/rollup-win32-x64-msvc, 那是 npm 对 optionalDependencies 的已知问题,执行下面一行即可:npm install @esbuild/win32-x64 @rollup/rollup-win32-x64-msvc --save-optional
npm install && npm run dev打开 http://localhost:5173 → 开始测试 → 20 题 → 结果页。
结果页可以:保存 1080 × 1440 结果卡 PNG、复制分享文案、复制彩蛋文案、查看图鉴、重新测试。
# 20 个选项,A/B/C/D(也支持 0/1/2/3 或紧凑串 0123...)
node scripts/score.mjs --answers "D,C,D,C,D,D,D,D,A,A,A,B,B,B,B,B,B,B,B,C"
# 也可以直接读答案文件(含每题作答时长,会参与隐藏人格判定)
node scripts/score.mjs --answers-file examples/answers-sample.json --out profile.json输出(节选):
{
"summary": {
"mbti": "INTJ",
"product": "双层吉士汉堡",
"title": "低调加码型",
"compatibility": 93,
"hidden": "芝士分子(彩蛋稀有度 0.08%)",
"dimensions": {
"EI": "E 0% / I 100% → I",
"SN": "S 23% / N 77% → N",
"TF": "T 100% / F 0% → T",
"JP": "J 92% / P 8% → J"
}
},
"shareText": "测完发现我是「双层吉士汉堡型 INTJ」:低调加码型。..."
}node scripts/plan-meal.mjs --profile profile.json --menu examples/menu-sample.json \
--store "示例门店(非真实门店)" --mode 堂食输出:
【今日人格套餐方案】INTJ 双层吉士汉堡型 · 低调加码型的今日人格套餐
门店:示例门店(非真实门店)|就餐方式:堂食
建议单品:
1. 双层吉士汉堡(¥22) —— 本命单品:双层吉士汉堡(INTJ 低调加码型)
2. 巨无霸四件套(¥39.5) —— 计划派 92%:优先可直接下单的套餐组合,减少现场决策
3. 香芋派(¥8) —— 尝鲜派 77%:限时/新品优先并入
无券合计:¥69.5
应当避免:超大分享装、临时加购导致返工、明显溢价的单品
彩蛋动作(芝士分子):输出价格与营养对照,并标注数据来源 Tool。
...
-
到 https://open.mcd.cn/mcp 用手机号申请 MCP Token。
-
WorkBuddy → 左侧【专家·技能·连接器】→【连接器】→ 右上角【自定义连接器】→【配置 MCP】, 填入仓库根目录
mcp-config.example.json的内容, 把${MCD_MCP_TOKEN}替换成你自己的 Token:{ "mcpServers": { "mcd-mcp": { "type": "streamablehttp", "url": "https://mcp.mcd.cn", "headers": { "Authorization": "Bearer ${MCD_MCP_TOKEN}" } } } }保存后回到【自定义连接器】把
mcd-mcp启用。 -
H5 测完 → 结果页点「复制人格档案 · 生成今日人格套餐」→ 粘贴到对话框。
-
Agent 按
SKILL.md执行:查时间 → 确认门店 → 拉实时菜单 → 先给无券方案 → 问你要不要查券 → 你同意后算到手价 → 确认后下单。
⚠️ 本仓库不包含任何真实 Token。所有配置一律使用YOUR_MCP_TOKEN占位符,.gitignore已排除.env、mcp.json、*.token。
maimen-personality-mcp/
├── README.md 本文件
├── CONTEST_DECLARATION.md 大赛官方参赛声明(原文,未做任何修改)
├── MCP_INTEGRATION.md MCP Server / Tool / 调用流程 / 业务价值
├── mcp-config.example.json 脱敏 MCP 配置示例(仅环境变量占位符,无真实凭证)
├── SKILL.md Agent Skill 主体(触发条件、执行流程、硬性边界)
├── workbuddy.md WorkBuddy 开发对话上下文
│
├── engine/ ★ 唯一事实来源:H5 与 CLI 共用(纯 ESM,无依赖)
│ ├── questions.mjs 20 道题、权重、行为标签、隐藏信号
│ ├── personalities.mjs 16 种主人格完整配置与文案
│ ├── hidden.mjs 8 种隐藏人格 + 反差解释 + 冲突优先级
│ ├── scoring.mjs 计分、四维、同分决胜、契合度、隐藏人格检测
│ ├── profile.mjs 人格档案(Agent 契约)与剪贴板载荷
│ ├── meal-plan.mjs 人格 → 选品的确定性策略引擎
│ ├── validate.mjs 配置校验(12 条)
│ └── versions.mjs 三套版本号 + 存储键名
│
├── scripts/
│ ├── score.mjs 答案 → 人格档案 CLI
│ ├── plan-meal.mjs 档案 + 菜单 → 套餐方案 CLI
│ ├── validate-config.mjs 配置校验 CLI
│ └── generate-assets.mjs 生成 17 张原创 SVG 插画
│
├── .github/workflows/
│ ├── ci.yml 推送即校验(校验 / 单测 / 构建 / 冒烟)
│ └── deploy-pages.yml 自动发布在线试玩版到 GitHub Pages
│
├── tests/engine.test.mjs 12 项单元测试
├── examples/ 离线可跑通的示例答案与菜单
├── public/assets/ 原创 SVG(16 张人格插画 + 主视觉 + favicon)
│ └── products/ 16 张麦当劳官方产品实拍图(取自 MCP query-meals,见下方合规说明)
│
└── src/ React 18 + TypeScript + Vite 前端
├── App.tsx 路由表(调试器条件注册)
├── pages/ Home / Quiz / Calculating / Result / Gallery / About / Debug
├── components/common.tsx 插画、进度条、四维条、免责声明弹层、Toast、Page 外壳
├── store/quizStore.ts Zustand + localStorage(进度 / 最新结果 / 历史 10 条)
├── lib/ 存储封装、图片导出、资源路径
└── styles/global.css 设计令牌与全部样式
四组维度(前台使用麦门语言):
| 维度 | 左侧 | 右侧 | 用户可见名称 |
|---|---|---|---|
| 社交能量 | E | I | 热闹派 / 独享派 |
| 选择方式 | S | N | 经典派 / 尝鲜派 |
| 决策依据 | T | F | 理性派 / 感受派 |
| 行动节奏 | J | P | 计划派 / 随心派 |
计分:强倾向 +3 / 中倾向 +2 / 弱倾向或辅助 +1;每组取分高的一侧组成四字母人格。 百分比取整后强制保证两侧之和为 100%。
同分决胜(三层,全程无随机数):
该维度核心题的 +3 答案数量 → 更靠近题末的相关答案 → 稳定哈希(输入 answerSequence + scoringVersion)。
因此同一套答案重复计算必然得到同一结果。
麦门契合度:round(clamp(74 + 平均倾向强度 × 22, 74, 96))。
它是娱乐化展示,不是准确率,不代表测量精度。
16 种主人格(产品不重复):巨无霸 ENTJ / 麦辣鸡腿汉堡 ENTP / 双层吉士汉堡 INTJ / 麦乐鸡 INTP / 板烧鸡腿堡 ENFJ / 奥利奥麦旋风 ENFP / 麦香鱼 INFJ / 香芋派 INFP / 那么大鸡排 ESTJ / 薯饼 ESFJ / 吉士汉堡 ISTJ / 麦香鸡 ISFJ / 麦辣鸡翅 ESTP / 薯条 ESFP / 麦麦脆汁鸡 ISTP / 圆筒冰淇淋 ISFP。
8 种隐藏人格(每名用户最多 1 个,条件不满足时不随机发放):
劳资数到三 → 劳力士 → 芝士分子 → 堡持冷静 → 鸡不可失 → 薯于你 → 麦已成粥 → 麦门项目经理。
判定分两层:先算必要条件 eligible,再按 triggerScore 降序,同分回落优先级。
劳力士与劳资数到三是两条完全独立的规则:前者强调“把事情做完、耐造”,不要求 Q20-D;
后者强调“结束磨叽、接管决策”,必须 Q20-D。
具体触发条件见 engine/scoring.mjs 的 evaluateHiddenRules(),人类可读版本写在 engine/hidden.mjs 的 ruleText。
所有人格介绍都在 engine/ 目录,不在 src/ 里 —— 前端、CLI、Agent Skill 共用同一份配置,
改一处三处同时生效,不存在第二份文案。改完跑 npm run validate && npm test 即可。
| 想改什么 | 文件 | 字段 |
|---|---|---|
| 16 种主人格的全部介绍 | engine/personalities.mjs |
description 完整解读、dailyTraits 麦门日常、weakness 隐藏软肋、misunderstood 易被误解、declaration 宣言、shareQuote 分享金句、bestMatchType / bestMatchText 最佳饭搭子、title、themeColor |
| 每个人格对应的产品与图片 | engine/personalities.mjs |
product 本命单品、productImage 官方产品图(public/assets/products/)、image 原创插画兜底 |
| 8 种隐藏人格 / 彩蛋的全部介绍 | engine/hidden.mjs |
name、title、declaration、description、keywords、storeScene 麦门表现、weakness、shareQuote、rarityLabel 彩蛋稀有度、eggAction 彩蛋动作 |
| 隐藏人格的触发条件 | engine/scoring.mjs |
evaluateHiddenRules();人类可读规则同步写在 hidden.mjs 的 ruleText |
| 隐藏人格的冲突优先级 | engine/hidden.mjs |
priority(数字越小越优先) |
| 人格的点单偏好 | engine/profile.mjs |
HIDDEN_MEAL_PREFERENCE(隐藏人格点单模式)、resolveAvoidList() 等维度 → 策略映射 |
| 选品规则(什么维度配什么菜) | engine/meal-plan.mjs |
buildMealPlan() 的 6 条规则 |
| 20 道题与四维权重 | engine/questions.mjs |
题干、选项、分值、行为标签 |
在页面上浏览全部文案:图鉴页 /gallery(16 型分组)与 /gallery/:type(单人详情);
开发模式下的 /debug 可逐个预览 16 + 8 种结果,不用真做题。
改完记得跑校验:
npm run validate会检查题量、选项数、分值合法性、产品唯一性、必填文案是否齐全。
完整说明见 MCP_INTEGRATION.md,要点:
- Server:
mcd-mcp(麦当劳中国官方托管,Streamable HTTP,https://mcp.mcd.cn) - 核心 Tool:
now-time-info、query-nearby-stores/delivery-query-stores、query-meals、query-meal-detail、calculate-price、query-store-coupons、available-coupons、auto-bind-coupons、query-my-coupons、list-nutrition-foods、create-order、query-order、cancel-order - 明确不用:积分抽奖、积分商城下单、机酒预订等消耗型能力 —— 本 Skill 只做“点一顿饭”
三段式安全顺序(写在 SKILL.md 里,Agent 必须遵守):
- 先给无券方案与选择理由 → 绝不提前读券
- 明确询问是否授权查券 → 同意后才领券、算到手价
- 复述订单摘要 → 用户确认后才
create-order
职责边界:事实归 MCP(门店/菜单/价格/库存),偏好归本地引擎(meal-plan.mjs),确认权归用户。
npm test12 项全部通过,覆盖规格书 §17.2 的 10 条验收项:
| # | 用例 |
|---|---|
| 1 | 全选 E/N/T/J 倾向 → ENTJ(巨无霸) |
| 2 | 全选 I/S/F/P 倾向 → ISFP(圆筒冰淇淋) |
| 3 | 同分输入经稳定哈希后重复运行结果一致 |
| 4 | 修改答案后旧分值被替换而非累计 |
| 5 | 百分比无 NaN,两侧之和恒为 100 |
| 6 | 契合度恒落在 74~96 |
| 7 | Q20-D 但条件不足 → 不授予“劳资数到三”,只给轻提示 |
| 8 | 劳力士不依赖 Q20-D |
| 9 | 多隐藏人格满足时按触发分与优先级只返回一个 |
| 10 | 无隐藏人格满足时返回 null |
| + | 配置校验通过 / 人格档案与套餐方案可稳定生成 |
npm run validate # ✅ 配置校验通过(同时输出 1 条已知冲突提示)端到端冒烟测试(npm run e2e,12 项):用本机 Chrome 的 DevTools Protocol 真实点完 20 题,
校验首页渲染、进入结果页、契合度与四维渲染、SPA 回退、生产构建屏蔽 /debug,并输出结果页截图。
不依赖 Playwright,也不用下载浏览器 —— 找得到 Chrome 或 Edge 就能跑。
产物是纯静态站点,任意静态托管都可用。必须配置 SPA 回退,否则刷新 /quiz、/result 会 404。
- Vercel:仓库已带
vercel.json(含 rewrites 与静态资源缓存头),导入即可。 - Netlify:仓库已带
netlify.toml(含/* → /index.html200 重写)。 - GitHub Pages:仓库已带
.github/workflows/deploy-pages.yml, 在 Settings → Pages → Source 选 GitHub Actions 即可自动发布 (工作流已自动处理VITE_BASE=/Mcdonalds-mbti/子路径与404.html回退)。 - Cloudflare Pages:构建命令
npm run build,输出目录dist,新建_redirects写入/* /index.html 200。
部署在子路径时不需要改代码:
vite.config.ts读取VITE_BASE环境变量注入base, 前端路由的basename与静态资源路径都跟随import.meta.env.BASE_URL自动适配。
规格书里存在一处内部矛盾,我们没有默默绕过,而是记录在案并按最小改动处理:
冲突:规格书 §6 的 Q19-A 说明写着「增加“鸡不可失”信号」, 但 §9.5 的「鸡不可失」触发规则要求必须满足
Q18-A,并未包含Q19-A。
处理方式:以判定章节 §9.5 为准(§9 是规则章节,§6 是题库章节)。
同时保留 engine/questions.mjs 里 q19a 的 hiddenSignals: ['chicken'] 数据以便追溯,
并在 engine/validate.mjs 中输出这条提示,npm run validate 会打印出来。
其他偏离规格书的地方(均为工程取舍,未改动任何题目、产品映射、结果文案与触发逻辑):
| 项 | 规格书 | 本实现 | 原因 |
|---|---|---|---|
| 单元测试框架 | Vitest | Node 内置 node:test |
零额外依赖,npm test 开箱即用;引擎是纯 ESM,两种框架都能跑 |
| E2E 测试 | Playwright | 自写 CDP 冒烟测试(scripts/smoke-e2e.mjs) |
不用下载数百 MB 的浏览器二进制,本机有 Chrome/Edge 即可;覆盖关键用户流 |
| 埋点 | 可选接入 Plausible / Umami | 未接入 | 首版默认不采集任何第三方数据,符合最小化采集原则 |
| 插画 | 原创或占位素材 | 脚本生成的几何 SVG | 规避版权风险,且保证导出图片时 Canvas 不被跨域污染 |
- 本测试为非官方趣味创作,仅供娱乐,不属于正式 MBTI 或心理测评, 与麦当劳品牌及其关联公司不存在商业合作、授权或隶属关系。
- 关于图片素材:页面中的产品图来自麦当劳官方菜单图(
menu-img.mcd.cn,经麦当劳 MCPquery-meals返回的image字段获取后本地打包),版权归麦当劳中国所有,此处仅在本次非商业参赛作品中作展示用途; 所有插画与图形均为scripts/generate-assets.mjs生成的原创几何图形,未使用任何官方商标图形或角色形象。 因菜单季节轮换,个别产品图为当前在售的最近似款(如经典麦旋风替代奥利奥麦旋风、心形薯饼替代经典薯饼), 官方图加载失败时会自动回退到原创插画。 - 页面中的「彩蛋稀有度」为娱乐化设定,并非真实用户统计结果,也不构成任何概率承诺。
- 不采集手机号、头像、定位坐标、设备指纹;答题进度与结果仅保存在浏览器
localStorage。 - 仓库与提交材料中不包含任何真实 Token、密钥或凭证,配置文件仅使用环境变量占位符。
- 麦当劳 MCP 返回的餐品信息、价格与供应状态以麦当劳官方渠道的实时结果为准; 本项目的输出不构成医疗、营养或其他专业建议。
- 完整参赛声明见 CONTEST_DECLARATION.md。
麦当劳程序员创意开发大赛(M-CODE)参赛作品 · 使用 WorkBuddy 开发 · 非麦当劳官方产品