Type-safe Model Context Protocol (MCP 2025-11-25) server and client implementation in MoonBit.
Version: 0.13.4 · Protocol: 2025-11-25 · License: Apache-2.0
moon add colmugx/mcpRequires moonbitlang/async (auto-resolved as a dependency).
// 1. Define a tool
struct EchoTool {}
pub impl Tool for EchoTool with name(_) -> String { "echo" }
pub impl Tool for EchoTool with description(_) -> String { "Echo input" }
pub impl Tool for EchoTool with params(_) -> Array[ParamDef] {
[ParamDef::{ name: "text", schema: @core.str_schema(desc="Text"), required: true }]
}
pub impl Tool for EchoTool with async execute(_, args) -> ToolResult {
match @core.get_string(args, "text") {
Ok(t) => @tool.ToolResult::text("Echo: " + t)
Err(_) => @tool.ToolResult::error("Missing 'text'")
}
}
// 2. Create and run
fn main {
@mcp.mcp_server(name="my-server", version="1.0.0")
.with_tool(EchoTool::{})
.run_stdio() // or .run_http(port=4240)
}Claude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"my-server": {
"command": "moon",
"args": ["run", "path/to/server"]
}
}
}async fn main {
let transport = @transport.AnyTransport::HttpClient(
@transport.HttpClientTransport::new("http://localhost:4240/mcp"),
)
let client = MCPClient::new(name="my-client", version="1.0.0", transport~)
match client.initialize() {
Ok(info) => {
println("Connected to \{info.name}")
match client.list_tools() {
Ok(result) => for t in result.tools { println(" \{t.name}") }
Err(e) => println("Error: \{e.message()}")
}
match client.call_tool("echo", arguments="{\"text\":\"hello\"}") {
Ok(result) => for item in result.content {
match item { Text(t) => println(t) _ => () }
}
Err(e) => println("Error: \{e.message()}")
}
}
Err(e) => println("Init failed: \{e.message()}")
}
client.close()
}For bidirectional mode (handling server-initiated requests), see Client Guide.
MCP 2025-11-25 compliance status:
- JSON-RPC 2.0 (RequestId Int/Str, error codes)
- Lifecycle (initialize + initialized notification)
- Ping
- Tools (list, call, concurrent execution via TaskGroup)
- Resources (list, read, subscribe, unsubscribe)
- Prompts (list, get)
- Logging (setLevel)
- Notifications (tools/resources/prompts list_changed)
- Completions (server-side handler)
- Sampling (
on_samplinghandler, CreateMessageRequest/Result) - Roots (
on_rootshandler, Root type) - Elicitation (
on_elicitationhandler, ElicitationRequest/Result)
- STDIO (server + client)
- HTTP/SSE server (Streamable HTTP, session management)
- HTTP Client (SSE POST, DELETE session, Last-Event-ID)
- WebSocket
- Pagination (cursor/nextCursor on all list methods)
- Bidirectional event loop (
client.run(group)) - 7 notification types (progress, cancelled, resource_updated, etc.)
- ContentItem (Text, Image, ResourceLink, EmbeddedResource Text/Blob)
- SchemaBuilder fluent API
- Authentication (Bearer token, AuthConfig, Protected Resource Metadata)
- Concurrent request handling (@async.TaskGroup)
- Error handling (MCPError hierarchy with JSON-RPC error codes)
- Schema caching (stringified once at registration)
- Session management (Mcp-Session-Id, HTTP DELETE)
- Cross-platform protocol layer (wasm-gc targets)
- Tasks (experimental)
- OAuth 2.1 flow (authorization code + PKCE + token refresh)
- WebSocket transport
- Server-side completions handler
| Document | Description |
|---|---|
| Quickstart | 5-minute setup guide |
| Protocol Types | Type reference (JSON-RPC, errors, ContentItem) |
| Server Guide | Tool/Resource/Prompt registration, SchemaBuilder |
| Transport Reference | STDIO, HTTP/SSE, custom transport |
| Client Guide | Client API, pagination, bidirectional communication |
| Architecture | Three-layer design, cross-platform, performance |
| Host Guide | Multi-server host pattern |
Other: CHANGELOG · Migration Guide · Contributing · MCP Spec
Apache-2.0