Token导航 LogoToken导航TokenDH.com
MCP Attr logo
AI代理未说明官方级别未说明来源级核验

MCP Attr

MCP Server

mcp-attr是一个用于声明式构建Model Context Protocol服务器的Rust库,支持通过属性宏简化MCP服务器开发,适用于AI辅助编程和人类开发者。

工具数

0

提示词数

0

GitHub Stars

28

资源数

0
服务器框架RustAI代理

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

frozenlib

提供方

frozenlib

最后核验

2026/5/17 20:21

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

详细介绍

mcp attr

![Crates.io](https://crates.io/crates/mcp-attr) ![Docs.rs](https://docs.rs/mcp-attr/) ![Actions Status](https://github.com/frozenlib/mcp-attr/actions)

用于声明性构建模型上下文协议服务器的库。

特性

mcp-attr是一个机箱,旨在使人类和人工智能都能轻松创建 模型上下文协议 服务器。 为了实现这一目标,它具有以下特点:

  • 声明性描述:

- 使用以下属性 #[mcp_server] 用最少的代码描述MCP服务器 - 更少的代码行使人类更容易理解和使用更少的AI上下文窗口

  • DRY(不要重复自己)原则:

- 声明性描述确保代码遵循DRY原则 - 防止AI编写不一致的代码

  • 利用类型系统:

- 通过类型表示发送给MCP客户端的信息可以减少源代码量并提高可读性 - 类型错误有助于AI进行编码

  • rustfmt 友好的:

- 仅使用可通过以下方式格式化的属性宏 rustfmt - 确保AI生成的代码能够可靠地格式化

快速开始

安装

将以下内容添加到您的 Cargo.toml:

[dependencies]
mcp-attr = "0.0.7"
tokio = "1.43.0"

示例

use std::sync::Mutex;

use mcp_attr::server::{mcp_server, McpServer, serve_stdio};
use mcp_attr::Result;

#[tokio::main]
async fn main() -> Result {
    serve_stdio(ExampleServer(Mutex::new(ServerData { count: 0 }))).await?;
    Ok(())
}

struct ExampleServer(Mutex);

struct ServerData {
  /// Server state
  count: u32,
}

#[mcp_server]
impl McpServer for ExampleServer {
    /// Description sent to MCP client
    #[tool]
    async fn add_count(&self, message: String) -> Result {
        let mut state = self.0.lock().unwrap();
        state.count += 1;
        Ok(format!("Echo: {message} {}", state.count))
    }

    #[resource("my_app://files/{name}.txt")]
    async fn read_file(&self, name: String) -> Result {
        Ok(format!("Content of {name}.txt"))
    }

    #[prompt]
    async fn example_prompt(&self) -> Result {
        Ok("Hello!")
    }
}

支持状态

协议版本

  • 2025-03-26
  • 2024-11-05

运输

  • 标准

尚未支持SSE。然而,传输是可扩展的,因此可以实现自定义传输。

方法

属性McpServer 方法模型上下文协议方法

用法

启动服务器

使用此机箱创建的MCP服务器在tokio异步运行时上运行。

通过启动异步运行时启动服务器 #[tokio::main] 并传递一个值来实现 McpServer 特质到 serve_stdio 功能, 其使用标准输入/输出作为传输来启动服务器。

虽然你可以实现 McpServer trait可以手动实现,您可以通过使用 [#[mcp_server]](https://docs.rs/mcp-attr/latest/mcp_attr/server/attr.mcp_server.html) 属性。

use mcp_attr::server::{mcp_server, McpServer, serve_stdio};
use mcp_attr::Result;

#[tokio::main]
async fn main() -> Result {
  serve_stdio(ExampleServer).await?;
  Ok(())
}

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
  #[tool]
  async fn hello(&self) -> Result {
    Ok("Hello, world!")
  }
}

实现MCP方法的大多数函数都是异步的,可以并发执行。

输入/输出

MCP服务器如何从MCP客户端接收数据是通过函数参数定义来表达的。

例如,在以下示例中 add 工具表示它接收名为的整数 lhsrhs. 此信息从MCP服务器发送到MCP客户端,MCP客户端向服务器发送适当的数据。

use mcp_attr::server::{mcp_server, McpServer};
use mcp_attr::Result;

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
  #[tool]
  async fn add(&self, lhs: u32, rhs: u32) -> Result {
    Ok(format!("{}", lhs + rhs))
  }
}

可用于参数的类型因方法而异,并且必须实现以下特征:

属性参数类型的特性返回类型
[#[prompt]](#prompt)FromStrGetPromptResult
[#[resource]](#resource)FromStrReadResourceResult
[#[tool]](#tool)DeserializeOwned + JsonSchemaCallToolResult

参数也可以使用 Option,在这种情况下,它们作为可选参数传递给MCP客户端。

返回值必须是可以转换为中所示类型的类型 Return type 上面的柱子,包裹着 Result. 例如,由于 CallToolResult 实现 From,您可以使用 Result 如上例所示的返回值。

AI的解释

对于MCP客户端调用MCP服务器方法,AI需要理解方法和参数的含义。

在方法和参数中添加文档注释会将此信息发送给MCP客户端,使AI能够理解其含义。

您还可以使用以下命令指定描述 description 属性参数。当同时指定文档注释和描述属性时,描述属性优先。

use mcp_attr::server::{mcp_server, McpServer};
use mcp_attr::Result;

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
  /// Tool description
  #[tool]
  async fn concat(&self,
    /// Description of argument a (for AI)
    a: u32,
    /// Description of argument b (for AI)
    b: u32,
  ) -> Result {
    Ok(format!("{a},{b}"))
  }
}

状态管理

自价值观实施以来 McpServer 仅在多个并发执行的方法之间共享 &self 可用。 &mut self 不能使用。

为了维护状态,您需要使用具有内部可变性的线程安全类型,例如 Mutex.

use std::sync::Mutex;
use mcp_attr::server::{mcp_server, McpServer};
use mcp_attr::Result;

struct ExampleServer(Mutex);
struct ServerData {
  count: u32,
}

#[mcp_server]
impl McpServer for ExampleServer {
  #[tool]
  async fn add_count(&self) -> Result {
    let mut state = self.0.lock().unwrap();
    state.count += 1;
    Ok(format!("count: {}", state.count))
  }
}

错误处理

mcp_attr使用 ResultRust的标准错误处理方法。

类型 mcp_attr::Errormcp_attr::Result (别名 std::result::Result)用于错误处理。

mcp_attr::Error 类似于 anyhow::Error,能够存储任何错误类型实现 std::error::Error + Sync + Send + 'static,并实现从其他错误类型的转换。 因此,在函数返回 mcp_attr::Result,您可以使用 ? 用于处理类型表达式错误的运算符 Result.

然而,它与 anyhow::Error 通过以下方式:

  • 可以存储MCP中使用的JSON-RPC错误
  • 具有区分错误消息是发送给MCP客户端的公共信息还是不发送的私人信息的功能

- (但是,在调试版本中,所有信息都会发送到MCP客户端)

bail!bail_public! 用于错误处理,类似于 anyhow::bail!.

  • bail! 接收格式字符串和参数,并引发被视为私有信息的错误。
  • bail_public! 接收错误代码、格式字符串和参数,并引发被视为公共信息的错误。

此外,来自其他错误类型的转换被视为私有信息。

use mcp_attr::server::{mcp_server, McpServer};
use mcp_attr::{bail, bail_public, Result, ErrorCode};

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
    #[prompt]
    async fn add(&self, a: String) -> Result {
        let something_wrong = false;
        if something_wrong {
            bail_public!(ErrorCode::INTERNAL_ERROR, "Error message");
        }
        if something_wrong {
            bail!("Error message");
        }
        let a = a.parse::()?;
        Ok(format!("Success {a}"))
    }
}

调用客户端功能

使用 RequestContext 在使用属性实现的方法中,添加 &RequestContext 方法参数的类型变量。

use mcp_attr::server::{mcp_server, McpServer, RequestContext};
use mcp_attr::Result;

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
  #[prompt]
  async fn echo_roots(&self, context: &RequestContext) -> Result {
    let roots = context.roots_list().await?;
    Ok(format!("{:?}", roots))
  }
}

文件注释说明

instructions 方法是从文档注释中自动生成的 impl McpServer 块。如果您编写了描述服务器的文档注释,它们将作为说明发送给MCP客户端。

use mcp_attr::server::{mcp_server, McpServer};
use mcp_attr::Result;

struct ExampleServer;

/// This server provides file operations and utilities.
/// It can handle various file formats and perform data transformations.
#[mcp_server]
impl McpServer for ExampleServer {
    #[tool]
    async fn hello(&self) -> Result {
        Ok("Hello, world!".to_string())
    }
}

如果 instructions 该方法是手动实现的,使用手动实现,不执行从文档注释自动生成指令。

完工支持(#[complete])

您可以使用以下命令为提示和资源参数添加完成功能 #[complete(function)] 属性。

完成功能必须有签名:

  • 方法形式(.method_name): async fn func_name(&self, p: &CompleteRequestParams, cx: &RequestContext) -> Result
  • 全局函数形式(method_name): async fn func_name(p: &CompleteRequestParams, cx: &RequestContext) -> Result

#[complete] 如果使用属性 completion_complete 方法是自动生成的。手动执行优先于自动生成。

为了使完成函数开发更容易,您可以使用 #[complete_fn] 属性自动将简单签名转换为所需签名:

use mcp_attr::server::{mcp_server, McpServer, RequestContext, complete_fn};
use mcp_attr::Result;

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
    #[prompt]
    async fn greet(&self, #[complete(.complete_names)] name: String) -> Result {
        Ok(format!("Hello, {name}!"))
    }

    #[resource("files://{path}")]
    async fn get_file(&self, #[complete(.complete_paths)] path: String) -> Result {
        Ok(format!("File: {path}"))
    }

    // #[complete_fn] can be written inside #[mcp_server] block
    #[complete_fn]
    async fn complete_paths(&self, _value: &str) -> Result> {
        Ok(vec!["home".to_string(), "usr".to_string()])
    }

    // When RequestContext is needed
    #[complete_fn]
    async fn complete_names(&self, _value: &str, _cx: &RequestContext) -> Result> {
        Ok(vec!["Alice", "Bob"])
    }
}

#[complete_fn] 属性允许省略 cx: &RequestContext 参数。当不需要RequestContext时,您可以省略它以获得更简单的完成函数。

完成仅适用于 #[prompt]#[resource] 争论,不是为了 #[tool] 论据。

属性描述

#[prompt]

#[prompt("name", description = "..", title = "..")]
async fn func_name(&self) -> Result { }
  • “name”(可选):提示名称。如果省略,则使用函数名称。
  • “description”(可选):AI的功能描述。优先于文档注释。
  • “title”(可选):人类可读的提示标题。

实现以下方法:

函数参数变为提示参数。参数必须实现以下特性:

  • FromStr:用于从字符串中恢复值的特性

可以使用以下命令为参数命名 #[arg("name")] 属性。 如果未指定,则使用的名称是带前导的函数参数名称 _ 远离的。

参数可以使用完成功能 #[complete(function)] 属性。 看 完工支持 了解详情。

返回值: Result>

use mcp_attr::Result;
use mcp_attr::server::{mcp_server, McpServer};

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
  /// Function description (for AI)
  #[prompt]
  async fn hello(&self) -> Result {
    Ok("Hello, world!")
  }

  #[prompt]
  async fn echo(&self,
    /// Argument description (for AI)
    a: String,
    /// Argument description (for AI)
    #[arg("x")]
    b: String,
  ) -> Result {
    Ok(format!("Hello, {a} {b}!"))
  }
}

#[resource]

#[resource("url_template", name = "..", mime_type = "..", description = "..", title = "..")]
async fn func_name(&self) -> Result { }
  • “url_template”(可选):URI模板(RFC 6570)指示此方法处理的资源的URL。如果省略,则处理所有URL。
  • “name”(可选):资源名称。如果省略,则使用函数名称。
  • “mime_type”(可选):资源的mime类型。
  • “description”(可选):AI的功能描述。优先于文档注释。
  • “title”(可选):人类可读的资源标题。

实现以下方法:

函数参数变为URI模板变量。参数必须实现以下特性:

  • FromStr:用于从字符串中恢复值的特性

参数可以使用完成功能 #[complete(function)] 属性。 看 完工支持 了解详情。

URI模板在中指定 RFC 6570 Level2.以下变量可用于URI模板:

  • {var}
  • {+var}
  • {#var}

返回值: Result>

use mcp_attr::Result;
use mcp_attr::server::{mcp_server, McpServer};

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
  /// Function description (for AI)
  #[resource("my_app://x/y.txt")]
  async fn file_one(&self) -> Result {
    Ok(format!("one file"))
  }

  #[resource("my_app://{a}/{+b}")]
  async fn file_ab(&self, a: String, b: String) -> Result {
    Ok(format!("{a} and {b}"))
  }

  #[resource]
  async fn file_any(&self, url: String) -> Result {
    Ok(format!("any file"))
  }
}

自动执行 resources_list 返回一个没有在中指定变量的URL列表 #[resource] 属性。 如果需要返回其他URL,则必须手动实现 resources_list. 如果 resources_list 如果是手动实现的,则不会自动实现。

#[tool]

#[tool(
    "name", 
    description = "..", 
    title = "..",
    non_destructive,
    idempotent,
    read_only,
    closed_world,
)]
async fn func_name(&self) -> Result { }
  • “name”(可选):工具名称。如果省略,则使用函数名称。
  • “description”(可选):AI的功能描述。优先于文档注释。
  • “title”(可选):人类可读的工具标题。
  • “non_destructive”(可选):工具仅执行附加更新(MCP规范: destructive = false)
  • “幂等”(可选):使用相同的参数重复调用该工具没有额外效果(MCP规范: idempotent = true)
  • “只读”(可选):工具不修改其环境(MCP规范: read_only = true)
  • “closed_world”(可选):工具的交互域已关闭(MCP规范: open_world = false)

实现以下方法:

函数参数变成工具参数。参数必须实现以下所有特征:

  • DeserializeOwned:用于从JSON恢复值的特性
  • JsonSchema:用于生成JSON模式的特性(JSON模式被发送到MCP客户端,以便AI能够理解参数结构)

可以使用以下命令为参数命名 #[arg("name")] 属性。 如果未指定,则使用的名称是带前导的函数参数名称 _ 远离的。

返回值: Result>

use mcp_attr::Result;
use mcp_attr::server::{mcp_server, McpServer};

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
  /// Function description (for AI)
  #[tool]
  async fn echo(&self,
    /// Argument description (for AI)
    a: String,
    /// Argument description (for AI)
    #[arg("x")]
    b: String,
  ) -> Result {
    Ok(format!("Hello, {a} {b}!"))
  }
}

手动执行

您还可以直接实现 McpServer 不使用属性的方法。

以下方法不支持通过属性实现,必须手动实现:

以下方法可以通过手动实现覆盖基于属性的实现:

测试

随着AI编码代理的出现,测试变得更加重要。 没有测试,人工智能很难写出正确的代码,但有了测试,它可以通过反复的测试和修复来写出正确的编码。

mcp_attr包括 McpClient 用于测试,它连接到流程中的MCP服务器。

use mcp_attr::client::McpClient;
use mcp_attr::server::{mcp_server, McpServer};
use mcp_attr::schema::{GetPromptRequestParams, GetPromptResult};
use mcp_attr::Result;

struct ExampleServer;

#[mcp_server]
impl McpServer for ExampleServer {
    #[prompt]
    async fn hello(&self) -> Result {
        Ok("Hello, world!")
    }
}

#[tokio::test]
async fn test_hello() -> Result {
    let client = McpClient::with_server(ExampleServer).await?;
    let a = client
        .prompts_get(GetPromptRequestParams::new("hello"))
        .await?;
    let e: GetPromptResult = "Hello, world!".into();
    assert_eq!(a, e);
    Ok(())
}

许可证

该项目在Apache-2.0/MIT下获得双重许可。有关详细信息,请参阅两个LICENSE-\*文件。

贡献

除非您另有明确说明,否则根据Apache-2.0许可证的定义,您有意提交以包含在作品中的任何贡献都应如上所述获得双重许可,无需任何额外的条款或条件。

目录标签

目录标签

服务器框架RustAI代理Rust库本地部署MCP协议声明式编程AI辅助开发

接入字段

传输方式(transport,传输协议)

未说明

鉴权方式(authType,认证方式)

none

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

未说明none部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

仍需确认:installCommand

来源信息

继续浏览同类 MCP