Skip to content

Add Streamable HTTP transport support for MCP servers - #4

Closed
bu5hm4nn wants to merge 5 commits into
feature/streaming-http-mcpfrom
auto-claude/004-add-streamable-http-transport-support-for-mcp-serv
Closed

Add Streamable HTTP transport support for MCP servers#4
bu5hm4nn wants to merge 5 commits into
feature/streaming-http-mcpfrom
auto-claude/004-add-streamable-http-transport-support-for-mcp-serv

Conversation

@bu5hm4nn

@bu5hm4nn bu5hm4nn commented Jan 29, 2026

Copy link
Copy Markdown
Owner

User description

test body


PR Type

Enhancement, Tests


Description

  • Add Streamable HTTP transport support for MCP servers (2025-03-26 protocol)

  • Implement health checks and connection tests for streamable-http type

  • Update validation logic to accept streamable-http server configuration

  • Add comprehensive test coverage for HTTP and streamable-http functionality

  • Add UI support with radio option and i18n translations


Diagram Walkthrough

flowchart LR
  A["CustomMcpServer Type"] -->|"Add streamable-http"| B["Type Union"]
  C["Backend Validation"] -->|"Accept streamable-http"| D["_validate_custom_mcp_server"]
  E["Health Check Functions"] -->|"checkStreamableHttpHealth"| F["MCP Health Status"]
  G["Connection Tests"] -->|"testStreamableHttpConnection"| H["MCP Test Result"]
  I["UI Dialog"] -->|"Radio Option"| J["Server Type Selection"]
  K["i18n Locales"] -->|"Add translations"| L["en/fr settings.json"]
Loading

File Walkthrough

Relevant files
Enhancement
project.ts
Add streamable-http to CustomMcpServer type union               

apps/frontend/src/shared/types/project.ts

  • Extended CustomMcpServer.type union to include 'streamable-http'
    alongside 'command' and 'http'
  • Enables type-safe support for streamable HTTP transport specification
+1/-1     
client.py
Update validation to accept streamable-http type                 

apps/backend/core/client.py

  • Updated _validate_custom_mcp_server() to accept 'streamable-http' in
    allowed types tuple
  • Applied same URL/headers validation logic for streamable-http as http
    type
  • Improved error message to show server type in uppercase for clarity
+4/-3     
CustomMcpDialog.tsx
Add streamable-http UI support to CustomMcpDialog               

apps/frontend/src/renderer/components/CustomMcpDialog.tsx

  • Added 'streamable-http' radio option to server type selection group
  • Updated validation logic to treat streamable-http same as http (URL
    required)
  • Updated header building logic to handle streamable-http type
  • Updated isValid check to include streamable-http with URL requirement
  • HTTP-based fields now display for both http and streamable-http types
+12/-5   
mcp-handlers.ts
Add streamable-http health checks and connection tests     

apps/frontend/src/main/ipc-handlers/mcp-handlers.ts

  • Added checkStreamableHttpHealth() function with Accept header
    supporting both 'application/json' and 'text/event-stream'
  • Added testStreamableHttpConnection() function using MCP protocol
    version '2025-03-26'
  • Updated checkMcpHealth() to route streamable-http servers to dedicated
    health check function
  • Updated testMcpConnection() to route streamable-http servers to
    dedicated connection test function
  • Both functions handle timeouts, authentication errors, and connection
    failures with appropriate messages
+227/-2 
Documentation
settings.json
Add English translation for streamable-http                           

apps/frontend/src/shared/i18n/locales/en/settings.json

  • Added 'typeStreamableHttp': 'Streamable HTTP' translation key for UI
    display
+1/-0     
settings.json
Add French translation for streamable-http                             

apps/frontend/src/shared/i18n/locales/fr/settings.json

  • Added 'typeStreamableHttp': 'Streamable HTTP' translation key for
    French locale
+1/-0     
Tests
mcp-handlers.test.ts
Add comprehensive MCP handler test coverage                           

apps/frontend/src/main/ipc-handlers/tests/mcp-handlers.test.ts

  • Comprehensive test suite for HTTP and streamable-http health checks
    with 200, 401, 403 responses
  • Tests for streamable-http Accept header validation ('application/json,
    text/event-stream')
  • Connection test coverage for both HTTP (protocol 2024-11-05) and
    streamable-http (protocol 2025-03-26)
  • Error handling tests for connection refused, server not found,
    timeouts, and missing URLs
  • Command security validation tests for safe commands allowlist and
    dangerous flags detection
  • Mock setup for fetch, spawn, platform detection, and app logger
+1045/-0
test_mcp_validation.py
Add MCP server validation test suite                                         

tests/test_mcp_validation.py

  • Test suite validating _validate_custom_mcp_server() for command, http,
    and streamable-http types
  • Tests for valid server configurations with and without headers
  • Tests rejecting invalid types, missing URLs, empty URLs, and invalid
    header types
  • Tests for dangerous commands and flags rejection
  • Tests for command path separator rejection and unexpected field
    detection
  • Tests validating all safe commands (npx, npm, node, python, python3,
    uv, uvx) are accepted
+238/-0 

bu5hm4nn and others added 5 commits January 29, 2026 12:59
…ype union

Extends the CustomMcpServer.type union to include 'streamable-http' transport
option alongside existing 'command' and 'http' types. This enables support
for the MCP Streamable HTTP transport specification.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…cept 'streamable-http' type

- Add 'streamable-http' to allowed MCP server types tuple
- Update type-specific validation to handle streamable-http with same URL/headers
  validation as http type
- Supports MCP 2025-03-26 streamable HTTP transport specification

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…McpDialog

- Add 'streamable-http' radio option to server type RadioGroup
- Update validation to handle streamable-http same as http (URL required)
- Update header building logic for streamable-http type
- Update isValid check to include streamable-http
- Show HTTP-based fields when streamable-http is selected
- Add translation keys for typeStreamableHttp in en/fr locales

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…er Accept header

- Add checkStreamableHttpHealth() function with Accept header supporting
  both 'application/json' and 'text/event-stream' for MCP protocol
- Add testStreamableHttpConnection() function with protocol version 2025-03-26
- Update checkMcpHealth() to handle 'streamable-http' server type
- Update testMcpConnection() to handle 'streamable-http' server type

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…rt support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
SSRF via user URL

Description: The new streamable-http transport performs fetch() requests to a user-configurable
server.url (GET in checkStreamableHttpHealth and POST in testStreamableHttpConnection),
which can enable SSRF-style access to internal network resources (e.g.,
http://127.0.0.1:..., http://169.254.169.254/...) if an attacker can influence MCP server
configuration.
mcp-handlers.ts [172-575]

Referred Code
async function checkStreamableHttpHealth(server: CustomMcpServer, startTime: number): Promise<McpHealthCheckResult> {
  if (!server.url) {
    return {
      serverId: server.id,
      status: 'unhealthy',
      message: 'No URL configured',
      checkedAt: new Date().toISOString(),
    };
  }

  try {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 10000); // 10 second timeout

    // Streamable HTTP requires Accept header with both JSON and SSE support
    const headers: Record<string, string> = {
      'Accept': 'application/json, text/event-stream',
    };

    // Add custom headers if configured
    if (server.headers) {


 ... (clipped 383 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
URL validation gaps: The newly-accepted streamable-http type reuses the existing URL checks but the diff does
not show any validation/sanitization of URL scheme/format (e.g., restricting to https?),
which may allow unsafe URL inputs depending on how the URL is used downstream.

Referred Code
elif server["type"] in ("http", "streamable-http"):
    if not isinstance(server.get("url"), str) or not server["url"]:
        logger.warning(f"{server['type'].upper()}-type MCP server missing 'url' field")
        return False

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review

Copy link
Copy Markdown

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Refactor duplicated HTTP handling logic

Refactor the duplicated logic in mcp-handlers.ts for handling http and
streamable-http types. Create a single, generalized function for each task
(health check, connection test) to improve maintainability.

Examples:

apps/frontend/src/main/ipc-handlers/mcp-handlers.ts [172-251]
async function checkStreamableHttpHealth(server: CustomMcpServer, startTime: number): Promise<McpHealthCheckResult> {
  if (!server.url) {
    return {
      serverId: server.id,
      status: 'unhealthy',
      message: 'No URL configured',
      checkedAt: new Date().toISOString(),
    };
  }


 ... (clipped 70 lines)
apps/frontend/src/main/ipc-handlers/mcp-handlers.ts [484-613]
async function testStreamableHttpConnection(server: CustomMcpServer, startTime: number): Promise<McpTestConnectionResult> {
  if (!server.url) {
    return {
      serverId: server.id,
      success: false,
      message: 'No URL configured',
    };
  }

  try {

 ... (clipped 120 lines)

Solution Walkthrough:

Before:

// in mcp-handlers.ts
async function checkHttpHealth(server, startTime) {
  if (!server.url) { /* ... */ }
  try {
    const headers = { Accept: 'application/json', ... };
    const response = await fetch(server.url, { method: 'GET', headers });
    // ... handle response for 'http'
  } catch (error) {
    // ... handle fetch errors
  }
}

async function checkStreamableHttpHealth(server, startTime) {
  if (!server.url) { /* ... */ }
  try {
    const headers = { Accept: 'application/json, text/event-stream', ... };
    const response = await fetch(server.url, { method: 'GET', headers });
    // ... handle response for 'streamable-http'
  } catch (error) {
    // ... handle fetch errors
  }
}
// Similar duplication exists for test...Connection functions.

After:

// in mcp-handlers.ts
async function _checkHttpBasedHealth(server, startTime, options) {
  if (!server.url) { /* ... */ }
  try {
    const headers = { Accept: options.acceptHeader, ...server.headers };
    const response = await fetch(server.url, { method: 'GET', headers });
    if (response.ok) {
      return { status: 'healthy', message: options.successMessage, ... };
    }
    // ... generic response handling
  } catch (error) {
    // ... generic error handling
  }
}

function checkMcpHealth(server) {
  if (server.type === 'http' || server.type === 'streamable-http') {
    const options = server.type === 'http'
      ? { acceptHeader: 'application/json', successMessage: '...' }
      : { acceptHeader: 'application/json, text/event-stream', successMessage: '...' };
    return _checkHttpBasedHealth(server, Date.now(), options);
  }
  // ...
}
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies significant code duplication between http and streamable-http handlers in mcp-handlers.ts, and the proposed refactor would greatly improve code quality and maintainability.

Medium
General
Export health check function

Export the checkStreamableHttpHealth function to allow the test suite to import
and test the actual implementation directly, rather than relying on a
re-implemented version.

apps/frontend/src/main/ipc-handlers/mcp-handlers.ts [172]

-async function checkStreamableHttpHealth(server: CustomMcpServer, startTime: number): Promise<McpHealthCheckResult> {
+export async function checkStreamableHttpHealth(server: CustomMcpServer, startTime: number): Promise<McpHealthCheckResult> {
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that the test file mcp-handlers.test.ts re-implements the function logic instead of testing the actual code. Exporting the function would significantly improve the test quality, maintainability, and reliability by ensuring the real implementation is tested.

Medium
Possible issue
Use correct headers for requests

For the tools/list request, use a dedicated headers object that only specifies
Accept: 'application/json' to ensure the server returns a standard JSON response
instead of a potential stream.

apps/frontend/src/main/ipc-handlers/mcp-handlers.ts [571-575]

+const toolsHeaders = { ...headers, 'Accept': 'application/json' };
+
 const toolsResponse = await fetch(server.url, {
   method: 'POST',
-  headers,
+  headers: toolsHeaders,
   body: JSON.stringify(toolsRequest),
 });
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: This is a valid and subtle point. While many servers might handle the broad Accept header gracefully, sending a more specific header for the non-streaming tools/list request improves robustness and adherence to protocol, preventing potential issues with stricter server implementations.

Low
  • More

@bu5hm4nn bu5hm4nn closed this Jan 29, 2026
@bu5hm4nn
bu5hm4nn deleted the auto-claude/004-add-streamable-http-transport-support-for-mcp-serv branch January 29, 2026 11:17
@bu5hm4nn
bu5hm4nn restored the auto-claude/004-add-streamable-http-transport-support-for-mcp-serv branch January 29, 2026 11:19
bu5hm4nn pushed a commit that referenced this pull request Feb 9, 2026
…ndyMik90#1747)

* auto-claude: subtask-1-1 - Add errorCode propagation in reactiveTokenRefresh()

* auto-claude: subtask-1-2 - Return null instead of revoked token for permanent errors in ensureValidToken()

* auto-claude: subtask-1-3 - Clear credential cache on invalid_grant error in refreshOAuthToken()

* auto-claude: subtask-1-4 - Clear revoked credentials on persistence failure (Bug #5)

When token refresh succeeds but persistence to keychain fails, the old
credentials in the keychain are now revoked server-side. This commit adds
defensive cache clearing in both ensureValidToken() and reactiveTokenRefresh()
to prevent serving revoked tokens from cache.

On app restart, Bugs #3 and #4 fixes will handle the revoked credentials
properly by returning null and clearing the cache, forcing re-authentication.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* auto-claude: subtask-2-1 - Move authFailedProfiles marking before early return

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant