Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 48 additions & 6 deletions src/custom-stdio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class FilteredStdioServerTransport extends StdioServerTransport {
info: typeof console.info;
};
private originalStdoutWrite: typeof process.stdout.write;
private isInitialized: boolean = false;

constructor() {
super();
Expand All @@ -49,25 +50,61 @@ export class FilteredStdioServerTransport extends StdioServerTransport {
process.stderr.write(`[desktop-commander] Enhanced FilteredStdioServerTransport initialized\n`);
}

/**
* Call this method after MCP initialization is complete to enable JSON-RPC notifications
*/
public enableNotifications() {
this.isInitialized = true;
process.stderr.write(`[desktop-commander] JSON-RPC notifications enabled\n`);
}

/**
* Check if notifications are enabled
*/
public get isNotificationsEnabled(): boolean {
return this.isInitialized;
}

private setupConsoleRedirection() {
console.log = (...args: any[]) => {
this.sendLogNotification("info", args);
if (this.isInitialized) {
this.sendLogNotification("info", args);
} else {
// During initialization, send to stderr to avoid protocol violations
process.stderr.write(`[LOG] ${args.join(' ')}\n`);
}
};

console.info = (...args: any[]) => {
this.sendLogNotification("info", args);
if (this.isInitialized) {
this.sendLogNotification("info", args);
} else {
process.stderr.write(`[INFO] ${args.join(' ')}\n`);
}
};

console.warn = (...args: any[]) => {
this.sendLogNotification("warning", args);
if (this.isInitialized) {
this.sendLogNotification("warning", args);
} else {
process.stderr.write(`[WARN] ${args.join(' ')}\n`);
}
};

console.error = (...args: any[]) => {
this.sendLogNotification("error", args);
if (this.isInitialized) {
this.sendLogNotification("error", args);
} else {
process.stderr.write(`[ERROR] ${args.join(' ')}\n`);
}
};

console.debug = (...args: any[]) => {
this.sendLogNotification("debug", args);
if (this.isInitialized) {
this.sendLogNotification("debug", args);
} else {
process.stderr.write(`[DEBUG] ${args.join(' ')}\n`);
}
};
}

Expand All @@ -87,7 +124,12 @@ export class FilteredStdioServerTransport extends StdioServerTransport {
return this.originalStdoutWrite.call(process.stdout, buffer, encoding, callback);
} else if (trimmed.length > 0) {
// Non-JSON-RPC output, wrap it in a log notification
this.sendLogNotification("info", [buffer.replace(/\n$/, '')]);
if (this.isInitialized) {
this.sendLogNotification("info", [buffer.replace(/\n$/, '')]);
} else {
// During initialization, send to stderr
process.stderr.write(`[STDOUT] ${buffer}`);
}
if (callback) callback();
return true;
}
Expand Down
11 changes: 11 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ async function runServer() {


console.error("Connecting server...");

// Set up event-driven initialization completion handler
server.oninitialized = () => {
// This callback is triggered after the client sends the "initialized" notification
// At this point, the MCP protocol handshake is fully complete
transport.enableNotifications();
process.stderr.write(
`[desktop-commander] MCP fully initialized, notifications enabled\n`
);
};

await server.connect(transport);
console.error("Server connected successfully");
} catch (error) {
Expand Down
3 changes: 2 additions & 1 deletion src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ server.setRequestHandler(InitializeRequestSchema, async (request: InitializeRequ
name: clientInfo.name || 'unknown',
version: clientInfo.version || 'unknown'
};
console.log(`Client connected: ${currentClient.name} v${currentClient.version}`);
// Log to stderr during initialization to avoid protocol violations
process.stderr.write(`[desktop-commander] Client connected: ${currentClient.name} v${currentClient.version}\n`);
}

// Return standard initialization response
Expand Down