@reproapp/mcp 0.0.6 → 0.0.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/package.json +1 -1
- package/src/index.js +189 -2
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1192,9 +1192,10 @@ async function executeTool(params, config, client, getTools) {
|
|
|
1192
1192
|
throw rpcError(-32602, `Unknown tool: ${name}`);
|
|
1193
1193
|
}
|
|
1194
1194
|
|
|
1195
|
-
const response = await client.executeTool(name, input);
|
|
1195
|
+
const response = await client.executeTool(name, inputWithExactCapturedPayloads(name, input));
|
|
1196
|
+
const expandedResponse = await expandLinkedCapturedPayloads(name, response, client, input);
|
|
1196
1197
|
|
|
1197
|
-
const augmented = augmentPaths(
|
|
1198
|
+
const augmented = augmentPaths(expandedResponse, config.pathMappings);
|
|
1198
1199
|
const isError =
|
|
1199
1200
|
augmented &&
|
|
1200
1201
|
typeof augmented === 'object' &&
|
|
@@ -1213,6 +1214,189 @@ async function executeTool(params, config, client, getTools) {
|
|
|
1213
1214
|
};
|
|
1214
1215
|
}
|
|
1215
1216
|
|
|
1217
|
+
function inputWithExactCapturedPayloads(name, input) {
|
|
1218
|
+
if (name !== 'get_kafka_messages') {
|
|
1219
|
+
return input;
|
|
1220
|
+
}
|
|
1221
|
+
return {
|
|
1222
|
+
...input,
|
|
1223
|
+
includeLargeValues: true,
|
|
1224
|
+
expandLargeValue: true,
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
async function expandLinkedCapturedPayloads(name, response, client, originalInput = {}) {
|
|
1229
|
+
if (name !== 'get_kafka_messages') {
|
|
1230
|
+
return response;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
const root = cloneJson(response) ?? response;
|
|
1234
|
+
const visited = new Set();
|
|
1235
|
+
|
|
1236
|
+
while (true) {
|
|
1237
|
+
const links = collectCapturedPayloadLinks(root)
|
|
1238
|
+
.filter((entry) => !visited.has(capturedPayloadLinkKey(entry.link)));
|
|
1239
|
+
if (!links.length) {
|
|
1240
|
+
return root;
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
for (const { link } of links) {
|
|
1244
|
+
const key = capturedPayloadLinkKey(link);
|
|
1245
|
+
visited.add(key);
|
|
1246
|
+
|
|
1247
|
+
const toolName = typeof link.tool === 'string' ? link.tool : '';
|
|
1248
|
+
if (toolName !== 'get_kafka_messages') {
|
|
1249
|
+
throw new Error(`Cannot expand captured payload through unsupported MCP tool: ${toolName || 'unknown'}`);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
const linkArgs = link.arguments && typeof link.arguments === 'object' && !Array.isArray(link.arguments)
|
|
1253
|
+
? link.arguments
|
|
1254
|
+
: {};
|
|
1255
|
+
const scopedLinkArgs = {
|
|
1256
|
+
...originalInput,
|
|
1257
|
+
...linkArgs,
|
|
1258
|
+
};
|
|
1259
|
+
const expanded = await client.executeTool(toolName, inputWithExactCapturedPayloads(toolName, scopedLinkArgs));
|
|
1260
|
+
const expandedLookup = lookupLinkedPayloadValue(expanded, link.path);
|
|
1261
|
+
if (!expandedLookup.found) {
|
|
1262
|
+
throw new Error(`Repro MCP could not expand captured payload at ${link.path || 'unknown path'}`);
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
const applied = replaceLinkedPayloadValue(root, link.path, expandedLookup.value);
|
|
1266
|
+
if (!applied) {
|
|
1267
|
+
throw new Error(`Repro MCP could not replace captured payload at ${link.path || 'unknown path'}`);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
function collectCapturedPayloadLinks(value, out = []) {
|
|
1274
|
+
if (!value || typeof value !== 'object') {
|
|
1275
|
+
return out;
|
|
1276
|
+
}
|
|
1277
|
+
if (Array.isArray(value)) {
|
|
1278
|
+
for (const item of value) {
|
|
1279
|
+
collectCapturedPayloadLinks(item, out);
|
|
1280
|
+
}
|
|
1281
|
+
return out;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
const link = value.valueOmitted === true ? value.valueLink : value.rawValueLink;
|
|
1285
|
+
if (
|
|
1286
|
+
(value.valueOmitted === true || value.rawValueOmitted === true) &&
|
|
1287
|
+
link &&
|
|
1288
|
+
typeof link === 'object' &&
|
|
1289
|
+
link.kind === 'mcp-tool-call' &&
|
|
1290
|
+
typeof link.tool === 'string' &&
|
|
1291
|
+
typeof link.path === 'string'
|
|
1292
|
+
) {
|
|
1293
|
+
out.push({ holder: value, link });
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
for (const nested of Object.values(value)) {
|
|
1297
|
+
collectCapturedPayloadLinks(nested, out);
|
|
1298
|
+
}
|
|
1299
|
+
return out;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
function capturedPayloadLinkKey(link) {
|
|
1303
|
+
return JSON.stringify({
|
|
1304
|
+
tool: link?.tool ?? null,
|
|
1305
|
+
path: link?.path ?? null,
|
|
1306
|
+
arguments: link?.arguments ?? null,
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
function lookupLinkedPayloadValue(root, pathExpression) {
|
|
1311
|
+
const segments = parseLinkedPayloadPath(pathExpression);
|
|
1312
|
+
if (!segments.length) {
|
|
1313
|
+
return { found: false };
|
|
1314
|
+
}
|
|
1315
|
+
return lookupPathCandidates(root, segments);
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
function replaceLinkedPayloadValue(root, pathExpression, value) {
|
|
1319
|
+
const segments = parseLinkedPayloadPath(pathExpression);
|
|
1320
|
+
if (!segments.length) {
|
|
1321
|
+
return false;
|
|
1322
|
+
}
|
|
1323
|
+
const candidates = pathCandidateSegments(segments);
|
|
1324
|
+
for (const candidate of candidates) {
|
|
1325
|
+
const parentLookup = getAtPath(root, candidate.slice(0, -1));
|
|
1326
|
+
if (!parentLookup.found || !parentLookup.value || typeof parentLookup.value !== 'object') {
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1329
|
+
const leaf = candidate[candidate.length - 1];
|
|
1330
|
+
parentLookup.value[leaf] = value;
|
|
1331
|
+
if (leaf === 'value') {
|
|
1332
|
+
delete parentLookup.value.valueOmitted;
|
|
1333
|
+
delete parentLookup.value.valuePreview;
|
|
1334
|
+
delete parentLookup.value.valueLink;
|
|
1335
|
+
} else if (leaf === 'rawValue') {
|
|
1336
|
+
delete parentLookup.value.rawValueOmitted;
|
|
1337
|
+
delete parentLookup.value.rawValuePreview;
|
|
1338
|
+
delete parentLookup.value.rawValueLink;
|
|
1339
|
+
}
|
|
1340
|
+
return true;
|
|
1341
|
+
}
|
|
1342
|
+
return false;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
function lookupPathCandidates(root, segments) {
|
|
1346
|
+
for (const candidate of pathCandidateSegments(segments)) {
|
|
1347
|
+
const lookup = getAtPath(root, candidate);
|
|
1348
|
+
if (lookup.found) {
|
|
1349
|
+
return lookup;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
return { found: false };
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
function pathCandidateSegments(segments) {
|
|
1356
|
+
return [
|
|
1357
|
+
['data', ...segments],
|
|
1358
|
+
segments,
|
|
1359
|
+
];
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
function parseLinkedPayloadPath(pathExpression) {
|
|
1363
|
+
if (typeof pathExpression !== 'string' || !pathExpression.trim()) {
|
|
1364
|
+
return [];
|
|
1365
|
+
}
|
|
1366
|
+
const segments = [];
|
|
1367
|
+
const pattern = /([A-Za-z_$][\w$-]*)|\[(\d+)\]/g;
|
|
1368
|
+
let match;
|
|
1369
|
+
while ((match = pattern.exec(pathExpression)) !== null) {
|
|
1370
|
+
if (typeof match[1] === 'string') {
|
|
1371
|
+
segments.push(match[1]);
|
|
1372
|
+
} else if (typeof match[2] === 'string') {
|
|
1373
|
+
segments.push(Number.parseInt(match[2], 10));
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
return segments;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
function getAtPath(root, segments) {
|
|
1380
|
+
let current = root;
|
|
1381
|
+
for (const segment of segments) {
|
|
1382
|
+
if (current == null) {
|
|
1383
|
+
return { found: false };
|
|
1384
|
+
}
|
|
1385
|
+
if (typeof segment === 'number') {
|
|
1386
|
+
if (!Array.isArray(current) || segment < 0 || segment >= current.length) {
|
|
1387
|
+
return { found: false };
|
|
1388
|
+
}
|
|
1389
|
+
current = current[segment];
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
if (typeof current !== 'object' || !Object.prototype.hasOwnProperty.call(current, segment)) {
|
|
1393
|
+
return { found: false };
|
|
1394
|
+
}
|
|
1395
|
+
current = current[segment];
|
|
1396
|
+
}
|
|
1397
|
+
return { found: true, value: current };
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1216
1400
|
function formatLocalToolContentText(name, value) {
|
|
1217
1401
|
if (name === 'inspect_privacy_policy' || name === 'list_privacy_policy_blockers') {
|
|
1218
1402
|
const text = renderPolicyInspectionText(value);
|
|
@@ -1222,6 +1406,9 @@ function formatLocalToolContentText(name, value) {
|
|
|
1222
1406
|
const text = renderPrivacyCoverageText(value);
|
|
1223
1407
|
if (text) return text;
|
|
1224
1408
|
}
|
|
1409
|
+
if (name === 'get_kafka_messages') {
|
|
1410
|
+
return JSON.stringify(value, null, 2);
|
|
1411
|
+
}
|
|
1225
1412
|
return JSON.stringify(value, null, 2);
|
|
1226
1413
|
}
|
|
1227
1414
|
|