pulseengine-mcp-macros

Crates.iopulseengine-mcp-macros
lib.rspulseengine-mcp-macros
version0.10.0
created_at2025-07-27 16:11:07.929358+00
updated_at2025-08-15 04:22:11.438237+00
descriptionProcedural macros for PulseEngine MCP Framework - simplified server and tool development
homepagehttps://github.com/pulseengine/mcp
repositoryhttps://github.com/pulseengine/mcp
max_upload_size
id1770196
size402,381
Ralf Anton Beier (avrabe)

documentation

https://docs.rs/pulseengine-mcp-macros

README

PulseEngine MCP Macros

Procedural macros for the PulseEngine MCP Framework that dramatically simplify server and tool development.

Quick Start

Add to your Cargo.toml:

[dependencies]
# Core macros
pulseengine-mcp-macros = "0.7.1"

# Required dependencies for generated code
pulseengine-mcp-protocol = "0.7.1"
pulseengine-mcp-server = "0.7.1"
pulseengine-mcp-transport = "0.7.1"
async-trait = "0.1"
thiserror = "1.0"
tokio = { version = "1.0", features = ["full"] }

# For STDIO transport (recommended)
tracing = "0.1"
tracing-subscriber = "0.3"

Basic Server Example

use pulseengine_mcp_macros::{mcp_server, mcp_tools};

#[mcp_server(name = "Hello Server")]
#[derive(Default, Clone)]
pub struct HelloServer;

#[mcp_tools]
impl HelloServer {
    /// Say hello to someone
    pub async fn hello(&self, name: Option<String>) -> anyhow::Result<String> {
        Ok(format!("Hello, {}!", name.unwrap_or_else(|| "World".to_string())))
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // CRITICAL for STDIO: Configure logging to stderr
    HelloServer::configure_stdio_logging();

    let server = HelloServer::with_defaults().serve_stdio().await?;
    server.run().await?;
    Ok(())
}

Required Dependencies

Always Required

These dependencies are always required when using #[mcp_server]:

pulseengine-mcp-protocol = "0.7.1"
pulseengine-mcp-server = "0.7.1"
pulseengine-mcp-transport = "0.7.1"
async-trait = "0.1"
thiserror = "1.0"
tokio = { version = "1.0", features = ["full"] }

Feature-Based Dependencies

STDIO Logging (stdio-logging feature)

For STDIO transport compatibility:

pulseengine-mcp-macros = { version = "0.7.1", features = ["stdio-logging"] }
tracing-subscriber = "0.3"

Authentication (auth feature + auth parameter)

Important: Authentication is opt-in. By default, servers have no authentication.

When using auth = "memory", auth = "file", etc.:

pulseengine-mcp-macros = { version = "0.7.1", features = ["auth"] }
pulseengine-mcp-auth = "0.7.1"

Macros

#[mcp_server]

Generates a complete MCP server from a struct:

#[mcp_server(
    name = "My Server",
    version = "1.0.0",
    description = "Server description",
    auth = "memory"  // Optional: "memory", "file", "disabled"
)]
#[derive(Default, Clone)]
pub struct MyServer;

Generated methods:

  • MyServer::with_defaults() - Create instance
  • MyServer::serve_stdio() - Start STDIO transport
  • MyServer::serve_http(port) - Start HTTP transport
  • MyServer::configure_stdio_logging() - Fix STDIO logging

#[mcp_tools]

Automatically discovers public methods as MCP tools:

#[mcp_tools]
impl MyServer {
    /// Tool description from doc comment
    pub async fn my_tool(&self, param: String) -> anyhow::Result<String> {
        Ok(format!("Result: {}", param))
    }
}

Note: Currently passthrough - full implementation coming soon.

Transport Types

STDIO (Default)

For MCP clients like Claude Desktop:

// CRITICAL: Configure logging first!
MyServer::configure_stdio_logging();
let server = MyServer::with_defaults().serve_stdio().await?;

HTTP

For web-based clients:

let server = MyServer::with_defaults().serve_http(8080).await?;

WebSocket

For real-time clients:

let server = MyServer::with_defaults().serve_websocket(8080).await?;

Authentication

By default, servers have no authentication. To enable authentication, add the auth parameter:

// Memory-based (development)
#[mcp_server(name = "Dev Server", auth = "memory")]

// File-based (production)
#[mcp_server(name = "Prod Server", auth = "file", app_name = "my-app")]

// Explicitly disabled (same as default)
#[mcp_server(name = "Test Server", auth = "disabled")]

// No auth parameter = no authentication (default)
#[mcp_server(name = "Simple Server")]

Requires: pulseengine-mcp-auth dependency and auth feature only when auth parameter is specified.

STDIO Transport Critical Note

⚠️ CRITICAL: For STDIO transport, you MUST configure logging to go to stderr, not stdout. Stdout is reserved for JSON-RPC messages only.

// Always call this before serve_stdio()
MyServer::configure_stdio_logging();

Failure to do this will break MCP client compatibility with errors like:

Error from MCP server: SyntaxError: Unexpected token '2025-0"... is not valid JSON

Complete Example

See examples/hello-world-stdio-fixed/ for a working example with proper STDIO logging configuration.

License

Licensed under either of

at your option.

Commit count: 293

cargo fmt