Skip to content

Expand MCP tool surface: is_safe, score_batch, explain_risk, health_check#7

Merged
AlexanderLawson17 merged 4 commits into
mainfrom
feat/mcp-expansion
Apr 2, 2026
Merged

Expand MCP tool surface: is_safe, score_batch, explain_risk, health_check#7
AlexanderLawson17 merged 4 commits into
mainfrom
feat/mcp-expansion

Conversation

@AlexanderLawson17

Copy link
Copy Markdown
Owner

Summary

Expands Revettr MCP server from 1 tool to 5 tools, making the scoring surface integration-ready for Bankr, Gina, and Robonet partnerships. Extracts shared _score_one helper, adds amount_usd to existing tool, and creates 4 new tools with full test coverage.

Changes

  • Refactor: Extract _score_one(body) shared helper for payment path routing
  • Enhanced: score_counterparty now accepts amount_usd parameter
  • New: is_safe_to_transact — binary safety gate with configurable threshold
  • New: score_batch — parallel scoring of up to 10 wallets with Semaphore(5)
  • New: explain_risk — human-readable risk narrative via FLAG_DESCRIPTIONS mapping (17 flags)
  • New: health_check — API liveness probe
  • Tests: 45 new tests in test_mcp_tools.py and test_explain_flags.py
  • Version: 0.3.0 → 0.4.0

Plan Reference

Plan file: ~/.claude/plans/harmonic-sprouting-melody.md — Agent A workstream

Test Plan

  • pytest tests/ -v — all 45+ tests pass
  • MCP server starts: python -m revettr_mcp lists all 5 tools
  • is_safe_to_transact returns {"safe": true/false} with correct threshold logic
  • score_batch caps at 10 wallets, sorts by score desc
  • explain_risk maps known flags to sentences, unknown flags get generic fallback
  • health_check returns API status on 200, error dict on failure

Generated with Claude Code

Add is_safe_to_transact, score_batch, explain_risk, and health_check
MCP tools. Refactor shared scoring logic into _score_one helper. Add
amount_usd parameter to score_counterparty. Include FLAG_DESCRIPTIONS
constant with 17 human-readable risk flag explanations. Bump version
to 0.4.0.

New tools:
- is_safe_to_transact: quick yes/no wallet safety check with threshold
- score_batch: parallel scoring of up to 10 wallets with semaphore(5)
- explain_risk: human-readable flag explanations with tier recommendations
- health_check: API availability check

Tests: 45 new tests across test_mcp_tools.py and test_explain_flags.py.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff9d59e721

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread revettr_mcp/server.py
Comment on lines +251 to 255
if amount_usd is not None:
body["amount"] = amount_usd

if not body:
return {"error": "At least one input field is required (domain, ip, wallet_address, stellar_wallet, or company_name)"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce identifier presence when amount_usd is the only input

score_counterparty now adds amount_usd to body before checking whether any identifying field was provided, so a call like score_counterparty(amount_usd=100) bypasses the documented “at least one input field” guard and proceeds to _score_one with no counterparty identifier. This violates the tool contract and can trigger avoidable failed (or billable) upstream requests; the emptiness check should be based only on identifier fields (domain, ip, wallet_address, stellar_wallet, company_name).

Useful? React with 👍 / 👎.

Comment thread revettr_mcp/server.py
Comment on lines +381 to +382
# Sort by score descending
results.sort(key=lambda r: r.get("score", 0), reverse=True)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return score_batch results in the documented risk order

score_batch currently sorts with reverse=True, which places highest scores first, but the MCP tool instructions describe this output as “sorted by risk (lowest score first).” Consumers that use the first element as the riskiest counterparty will get the opposite ordering, so this should either sort ascending by score or have the contract text updated to match behavior.

Useful? React with 👍 / 👎.

- R1-2: Add exception handling to _call_direct (network errors no longer crash tools)
- R1-3: Add domain/ip/company_name validation to explain_risk (matches score_counterparty)
- R1-5: Fix sort order description in MCP instructions string

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexanderLawson17

Copy link
Copy Markdown
Owner Author

[Claude QA Review]

Summary

7 findings total: 3 auto-fixed, 2 need manual review, 2 informational (below threshold)

Auto-Fixed (commit 040e528)

  • R1-2 (HIGH): _call_direct lacked exception handling — network failures crashed 4/5 tools — resolved
  • R1-3 (HIGH): explain_risk skipped input validation for domain/ip/company_name — resolved
  • R1-5 (MEDIUM): MCP instructions described opposite sort order for score_batch — resolved

Needs Attention

  • [MEDIUM] R1-7: No test for score_batch partial failure scenario (where some wallets score and others error). The concurrent append pattern makes this the most important test gap.
  • [MEDIUM] R3-10: Existing test_defensive_instructions_in_tool_desc only checks score_counterparty docstring for "do not fabricate" text. The 3 new tools with user inputs (is_safe_to_transact, score_batch, explain_risk) also include this text but aren't verified by tests.

Plan Coverage

Work Item Status
Extract _score_one shared helper IMPLEMENTED
Add amount_usd to score_counterparty IMPLEMENTED
New tool: is_safe_to_transact IMPLEMENTED
New tool: score_batch IMPLEMENTED
New tool: explain_risk IMPLEMENTED
New tool: health_check IMPLEMENTED
Update FastMCP instructions IMPLEMENTED
Tests (test_mcp_tools + test_explain_flags) IMPLEMENTED (45 tests, exceeds ~25 target)
Version bump 0.3.0 → 0.4.0 IMPLEMENTED

All 9 plan items: IMPLEMENTED. No scope creep detected.


Review by Claude Code — 3 review agents (code quality, plan coverage, integration) + auto-fix cycle

@AlexanderLawson17

Copy link
Copy Markdown
Owner Author

[Claude CI Monitor] CI completed with failures: test (3.12), test (3.10), test (3.11)

…lity

The 127.0.0.1.evil.com hostname validation vulnerability was already
fixed — the xfail(strict=True) markers caused XPASS failures in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexanderLawson17

Copy link
Copy Markdown
Owner Author

[Claude CI Monitor] All CI checks passed on re-run (after xfail fix).

- R1-7: Add score_batch partial failure test (2 successes + 1 error,
  verifies both results and errors buckets populated correctly)
- R3-10: Extend defensive docstring test to cover all 4 tools that
  accept user identifiers (score_counterparty, is_safe_to_transact,
  score_batch, explain_risk). health_check exempt — no user inputs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexanderLawson17 AlexanderLawson17 merged commit 83283bf into main Apr 2, 2026
3 checks passed

@jp8x7rgh6j-cmd jp8x7rgh6j-cmd left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey boo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants