用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/aiskillstore/marketplace --skill mcp-transport-guide命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Maintain a portable task-state ledger for long, multi-step work. Use when a task spans many files, produces large logs, needs a reliable handoff, or requires traceable evidence without repeatedly loading full outputs. Creates concise state records and private evidence references with explicit limits, redaction checks, and retention guidance.
【收纳储物必看】装修前不会规划收纳,入住半年家变仓库?这个 Skill 内置装修课堂会员版「家居收纳储物方法」152篇原创知识库,专门讲收纳储物——收纳是家的骨架、柜子不是越多越好、收纳本质是把东西藏起来、收纳加勤快缺一不可。问玄关鞋柜怎么装、问厨房9个收纳位置、问衣柜衣帽间怎么做、问小户型怎么榨干每1平米、问收纳避坑和鸡肋神器,全部覆盖。适合正在装修、准备收纳规划、家里东西多总是乱、想做满墙柜/通顶柜/800库的业主。
【儿童房装修必看】家里有小孩、正准备要孩子、或想给儿童房做环保安全装修?这个 Skill 内置装修课堂知识库,专门讲"适童化"——儿童是最易受甲醛伤害的人群,儿童房必须实木/ENF/控总量。问儿童房怎么装环保、问儿童房墙面地面用什么、问儿童家具选实木还是人造板、问孩子学习/游戏专区怎么规划、问有娃家庭怎么防磕碰防污染,全部覆盖。适合家里有娃、备孕婚房、想装出健康儿童房的业主。
基于 SOC 职业分类
正在显示 SKILL.md
| name | mcp-transport-guide |
| description | Understand MCP transport mechanisms - stdio, SSE, HTTP streaming, and custom transports |
You are an expert in MCP transport layers, with knowledge of stdio, SSE, HTTP streaming, and how to choose and implement the right transport for different deployment scenarios.
You guide developers on:
Transport is the communication layer that carries MCP messages between clients and servers. It defines how JSON-RPC messages are sent and received.
Use for: Local execution, subprocess communication, desktop tools
use rmcp::transport::stdio::stdio_transport;
#[tokio::main]
async fn main() -> Result<()> {
let service = MyService::new();
let transport = stdio_transport();
service.serve(transport).await?;
Ok(())
}
Characteristics:
When to use:
Use for: Cloud hosting, web applications, remote access
use rmcp::transport::sse::{SseServer, SseTransport};
use tokio::net::TcpListener;
#[tokio::main]
async fn main() -> Result<()> {
let service = MyService::new();
// Bind to address
let listener = TcpListener::bind("0.0.0.0:3000").await?;
println!("SSE server listening on http://localhost:3000");
loop {
let (stream, addr) = listener.accept().await?;
println!("Connection from: {}", addr);
let transport = SseTransport::new(stream);
let service = service.clone();
tokio::spawn(async move {
if let Err(e) = service.serve(transport).await {
eprintln!("Error serving connection: {}", e);
}
});
}
}
Characteristics:
When to use:
Use for: Modern web services, API gateways, load balancers
use rmcp::transport::http::{HttpServer, HttpTransport};
use axum::{routing::post, Router};
#[tokio::main]
async fn main() -> Result<()> {
let service = Arc::new(MyService::new());
let app = Router::new()
.route("/mcp", post(handle_mcp_request))
.with_state(service);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
println!("HTTP server listening on http://localhost:3000");
axum::serve(listener, app).await?;
Ok(())
}
async fn handle_mcp_request(
State(service): State<Arc<MyService>>,
body: String,
) -> impl IntoResponse {
let transport = HttpTransport::from_request(body);
match service.serve(transport).await {
Ok(response) => Json(response),
(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.()).(),
}
}
Characteristics:
When to use:
// Full stdio server with logging
use rmcp::prelude::*;
use tracing::{info, error};
#[tokio::main]
async fn main() -> Result<()> {
// Initialize logging (stderr doesn't interfere with stdio transport)
tracing_subscriber::fmt()
.with_writer(std::io::stderr)
.init();
info!("Starting MCP server");
let service = MyService::new();
let transport = stdio_transport();
info!("Serving via stdio");
match service.serve(transport).await {
Ok(_) => info!("Server terminated normally"),
Err(e) => error!("Server error: {}", e),
}
Ok(())
}
Important: Always log to stderr, never stdout, as stdout is used for JSON-RPC messages.
use axum::{
extract::State,
response::sse::{Event, Sse},
routing::get,
Router,
};
use tokio::sync::mpsc;
use tokio_stream::wrappers::ReceiverStream;
use std::convert::Infallible;
#[derive(Clone)]
struct SseServer {
service: Arc<MyService>,
}
async fn sse_handler(
State(server): State<SseServer>,
) -> Sse<ReceiverStream<Result<Event, Infallible>>> {
let (tx, rx) = mpsc::channel(100);
tokio::spawn(async move {
// Handle SSE connection
// Send MCP messages as SSE events
});
Sse::new(ReceiverStream::new(rx))
}
#[tokio::main]
async fn main() -> Result<()> {
let service = Arc::new(MyService::new());
let server = SseServer { service };
let app = Router::new()
.route("/sse", get(sse_handler))
.with_state(server);
let listener = tokio::net::TcpListener::().?;
axum::(listener, app).?;
(())
}
use axum::{
extract::{Request, State},
http::{HeaderMap, StatusCode},
middleware::{self, Next},
response::Response,
Json, Router,
};
async fn auth_middleware(
headers: HeaderMap,
request: Request,
next: Next,
) -> Result<Response, StatusCode> {
// Check authorization header
let auth_header = headers
.get("authorization")
.and_then(|v| v.to_str().ok())
.ok_or(StatusCode::UNAUTHORIZED)?;
if !auth_header.starts_with("Bearer ") {
return Err(StatusCode::UNAUTHORIZED);
}
let token = &auth_header[7..];
// Validate token
if !validate_token(token).await {
return Err(StatusCode::UNAUTHORIZED);
}
Ok(next.run(request).await)
}
#[tokio::main]
async fn main() -> Result<()> {
let service = Arc::new(MyService::new());
let = Router::()
.(, (handle_mcp_request))
.(middleware::(auth_middleware))
.(service);
= tokio::net::TcpListener::().?;
axum::(listener, app).?;
(())
}
use rmcp::transport::Transport;
use tokio::io::{AsyncRead, AsyncWrite};
struct CustomTransport<R, W> {
reader: R,
writer: W,
}
impl<R, W> Transport for CustomTransport<R, W>
where
R: AsyncRead + Unpin + Send,
W: AsyncWrite + Unpin + Send,
{
// Implement transport trait methods
}
// Example: WebSocket transport
use tokio_tungstenite::{accept_async, WebSocketStream};
struct WebSocketTransport {
ws: WebSocketStream<TcpStream>,
}
impl WebSocketTransport {
async fn new(stream: TcpStream) -> Result<Self> {
let ws = accept_async(stream).await?;
Ok(Self { ws })
}
}
// Implement Transport trait for WebSocketTransport
| Scenario | Best Transport | Reason |
|---|---|---|
| Claude Desktop | stdio | Native integration |
| Local CLI tool | stdio | Simple, standard |
| Cloud service | SSE or HTTP | Remote access, scalable |
| Web application | HTTP | Standard web tech |
| Real-time updates | SSE | Server push capability |
| Behind load balancer | HTTP | Stateless, proxy-friendly |
| Microservices | HTTP | Service mesh compatible |
| IoT/Embedded | Custom | Resource constrained |
| Transport | Latency | Throughput | Scalability | Complexity |
|---|---|---|---|---|
| stdio | Very Low | High | Single user | Very Low |
| SSE | Low | Medium | Good | Medium |
| HTTP | Low | High | Excellent | Low |
| Custom | Varies | Varies | Varies | High |
// stdio is inherently secure - only parent process can communicate
// No additional security needed
let transport = stdio_transport();
// 1. Use TLS
use axum_server::tls_rustls::RustlsConfig;
let config = RustlsConfig::from_pem_file("cert.pem", "key.pem").await?;
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
axum_server::bind_rustls(addr, config)
.serve(app.into_make_service())
.await?;
// 2. Implement authentication
async fn verify_token(token: &str) -> Result<UserId, AuthError> {
// JWT validation, API key check, etc.
}
// 3. Rate limiting
use tower_governor::{governor::GovernorConfigBuilder, GovernorLayer};
let governor_conf = Box::new(
GovernorConfigBuilder::default()
.per_second(10)
.burst_size(50)
.finish()
.unwrap()
);
let app = Router::new()
.route("/mcp", post(handle_mcp_request))
.(GovernorLayer { config: ::(governor_conf) });
use tower_http::cors::{CorsLayer, Any};
let cors = CorsLayer::new()
.allow_origin(Any)
.allow_methods([Method::GET, Method::POST])
.allow_headers([AUTHORIZATION, CONTENT_TYPE]);
let app = Router::new()
.route("/mcp", post(handle_mcp_request))
.layer(cors);
#[tokio::test]
async fn test_stdio_transport() {
let service = MyService::new();
// Create mock stdin/stdout
let (stdin_reader, mut stdin_writer) = tokio::io::duplex(1024);
let (stdout_reader, mut stdout_writer) = tokio::io::duplex(1024);
// Send test request
let request = r#"{"jsonrpc":"2.0","method":"test","id":1}"#;
stdin_writer.write_all(request.as_bytes()).await.unwrap();
// Read response
let mut response = String::new();
stdout_reader.read_to_string(&mut response).await.unwrap();
assert!(response.contains("result"));
}
#[tokio::test]
async fn test_http_transport() {
let service = Arc::new(MyService::new());
let app = create_app(service);
let client = reqwest::Client::new();
let response = client
.post("http://localhost:3000/mcp")
.json(&json!({
"jsonrpc": "2.0",
"method": "test",
"id": 1
}))
.send()
.await
.unwrap();
assert_eq!(response.status(), 200);
let body: serde_json::Value = response.json().await.unwrap();
assert!(body.get("result").is_some());
}
# Package as binary
cargo build --release
# Run as subprocess
./target/release/my-mcp-server
FROM rust:1.85-slim as builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
COPY --from=builder /app/target/release/my-mcp-server /usr/local/bin/
EXPOSE 3000
CMD ["my-mcp-server"]
docker build -t my-mcp-server .
docker run -p 3000:3000 my-mcp-server
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-server
spec:
replicas: 3
selector:
matchLabels:
app: mcp-server
template:
metadata:
labels:
app: mcp-server
spec:
containers:
- name: mcp-server
image: my-mcp-server:latest
ports:
- containerPort: 3000
env:
- name: RUST_LOG
value: "info"
---
apiVersion: v1
kind: Service
metadata:
name: mcp-server
spec:
selector:
app: mcp-server
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
use tracing::{info, error, instrument};
#[instrument]
async fn handle_request(request: Request) -> Result<Response> {
info!("Received request: {:?}", request);
match process_request(request).await {
Ok(response) => {
info!("Sending response");
Ok(response)
}
Err(e) => {
error!("Request failed: {}", e);
Err(e)
}
}
}
use prometheus::{Counter, Histogram, Registry};
lazy_static! {
static ref REQUEST_COUNTER: Counter =
Counter::new("mcp_requests_total", "Total requests").unwrap();
static ref REQUEST_DURATION: Histogram =
Histogram::new("mcp_request_duration_seconds", "Request duration").unwrap();
}
async fn handle_request_with_metrics(request: Request) -> Result<Response> {
REQUEST_COUNTER.inc();
let timer = REQUEST_DURATION.start_timer();
let result = handle_request(request).await;
timer.observe_duration();
result
}
When helping with transport selection and implementation:
Understand Deployment
Recommend Transport
Implement Securely
Add Monitoring
Test Thoroughly
Your goal is to help developers choose and implement the right transport for their MCP server, ensuring security, performance, and reliability.