HTTP MCP服务器

一个基于Rust SDK的远程HTTP MCP服务器教程,适用于开发者快速搭建和测试MCP服务。

  • by OscarSaharoy
  • Rust
  • 本地部署
  • 更新于
在 GitHub 查看 oscarsaharoy/mcp-server-scaffold

使用说明

HTTP MCP服务器教程

出于某种原因,很难找到一个好的MCP服务器教程:(大多数都是人工智能生成的)

此仓库包含创建远程HTTP MCP服务器的步骤。

检查您的MCP服务器是否正常工作

在开发过程中检查MCP服务器是否正常工作是有帮助的——这可以通过 MCP检查器工具.

你可以跑 npx @modelcontextprotocol/inspector 然后,它为您提供了一个用户界面,以便在运行过程中测试您的服务器。

使用哪个SDK

我认为rust SDK是最好的,因为有API文档可用(https://docs.rs/rmcp/0.4.1/rmcp/).要使用它,您需要 安装铁锈.

如何部署它

对于远程MCP服务器(使用HTTP传输而不是stdio),您需要使用web可访问的URL来托管它,以便人们可以向其发送请求。

然而,你可以在EC2实例或类似的甚至自托管上这样做,但我认为 Vercel功能 最适合最简单的开发、最低的成本和最成熟的防锈剂。因此,对于本地开发,您需要安装 vercel命令行界面 (npm i -g vercel).

[!注意] 我发现,如果你的网络连接速度很慢,这个堆栈可能很难使用,因为有很多东西需要下载和构建——如果因为这个原因不起作用,很抱歉。

入门

以下是如何使用rust SDK创建通过HTTP运行MCP服务器的最小代码:

1.创建 Cargo.toml

您可以使用这些命令创建最小 Cargo.toml 并添加依赖关系:

这 [[bin]] 为了使vercel函数正常工作,需要一个部分。

cargo init
cat << EOF >> Cargo.toml
tokio = { version = "1.47.1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
rmcp = { version = "0.2.0", features = ["server", "transport-streamable-http-server-session", "transport-sse-server", "transport-worker", "transport-streamable-http-server"] }
vercel_runtime = { version = "1" }
tower = "0.5.2"
http-body-util = "0.1.3"

[[bin]]
name = "mcp"
path = "api/mcp.rs"
EOF

您可以通过运行以下命令来测试您的基础生锈项目是否正常工作 cargo run -编译后,它应该打印“Hello,World!”:)

2.创建 vercel.json 和 .vercelignore

vercel.json 是配置vercel以能够为您的MCP工具提供服务的文件:)这指定了位于 api/mcp.rs 这是一个vercel功能,可以在 /api/mcp 当我们部署到网络时的路径(它将在 http://localhost:3000/api/mcp 在开发过程中,当你运行 vercel dev).

cat << EOF > vercel.json
{
  "functions": {
    "api/mcp.rs": {
      "runtime": "vercel-rust@4.0.9"
    }
  }
}
EOF

.vercelignore 只是告诉维塞尔不要上传生锈的人工制品,因为它们可能非常大。

echo "target/" > .vercelignore

3.添加MCP服务器代码 api/mcp.rs

现在,用最少的代码创建主rust文件来运行服务器——我得到的最少代码大约是100行,希望它足够清晰:)

代码将仅保存在一个文件中 api/mcp.rs,因为我认为代码需要在 api 目录而不是 src vercel可以从中创建无服务器功能。

mv src/ api/
mv api/main.rs api/mcp.rs

cat << EOF > api/mcp.rs
use rmcp::transport::streamable_http_server::{
    StreamableHttpService, session::local::LocalSessionManager, StreamableHttpServerConfig,
};
use vercel_runtime::{run, Body, Error, Request, Response};
use http_body_util::BodyExt;
use tower::util::ServiceExt;
use rmcp::{
    model::ErrorData as McpError,
    RoleServer,
    ServerHandler,
    handler::server::{router::tool::ToolRouter, tool::Parameters},
    model::*,
    schemars,
    service::RequestContext,
    tool, tool_handler, tool_router,
};

#[derive(Clone)]
pub struct MyMCPServerHandler {
    tool_router: ToolRouter<MyMCPServerHandler>,
    // counter: Arc<Mutex<i32>>,  // to persist data between tool calls you can add fields something like this
}

// This defines the input parameters for the `get_test_message` tool
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
pub struct TestMessageParams {
    pub test_param: String,
    // pub test_param_2: i32,  // you can add more params like this
}

#[tool_router]
impl MyMCPServerHandler {

    pub fn new() -> Self {
        Self {
            tool_router: Self::tool_router(),
        }
    }

    #[tool(description = "Return a test string")]
    async fn get_test_message(
        &self,
        Parameters(TestMessageParams { test_param }): Parameters<TestMessageParams>
    ) -> Result<CallToolResult, McpError> {

        Ok(CallToolResult::success(vec![Content::text(
            format!("Hello World! Value of test_param is: {}", test_param),
        )]))
    }
}

#[tool_handler]
impl ServerHandler for MyMCPServerHandler {
    fn get_info(&self) -> ServerInfo {
        ServerInfo {
            protocol_version: ProtocolVersion::V_2024_11_05,
            capabilities: ServerCapabilities::builder()
                .enable_tools()  // this enables MCP tools. You can also add eg. `.enable_prompts()` and `.enable_resources()`
                .build(),
            server_info: Implementation::from_build_env(),
            instructions: Some(
                "This is a test MCP server. Use the `get_test_message` tool to return a test message.".to_string()
            ),
        }
    }

    async fn initialize(
        &self,
        _request: InitializeRequestParam,  // the _request and _context parameters contain info about the request that can be parsed to get eg. the request URI and headers
        _context: RequestContext<RoleServer>,
    ) -> Result<InitializeResult, McpError> {

        Ok(self.get_info())
    }
}

pub async fn handler(req: Request) -> Result<Response<Body>, Error> {

    let service = StreamableHttpService::new(
        || Ok(MyMCPServerHandler::new()),
        LocalSessionManager::default().into(),
        StreamableHttpServerConfig {
            sse_keep_alive: None, // Not using SSE in serverless
            stateful_mode: false, // Stateless fits serverless best
        },
    );

    let response = service
        .oneshot(req)
        .await?;

    // Convert the body from BoxBody<Bytes, Infallible> to Vercel Body
    let (parts, body) = response.into_parts();
    let bytes = body.collect().await?.to_bytes();
    let vercel_body = Body::Binary(bytes.to_vec());

    Ok(Response::from_parts(parts, vercel_body))}

#[tokio::main]
async fn main() -> Result<(), Error> {
    run(handler).await
}
EOF

4.在本地运行 vercel dev

要在本地测试MCP服务器,请运行 vercel dev 这应该启动本地开发服务器。此时,它可能会问你一些设置问题,以帮助初始化你的vercel项目;您应该能够接受所有默认值。

当服务器启动并且您请求与无服务器功能对应的url时(http://localhost:3000/api/mcp),代码将构建,这可能需要一些时间。

(venv) [oscarsaharoy@LCCC-MB-pTIY21 ~/projects/mcp-server-scaffold] $ vercel dev
Vercel CLI 44.3.0
> Ready! Available at http://localhost:3000

如果你只是在浏览器中访问URL,它将无法工作,因为你的浏览器不使用MCP。因此,您可以使用 MCP检查器工具 通过跑步 npx @modelcontextprotocol/inspector。然后,在它提供的UI中,输入 http://localhost:3000/api/mcp 作为URL,“流式HTTP”作为传输。当您单击“连接”时,if应该工作良好,并允许您列出可用的工具并运行测试工具,该工具应返回测试消息。

您可以根据需要对代码进行任何编辑,并在MCP检查器中对其进行测试。

5.部署到vercel

现在,要将MCP服务器部署到生产环境,请运行 vercel。它将在部署时显示构建日志,不幸的是,这可能需要几分钟的时间。但是,一旦完成,您的MCP服务器应该已经部署并可用:)您可以通过输入url(在我的例子中是 https://mcp-server-scaffold.vercel.app/api/mcp 正如我所说的vercel项目“mcp服务器脚手架”)。