Skip to content

Quick start

  1. Install the CLI

    Terminal window
    cargo install carmy-cli

    Carmy requires Rust 1.88 or newer.

  2. Create an application

    Terminal window
    carmy new shop
    cd shop

    The project follows the Carmy conventions: src/main.rs, one file per tool in src/tools/, and a carmy.toml.

  3. Serve it over HTTP

    Terminal window
    cargo run
    Terminal window
    $ curl localhost:3000/.well-known/agent
    {"capabilities":["tools","streaming","idempotency"],"execute_url":"/agent/execute","protocol":"carmy/1","server":"shop","tools_url":"/agent/tools","tools_version":"…"}
    $ curl localhost:3000/agent/execute -H 'content-type: application/json' \
    -d '{"tool":"hello","arguments":{"name":"Ada"}}'
    {"execution_id":"exec_…","status":"completed","data":{"message":"Hello, Ada!"},"_agent":{"cacheable":true,"next_actions":[]}}
  4. Serve the same app over MCP

    Terminal window
    cargo run -- mcp

    Any MCP client, such as Claude Desktop or Cursor, can now list and call your tools. See MCP.

  5. Run the tests

    Terminal window
    cargo test

    The generated hello tool ships with tests that call it through the real runtime.

Create src/tools/search.rs:

use carmy::prelude::*;
#[derive(Deserialize, JsonSchema)]
struct SearchInput {
/// Search expression.
query: String,
}
#[derive(Serialize, JsonSchema)]
struct SearchOutput {
results: Vec<String>,
}
#[carmy::tool(description = "Search the catalog", effect = "read", idempotent = true)]
async fn search(input: SearchInput) -> AgentResult<SearchOutput> {
Ok(SearchOutput {
results: vec![format!("Result for {}", input.query)],
})
}

Then add mod search; to src/tools/mod.rs. That’s it: the tool registers itself and is available over HTTP and MCP.

Next: Project structure.