| Crates.io | mcplease-cli |
| lib.rs | mcplease-cli |
| version | 0.2.1 |
| created_at | 2025-07-18 21:44:19.479838+00 |
| updated_at | 2025-07-18 22:24:55.544693+00 |
| description | CLI tool for creating MCP servers with mcplease |
| homepage | |
| repository | https://github.com/jbr/mcplease |
| max_upload_size | |
| id | 1759714 |
| size | 49,547 |
The MCPlease CLI is a code generation tool that makes building MCP (Model Context Protocol) servers fast and enjoyable. It handles all the boilerplate so you can focus on implementing your tool logic.
cargo install mcplease-cli
mcplease createCreates a new MCP server project with the specified tools.
mcplease create <PROJECT_NAME> --tools <TOOL1,TOOL2,...> [OPTIONS]
Arguments:
<PROJECT_NAME> - Name of the project to createOptions:
--tools <TOOLS> - Comma-separated list of tool names to generate--state <STATE> - Name of the state type (default: "State")--output <DIR> - Output directory (default: same as project name)--description <DESC> - Project description for Cargo.toml--instructions <TEXT> - Instructions for the MCP serverExamples:
# Basic server with a few tools
mcplease create my-server --tools hello,goodbye,status
# Server with custom state type and description
mcplease create file-manager \
--tools read,write,delete,list \
--state FileManagerState \
--description "A file management MCP server"
# Server with custom instructions
mcplease create calculator \
--tools add,subtract,multiply,divide \
--instructions "Use this server to perform basic arithmetic operations"
Generated Structure:
my-server/
├── Cargo.toml
└── src/
├── main.rs # Entry point with server setup
├── state.rs # State struct definition
├── tools.rs # Tools macro invocation
└── tools/
├── hello.rs # Individual tool implementations
├── goodbye.rs
└── status.rs
mcplease addAdds a new tool to an existing MCP server project.
mcplease add <TOOL_NAME>
Arguments:
<TOOL_NAME> - Name of the tool to addExamples:
# Add a single tool
mcplease add health_check
# Add multiple tools (run multiple times)
mcplease add ping
mcplease add version
mcplease add metrics
What it does:
src/tools.rstools! macrosrc/tools/<tool_name>.rs with boilerplatecargo fmtNote: Run this command from the root of your MCP server project (where src/tools.rs exists).
Each generated tool follows this pattern:
use crate::state::MyState;
use anyhow::Result;
use mcplease::traits::{Tool, WithExamples};
use mcplease::types::Example;
use serde::{Deserialize, Serialize};
/// TODO: Add description for this tool
#[derive(Debug, Serialize, Deserialize, schemars::JsonSchema, clap::Args)]
#[serde(rename = "tool_name")]
pub struct ToolName {
/// TODO: Add parameter description
pub example_param: String,
}
impl WithExamples for ToolName {
fn examples() -> Vec<Example<Self>> {
vec![
Example {
description: "TODO: Add example description",
item: Self {
example_param: "example_value".into(),
},
},
]
}
}
impl Tool<MyState> for ToolName {
fn execute(self, _state: &mut MyState) -> Result<String> {
// TODO: Implement tool logic
Ok(format!("tool_name executed with param: {}", self.example_param))
}
}
The generated state provides a foundation for session management:
use anyhow::Result;
/// State for the MCP server
///
/// TODO: Add your state fields here. Common patterns include:
/// - Working directory tracking
/// - Session management with mcplease::session::SessionStore
/// - Configuration data
/// - Cache or temporary data
#[derive(Debug)]
pub struct MyState {
// TODO: Add your state fields here
}
impl MyState {
pub fn new() -> Result<Self> {
Ok(Self {
// TODO: Initialize your state
})
}
}
The tools.rs file uses the tools! macro for clean registration:
use crate::state::MyState;
mcplease::tools!(
MyState,
(Hello, hello, "hello"),
(Goodbye, goodbye, "goodbye"),
(Status, status, "status")
);
mcplease create my-server --tools hello,status
cd my-server
Edit the generated files in src/tools/ to add your logic:
// src/tools/hello.rs
impl Tool<MyState> for Hello {
fn execute(self, _state: &mut MyState) -> Result<String> {
Ok(format!("Hello, {}!", self.name))
}
}
// src/state.rs
use mcplease::session::SessionStore;
#[derive(Debug)]
pub struct MyState {
session_store: SessionStore<SessionData>,
}
# Check that everything compiles
cargo check
# Run the server
cargo run serve
# Test tools via command line
cargo run hello --name "World"
cargo run status
mcplease add goodbye
mcplease add version
get_file_content vs readanyhow::Result for clear error messagesfile_path vs pathuse mcplease::session::SessionStore;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct SessionData {
pub working_directory: Option<PathBuf>,
pub user_preferences: HashMap<String, String>,
}
#[derive(Debug)]
pub struct MyState {
session_store: SessionStore<SessionData>,
}
impl MyState {
pub fn new() -> Result<Self> {
let session_store = SessionStore::new(Some(
dirs::home_dir()
.unwrap_or_default()
.join(".my-server/sessions.json")
))?;
Ok(Self { session_store })
}
pub fn get_working_directory(&mut self) -> Result<Option<PathBuf>> {
Ok(self.session_store.get_or_create("default")?.working_directory.clone())
}
}
#[derive(Debug, Serialize, Deserialize, schemars::JsonSchema, clap::Args)]
#[serde(rename = "search_files")]
pub struct SearchFiles {
/// Pattern to search for (supports regex)
pub pattern: String,
/// Directory to search in
#[serde(skip_serializing_if = "Option::is_none")]
#[arg(long)]
pub directory: Option<String>,
/// File extensions to include
#[serde(skip_serializing_if = "Option::is_none")]
#[arg(long, value_delimiter = ',')]
pub extensions: Option<Vec<String>>,
/// Whether to search recursively
#[serde(skip_serializing_if = "Option::is_none")]
#[arg(long)]
pub recursive: Option<bool>,
}
impl WithExamples for SearchFiles {
fn examples() -> Vec<Example<Self>> {
vec![
Example {
description: "Search for TODO comments in Rust files",
item: Self {
pattern: "TODO".into(),
directory: Some("src".into()),
extensions: Some(vec!["rs".into()]),
recursive: Some(true),
},
},
Example {
description: "Find all JSON files in current directory",
item: Self {
pattern: r"\.json$".into(),
directory: None,
extensions: None,
recursive: Some(false),
},
},
]
}
}
You're not in the root of an mcplease project. Navigate to the directory containing src/tools.rs.
The tool name you're trying to add already exists in the tools! macro. Use a different name or modify the existing tool.
The CLI will still generate your files, but they may not be perfectly formatted. This usually means:
cargo is not in your PATHCargo.tomlThis shouldn't happen! If it does, please file an issue with:
The CLI is part of the mcplease workspace. To contribute:
git clone https://github.com/jbr/mcplease
cd mcplease
# Test the CLI
cargo test -p mcplease-cli
# Build the CLI
cargo build -p mcplease-cli
# Test code generation
cargo run -p mcplease-cli -- create test-server --tools hello,world
mcplease create file-manager \
--tools read,write,delete,list,move \
--state FileManagerState \
--description "MCP server for file operations"
mcplease create http-client \
--tools get,post,put,delete \
--state HttpClientState \
--instructions "Use this server to make HTTP requests"
mcplease create db-server \
--tools query,insert,update,delete,migrate \
--state DatabaseState
cd db-server
mcplease add backup
mcplease add restore
Back to main documentation: ../README.md