Skip to content

MCP client as a new subproject#138

Merged
kubinio123 merged 39 commits into
masterfrom
136-add-mcp-client-as-a-new-sub-project
May 15, 2026
Merged

MCP client as a new subproject#138
kubinio123 merged 39 commits into
masterfrom
136-add-mcp-client-as-a-new-sub-project

Conversation

@kubinio123
Copy link
Copy Markdown
Contributor

@kubinio123 kubinio123 commented May 13, 2026

DONE:

CODE WISE:

  • McpClient interface defines possible interactions client side
  • McpClientImpl actual client implementation
  • Transport[F[_]] main abstraction
    • StdioTransport a library default implementation for stdio, backend agnostic
    • StreamingStdioTransport for backend specific implementations (coming soon) like ZIO, Future, ox or other runtimes
    • HttpTransport a library default implementation for non streaming sttp backends
    • StreamingHttpTransport for backend specific implementations (coming soon); note: some MCP client features require streaming

I am not yet certain of correctness of those abstractions especially streaming ones. I would rather see them as extensions to base StdioTransport and HttpTransport instead. But I think I will get there once implementing a first streaming one soon.

Created a new GH label tier:2 SDK that I will use to flag followup issues when creating a issues "roadmap" for chimp.
Tiers are described here - https://modelcontextprotocol.io/community/sdk-tiers.

@kubinio123 kubinio123 linked an issue May 13, 2026 that may be closed by this pull request
@kubinio123 kubinio123 changed the title 136 add mcp client as a new sub project MCP client as a new subproject May 13, 2026
@kubinio123 kubinio123 force-pushed the 136-add-mcp-client-as-a-new-sub-project branch from 18365ec to ae83b7b Compare May 13, 2026 11:20
kubinio123 added 27 commits May 14, 2026 11:11
…for a short period of time and is gone in 2 last versions, not adopted by official clients
@kubinio123 kubinio123 force-pushed the 136-add-mcp-client-as-a-new-sub-project branch from baa677b to dbdf8bb Compare May 14, 2026 09:14
@kubinio123 kubinio123 requested a review from adamw May 14, 2026 09:22
@kubinio123 kubinio123 marked this pull request as ready for review May 14, 2026 09:38
//> using dep ch.qos.logback:logback-classic:1.5.20

package chimp
package chimp.server
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe the examples should live in a different package, to also show what imports you need

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, updating 👍

@adamw
Copy link
Copy Markdown
Member

adamw commented May 14, 2026

Review by my Claude review agents:

  Findings

  Critical

  - Transport abstraction conflates message-pipe with request/response correlation (client/transport/Transport.scala:8). send(msg): F[Option[JSONRPCMessage]] forces every transport to do correlation: StdioTransport does it via pending +
  SynchronousQueue; HttpTransport only works because the JSON-RPC reply happens to be the HTTP body; both Streaming* traits don't specify how this works. This is also why HttpTransport.onIncoming is a no-op (HttpTransport.scala:70) —
  server-initiated requests over HTTP are impossible today. Correlation should live in McpClientImpl; Transport should just be send: F[Unit] + onIncoming. The author's own uncertainty about streaming flows directly from this.
  - StdioTransport.send blocks indefinitely on q.take() (StdioTransport.scala:102) with no timeout and no cancellation. close() does not unblock waiters: drainPending() only runs when the reader loop ends, and readerThread.interrupt() won't
  interrupt a BufferedReader.readLine() blocked on the pipe (StdioTransport.scala:116-125). To force EOF, close() must also close proc.getInputStream (and ideally drain pending directly).
  - Malformed Accept header in HttpTransport (HttpTransport.scala:30): s"…${MediaType.TextEventStream.toString()}}" — stray trailing }. Some servers will reject the media-type list.

  Warnings

  - Server-notification listener exceptions are silently swallowed (McpClientImpl.scala:103) — at least log them.
  - installIncoming() discards the F effect at construction (McpClientImpl.scala:72); only works because the current transports' onIncoming is eager. Either return F[McpClient[F]] or document the requirement.
  - notificationListeners grows unboundedly with no deregistration (McpClientImpl.scala:194).
  - HttpTransport.scala:27 uses a local var request for an optional header — fold into the builder.

  Suggestions

  - Once correlation moves out of the transport, most of the AtomicReferences in McpClientImpl can go too.
  - serverCapabilities: Option[...] returning state from an AtomicReference is an API smell; the value is also returned from initialize().


val rc: Int =
try
scenario match
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

so we support only two scenarios?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the implementation would support few more already especially auth/* related, they just require some implementation in this file. I didn't want to make the scope of single PR too large.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ok, so currently we do support 2 scenarios, and that's expected :)

McpResponse.JsonResponse((response: JSONRPCMessage).asJson).unit
case other =>
val errorResponse = protocolError(id, JSONRPCErrorCodes.MethodNotFound.code, s"Unknown method: $other")
McpResponse.JsonResponse((errorResponse: JSONRPCMessage).asJson).unit
case Right(JSONRPCMessage.BatchRequest(requests)) =>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what happened to batch requests?

Copy link
Copy Markdown
Contributor Author

@kubinio123 kubinio123 May 15, 2026

Choose a reason for hiding this comment

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

They aren't included anymore in latest spec version. They were there two versions ago (in version 2025-03-26). I thought let's code against the latest spec if we are doing a general rework of the project.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah of course, let's remove then

@kubinio123
Copy link
Copy Markdown
Contributor Author

I've pushed some updates, from the claude review I addressed the ones that doesn't affect Transport as I am currently reworking that on a separate branch as part of #140.

@kubinio123 kubinio123 requested a review from adamw May 15, 2026 07:46
Copy link
Copy Markdown
Member

@adamw adamw left a comment

Choose a reason for hiding this comment

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

Great, let's merge, one thing that we might want to do in this PR or a seaprate one before releasing - update the main README :)

@kubinio123
Copy link
Copy Markdown
Contributor Author

Yep, I will make sure README is up to date before next release. Merging ✅

@kubinio123 kubinio123 merged commit 5cb4331 into master May 15, 2026
@kubinio123 kubinio123 deleted the 136-add-mcp-client-as-a-new-sub-project branch May 15, 2026 10:23
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.

Add MCP client as a new sub project

2 participants