@uwa4d/openapi-mcp 0.2.0-beta.9 → 0.2.1-beta.0

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.
@@ -0,0 +1,2 @@
1
+ /** 与 package.json 同步,避免 MCP 握手版本和 npm 包不一致。 */
2
+ export declare const PACKAGE_VERSION: string;
@@ -0,0 +1,15 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ function readPackageVersion() {
5
+ try {
6
+ const here = dirname(fileURLToPath(import.meta.url));
7
+ const pkg = JSON.parse(readFileSync(join(here, '..', 'package.json'), 'utf8'));
8
+ return pkg.version ?? '0.0.0';
9
+ }
10
+ catch {
11
+ return '0.0.0';
12
+ }
13
+ }
14
+ /** 与 package.json 同步,避免 MCP 握手版本和 npm 包不一致。 */
15
+ export const PACKAGE_VERSION = readPackageVersion();
package/dist/presets.js CHANGED
@@ -25,12 +25,14 @@ export const PRESET_DEFAULT = [
25
25
  'gotonline_overview_indicator_dashboard_keys',
26
26
  'gotonline_overview_memory_manage_data_report',
27
27
  'gotonline_overview_method_group_statistic',
28
+ 'gotonline_overview_method_customidmap_statistic',
28
29
  'gotonline_overview_stack_id_map',
29
30
  'gotonline_overview_stack_stutter_full_presign',
30
31
  'gotonline_overview_stack_stutter_full_tree_presign',
31
32
  'gotonline_overview_stack_stutter_scene_tree_presign',
32
33
  'gotonline_overview_stack_tree_frame_presign',
33
34
  // 复合工具(手写,见 src/composite/)
35
+ 'uwa_mcp_version',
34
36
  'top_resources',
35
37
  'top_functions',
36
38
  'report_diagnosis',
@@ -11,6 +11,8 @@ export const SERVER_INSTRUCTIONS = [
11
11
  '4. 卡顿根因:优先 gotonline_overview_stack_stutter_full_tree_presign / stutter_scene_tree;禁止把 WaitForVsync 直接当根因。尖峰再查单帧树。',
12
12
  '5. 非法面板名要纠正(fps_mean→fps_avg;android_pss_max→android_memory_pss@max);数值带单位。PSS 优先读 pss_peak_kb/mb/frame。',
13
13
  '6. 接口失败时说明原因:运行日志 80108 — Unity 无 LG file_meta 表示未解析、无可用日志;UE 无 meta 只能说「暂不支持获取当前报告的运行日志」(方案切换过),勿断定报告本身无日志。其它失败勿把瞬时错误说成「一定没有数据」。',
14
+ '7. 接口限流 31004(API_RATE_LIMIT):UWA 服务端保护,预期行为,不是 Bug。稍等重试或减少并行/批量(如 top_resources 缩小 assetTypes)。若返回含 _partialErrors 且 _rateLimitHint,部分类型限流时已有 Top 仍可用,需说明可能不完整,勿当成报告无资源。',
15
+ '8. MCP 版本(每对话最多一次):本对话第一次使用任意 UWA MCP 工具前,先调用一次 uwa_mcp_version 核对 npm(正式版只对比正式版,内部测试版只对比测试版,互不交叉)。若 updateAvailable=true / suggestTellUser=true,必须用 userNotice 主动转告并说明重启 MCP 升级;已是最新则不要打扰用户。同一对话内勿重复调用。用户显式问版本时也可再调。',
14
16
  '',
15
17
  '体检优先调用 report_diagnosis;细节再按 _apisUsed 深挖。对比多份报告时说明场景/时长/目标帧是否可比(见 comparability_note)。',
16
18
  ].join('\n');
package/dist/server.d.ts CHANGED
@@ -16,9 +16,10 @@ export interface ServerOptions {
16
16
  maxChars: number;
17
17
  timeoutMs: number;
18
18
  specPath?: string;
19
+ /** 覆盖默认 server instructions(用于启动时注入版本升级提醒)。 */
20
+ instructions?: string;
19
21
  }
20
- /** package.json 同步,避免 MCP 握手版本和 npm 包不一致。 */
21
- export declare const PACKAGE_VERSION: string;
22
+ export { PACKAGE_VERSION } from './package-version.js';
22
23
  export declare function createServer(opts: ServerOptions): {
23
24
  server: McpServer;
24
25
  toolCount: number;
package/dist/server.js CHANGED
@@ -1,6 +1,3 @@
1
- import { readFileSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
3
  import { UwaClient } from './client.js';
@@ -9,18 +6,9 @@ import { selectOperations } from './presets.js';
9
6
  import { loadSpec } from './spec.js';
10
7
  import { makeHandler, toolConfig, toolName } from './tools.js';
11
8
  import { SERVER_INSTRUCTIONS } from './server-instructions.js';
12
- function readPackageVersion() {
13
- try {
14
- const here = dirname(fileURLToPath(import.meta.url));
15
- const pkg = JSON.parse(readFileSync(join(here, '..', 'package.json'), 'utf8'));
16
- return pkg.version ?? '0.0.0';
17
- }
18
- catch {
19
- return '0.0.0';
20
- }
21
- }
22
- /** 与 package.json 同步,避免 MCP 握手版本和 npm 包不一致。 */
23
- export const PACKAGE_VERSION = readPackageVersion();
9
+ import { PACKAGE_VERSION } from './package-version.js';
10
+ import { buildMcpVersionInfo, buildUpdateInstructionAppendix, scheduleUpdateNotice, } from './version-check.js';
11
+ export { PACKAGE_VERSION } from './package-version.js';
24
12
  export function createServer(opts) {
25
13
  const spec = loadSpec(opts.specPath);
26
14
  const operations = selectOperations(spec.operations, { tools: opts.tools, engine: opts.engine });
@@ -29,7 +17,7 @@ export function createServer(opts) {
29
17
  credentials: { appId: opts.appId, appSecret: opts.appSecret },
30
18
  timeoutMs: opts.timeoutMs,
31
19
  });
32
- const server = new McpServer({ name: 'uwa-openapi-mcp', version: PACKAGE_VERSION }, { instructions: SERVER_INSTRUCTIONS });
20
+ const server = new McpServer({ name: 'uwa-openapi-mcp', version: PACKAGE_VERSION }, { instructions: opts.instructions ?? SERVER_INSTRUCTIONS });
33
21
  for (const op of operations) {
34
22
  server.registerTool(toolName(op.id, opts.nameCase, opts.namePrefix), toolConfig(op), makeHandler(op, client, opts.maxRows, opts.maxChars));
35
23
  }
@@ -45,9 +33,25 @@ export function createServer(opts) {
45
33
  return { server, toolCount, total, atomicCount: operations.length, compositeCount };
46
34
  }
47
35
  export async function startStdio(opts) {
48
- const { server, toolCount, total, atomicCount, compositeCount } = createServer(opts);
36
+ let instructions = SERVER_INSTRUCTIONS;
37
+ if (process.env['UWA_MCP_SKIP_UPDATE_CHECK'] !== '1') {
38
+ try {
39
+ const info = await buildMcpVersionInfo(PACKAGE_VERSION);
40
+ const appendix = buildUpdateInstructionAppendix(info);
41
+ if (appendix)
42
+ instructions = `${SERVER_INSTRUCTIONS}\n\n${appendix}`;
43
+ }
44
+ catch {
45
+ /* 版本检查失败不阻塞启动 */
46
+ }
47
+ }
48
+ const { server, toolCount, total, atomicCount, compositeCount } = createServer({
49
+ ...opts,
50
+ instructions,
51
+ });
49
52
  // stdout 是 MCP 协议通道,任何日志都必须走 stderr
50
- console.error(`[uwa-openapi-mcp] 已加载 ${toolCount}/${total} 个工具(原子 ${atomicCount} + 复合 ${compositeCount}),接口地址 ${opts.baseUrl}`);
53
+ console.error(`[uwa-openapi-mcp] v${PACKAGE_VERSION} 已加载 ${toolCount}/${total} 个工具(原子 ${atomicCount} + 复合 ${compositeCount}),接口地址 ${opts.baseUrl}`);
54
+ scheduleUpdateNotice(PACKAGE_VERSION);
51
55
  await server.connect(new StdioServerTransport());
52
56
  }
53
57
  export { selectCompositeTools, COMPOSITE_TOOLS };
@@ -0,0 +1,41 @@
1
+ /** npm 包名(与 package.json 同步)。 */
2
+ export declare const PACKAGE_NAME = "@uwa4d/openapi-mcp";
3
+ export interface UpdateCheckResult {
4
+ current: string;
5
+ latest: string;
6
+ /** npm dist-tag,仅作逻辑区分 */
7
+ registryTag: 'beta' | 'latest';
8
+ }
9
+ /** uwa_mcp_version 工具与启动 instructions 用的结构化版本信息。 */
10
+ export interface McpVersionInfo {
11
+ package: string;
12
+ currentVersion: string;
13
+ /** stable=正式版(客户) / internal=内部测试版;与 npm dist-tag 一一对应,互不交叉比对 */
14
+ releaseLine: 'stable' | 'internal';
15
+ /** 对用户/模型可见的通道名,正式版不说 beta */
16
+ releaseLabel: string;
17
+ latestOnChannel: string | null;
18
+ registryReachable: boolean;
19
+ updateAvailable: boolean;
20
+ userNotice: string;
21
+ upgradeHint: string;
22
+ }
23
+ export interface ReleaseChannelPresentation {
24
+ registryTag: 'beta' | 'latest';
25
+ releaseLine: 'stable' | 'internal';
26
+ releaseLabel: string;
27
+ packageInstallRef: string;
28
+ }
29
+ /** 当前运行版本应跟哪个 npm dist-tag 比对新版(正式↔latest,测试↔beta,不交叉)。 */
30
+ export declare function resolveUpdateChannel(version: string): 'beta' | 'latest';
31
+ /** 正式版与内部测试版的分发呈现(客户侧不出现 beta 字样)。 */
32
+ export declare function describeReleaseChannel(version: string): ReleaseChannelPresentation;
33
+ /** 查询 registry 是否有比 current 更新的同通道版本;失败时返回 null。 */
34
+ export declare function checkForUpdate(current: string): Promise<UpdateCheckResult | null>;
35
+ /** 拉取完整版本信息(工具返回 + 启动 instructions)。 */
36
+ export declare function buildMcpVersionInfo(current: string): Promise<McpVersionInfo>;
37
+ /** 有新版本时追加到 server instructions,让模型在对话里主动提醒用户。 */
38
+ export declare function buildUpdateInstructionAppendix(info: McpVersionInfo): string | null;
39
+ export declare function formatUpdateNotice(result: UpdateCheckResult): string;
40
+ /** 启动时异步检查;仅写 stderr,不阻塞 MCP 握手。 */
41
+ export declare function scheduleUpdateNotice(current: string): void;
@@ -0,0 +1,161 @@
1
+ /** npm 包名(与 package.json 同步)。 */
2
+ export const PACKAGE_NAME = '@uwa4d/openapi-mcp';
3
+ const REGISTRY_URL = 'https://registry.npmjs.org/@uwa4d%2Fopenapi-mcp';
4
+ const CHECK_TIMEOUT_MS = 8_000;
5
+ /** 当前运行版本应跟哪个 npm dist-tag 比对新版(正式↔latest,测试↔beta,不交叉)。 */
6
+ export function resolveUpdateChannel(version) {
7
+ return version.includes('-') ? 'beta' : 'latest';
8
+ }
9
+ /** 正式版与内部测试版的分发呈现(客户侧不出现 beta 字样)。 */
10
+ export function describeReleaseChannel(version) {
11
+ const registryTag = resolveUpdateChannel(version);
12
+ if (registryTag === 'beta') {
13
+ return {
14
+ registryTag: 'beta',
15
+ releaseLine: 'internal',
16
+ releaseLabel: '内部测试版',
17
+ packageInstallRef: `${PACKAGE_NAME}@beta`,
18
+ };
19
+ }
20
+ return {
21
+ registryTag: 'latest',
22
+ releaseLine: 'stable',
23
+ releaseLabel: '正式版',
24
+ packageInstallRef: PACKAGE_NAME,
25
+ };
26
+ }
27
+ /** 简易 semver 比较:a > b 返回 1,相等 0,a < b 返回 -1。 */
28
+ function compareVersions(a, b) {
29
+ if (a === b)
30
+ return 0;
31
+ const parseCore = (v) => v.split('-')[0].split('.').map((n) => Number.parseInt(n, 10) || 0);
32
+ const parsePre = (v) => {
33
+ const idx = v.indexOf('-');
34
+ if (idx < 0)
35
+ return [];
36
+ return v
37
+ .slice(idx + 1)
38
+ .split('.')
39
+ .map((part, i) => (i === 0 ? part : Number.parseInt(part, 10) || part));
40
+ };
41
+ const aCore = parseCore(a);
42
+ const bCore = parseCore(b);
43
+ for (let i = 0; i < Math.max(aCore.length, bCore.length); i++) {
44
+ const av = aCore[i] ?? 0;
45
+ const bv = bCore[i] ?? 0;
46
+ if (av !== bv)
47
+ return av > bv ? 1 : -1;
48
+ }
49
+ const aPre = parsePre(a);
50
+ const bPre = parsePre(b);
51
+ const aHasPre = aPre.length > 0;
52
+ const bHasPre = bPre.length > 0;
53
+ if (!aHasPre && bHasPre)
54
+ return 1;
55
+ if (aHasPre && !bHasPre)
56
+ return -1;
57
+ if (!aHasPre && !bHasPre)
58
+ return 0;
59
+ for (let i = 0; i < Math.max(aPre.length, bPre.length); i++) {
60
+ const av = aPre[i];
61
+ const bv = bPre[i];
62
+ if (av === bv)
63
+ continue;
64
+ if (av === undefined)
65
+ return -1;
66
+ if (bv === undefined)
67
+ return 1;
68
+ if (typeof av === 'number' && typeof bv === 'number')
69
+ return av > bv ? 1 : -1;
70
+ return String(av) > String(bv) ? 1 : -1;
71
+ }
72
+ return 0;
73
+ }
74
+ async function fetchDistTagVersion(channel) {
75
+ try {
76
+ const res = await fetch(REGISTRY_URL, {
77
+ signal: AbortSignal.timeout(CHECK_TIMEOUT_MS),
78
+ headers: { Accept: 'application/json' },
79
+ });
80
+ if (!res.ok)
81
+ return null;
82
+ const data = (await res.json());
83
+ const tag = data['dist-tags']?.[channel];
84
+ return typeof tag === 'string' && tag.trim() ? tag.trim() : null;
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ /** 查询 registry 是否有比 current 更新的同通道版本;失败时返回 null。 */
91
+ export async function checkForUpdate(current) {
92
+ const info = await buildMcpVersionInfo(current);
93
+ if (!info.updateAvailable || !info.latestOnChannel)
94
+ return null;
95
+ return { current: info.currentVersion, latest: info.latestOnChannel, registryTag: describeReleaseChannel(current).registryTag };
96
+ }
97
+ function buildUpgradeHint(presentation) {
98
+ return (`若 MCP 配置未锁定具体版本号,请在您使用的 AI 客户端中重启 MCP 服务以升级(重载 MCP 配置或重启客户端均可);` +
99
+ `终端核对:npx --yes --prefer-online ${presentation.packageInstallRef} --version`);
100
+ }
101
+ /** 拉取完整版本信息(工具返回 + 启动 instructions)。 */
102
+ export async function buildMcpVersionInfo(current) {
103
+ const presentation = describeReleaseChannel(current);
104
+ const latestOnChannel = await fetchDistTagVersion(presentation.registryTag);
105
+ const registryReachable = latestOnChannel !== null;
106
+ const updateAvailable = registryReachable && latestOnChannel !== null && compareVersions(latestOnChannel, current) > 0;
107
+ const upgradeHint = buildUpgradeHint(presentation);
108
+ if (updateAvailable && latestOnChannel) {
109
+ return {
110
+ package: PACKAGE_NAME,
111
+ currentVersion: current,
112
+ releaseLine: presentation.releaseLine,
113
+ releaseLabel: presentation.releaseLabel,
114
+ latestOnChannel,
115
+ registryReachable,
116
+ updateAvailable: true,
117
+ userNotice: `UWA OpenAPI MCP(${presentation.releaseLabel})有新版本:当前 ${current},${presentation.releaseLabel}最新 ${latestOnChannel}。` +
118
+ upgradeHint,
119
+ upgradeHint,
120
+ };
121
+ }
122
+ const latestLabel = latestOnChannel ?? '(暂时无法连接 npm 核对最新版)';
123
+ return {
124
+ package: PACKAGE_NAME,
125
+ currentVersion: current,
126
+ releaseLine: presentation.releaseLine,
127
+ releaseLabel: presentation.releaseLabel,
128
+ latestOnChannel,
129
+ registryReachable,
130
+ updateAvailable: false,
131
+ userNotice: registryReachable
132
+ ? `UWA OpenAPI MCP(${presentation.releaseLabel})已是最新:当前 ${current},${presentation.releaseLabel}最新 ${latestLabel}。`
133
+ : `UWA OpenAPI MCP(${presentation.releaseLabel})当前版本 ${current};暂时无法连接 npm 核对最新版。`,
134
+ upgradeHint,
135
+ };
136
+ }
137
+ /** 有新版本时追加到 server instructions,让模型在对话里主动提醒用户。 */
138
+ export function buildUpdateInstructionAppendix(info) {
139
+ if (!info.updateAvailable || !info.latestOnChannel)
140
+ return null;
141
+ const headline = info.releaseLine === 'stable'
142
+ ? '【MCP 正式版有新版本 — 请主动告知用户】'
143
+ : '【MCP 内部测试版有新版本 — 请主动告知内部测试人员】';
144
+ return (`${headline}当前运行 ${info.currentVersion},${info.releaseLabel}最新 ${info.latestOnChannel}。` +
145
+ `请用自然语言转告用户重启 MCP 升级(勿只写 stderr 日志)。详情可调工具 uwa_mcp_version。` +
146
+ ` ${info.upgradeHint}`);
147
+ }
148
+ export function formatUpdateNotice(result) {
149
+ const presentation = describeReleaseChannel(result.current);
150
+ return (`[uwa-openapi-mcp] ${presentation.releaseLabel}有新版本 ${result.latest}(当前 ${result.current})。` +
151
+ buildUpgradeHint(presentation));
152
+ }
153
+ /** 启动时异步检查;仅写 stderr,不阻塞 MCP 握手。 */
154
+ export function scheduleUpdateNotice(current) {
155
+ if (process.env['UWA_MCP_SKIP_UPDATE_CHECK'] === '1')
156
+ return;
157
+ void checkForUpdate(current).then((result) => {
158
+ if (result)
159
+ console.error(formatUpdateNotice(result));
160
+ });
161
+ }
@@ -152,18 +152,26 @@ export const VERSION_GUIDE = {
152
152
  '- Unity:dataKey/recordId;UE:另传 threadName(如 GameThread)。Header v1.0.2。',
153
153
  '- 复合工具 top_functions(Overview)会读 stackTestMode 并校验 metric;Mono 报告不走此规则。',
154
154
  ].join('\n'),
155
+ gotonline_overview_method_customidmap_statistic: [
156
+ '【选用规则——务必先看】',
157
+ '- **仅 Unity Overview**。查 SDK 打点的自定义代码段(custom_id_map),不是门户「自定义函数组」。',
158
+ '- 未打点或无 custom_id_map 时 data=[],不要说报告没有函数。',
159
+ '- 返回 methodId / methodName / totalTimeTotal / totalTimeMean;子线程才有 threadId。',
160
+ '- 逐帧曲线:把 methodId 当作 stackMethodId 传给 gotonline_overview_method_curve_presign。',
161
+ '- 不要和 gotonline_overview_method_group_statistic / method_idmap_statistic 混用。',
162
+ ].join('\n'),
155
163
  gotonline_overview_method_curve: [
156
164
  '【选用规则——务必先看】',
157
165
  '- v1.0.1 直出曲线 JSON(按 stackMethodName 或 stackMethodId)。',
158
- '- **MCP 与 Open API 推荐改用 gotonline_overview_method_curve_presign(v1.0.2)**:OSS 预签名,仅传 stackMethodId。',
159
- '- stackMethodId 来自 gotonline_overview_method_idmap_statistic 或自定义函数组统计。',
166
+ '- **MCP 与 Open API 推荐改用 gotonline_overview_method_curve_presign(v1.0.2)**:OSS 预签名,id 或 name 至少其一。',
167
+ '- stackMethodId 来自 gotonline_overview_method_idmap_statistic、自定义函数组统计,或自定义代码段统计(methodId)。',
160
168
  ].join('\n'),
161
169
  gotonline_overview_method_curve_presign: [
162
170
  '【选用规则——务必先看】',
163
171
  '- v1.0.2 OSS 预签名下载函数逐帧曲线 JSON(Unity · UE)。',
164
- '- **Open API 入口仅支持 stackMethodId(必填)**;UE 另需 threadName',
172
+ '- stackMethodId stackMethodName **至少传一个**(同时传时优先 id);UE 另需 threadName,Unity 不传。',
165
173
  '- 不要用 v1.0.1 gotonline_overview_method_curve 除非必须服务端直出。',
166
- '- stackMethodId 优先从 gotonline_overview_method_idmap_statistic 获取。',
174
+ '- id 优先从 gotonline_overview_method_idmap_statistic 获取;自定义代码段用 gotonline_overview_method_customidmap_statistic 的 methodId。',
167
175
  ].join('\n'),
168
176
  gotonline_overview_indicator_dashboard_keys: [
169
177
  '【选用规则——务必先看】',
@@ -208,6 +216,7 @@ export const VERSION_GUIDE = {
208
216
  gotonline_overview_stack_tree_frame_presign: [
209
217
  '【选用规则——务必先看】',
210
218
  '- **单帧**完整堆栈树(frameId 必填)。用于已知尖峰帧深挖,不是卡顿分析的第一步。',
219
+ '- Unity:不传 threadId=主线程;传子线程 id/名=该子线程指定帧树(thread idmap)。UE:threadId 必传(含 GameThread)。',
211
220
  '- 卡顿共性根因请先用 stutter_full_tree / stutter_scene_tree(已是多帧合并结果)。',
212
221
  '- ❌ 不要对 frametime valueGt 筛出的每个慢帧循环调用本工具来「聚类」。',
213
222
  STACK_ANALYSIS_GUIDE,
@@ -215,6 +224,7 @@ export const VERSION_GUIDE = {
215
224
  gotonline_overview_stack_sample_frame_presign: [
216
225
  '【选用规则——务必先看】',
217
226
  '- 堆栈树某个结点的逐帧曲线;结点 id 来自树文件。',
227
+ '- Unity 子线程须传 threadId + sampleId;不传 threadId 为主线程(可不传 sampleId 取全帧聚合)。',
218
228
  STACK_ANALYSIS_GUIDE,
219
229
  ].join('\n'),
220
230
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uwa4d/openapi-mcp",
3
- "version": "0.2.0-beta.9",
3
+ "version": "0.2.1-beta.0",
4
4
  "description": "UWA 开放平台 MCP Server,将 UWA Open API 暴露为 MCP 工具供 AI 助手调用",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,6 +27,7 @@
27
27
  "prepublishOnly": "npm run build && node scripts/check-publish-tag.mjs",
28
28
  "release": "node scripts/release.mjs",
29
29
  "release:dry": "node scripts/release.mjs --dry-run",
30
+ "release:stable-patch": "node scripts/release-stable-patch.mjs",
30
31
  "version:beta": "node scripts/bump.mjs beta",
31
32
  "version:release": "node scripts/bump.mjs release"
32
33
  },
@@ -21,6 +21,52 @@
21
21
  "to": "单次请求最多查询 30 份报告(文档写 50,实测上限 30,超出会返回 20001)"
22
22
  }
23
23
  ]
24
+ },
25
+ "gotonline_overview_method_idmap_statistic": {
26
+ "reason": "threadName 仅 UE 必填;Unity 主线程不传。MCP 全局 schema 不得 required,否则 Zod 拦 Unity 调用。",
27
+ "verifiedAt": "2026-08-12",
28
+ "evidence": "sandbox:Unity dataKey=20260812163333sdk6b704767 不传 threadName 返回 348 条;UE 同接口须 threadName=GameThread。",
29
+ "setQueryRequired": {
30
+ "threadName": false
31
+ },
32
+ "setQueryDescription": {
33
+ "threadName": "UE 必传(GameThread / RHIThread / RenderThread / FAsyncLoadingThread 等)。Unity 无需此参数(不传=主线程)"
34
+ }
35
+ },
36
+ "gotonline_overview_method_curve_presign": {
37
+ "reason": "threadName 仅 UE 必填;Unity 不传。stackMethodId/Name 至少其一即可(与线上 Open API 一致)。",
38
+ "verifiedAt": "2026-08-12",
39
+ "evidence": "sandbox:Unity 仅 stackMethodId 可取曲线;UE 须 threadName=GameThread。生产 Open API 支持 name+id。",
40
+ "setQueryRequired": {
41
+ "threadName": false,
42
+ "stackMethodId": false,
43
+ "stackMethodName": false
44
+ },
45
+ "setQueryDescription": {
46
+ "threadName": "UE 必传。Unity 无需此参数",
47
+ "stackMethodId": "函数 ID;与 stackMethodName 至少传一个,同时传时优先 id",
48
+ "stackMethodName": "函数名称;与 stackMethodId 至少传一个"
49
+ }
50
+ },
51
+ "gotonline_overview_stack_tree_frame_presign": {
52
+ "reason": "threadId 仅 UE 必填(含 GameThread);Unity 不传=主线程,传子线程 id/名=子线程树。",
53
+ "verifiedAt": "2026-08-12",
54
+ "evidence": "sandbox:Unity 帧树不传 threadId 成功;UE 传 GameThread/RenderThread 成功。旧 MCP schema 把 threadId 标成全局 required,Agent 调 Unity 时被 Zod 卡住。",
55
+ "setQueryRequired": {
56
+ "threadId": false
57
+ },
58
+ "setQueryDescription": {
59
+ "threadId": "UE 必传(线程 id 或线程名,含 GameThread)。Unity:不传=主线程;传子线程 id/名=该子线程指定帧树"
60
+ }
61
+ },
62
+ "gotonline_overview_stack_sample_frame_presign": {
63
+ "reason": "threadId / sampleId 文档写作「UE 是」,不得升成 MCP 全局必填。",
64
+ "verifiedAt": "2026-08-12",
65
+ "evidence": "文档表写作「UE 是」;旧 isRequired 用 /是/ 子串匹配会误判。Unity 主线程可不传 threadId,可不传 sampleId 取全帧聚合。",
66
+ "setQueryRequired": {
67
+ "threadId": false,
68
+ "sampleId": false
69
+ }
24
70
  }
25
71
  }
26
72
  }