sml_mcps
  
小型MCP服务器 -一个最小的同步MCP服务器实现。没有tokio,没有async,只是有效。
为什么?
官方的 rmcp SDK是基于异步/tokio的。对于某些用例来说,这很好,但是:
- 东京是病毒 -一旦你异步了,一切都想异步
- MCP是顺序的 -请求→ 响应→ 请求→ 响应
- 53%的测试覆盖率 -rmcp很年轻,测试不足
- Apache 2已获得许可 -rmcp从MIT切换而来;我们更喜欢麻省理工学院
- 我们想要控制 -我们的核心板条箱是同步的
sml_mcps为我们提供了一个由我们控制的干净、同步的MCP服务器。
特性
[features]
default = ["schema"]
schema = ["dep:schemars"] # JSON Schema generation for tools
http = ["dep:tiny_http"] # Streamable HTTP transport (with SSE)
auth = ["dep:jsonwebtoken"] # JWT validation for hosted
hosted = ["http", "auth"] # Both HTTP and auth用法(标准)
定义您的上下文和工具,然后将它们连接起来:
use sml_mcps::{Server, ServerConfig, StdioTransport, Tool, ToolEnv, CallToolResult, Result, LogLevel};
use serde_json::Value;
// Your shared context
struct AppContext {
counter: i64,
}
// Define a tool
struct IncrementTool;
impl Tool for IncrementTool {
fn name(&self) -> &str { "increment" }
fn description(&self) -> &str { "Increment the counter" }
fn schema(&self) -> Value {
serde_json::json!({
"type": "object",
"properties": {
"amount": { "type": "integer", "description": "Amount to increment by" }
}
})
}
fn execute(&self, args: Value, ctx: &mut AppContext, env: &ToolEnv) -> Result {
let amount = args.get("amount").and_then(|a| a.as_i64()).unwrap_or(1);
ctx.counter += amount;
// Send notification to client
env.log(LogLevel::Info, format!("Counter is now {}", ctx.counter))?;
Ok(CallToolResult::text(format!("Counter: {}", ctx.counter)))
}
}
fn main() -> Result {
let config = ServerConfig {
name: "my-server".to_string(),
version: "1.0.0".to_string(),
instructions: Some("A counter server".to_string()),
};
let mut server = Server::new(config);
server.add_tool(IncrementTool)?;
let context = AppContext { counter: 0 };
let transport = StdioTransport::new();
server.start(transport, context)
}HTTP传输(带SSE的流式HTTP)
随着 http 特征, HttpServer 为您处理所有HTTP样板:
use sml_mcps::{HttpServer, ServerConfig, Tool, ToolEnv, CallToolResult, Result};
use serde_json::Value;
use std::sync::Arc;
use std::sync::atomic::{AtomicI64, Ordering};
struct CounterTool;
impl Tool for CounterTool {
fn name(&self) -> &str { "counter" }
fn description(&self) -> &str { "Increment counter" }
fn schema(&self) -> Value { serde_json::json!({ "type": "object" }) }
fn execute(&self, _args: Value, ctx: &mut AppContext, _env: &ToolEnv) -> Result {
let val = ctx.counter.fetch_add(1, Ordering::SeqCst) + 1;
Ok(CallToolResult::text(format!("Counter: {}", val)))
}
}
struct AppContext {
counter: Arc,
}
fn main() -> Result {
let shared_counter = Arc::new(AtomicI64::new(0));
let config = ServerConfig {
name: "my-http-server".to_string(),
version: "1.0.0".to_string(),
instructions: None,
};
HttpServer::new(config)
.endpoint("/mcp") // optional, this is the default
.with_tools(|server| {
server.add_tool(CounterTool)?;
Ok(())
})
.serve("127.0.0.1:3000", {
let counter = shared_counter.clone();
move || AppContext { counter: counter.clone() }
})
}关键特性:当工具发送通知时(通过 env.log() 或 env.send_progress()), 响应被自动格式化为SSE。对于没有通知的请求,返回纯JSON。
看 examples/http_server.rs 举一个完整的例子。
JWT身份验证
随着 hosted 功能(同时启用 http 和 auth),添加JWT验证:
use sml_mcps::{HttpServer, ServerConfig, auth::JwtValidator};
struct AuthContext {
user_id: String,
tenant_id: String,
}
fn main() -> Result {
let config = ServerConfig {
name: "authenticated-server".to_string(),
version: "1.0.0".to_string(),
instructions: None,
};
HttpServer::new(config)
.with_tools(|server| {
server.add_tool(WhoamiTool)?;
Ok(())
})
.serve_with_auth(
"127.0.0.1:3001",
JwtValidator::hs256(b"your-secret-key"),
|claims| AuthContext {
user_id: claims.user_id().to_string(),
tenant_id: claims.tenant_id().to_string(),
},
)
}验证器支持HS256(对称)和RS256(非对称)算法:
// HS256 (symmetric)
let validator = JwtValidator::hs256(b"your-secret-key");
// RS256 (asymmetric)
let validator = JwtValidator::rs256(&public_key_pem)?;看 examples/http_auth.rs 对于一个完全经过身份验证的服务器。
工具环境
在工具执行期间, ToolEnv 提供:
// Send log notification
env.log(LogLevel::Info, "Processing...")?;
// Send progress update
env.send_progress("token", 0.5, Some(1.0))?;
// Access resources
let uris = env.list_resources();
let resource = env.get_resource("my://resource")?;低级HTTP(高级)
如果你需要自定义HTTP处理,你可以使用 HttpTransport 直接:
use sml_mcps::{Server, ServerConfig, HttpTransport};
use std::sync::{Arc, Mutex};
// In your HTTP handler:
let transport = Arc::new(Mutex::new(HttpTransport::new(request_body)));
server.process_one(transport.clone(), &mut context)?;
let mut t = transport.lock().unwrap();
if t.has_notifications() {
// Return as SSE (Content-Type: text/event-stream)
let sse_body = t.take_sse_response();
} else {
// Return plain JSON (Content-Type: application/json)
let json_body = t.take_response().unwrap_or_default();
}协议版本
实施MCP协议版本 2025-03-26 (流式HTTP)。
不包括什么
- 客户端实现 -这是一个服务器SDK
- 采样/LLM回调 -工具服务器不需要
- 异步任何东西 -通过设计
许可证
麻省理工学院
