mcp: declare tools capability in ServerInfo
rmcp 0.1.5's #[tool(tool_box)] macro doesn't backfill
ServerInfo::capabilities. Without an explicit ToolsCapability,
clients read "capabilities":{} from initialize and skip tools/list
entirely — the server looks connected (instructions field lands)
but the tool surface is empty. Claude Code's MCP log:
"hasTools":false,"hasPrompts":false,"hasResources":false
Fix: capabilities = ServerCapabilities::builder().enable_tools().build()
in get_info(). Adds a regression test on the wire shape.
This commit is contained in:
parent
ffdafc2028
commit
66829c9aea
1 changed files with 32 additions and 1 deletions
|
|
@ -36,7 +36,10 @@ use aldabra_core::{
|
|||
InputUtxo, Network, PaymentKey, PlutusExUnits, PlutusInput, PlutusVersion, PolicySpec,
|
||||
ProtocolParams, StakeKey, DEFAULT_EX_UNITS,
|
||||
};
|
||||
use rmcp::{model::ServerInfo, schemars, tool, ServerHandler};
|
||||
use rmcp::{
|
||||
model::{ServerCapabilities, ServerInfo},
|
||||
schemars, tool, ServerHandler,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
/// MCP-facing asset spec — separate from `aldabra_core::AssetSpec`
|
||||
|
|
@ -1268,7 +1271,13 @@ impl WalletService {
|
|||
#[tool(tool_box)]
|
||||
impl ServerHandler for WalletService {
|
||||
fn get_info(&self) -> ServerInfo {
|
||||
// Declare `tools` capability explicitly. rmcp 0.1.5's `#[tool(tool_box)]` macro
|
||||
// does NOT backfill ServerInfo::capabilities; without this line Claude Code (and
|
||||
// any spec-compliant MCP client) reads `"capabilities": {}` from the initialize
|
||||
// response and skips `tools/list` entirely. The instructions field still lands,
|
||||
// so the failure mode is silent — server appears connected, no tool surface.
|
||||
ServerInfo {
|
||||
capabilities: ServerCapabilities::builder().enable_tools().build(),
|
||||
instructions: Some(
|
||||
"aldabra — Cardano lite wallet over MCP. wallet_*: read (address/balance/utxos/network/stake_address), send (wallet_send with optional inline datum for script locks, wallet_send_unsigned + wallet_sign_partial + wallet_submit_signed_tx for cold/multi-sig, wallet_tx_status), mint (wallet_policy_create, wallet_mint with CIP-25 metadata, wallet_mint_cip68_nft for ref+user NFT pairs, wallet_mint_unsigned), Plutus (wallet_script_spend), stake (wallet_stake_delegate). chain_*: read-only Koios passthroughs (chain_tx_info, chain_address_info, chain_pool_list, chain_pool_info, chain_epoch_params, chain_asset_info, chain_account_info, chain_tip) — for inspecting the chain at addresses/txs/pools beyond this wallet.".into(),
|
||||
),
|
||||
|
|
@ -1276,3 +1285,25 @@ impl ServerHandler for WalletService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod server_info_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn capabilities_builder_declares_tools() {
|
||||
// Regression for the silent "hasTools:false" bug. Claude Code reads
|
||||
// `serverCapabilities.tools` from initialize and skips `tools/list`
|
||||
// entirely if it's missing — leaving the server connected but with
|
||||
// zero callable tools. If anyone refactors `get_info()` and drops
|
||||
// the `enable_tools()` call, this test catches it.
|
||||
let cap = ServerCapabilities::builder().enable_tools().build();
|
||||
assert!(cap.tools.is_some(), "tools capability must be declared");
|
||||
|
||||
let wire = serde_json::to_value(&cap).expect("ServerCapabilities serializes");
|
||||
assert!(
|
||||
wire.get("tools").is_some(),
|
||||
"wire-format capabilities must include 'tools' key, got: {wire}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue