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]:
reportProgress— progress notifications, auto-wired to the request’s progress token.log— logging 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.