π File detail
services/mcp/vscodeSdkMcp.ts
π― Use case
This file lives under βservices/β, which covers long-lived services (LSP, MCP, OAuth, tool execution, memory, compaction, voice, settings sync, β¦). On the API surface it exposes LogEventNotificationSchema, notifyVscodeFileUpdated, and setupVscodeSdkMcp β mainly functions, hooks, or classes. Dependencies touch src and schema validation. It composes internal code from utils, analytics, and types (relative imports). What the file header says: Mirror of AutoModeEnabledState in permissionSetup.ts β inlined because that file pulls in too many deps for this thin IPC module.
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
Mirror of AutoModeEnabledState in permissionSetup.ts β inlined because that file pulls in too many deps for this thin IPC module.
π€ Exports (heuristic)
LogEventNotificationSchemanotifyVscodeFileUpdatedsetupVscodeSdkMcp
π External import roots
Package roots from from "β¦" (relative paths omitted).
srczod
π₯οΈ Source preview
import { logForDebugging } from 'src/utils/debug.js'
import { z } from 'zod/v4'
import { lazySchema } from '../../utils/lazySchema.js'
import {
checkStatsigFeatureGate_CACHED_MAY_BE_STALE,
getFeatureValue_CACHED_MAY_BE_STALE,
} from '../analytics/growthbook.js'
import { logEvent } from '../analytics/index.js'
import type { ConnectedMCPServer, MCPServerConnection } from './types.js'
// Mirror of AutoModeEnabledState in permissionSetup.ts β inlined because that
// file pulls in too many deps for this thin IPC module.
type AutoModeEnabledState = 'enabled' | 'disabled' | 'opt-in'
function readAutoModeEnabledState(): AutoModeEnabledState | undefined {
const v = getFeatureValue_CACHED_MAY_BE_STALE<{ enabled?: string }>(
'tengu_auto_mode_config',
{},
)?.enabled
return v === 'enabled' || v === 'disabled' || v === 'opt-in' ? v : undefined
}
export const LogEventNotificationSchema = lazySchema(() =>
z.object({
method: z.literal('log_event'),
params: z.object({
eventName: z.string(),
eventData: z.object({}).passthrough(),
}),
}),
)
// Store the VSCode MCP client reference for sending notifications
let vscodeMcpClient: ConnectedMCPServer | null = null
/**
* Sends a file_updated notification to the VSCode MCP server. This is used to
* notify VSCode when files are edited or written by Claude.
*/
export function notifyVscodeFileUpdated(
filePath: string,
oldContent: string | null,
newContent: string | null,
): void {
if (process.env.USER_TYPE !== 'ant' || !vscodeMcpClient) {
return
}
void vscodeMcpClient.client
.notification({
method: 'file_updated',
params: { filePath, oldContent, newContent },
})
.catch((error: Error) => {
// Do not throw if the notification failed
logForDebugging(
`[VSCode] Failed to send file_updated notification: ${error.message}`,
)
})
}
/**
* Sets up the speicial internal VSCode MCP for bidirectional communication using notifications.
*/
export function setupVscodeSdkMcp(sdkClients: MCPServerConnection[]): void {
const client = sdkClients.find(client => client.name === 'claude-vscode')
if (client && client.type === 'connected') {
// Store the client reference for later use
vscodeMcpClient = client
client.client.setNotificationHandler(
LogEventNotificationSchema(),
async notification => {
const { eventName, eventData } = notification.params
logEvent(
`tengu_vscode_${eventName}`,
eventData as { [key: string]: boolean | number | undefined },
)
},
)
// Send necessary experiment gates to VSCode immediately.
const gates: Record<string, boolean | string> = {
tengu_vscode_review_upsell: checkStatsigFeatureGate_CACHED_MAY_BE_STALE(
'tengu_vscode_review_upsell',
),
tengu_vscode_onboarding: checkStatsigFeatureGate_CACHED_MAY_BE_STALE(
'tengu_vscode_onboarding',
),
// Browser support.
tengu_quiet_fern: getFeatureValue_CACHED_MAY_BE_STALE(
'tengu_quiet_fern',
false,
),
// In-band OAuth via claude_authenticate (vs. extension-native PKCE).
tengu_vscode_cc_auth: getFeatureValue_CACHED_MAY_BE_STALE(
'tengu_vscode_cc_auth',
false,
),
}
// Tri-state: 'enabled' | 'disabled' | 'opt-in'. Omit if unknown so VSCode
// fails closed (treats absent as 'disabled').
const autoModeState = readAutoModeEnabledState()
if (autoModeState !== undefined) {
gates.tengu_auto_mode_state = autoModeState
}
void client.client.notification({
method: 'experiment_gates',
params: { gates },
})
}
}