Skip to content

Conversation

@wonderwhy-er
Copy link
Owner

@wonderwhy-er wonderwhy-er commented Nov 4, 2025

User description

Problem

Cline (VSCode extension) displays MCP notifications/message prominently in its UI, creating visual clutter for users. Unlike Claude Desktop which handles notifications gracefully, Cline shows them as visible notifications that disrupt the user experience.
image

Solution

Implemented automatic client detection to disable JSON-RPC notifications specifically for Cline while maintaining them for other clients like Claude Desktop.

@codeant-ai
Copy link
Contributor

codeant-ai bot commented Nov 4, 2025

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

The PR adds client-specific configuration to the MCP stdio transport layer, enabling notifications to be selectively disabled for certain clients. It includes version bumps across configuration and manifest files, new documentation describing the notification architecture and problem statement, and transport modifications to query notification status and support per-client behavior.

Changes

Cohort / File(s) Summary
Configuration and CLI settings
\.claude/settings\.local\.json
New JSON file defining permissions allowing Bash commands for git log, npm run build, chmod, and node execution.
Documentation
CLINE_NOTIFICATION_PROBLEM\.md, CUSTOM_STDIO_EXPLANATION\.md
New markdown documents explaining MCP notification logging challenges, solution approaches, and custom stdio transport architecture with end-to-end flow details.
Version bumps
package\.json, server\.json, src/version\.ts
Version incremented from 0.2.19 to 0.2.20 across manifest and exported version constant.
Transport layer client configuration
src/custom-stdio\.ts
Added public method configureForClient(clientName: string) to enable client-specific notification disabling. Added public getters isNotificationsEnabled and bufferedMessageCount. Modified enableNotifications(), sendLog(), and sendLogNotification() to short-circuit when notifications are disabled for the configured client, with buffered messages flushed to stderr.
Server initialization
src/server\.ts
Integration point calling transport.configureForClient(currentClient.name) after client information is captured during MCP initialization.

Sequence Diagram

sequenceDiagram
    participant MCP Client
    participant Server
    participant Transport as FilteredStdioServerTransport
    participant Console/Stdout

    MCP Client->>Server: initialize(clientInfo)
    activate Server
    Server->>Server: Capture current client name
    Server->>Transport: configureForClient(clientName)
    activate Transport
    Transport->>Transport: Normalize and store client name<br/>Set disableNotifications flag
    deactivate Transport
    
    alt Notifications Disabled for Client
        Server->>Transport: enableNotifications()
        activate Transport
        Transport->>Transport: Flush buffered messages to stderr
        Transport->>Console/Stdout: Write summary to stderr
        Transport->>Transport: Clear buffer, early return
        deactivate Transport
    else Notifications Enabled for Client
        Server->>Transport: enableNotifications()
        activate Transport
        Transport->>MCP Client: Replay buffered log notifications
        Transport->>Transport: Clear buffer, enable notifications
        deactivate Transport
    end
    
    Server->>MCP Client: initialize response
    deactivate Server
    
    Note over Transport: Future messages either<br/>emit as notifications or<br/>pass through based on<br/>client config
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • src/custom-stdio.ts: Requires understanding existing buffering semantics, the new client-specific configuration paths, modified enableNotifications() flow with stderr flushing, and conditional notification short-circuits. The logic branches add meaningful complexity despite being localized.
  • src/server.ts: Simple single-line integration calling the new configureForClient() method; straightforward but depends on understanding transport behavior.
  • Documentation files do not require code review complexity assessment.

Possibly related PRs

  • Fix for cursor #178: Directly builds on the same FilteredStdioServerTransport modifications and transport.configureForClient() call pattern introduced here.
  • Fix server initialization #216: Modifies the same transport and server initialization code paths for managing buffering and notification state, overlapping substantially with notification status exposure.
  • fix: MCP protocol compliance for Linux Warp compatibility #241: Touches custom-stdio.ts notification and initialization buffering behavior, modifying when log notifications are emitted and enableNotifications()/sendLog() control flow.

Suggested reviewers

  • serg33v

Poem

🐰 A rabbit hops through buffered streams,
Configuring transports, fulfilling dreams,
Some clients quiet, some clients loud,
Notifications managed for every crowd,
Version bumped and messages replayed—
The perfect protocol parade! ✨

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title directly and clearly describes the main change: disabling notifications for Cline to prevent UI clutter, which matches the core objective and implementation in the changeset.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch do-not-show-notification-in-cline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codeant-ai codeant-ai bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Nov 4, 2025
@codeant-ai
Copy link
Contributor

codeant-ai bot commented Nov 4, 2025

CodeAnt AI finished reviewing your PR.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3afba4 and 96c6667.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • .claude/settings.local.json (1 hunks)
  • CLINE_NOTIFICATION_PROBLEM.md (1 hunks)
  • CUSTOM_STDIO_EXPLANATION.md (1 hunks)
  • package.json (1 hunks)
  • server.json (1 hunks)
  • src/custom-stdio.ts (5 hunks)
  • src/server.ts (1 hunks)
  • src/version.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-25T16:02:52.184Z
Learnt from: tillahoffmann
Repo: wonderwhy-er/DesktopCommanderMCP PR: 137
File: src/index.ts:160-162
Timestamp: 2025-05-25T16:02:52.184Z
Learning: In stateless MCP server implementations using the modelcontextprotocol/typescript-sdk, the pattern of calling both transport.close() and server.close() in the request close event handler is the official recommended approach according to the documentation at https://github.com/modelcontextprotocol/typescript-sdk.

Applied to files:

  • CUSTOM_STDIO_EXPLANATION.md
  • src/server.ts
📚 Learning: 2025-05-25T16:02:52.184Z
Learnt from: tillahoffmann
Repo: wonderwhy-er/DesktopCommanderMCP PR: 137
File: src/index.ts:160-162
Timestamp: 2025-05-25T16:02:52.184Z
Learning: In stateless MCP server implementations using the modelcontextprotocol/typescript-sdk, the correct pattern is to call both transport.close() and server.close() in the request close event handler. This is the official recommended approach according to the documentation for ensuring complete isolation between requests and preventing request ID collisions in concurrent scenarios.

Applied to files:

  • CUSTOM_STDIO_EXPLANATION.md
  • src/server.ts

Comment on lines +101 to +109
this.clientName = clientName.toLowerCase();

// Detect Cline and disable notifications
if (this.clientName.includes('cline') ||
this.clientName.includes('vscode') ||
this.clientName === 'claude-dev') {
this.disableNotifications = true;
process.stderr.write(`[INFO] Desktop Commander: Notifications disabled for ${clientName}\n`);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Reset disableNotifications for non-Cline clients

Once disableNotifications is set to true it never gets flipped back, so if a Cline session connects first, every subsequent client (e.g., Claude Desktop) will also have notifications suppressed in the same process. Please reset this.disableNotifications to false before applying the client-specific checks so the flag reflects the current client.

   public configureForClient(clientName: string) {
     this.clientName = clientName.toLowerCase();
-    
-    // Detect Cline and disable notifications
-    if (this.clientName.includes('cline') || 
-        this.clientName.includes('vscode') ||
-        this.clientName === 'claude-dev') {
+    // Default to notifications enabled unless explicitly disabled
+    this.disableNotifications = false;
+
+    // Detect Cline-like clients and disable notifications
+    if (this.clientName.includes('cline') || 
+        this.clientName.includes('vscode') ||
+        this.clientName === 'claude-dev') {
       this.disableNotifications = true;
       process.stderr.write(`[INFO] Desktop Commander: Notifications disabled for ${clientName}\n`);
     }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.clientName = clientName.toLowerCase();
// Detect Cline and disable notifications
if (this.clientName.includes('cline') ||
this.clientName.includes('vscode') ||
this.clientName === 'claude-dev') {
this.disableNotifications = true;
process.stderr.write(`[INFO] Desktop Commander: Notifications disabled for ${clientName}\n`);
}
this.clientName = clientName.toLowerCase();
// Default to notifications enabled unless explicitly disabled
this.disableNotifications = false;
// Detect Cline-like clients and disable notifications
if (this.clientName.includes('cline') ||
this.clientName.includes('vscode') ||
this.clientName === 'claude-dev') {
this.disableNotifications = true;
process.stderr.write(`[INFO] Desktop Commander: Notifications disabled for ${clientName}\n`);
}
🤖 Prompt for AI Agents
In src/custom-stdio.ts around lines 101 to 109, reset this.disableNotifications
to false before performing client-specific checks so the flag reflects the
current client; then run the existing checks (contains 'cline' or 'vscode' or
equals 'claude-dev') and set this.disableNotifications = true only when the
current client meets those conditions and log the message—this ensures a new
non-Cline client won't inherit a previous connection's disabled state.

@wonderwhy-er wonderwhy-er merged commit 2b785ed into main Nov 4, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants