diff --git a/README.md b/README.md index d5c8538..9a24bfd 100644 --- a/README.md +++ b/README.md @@ -155,8 +155,6 @@ server.run() - `beacon_agent_status` — Get detailed status of a specific agent - `beacon_send_message` — Send a message to another agent (costs RTC gas) - `beacon_chat` — Chat with native Beacon agents (Sophia, Boris, etc.) -- `beacon_gas_balance` — Check RTC gas balance for messaging -- `beacon_gas_deposit` — Deposit RTC gas for messaging - `beacon_contracts` — List bounties, agreements, and accords - `beacon_network_stats` — Beacon network statistics @@ -317,7 +315,7 @@ Solution: Check file size limits and format compatibility MCP clients should treat failed RustChain, BoTTube, and Beacon calls as verification failures, not as successful zero-value results. In particular, `wallet_balance`, `rustchain_balance`, `rustchain_miners`, -`beacon_gas_balance`, and related balance/miner tools should return a +and related balance/miner tools should return a predictable error object when the upstream service cannot be trusted. Recommended shape: diff --git a/rustchain_mcp/server.py b/rustchain_mcp/server.py index 6b7aeac..a39111d 100644 --- a/rustchain_mcp/server.py +++ b/rustchain_mcp/server.py @@ -168,8 +168,7 @@ def rustchain_balance(wallet_id: str) -> dict: """ # Bypass any potential local caching by forcing a fresh network request # and adding a timestamp to the query if the server supports it. - params = {"miner_id": wallet_id, "timestamp": int(time.time() * 1000)} - r = get_client().get(f"{RUSTCHAIN_NODE}/balance", params=params) + r = get_client().get(f"{RUSTCHAIN_NODE}/balance/{wallet_id}", params={"_ts": int(time.time() * 1000)}) r.raise_for_status() return r.json() @@ -220,7 +219,7 @@ def wallet_balance(wallet_id: str) -> dict: # Try querying by address directly pass - r = get_client().get(f"{RUSTCHAIN_NODE}/balance", params={"miner_id": wallet_id}) + r = get_client().get(f"{RUSTCHAIN_NODE}/balance/{wallet_id}") r.raise_for_status() return r.json() @@ -777,9 +776,6 @@ def beacon_send_message( ) -> dict: """Send a message to another agent via Beacon relay. - Costs RTC gas (0.0001 RTC per text message). Check your gas - balance with beacon_gas_balance first. - Args: relay_token: Your relay token (from beacon_register) from_agent: Your agent ID @@ -830,56 +826,6 @@ def beacon_chat(agent_id: str, message: str) -> dict: return r.json() -@mcp.tool() -def beacon_gas_balance(agent_id: str) -> dict: - """Check RTC gas balance for Beacon messaging. - - Sending messages through Beacon costs micro-fees in RTC: - - Text relay: 0.0001 RTC - - Attachment: 0.001 RTC - - Discovery: 0.00005 RTC - - Args: - agent_id: Your agent ID to check gas balance for - - Returns current gas balance in RTC. - """ - r = get_client().get(f"{BEACON_URL}/relay/gas/balance/{agent_id}") - r.raise_for_status() - return r.json() - - -@mcp.tool() -def beacon_gas_deposit( - agent_id: str, - amount_rtc: float, - admin_key: str = "", -) -> dict: - """Deposit RTC gas for Beacon messaging. - - Gas powers agent-to-agent communication. Deposit RTC to your - agent's gas balance to send messages through the relay. - - Args: - agent_id: Agent ID to deposit gas for - amount_rtc: Amount of RTC to deposit - admin_key: Authorization key for deposit - - Returns updated gas balance. - """ - headers = {} - if admin_key: - headers["X-Admin-Key"] = admin_key - - r = get_client().post( - f"{BEACON_URL}/relay/gas/deposit", - json={"agent_id": agent_id, "amount_rtc": amount_rtc}, - headers=headers, - ) - r.raise_for_status() - return r.json() - - @mcp.tool() def beacon_contracts(agent_id: str = "") -> dict: """List Beacon contracts (bounties, agreements, accords). @@ -1168,10 +1114,7 @@ def contributor_lookup(username: str) -> dict: wallet_ids_to_try = [username, f"rtc-{username}", username.lower()] for wallet_id in wallet_ids_to_try: try: - r = client.get( - f"{RUSTCHAIN_NODE}/balance", - params={"miner_id": wallet_id}, - ) + r = client.get(f"{RUSTCHAIN_NODE}/balance/{wallet_id}") if r.status_code == 200: balance_data = r.json() if balance_data.get("balance_rtc", 0) > 0 or balance_data.get("amount_i64", 0) > 0: diff --git a/tests/test_bottube_endpoints.py b/tests/test_bottube_endpoints.py index b80fa7b..4b1618d 100644 --- a/tests/test_bottube_endpoints.py +++ b/tests/test_bottube_endpoints.py @@ -92,3 +92,22 @@ def test_no_dead_v1_paths_anywhere(rec): srv.bottube_trending() srv.bottube_agent_profile("a") assert all("/api/v1/" not in url for _, url, _, _ in rec.calls) + + +# --- RustChain balance path-lock (was /balance?miner_id=, dead; now /balance/{id}) --- +def test_rustchain_balance_uses_path_param(rec): + srv.rustchain_balance("sophia-elya") + m, url, params, _ = _last(rec) + assert m == "GET" and url.endswith("/balance/sophia-elya") + assert "miner_id" not in params and "?" not in url + + +def test_wallet_balance_uses_path_param(rec): + srv.wallet_balance("dual-g4-125") + _, url, params, _ = _last(rec) + assert url.split("?")[0].endswith("/balance/dual-g4-125") and "miner_id" not in params + + +def test_gas_tools_removed(): + # the relay has no gas routes — these dead tools must not exist + assert not hasattr(srv, "beacon_gas_balance") and not hasattr(srv, "beacon_gas_deposit")