metro-mcp 0.6.2 → 0.6.3
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/dist/bin/metro-mcp.js +77 -19
- package/dist/index.js +77 -19
- package/dist/plugins/console.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bin/metro-mcp.js
CHANGED
|
@@ -3740,7 +3740,7 @@ function extractCDPExceptionMessage(details, fallback = "Evaluation failed") {
|
|
|
3740
3740
|
// package.json
|
|
3741
3741
|
var package_default = {
|
|
3742
3742
|
name: "metro-mcp",
|
|
3743
|
-
version: "0.6.
|
|
3743
|
+
version: "0.6.3",
|
|
3744
3744
|
description: "Plugin-based MCP server for React Native/Expo runtime debugging, inspection, and automation via Metro/CDP",
|
|
3745
3745
|
homepage: "https://metromcp.dev",
|
|
3746
3746
|
repository: {
|
|
@@ -3941,45 +3941,103 @@ class DeviceBufferManager {
|
|
|
3941
3941
|
}
|
|
3942
3942
|
|
|
3943
3943
|
// src/plugins/console.ts
|
|
3944
|
+
function formatPreview(preview) {
|
|
3945
|
+
if (!preview.properties)
|
|
3946
|
+
return null;
|
|
3947
|
+
const props = preview.properties.map((p) => {
|
|
3948
|
+
if (p.type === "object" && p.valuePreview) {
|
|
3949
|
+
const nested = formatPreview(p.valuePreview);
|
|
3950
|
+
return `${p.name}: ${nested || p.value || "[object]"}`;
|
|
3951
|
+
}
|
|
3952
|
+
return `${p.name}: ${p.value}`;
|
|
3953
|
+
});
|
|
3954
|
+
const overflow = preview.overflow ? ", ..." : "";
|
|
3955
|
+
if (preview.subtype === "array")
|
|
3956
|
+
return `[${props.join(", ")}${overflow}]`;
|
|
3957
|
+
return `{${props.join(", ")}${overflow}}`;
|
|
3958
|
+
}
|
|
3959
|
+
function formatRemoteObject(obj) {
|
|
3960
|
+
if (obj.type === "string")
|
|
3961
|
+
return obj.value;
|
|
3962
|
+
if (obj.type === "number")
|
|
3963
|
+
return String(obj.value);
|
|
3964
|
+
if (obj.type === "boolean")
|
|
3965
|
+
return String(obj.value);
|
|
3966
|
+
if (obj.type === "undefined")
|
|
3967
|
+
return "undefined";
|
|
3968
|
+
if (obj.subtype === "null")
|
|
3969
|
+
return "null";
|
|
3970
|
+
if (obj.preview) {
|
|
3971
|
+
const formatted = formatPreview(obj.preview);
|
|
3972
|
+
if (formatted)
|
|
3973
|
+
return formatted;
|
|
3974
|
+
}
|
|
3975
|
+
if (obj.description)
|
|
3976
|
+
return obj.description;
|
|
3977
|
+
if (obj.value !== undefined)
|
|
3978
|
+
return JSON.stringify(obj.value);
|
|
3979
|
+
return obj.className || obj.type || "[object]";
|
|
3980
|
+
}
|
|
3944
3981
|
function formatCDPArgs(args) {
|
|
3945
3982
|
return args.map((arg) => {
|
|
3946
3983
|
if (typeof arg === "object" && arg !== null) {
|
|
3947
|
-
|
|
3948
|
-
if (remoteObj.type === "string")
|
|
3949
|
-
return remoteObj.value;
|
|
3950
|
-
if (remoteObj.type === "number")
|
|
3951
|
-
return String(remoteObj.value);
|
|
3952
|
-
if (remoteObj.type === "boolean")
|
|
3953
|
-
return String(remoteObj.value);
|
|
3954
|
-
if (remoteObj.type === "undefined")
|
|
3955
|
-
return "undefined";
|
|
3956
|
-
if (remoteObj.subtype === "null")
|
|
3957
|
-
return "null";
|
|
3958
|
-
if (remoteObj.description)
|
|
3959
|
-
return remoteObj.description;
|
|
3960
|
-
if (remoteObj.value !== undefined)
|
|
3961
|
-
return JSON.stringify(remoteObj.value);
|
|
3962
|
-
return remoteObj.className || remoteObj.type || "[object]";
|
|
3984
|
+
return formatRemoteObject(arg);
|
|
3963
3985
|
}
|
|
3964
3986
|
return String(arg);
|
|
3965
3987
|
}).join(" ");
|
|
3966
3988
|
}
|
|
3989
|
+
async function resolveRemoteObject(cdpSend, objectId) {
|
|
3990
|
+
try {
|
|
3991
|
+
const result = await cdpSend("Runtime.callFunctionOn", {
|
|
3992
|
+
objectId,
|
|
3993
|
+
functionDeclaration: 'function() { try { return JSON.stringify(this, null, 2); } catch(e) { return "[unserializable]"; } }',
|
|
3994
|
+
returnByValue: true
|
|
3995
|
+
});
|
|
3996
|
+
const inner = result.result;
|
|
3997
|
+
return inner?.value ? inner.value : null;
|
|
3998
|
+
} catch {
|
|
3999
|
+
return null;
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
4002
|
+
async function formatCDPArgsDeep(cdpSend, args) {
|
|
4003
|
+
const parts = await Promise.all(args.map(async (arg) => {
|
|
4004
|
+
if (typeof arg !== "object" || arg === null)
|
|
4005
|
+
return String(arg);
|
|
4006
|
+
const remoteObj = arg;
|
|
4007
|
+
if (remoteObj.objectId && remoteObj.type === "object") {
|
|
4008
|
+
const deep = await resolveRemoteObject(cdpSend, remoteObj.objectId);
|
|
4009
|
+
if (deep)
|
|
4010
|
+
return deep;
|
|
4011
|
+
}
|
|
4012
|
+
return formatRemoteObject(remoteObj);
|
|
4013
|
+
}));
|
|
4014
|
+
return parts.join(" ");
|
|
4015
|
+
}
|
|
3967
4016
|
var consolePlugin = definePlugin({
|
|
3968
4017
|
name: "console",
|
|
3969
4018
|
description: "Console log collection and filtering",
|
|
3970
4019
|
async setup(ctx) {
|
|
3971
4020
|
const buffers = new DeviceBufferManager(500);
|
|
4021
|
+
const cdpSend = ctx.cdp.send.bind(ctx.cdp);
|
|
3972
4022
|
ctx.cdp.on("Runtime.consoleAPICalled", (params) => {
|
|
3973
4023
|
const key = ctx.getActiveDeviceKey();
|
|
3974
4024
|
if (!key)
|
|
3975
4025
|
return;
|
|
3976
4026
|
const args = params.args || [];
|
|
3977
|
-
|
|
4027
|
+
const entry = {
|
|
3978
4028
|
timestamp: Date.now(),
|
|
3979
4029
|
level: params.type,
|
|
3980
4030
|
message: formatCDPArgs(args),
|
|
3981
4031
|
stackTrace: params.stackTrace ? JSON.stringify(params.stackTrace.callFrames) : undefined
|
|
3982
|
-
}
|
|
4032
|
+
};
|
|
4033
|
+
buffers.getOrCreate(key).push(entry);
|
|
4034
|
+
const hasResolvable = args.some((arg) => typeof arg === "object" && arg !== null && arg.objectId);
|
|
4035
|
+
if (hasResolvable) {
|
|
4036
|
+
formatCDPArgsDeep(cdpSend, args).then((deep) => {
|
|
4037
|
+
if (deep !== entry.message)
|
|
4038
|
+
entry.message = deep;
|
|
4039
|
+
}).catch(() => {});
|
|
4040
|
+
}
|
|
3983
4041
|
});
|
|
3984
4042
|
ctx.events.on("bundle_transform_progressed", (event) => {
|
|
3985
4043
|
if (event.transformedFileCount === 1) {
|
package/dist/index.js
CHANGED
|
@@ -3748,7 +3748,7 @@ function extractCDPExceptionMessage(details, fallback = "Evaluation failed") {
|
|
|
3748
3748
|
// package.json
|
|
3749
3749
|
var package_default = {
|
|
3750
3750
|
name: "metro-mcp",
|
|
3751
|
-
version: "0.6.
|
|
3751
|
+
version: "0.6.3",
|
|
3752
3752
|
description: "Plugin-based MCP server for React Native/Expo runtime debugging, inspection, and automation via Metro/CDP",
|
|
3753
3753
|
homepage: "https://metromcp.dev",
|
|
3754
3754
|
repository: {
|
|
@@ -3944,45 +3944,103 @@ class DeviceBufferManager {
|
|
|
3944
3944
|
}
|
|
3945
3945
|
|
|
3946
3946
|
// src/plugins/console.ts
|
|
3947
|
+
function formatPreview(preview) {
|
|
3948
|
+
if (!preview.properties)
|
|
3949
|
+
return null;
|
|
3950
|
+
const props = preview.properties.map((p) => {
|
|
3951
|
+
if (p.type === "object" && p.valuePreview) {
|
|
3952
|
+
const nested = formatPreview(p.valuePreview);
|
|
3953
|
+
return `${p.name}: ${nested || p.value || "[object]"}`;
|
|
3954
|
+
}
|
|
3955
|
+
return `${p.name}: ${p.value}`;
|
|
3956
|
+
});
|
|
3957
|
+
const overflow = preview.overflow ? ", ..." : "";
|
|
3958
|
+
if (preview.subtype === "array")
|
|
3959
|
+
return `[${props.join(", ")}${overflow}]`;
|
|
3960
|
+
return `{${props.join(", ")}${overflow}}`;
|
|
3961
|
+
}
|
|
3962
|
+
function formatRemoteObject(obj) {
|
|
3963
|
+
if (obj.type === "string")
|
|
3964
|
+
return obj.value;
|
|
3965
|
+
if (obj.type === "number")
|
|
3966
|
+
return String(obj.value);
|
|
3967
|
+
if (obj.type === "boolean")
|
|
3968
|
+
return String(obj.value);
|
|
3969
|
+
if (obj.type === "undefined")
|
|
3970
|
+
return "undefined";
|
|
3971
|
+
if (obj.subtype === "null")
|
|
3972
|
+
return "null";
|
|
3973
|
+
if (obj.preview) {
|
|
3974
|
+
const formatted = formatPreview(obj.preview);
|
|
3975
|
+
if (formatted)
|
|
3976
|
+
return formatted;
|
|
3977
|
+
}
|
|
3978
|
+
if (obj.description)
|
|
3979
|
+
return obj.description;
|
|
3980
|
+
if (obj.value !== undefined)
|
|
3981
|
+
return JSON.stringify(obj.value);
|
|
3982
|
+
return obj.className || obj.type || "[object]";
|
|
3983
|
+
}
|
|
3947
3984
|
function formatCDPArgs(args) {
|
|
3948
3985
|
return args.map((arg) => {
|
|
3949
3986
|
if (typeof arg === "object" && arg !== null) {
|
|
3950
|
-
|
|
3951
|
-
if (remoteObj.type === "string")
|
|
3952
|
-
return remoteObj.value;
|
|
3953
|
-
if (remoteObj.type === "number")
|
|
3954
|
-
return String(remoteObj.value);
|
|
3955
|
-
if (remoteObj.type === "boolean")
|
|
3956
|
-
return String(remoteObj.value);
|
|
3957
|
-
if (remoteObj.type === "undefined")
|
|
3958
|
-
return "undefined";
|
|
3959
|
-
if (remoteObj.subtype === "null")
|
|
3960
|
-
return "null";
|
|
3961
|
-
if (remoteObj.description)
|
|
3962
|
-
return remoteObj.description;
|
|
3963
|
-
if (remoteObj.value !== undefined)
|
|
3964
|
-
return JSON.stringify(remoteObj.value);
|
|
3965
|
-
return remoteObj.className || remoteObj.type || "[object]";
|
|
3987
|
+
return formatRemoteObject(arg);
|
|
3966
3988
|
}
|
|
3967
3989
|
return String(arg);
|
|
3968
3990
|
}).join(" ");
|
|
3969
3991
|
}
|
|
3992
|
+
async function resolveRemoteObject(cdpSend, objectId) {
|
|
3993
|
+
try {
|
|
3994
|
+
const result = await cdpSend("Runtime.callFunctionOn", {
|
|
3995
|
+
objectId,
|
|
3996
|
+
functionDeclaration: 'function() { try { return JSON.stringify(this, null, 2); } catch(e) { return "[unserializable]"; } }',
|
|
3997
|
+
returnByValue: true
|
|
3998
|
+
});
|
|
3999
|
+
const inner = result.result;
|
|
4000
|
+
return inner?.value ? inner.value : null;
|
|
4001
|
+
} catch {
|
|
4002
|
+
return null;
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
async function formatCDPArgsDeep(cdpSend, args) {
|
|
4006
|
+
const parts = await Promise.all(args.map(async (arg) => {
|
|
4007
|
+
if (typeof arg !== "object" || arg === null)
|
|
4008
|
+
return String(arg);
|
|
4009
|
+
const remoteObj = arg;
|
|
4010
|
+
if (remoteObj.objectId && remoteObj.type === "object") {
|
|
4011
|
+
const deep = await resolveRemoteObject(cdpSend, remoteObj.objectId);
|
|
4012
|
+
if (deep)
|
|
4013
|
+
return deep;
|
|
4014
|
+
}
|
|
4015
|
+
return formatRemoteObject(remoteObj);
|
|
4016
|
+
}));
|
|
4017
|
+
return parts.join(" ");
|
|
4018
|
+
}
|
|
3970
4019
|
var consolePlugin = definePlugin({
|
|
3971
4020
|
name: "console",
|
|
3972
4021
|
description: "Console log collection and filtering",
|
|
3973
4022
|
async setup(ctx) {
|
|
3974
4023
|
const buffers = new DeviceBufferManager(500);
|
|
4024
|
+
const cdpSend = ctx.cdp.send.bind(ctx.cdp);
|
|
3975
4025
|
ctx.cdp.on("Runtime.consoleAPICalled", (params) => {
|
|
3976
4026
|
const key = ctx.getActiveDeviceKey();
|
|
3977
4027
|
if (!key)
|
|
3978
4028
|
return;
|
|
3979
4029
|
const args = params.args || [];
|
|
3980
|
-
|
|
4030
|
+
const entry = {
|
|
3981
4031
|
timestamp: Date.now(),
|
|
3982
4032
|
level: params.type,
|
|
3983
4033
|
message: formatCDPArgs(args),
|
|
3984
4034
|
stackTrace: params.stackTrace ? JSON.stringify(params.stackTrace.callFrames) : undefined
|
|
3985
|
-
}
|
|
4035
|
+
};
|
|
4036
|
+
buffers.getOrCreate(key).push(entry);
|
|
4037
|
+
const hasResolvable = args.some((arg) => typeof arg === "object" && arg !== null && arg.objectId);
|
|
4038
|
+
if (hasResolvable) {
|
|
4039
|
+
formatCDPArgsDeep(cdpSend, args).then((deep) => {
|
|
4040
|
+
if (deep !== entry.message)
|
|
4041
|
+
entry.message = deep;
|
|
4042
|
+
}).catch(() => {});
|
|
4043
|
+
}
|
|
3986
4044
|
});
|
|
3987
4045
|
ctx.events.on("bundle_transform_progressed", (event) => {
|
|
3988
4046
|
if (event.transformedFileCount === 1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/plugins/console.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/plugins/console.ts"],"names":[],"mappings":"AAuHA,eAAO,MAAM,aAAa,yCAiIxB,CAAC"}
|
package/package.json
CHANGED