Server capabilities

Most tools just answer a request, so serverLogic/handle expose no context. A tool that needs to push to the client while it runs uses streamingServerLogic, which receives a StreamingServerContext[F]:

  • reportProgressprogress notifications, auto-wired to the request’s progress token.

  • loglogging notifications.

Note

Pushing to the client requires an open stream, so a streamingServerLogic tool is registered with addStreamingTool on a StreamingMcpServer, and will not compile on the plain request/response endpoint.

import chimp.server.*
import chimp.protocol.LoggingLevel
import io.circe.{Codec, Json}
import sttp.shared.Identity
import sttp.tapir.*

case class WorkInput(steps: Int) derives Codec, Schema

val work = tool("work")
  .input[WorkInput]
  .streamingServerLogic[Identity]: (_, ctx, _) =>
    ctx.reportProgress(0.5, total = Some(1.0))
    ctx.log(LoggingLevel.Info, Json.fromString("halfway"))
    ToolResult.text("done")

val server = StreamingMcpServer[Identity]().addStreamingTool(work)

Server-wide capabilities are enabled by registering a handler — only what you wire up is advertised: .withCompletion, .withLoggingLevel, .withSubscriptions.