singularity-forge/packages/mcp-server/src/cli.ts

71 lines
2 KiB
TypeScript
Raw Normal View History

/**
feat: Headless Integration Hardening & Release (M002) (#2811) * feat: Migrated headless orchestrator to use execution_complete events,… - "src/headless.ts" - "src/headless-ui.ts" - "src/tests/headless-v2-migration.test.ts" GSD-Task: S06/T02 * test: Wired pi-coding-agent to re-export JSONL utils from @gsd/rpc-clie… - "packages/pi-coding-agent/src/modes/rpc/jsonl.ts" - "packages/pi-coding-agent/package.json" - "packages/rpc-client/src/index.ts" - "packages/rpc-client/src/jsonl.ts" - "packages/rpc-client/src/rpc-client.ts" - "packages/rpc-client/src/rpc-types.ts" - "packages/rpc-client/src/rpc-client.test.ts" - "packages/rpc-client/package.json" GSD-Task: S06/T03 * feat: Wire --resume flag to resolve session IDs via prefix matching and… - "src/headless.ts" - "dist/headless.js" GSD-Task: S01/T01 * test: Added 5 e2e integration tests proving headless JSON batch, SIGINT… - "src/tests/integration/e2e-headless.test.ts" GSD-Task: S01/T02 * test: Updated @gsd/rpc-client and @gsd/mcp-server to 2.52.0 with publis… - "packages/rpc-client/package.json" - "packages/mcp-server/package.json" - "packages/rpc-client/.npmignore" - "packages/mcp-server/.npmignore" GSD-Task: S02/T01 * chore: auto-commit after complete-milestone GSD-Unit: M002-gzq23a * fix: revert jsonl.ts to inline implementation — @gsd-build/rpc-client not available at source-level test time in CI The re-export from @gsd-build/rpc-client fails in CI because tests run against TypeScript source (--experimental-strip-types) before any build step. The npm dependency resolves to node_modules/ which requires dist/ to exist. Reverting to the original inline implementation eliminates the cross-package dependency for source-level imports.
2026-03-26 23:33:22 -06:00
* @gsd-build/mcp-server CLI stdio transport entry point.
*
* Connects the MCP server to stdin/stdout for use by Claude Code,
* Cursor, and other MCP-compatible clients.
*/
import { SessionManager } from './session-manager.js';
import { createMcpServer } from './server.js';
import { loadStoredToolEnvKeys } from './tool-credentials.js';
const MCP_PKG = '@modelcontextprotocol/sdk';
async function main(): Promise<void> {
loadStoredToolEnvKeys();
const sessionManager = new SessionManager();
// Create the configured MCP server with session, interactive, read-only,
// and workflow tools.
const { server } = await createMcpServer(sessionManager);
// Dynamic import for StdioServerTransport (same TS subpath workaround)
const { StdioServerTransport } = await import(`${MCP_PKG}/server/stdio.js`);
const transport = new StdioServerTransport();
// Cleanup handler — stop all sessions before exiting
let cleaningUp = false;
async function cleanup(): Promise<void> {
if (cleaningUp) return;
cleaningUp = true;
process.stderr.write('[gsd-mcp-server] Shutting down...\n');
try {
await sessionManager.cleanup();
} catch {
// swallow cleanup errors
}
try {
await server.close();
} catch {
// swallow close errors
}
process.exit(0);
}
process.on('SIGTERM', () => void cleanup());
process.on('SIGINT', () => void cleanup());
// Handle stdin end — MCP client disconnected
process.stdin.on('end', () => void cleanup());
// Connect and start serving
try {
await server.connect(transport);
process.stderr.write('[gsd-mcp-server] MCP server started on stdio\n');
} catch (err) {
process.stderr.write(
`[gsd-mcp-server] Fatal: failed to start — ${err instanceof Error ? err.message : String(err)}\n`
);
await sessionManager.cleanup();
process.exit(1);
}
}
main().catch((err) => {
process.stderr.write(
`[gsd-mcp-server] Fatal: ${err instanceof Error ? err.message : String(err)}\n`
);
process.exit(1);
});