@leonxin/meetgames 0.1.8 → 0.1.11

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.
Files changed (285) hide show
  1. package/.agents/skills/meet-sdk-regression/SKILL.md +93 -0
  2. package/.cursor/mcp.example.json +16 -0
  3. package/.cursor/mcp.json +11 -0
  4. package/.cursor/skills/meetgames-mcp/SKILL.md +48 -0
  5. package/.vite/vitest/results.json +1 -0
  6. package/README.md +31 -8
  7. package/dist/aab-converter/aab-entry.d.ts +3 -0
  8. package/dist/aab-converter/aab-entry.d.ts.map +1 -0
  9. package/dist/aab-converter/aab-entry.js +49 -0
  10. package/dist/aab-converter/aab-entry.js.map +1 -0
  11. package/dist/aab-converter/apksExtractor.d.ts +2 -0
  12. package/dist/aab-converter/apksExtractor.d.ts.map +1 -0
  13. package/dist/aab-converter/apksExtractor.js +108 -0
  14. package/dist/aab-converter/apksExtractor.js.map +1 -0
  15. package/dist/aab-converter/bundletoolRunner.d.ts +15 -0
  16. package/dist/aab-converter/bundletoolRunner.d.ts.map +1 -0
  17. package/dist/aab-converter/bundletoolRunner.js +46 -0
  18. package/dist/aab-converter/bundletoolRunner.js.map +1 -0
  19. package/dist/aab-converter/cliArgs.d.ts +27 -0
  20. package/dist/aab-converter/cliArgs.d.ts.map +1 -0
  21. package/dist/aab-converter/cliArgs.js +170 -0
  22. package/dist/aab-converter/cliArgs.js.map +1 -0
  23. package/dist/aab-converter/convertAabToApk.d.ts +7 -0
  24. package/dist/aab-converter/convertAabToApk.d.ts.map +1 -0
  25. package/dist/aab-converter/convertAabToApk.js +69 -0
  26. package/dist/aab-converter/convertAabToApk.js.map +1 -0
  27. package/dist/aab-converter/resourcePaths.d.ts +4 -0
  28. package/dist/aab-converter/resourcePaths.d.ts.map +1 -0
  29. package/dist/aab-converter/resourcePaths.js +42 -0
  30. package/dist/aab-converter/resourcePaths.js.map +1 -0
  31. package/dist/aab-converter/signingOptions.d.ts +9 -0
  32. package/dist/aab-converter/signingOptions.d.ts.map +1 -0
  33. package/dist/aab-converter/signingOptions.js +21 -0
  34. package/dist/aab-converter/signingOptions.js.map +1 -0
  35. package/dist/aab-converter/types.d.ts +24 -0
  36. package/dist/aab-converter/types.d.ts.map +1 -0
  37. package/dist/aab-converter/types.js +2 -0
  38. package/dist/aab-converter/types.js.map +1 -0
  39. package/dist/android/adapter.d.ts.map +1 -1
  40. package/dist/android/adapter.js +2 -2
  41. package/dist/android/adapter.js.map +1 -1
  42. package/dist/android/detect.d.ts +2 -2
  43. package/dist/android/detect.d.ts.map +1 -1
  44. package/dist/android/detect.js +36 -8
  45. package/dist/android/detect.js.map +1 -1
  46. package/dist/cli.d.ts.map +1 -1
  47. package/dist/cli.js +157 -31
  48. package/dist/cli.js.map +1 -1
  49. package/dist/config/meetSdkDefaultConfig.d.ts +19 -2
  50. package/dist/config/meetSdkDefaultConfig.d.ts.map +1 -1
  51. package/dist/config/meetSdkDefaultConfig.js +67 -5
  52. package/dist/config/meetSdkDefaultConfig.js.map +1 -1
  53. package/dist/config/meetSdkIosConfig.d.ts +21 -0
  54. package/dist/config/meetSdkIosConfig.d.ts.map +1 -0
  55. package/dist/config/meetSdkIosConfig.js +66 -0
  56. package/dist/config/meetSdkIosConfig.js.map +1 -0
  57. package/dist/config/meetSdkRemoteConfig.d.ts +18 -1
  58. package/dist/config/meetSdkRemoteConfig.d.ts.map +1 -1
  59. package/dist/config/meetSdkRemoteConfig.js +61 -25
  60. package/dist/config/meetSdkRemoteConfig.js.map +1 -1
  61. package/dist/contracts/types.d.ts +19 -6
  62. package/dist/contracts/types.d.ts.map +1 -1
  63. package/dist/core/doctor.d.ts +17 -0
  64. package/dist/core/doctor.d.ts.map +1 -0
  65. package/dist/core/doctor.js +444 -0
  66. package/dist/core/doctor.js.map +1 -0
  67. package/dist/core/pipeline.d.ts.map +1 -1
  68. package/dist/core/pipeline.js +0 -15
  69. package/dist/core/pipeline.js.map +1 -1
  70. package/dist/core/platform.d.ts +12 -0
  71. package/dist/core/platform.d.ts.map +1 -0
  72. package/dist/core/platform.js +40 -0
  73. package/dist/core/platform.js.map +1 -0
  74. package/dist/core/reporter.js +1 -1
  75. package/dist/core/reporter.js.map +1 -1
  76. package/dist/core/workspace.d.ts +2 -2
  77. package/dist/core/workspace.d.ts.map +1 -1
  78. package/dist/core/workspace.js +4 -5
  79. package/dist/core/workspace.js.map +1 -1
  80. package/dist/index.d.ts +3 -1
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +3 -1
  83. package/dist/index.js.map +1 -1
  84. package/dist/ios/channelConfig.d.ts +1 -0
  85. package/dist/ios/channelConfig.d.ts.map +1 -1
  86. package/dist/ios/channelConfig.js +82 -0
  87. package/dist/ios/channelConfig.js.map +1 -1
  88. package/dist/ios/codeUtils.d.ts +1 -0
  89. package/dist/ios/codeUtils.d.ts.map +1 -1
  90. package/dist/ios/codeUtils.js +11 -2
  91. package/dist/ios/codeUtils.js.map +1 -1
  92. package/dist/ios/detect.d.ts +2 -2
  93. package/dist/ios/detect.d.ts.map +1 -1
  94. package/dist/ios/detect.js +49 -10
  95. package/dist/ios/detect.js.map +1 -1
  96. package/dist/ios/entitlements.d.ts +4 -0
  97. package/dist/ios/entitlements.d.ts.map +1 -0
  98. package/dist/ios/entitlements.js +53 -0
  99. package/dist/ios/entitlements.js.map +1 -0
  100. package/dist/ios/fileManager.d.ts.map +1 -1
  101. package/dist/ios/fileManager.js +3 -2
  102. package/dist/ios/fileManager.js.map +1 -1
  103. package/dist/ios/infoPlist.d.ts +1 -1
  104. package/dist/ios/infoPlist.d.ts.map +1 -1
  105. package/dist/ios/infoPlist.js.map +1 -1
  106. package/dist/ios/integrate.d.ts.map +1 -1
  107. package/dist/ios/integrate.js +211 -36
  108. package/dist/ios/integrate.js.map +1 -1
  109. package/dist/ios/pbxprojEditor.d.ts +2 -0
  110. package/dist/ios/pbxprojEditor.d.ts.map +1 -1
  111. package/dist/ios/pbxprojEditor.js +179 -1
  112. package/dist/ios/pbxprojEditor.js.map +1 -1
  113. package/dist/ios/pluginConfig.d.ts +1 -0
  114. package/dist/ios/pluginConfig.d.ts.map +1 -1
  115. package/dist/ios/pluginConfig.js +36 -4
  116. package/dist/ios/pluginConfig.js.map +1 -1
  117. package/dist/ios/sdkBundle.d.ts +1 -1
  118. package/dist/ios/sdkBundle.d.ts.map +1 -1
  119. package/dist/ios/sdkBundle.js +7 -5
  120. package/dist/ios/sdkBundle.js.map +1 -1
  121. package/dist/ios/template.d.ts +1 -0
  122. package/dist/ios/template.d.ts.map +1 -1
  123. package/dist/ios/template.js +14 -1
  124. package/dist/ios/template.js.map +1 -1
  125. package/dist/ios/types.d.ts +2 -2
  126. package/dist/ios/types.d.ts.map +1 -1
  127. package/dist/mcp/server.d.ts.map +1 -1
  128. package/dist/mcp/server.js +14 -13
  129. package/dist/mcp/server.js.map +1 -1
  130. package/dist/mcp/service.d.ts +8 -6
  131. package/dist/mcp/service.d.ts.map +1 -1
  132. package/dist/mcp/service.js +34 -14
  133. package/dist/mcp/service.js.map +1 -1
  134. package/dist/ops/handlers.d.ts.map +1 -1
  135. package/dist/ops/handlers.js +10 -4
  136. package/dist/ops/handlers.js.map +1 -1
  137. package/dist/remote/sdkHomeDownload.d.ts +65 -0
  138. package/dist/remote/sdkHomeDownload.d.ts.map +1 -0
  139. package/dist/remote/sdkHomeDownload.js +208 -0
  140. package/dist/remote/sdkHomeDownload.js.map +1 -0
  141. package/dist/remote/topsdkDownloadSdkConfig.d.ts.map +1 -1
  142. package/dist/remote/topsdkDownloadSdkConfig.js +11 -1
  143. package/dist/remote/topsdkDownloadSdkConfig.js.map +1 -1
  144. package/dist/shared/errors.d.ts +7 -0
  145. package/dist/shared/errors.d.ts.map +1 -0
  146. package/dist/shared/errors.js +16 -0
  147. package/dist/shared/errors.js.map +1 -0
  148. package/dist/shared/fileUtils.d.ts +5 -0
  149. package/dist/shared/fileUtils.d.ts.map +1 -0
  150. package/dist/shared/fileUtils.js +35 -0
  151. package/dist/shared/fileUtils.js.map +1 -0
  152. package/dist/shared/logger.d.ts +10 -0
  153. package/dist/shared/logger.d.ts.map +1 -0
  154. package/dist/shared/logger.js +37 -0
  155. package/dist/shared/logger.js.map +1 -0
  156. package/dist/shared/pathUtils.d.ts +4 -0
  157. package/dist/shared/pathUtils.d.ts.map +1 -0
  158. package/dist/shared/pathUtils.js +22 -0
  159. package/dist/shared/pathUtils.js.map +1 -0
  160. package/dist/shared/processRunner.d.ts +12 -0
  161. package/dist/shared/processRunner.d.ts.map +1 -0
  162. package/dist/shared/processRunner.js +31 -0
  163. package/dist/shared/processRunner.js.map +1 -0
  164. package/docs/AAB_CONVERTER_CLI_PLAN.md +392 -0
  165. package/docs/API.md +246 -32
  166. package/docs/CLI.md +292 -0
  167. package/docs/INTEGRATION.md +116 -0
  168. package/docs/MCP.md +86 -0
  169. package/docs/README.md +19 -10
  170. package/docs/{api → archive/api}/downloadSDKConfig.md +8 -6
  171. package/docs/{api → archive/api}/getChannelConfig-meetgames.md +1 -1
  172. package/docs/archive/ios-migration.md +2139 -0
  173. package/docs/{ → archive/product/}/346/212/200/346/234/257/346/226/271/346/241/210/350/260/203/347/240/224.md +7 -7
  174. package/docs/{ → archive/product/}/351/234/200/346/261/202/346/226/207/346/241/243.md +15 -14
  175. package/logs/convert-20260622-155037.log +5 -0
  176. package/logs/convert-20260622-155226.log +6 -0
  177. package/meetsdk-android.json +2 -1
  178. package/meetsdk-ios.json +15 -0
  179. package/package.json +10 -36
  180. package/scripts/package-aab-cli-win.mjs +193 -0
  181. package/src/aab-converter/aab-entry.ts +48 -0
  182. package/src/aab-converter/apksExtractor.ts +119 -0
  183. package/src/aab-converter/bundletoolRunner.ts +63 -0
  184. package/src/aab-converter/cliArgs.ts +194 -0
  185. package/src/aab-converter/convertAabToApk.ts +81 -0
  186. package/src/aab-converter/resourcePaths.ts +43 -0
  187. package/src/aab-converter/signingOptions.ts +29 -0
  188. package/src/aab-converter/types.ts +26 -0
  189. package/src/android/adapter.ts +9 -0
  190. package/src/android/assembleIntegrationJson.ts +33 -0
  191. package/src/android/detect.ts +132 -0
  192. package/src/android/downloadGoogleServicesJson.ts +56 -0
  193. package/src/android/gradle.ts +116 -0
  194. package/src/android/manifest.ts +50 -0
  195. package/src/android/meetSdkRemoteGradle.ts +837 -0
  196. package/src/cli.ts +488 -0
  197. package/src/config/fetchConfigWrite.ts +30 -0
  198. package/src/config/loadAndroidIntegration.ts +41 -0
  199. package/src/config/loadManifest.ts +40 -0
  200. package/src/config/meetSdkDefaultConfig.ts +99 -0
  201. package/src/config/meetSdkIosConfig.ts +87 -0
  202. package/src/config/meetSdkRemoteConfig.ts +1211 -0
  203. package/src/config/topsdkFeatureModules.ts +92 -0
  204. package/src/contracts/types.ts +121 -0
  205. package/src/core/doctor.ts +485 -0
  206. package/src/core/patch.ts +64 -0
  207. package/src/core/pipeline.ts +107 -0
  208. package/src/core/platform.ts +47 -0
  209. package/src/core/previewPatches.ts +23 -0
  210. package/src/core/reporter.ts +24 -0
  211. package/src/core/workspace.ts +29 -0
  212. package/src/entry.ts +7 -0
  213. package/src/index.ts +133 -0
  214. package/src/ios/channelConfig.ts +128 -0
  215. package/src/ios/codeUtils.ts +160 -0
  216. package/src/ios/detect.ts +105 -0
  217. package/src/ios/entitlements.ts +61 -0
  218. package/src/ios/fileManager.ts +48 -0
  219. package/src/ios/infoPlist.ts +55 -0
  220. package/src/ios/integrate.ts +516 -0
  221. package/src/ios/pbxprojEditor.ts +383 -0
  222. package/src/ios/pluginConfig.ts +97 -0
  223. package/src/ios/reserved.ts +8 -0
  224. package/src/ios/sdkBundle.ts +36 -0
  225. package/src/ios/template.ts +36 -0
  226. package/src/ios/types.ts +65 -0
  227. package/src/mcp/server.ts +170 -0
  228. package/src/mcp/service.ts +222 -0
  229. package/src/mcp-entry.ts +7 -0
  230. package/src/ops/fileStore.ts +56 -0
  231. package/src/ops/handlers.ts +304 -0
  232. package/src/remote/fetchJson.ts +22 -0
  233. package/src/remote/sdkHomeDownload.ts +274 -0
  234. package/src/remote/topsdkDownloadSdkConfig.ts +93 -0
  235. package/src/remote/topsdkGetSdkConfig.ts +122 -0
  236. package/src/remote/topsdkSign.ts +10 -0
  237. package/src/shared/errors.ts +16 -0
  238. package/src/shared/fileUtils.ts +41 -0
  239. package/src/shared/logger.ts +49 -0
  240. package/src/shared/pathUtils.ts +24 -0
  241. package/src/shared/processRunner.ts +43 -0
  242. package/test-projects/README.md +51 -0
  243. package/test-projects/_preview/pipeline.patch +281 -0
  244. package/tests/aab-converter.test.ts +213 -0
  245. package/tests/assemble.test.ts +12 -0
  246. package/tests/doctor.test.ts +89 -0
  247. package/tests/downloadGoogleServicesJson.test.ts +47 -0
  248. package/tests/fetch-remote.test.ts +23 -0
  249. package/tests/fetchConfigOverrides.test.ts +28 -0
  250. package/tests/fetchConfigWrite.test.ts +54 -0
  251. package/tests/gradle.test.ts +33 -0
  252. package/tests/integration-json.test.ts +29 -0
  253. package/tests/ios.codeUtils.test.ts +23 -0
  254. package/tests/ios.sdkBundle.test.ts +16 -0
  255. package/tests/loadManifest.test.ts +15 -0
  256. package/tests/manifest-xml.test.ts +30 -0
  257. package/tests/mcp.e2e.ts +217 -0
  258. package/tests/mcp.service.test.ts +53 -0
  259. package/tests/meetSdkRemoteConfig.test.ts +456 -0
  260. package/tests/meetSdkRemoteGradle.test.ts +414 -0
  261. package/tests/pipeline.android.test.ts +96 -0
  262. package/tests/pipeline.integration-json.test.ts +58 -0
  263. package/tests/pipeline.ios.test.ts +385 -0
  264. package/tests/pipeline.preview.patch.test.ts +85 -0
  265. package/tests/platformSelection.test.ts +77 -0
  266. package/tests/sdkHomeDownload.test.ts +124 -0
  267. package/tests/sdkVersionConfig.test.ts +130 -0
  268. package/tests/test-projects-hosts.test.ts +78 -0
  269. package/tests/topsdk.test.ts +53 -0
  270. package/tests/topsdkDownloadSdkConfig.test.ts +81 -0
  271. package/tests/topsdkFeatureModules.test.ts +116 -0
  272. package/tsconfig.json +19 -0
  273. package/vitest.config.ts +9 -0
  274. package/vitest.mcp.config.ts +11 -0
  275. package/bundled/android/sample.txt +0 -1
  276. package/docs/ANDROID.md +0 -133
  277. package/docs/CURSOR-MCP-SETUP.md +0 -72
  278. package/docs/MCP-SKILL.md +0 -63
  279. package/fixtures/api-samples/getChannelConfig-meetgames.sample.json +0 -123
  280. package/fixtures/meetsdk-remote-config.download-shape.json +0 -20
  281. package/fixtures/meetsdk-remote-config.mock.json +0 -69
  282. package/fixtures/recipes/android-default.fixture.yaml +0 -15
  283. package/fixtures/recipes/android-integration.fixture.json +0 -29
  284. package/fixtures/topsdk-config-reference.json +0 -39
  285. /package/docs/{api → archive/api}/getSDKConfig.md +0 -0
@@ -0,0 +1,217 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
6
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
7
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
8
+
9
+ const here = path.dirname(fileURLToPath(import.meta.url));
10
+ const pkgRoot = path.resolve(here, "..");
11
+ const androidFixtureRoot = path.join(pkgRoot, "fixtures", "android-test-project", "android-latest-project");
12
+ const remoteConfigFixture = path.join(pkgRoot, "fixtures", "meetsdk-remote-config.mock.json");
13
+ const mcpEntry = path.join(pkgRoot, "dist", "mcp-entry.js");
14
+
15
+ function copyAndroidProjectToTemp(): string {
16
+ const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "meet-mcp-e2e-"));
17
+ const projectRoot = path.join(tmpRoot, "android-project");
18
+ fs.cpSync(androidFixtureRoot, projectRoot, { recursive: true });
19
+ return projectRoot;
20
+ }
21
+
22
+ function createMockFetchPreload(): { path: string; cleanup: () => void } {
23
+ const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "meet-mcp-fetch-"));
24
+ const preloadPath = path.join(tmpRoot, "mock-fetch.mjs");
25
+ const remoteConfigText = fs.readFileSync(remoteConfigFixture, "utf8");
26
+ const preload = `
27
+ const remoteConfigText = ${JSON.stringify(remoteConfigText)};
28
+ const sdkHomeVersionResponse = {
29
+ code: 200,
30
+ data: {
31
+ result: {
32
+ android: { ver: "1.6.1.3", date: "2026-05-25" },
33
+ ios: { ver: "1.6.0.5", date: "2026-06-09" }
34
+ }
35
+ }
36
+ };
37
+
38
+ function jsonResponse(body) {
39
+ return new Response(JSON.stringify(body, null, 2), {
40
+ status: 200,
41
+ headers: { "content-type": "application/json; charset=utf-8" }
42
+ });
43
+ }
44
+
45
+ globalThis.fetch = async (input) => {
46
+ const url = new URL(typeof input === "string" ? input : input.url);
47
+ if (url.pathname === "/sdk/home/version") {
48
+ return jsonResponse(sdkHomeVersionResponse);
49
+ }
50
+ if (url.pathname === "/console/openSDK/downloadSDKConfig") {
51
+ return new Response(remoteConfigText, {
52
+ status: 200,
53
+ headers: { "content-type": "application/json; charset=utf-8" }
54
+ });
55
+ }
56
+ if (url.pathname === "/firebase/google-services.json" || url.pathname.endsWith(".json")) {
57
+ return jsonResponse({ project_info: { project_id: "mock-project" }, client: [] });
58
+ }
59
+ return new Response("Unhandled mock route: " + url.pathname, { status: 404 });
60
+ };
61
+ `;
62
+ fs.writeFileSync(preloadPath, preload);
63
+ return {
64
+ path: preloadPath,
65
+ cleanup: () => fs.rmSync(tmpRoot, { recursive: true, force: true }),
66
+ };
67
+ }
68
+
69
+ function childEnv(baseUrl: string, preloadPath: string): Record<string, string> {
70
+ const env = Object.fromEntries(
71
+ Object.entries(process.env).filter((entry): entry is [string, string] => typeof entry[1] === "string")
72
+ );
73
+ const preloadOption = `--import=${pathToFileURL(preloadPath).href}`;
74
+ return {
75
+ ...env,
76
+ NODE_OPTIONS: [env.NODE_OPTIONS, preloadOption].filter(Boolean).join(" "),
77
+ TOPSDK_API_BASE_URL: baseUrl,
78
+ MEETGAMES_SDK_HOME_API_BASE_URL: baseUrl,
79
+ };
80
+ }
81
+
82
+ async function connectMcpClient(baseUrl: string, preloadPath: string): Promise<Client> {
83
+ const client = new Client({ name: "meet-sdk-tool-mcp-e2e", version: "1.0.0" });
84
+ const transport = new StdioClientTransport({
85
+ command: process.execPath,
86
+ args: [mcpEntry],
87
+ cwd: pkgRoot,
88
+ env: childEnv(baseUrl, preloadPath),
89
+ stderr: "pipe",
90
+ });
91
+ await client.connect(transport);
92
+ return client;
93
+ }
94
+
95
+ function structured(result: Awaited<ReturnType<Client["callTool"]>>): Record<string, unknown> {
96
+ expect("structuredContent" in result).toBe(true);
97
+ const data = "structuredContent" in result ? result.structuredContent : undefined;
98
+ expect(data).toBeTruthy();
99
+ return data as Record<string, unknown>;
100
+ }
101
+
102
+ describe("meetgames MCP stdio server", () => {
103
+ const mockBaseUrl = "https://meet-sdk-tool-mcp-e2e.invalid";
104
+ let mockFetchPreload: ReturnType<typeof createMockFetchPreload>;
105
+ let client: Client;
106
+ const tmpRoots: string[] = [];
107
+
108
+ beforeEach(async () => {
109
+ expect(fs.existsSync(mcpEntry)).toBe(true);
110
+ mockFetchPreload = createMockFetchPreload();
111
+ client = await connectMcpClient(mockBaseUrl, mockFetchPreload.path);
112
+ });
113
+
114
+ afterEach(async () => {
115
+ await client?.close().catch(() => undefined);
116
+ mockFetchPreload?.cleanup();
117
+ for (const root of tmpRoots.splice(0)) {
118
+ fs.rmSync(root, { recursive: true, force: true });
119
+ }
120
+ });
121
+
122
+ it("lists all public meetgames tools", async () => {
123
+ const { tools } = await client.listTools();
124
+ expect(tools.map((tool) => tool.name).sort()).toEqual([
125
+ "meetgames_doctor",
126
+ "meetgames_fetch_config",
127
+ "meetgames_integrate_apply",
128
+ "meetgames_integrate_dry_run",
129
+ "meetgames_setup",
130
+ ]);
131
+ });
132
+
133
+ it("runs doctor and integrate dry-run through stdio", async () => {
134
+ const projectRoot = copyAndroidProjectToTemp();
135
+ tmpRoots.push(path.dirname(projectRoot));
136
+
137
+ const doctor = structured(
138
+ await client.callTool({
139
+ name: "meetgames_doctor",
140
+ arguments: { projectRoot, appTarget: "app" },
141
+ })
142
+ );
143
+ expect(doctor.projectRoot).toBe(projectRoot);
144
+ expect(doctor.platform).toBe("android");
145
+ expect((doctor.android as { moduleName?: string }).moduleName).toBe(":app");
146
+
147
+ const dryRun = structured(
148
+ await client.callTool({
149
+ name: "meetgames_integrate_dry_run",
150
+ arguments: { projectRoot, appTarget: "app" },
151
+ })
152
+ );
153
+ expect(dryRun.dryRun).toBe(true);
154
+ expect(dryRun.hasErrors).toBe(false);
155
+ expect(String(dryRun.patch)).toContain("TOPSDK AUTO");
156
+ expect(fs.existsSync(path.join(projectRoot, "vendor", "meet-integrate", "sample.txt"))).toBe(false);
157
+ });
158
+
159
+ it("runs fetch-config and setup dry-run through stdio", async () => {
160
+ const projectRoot = copyAndroidProjectToTemp();
161
+ tmpRoots.push(path.dirname(projectRoot));
162
+ fs.rmSync(path.join(projectRoot, "meetsdk-remote-config.json"), { force: true });
163
+
164
+ const fetched = structured(
165
+ await client.callTool({
166
+ name: "meetgames_fetch_config",
167
+ arguments: {
168
+ projectRoot,
169
+ env: "test",
170
+ appId: "mock-topsdk-app-id",
171
+ appSecret: "mock-secret",
172
+ channelType: "GOOGLE",
173
+ },
174
+ })
175
+ );
176
+ expect(fetched.env).toBe("test");
177
+ expect(String(fetched.requestUrl)).toContain("/console/openSDK/downloadSDKConfig");
178
+ expect(fs.readFileSync(path.join(projectRoot, "meetsdk-remote-config.json"), "utf8")).toBe(
179
+ fs.readFileSync(remoteConfigFixture, "utf8")
180
+ );
181
+
182
+ const setup = structured(
183
+ await client.callTool({
184
+ name: "meetgames_setup",
185
+ arguments: {
186
+ projectRoot,
187
+ env: "test",
188
+ appId: "mock-topsdk-app-id",
189
+ appSecret: "mock-secret",
190
+ channelType: "GOOGLE",
191
+ appTarget: "app",
192
+ dryRun: true,
193
+ },
194
+ })
195
+ );
196
+ expect((setup.fetch as { env?: string }).env).toBe("test");
197
+ expect((setup.integrate as { dryRun?: boolean; hasErrors?: boolean }).dryRun).toBe(true);
198
+ expect((setup.integrate as { dryRun?: boolean; hasErrors?: boolean }).hasErrors).toBe(false);
199
+ });
200
+
201
+ it("runs integrate apply through stdio against a temporary fixture", async () => {
202
+ const projectRoot = copyAndroidProjectToTemp();
203
+ tmpRoots.push(path.dirname(projectRoot));
204
+
205
+ const applied = structured(
206
+ await client.callTool({
207
+ name: "meetgames_integrate_apply",
208
+ arguments: { projectRoot, appTarget: "app" },
209
+ })
210
+ );
211
+ expect(applied.dryRun).toBe(false);
212
+ expect((applied.report as { errors?: string[] }).errors).toEqual([]);
213
+ expect(applied.hasErrors).toBe(false);
214
+ expect(fs.existsSync(path.join(projectRoot, "vendor", "meet-integrate", "sample.txt"))).toBe(true);
215
+ expect(fs.readFileSync(path.join(projectRoot, "app", "build.gradle"), "utf8")).toContain("TOPSDK AUTO");
216
+ });
217
+ });
@@ -0,0 +1,53 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+ import { meetgamesDoctor, meetgamesIntegrate } from "../src/mcp/service.js";
5
+
6
+ const here = path.dirname(fileURLToPath(import.meta.url));
7
+ const pkgRoot = path.resolve(here, "..");
8
+ const androidLatestRoot = path.join(pkgRoot, "fixtures", "android-test-project", "android-latest-project");
9
+
10
+ function stubSdkHomeVersion(): void {
11
+ vi.stubGlobal(
12
+ "fetch",
13
+ vi.fn(async () => ({
14
+ ok: true,
15
+ status: 200,
16
+ text: async () =>
17
+ JSON.stringify({
18
+ code: 200,
19
+ data: {
20
+ result: {
21
+ android: { ver: "1.6.1.3", date: "2026-05-25" },
22
+ ios: { ver: "1.6.0.5", date: "2026-06-09" },
23
+ },
24
+ },
25
+ }),
26
+ })) as unknown as typeof fetch
27
+ );
28
+ }
29
+
30
+ describe("mcp service", () => {
31
+ beforeEach(() => {
32
+ stubSdkHomeVersion();
33
+ });
34
+
35
+ afterEach(() => {
36
+ vi.unstubAllGlobals();
37
+ });
38
+
39
+ it("doctor returns android detection summary", () => {
40
+ const summary = meetgamesDoctor({ projectRoot: androidLatestRoot, appTarget: "app" });
41
+ expect(summary.projectRoot).toBe(androidLatestRoot);
42
+ expect((summary.android as { ok: boolean }).ok).toBe(true);
43
+ expect((summary.android as { moduleName: string }).moduleName).toBe(":app");
44
+ });
45
+
46
+ it("integrate dry-run returns patch and no errors", async () => {
47
+ const result = await meetgamesIntegrate({ projectRoot: androidLatestRoot, dryRun: true });
48
+ expect(result.dryRun).toBe(true);
49
+ expect(result.patch.length).toBeGreaterThan(0);
50
+ const report = result.report as { errors: string[] };
51
+ expect(report.errors).toEqual([]);
52
+ });
53
+ });