Getting Started
Build your first MCP server in Scala.
New to Cats Effect?
If you're coming from Java/Kotlin or haven't used the Typelevel stack before, read Key Concepts first — it covers IO, Resource, and other patterns used throughout this guide.
Installation
Requires Scala 3.7+.
Add the dependencies to your build:
build.sbt
libraryDependencies += "com.github.ingarabr.mcp" %% "server" % "0.2.0"
Or with Bleep:
# bleep.yaml
dependencies:
- com.github.ingarabr.mcp::server:0.2.0
Or with Mill:
build.mill
import mill._, scalalib._
object myserver extends ScalaModule {
def scalaVersion = "3.7.3"
def ivyDeps = Agg(
ivy"com.github.ingarabr.mcp::server:0.2.0"
)
}
The server module includes stdio transport. For HTTP transport, also add server-http4s.
Your First Server
Here's a minimal MCP server with a single tool:
import cats.effect.*
import mcp.protocol.*
import mcp.server.*
// Define the input type as a named tuple with field descriptors
type GreetInput = (name: String, excited: Option[Boolean])
given InputDef[GreetInput] = InputDef[GreetInput](
name = InputField[String]("Name to greet"),
excited = InputField[Option[Boolean]]("Add exclamation marks")
)
object MyServer extends IOApp.Simple {
val greetTool = ToolDef.unstructured[IO, GreetInput](
name = "greet",
description = Some("Greet someone by name")
) { (input, ctx) =>
val mark = if input.excited.getOrElse(false) then "!!!" else "!"
IO.pure(List(Content.Text(s"Hello, ${input.name}$mark")))
}
def run: IO[Unit] = {
(for {
server <- McpServer[IO](
info = Implementation("my-server", "1.0.0"),
tools = List(greetTool)
)
transport <- StdioTransport[IO]()
_ <- server.serve(transport)
} yield ()).useForever
}
}
What's Happening?
- Input type - Define a named tuple with
InputFielddescriptors for schema generation ToolDef.unstructured- Creates a tool that returns raw content (resolvesInputDefviausing)McpServer[IO](...)- Creates a server resource with your primitivesStdioTransport[IO]()- Creates a stdio transport resourceserver.serve(transport)- Connects them together.useForever- Runs until interrupted
Running Your Server
With sbt:
sbt run
With scala-cli (single file):
scala-cli run MyServer.scala
Your server is now listening on stdin/stdout for MCP messages.
Testing with MCP Inspector
The MCP Inspector lets you test your server:
npx @anthropic/mcp-inspector scala-cli run MyServer.scala