Skip to content

Commit 62802fb

Browse files
committed
release: v2.7.246 lazy MCP deferred startup semantics
1 parent 04ff0ef commit 62802fb

File tree

7 files changed

+102
-6
lines changed

7 files changed

+102
-6
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
All notable changes to this project will be documented in this file.
66

7+
## [2.7.246] — 2026-03-16
8+
9+
- changed(core/mcp): `packages/core/src/MCPServer.ts` now honors lifecycle lazy-session mode during startup and skips eager `warmAdvertisedServers()` preconnects when lazy mode is enabled, preventing downstream MCP binaries from auto-spawning at boot.
10+
- changed(core/startup-status): `packages/core/src/routers/startupStatus.ts` + `packages/core/src/routers/systemProcedures.ts` now treat resident always-on warmup as optional in lazy mode, so startup readiness reflects deferred-on-demand MCP behavior instead of requiring preconnected always-on runtimes.
11+
- test(core/startup-status): `packages/core/src/routers/startupStatus.test.ts` adds regression coverage for lazy-mode readiness semantics.
12+
- test(validation): revalidated targeted startup-status suite and strict TypeScript gates (`vitest startupStatus`, `CORE_TSC_OK`, `WEB_TSC_OK`).
13+
714
## [2.7.245] — 2026-03-16
815

916
- changed(web/billing): `apps/web/src/app/dashboard/billing/page.tsx` adds fallback-history triage controls for **cause** and **task** filtering, including dynamic facet counts and scoped-result rendering.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.7.245
1+
2.7.246

VERSION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# Borg Project Version: 2.7.245
1+
# Borg Project Version: 2.7.246

packages/core/src/MCPServer.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ import { createCouncilTools } from "./mcp/tools/council_tools.js";
159159
import { NativeSessionMetaTools } from "./mcp/NativeSessionMetaTools.js";
160160
import { jsonConfigProvider } from './services/config/JsonConfigProvider.js';
161161
import { configImportService } from './services/config-import.service.js';
162+
import { mcpServerPool } from './services/mcp-server-pool.service.js';
162163
import {
163164
applyBridgeClientHello,
164165
buildBridgeManifest,
@@ -3138,7 +3139,12 @@ export class MCPServer {
31383139
})),
31393140
source: inventory.source,
31403141
});
3141-
this.mcpAggregator.warmAdvertisedServers();
3142+
const { lazySessionMode } = mcpServerPool.getLifecycleModes();
3143+
if (lazySessionMode) {
3144+
mcpServerDebugLog('[MCPServer] Lazy MCP session mode enabled; skipping eager advertised-server warmup.');
3145+
} else {
3146+
this.mcpAggregator.warmAdvertisedServers();
3147+
}
31423148
})
31433149
.catch(e => console.error("[MCPServer] Aggregator Init Failed:", e));
31443150

packages/core/src/routers/startupStatus.test.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,4 +767,80 @@ describe('buildStartupStatusSnapshot', () => {
767767
ready: false,
768768
}));
769769
});
770+
771+
it('treats resident always-on warmup as optional when lazy MCP sessions are enabled', async () => {
772+
const snapshot = await buildStartupStatusSnapshot({
773+
mcpServer: {
774+
memoryManager: {},
775+
isMemoryInitialized: true,
776+
getBridgeStatus: () => ({
777+
ready: true,
778+
clientCount: 0,
779+
clients: [],
780+
supportedCapabilities: [],
781+
supportedHookPhases: [],
782+
}),
783+
},
784+
aggregator: {
785+
getInitializationStatus: () => ({
786+
inProgress: false,
787+
initialized: true,
788+
connectedClientCount: 0,
789+
configuredServerCount: 4,
790+
}),
791+
},
792+
agentMemory: {},
793+
browserService: {},
794+
browserStatus: { active: false, pageCount: 0, pageIds: [] },
795+
sessionSupervisor: {
796+
getRestoreStatus: () => ({
797+
lastRestoreAt: 1_700_000_000_000,
798+
restoredSessionCount: 0,
799+
autoResumeCount: 0,
800+
}),
801+
},
802+
sessionCount: 0,
803+
mcpConfigService: {
804+
getStatus: () => ({
805+
inProgress: false,
806+
lastCompletedAt: 1_700_000_000_000,
807+
lastSuccessAt: 1_700_000_000_000,
808+
lastServerCount: 4,
809+
lastToolCount: 16,
810+
}),
811+
},
812+
liveServerCount: 0,
813+
residentLiveServerCount: 0,
814+
warmingServerCount: 0,
815+
failedWarmupServerCount: 0,
816+
lazySessionMode: true,
817+
persistedServerCount: 4,
818+
persistedToolCount: 16,
819+
persistedAlwaysOnServerCount: 2,
820+
persistedAlwaysOnToolCount: 6,
821+
executionEnvironment: {
822+
ready: true,
823+
preferredShellId: 'pwsh',
824+
preferredShellLabel: 'PowerShell 7',
825+
shellCount: 1,
826+
verifiedShellCount: 1,
827+
toolCount: 2,
828+
verifiedToolCount: 2,
829+
harnessCount: 1,
830+
verifiedHarnessCount: 1,
831+
supportsPowerShell: true,
832+
supportsPosixShell: false,
833+
notes: ['Prefer PowerShell 7.'],
834+
},
835+
});
836+
837+
expect(snapshot.ready).toBe(true);
838+
expect(snapshot.checks.mcpAggregator.liveReady).toBe(true);
839+
expect(snapshot.checks.mcpAggregator.residentReady).toBe(true);
840+
expect(snapshot.blockingReasons).not.toEqual(
841+
expect.arrayContaining([
842+
expect.objectContaining({ code: 'mcp_resident_runtime_not_ready' }),
843+
]),
844+
);
845+
});
770846
});

packages/core/src/routers/startupStatus.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ type StartupStatusInput = {
7979
residentLiveServerCount?: number;
8080
warmingServerCount?: number;
8181
failedWarmupServerCount?: number;
82+
lazySessionMode?: boolean;
8283
persistedServerCount: number;
8384
persistedToolCount: number;
8485
persistedAlwaysOnServerCount: number;
@@ -130,6 +131,7 @@ export async function buildStartupStatusSnapshot(input: StartupStatusInput) {
130131
residentLiveServerCount = 0,
131132
warmingServerCount = 0,
132133
failedWarmupServerCount = 0,
134+
lazySessionMode = false,
133135
persistedServerCount,
134136
persistedToolCount,
135137
persistedAlwaysOnServerCount,
@@ -190,12 +192,14 @@ export async function buildStartupStatusSnapshot(input: StartupStatusInput) {
190192
);
191193
const aggregatorReady = Boolean(aggregatorStatus?.initialized);
192194
const liveReady = mcpReady && aggregatorReady;
193-
const residentReady = liveReady && residentLiveServerCount >= advertisedAlwaysOnServerCount;
195+
const residentReady = lazySessionMode
196+
? liveReady
197+
: liveReady && residentLiveServerCount >= advertisedAlwaysOnServerCount;
194198
const mcpWarmupInProgress = Boolean(
195199
aggregatorStatus?.inProgress
196200
|| configSyncStatus?.inProgress
197201
|| warmingServerCount > 0
198-
|| (inventoryReady && configuredServerCount > 0 && liveServerCount < configuredServerCount),
202+
|| (!lazySessionMode && inventoryReady && configuredServerCount > 0 && liveServerCount < configuredServerCount),
199203
);
200204
const executionReady = Boolean(executionEnvironment?.ready);
201205
const claudeMemEnabled = Boolean(claudeMem?.enabled);
@@ -221,7 +225,7 @@ export async function buildStartupStatusSnapshot(input: StartupStatusInput) {
221225
});
222226
}
223227

224-
if (!residentReady) {
228+
if (!residentReady && !lazySessionMode) {
225229
const residentTarget = persistedAlwaysOnServerCount;
226230
const residentConnected = residentLiveServerCount;
227231
blockingReasons.push({

packages/core/src/routers/systemProcedures.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { detectLocalExecutionEnvironment } from '../services/execution-environme
1818
import { getCachedToolInventory } from '../mcp/cachedToolInventory.js';
1919
import { readClaudeMemStoreStatus } from './memoryRouter.claude-mem.js';
2020
import { summarizeCachedInventory } from './startupInventorySummary.js';
21+
import { mcpServerPool } from '../services/mcp-server-pool.service.js';
2122
import type { MemoryPipelineSummary } from '../services/memory/MemoryManager.js';
2223

2324
const EXECUTION_ENV_CACHE_TTL_MS = Number(process.env.BORG_EXECUTION_ENV_CACHE_TTL_MS ?? 30_000);
@@ -98,6 +99,7 @@ export const systemProcedures = {
9899
).length;
99100
const warmingServerCount = runtimeServers.filter((server) => server.warmupStatus === 'scheduled' || server.warmupStatus === 'warming').length;
100101
const failedWarmupServerCount = runtimeServers.filter((server) => server.warmupStatus === 'failed').length;
102+
const lifecycleModes = mcpServerPool.getLifecycleModes();
101103

102104
const cachedInventorySummary = summarizeCachedInventory(cachedInventory);
103105

@@ -132,6 +134,7 @@ export const systemProcedures = {
132134
residentLiveServerCount,
133135
warmingServerCount,
134136
failedWarmupServerCount,
137+
lazySessionMode: lifecycleModes.lazySessionMode,
135138
persistedServerCount,
136139
persistedToolCount,
137140
persistedAlwaysOnServerCount,

0 commit comments

Comments
 (0)