Pre-alpha documentation
Call a stateless MCP Tool safely.
Connect the bounded StateKnot MCP 2026-07-28 Tool client, inspect its trust boundary, handle MRTR, and reproduce the pinned official evidence.
Choose the correct MCP boundary
McpClient- Dynamic interoperability: discover a bounded Tool catalog, preserve untrusted wire schemas, call Tools, receive request-scoped SSE, and mediate multi-round input.
McpRemoteTool- Durable external effects: pin reviewed server/input/output identity, commit dispatch evidence first, retain ambiguous writes, and reconcile without redispatch.
Discover and call one Tool
Production endpoints require HTTPS. Authorization resolves independently for every stateless POST, so a production provider can rotate credentials. Never put secrets in endpoint URLs, request metadata, or logs.
use std::sync::Arc;
use serde_json::json;
use stateknot_integrations::{
ApiKey, McpClient, McpClientIdentity, McpClientOptions,
McpToolCall, ProviderEndpoint, StaticMcpBearerAuthorization,
};
let client = McpClient::connect(
ProviderEndpoint::https("https://mcp.example.com/mcp/")?,
McpClientIdentity::new("inventory-agent", "1.0.0")?,
Arc::new(StaticMcpBearerAuthorization::new(
ApiKey::new(std::env::var("MCP_TOKEN")?)?,
)),
McpClientOptions::default(),
)
.await?;
let catalog = client.list_tools().await?;
let tool = catalog.find("inventory_lookup").ok_or("Tool unavailable")?;
let response = client.call_tool(tool, json!({ "sku": "STK-001" })).await?;
match response.into_outcome() {
McpToolCall::Complete(result) => println!("{}", result.content().len()),
McpToolCall::InputRequired(pending) => {
// Route each request to a trusted host subsystem; never auto-approve it.
println!("{} inputs required", pending.input_requests().len());
}
_ => return Err("unsupported future outcome".into()),
}
Inspect rejected_tools() before relying on catalog shape. An invalid
x-mcp-header descriptor is excluded individually; it never becomes
callable and does not hide valid siblings.
Keep discovery and output untrusted
- Tool descriptions, annotations, schemas, content, structured content, notifications, and server instructions do not grant authority.
-
Network
$refvalues are retained but never dereferenced. Apply an offline allowlisted schema policy before local validation. -
String, integer, and boolean
x-mcp-headervalues are derived only through statically reachable properties. Unsafe bytes use the MCP Base64 sentinel; null and absent values are omitted. -
Tool-level
isErrorremains a result for Agent recovery; transport and protocol failures remain typed client errors.
Mediate every MRTR round
An input_required result owns the original Tool, arguments, client,
and opaque requestState. The host must route each declared
request to a trusted subsystem and return exactly the requested keys. resume consumes the pending value, uses a fresh JSON-RPC ID, echoes the exact state
when present, and never leaks it across calls. StateKnot does not auto-approve
elicitation or invent Roots/Sampling data.
Bound every exchange
| Resource | Default |
|---|---|
| Logical request / concurrent requests | 30 s / 16 |
| Catalog pages / entries | 16 / 1,024 |
| Request / JSON response | 16 MiB / 2 MiB |
| SSE line / event / total | 512 KiB / 2 MiB / 64 MiB |
| Notifications per response | 1,024 |
The logical request deadline has a 24-hour hard ceiling. Redirects and generic retries are disabled. A timeout or lost Tool response is never automatically replayed. Protocol version negotiation receives one bounded retry after the server explicitly advertises this version. A Bearer challenge receives one replay by default only after the authorization provider explicitly approves recovery; the replay uses a fresh JSON-RPC ID. See the MCP OAuth client contract.
Reproduce the evidence
cargo test -p stateknot-integrations --test mcp_client_contract --locked
bash conformance/mcp-client/run-2026-07-28.sh The pinned official runner passes all 32 scored client scenarios, including all 25 OAuth scenarios: 371 scored assertions succeed, zero fail, and 11 out-of-surface checks are explicitly skipped. Read the exact conformance boundary before making a compatibility claim.