Skip to content

Using comindly as a library

The comindly crate is the same code the binary runs: reading an index, querying the graph, the ledger and the MCP server. Use it to build your own tools on a team's index, or to serve comindly's MCP tools from your own service. API reference: docs.rs/comindly.

The library follows the binary's version. Until 1.0, minor versions may change it; pin one.

cargo add comindly

Building needs what cargo install comindly needs: Rust 1.95+, protoc and cmake.

Read an index

An index root holds the graph under _graph and the ledger under _ledger, in a folder or a bucket (Storage):

use comindly::graph::CodeGraph;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let root = "s3://bucket/comindly";
    let (symbols, edges) = comindly::index::read_graph(&format!("{root}/_graph")).await?;
    let graph = CodeGraph::build(&symbols, &edges);

    for (repo, count) in graph.repos() {
        println!("{repo}: {count} symbols");
    }
    for node in graph.find("create_order", 5) {
        println!("{} {} at {}", node.kind, node.name, node.location);
    }
    Ok(())
}

Follow a flow across repositories

flow walks from a symbol through calls and across HTTP routes, topics and queues into the services that handle them; entry_points ranks where flows start by how many repositories they reach:

if let Some(start) = graph.lookup("placeOrder") {
    for step in graph.flow(start, 8) {
        println!("{}{} via {}", "  ".repeat(step.depth), step.node.name, step.via);
    }
}
for (entry, repos) in graph.entry_points(10) {
    println!("{} reaches {repos} repositories", graph.node(entry).name);
}

Read the ledger

let ledger = comindly::ledger::Ledger::open(root)?;
for record in ledger.all().await? {
    println!("{:?}: {}", record.kind, record.title);
}

comindly::ledger::derive(&records, &symbols) adds each record's status (active, stale, orphaned, superseded) against the current code, as the app shows it.

Serve the MCP tools from your own service

mcp::load reads an index into a server with every tool agents get from comindly serve. Serve it over any rmcp transport, or mount the HTTP one in an axum router next to your own routes:

use std::sync::{Arc, RwLock};

let server = comindly::mcp::load(&format!("{root}/_graph"), true).await?;
let current = Arc::new(RwLock::new(Some(server)));
let app = axum::Router::new().nest_service(
    "/mcp",
    comindly::mcp::http(current.clone(), vec!["mcp.example.com".into()]),
);

Replace what current holds after a re-index and new sessions get the new index. Put your own authentication in front of /mcp; comindly's server mode does that with personal access tokens (Self-hosting).