FastMCP-Scala
A Scala 3 library for building Model Context Protocol (MCP) servers.
FastMCP-Scala
A high‑level, developer‑friendly Scala 3 library for building Model Context Protocol (MCP) servers.
Features
- ZIO‑based effect handling and async support
- Annotation‑driven API (
@Tool,@Resource,@Prompt) - Automatic JSON Schema & handler generation via Scala 3 macros
- Two transports —
runStdio()orrunHttp()(streamable by default,stateless = truefor lightweight mode) - Seamless integration with the Java MCP SDK 1.0.0
Installation
Add to your build.sbt (defaulting to Scala 3.7.2):
libraryDependencies += "com.tjclp" %% "fast-mcp-scala" % "0.2.3"
Quickstart
//> using scala 3.7.2
//> using dep com.tjclp::fast-mcp-scala:0.2.3
//> using options "-Xcheck-macros" "-experimental"
import com.tjclp.fastmcp.core.{Tool, Param, Prompt, Resource}
import com.tjclp.fastmcp.server.FastMcpServer
import com.tjclp.fastmcp.macros.RegistrationMacro.*
import zio.*
// Define annotated tools, prompts, and resources
object Example:
@Tool(name = Some("add"), description = Some("Add two numbers"))
def add(
@Param("First operand") a: Double,
@Param("Second operand") b: Double
): Double = a + b
@Prompt(name = Some("greet"), description = Some("Generate a greeting message"))
def greet(@Param("Name to greet") name: String): String =
s"Hello, $name!"
@Resource(uri = "file://test", description = Some("Test resource"))
def test(): String = "This is a test"
@Resource(uri = "user://{userId}", description = Some("Test resource"))
def getUser(@Param("The user id") userId: String): String = s"User ID: $userId"
object ExampleServer extends ZIOAppDefault:
override def run =
for
server <- ZIO.succeed(FastMcpServer("ExampleServer", "0.2.0"))
_ <- ZIO.attempt(server.scanAnnotations[Example.type])
_ <- server.runStdio()
yield ()
Running Examples
The above example can be run using scala-cli README.md or scala-cli scripts/quickstart.sc from the repo root. You can run the server via the MCP inspector by running:
npx @modelcontextprotocol/inspector scala-cli README.md
or
npx @modelcontextprotocol/inspector scala-cli scripts/quickstart.sc
You can also run examples directly from the command line:
scala-cli \
-e '//> using dep com.tjclp::fast-mcp-scala:0.2.3' \
--main-class com.tjclp.fastmcp.examples.AnnotatedServer
HTTP Transport (Recommended for Remote)
FastMCP-Scala supports the full MCP Streamable HTTP spec with session management and SSE streaming. Just call runHttp():
//> using scala 3.7.2
//> using dep com.tjclp::fast-mcp-scala:0.2.3
//> using options "-Xcheck-macros" "-experimental"
import com.tjclp.fastmcp.core.{Tool, Param}
import com.tjclp.fastmcp.server.{FastMcpServer, FastMcpServerSettings}
import com.tjclp.fastmcp.macros.RegistrationMacro.*
import zio.*
object StreamableExample:
@Tool(name = Some("greet"), description = Some("Greet someone by name"))
def greet(@Param("Name to greet") name: String): String =
s"Hello, $name!"
object StreamableServer extends ZIOAppDefault:
override def run =
val server = FastMcpServer(
name = "StreamableExample",
version = "0.1.0",
settings = FastMcpServerSettings(port = 8090)
)
for
_ <- ZIO.attempt(server.scanAnnotations[StreamableExample.type])
_ <- server.runHttp()
yield ()
Then test with curl:
# Initialize (returns mcp-session-id header)
curl -s -D- -X POST http://localhost:8090/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
# Call tool (SSE stream response)
curl -N -X POST http://localhost:8090/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: <session-id>" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"greet","arguments":{"name":"World"}}}'
# Delete session
curl -X DELETE http://localhost:8090/mcp -H "mcp-session-id: <session-id>"
Stateless HTTP Transport
For lightweight servers that don't need sessions or SSE, set stateless = true:
//> using scala 3.7.2
//> using dep com.tjclp::fast-mcp-scala:0.2.3
//> using options "-Xcheck-macros" "-experimental"
import com.tjclp.fastmcp.core.{Tool, Param, Resource, Prompt, Message, Role, TextContent}
import com.tjclp.fastmcp.server.{FastMcpServer, FastMcpServerSettings}
import com.tjclp.fastmcp.macros.RegistrationMacro.*
import zio.*
object HttpExample:
@Tool(name = Some("greet"), description = Some("Greet someone by name"))
def greet(@Param("Name to greet") name: String): String =
s"Hello, $name!"
object HttpServer extends ZIOAppDefault:
override def run =
val server = FastMcpServer(
name = "HttpExample",
version = "0.1.0",
settings = FastMcpServerSettings(port = 8090, stateless = true)
)
for
_ <- ZIO.attempt(server.scanAnnotations[HttpExample.type])
_ <- server.runHttp()
yield ()
Then test with curl:
# Initialize
curl -s -X POST http://localhost:8090/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl-test","version":"1.0"}}}'
# Call tool
curl -s -X POST http://localhost:8090/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"greet","arguments":{"name":"World"}}}'
The HTTP transport settings are configured via FastMcpServerSettings:
| Setting | Default | Description |
|---|---|---|
host | 0.0.0.0 | Bind address |
port | 8000 | Listen port |
httpEndpoint | /mcp | JSON-RPC endpoint path |
stateless | false | When true, disables sessions and SSE (stateless mode) |
Integration with Claude Desktop
In Claude desktop, you can add the following to your claude_desktop_config.json:
{
"mcpServers": {
"example-fast-mcp-server": {
"command": "scala-cli",
"args": [
"-e",
"//> using dep com.tjclp::fast-mcp-scala:0.2.3",
"--main-class",
"com.tjclp.fastmcp.examples.AnnotatedServer"
]
}
}
}
Note: FastMCP-Scala example servers are for demo purposes only and don't do anything useful
For additional examples and in‑depth docs, see docs/guide.md.
License
Development Documentation
Developing Locally
When hacking on FastMCP‑Scala itself, you can consume a local build in any project.
🔨 Build Commands (Mill)
FastMCP-Scala uses Mill as its build tool.
# Compile the library
./mill fast-mcp-scala.compile
# Run tests
./mill fast-mcp-scala.test
# Check code formatting
./mill fast-mcp-scala.checkFormat
# Auto-format code
./mill fast-mcp-scala.reformat
# Generate test coverage report
./mill fast-mcp-scala.scoverage.htmlReport
🔨 Publish to the Local Ivy Repository
# From the fast-mcp-scala root
./mill fast-mcp-scala.publishLocal
Then, in your consuming sbt project:
libraryDependencies += "com.tjclp" %% "fast-mcp-scala" % "0.2.4-SNAPSHOT"
Or in Mill:
def ivyDeps = Agg(
ivy"com.tjclp::fast-mcp-scala:0.2.4-SNAPSHOT"
)
publishLocalinstalls the artifact under~/.ivy2/local.
📦 Use the JAR Directly (Unmanaged Dependencies)
# Build the JAR
./mill fast-mcp-scala.jar
# The JAR is located at:
# out/fast-mcp-scala/jar.dest/out.jar
🚀 Using with scala‑cli
You can use fast-mcp-scala in another scala‑cli project:
//> using scala 3.7.2
//> using dep com.tjclp::fast-mcp-scala:0.2.3
//> using options "-Xcheck-macros" "-experimental"
You can also point directly at the local JAR:
//> using scala 3.7.2
//> using jar "/absolute/path/to/out/fast-mcp-scala/jar.dest/out.jar"
//> using options "-Xcheck-macros" "-experimental"
Related Servers
Scout Monitoring MCP
sponsorPut performance and error data directly in the hands of your AI assistant.
Alpha Vantage MCP Server
sponsorAccess financial market data: realtime & historical stock, ETF, options, forex, crypto, commodities, fundamentals, technical indicators, & more
Email MCP Server by Sidemail
Let AI agents write & manage your SaaS emails
QA Sphere
Integration with QA Sphere test management system, enabling LLMs to discover, summarize, and interact with test cases directly from AI-powered IDEs
SEO & Web Analysis MCP Server
Lighthouse audits, PageSpeed analysis, SSL checks, tech stack detection, WHOIS and DNS queries
Damn Vulnerable MCP Server
A server designed to be intentionally vulnerable for security testing and educational purposes.
Neovim MCP Server
Connects any MCP client to the Neovim editor for seamless integration and control.
MCP Server on Cloudflare
A template for deploying a remote MCP server on Cloudflare Workers without authentication.
Pistachio MobileDev MCP
Android + iOS development for non-technical users
Sequential Thinking Multi-Agent System (MAS)
An MCP agent that utilizes a Multi-Agent System (MAS) for sequential thinking and problem-solving.
AIO-MCP Server
An MCP server with integrations for GitLab, Jira, Confluence, and YouTube, providing AI-powered search and development utility tools.
App Market Intelligence MCP
Analyze app data from the Apple App Store and Google Play Store for market intelligence and insights.