Skip to content

Add streamable http client transport #147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

devcrocod
Copy link
Contributor

@devcrocod devcrocod commented Jul 14, 2025

#79

Motivation and Context

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@devcrocod devcrocod requested review from e5l and Copilot July 14, 2025 01:51
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Adds a new Streamable HTTP transport implementation for the Model Context Protocol, complete with client extensions and unit tests.

  • Introduces StreamableHttpClientTransport to send JSON-RPC messages over POST and receive via SSE
  • Provides HttpClient extension functions for easy transport/client creation
  • Adds tests and updates dependencies to support mock HTTP interactions

Reviewed Changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTransport.kt Implements the new streamable HTTP transport with SSE and inline-SSE handling
src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpMcpKtorClientExtensions.kt Adds mcpStreamableHttpTransport and mcpStreamableHttp extension functions on HttpClient
src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt Adds a copy method to JSONRPCResponse
src/jvmTest/kotlin/client/StreamableHttpClientTransportTest.kt Unit tests for the new transport, including error handling and header behaviors
gradle/libs.versions.toml Adds ktor-client-mock dependency for testing
api/kotlin-sdk.api Exposes the new transport and extension APIs in the public SDK
Comments suppressed due to low confidence (2)

src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt:249

  • [nitpick] The newly added copy function for JSONRPCResponse lacks KDoc. Consider adding a brief description explaining its purpose and usage.
    public fun copy(

src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpMcpKtorClientExtensions.kt:18

  • [nitpick] Consider adding unit tests for the new extension functions mcpStreamableHttpTransport and mcpStreamableHttp to ensure they configure the transport and client correctly.
public fun HttpClient.mcpStreamableHttpTransport(

val jsonBody = McpJson.encodeToString(message)
val response = client.post(url) {
applyCommonHeaders(this)
headers.append(HttpHeaders.Accept, "${ContentType.Application.Json}, ${ContentType.Text.EventStream}")
Copy link
Preview

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

This appends the Accept header after applyCommonHeaders, which itself appends an Accept header for JSON. Consider consolidating these into a single header call or using headers.set to avoid duplicate Accept entries.

Suggested change
headers.append(HttpHeaders.Accept, "${ContentType.Application.Json}, ${ContentType.Text.EventStream}")
headers.set(HttpHeaders.Accept, "${ContentType.Application.Json}, ${ContentType.Text.EventStream}")

Copilot uses AI. Check for mistakes.

if (response.contentType() == null && body.isBlank()) return

val ct = response.contentType()?.toString() ?: "<none>"
val error = StreamableHttpError(-1, "Unexpected content type: $$ct")
Copy link
Preview

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

The string template uses $$ct which escapes to a literal $ct. To include the actual content type, use $ct instead of $$ct.

Suggested change
val error = StreamableHttpError(-1, "Unexpected content type: $$ct")
val error = StreamableHttpError(-1, "Unexpected content type: $ct")

Copilot uses AI. Check for mistakes.


@Test
fun testTerminateSession() = runTest {
// transport.sessionId = "test-session-id"
Copy link
Preview

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

The test for terminateSession skips setting sessionId, so the method returns early and never sends the DELETE request. Uncomment or set transport.sessionId before calling terminateSession().

Suggested change
// transport.sessionId = "test-session-id"
transport.sessionId = "test-session-id"

Copilot uses AI. Check for mistakes.

}

// @Test
// fun testStoreSessionId() = runTest {
Copy link
Preview

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

[nitpick] There's a commented-out test (testStoreSessionId). If it's not needed, consider removing it, or if it's a work in progress, add a TODO so it's clear why it's disabled.

Suggested change
// fun testStoreSessionId() = runTest {
// fun testStoreSessionId() = runTest {
// // TODO: This test is currently disabled. It needs further development or debugging
// // to verify the handling of session IDs. Uncomment and complete the test when ready.

Copilot uses AI. Check for mistakes.

e5l
e5l previously approved these changes Jul 14, 2025
Copy link
Contributor

@e5l e5l left a comment

Choose a reason for hiding this comment

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

lgtm, could you add end2end test on notification schema as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants