mcp-server-diff 2.1.6 ā 2.2.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.
- package/README.md +42 -2
- package/dist/cli/index.js +30 -18
- package/dist/cli/types.d.ts +9 -0
- package/dist/index.js +123 -62
- package/dist/types.d.ts +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -223,6 +223,46 @@ When using `configurations`, each object supports:
|
|
|
223
223
|
| `headers` | HTTP headers for this configuration | No |
|
|
224
224
|
| `env_vars` | Additional environment variables | No |
|
|
225
225
|
| `custom_messages` | Config-specific custom messages | No |
|
|
226
|
+
| `base_start_command` | Command for baseline comparison (skips git checkout for this config) | No |
|
|
227
|
+
| `base_server_url` | URL for baseline HTTP server (used with `base_start_command`) | No |
|
|
228
|
+
|
|
229
|
+
### Comparing Against External Servers
|
|
230
|
+
|
|
231
|
+
When comparing against external servers (e.g., Docker images, remote services), use `base_start_command` to specify a different command for the baseline. This skips git checkout for that configuration and probes the specified server directly:
|
|
232
|
+
|
|
233
|
+
```yaml
|
|
234
|
+
configurations: |
|
|
235
|
+
[
|
|
236
|
+
{
|
|
237
|
+
"name": "compare-versions",
|
|
238
|
+
"transport": "stdio",
|
|
239
|
+
"start_command": "docker run -i ghcr.io/example/mcp-server:v2.0.0",
|
|
240
|
+
"base_start_command": "docker run -i ghcr.io/example/mcp-server:v1.0.0"
|
|
241
|
+
}
|
|
242
|
+
]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
This is useful for:
|
|
246
|
+
- **Version comparison**: Compare a new release against the previous version
|
|
247
|
+
- **Golden reference testing**: Compare your local code against a known-good reference
|
|
248
|
+
- **Cross-implementation testing**: Compare different implementations of the same server
|
|
249
|
+
- **Self-testing CI**: Verify the action detects diffs by comparing two known-different servers
|
|
250
|
+
|
|
251
|
+
For HTTP transport, use `base_server_url` alongside `base_start_command`:
|
|
252
|
+
|
|
253
|
+
```yaml
|
|
254
|
+
configurations: |
|
|
255
|
+
[
|
|
256
|
+
{
|
|
257
|
+
"name": "http-comparison",
|
|
258
|
+
"transport": "streamable-http",
|
|
259
|
+
"start_command": "docker run -p 3000:3000 myserver:latest",
|
|
260
|
+
"server_url": "http://localhost:3000/mcp",
|
|
261
|
+
"base_start_command": "docker run -p 3001:3000 myserver:v1.0.0",
|
|
262
|
+
"base_server_url": "http://localhost:3001/mcp"
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
```
|
|
226
266
|
|
|
227
267
|
## How It Works
|
|
228
268
|
|
|
@@ -595,8 +635,8 @@ npx mcp-server-diff -c servers.json -o diff
|
|
|
595
635
|
| `-b, --base <cmd\|url>` | Base server command (stdio) or URL (http) |
|
|
596
636
|
| `-t, --target <cmd\|url>` | Target server command (stdio) or URL (http) |
|
|
597
637
|
| `-H, --header <header>` | HTTP header for target (repeatable) |
|
|
598
|
-
|
|
|
599
|
-
|
|
|
638
|
+
| `-B, --base-header <header>` | HTTP header for base server (repeatable) |
|
|
639
|
+
| `-T, --target-header <header>` | HTTP header for target (same as `-H`) |
|
|
600
640
|
| `-c, --config <file>` | Config file with base and targets |
|
|
601
641
|
| `-o, --output <format>` | Output: `diff`, `json`, `markdown`, `summary` (default) |
|
|
602
642
|
| `-v, --verbose` | Verbose output |
|
package/dist/cli/index.js
CHANGED
|
@@ -56368,6 +56368,7 @@ function isMethodNotFound(error) {
|
|
|
56368
56368
|
async function probeServer(options) {
|
|
56369
56369
|
const result = {
|
|
56370
56370
|
initialize: null,
|
|
56371
|
+
instructions: null,
|
|
56371
56372
|
tools: null,
|
|
56372
56373
|
prompts: null,
|
|
56373
56374
|
resources: null,
|
|
@@ -56426,6 +56427,12 @@ async function probeServer(options) {
|
|
|
56426
56427
|
serverInfo,
|
|
56427
56428
|
capabilities: serverCapabilities,
|
|
56428
56429
|
};
|
|
56430
|
+
// Get server instructions
|
|
56431
|
+
const instructions = client.getInstructions();
|
|
56432
|
+
if (instructions) {
|
|
56433
|
+
result.instructions = instructions;
|
|
56434
|
+
log.info(` Got server instructions (${instructions.length} chars)`);
|
|
56435
|
+
}
|
|
56429
56436
|
// Probe tools if supported
|
|
56430
56437
|
if (serverCapabilities?.tools) {
|
|
56431
56438
|
try {
|
|
@@ -56623,6 +56630,9 @@ function probeResultToFiles(result) {
|
|
|
56623
56630
|
if (result.initialize) {
|
|
56624
56631
|
files.set("initialize", JSON.stringify(normalizeProbeResult(result.initialize), null, 2));
|
|
56625
56632
|
}
|
|
56633
|
+
if (result.instructions) {
|
|
56634
|
+
files.set("instructions", result.instructions);
|
|
56635
|
+
}
|
|
56626
56636
|
if (result.tools) {
|
|
56627
56637
|
files.set("tools", JSON.stringify(normalizeProbeResult(result.tools), null, 2));
|
|
56628
56638
|
}
|
|
@@ -56870,8 +56880,8 @@ function parseCliArgs() {
|
|
|
56870
56880
|
base: { type: "string", short: "b" },
|
|
56871
56881
|
target: { type: "string", short: "t" },
|
|
56872
56882
|
header: { type: "string", short: "H", multiple: true },
|
|
56873
|
-
"base-header": { type: "string", multiple: true },
|
|
56874
|
-
"target-header": { type: "string", multiple: true },
|
|
56883
|
+
"base-header": { type: "string", short: "B", multiple: true },
|
|
56884
|
+
"target-header": { type: "string", short: "T", multiple: true },
|
|
56875
56885
|
config: { type: "string", short: "c" },
|
|
56876
56886
|
output: { type: "string", short: "o", default: "summary" },
|
|
56877
56887
|
verbose: { type: "boolean", short: "v", default: false },
|
|
@@ -56900,8 +56910,8 @@ OPTIONS:
|
|
|
56900
56910
|
-b, --base <command> Base server command (stdio) or URL (http)
|
|
56901
56911
|
-t, --target <command> Target server command (stdio) or URL (http)
|
|
56902
56912
|
-H, --header <header> HTTP header for target (repeatable)
|
|
56903
|
-
|
|
56904
|
-
|
|
56913
|
+
-B, --base-header <header> HTTP header for base server (repeatable)
|
|
56914
|
+
-T, --target-header <hdr> HTTP header for target server (repeatable, same as -H)
|
|
56905
56915
|
Values support: env:VAR_NAME, secret:name, "Bearer secret:token"
|
|
56906
56916
|
-c, --config <file> Config file with base and targets
|
|
56907
56917
|
-o, --output <format> Output format: diff, json, markdown, summary (default: summary)
|
|
@@ -57060,44 +57070,46 @@ function findSecrets(headerStrings) {
|
|
|
57060
57070
|
*/
|
|
57061
57071
|
async function promptSecret(prompt) {
|
|
57062
57072
|
return new Promise((resolve) => {
|
|
57063
|
-
|
|
57064
|
-
input: process.stdin,
|
|
57065
|
-
output: process.stdout,
|
|
57066
|
-
});
|
|
57073
|
+
process.stdout.write(`${prompt}: `);
|
|
57067
57074
|
// Hide input by using raw mode if available
|
|
57068
|
-
if (process.stdin.isTTY) {
|
|
57069
|
-
process.stdout.write(`${prompt}: `);
|
|
57075
|
+
if (process.stdin.isTTY && process.stdin.setRawMode) {
|
|
57070
57076
|
process.stdin.setRawMode(true);
|
|
57071
57077
|
process.stdin.resume();
|
|
57078
|
+
process.stdin.setEncoding("utf8");
|
|
57072
57079
|
let value = "";
|
|
57073
57080
|
const onData = (char) => {
|
|
57074
|
-
|
|
57075
|
-
if (c === "\n" || c === "\r") {
|
|
57081
|
+
if (char === "\n" || char === "\r" || char === "\u0004") {
|
|
57076
57082
|
process.stdin.setRawMode(false);
|
|
57083
|
+
process.stdin.pause();
|
|
57077
57084
|
process.stdin.removeListener("data", onData);
|
|
57078
|
-
rl.close();
|
|
57079
57085
|
process.stdout.write("\n");
|
|
57080
57086
|
resolve(value);
|
|
57081
57087
|
}
|
|
57082
|
-
else if (
|
|
57088
|
+
else if (char === "\u0003") {
|
|
57083
57089
|
// Ctrl+C
|
|
57090
|
+
process.stdin.setRawMode(false);
|
|
57091
|
+
process.stdout.write("\n");
|
|
57084
57092
|
process.exit(1);
|
|
57085
57093
|
}
|
|
57086
|
-
else if (
|
|
57094
|
+
else if (char === "\u007F" || char === "\b") {
|
|
57087
57095
|
// Backspace
|
|
57088
57096
|
if (value.length > 0) {
|
|
57089
57097
|
value = value.slice(0, -1);
|
|
57090
57098
|
}
|
|
57091
57099
|
}
|
|
57092
57100
|
else {
|
|
57093
|
-
value +=
|
|
57101
|
+
value += char;
|
|
57094
57102
|
}
|
|
57095
57103
|
};
|
|
57096
57104
|
process.stdin.on("data", onData);
|
|
57097
57105
|
}
|
|
57098
57106
|
else {
|
|
57099
|
-
// Non-TTY:
|
|
57100
|
-
rl
|
|
57107
|
+
// Non-TTY: use readline (won't be hidden)
|
|
57108
|
+
const rl = external_readline_namespaceObject.createInterface({
|
|
57109
|
+
input: process.stdin,
|
|
57110
|
+
output: process.stdout,
|
|
57111
|
+
});
|
|
57112
|
+
rl.question("", (answer) => {
|
|
57101
57113
|
rl.close();
|
|
57102
57114
|
resolve(answer);
|
|
57103
57115
|
});
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -18,6 +18,14 @@ export interface TestConfiguration {
|
|
|
18
18
|
startup_wait_ms?: number;
|
|
19
19
|
/** Command to run after stopping the MCP server for this config (cleanup) */
|
|
20
20
|
post_test_command?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Command to use for the base/comparison server instead of checking out a git ref.
|
|
23
|
+
* When set, skips git operations and uses this command directly for comparison.
|
|
24
|
+
* Useful for comparing against external servers (e.g., docker images of previous releases).
|
|
25
|
+
*/
|
|
26
|
+
base_start_command?: string;
|
|
27
|
+
/** Server URL for base comparison (for HTTP transport with base_start_command) */
|
|
28
|
+
base_server_url?: string;
|
|
21
29
|
}
|
|
22
30
|
export interface CustomMessage {
|
|
23
31
|
id: number;
|
|
@@ -53,6 +61,7 @@ export interface ActionInputs {
|
|
|
53
61
|
}
|
|
54
62
|
export interface ProbeResult {
|
|
55
63
|
initialize: InitializeInfo | null;
|
|
64
|
+
instructions: string | null;
|
|
56
65
|
tools: ToolsResult | null;
|
|
57
66
|
prompts: PromptsResult | null;
|
|
58
67
|
resources: ResourcesResult | null;
|
package/dist/index.js
CHANGED
|
@@ -56618,6 +56618,7 @@ function isMethodNotFound(error) {
|
|
|
56618
56618
|
async function probeServer(options) {
|
|
56619
56619
|
const result = {
|
|
56620
56620
|
initialize: null,
|
|
56621
|
+
instructions: null,
|
|
56621
56622
|
tools: null,
|
|
56622
56623
|
prompts: null,
|
|
56623
56624
|
resources: null,
|
|
@@ -56676,6 +56677,12 @@ async function probeServer(options) {
|
|
|
56676
56677
|
serverInfo,
|
|
56677
56678
|
capabilities: serverCapabilities,
|
|
56678
56679
|
};
|
|
56680
|
+
// Get server instructions
|
|
56681
|
+
const instructions = client.getInstructions();
|
|
56682
|
+
if (instructions) {
|
|
56683
|
+
result.instructions = instructions;
|
|
56684
|
+
log.info(` Got server instructions (${instructions.length} chars)`);
|
|
56685
|
+
}
|
|
56679
56686
|
// Probe tools if supported
|
|
56680
56687
|
if (serverCapabilities?.tools) {
|
|
56681
56688
|
try {
|
|
@@ -56873,6 +56880,9 @@ function probeResultToFiles(result) {
|
|
|
56873
56880
|
if (result.initialize) {
|
|
56874
56881
|
files.set("initialize", JSON.stringify(normalizeProbeResult(result.initialize), null, 2));
|
|
56875
56882
|
}
|
|
56883
|
+
if (result.instructions) {
|
|
56884
|
+
files.set("instructions", result.instructions);
|
|
56885
|
+
}
|
|
56876
56886
|
if (result.tools) {
|
|
56877
56887
|
files.set("tools", JSON.stringify(normalizeProbeResult(result.tools), null, 2));
|
|
56878
56888
|
}
|
|
@@ -57133,8 +57143,10 @@ async function runPostTestCommand(config, workDir) {
|
|
|
57133
57143
|
/**
|
|
57134
57144
|
* Probe a server with a specific configuration
|
|
57135
57145
|
* @param useSharedServer - If true, skip starting per-config HTTP server (shared server is already running)
|
|
57146
|
+
* @param overrideCommand - If provided, use this command instead of config.start_command (for base_start_command)
|
|
57147
|
+
* @param overrideUrl - If provided, use this URL instead of config.server_url (for base_server_url)
|
|
57136
57148
|
*/
|
|
57137
|
-
async function probeWithConfig(config, workDir, globalEnvVars, globalHeaders, globalCustomMessages, useSharedServer = false) {
|
|
57149
|
+
async function probeWithConfig(config, workDir, globalEnvVars, globalHeaders, globalCustomMessages, useSharedServer = false, overrideCommand, overrideUrl) {
|
|
57138
57150
|
const configEnvVars = parseEnvVars(config.env_vars);
|
|
57139
57151
|
const envVars = { ...globalEnvVars, ...configEnvVars };
|
|
57140
57152
|
const headers = { ...globalHeaders, ...config.headers };
|
|
@@ -57142,12 +57154,12 @@ async function probeWithConfig(config, workDir, globalEnvVars, globalHeaders, gl
|
|
|
57142
57154
|
// Run pre-test command before probing
|
|
57143
57155
|
await runPreTestCommand(config, workDir);
|
|
57144
57156
|
if (config.transport === "stdio") {
|
|
57145
|
-
const command = config.start_command || "";
|
|
57157
|
+
const command = overrideCommand || config.start_command || "";
|
|
57146
57158
|
const parts = command.split(/\s+/);
|
|
57147
57159
|
const cmd = parts[0];
|
|
57148
57160
|
const args = parts.slice(1);
|
|
57149
|
-
// Also parse additional args if provided
|
|
57150
|
-
if (config.args) {
|
|
57161
|
+
// Also parse additional args if provided (only when not using override)
|
|
57162
|
+
if (!overrideCommand && config.args) {
|
|
57151
57163
|
args.push(...config.args.split(/\s+/));
|
|
57152
57164
|
}
|
|
57153
57165
|
return await probeServer({
|
|
@@ -57163,13 +57175,17 @@ async function probeWithConfig(config, workDir, globalEnvVars, globalHeaders, gl
|
|
|
57163
57175
|
// For HTTP transport, optionally start the server if start_command is provided
|
|
57164
57176
|
// Skip if using shared server
|
|
57165
57177
|
let serverProcess = null;
|
|
57178
|
+
const serverUrl = overrideUrl || config.server_url;
|
|
57166
57179
|
try {
|
|
57167
|
-
|
|
57168
|
-
|
|
57180
|
+
const startCmd = overrideCommand || config.start_command;
|
|
57181
|
+
if (startCmd && !useSharedServer) {
|
|
57182
|
+
// Create a temporary config for the override
|
|
57183
|
+
const tempConfig = { ...config, start_command: startCmd };
|
|
57184
|
+
serverProcess = await startHttpServer(tempConfig, workDir, envVars);
|
|
57169
57185
|
}
|
|
57170
57186
|
return await probeServer({
|
|
57171
57187
|
transport: "streamable-http",
|
|
57172
|
-
url:
|
|
57188
|
+
url: serverUrl,
|
|
57173
57189
|
headers,
|
|
57174
57190
|
envVars,
|
|
57175
57191
|
customMessages,
|
|
@@ -57442,13 +57458,18 @@ async function startSharedHttpServer(command, workDir, waitMs, envVars) {
|
|
|
57442
57458
|
}
|
|
57443
57459
|
/**
|
|
57444
57460
|
* Probe a single configuration (without comparison)
|
|
57445
|
-
|
|
57446
|
-
|
|
57447
|
-
|
|
57461
|
+
* @param overrideCommand - If provided, use this command instead of config.start_command
|
|
57462
|
+
* @param overrideUrl - If provided, use this URL instead of config.server_url
|
|
57463
|
+
*/
|
|
57464
|
+
async function probeConfig(config, workDir, envVars, headers, customMessages, useSharedServer, overrideCommand, overrideUrl) {
|
|
57465
|
+
const displayName = overrideCommand
|
|
57466
|
+
? `${config.name} (base: ${overrideCommand.slice(0, 50)}${overrideCommand.length > 50 ? "..." : ""})`
|
|
57467
|
+
: config.name;
|
|
57468
|
+
lib_core.info(` š Probing: ${displayName} (${config.transport})`);
|
|
57448
57469
|
const start = Date.now();
|
|
57449
57470
|
let result;
|
|
57450
57471
|
try {
|
|
57451
|
-
result = await probeWithConfig(config, workDir, envVars, headers, customMessages, useSharedServer);
|
|
57472
|
+
result = await probeWithConfig(config, workDir, envVars, headers, customMessages, useSharedServer, overrideCommand, overrideUrl);
|
|
57452
57473
|
}
|
|
57453
57474
|
finally {
|
|
57454
57475
|
await runPostTestCommand(config, workDir);
|
|
@@ -57491,6 +57512,7 @@ async function runAllTests(ctx) {
|
|
|
57491
57512
|
branchResults.set(config.name, {
|
|
57492
57513
|
result: {
|
|
57493
57514
|
initialize: null,
|
|
57515
|
+
instructions: null,
|
|
57494
57516
|
tools: null,
|
|
57495
57517
|
prompts: null,
|
|
57496
57518
|
resources: null,
|
|
@@ -57511,65 +57533,102 @@ async function runAllTests(ctx) {
|
|
|
57511
57533
|
}
|
|
57512
57534
|
}
|
|
57513
57535
|
// ========================================
|
|
57514
|
-
// PHASE 2: Probe all configs
|
|
57536
|
+
// PHASE 2: Probe all configs for base comparison
|
|
57515
57537
|
// ========================================
|
|
57516
|
-
|
|
57517
|
-
|
|
57518
|
-
|
|
57519
|
-
|
|
57520
|
-
|
|
57521
|
-
|
|
57522
|
-
|
|
57523
|
-
|
|
57524
|
-
|
|
57525
|
-
|
|
57526
|
-
|
|
57527
|
-
|
|
57528
|
-
|
|
57529
|
-
|
|
57530
|
-
let baseServerProcess = null;
|
|
57531
|
-
try {
|
|
57532
|
-
// Start HTTP server for base ref if needed
|
|
57533
|
-
if (useSharedServer) {
|
|
57534
|
-
baseServerProcess = await startSharedHttpServer(httpStartCommand, baseWorkDir, httpStartupWaitMs, globalEnvVars);
|
|
57538
|
+
// Split configs: those with base_start_command use direct probing,
|
|
57539
|
+
// those without need git checkout/worktree
|
|
57540
|
+
const configsWithBaseCommand = ctx.inputs.configurations.filter((c) => c.base_start_command);
|
|
57541
|
+
const configsNeedingGit = ctx.inputs.configurations.filter((c) => !c.base_start_command);
|
|
57542
|
+
// PHASE 2a: Probe configs with base_start_command directly (no git operations)
|
|
57543
|
+
if (configsWithBaseCommand.length > 0) {
|
|
57544
|
+
lib_core.info(`\nš Phase 2a: Testing ${configsWithBaseCommand.length} config(s) with explicit base commands...`);
|
|
57545
|
+
for (const config of configsWithBaseCommand) {
|
|
57546
|
+
try {
|
|
57547
|
+
// Use base_start_command/base_server_url for comparison
|
|
57548
|
+
const probeData = await probeConfig(config, ctx.workDir, // Use current workdir since we're not checking out
|
|
57549
|
+
globalEnvVars, globalHeaders, globalCustomMessages, false, // Don't use shared server for base commands
|
|
57550
|
+
config.base_start_command, config.base_server_url);
|
|
57551
|
+
baseResults.set(config.name, probeData);
|
|
57535
57552
|
}
|
|
57536
|
-
|
|
57537
|
-
|
|
57538
|
-
|
|
57539
|
-
|
|
57540
|
-
|
|
57553
|
+
catch (error) {
|
|
57554
|
+
lib_core.error(`Failed to probe ${config.name} with base command: ${error}`);
|
|
57555
|
+
baseResults.set(config.name, {
|
|
57556
|
+
result: {
|
|
57557
|
+
initialize: null,
|
|
57558
|
+
instructions: null,
|
|
57559
|
+
tools: null,
|
|
57560
|
+
prompts: null,
|
|
57561
|
+
resources: null,
|
|
57562
|
+
resourceTemplates: null,
|
|
57563
|
+
customResponses: new Map(),
|
|
57564
|
+
error: String(error),
|
|
57565
|
+
},
|
|
57566
|
+
time: 0,
|
|
57567
|
+
});
|
|
57568
|
+
}
|
|
57569
|
+
}
|
|
57570
|
+
}
|
|
57571
|
+
// PHASE 2b: Probe configs needing git checkout
|
|
57572
|
+
if (configsNeedingGit.length > 0) {
|
|
57573
|
+
lib_core.info(`\nš Phase 2b: Testing comparison ref: ${ctx.compareRef}...`);
|
|
57574
|
+
const worktreePath = external_path_.join(ctx.workDir, ".mcp-diff-base");
|
|
57575
|
+
let useWorktree = false;
|
|
57576
|
+
try {
|
|
57577
|
+
// Set up comparison ref
|
|
57578
|
+
useWorktree = await createWorktree(ctx.compareRef, worktreePath);
|
|
57579
|
+
if (!useWorktree) {
|
|
57580
|
+
lib_core.info(" Worktree not available, using checkout");
|
|
57581
|
+
await checkout(ctx.compareRef);
|
|
57582
|
+
}
|
|
57583
|
+
const baseWorkDir = useWorktree ? worktreePath : ctx.workDir;
|
|
57584
|
+
// Build on base
|
|
57585
|
+
lib_core.info("šØ Building on comparison ref...");
|
|
57586
|
+
await runBuild(baseWorkDir, ctx.inputs);
|
|
57587
|
+
let baseServerProcess = null;
|
|
57588
|
+
try {
|
|
57589
|
+
// Start HTTP server for base ref if needed
|
|
57590
|
+
if (useSharedServer) {
|
|
57591
|
+
baseServerProcess = await startSharedHttpServer(httpStartCommand, baseWorkDir, httpStartupWaitMs, globalEnvVars);
|
|
57541
57592
|
}
|
|
57542
|
-
|
|
57543
|
-
|
|
57544
|
-
|
|
57545
|
-
|
|
57546
|
-
|
|
57547
|
-
|
|
57548
|
-
|
|
57549
|
-
|
|
57550
|
-
|
|
57551
|
-
|
|
57552
|
-
|
|
57553
|
-
|
|
57554
|
-
|
|
57555
|
-
|
|
57593
|
+
for (const config of configsNeedingGit) {
|
|
57594
|
+
const configUsesSharedServer = useSharedServer && config.transport === "streamable-http";
|
|
57595
|
+
try {
|
|
57596
|
+
const probeData = await probeConfig(config, baseWorkDir, globalEnvVars, globalHeaders, globalCustomMessages, configUsesSharedServer);
|
|
57597
|
+
baseResults.set(config.name, probeData);
|
|
57598
|
+
}
|
|
57599
|
+
catch (error) {
|
|
57600
|
+
lib_core.error(`Failed to probe ${config.name} on base ref: ${error}`);
|
|
57601
|
+
baseResults.set(config.name, {
|
|
57602
|
+
result: {
|
|
57603
|
+
initialize: null,
|
|
57604
|
+
instructions: null,
|
|
57605
|
+
tools: null,
|
|
57606
|
+
prompts: null,
|
|
57607
|
+
resources: null,
|
|
57608
|
+
resourceTemplates: null,
|
|
57609
|
+
customResponses: new Map(),
|
|
57610
|
+
error: String(error),
|
|
57611
|
+
},
|
|
57612
|
+
time: 0,
|
|
57613
|
+
});
|
|
57614
|
+
}
|
|
57615
|
+
}
|
|
57616
|
+
}
|
|
57617
|
+
finally {
|
|
57618
|
+
if (baseServerProcess) {
|
|
57619
|
+
lib_core.info("š Stopping base ref HTTP server...");
|
|
57620
|
+
stopHttpServer(baseServerProcess);
|
|
57556
57621
|
}
|
|
57557
57622
|
}
|
|
57558
57623
|
}
|
|
57559
57624
|
finally {
|
|
57560
|
-
|
|
57561
|
-
|
|
57562
|
-
|
|
57625
|
+
// Clean up
|
|
57626
|
+
if (useWorktree) {
|
|
57627
|
+
await removeWorktree(worktreePath);
|
|
57628
|
+
}
|
|
57629
|
+
else {
|
|
57630
|
+
await checkoutPrevious();
|
|
57563
57631
|
}
|
|
57564
|
-
}
|
|
57565
|
-
}
|
|
57566
|
-
finally {
|
|
57567
|
-
// Clean up
|
|
57568
|
-
if (useWorktree) {
|
|
57569
|
-
await removeWorktree(worktreePath);
|
|
57570
|
-
}
|
|
57571
|
-
else {
|
|
57572
|
-
await checkoutPrevious();
|
|
57573
57632
|
}
|
|
57574
57633
|
}
|
|
57575
57634
|
// ========================================
|
|
@@ -57773,6 +57832,7 @@ function saveReport(report, markdown, outputDir) {
|
|
|
57773
57832
|
external_fs_.appendFileSync(githubOutput, `has_differences=${report.diffCount > 0}\n`);
|
|
57774
57833
|
external_fs_.appendFileSync(githubOutput, `passed_count=${report.passedCount}\n`);
|
|
57775
57834
|
external_fs_.appendFileSync(githubOutput, `diff_count=${report.diffCount}\n`);
|
|
57835
|
+
external_fs_.appendFileSync(githubOutput, `total_configs=${report.results.length}\n`);
|
|
57776
57836
|
}
|
|
57777
57837
|
// Also set via core for compatibility
|
|
57778
57838
|
lib_core.setOutput("report_path", mdPath);
|
|
@@ -57780,6 +57840,7 @@ function saveReport(report, markdown, outputDir) {
|
|
|
57780
57840
|
lib_core.setOutput("has_differences", report.diffCount > 0);
|
|
57781
57841
|
lib_core.setOutput("passed_count", report.passedCount);
|
|
57782
57842
|
lib_core.setOutput("diff_count", report.diffCount);
|
|
57843
|
+
lib_core.setOutput("total_configs", report.results.length);
|
|
57783
57844
|
}
|
|
57784
57845
|
/**
|
|
57785
57846
|
* Write a simple summary for PR comments
|
package/dist/types.d.ts
CHANGED
|
@@ -18,6 +18,14 @@ export interface TestConfiguration {
|
|
|
18
18
|
startup_wait_ms?: number;
|
|
19
19
|
/** Command to run after stopping the MCP server for this config (cleanup) */
|
|
20
20
|
post_test_command?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Command to use for the base/comparison server instead of checking out a git ref.
|
|
23
|
+
* When set, skips git operations and uses this command directly for comparison.
|
|
24
|
+
* Useful for comparing against external servers (e.g., docker images of previous releases).
|
|
25
|
+
*/
|
|
26
|
+
base_start_command?: string;
|
|
27
|
+
/** Server URL for base comparison (for HTTP transport with base_start_command) */
|
|
28
|
+
base_server_url?: string;
|
|
21
29
|
}
|
|
22
30
|
export interface CustomMessage {
|
|
23
31
|
id: number;
|
|
@@ -53,6 +61,7 @@ export interface ActionInputs {
|
|
|
53
61
|
}
|
|
54
62
|
export interface ProbeResult {
|
|
55
63
|
initialize: InitializeInfo | null;
|
|
64
|
+
instructions: string | null;
|
|
56
65
|
tools: ToolsResult | null;
|
|
57
66
|
prompts: PromptsResult | null;
|
|
58
67
|
resources: ResourcesResult | null;
|