Compare commits
1 Commits
main
...
fix/list-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90b214b57c |
@ -10,6 +10,7 @@
|
||||
|
||||
- Add `mcporter record` and `mcporter replay` helpers for capturing and replaying MCP JSON-RPC traffic, with server filters and daemon-safe manual env setup. (PR #192, thanks @LDMB123)
|
||||
- Prevent direct daemon starts from rebinding over an already-running healthy daemon, avoiding orphaned keep-alive processes during foreground or launch races. (PR #195, thanks @zm2231)
|
||||
- Return a non-zero exit code for explicit `mcporter list <unknown-server>` failures while preserving aggregate list health checks by default. (Issue #203, thanks @theo674)
|
||||
- Reconcile keep-alive daemon metadata with the responding process and serialize daemon startup across parallel clients, preventing duplicate orphaned daemons. (Issue #191, thanks @dtmsyi)
|
||||
- Keep daemon-managed stdio servers warm across repeated `mcporter list` requests instead of treating non-interactive tool listing as a throwaway process. (Issue #188, thanks @robertoronderosjr)
|
||||
|
||||
|
||||
@ -175,7 +175,7 @@ export async function handleList(
|
||||
|
||||
const resolved = resolveServerDefinition(runtime, target, { quiet: flags.quiet });
|
||||
if (!resolved) {
|
||||
maybeSetListExitCode([{ status: 'error' }], flags);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
target = resolved.name;
|
||||
|
||||
@ -330,6 +330,8 @@ describe('CLI list classification and routing', () => {
|
||||
|
||||
it('suggests a server name when the typo is large', async () => {
|
||||
const { handleList } = await cliModulePromise;
|
||||
const previousExitCode = process.exitCode;
|
||||
process.exitCode = undefined;
|
||||
const definition = linearDefinition;
|
||||
const listTools = vi.fn();
|
||||
const runtime = {
|
||||
@ -343,13 +345,17 @@ describe('CLI list classification and routing', () => {
|
||||
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
|
||||
await handleList(runtime, ['zzz']);
|
||||
try {
|
||||
await handleList(runtime, ['zzz']);
|
||||
|
||||
const errorLines = errorSpy.mock.calls.map((call) => call.join(' '));
|
||||
expect(errorLines.some((line) => line.includes('Did you mean linear?'))).toBe(true);
|
||||
expect(listTools).not.toHaveBeenCalled();
|
||||
|
||||
errorSpy.mockRestore();
|
||||
logSpy.mockRestore();
|
||||
const errorLines = errorSpy.mock.calls.map((call) => call.join(' '));
|
||||
expect(errorLines.some((line) => line.includes('Did you mean linear?'))).toBe(true);
|
||||
expect(listTools).not.toHaveBeenCalled();
|
||||
expect(process.exitCode).toBe(1);
|
||||
} finally {
|
||||
errorSpy.mockRestore();
|
||||
logSpy.mockRestore();
|
||||
process.exitCode = previousExitCode;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -37,20 +37,26 @@ function createRuntime(): Runtime {
|
||||
describe('handleList JSON output', () => {
|
||||
it('emits aggregated status counts', async () => {
|
||||
const runtime = createRuntime();
|
||||
const previousExitCode = process.exitCode;
|
||||
process.exitCode = undefined;
|
||||
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
|
||||
await runHandleList(runtime, ['--json']);
|
||||
try {
|
||||
await runHandleList(runtime, ['--json']);
|
||||
|
||||
const payload = JSON.parse(logSpy.mock.calls.at(-1)?.[0] ?? '{}');
|
||||
expect(payload.mode).toBe('list');
|
||||
expect(payload.counts.auth).toBe(1);
|
||||
const healthyEntry = payload.servers.find((entry: { name: string }) => entry.name === 'healthy');
|
||||
expect(healthyEntry.status).toBe('ok');
|
||||
const authEntry = payload.servers.find((entry: { name: string }) => entry.name === 'auth-server');
|
||||
expect(authEntry.status).toBe('auth');
|
||||
expect(authEntry.issue.kind).toBe('auth');
|
||||
|
||||
logSpy.mockRestore();
|
||||
const payload = JSON.parse(logSpy.mock.calls.at(-1)?.[0] ?? '{}');
|
||||
expect(payload.mode).toBe('list');
|
||||
expect(payload.counts.auth).toBe(1);
|
||||
const healthyEntry = payload.servers.find((entry: { name: string }) => entry.name === 'healthy');
|
||||
expect(healthyEntry.status).toBe('ok');
|
||||
const authEntry = payload.servers.find((entry: { name: string }) => entry.name === 'auth-server');
|
||||
expect(authEntry.status).toBe('auth');
|
||||
expect(authEntry.issue.kind).toBe('auth');
|
||||
expect(process.exitCode).toBeUndefined();
|
||||
} finally {
|
||||
logSpy.mockRestore();
|
||||
process.exitCode = previousExitCode;
|
||||
}
|
||||
});
|
||||
|
||||
it('sets a non-zero exit code for unhealthy multi-server checks when requested', async () => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user