polyc-tools 2026.9.0

The in-process tool core for polychrome agents: local executors (coding, web fetch, wallet, ...), the tool registry, and MCP composition. The networked connectors live in polyc-connectors.
[package]
name = "polyc-tools"
description = "The in-process tool core for polychrome agents: local executors (coding, web fetch, wallet, ...), the tool registry, and MCP composition. The networked connectors live in polyc-connectors."
version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true
rust-version.workspace = true
repository.workspace = true

[package.metadata.polychrome]
# Software-system layer — see docs/architecture/. A Component composed
# into Containers; depends inward only (never on a Container).
layer = "component"
# Logical plane role in the separated state, projection, and query topology
# (#1565, chunk A1) — a different question than `layer` above. The canonical
# policy is arch-capabilities.toml; scripts/check_plane_capabilities.py checks it.
plane_role = "shared"

[dependencies]
polyc-capability = { version = "=2026.9.0", path = "../capability" }
polyc-agent = { version = "=2026.9.0", path = "../agent" }
polyc-crypto = { version = "=2026.9.0", path = "../crypto" }
polyc-llm = { version = "=2026.9.0", path = "../llm" }
async-trait.workspace = true
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
tracing.workspace = true
# `grep` coding tool — battle-tested Rust regex (linear-time guarantees).
regex = "1"

# Model Context Protocol SDK. Both client and server are wired through the
# streamable-HTTP transport — the client wraps a remote MCP server as an
# extra `ToolExecutor`; the server exposes our tools to outside MCP clients.
# rmcp's client transport links the same `reqwest` 0.13 line as the workspace,
# so we inject our own client (below) to bound the dial.
rmcp = { version = "3", features = [
    "client",
    "server",
    "transport-streamable-http-client-reqwest",
    "transport-streamable-http-server",
] }
# Build the streamable-HTTP client ourselves so the dial carries a bounded
# `connect_timeout` (rmcp's default client has none). Same `reqwest` 0.13 line
# rmcp 2.0 links, so injecting our `reqwest::Client` into `with_client` satisfies
# its `StreamableHttpClient for reqwest::Client` impl with no version skew.
reqwest = { workspace = true }
# `HeaderName`/`HeaderValue` for the caller-identity header on a connector
# dial (`ConnectOptions::caller`) — the same `http` line rmcp's transport
# takes `custom_headers` in.
http.workspace = true
tokio = { workspace = true, features = [
    "rt-multi-thread",
    "macros",
    "net",
    "signal",
    "process",
    "time",
] }
tokio-util = { workspace = true }

# MCP server transport (`serve`) is axum-based; anyhow surfaces its bring-up
# errors.
axum = { workspace = true }
anyhow = { workspace = true }
# Standard gRPC health-checking service (`grpc.health.v1.Health`), mounted
# alongside the MCP streamable-HTTP service in `serve()` so a connector gets a
# real `grpc:` readiness/liveness probe — see `crates/control-plane` and
# `crates/harness` for the same pattern.
connectrpc = { workspace = true }
connectrpc-health = { workspace = true }

[dev-dependencies]
# Round-trip integration test: spin our server in-process, connect via the
# client wrapper, run the executor end-to-end. No external services.
tokio = { workspace = true, features = ["test-util"] }
# Drive the `serve()` health-check router via `ServiceExt::oneshot` in unit
# tests, without binding a socket.
tower = { version = "0.5", features = ["util"] }

[lints]
workspace = true