@taptap/instant-games-open-mcp 1.22.0-beta.6 → 1.22.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,39 +51,41 @@
51
51
 
52
52
  ```text
53
53
  maker_status
54
- maker_check_environment
55
54
  maker_exchange_pat(manual_pat)
56
55
  自动获取 TapTap token
57
56
  自动列出 app
57
+ maker_list_apps
58
58
  用户选择 app
59
59
  maker_clone_to_current_directory
60
- maker_configure_remote_proxy
61
60
  maker_build_current_directory
62
61
  maker_submit_current_directory
63
- maker_push_current_directory
64
62
  ```
65
63
 
66
64
  说明:
67
65
 
68
66
  - Maker MCP 依赖用户本机已有 Git。工具只检测并给出安装引导,不会代替用户安装 Git。
69
67
  - 用户说“我要开发maker游戏 / 本地maker开发 / 拉取maker游戏到本地 / 把maker游戏代码拉到本地 / clone maker项目 / 下载maker游戏代码 / 初始化maker开发目录 / 配置maker本地开发 / 继续开发maker项目”时,应触发 Maker 本地开发初始化流程。
70
- - 如果 `maker_status` 或 `maker_check_environment` 显示 Git 缺失,必须持续提示用户自行安装 Git;在 `git --version` 可用前,不执行 clone、fetch、commit 或 push。
68
+ - 如果 `maker_status` 显示 Git 缺失,必须持续提示用户自行安装 Git;在 `git --version` 可用前,不执行 clone、fetch、commit 或 push。
71
69
  - Maker API、git 和 TapTap token 默认走 PAT-first:如果用户还没有 PAT,引导用户打开临时 PAT 页面 `https://fuping.agnt.xd.com/pat-tokens` 新建 PAT;用户提供 PAT 后调用 `maker_exchange_pat(manual_pat)` 保存。
72
70
  - 保存 PAT 后会自动列出 app;`maker_status` 如果发现本地已有 PAT 且当前目录未绑定,也会自动列出 app,无需用户额外要求。
73
- - 保存 PAT 后会自动调用 `GET /api/v1/user/taptap-token` 获取并保存 TapTap MAC token;Tap OAuth 登录只作为 legacy fallback
71
+ - 保存 PAT 后会自动调用 `GET /api/v1/user/taptap-token` 获取并保存 TapTap MAC token。
74
72
  - `maker_list_apps` 和 `maker_clone_to_current_directory` 不再要求先完成 Tap 登录。
75
73
  - `maker_clone_to_current_directory` 不要求当前目录为空;clone 前会检查本地目录,忽略 `.claude`、`.mcp`、`.skill`、`.config`、`.ini` 等点开头配置项,只对普通本地文件输出提醒。clone 最终结果固定包含 `Pre-clone local directory check` 区块;已有本地文件会保留,若与 Maker 项目文件同路径冲突则失败并列出冲突文件。
76
74
  - `maker_list_apps` 会解析 Maker `/apps` 返回的创建时间、最近会话时间、游戏类型、阶段、图标、置顶/归档/删除时间等字段,并保留原始 `raw` 数据。
77
- - Maker Tap 登录只需要 client id;`rnd` 环境或 npm `@beta` 包会使用内置 Maker client id 兜底,不要求产品配置 `TAPTAP_MCP_CLIENT_SECRET`。
78
75
  - PAT 会保存到 `~/.taptap-maker/pat.json`,并兼容旧的 `~/.maker-pat`、`PAT` / `MAKER_PAT` 环境变量。
79
- - JWT 仅作为 legacy fallback 保留:`maker_exchange_jwt(manual_jwt)`、`JWT` / `MAKER_JWT` 仍可用于旧后端或创建新 PAT。
80
76
  - Maker app 必须先通过 `maker_list_apps` 展示给用户选择,再调用 clone。
81
77
  - Maker 后端地址按 `TAPTAP_MCP_ENV` 从 `src/maker/config.ts` 的环境配置表读取,本地 MCP 配置只需要切 `rnd` / `production`。
82
- - 如果用户直接说“构建 / build / 重新构建游戏”,本地 Maker MCP 应调用 `maker_build_current_directory` 转发到远端 `build` tool。
78
+ - 如果用户直接说“构建 / build / 重新构建游戏”,本地 Maker MCP 应调用 `maker_build_current_directory`。该工具会强制检查本地 Maker 项目是否有未提交改动。
79
+ - 如果构建前发现本地有改动且尚未保存自动提交偏好,工具会停止并提示用户选择:`提交本地改动并触发构建(以后都是如此)`,或明确不提交、只构建云端已有版本。
80
+ - 用户选择 `提交本地改动并触发构建(以后都是如此)` 后,应再次调用 `maker_build_current_directory` 并传入 `submit_local_changes_before_build=true` 和 `remember_build_submit_preference=true`;工具会完整执行 commit + push + build,并在当前项目 `.maker-mcp/config.json` 记住偏好。
81
+ - 保存偏好后,后续用户说“构建”且本地有改动时,`maker_build_current_directory` 会默认自动提交并继续执行远端 build,不再重复询问。
82
+ - 只有当用户明确说“不提交 / 直接构建云端版本”时,才可再次调用 `maker_build_current_directory` 并传入 `confirm_remote_build_without_submit=true`。
83
+ - 用户说“查看结果 / 预览 / 跑一下 / 验证一下 / 看看效果”时,也按构建流程处理;如果本地有改动,先提醒用户选择是否提交,确认提交后执行 commit + push + build。
83
84
  - 构建转发会从 MCP 包自身定位 `dist/proxy.js`;`cwd` / `target_dir` 只用于识别 Maker 游戏项目,不要求游戏目录存在 MCP 的 `dist/proxy.js`。
84
- - 如需在当前游戏项目里直接暴露远端全量 `taptap-proxy` tools,再使用 `maker_configure_remote_proxy` 写入 `.mcp.json` 并重启 MCP 会话。
85
- - 用户说“帮我提交/提交代码”时使用 `maker_submit_current_directory`,会对当前 Maker 项目执行 commit + push
86
- - “帮我提交代码到maker / taptap制造 / tap制造 / tap”也应触发 `maker_submit_current_directory`。
85
+ - 用户未指定构建入口且本地存在 `scripts/main.lua` 时,Maker MCP 默认向远端 build 传 `scriptsPath="scripts"` `entry="main.lua"`,避免第一次构建多一轮“入口配置缺失”的提示;用户显式传入口或多人入口时优先生效。
86
+ - 远端 proxy 配置是内部能力,不单独暴露给 Agent;构建工具会在需要时直接使用远端 Maker MCP
87
+ - 用户说“帮我提交/提交代码”时使用 `maker_submit_current_directory`,会对当前 Maker 项目执行 commit + push + build;只有实际 push 成功后才继续远端 build。
88
+ - “帮我提交代码到maker / taptap制造 / tap制造 / tap / push / 提交并推送”也应触发 `maker_submit_current_directory`,并在 push 成功后继续远端 build。
87
89
  - Maker 项目提交不走通用 Git skill 的任务号、新分支规则;冲突时先和用户确认 pull/rebase 流程。
88
90
  - 如果 commit 已完成但 push 失败,Maker MCP 会返回 commit hash、ahead 状态、exit code、stderr/stdout 和下一步建议,便于开发期排查。
89
91
  - clone/fetch、push 和远端 build 属于慢操作;工具会尽量发送 MCP progress notification,Git 阶段会解析 stderr 百分比,最终返回会包含耗时和最近进度。
@@ -332,15 +334,15 @@ Issue #162 引入了 Maker 本地 MCP,用于后续支持 Maker 登录、项目
332
334
 
333
335
  ```text
334
336
  maker_status
335
- maker_check_environment
336
337
  maker_exchange_pat
337
338
  自动获取 TapTap token
338
339
  自动列出 app
340
+ maker_list_apps
339
341
  maker_clone_to_current_directory
340
- maker_push_current_directory
342
+ maker_submit_current_directory
341
343
  ```
342
344
 
343
- `maker_check_environment` 只做检测和引导,不安装 Git。若 Git 不可用,clone/push 会直接停止,直到用户自行安装 Git 并通过 `git --version` 验证。
345
+ `maker_status` 会检查 Git 并输出初始化引导。若 Git 不可用,clone/push 会直接停止,直到用户自行安装 Git 并通过 `git --version` 验证。
344
346
 
345
347
  测试时引导用户访问临时 PAT 页面 `https://fuping.agnt.xd.com/pat-tokens` 新建 Maker PAT,
346
348
  再作为 `manual_pat` 传给 `maker_exchange_pat`,工具会同步获取 TapTap token。
package/dist/maker.js CHANGED
@@ -25655,7 +25655,7 @@ function formatBrowserJwtGuide() {
25655
25655
  `1. 在 Chrome 打开 ${makerWebUrl} 并确认已登录。`,
25656
25656
  "2. 打开开发者工具,进入 Application -> Local storage。",
25657
25657
  "3. 找到 `taptap_access_token` 并拿到它的 value 给我。",
25658
- "拿到 value 后,MCP 会将它作为 `manual_jwt` 传给 maker_exchange_jwt。",
25658
+ "拿到 value 后,可将它作为 legacy JWT 传给仍支持 jwt 参数的 Maker 内部流程。",
25659
25659
  "",
25660
25660
  `MCP 会把 JWT 保存到本地 ${process.env.TAPTAP_MAKER_HOME || "~/.taptap-maker"}/jwt.json。`
25661
25661
  ].join("\n");
@@ -25711,34 +25711,6 @@ async function exchangeTapTokenForMakerJwt(tapToken) {
25711
25711
  saveJwt(jwt2);
25712
25712
  return jwt2;
25713
25713
  }
25714
- async function exchangeSavedTapAuthForMakerJwt(options) {
25715
- const exchangeUrl = getMakerJwtExchangeUrl();
25716
- const tapAuth = loadTapAuth();
25717
- if (exchangeUrl && tapAuth) {
25718
- return exchangeTapTokenForMakerJwt(tapAuth);
25719
- }
25720
- const manualJwt = getManualMakerJwt(options == null ? void 0 : options.manualJwt);
25721
- if (manualJwt == null ? void 0 : manualJwt.token) {
25722
- const saved = saveManualMakerJwt(manualJwt.token);
25723
- return saved;
25724
- }
25725
- const cachedJwt = loadJwt();
25726
- if (cachedJwt) {
25727
- return cachedJwt;
25728
- }
25729
- if (!exchangeUrl) {
25730
- throw new Error(
25731
- [
25732
- `${JWT_EXCHANGE_ENV} is not configured. Provide manual_jwt for now.`,
25733
- "",
25734
- formatBrowserJwtGuide()
25735
- ].join("\n")
25736
- );
25737
- }
25738
- throw new Error(
25739
- "Tap auth not found. Call maker_tap_login_start and maker_tap_login_complete first."
25740
- );
25741
- }
25742
25714
  function requireMakerJwt(manualJwt) {
25743
25715
  const jwt2 = getManualMakerJwt(manualJwt) || loadJwt();
25744
25716
  if (!jwt2) {
@@ -25751,7 +25723,7 @@ function requireMakerJwt(manualJwt) {
25751
25723
  var BUILT_IN_MAKER_CLIENT_ID = "m2dnabebip3fpardnm";
25752
25724
  var MAKER_CLIENT_ID_ENV = "TAPTAP_MAKER_CLIENT_ID";
25753
25725
  var TAPTAP_CLIENT_ID_ENV = "TAPTAP_MCP_CLIENT_ID";
25754
- var MAKER_VERSION = true ? "1.22.0-beta.6" : "dev";
25726
+ var MAKER_VERSION = true ? "1.22.0-beta.8" : "dev";
25755
25727
  async function startTapDeviceLogin() {
25756
25728
  ensureMakerClientId();
25757
25729
  const environment = EnvConfig.environment;
@@ -25775,7 +25747,7 @@ async function completeTapDeviceLogin(options) {
25775
25747
  const session = (options == null ? void 0 : options.deviceCode) ? null : loadTapDeviceSession();
25776
25748
  const deviceCode = (options == null ? void 0 : options.deviceCode) || (session == null ? void 0 : session.device_code);
25777
25749
  if (!deviceCode) {
25778
- throw new Error("Tap device_code not found. Call maker_tap_login_start first.");
25750
+ throw new Error("Tap device_code not found. Use maker_exchange_pat with a valid Maker PAT.");
25779
25751
  }
25780
25752
  const environment = (session == null ? void 0 : session.environment) || EnvConfig.environment;
25781
25753
  const intervalMs = ((session == null ? void 0 : session.interval_seconds) || 3) * 1e3;
@@ -26595,6 +26567,30 @@ async function pushMakerProject(options) {
26595
26567
  status: "pushed"
26596
26568
  };
26597
26569
  }
26570
+ async function readMakerProjectLocalChanges(cwd) {
26571
+ ensureGitAvailable();
26572
+ const requestedDir = path6.resolve(cwd);
26573
+ if (!isGitRepo(requestedDir)) {
26574
+ throw new Error(`${requestedDir} is not a git repository.`);
26575
+ }
26576
+ const projectRoot = (await readGit(["rev-parse", "--show-toplevel"], requestedDir)).trim();
26577
+ const configPath = path6.join(projectRoot, ".maker-mcp", "config.json");
26578
+ if (!fs4.existsSync(configPath)) {
26579
+ throw new Error(
26580
+ `${projectRoot} is not bound to a Maker project. .maker-mcp/config.json is missing.`
26581
+ );
26582
+ }
26583
+ const rawStatus = await readGit(["status", "--porcelain", "-z"], projectRoot);
26584
+ const files = parseGitStatusFiles(rawStatus).filter(
26585
+ (file2) => file2 !== ".maker-mcp" && !file2.startsWith(".maker-mcp/")
26586
+ );
26587
+ return {
26588
+ hasChanges: files.length > 0,
26589
+ projectRoot,
26590
+ files,
26591
+ rawStatus
26592
+ };
26593
+ }
26598
26594
  function ensureTargetCanBindApp(target, appId) {
26599
26595
  const existingConfig = loadProjectConfig(target);
26600
26596
  if (!(existingConfig == null ? void 0 : existingConfig.project_id) || existingConfig.project_id === appId) {
@@ -26625,6 +26621,22 @@ function generateCommitMessage(status) {
26625
26621
  }
26626
26622
  return "chore: update maker project";
26627
26623
  }
26624
+ function parseGitStatusFiles(status) {
26625
+ const entries = status.split("\0").filter(Boolean);
26626
+ const files = [];
26627
+ for (let index = 0; index < entries.length; index += 1) {
26628
+ const entry = entries[index];
26629
+ const statusCode = entry.slice(0, 2);
26630
+ const file2 = entry.slice(3);
26631
+ if (file2) {
26632
+ files.push(file2);
26633
+ }
26634
+ if (statusCode.includes("R") || statusCode.includes("C")) {
26635
+ index += 1;
26636
+ }
26637
+ }
26638
+ return files;
26639
+ }
26628
26640
  async function readAheadState(cwd) {
26629
26641
  var _a2;
26630
26642
  try {
@@ -26689,9 +26701,9 @@ function nextActionForFailure(classification) {
26689
26701
  case "git_missing":
26690
26702
  return "本机未检测到可用的 Git。请用户自行安装 Git,并在 `git --version` 可用后重启 MCP 客户端再重试;安装前不要执行 clone、fetch、commit 或 push。";
26691
26703
  case "auth":
26692
- return "刷新 Maker PAT 后重试 maker_push_current_directory;如果仍失败,请确认 PAT 是否过期或缺少 Maker git 权限。";
26704
+ return "刷新 Maker PAT 后重试 maker_submit_current_directory;如果仍失败,请确认 PAT 是否过期或缺少 Maker git 权限。";
26693
26705
  case "remote_transient":
26694
- return "远端 Maker git 服务临时不可用。不要重新提交,稍后直接重试 maker_push_current_directory。";
26706
+ return "远端 Maker git 服务临时不可用。不要重新提交,稍后直接重试 maker_submit_current_directory。";
26695
26707
  case "remote_rejected":
26696
26708
  return "远端已有新提交。不要新建分支或要任务号,先询问用户是否 pull/rebase 当前 Maker 远端变更,再重试 push。";
26697
26709
  case "local":
@@ -27326,15 +27338,15 @@ function formatIdentifyHint() {
27326
27338
  "",
27327
27339
  "常见触发意图:我要开发maker游戏 / 本地maker开发 / 拉取maker游戏到本地 / 把maker游戏代码拉到本地 / 初始化maker开发目录。",
27328
27340
  "在 Codex/MCP 场景下,请不要运行 shell 命令 `taptap-maker init`。",
27329
- "初始化前必须先确认本机 Git 可用。若 `maker_status` `maker_check_environment` 显示 Git 缺失,只能提示用户自行安装 Git;在 `git --version` 可用前不要执行 clone。",
27330
- "请按完整 MCP 工具流程初始化当前目录;当前默认使用 Maker PAT 获取 app 列表并执行 git clone/push。",
27341
+ "初始化前必须先调用 `maker_status` 确认本机 Git 可用。若 Git 缺失,只能提示用户自行安装 Git;在 `git --version` 可用前不要执行 clone。",
27342
+ "请按完整 MCP 工具流程初始化当前目录;当前默认使用 Maker PAT 获取 app 列表并执行 clone 和提交。",
27331
27343
  "",
27332
- "1. 调用 `maker_check_environment` 或查看 `maker_status`,确认 Git 已安装。",
27344
+ "1. 调用 `maker_status`,确认 Git 已安装。",
27333
27345
  `2. 如果还没有 PAT,主动让用户打开临时 PAT 页面 ${TEMP_MAKER_PAT_TOKENS_URL} 新建 PAT,并把 PAT 发给你。`,
27334
27346
  "3. 调用 `maker_exchange_pat` 把 PAT 作为 `manual_pat` 保存;工具会自动获取 TapTap token 并列出可用 Maker Apps。",
27335
27347
  "4. 必须把 app 列表展示给用户,让用户选择。",
27336
27348
  "5. 用户选择后,调用 `maker_clone_to_current_directory` 把代码拉到当前对话目录。",
27337
- "6. 如果 PAT 获取 TapTap token 失败,再使用 `maker_tap_login_start` `maker_tap_login_complete` 作为 fallback。",
27349
+ "6. 如果 PAT 获取 TapTap token 失败,请确认 PAT 是否有效后重新调用 `maker_exchange_pat`。",
27338
27350
  "",
27339
27351
  `clone 成功后会在当前目录写入 ${getProjectMarkerDirName()}/config.json。`
27340
27352
  ].join("\n");
@@ -42381,54 +42393,14 @@ function isElectron() {
42381
42393
  }
42382
42394
 
42383
42395
  // src/maker/server/mcp.ts
42384
- var VERSION = true ? "1.22.0-beta.6" : "dev";
42385
- var DEFAULT_PROXY_MCP_NAME = "taptap-proxy";
42396
+ var VERSION = true ? "1.22.0-beta.8" : "dev";
42386
42397
  var DEFAULT_PROXY_PACKAGE = "@taptap/instant-games-open-mcp@1.22.0";
42387
42398
  var DEFAULT_BUILD_TIMEOUT_MS = 10 * 60 * 1e3;
42388
42399
  var LONG_OPERATION_HEARTBEAT_MS = 3 * 60 * 1e3;
42389
- var MAKER_WEB_URL = getMakerWebUrl();
42390
42400
  var tools = [
42391
- {
42392
- name: "maker_tap_login_start",
42393
- description: "Legacy fallback: start TapTap OAuth device login for Maker. Prefer maker_exchange_pat because it can fetch and save TapTap token automatically with a Maker PAT.",
42394
- inputSchema: {
42395
- type: "object",
42396
- properties: {}
42397
- }
42398
- },
42399
- {
42400
- name: "maker_tap_login_complete",
42401
- description: "Legacy fallback: complete TapTap OAuth device login after the user says authorization is done. Saves Tap MAC auth locally for remote Maker MCP tools.",
42402
- inputSchema: {
42403
- type: "object",
42404
- properties: {
42405
- device_code: {
42406
- type: "string",
42407
- description: "Optional device_code from maker_tap_login_start. Defaults to the cached latest login session."
42408
- },
42409
- max_attempts: {
42410
- type: "number",
42411
- description: "Optional polling attempts. Defaults to 20; increase only when the user is still authorizing."
42412
- }
42413
- }
42414
- }
42415
- },
42416
- {
42417
- name: "maker_exchange_jwt",
42418
- description: `Prepare and save the Maker JWT used by Maker API and Git PAT operations. After Tap login is completed, ask the user to open ${MAKER_WEB_URL}, open Chrome DevTools > Application > Local storage, find \`taptap_access_token\`, give its value to the agent, and pass it as manual_jwt.`,
42419
- inputSchema: {
42420
- type: "object",
42421
- properties: {
42422
- manual_jwt: {
42423
- type: "string",
42424
- description: `Maker JWT copied from Chrome DevTools Application > Local storage key \`taptap_access_token\` on ${MAKER_WEB_URL}.`
42425
- }
42426
- }
42427
- }
42428
- },
42429
42401
  {
42430
42402
  name: "maker_exchange_pat",
42431
- description: `Prepare and save the Maker PAT used by Maker API app listing, Git operations, and TapTap token retrieval. Prefer this PAT-first flow over maker_exchange_jwt. If the user does not have a PAT, ask them to open the temporary PAT page ${TEMP_MAKER_PAT_TOKENS_URL}, create one, and give it to the agent. After saving PAT, this tool automatically fetches TapTap token and lists apps.`,
42403
+ description: `Prepare and save the Maker PAT used by Maker API app listing, Git operations, and TapTap token retrieval. If the user does not have a PAT, ask them to open the temporary PAT page ${TEMP_MAKER_PAT_TOKENS_URL}, create one, and give it to the agent. After saving PAT, this tool automatically fetches TapTap token and lists apps.`,
42432
42404
  inputSchema: {
42433
42405
  type: "object",
42434
42406
  properties: {
@@ -42442,40 +42414,20 @@ var tools = [
42442
42414
  },
42443
42415
  {
42444
42416
  name: "maker_list_apps",
42445
- description: "List Maker apps available to the current Maker PAT. Prefer cached PAT from maker_exchange_pat or the pat argument. JWT is accepted only as a legacy fallback. Always show the list to the user and ask them to choose before cloning.",
42417
+ description: "List Maker apps available to the current Maker PAT. Prefer cached PAT from maker_exchange_pat or the pat argument. Always show the list to the user and ask them to choose before cloning.",
42446
42418
  inputSchema: {
42447
42419
  type: "object",
42448
42420
  properties: {
42449
42421
  pat: {
42450
42422
  type: "string",
42451
42423
  description: "Optional Maker PAT override. If provided, it is saved for later Maker operations."
42452
- },
42453
- jwt: {
42454
- type: "string",
42455
- description: "Legacy Maker JWT override. Prefer PAT instead."
42456
42424
  }
42457
42425
  }
42458
42426
  }
42459
42427
  },
42460
42428
  {
42461
42429
  name: "maker_status",
42462
- description: `Show local Maker MCP binding status, including whether Git is available. Use this as the first step for Maker local development requests such as "我要开发maker游戏", "本地maker开发", "拉取maker游戏到本地", "把maker游戏代码拉到本地", "clone maker项目", "打开/继续开发maker项目", or "初始化maker开发目录". If Git is missing, do not call clone/push/build-side git operations; keep showing the install guidance until the user installs Git and git --version works. If PAT is missing, ask the user to open the temporary PAT page ${TEMP_MAKER_PAT_TOKENS_URL}, create a PAT, give it to the agent, then call maker_exchange_pat. If PAT exists and no project is bound, this tool automatically lists apps; ask the user to choose an app, then call maker_clone_to_current_directory.`,
42463
- inputSchema: {
42464
- type: "object",
42465
- properties: {}
42466
- }
42467
- },
42468
- {
42469
- name: "maker_check_environment",
42470
- description: "Check local Maker MCP prerequisites. This tool only detects and guides; it MUST NOT install Git or modify the user machine. If Git is missing, show the platform-specific install guidance and do not run clone, fetch, commit, or push until the user installs Git and git --version works.",
42471
- inputSchema: {
42472
- type: "object",
42473
- properties: {}
42474
- }
42475
- },
42476
- {
42477
- name: "maker_setup_guide",
42478
- description: `Show setup guidance when the current directory is not bound to a Maker project yet. Use this for user intents like "我要开发maker游戏", "本地maker开发", "拉取maker游戏到本地", "把maker游戏代码拉到本地", "clone maker游戏", "下载maker项目代码", "初始化maker项目", or "配置maker本地开发". In Codex/MCP mode, first make sure Git is installed by checking maker_status or maker_check_environment. If Git is missing, keep showing the install guidance and do not clone. If PAT is missing, ask the user to open the temporary PAT page ${TEMP_MAKER_PAT_TOKENS_URL}, create a PAT, give it to the agent, then call maker_exchange_pat; maker_exchange_pat automatically lists apps after saving PAT. If PAT already exists, maker_status automatically lists apps. Ask the user to choose an app, then maker_clone_to_current_directory. Do not ask for app_id upfront and do not run shell commands.`,
42430
+ description: `Show local Maker MCP status, environment prerequisites, and initialization guidance. Use this as the first step for Maker local development requests such as "我要开发maker游戏", "本地maker开发", "拉取maker游戏到本地", "把maker游戏代码拉到本地", "clone maker项目", "打开/继续开发maker项目", "初始化maker开发目录", or "配置maker本地开发". This tool includes the Git prerequisite check and setup guide; do not look for separate environment or setup tools. If Git is missing, do not call clone/submit/build-side git operations; keep showing the install guidance until the user installs Git and git --version works. If PAT is missing, ask the user to open the temporary PAT page ${TEMP_MAKER_PAT_TOKENS_URL}, create a PAT, give it to the agent, then call maker_exchange_pat. If PAT exists and no project is bound, this tool automatically lists apps; ask the user to choose an app, then call maker_clone_to_current_directory.`,
42479
42431
  inputSchema: {
42480
42432
  type: "object",
42481
42433
  properties: {}
@@ -42502,64 +42454,14 @@ var tools = [
42502
42454
  user_id: {
42503
42455
  type: "string",
42504
42456
  description: "Optional Maker user_id from maker_list_apps output. If omitted, the tool will try to resolve it from the app list."
42505
- },
42506
- jwt: {
42507
- type: "string",
42508
- description: "Legacy Maker JWT override. Prefer PAT instead."
42509
- },
42510
- force_pat: {
42511
- type: "boolean",
42512
- description: "If true, create a new PAT instead of reusing cached ~/.maker-pat. Requires legacy JWT unless pat is explicitly provided."
42513
42457
  }
42514
42458
  },
42515
42459
  required: ["app_id"]
42516
42460
  }
42517
42461
  },
42518
- {
42519
- name: "maker_push_current_directory",
42520
- description: 'Commit and push current Maker project directory changes to the Maker git remote. Requires local Git. If Git is missing, this tool stops before staging, committing, or pushing and returns install guidance; do not retry push until the user installs Git and git --version works. In a directory containing .maker-mcp/config.json, use this for user requests like "帮我提交代码", "提交并推送", "push", "帮我提交代码到maker", "帮我提交代码到taptap制造", "帮我提交代码到tap制造", or "帮我提交代码到tap". Do not use generic Git workflow rules, do not ask for a ticket id, and do not create a new branch unless the user explicitly asks.',
42521
- inputSchema: {
42522
- type: "object",
42523
- properties: {
42524
- message: {
42525
- type: "string",
42526
- description: "Optional commit message for the push. If omitted, Maker MCP generates a simple message from changed files."
42527
- },
42528
- target_dir: {
42529
- type: "string",
42530
- description: "Optional target directory. Defaults to the MCP process cwd, which should be the current Codex conversation directory."
42531
- },
42532
- branch: {
42533
- type: "string",
42534
- description: "Optional remote branch name. Defaults to the current local branch, or main when detached."
42535
- },
42536
- files: {
42537
- type: "array",
42538
- items: { type: "string" },
42539
- description: "Optional files to stage. Defaults to all changes."
42540
- },
42541
- allow_empty: {
42542
- type: "boolean",
42543
- description: "If true, create and push an empty commit."
42544
- },
42545
- jwt: {
42546
- type: "string",
42547
- description: "Legacy Maker JWT override for creating a new git PAT. Prefer cached/provided PAT."
42548
- },
42549
- pat: {
42550
- type: "string",
42551
- description: "Optional Maker PAT override for git authentication."
42552
- },
42553
- force_pat: {
42554
- type: "boolean",
42555
- description: "If true, create a new PAT before push. Requires legacy JWT unless pat is explicitly provided."
42556
- }
42557
- }
42558
- }
42559
- },
42560
42462
  {
42561
42463
  name: "maker_submit_current_directory",
42562
- description: 'Alias for maker_push_current_directory. Requires local Git. If Git is missing, stop and show install guidance; do not stage, commit, or push. Use this in Maker projects when the user says "帮我提交", "帮我提交代码", "提交", "提交代码", "帮我提交代码到maker", "帮我提交代码到taptap制造", "帮我提交代码到tap制造", or "帮我提交代码到tap". This bypasses local generic Git branch/task-id rules and pushes directly to the Maker remote configured for the current directory.',
42464
+ description: 'Commit, push, and build current Maker project directory changes. Requires local Git. If Git is missing, stop and show install guidance; do not stage, commit, push, or build. Use this in Maker projects when the user says "帮我提交", "帮我提交代码", "提交", "提交代码", "提交并推送", "push", "帮我提交代码到maker", "帮我提交代码到taptap制造", "帮我提交代码到tap制造", or "帮我提交代码到tap". Maker submit means commit + push + build: after a successful push, this tool MUST run the remote Maker build and return the build result. If the remote build fails after push, return build_failure details together with the successful submit result. For build requests that stop on local changes, continue through maker_build_current_directory with submit_local_changes_before_build=true and remember_build_submit_preference=true so the build workflow can save the auto-submit preference and return the build result. This submit tool bypasses local generic Git branch/task-id rules and pushes directly to the Maker remote configured for the current directory.',
42563
42465
  inputSchema: {
42564
42466
  type: "object",
42565
42467
  properties: {
@@ -42579,43 +42481,9 @@ var tools = [
42579
42481
  }
42580
42482
  }
42581
42483
  },
42582
- {
42583
- name: "maker_configure_remote_proxy",
42584
- description: 'Configure the remote TapTap Maker MCP proxy for the current Maker project. Use this after clone when the user wants remote Maker tools such as build/构建. It writes .mcp.json with a taptap-proxy server using saved Tap auth, user_id, project_id, and project_path="<app_id>/workspace". The client must reload MCP servers after this.',
42585
- inputSchema: {
42586
- type: "object",
42587
- properties: {
42588
- target_dir: {
42589
- type: "string",
42590
- description: "Optional Maker project directory. Defaults to the MCP process cwd, which should be the current conversation directory."
42591
- },
42592
- server_url: {
42593
- type: "string",
42594
- description: "Optional remote MCP server URL override. Defaults to the Maker endpoint table for TAPTAP_MCP_ENV."
42595
- },
42596
- env: {
42597
- type: "string",
42598
- enum: ["rnd", "production"],
42599
- description: "Remote MCP environment. Defaults to TAPTAP_MCP_ENV."
42600
- },
42601
- mcp_name: {
42602
- type: "string",
42603
- description: "MCP server name to write in .mcp.json. Defaults to taptap-proxy."
42604
- },
42605
- use_npx: {
42606
- type: "boolean",
42607
- description: "If true, write the script-style npx package command. Defaults to false and uses the proxy.js bundled with the Maker MCP package when available."
42608
- },
42609
- pkg: {
42610
- type: "string",
42611
- description: "Package used when use_npx=true. Defaults to @taptap/instant-games-open-mcp@1.22.0."
42612
- }
42613
- }
42614
- }
42615
- },
42616
42484
  {
42617
42485
  name: "maker_build_current_directory",
42618
- description: 'Build the current Maker game by forwarding to the remote TapTap Maker MCP build tool. MUST use this for user requests like "构建", "build", "重新构建游戏", "帮我构建maker游戏", "compile", or "run" in a Maker project. Do not write local build scripts. Uses saved Tap auth and current .maker-mcp/config.json project binding to call the remote build tool through taptap-proxy.',
42486
+ description: 'Build the current Maker game by forwarding to the remote TapTap Maker MCP build tool. MUST use this for user requests like "构建", "build", "重新构建游戏", "帮我构建maker游戏", "compile", or "run" in a Maker project. The tool itself enforces a local-change guard before remote build: if local Maker project changes exist, it will stop unless confirm_remote_build_without_submit is true, submit_local_changes_before_build is true, or the project has saved build_local_changes_policy=auto_submit. Explain to the user that direct build only uses the Maker remote committed version and may not include local edits. The primary option should be "提交本地改动并触发构建(以后都是如此)"; if the user chooses it, call maker_build_current_directory again with submit_local_changes_before_build=true and remember_build_submit_preference=true. Maker MCP will commit + push local changes, then run remote build and return the build result. If auto_submit preference is already saved, this build tool will submit local changes automatically and then run remote build. If the user explicitly says not to submit and wants to build the remote version, call this tool with confirm_remote_build_without_submit=true. Do not write local build scripts. Uses saved Tap auth and current .maker-mcp/config.json project binding to call the remote build tool through taptap-proxy.',
42619
42487
  inputSchema: {
42620
42488
  type: "object",
42621
42489
  properties: {
@@ -42625,11 +42493,11 @@ var tools = [
42625
42493
  },
42626
42494
  entry: {
42627
42495
  type: "string",
42628
- description: 'Optional single-player Lua entry file relative to scriptsPath, e.g. "main.lua". Omit to let the remote build tool infer/default.'
42496
+ description: 'Optional single-player Lua entry file relative to scriptsPath, e.g. "main.lua". If omitted and local scripts/main.lua exists with no explicit multiplayer entries, Maker MCP sends entry="main.lua" and scriptsPath="scripts" by default to avoid remote entry-missing prompts. Otherwise omit to let the remote build tool infer/default.'
42629
42497
  },
42630
42498
  scriptsPath: {
42631
42499
  type: "string",
42632
- description: 'Optional scripts directory relative to workspace. Remote build defaults to "scripts" when omitted.'
42500
+ description: 'Optional scripts directory relative to workspace. If omitted and local scripts/main.lua exists with no explicit entry overrides, Maker MCP sends scriptsPath="scripts" by default.'
42633
42501
  },
42634
42502
  entry_client: {
42635
42503
  type: "string",
@@ -42655,6 +42523,18 @@ var tools = [
42655
42523
  timeout_ms: {
42656
42524
  type: "number",
42657
42525
  description: "Optional remote build timeout in milliseconds. Defaults to 10 minutes. If timed out, do not retry blindly; inspect remote build logs first."
42526
+ },
42527
+ confirm_remote_build_without_submit: {
42528
+ type: "boolean",
42529
+ description: "Set true only after the user explicitly confirms they do not want to submit local changes and want to build the current Maker remote committed version."
42530
+ },
42531
+ submit_local_changes_before_build: {
42532
+ type: "boolean",
42533
+ description: 'Set true only after the user explicitly chooses "提交本地改动并触发构建(以后都是如此)". Maker MCP will commit + push local changes, then run the remote build and return the build result.'
42534
+ },
42535
+ remember_build_submit_preference: {
42536
+ type: "boolean",
42537
+ description: 'Set true together with submit_local_changes_before_build when the user chooses "提交本地改动并触发构建(以后都是如此)". Saves build_local_changes_policy=auto_submit for future build requests.'
42658
42538
  }
42659
42539
  }
42660
42540
  }
@@ -42687,100 +42567,6 @@ async function startMakerMcpServer() {
42687
42567
  ]
42688
42568
  };
42689
42569
  }
42690
- if (name === "maker_check_environment") {
42691
- return {
42692
- content: [
42693
- {
42694
- type: "text",
42695
- text: formatEnvironment()
42696
- }
42697
- ]
42698
- };
42699
- }
42700
- if (name === "maker_tap_login_start") {
42701
- const session = await startTapDeviceLogin();
42702
- return {
42703
- content: [
42704
- {
42705
- type: "text",
42706
- text: [
42707
- "TapTap login started",
42708
- "",
42709
- "请让用户打开下面链接或用 TapTap App 扫码授权:",
42710
- session.auth_url,
42711
- "",
42712
- `- environment: ${session.environment}`,
42713
- `- expires_at: ${session.expires_at}`,
42714
- `- interval_seconds: ${session.interval_seconds}`,
42715
- "",
42716
- "授权完成后调用 maker_tap_login_complete。"
42717
- ].join("\n")
42718
- }
42719
- ]
42720
- };
42721
- }
42722
- if (name === "maker_tap_login_complete") {
42723
- const args = request.params.arguments || {};
42724
- const auth = await completeTapDeviceLogin({
42725
- deviceCode: args.device_code,
42726
- maxAttempts: args.max_attempts
42727
- });
42728
- return {
42729
- content: [
42730
- {
42731
- type: "text",
42732
- text: [
42733
- "✓ TapTap login completed",
42734
- "",
42735
- `- kid: ${mask2(auth.kid)}`,
42736
- `- token_type: ${auth.token_type}`,
42737
- `- mac_algorithm: ${auth.mac_algorithm}`,
42738
- `- saved: ${getTapAuthPath()}`,
42739
- "",
42740
- "如果还未保存 Maker PAT,下一步调用 maker_exchange_pat。"
42741
- ].join("\n")
42742
- }
42743
- ]
42744
- };
42745
- }
42746
- if (name === "maker_exchange_jwt") {
42747
- const args = request.params.arguments || {};
42748
- if (!args.manual_jwt && !loadJwt() && !getMakerJwtExchangeUrl()) {
42749
- return {
42750
- isError: true,
42751
- content: [
42752
- {
42753
- type: "text",
42754
- text: [
42755
- "Maker JWT is required before listing apps or cloning projects.",
42756
- "",
42757
- formatBrowserJwtGuide()
42758
- ].join("\n")
42759
- }
42760
- ]
42761
- };
42762
- }
42763
- const jwt2 = await exchangeSavedTapAuthForMakerJwt({
42764
- manualJwt: args.manual_jwt
42765
- });
42766
- return {
42767
- content: [
42768
- {
42769
- type: "text",
42770
- text: [
42771
- "✓ Maker JWT ready",
42772
- "",
42773
- `- jwt: ${mask2(jwt2.token)}`,
42774
- `- user_id: ${jwt2.user_id || "(unknown)"}`,
42775
- `- implementation: ${getMakerJwtExchangeUrl() ? "remote_exchange" : "temporary_cached_or_manual_jwt"}`,
42776
- `- saved: ${getJwtPath()}`,
42777
- "",
42778
- "下一步调用 maker_list_apps。"
42779
- ].join("\n")
42780
- }
42781
- ]
42782
- };
42783
- }
42784
42570
  if (name === "maker_exchange_pat") {
42785
42571
  const args = request.params.arguments || {};
42786
42572
  if (!args.manual_pat) {
@@ -42835,8 +42621,7 @@ async function startMakerMcpServer() {
42835
42621
  if (name === "maker_list_apps") {
42836
42622
  const args = request.params.arguments || {};
42837
42623
  const projects = await listMakerProjects({
42838
- pat: args.pat,
42839
- jwt: args.jwt
42624
+ pat: args.pat
42840
42625
  });
42841
42626
  return {
42842
42627
  content: [
@@ -42847,16 +42632,6 @@ async function startMakerMcpServer() {
42847
42632
  ]
42848
42633
  };
42849
42634
  }
42850
- if (name === "maker_setup_guide") {
42851
- return {
42852
- content: [
42853
- {
42854
- type: "text",
42855
- text: formatIdentifyHint()
42856
- }
42857
- ]
42858
- };
42859
- }
42860
42635
  if (name === "maker_clone_to_current_directory") {
42861
42636
  const args = request.params.arguments || {};
42862
42637
  if (!args.app_id) {
@@ -42876,8 +42651,6 @@ async function startMakerMcpServer() {
42876
42651
  targetDir,
42877
42652
  pat: args.pat,
42878
42653
  userId: args.user_id,
42879
- jwt: args.jwt,
42880
- forcePat: args.force_pat === true,
42881
42654
  sceEndpoint: process.env.SCE_MCP_URL,
42882
42655
  onProgress: progressReporter.report
42883
42656
  });
@@ -42905,26 +42678,21 @@ async function startMakerMcpServer() {
42905
42678
  ]
42906
42679
  };
42907
42680
  }
42908
- if (name === "maker_push_current_directory" || name === "maker_submit_current_directory") {
42681
+ if (name === "maker_submit_current_directory") {
42909
42682
  const args = request.params.arguments || {};
42910
42683
  const targetDir = args.target_dir || process.cwd();
42911
42684
  const progressReporter = createToolProgressReporter(
42912
42685
  (_b = request.params._meta) == null ? void 0 : _b.progressToken,
42913
42686
  extra,
42914
- "Maker push"
42687
+ "Maker submit"
42915
42688
  );
42916
42689
  let result;
42917
42690
  let progressSummary;
42918
42691
  try {
42919
- result = await pushMakerProject({
42920
- cwd: targetDir,
42692
+ result = await pushThenBuildCurrentDirectory({
42693
+ targetDir,
42921
42694
  message: args.message,
42922
- branch: args.branch,
42923
42695
  files: args.files,
42924
- allowEmpty: args.allow_empty === true,
42925
- pat: args.pat,
42926
- jwt: args.jwt,
42927
- forcePat: args.force_pat === true,
42928
42696
  onProgress: progressReporter.report
42929
42697
  });
42930
42698
  progressSummary = progressReporter.finish();
@@ -42941,25 +42709,6 @@ async function startMakerMcpServer() {
42941
42709
  ]
42942
42710
  };
42943
42711
  }
42944
- if (name === "maker_configure_remote_proxy") {
42945
- const args = request.params.arguments || {};
42946
- const result = configureRemoteProxy({
42947
- targetDir: args.target_dir || process.cwd(),
42948
- serverUrl: args.server_url,
42949
- env: args.env,
42950
- mcpName: args.mcp_name,
42951
- useNpx: args.use_npx === true,
42952
- pkg: args.pkg
42953
- });
42954
- return {
42955
- content: [
42956
- {
42957
- type: "text",
42958
- text: formatRemoteProxyResult(result)
42959
- }
42960
- ]
42961
- };
42962
- }
42963
42712
  if (name === "maker_build_current_directory") {
42964
42713
  const args = request.params.arguments || {};
42965
42714
  const progressReporter = createToolProgressReporter(
@@ -42980,6 +42729,9 @@ async function startMakerMcpServer() {
42980
42729
  serverUrl: args.server_url,
42981
42730
  env: args.env,
42982
42731
  timeoutMs: args.timeout_ms,
42732
+ confirmRemoteBuildWithoutSubmit: args.confirm_remote_build_without_submit,
42733
+ submitLocalChangesBeforeBuild: args.submit_local_changes_before_build,
42734
+ rememberBuildSubmitPreference: args.remember_build_submit_preference,
42983
42735
  onProgress: progressReporter.report
42984
42736
  });
42985
42737
  progressSummary = progressReporter.finish();
@@ -43035,19 +42787,21 @@ async function formatStatus() {
43035
42787
  ].join("\n");
43036
42788
  }
43037
42789
  }
43038
- const tapSession = loadTapDeviceSession();
43039
42790
  const git = checkGitEnvironment();
43040
42791
  const projectSection = identify.projectId ? [
43041
42792
  "当前目录已绑定 Maker 项目。",
43042
- "如果用户要求“帮我提交代码 / 提交并推送 / push / 帮我提交代码到maker / 帮我提交代码到taptap制造 / 帮我提交代码到tap制造 / 帮我提交代码到tap”,必须调用 maker_submit_current_directory 或 maker_push_current_directory。",
43043
- "不要套用本地通用 Git skill 的任务号、默认分支保护、新建分支规则;Maker push 按远端 Maker 仓库当前分支直接提交并推送。"
42793
+ "如果用户要求“帮我提交代码 / 提交并推送 / push / 帮我提交代码到maker / 帮我提交代码到taptap制造 / 帮我提交代码到tap制造 / 帮我提交代码到tap”,必须调用 maker_submit_current_directory;提交/推送成功后工具会继续执行远端 build。",
42794
+ "如果用户要求“构建 / build / 重新构建 / 查看结果 / 预览 / 跑一下 / 验证一下”,必须先经过 maker_build_current_directory 的本地改动强制检查;有本地改动时不要静默构建云端旧版本,应询问用户是否提交。",
42795
+ "优先选项文案应是“提交本地改动并触发构建(以后都是如此)”;用户选择后再次调用 maker_build_current_directory,并设置 submit_local_changes_before_build=true 和 remember_build_submit_preference=true。",
42796
+ "Maker 构建入口负责完整执行 commit + push + build;保存偏好后,后续构建遇到本地改动会自动提交并继续构建。",
42797
+ "用户明确说不提交、直接构建云端版本时,才允许调用 maker_build_current_directory 并设置 confirm_remote_build_without_submit=true。",
42798
+ "不要套用本地通用 Git skill 的任务号、默认分支保护、新建分支规则;Maker 提交流程按远端 Maker 仓库当前分支直接提交并推送。"
43044
42799
  ].join("\n") : pat ? await formatAutoProjectListFromPat() : formatIdentifyHint();
43045
42800
  return [
43046
42801
  "TapTap Maker MCP status",
43047
42802
  "",
43048
42803
  `- version: ${VERSION}`,
43049
42804
  `- tap_auth: ${tapAuth ? "found" : "missing"} (${getTapAuthPath()})`,
43050
- `- tap_login_session: ${tapSession ? "found" : "missing"} (${getTapDeviceSessionPath()})`,
43051
42805
  `- pat: ${pat ? "found" : "missing"} (${getPatPath()})`,
43052
42806
  `- project_source: ${identify.source}`,
43053
42807
  `- project_id: ${identify.projectId || "(none)"}`,
@@ -43069,6 +42823,19 @@ async function formatStatus() {
43069
42823
  projectSection
43070
42824
  ].filter(Boolean).join("\n");
43071
42825
  }
42826
+ function rememberBuildSubmitPreference(targetDir) {
42827
+ const identify = identifyMakerProject({ cwd: targetDir });
42828
+ if (!identify.projectRoot || !identify.projectId) {
42829
+ throw new Error(
42830
+ `${targetDir} is not bound to a Maker project. Cannot save build submit preference.`
42831
+ );
42832
+ }
42833
+ saveProjectConfig(identify.projectRoot, {
42834
+ ...identify.config || { project_id: identify.projectId },
42835
+ project_id: identify.projectId,
42836
+ build_local_changes_policy: "auto_submit"
42837
+ });
42838
+ }
43072
42839
  async function formatAutoProjectListFromPat() {
43073
42840
  try {
43074
42841
  const projects = await listMakerProjects();
@@ -43086,18 +42853,6 @@ async function formatAutoProjectListFromPat() {
43086
42853
  ].join("\n");
43087
42854
  }
43088
42855
  }
43089
- function formatEnvironment() {
43090
- const git = checkGitEnvironment();
43091
- return [
43092
- "TapTap Maker MCP environment",
43093
- "",
43094
- `- version: ${VERSION}`,
43095
- `- node_version: ${process.version}`,
43096
- formatGitEnvironmentStatus(git),
43097
- "",
43098
- git.installed ? "Git 已可用,可以继续 Maker 登录、列出 app、clone 或 push 流程。" : "Git 未可用。安装并验证 Git 前,Maker MCP 不会执行 clone、fetch、commit 或 push。"
43099
- ].join("\n");
43100
- }
43101
42856
  function mask2(value) {
43102
42857
  if (value.length <= 12) {
43103
42858
  return "***";
@@ -43153,9 +42908,7 @@ function createRemoteProxyContext(options) {
43153
42908
  const projectId = (projectConfig == null ? void 0 : projectConfig.project_id) || identify.projectId;
43154
42909
  const tapAuth = loadTapAuth();
43155
42910
  if (!tapAuth) {
43156
- throw new Error(
43157
- "Tap auth not found. Run maker_tap_login_start and maker_tap_login_complete first."
43158
- );
42911
+ throw new Error("Tap auth not found. Run maker_exchange_pat with a valid Maker PAT first.");
43159
42912
  }
43160
42913
  let userId = projectConfig == null ? void 0 : projectConfig.user_id;
43161
42914
  if (!userId) {
@@ -43208,35 +42961,6 @@ function createRemoteProxyContext(options) {
43208
42961
  }
43209
42962
  };
43210
42963
  }
43211
- function configureRemoteProxy(options) {
43212
- const mcpName = options.mcpName || DEFAULT_PROXY_MCP_NAME;
43213
- const proxy = createRemoteProxyContext(options);
43214
- const mcpJsonPath = path9.join(proxy.projectRoot, ".mcp.json");
43215
- const mcpJson = readMcpJson(mcpJsonPath);
43216
- mcpJson.mcpServers = {
43217
- ...mcpJson.mcpServers || {},
43218
- [mcpName]: {
43219
- command: proxy.command,
43220
- args: proxy.args,
43221
- env: proxy.envVars
43222
- }
43223
- };
43224
- fs6.writeFileSync(mcpJsonPath, JSON.stringify(mcpJson, null, 2) + "\n", "utf8");
43225
- excludeProjectMcpJson(proxy.projectRoot);
43226
- return {
43227
- mcpJsonPath,
43228
- projectRoot: proxy.projectRoot,
43229
- mcpName,
43230
- serverUrl: proxy.serverUrl,
43231
- env: proxy.env,
43232
- projectId: proxy.projectId,
43233
- projectPath: proxy.projectPath,
43234
- userId: proxy.userId,
43235
- command: proxy.command,
43236
- args: proxy.args,
43237
- envVars: proxy.envVars
43238
- };
43239
- }
43240
42964
  function resolveLocalProxyBundle(options) {
43241
42965
  const currentModuleUrl = (options == null ? void 0 : options.currentModuleUrl) || (typeof __MAKER_BUNDLE_URL__ !== "undefined" ? __MAKER_BUNDLE_URL__ : void 0);
43242
42966
  const currentModuleDir = currentModuleUrl ? path9.dirname(fileURLToPath(currentModuleUrl)) : "";
@@ -43255,70 +42979,6 @@ function resolveLocalProxyBundle(options) {
43255
42979
  }
43256
42980
  throw new Error(`MCP proxy bundle not found. Checked: ${candidates.join(", ")}`);
43257
42981
  }
43258
- function readMcpJson(filePath) {
43259
- if (!fs6.existsSync(filePath)) {
43260
- return {};
43261
- }
43262
- try {
43263
- return JSON.parse(fs6.readFileSync(filePath, "utf8"));
43264
- } catch (error2) {
43265
- throw new Error(
43266
- `Failed to parse existing .mcp.json: ${error2 instanceof Error ? error2.message : String(error2)}`
43267
- );
43268
- }
43269
- }
43270
- function excludeProjectMcpJson(projectRoot) {
43271
- const gitDir = path9.join(projectRoot, ".git");
43272
- if (!fs6.existsSync(gitDir)) {
43273
- return;
43274
- }
43275
- const infoDir = path9.join(gitDir, "info");
43276
- const excludePath = path9.join(infoDir, "exclude");
43277
- const entry = ".mcp.json";
43278
- fs6.mkdirSync(infoDir, { recursive: true });
43279
- const existing = fs6.existsSync(excludePath) ? fs6.readFileSync(excludePath, "utf8") : "";
43280
- const hasEntry = existing.split("\n").map((line) => line.trim()).includes(entry);
43281
- if (hasEntry) {
43282
- return;
43283
- }
43284
- const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
43285
- fs6.appendFileSync(excludePath, `${prefix}${entry}
43286
- `, "utf8");
43287
- }
43288
- function formatRemoteProxyResult(result) {
43289
- return [
43290
- "✓ Remote Maker MCP proxy configured",
43291
- "",
43292
- `- mcp_name: ${result.mcpName}`,
43293
- `- project_root: ${result.projectRoot}`,
43294
- `- mcp_json: ${result.mcpJsonPath}`,
43295
- `- server_url: ${result.serverUrl}`,
43296
- `- env: ${result.env}`,
43297
- `- project_id: ${result.projectId}`,
43298
- `- project_path: ${result.projectPath}`,
43299
- `- user_id: ${result.userId || "(unknown)"}`,
43300
- `- command: ${result.command}`,
43301
- `- args: ${formatProxyArgs(result.args)}`,
43302
- `- env: ${formatProxyEnv(result.envVars)}`,
43303
- "",
43304
- "已将 .mcp.json 写入本地 .git/info/exclude,避免误提交包含认证信息的本地 MCP 配置。",
43305
- "下一步:请重启当前 Claude/Codex 对话或重新加载 MCP servers,然后远端 taptap-proxy 暴露的 build/构建 tools 才会出现。"
43306
- ].join("\n");
43307
- }
43308
- function formatProxyArgs(args) {
43309
- return args.map((arg) => {
43310
- if (arg.startsWith("{") && arg.includes("mac_key")) {
43311
- return "<proxy_cfg_with_auth>";
43312
- }
43313
- return arg;
43314
- }).join(" ");
43315
- }
43316
- function formatProxyEnv(envVars) {
43317
- if (!envVars) {
43318
- return "(none)";
43319
- }
43320
- return Object.keys(envVars).map((key) => `${key}=<redacted>`).join(" ");
43321
- }
43322
42982
  function createToolProgressReporter(progressToken, extra, operationName) {
43323
42983
  var _a2;
43324
42984
  const startedAt = Date.now();
@@ -43398,8 +43058,64 @@ function formatDuration(ms) {
43398
43058
  return `${minutes}m ${seconds}s`;
43399
43059
  }
43400
43060
  async function buildCurrentDirectory(options) {
43061
+ var _a2;
43062
+ const localChanges = await readMakerProjectLocalChanges(options.targetDir);
43063
+ if (localChanges.hasChanges && !options.confirmRemoteBuildWithoutSubmit) {
43064
+ const config2 = loadProjectConfig(localChanges.projectRoot);
43065
+ let buildLocalChangesPolicy = (config2 == null ? void 0 : config2.build_local_changes_policy) === "auto_submit" ? "auto_submit" : void 0;
43066
+ if ((config2 == null ? void 0 : config2.build_local_changes_policy) === "auto_submit" || options.submitLocalChangesBeforeBuild) {
43067
+ (_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
43068
+ progress: 0,
43069
+ total: 100,
43070
+ phase: "auto_submit",
43071
+ message: "Auto-submitting local Maker changes before build"
43072
+ });
43073
+ const submitResult = await (options.submitLocalChanges || pushMakerProject)({
43074
+ cwd: localChanges.projectRoot,
43075
+ onProgress: options.onProgress
43076
+ });
43077
+ if (options.rememberBuildSubmitPreference && !submitResult.failure) {
43078
+ rememberBuildSubmitPreference(localChanges.projectRoot);
43079
+ buildLocalChangesPolicy = "auto_submit";
43080
+ }
43081
+ if (submitResult.failure || !submitResult.pushed && submitResult.status !== "clean") {
43082
+ return {
43083
+ mode: "submit_failed_before_build",
43084
+ projectRoot: localChanges.projectRoot,
43085
+ projectId: (config2 == null ? void 0 : config2.project_id) || "unknown",
43086
+ submitResult,
43087
+ buildLocalChangesPolicy
43088
+ };
43089
+ }
43090
+ let buildResult;
43091
+ try {
43092
+ buildResult = await runRemoteBuildCurrentDirectory(options, localChanges.projectRoot);
43093
+ } catch (error2) {
43094
+ return {
43095
+ mode: "build_failed_after_submit",
43096
+ projectRoot: localChanges.projectRoot,
43097
+ projectId: (config2 == null ? void 0 : config2.project_id) || "unknown",
43098
+ submitResult,
43099
+ buildFailure: toMakerBuildFailure(error2),
43100
+ buildLocalChangesPolicy
43101
+ };
43102
+ }
43103
+ return {
43104
+ ...buildResult,
43105
+ submitResult,
43106
+ buildLocalChangesPolicy
43107
+ };
43108
+ }
43109
+ throw new Error(formatLocalChangesBeforeBuildMessage(localChanges.files));
43110
+ }
43111
+ return runRemoteBuildCurrentDirectory(options, options.targetDir);
43112
+ }
43113
+ async function runRemoteBuildCurrentDirectory(options, targetDir) {
43114
+ if (options.callRemoteBuild) {
43115
+ return options.callRemoteBuild(targetDir);
43116
+ }
43401
43117
  const proxy = createRemoteProxyContext({
43402
- targetDir: options.targetDir,
43118
+ targetDir,
43403
43119
  serverUrl: options.serverUrl,
43404
43120
  env: options.env
43405
43121
  });
@@ -43443,6 +43159,7 @@ async function buildCurrentDirectory(options) {
43443
43159
  }
43444
43160
  );
43445
43161
  return {
43162
+ mode: "remote_build",
43446
43163
  projectRoot: proxy.projectRoot,
43447
43164
  projectId: proxy.projectId,
43448
43165
  projectPath: proxy.projectPath,
@@ -43456,6 +43173,65 @@ async function buildCurrentDirectory(options) {
43456
43173
  await client.close();
43457
43174
  }
43458
43175
  }
43176
+ async function pushThenBuildCurrentDirectory(options) {
43177
+ const submitResult = await (options.pushLocalChanges || pushMakerProject)({
43178
+ cwd: options.targetDir,
43179
+ message: options.message,
43180
+ files: options.files,
43181
+ onProgress: options.onProgress
43182
+ });
43183
+ if (!submitResult.pushed) {
43184
+ return {
43185
+ targetDir: options.targetDir,
43186
+ submitResult
43187
+ };
43188
+ }
43189
+ let buildResult;
43190
+ try {
43191
+ buildResult = await runRemoteBuildCurrentDirectory(
43192
+ {
43193
+ targetDir: options.targetDir,
43194
+ callRemoteBuild: options.callRemoteBuild,
43195
+ onProgress: options.onProgress
43196
+ },
43197
+ options.targetDir
43198
+ );
43199
+ } catch (error2) {
43200
+ return {
43201
+ targetDir: options.targetDir,
43202
+ submitResult,
43203
+ buildFailure: toMakerBuildFailure(error2)
43204
+ };
43205
+ }
43206
+ return {
43207
+ targetDir: options.targetDir,
43208
+ submitResult,
43209
+ buildResult
43210
+ };
43211
+ }
43212
+ function toMakerBuildFailure(error2) {
43213
+ return {
43214
+ name: error2 instanceof Error ? error2.name : typeof error2,
43215
+ message: error2 instanceof Error ? error2.message : String(error2),
43216
+ ...error2 instanceof Error && error2.stack ? { stack: error2.stack } : {}
43217
+ };
43218
+ }
43219
+ function formatLocalChangesBeforeBuildMessage(files) {
43220
+ const visibleFiles = files.slice(0, 20);
43221
+ const hiddenCount = Math.max(0, files.length - visibleFiles.length);
43222
+ return [
43223
+ "Current Maker project has local changes that are not submitted.",
43224
+ "",
43225
+ "当前有本地修改还没有提交。直接构建只会构建 Maker 云端已有版本,可能看不到这些新修改。",
43226
+ "请先询问用户选择:",
43227
+ "- 提交本地改动并触发构建(以后都是如此):再次调用 maker_build_current_directory,并设置 submit_local_changes_before_build=true 和 remember_build_submit_preference=true;工具会先 commit + push,再继续执行远端 build 并返回构建结果。后续构建遇到本地改动会默认自动提交并继续构建。",
43228
+ "- 如果用户明确说不提交、直接构建云端版本,再调用 maker_build_current_directory,并设置 confirm_remote_build_without_submit=true。",
43229
+ "",
43230
+ "local_changes:",
43231
+ ...visibleFiles.map((file2) => `- ${file2}`),
43232
+ ...hiddenCount > 0 ? [`- ... and ${hiddenCount} more`] : []
43233
+ ].join("\n");
43234
+ }
43459
43235
  function createBuildArgs(projectRoot, options) {
43460
43236
  const buildArgs = {};
43461
43237
  if (options.entry) {
@@ -43464,6 +43240,10 @@ function createBuildArgs(projectRoot, options) {
43464
43240
  if (options.scriptsPath) {
43465
43241
  buildArgs.scriptsPath = options.scriptsPath;
43466
43242
  }
43243
+ if (!options.entry && !options.scriptsPath && !options.entryClient && !options.entryServer && !options.multiplayer && fs6.existsSync(path9.join(projectRoot, "scripts", "main.lua"))) {
43244
+ buildArgs.entry = "main.lua";
43245
+ buildArgs.scriptsPath = "scripts";
43246
+ }
43467
43247
  if (options.entryClient) {
43468
43248
  buildArgs.entry_client = options.entryClient;
43469
43249
  }
@@ -43507,52 +43287,151 @@ function formatRemoteToolResult(result) {
43507
43287
  }).join("\n");
43508
43288
  }
43509
43289
  function formatBuildResult(result, progressSummary) {
43510
- return [
43511
- "✓ Remote Maker build finished",
43290
+ if (result.mode === "submit_failed_before_build") {
43291
+ return [
43292
+ result.submitResult.pushed ? "✓ Maker project submitted; remote build was not started" : result.submitResult.status === "clean" ? "Maker project has no changes to submit; remote build was not started" : "✗ Maker project submit failed; remote build was not started",
43293
+ "",
43294
+ `- project_root: ${result.projectRoot}`,
43295
+ `- project_id: ${result.projectId}`,
43296
+ "- build_local_changes_policy: auto_submit",
43297
+ `- branch: ${result.submitResult.branch}`,
43298
+ `- status: ${result.submitResult.status}`,
43299
+ `- committed: ${result.submitResult.committed ? "yes" : "no"}`,
43300
+ result.submitResult.commitHash ? `- commit_hash: ${result.submitResult.commitHash}` : "",
43301
+ result.submitResult.message ? `- commit_message: ${result.submitResult.message}` : "",
43302
+ result.submitResult.ahead ? `- git_state: ${result.submitResult.ahead}` : "",
43303
+ ...formatProgressSummary(progressSummary),
43304
+ "",
43305
+ "note: Maker build was not started because submit did not produce a pushed state.",
43306
+ ...result.submitResult.failure ? ["", ...formatMakerFailureLines(result.submitResult.failure)] : []
43307
+ ].filter(Boolean).join("\n");
43308
+ }
43309
+ if (result.mode === "build_failed_after_submit") {
43310
+ return [
43311
+ "✗ Maker project submitted, but remote Maker build failed",
43312
+ "",
43313
+ `- project_root: ${result.projectRoot}`,
43314
+ `- project_id: ${result.projectId}`,
43315
+ result.buildLocalChangesPolicy ? `- build_local_changes_policy: ${result.buildLocalChangesPolicy}` : "",
43316
+ `- branch: ${result.submitResult.branch}`,
43317
+ `- status: ${result.submitResult.status}`,
43318
+ `- committed: ${result.submitResult.committed ? "yes" : "no"}`,
43319
+ result.submitResult.commitHash ? `- commit_hash: ${result.submitResult.commitHash}` : "",
43320
+ result.submitResult.message ? `- commit_message: ${result.submitResult.message}` : "",
43321
+ result.submitResult.ahead ? `- git_state: ${result.submitResult.ahead}` : "",
43322
+ ...formatProgressSummary(progressSummary),
43323
+ "",
43324
+ ...formatMakerBuildFailureLines(result.buildFailure)
43325
+ ].filter(Boolean).join("\n");
43326
+ }
43327
+ const submitLines = result.submitResult ? [
43328
+ "submit_result:",
43329
+ ` - branch: ${result.submitResult.branch}`,
43330
+ ` - status: ${result.submitResult.status}`,
43331
+ ` - committed: ${result.submitResult.committed ? "yes" : "no"}`,
43332
+ result.submitResult.commitHash ? ` - commit_hash: ${result.submitResult.commitHash}` : "",
43333
+ result.submitResult.message ? ` - commit_message: ${result.submitResult.message}` : "",
43334
+ result.submitResult.ahead ? ` - git_state: ${result.submitResult.ahead}` : "",
43335
+ ""
43336
+ ].filter(Boolean) : [];
43337
+ const lines = [
43338
+ result.submitResult ? "✓ Maker project submitted, then remote Maker build finished" : "✓ Remote Maker build finished",
43512
43339
  "",
43513
43340
  `- project_root: ${result.projectRoot}`,
43514
43341
  `- project_id: ${result.projectId}`,
43515
43342
  `- project_path: ${result.projectPath}`,
43516
43343
  `- server_url: ${result.serverUrl}`,
43517
- `- env: ${result.env}`,
43344
+ `- env: ${result.env}`
43345
+ ];
43346
+ if (result.buildLocalChangesPolicy) {
43347
+ lines.push(`- build_local_changes_policy: ${result.buildLocalChangesPolicy}`);
43348
+ }
43349
+ lines.push(
43518
43350
  `- timeout_ms: ${result.timeoutMs}`,
43519
43351
  `- build_args: ${JSON.stringify(result.buildArgs)}`,
43520
43352
  ...formatProgressSummary(progressSummary),
43521
- "",
43522
- "remote_result:",
43523
- indent(result.resultText)
43524
- ].join("\n");
43353
+ ""
43354
+ );
43355
+ if (submitLines.length > 0) {
43356
+ lines.push(...submitLines);
43357
+ }
43358
+ lines.push("remote_result:", indent(result.resultText));
43359
+ return lines.join("\n");
43525
43360
  }
43526
43361
  function formatPushResult(targetDir, result, progressSummary) {
43362
+ const submitResult = result.submitResult;
43527
43363
  const lines = [
43528
- result.pushed ? "✓ Maker project pushed" : result.status === "clean" ? "Maker project has no changes to push" : "✗ Maker project push failed",
43364
+ result.buildResult ? "✓ Maker project pushed, then remote Maker build finished" : submitResult.pushed ? "✗ Maker project pushed, but remote build result is missing" : submitResult.status === "clean" ? "Maker project has no changes to push" : "✗ Maker project push failed",
43529
43365
  "",
43530
43366
  `- target_dir: ${targetDir}`,
43531
- `- branch: ${result.branch}`,
43532
- `- status: ${result.status}`,
43533
- `- committed: ${result.committed ? "yes" : "no"}`,
43534
- result.commitHash ? `- commit_hash: ${result.commitHash}` : "",
43535
- result.message ? `- commit_message: ${result.message}` : "",
43536
- result.ahead ? `- git_state: ${result.ahead}` : "",
43367
+ `- branch: ${submitResult.branch}`,
43368
+ `- status: ${submitResult.status}`,
43369
+ `- committed: ${submitResult.committed ? "yes" : "no"}`,
43370
+ submitResult.commitHash ? `- commit_hash: ${submitResult.commitHash}` : "",
43371
+ submitResult.message ? `- commit_message: ${submitResult.message}` : "",
43372
+ submitResult.ahead ? `- git_state: ${submitResult.ahead}` : "",
43537
43373
  ...formatProgressSummary(progressSummary)
43538
43374
  ].filter(Boolean);
43539
- if (!result.failure) {
43540
- return lines.join("\n");
43375
+ if (result.buildResult) {
43376
+ return [
43377
+ ...lines,
43378
+ "",
43379
+ "remote_build:",
43380
+ indent(
43381
+ [
43382
+ `- project_id: ${result.buildResult.projectId}`,
43383
+ `- project_path: ${result.buildResult.projectPath}`,
43384
+ `- server_url: ${result.buildResult.serverUrl}`,
43385
+ `- env: ${result.buildResult.env}`,
43386
+ `- timeout_ms: ${result.buildResult.timeoutMs}`,
43387
+ `- build_args: ${JSON.stringify(result.buildResult.buildArgs)}`,
43388
+ "",
43389
+ "remote_result:",
43390
+ indent(result.buildResult.resultText)
43391
+ ].join("\n")
43392
+ )
43393
+ ].join("\n");
43541
43394
  }
43395
+ if (result.buildFailure) {
43396
+ return [
43397
+ ...lines,
43398
+ "",
43399
+ "note: Maker project was pushed successfully, but remote build failed.",
43400
+ "",
43401
+ ...formatMakerBuildFailureLines(result.buildFailure)
43402
+ ].join("\n");
43403
+ }
43404
+ if (!submitResult.failure) {
43405
+ return [
43406
+ ...lines,
43407
+ "",
43408
+ submitResult.pushed ? "note: This is an internal contract error: pushed=true requires remote_build or build_failure." : "note: Maker build was not started because no push was performed."
43409
+ ].join("\n");
43410
+ }
43411
+ return [...lines, "", ...formatMakerFailureLines(submitResult.failure)].filter(Boolean).join("\n");
43412
+ }
43413
+ function formatMakerBuildFailureLines(failure) {
43414
+ return [
43415
+ "build_failure:",
43416
+ `- error_name: ${failure.name}`,
43417
+ `- message: ${failure.message}`,
43418
+ failure.stack ? `- stack:
43419
+ ${indent(failure.stack)}` : ""
43420
+ ].filter(Boolean);
43421
+ }
43422
+ function formatMakerFailureLines(failure) {
43542
43423
  return [
43543
- ...lines,
43544
- "",
43545
43424
  "failure:",
43546
- `- stage: ${result.failure.stage}`,
43547
- `- classification: ${result.failure.classification}`,
43548
- `- exit_code: ${result.failure.exitCode ?? "(none)"}`,
43549
- result.failure.command ? `- command: ${result.failure.command}` : "",
43550
- result.failure.stderr ? `- stderr:
43551
- ${indent(result.failure.stderr)}` : "",
43552
- result.failure.stdout ? `- stdout:
43553
- ${indent(result.failure.stdout)}` : "",
43554
- `- next_action: ${result.failure.nextAction}`
43555
- ].filter(Boolean).join("\n");
43425
+ `- stage: ${failure.stage}`,
43426
+ `- classification: ${failure.classification}`,
43427
+ `- exit_code: ${failure.exitCode ?? "(none)"}`,
43428
+ failure.command ? `- command: ${failure.command}` : "",
43429
+ failure.stderr ? `- stderr:
43430
+ ${indent(failure.stderr)}` : "",
43431
+ failure.stdout ? `- stdout:
43432
+ ${indent(failure.stdout)}` : "",
43433
+ `- next_action: ${failure.nextAction}`
43434
+ ].filter(Boolean);
43556
43435
  }
43557
43436
  function formatToolException(toolName, error2) {
43558
43437
  const message = error2 instanceof Error ? error2.message : String(error2);
@@ -43579,7 +43458,7 @@ function formatToolException(toolName, error2) {
43579
43458
  "debug:",
43580
43459
  stack ? indent(stack) : indent(message),
43581
43460
  "",
43582
- "next_action: 请把上面的完整错误反馈给开发者;如果本地已有 commit 但 push 未完成,不要重复 commit,直接重试 maker_push_current_directory。"
43461
+ "next_action: 请把上面的完整错误反馈给开发者;如果本地已有 commit 但 push 未完成,不要重复 commit,直接重试 maker_submit_current_directory。"
43583
43462
  ].join("\n");
43584
43463
  }
43585
43464
  function indent(value) {
package/dist/proxy.js CHANGED
@@ -29137,7 +29137,7 @@ var LogWriter = class {
29137
29137
  };
29138
29138
 
29139
29139
  // src/mcp-proxy/proxy.ts
29140
- var VERSION = true ? "1.22.0-beta.6" : "dev";
29140
+ var VERSION = true ? "1.22.0-beta.8" : "dev";
29141
29141
  var TapTapMCPProxy = class {
29142
29142
  constructor(config2) {
29143
29143
  this.connected = false;
package/dist/server.js CHANGED
@@ -6078,7 +6078,7 @@ class MultiplayerManager {
6078
6078
  // 导出
6079
6079
  // export default MultiplayerManager;
6080
6080
  // module.exports = MultiplayerManager;
6081
- // window.MultiplayerManager = MultiplayerManager;`}]}}};var ws;ws="1.22.0-beta.6";async function MRe(){return Go(Rm,"api_event_relations")}async function NRe(){return Go(Rm,"protocol_template")}async function SD(){return Go(Rm,"complete_example")}async function jRe(){return`# TapTap 多人联机集成指南
6081
+ // window.MultiplayerManager = MultiplayerManager;`}]}}};var ws;ws="1.22.0-beta.8";async function MRe(){return Go(Rm,"api_event_relations")}async function NRe(){return Go(Rm,"protocol_template")}async function SD(){return Go(Rm,"complete_example")}async function jRe(){return`# TapTap 多人联机集成指南
6082
6082
 
6083
6083
  ---
6084
6084
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taptap/instant-games-open-mcp",
3
- "version": "1.22.0-beta.6",
3
+ "version": "1.22.0-beta.8",
4
4
  "type": "module",
5
5
  "description": "TapTap Open API MCP Server - Documentation and Management APIs for TapTap Minigame and H5 Games (Leaderboard, and more features coming)",
6
6
  "main": "dist/server.js",