bote 0.50.0

MCP core service — JSON-RPC 2.0 protocol, tool registry, audit integration, and TypeScript bridge
Documentation

bote

MCP core service for Rust.

JSON-RPC 2.0 protocol, tool registry, schema validation, and dispatch — in a single crate. Eliminates 23 separate MCP server implementations across the AGNOS ecosystem.

Name: Bote (German) — messenger. The messenger between agents and tools.

Crates.io CI License: AGPL-3.0


What it does

bote is the MCP protocol layer — it handles the JSON-RPC 2.0 wire format, tool registration, schema validation, and call dispatch so individual apps don't each reimplement the same protocol.

Capability Details
JSON-RPC 2.0 Requests, responses, notifications, batch arrays
Tool registry Register tools with schemas, discover, validate params
Dispatch Route tools/call to registered handler functions
Streaming Progress notifications and cancellation for long-running tools
Transports Stdio, HTTP (axum + SSE), WebSocket, Unix socket
Audit Tool call logging via libro hash-linked chain
Events Tool events published via majra pub/sub
Protocol Version negotiation, batch requests, notifications

Feature Flags

Flag Description
http HTTP transport via axum (POST + SSE streaming)
ws WebSocket transport via tokio-tungstenite
unix Unix domain socket transport
all-transports Enables http, ws, and unix
audit Audit logging via libro hash-linked chain
events Event publishing via majra pub/sub
full All transports + audit + events

None are enabled by default — enable only what you need.


Quick start

[dependencies]
bote = "0.22"
use std::sync::Arc;
use std::collections::HashMap;
use bote::{Dispatcher, ToolRegistry, ToolDef, ToolSchema, JsonRpcRequest};

// Register tools
let mut registry = ToolRegistry::new();
registry.register(ToolDef {
    name: "my_tool".into(),
    description: "Does something useful".into(),
    input_schema: ToolSchema {
        schema_type: "object".into(),
        properties: HashMap::new(),
        required: vec!["input".into()],
    },
});

// Wire up handlers
let mut dispatcher = Dispatcher::new(registry);
dispatcher.handle("my_tool", Arc::new(|params| {
    let input = params["input"].as_str().unwrap_or("none");
    serde_json::json!({
        "content": [{ "type": "text", "text": format!("result: {input}") }]
    })
}));

// Dispatch requests
let request = JsonRpcRequest::new(1, "tools/call")
    .with_params(serde_json::json!({
        "name": "my_tool",
        "arguments": { "input": "hello" }
    }));

let response = dispatcher.dispatch(&request).unwrap();
// response.result = {"content": [{"type": "text", "text": "result: hello"}]}

MCP server (stdio)

use bote::transport::stdio;

// Runs a blocking loop: reads JSON-RPC from stdin, dispatches, writes to stdout.
stdio::run(&dispatcher)?;

HTTP transport

[dependencies]
bote = { version = "0.22", features = ["http"] }
use bote::transport::http::{serve, HttpConfig};
use std::sync::Arc;

let config = HttpConfig { addr: "127.0.0.1:3000".parse().unwrap() };
serve(Arc::new(dispatcher), config, shutdown_signal).await?;
// POST / for JSON-RPC, GET /health for liveness

MCP Protocol

bote implements the Model Context Protocol over JSON-RPC 2.0:

Method Description Response
initialize Handshake Server info, capabilities, negotiated protocol version
tools/list Discovery Array of tool definitions with schemas
tools/call Execution Tool result or JSON-RPC error
$/cancelRequest Cancellation Cancels an in-progress streaming call

Error codes

Code Meaning When
-32700 Parse error Malformed JSON
-32600 Invalid request Bad jsonrpc version, empty batch
-32601 Method not found Unknown method or tool name
-32602 Invalid params Missing required fields, empty tool name
-32000 Execution error Handler returned an error
-32603 Internal error Handler panicked
-32800 Request cancelled Streaming call cancelled by client

Why bote?

Every AGNOS consumer app currently implements its own MCP server:

Before bote:                          After bote:
─────────────                         ────────────
jalwa/src/mcp.rs    (150 lines)       jalwa: bote::Dispatcher + 5 handlers
shruti/src/mcp.rs   (180 lines)       shruti: bote::Dispatcher + 7 handlers
tazama/src/mcp.rs   (160 lines)       tazama: bote::Dispatcher + 7 handlers
rasa/src/mcp.rs     (200 lines)       rasa: bote::Dispatcher + 9 handlers
... × 23 apps       (~4000 lines)     ... × 23 apps (0 protocol code)

4000 lines of duplicated JSON-RPC parsing replaced by bote = "0.22" in Cargo.toml.


Who uses this

Project Usage
23 AGNOS consumer apps Replace inline MCP servers with bote dispatch
daimon 144 MCP tools via bote registry
SecureYeoman TypeScript bridge to Rust MCP core
agnoshi Tool discovery and invocation
AgnosAI Sandboxed tool execution via kavach + bote

Roadmap

Version Milestone Key features
0.21.3 Foundation JSON-RPC 2.0, registry, dispatch, stdio
0.22.3 Transport & Streaming HTTP, WebSocket, Unix, SSE, batch, audit, events
0.23.3 TypeScript Bridge SY bridge, cross-node discovery
0.24.3 Advanced Registry Full JSON Schema, versioning, hot-reload
0.25.3 Adoption daimon, 23 apps, SY, agnoshi integration
1.0.0 Stable Full compliance, < 500ns dispatch, all transports

Full details: docs/development/roadmap.md


Building from source

git clone https://github.com/MacCracken/bote.git
cd bote
make check          # fmt + clippy + test + audit
make test-all       # test every feature flag
make bench          # run benchmarks + log history
make coverage       # HTML coverage report

Versioning

Pre-1.0: 0.D.M SemVer (day.month). Post-1.0: standard SemVer.


License

AGPL-3.0-only. See LICENSE for details.