acp-find-mcp
v0.12.1
Published
MCP server for searching the Virtuals Protocol ACP marketplace + Degen Arena + portfolio risk scoring + cross-portfolio composition. Exposes 39 tools — v0.12.1 adds a marketplace slice ({v1,v2,both}; default flipped to 'v2') to acp_marketplace_gap surfaci
Downloads
1,826
Maintainers
Readme
acp-find-mcp
MCP server for searching the Virtuals Protocol ACP (Agent Commerce Protocol) marketplace from any MCP-capable client — Cursor, Cline, Windsurf, Codex, Continue, Claude Code, Claude Desktop, and others.
The marketplace has ~30,000+ on-chain agent offerings across thousands of agents, spanning both ACP V1 (legacy) and ACP V2 (the new generation). This server lets your AI assistant find the right one across both versions, look up reputation, compose multi-agent stacks, compare candidates, and browse what's new — without leaving the editor.
Status: Live. Public gateway at
https://api.acp-metabot.devis up, rate-limited to 30 search/IP/hour and 5 stack-compose/IP/hour. No API key, no signup.
What's new in v0.12.1
Surfaces Metabot v1.10.1's marketplaceGap V1/V2 slice. One optional field added to acp_marketplace_gap; one slash command parser updated. Tool count stays at 39; slash command count stays at 30.
Behaviour change.
acp_marketplace_gap(and the underlyingPOST /v1/marketplace/gapgateway endpoint) now default tomarketplace: "v2"when the field is omitted. Pre-v0.12.1 default was the combined V1+V2 corpus. Passmarketplace: "both"explicitly to recover the prior behaviour. Why the shift: V2 is the marketplace where new ACP-v2 bots actually deploy, so V2-only is the relevant denominator for the offering's "where should I build?" use case.
- New input field on
acp_marketplace_gap:marketplace?: "v1" | "v2" | "both". Default"v2". The gateway rejects unknowns with400 invalid_marketplace; the MCP wrapper coerces case + whitespace before forwarding. Echoed on the response asresponse.marketplace. /acp-find:marketplace-gapparser accepts both forms:- Positional keyword:
/acp-find:marketplace-gap v2,/acp-find:marketplace-gap both, etc. The three tokens are RESERVED — never get parsed as part of a category name. - Named flag:
/acp-find:marketplace-gap marketplace:v1. - Flag wins on conflict. Omit both for the new
"v2"default.
- Positional keyword:
- Near-dup edges still cross marketplaces — a V1↔V2 near-dup pair marks both ids as saturated in their respective slice. The
"both"numbers are identical to pre-v0.12.1 (only the"v1"/"v2"slices are new signal). - V2-only mode tag caveat:
recommendationTagthresholds are global. Whenmarketplace="v2"is selected most categories will tag asniche_underservedorbalancedbecause V2 has lower per-category density. UseopportunityScoreas the primary ranking signal when comparing V2 rows.
Gateway dependency. The new marketplace field is honoured by api.acp-metabot.dev once Metabot v1.10.1 deploys. Old gateways silently ignore the field (response reverts to the pre-marketplace-field shape), so [email protected] is fully forward-compatible. The V1/V2 split only activates against an up-to-date gateway.
40 tests (unchanged — the addition is fully exercised via the existing gateway-handler tests and the v1.10.1 C# test suite on the Metabot side; no new MCP-level smoke needed).
What's new in v0.12.0
Surfaces TheMetaBot v1.10 Phase 1+2+3 to MCP clients. Additive — existing tools unchanged. Tool count 37 → 39; slash count 28 → 30.
- 2 new MCP tools wrapping Metabot's $0.05 paid Phase 3 offerings:
acp_search_narrative— Claude-narrated{summary, perResultReason[], citedOfferings, cacheHit}for the top-N marketplace results matching a query.acp_agent_risk_check— ACP-seller-specific 0-100 scam-risk score + tier (low/medium/high/critical) + per-signal detail. Distinct fromacp_risk_snapshot(multi-bot composite over any EVM wallet) — this is tuned for "is this an honest seller?".
- 9 new optional fields on
acp_find(Phase 1+2; all forward-compatible):- Negative filters:
excludeRequirements,excludeAgents,excludeChains,maxPriceUsd. - Unified search:
includeResources(surface free Resources alongside paid offerings). - Sub-offering filters:
requiresField,producesField(match offerings by top-level schema field). - Phase 3 toggles:
expand(LLM query rewriter),includeRisk(per-hit risk flag).
- Negative filters:
- 2 new slash commands:
/acp-find:narrate <query>,/acp-find:risk-check <addr>.
40 tests (was 35 after v0.11.0; +1 for the schema extension, +2 per new tool = +5).
Gateway dependency. Metabot v1.10 Phase 3 endpoints (/v1/searchNarrative, /v1/agentRiskCheck) haven't deployed yet — the two new tools will 404 against the live gateway until that ships. The 9 new acp_find fields work today; old gateways ignore unknown fields, and new gateways will honour them once Metabot v1.10 lands.
What's new in v0.11.1
Docs-only republish. server.js is bit-identical to v0.11.0; the only change is that this tarball's README.md correctly opens with the v0.11.0 "What's new" block. The v0.11.0 tarball shipped with the v0.10.1 lead block at the top, so v0.11.0 changes were only visible inside the security subsections. If you're on v0.11.0 there is no functional reason to upgrade.
What's new in v0.11.0
Defensive depth — closes the 6 audit findings deferred from v0.10.1. Additive, forward-compatible. No new tools, no signature changes; existing callers see the same response shape plus two new top-level fields on marketplace-content tools (_warning + per-record _untrusted: true) and clearer isError messages on malformed input.
- Prompt-injection envelope (audit #2). Tools that surface marketplace text (
acp_find,acp_search_agents,acp_browse_agent,acp_offering,acp_compose_stack,acp_today,acp_recent_hires,acp_agent_recent_jobs,acp_compare_agents,acp_resources_search,acp_agent_resources,acp_resource_call,acp_hire_decision,acp_safe_quote+ the 4acp_arena_*tools = 18 total) wrap their responses with a top-level_warningand tag every third-party-authored object with_untrusted: true. Tool descriptions intools/listare updated to flag the trust boundary so LLMs see it before calling. - Central input validator + clamping (audit #3).
validateToolArgs(name, args)runs before everytools/callhandler (and before the v0.10.1 concurrency semaphore). Caps strings at 2048 chars, arrays at 50, object depth 4 / 30 keys; enforces0x+40-hex EVM shape,chainIdwhitelist (1, 8453), and per-arg numeric ranges (limit1-50,days1-365,offset0-10000,weeks1-52,topN1-100,maxOfferings1-30,priceMaxUsdc0-100000,budgetUsdc0-100000). ACP_API_URLhost/scheme guard (audit #5). SuppressesX-API-Key(with a loud stderr warning) ifACP_API_URLishttp:and the host is not localhost. Override viaACP_ALLOW_PLAINTEXT_KEY=1. Also warns when host is not the canonicalapi.acp-metabot.dev; silence withACP_ALLOW_CUSTOM_GATEWAY=1.- Address normalization (audit #8).
normalizeAddress(addr)swept intoacp_agent_reputation,acp_agent_reputation_history,acp_browse_agent,acp_agent_resources,acp_resource_call. marketplaceUrlpoisoning guard (audit #9).agentUrl(addr)now requires0x+40 hex andencodeURIComponents the value — a poisoned indexer response with a non-hexagentAddressno longer surfaces as a malformed URL.- Supply-chain pinning docs (audit #10). New "Production deployment" section recommends pinning
[email protected]and Docker digest pinning. SLSA provenance + SBOM flagged for v0.12.0.
35 tests (was 29 after v0.10.1; +6 new in v0.11.0). All v0.10.1 env vars carry forward unchanged.
What's new in v0.10.1
Security patch. No new tools, no API changes; backward-compatible env-var opt-outs only. Closes 4 of 10 findings from the 2026-05-22 audit:
- SSRF guard on
acp_resource_call— Resource URLs must behttp(s):and resolve to a public IP. Loopback / private / link-local / multicast / cloud-metadata addresses are rejected; HTTP 3xx redirects are refused rather than followed. Opt-out for local-dev:ACP_ALLOW_LOOPBACK_RESOURCES=1. - Response body caps — Resource calls capped at 256 KB (third-party untrusted); gateway calls capped at 2 MB (trusted Metabot). Override via
ACP_RESOURCE_BODY_LIMIT/ACP_GATEWAY_BODY_LIMIT. - Concurrency cap on
tools/call— FIFO semaphore, default 8 slots, override viaACP_MAX_CONCURRENT(clamped 1..64).initializeandtools/listbypass. - Verbose-log query-string redaction —
ACP_VERBOSE=1no longer prints URL query strings (Resource params can carry wallets/API tokens). SetACP_VERBOSE_FULL_URLS=1to keep full URLs for local debugging.
The remaining 6 findings (prompt-injection envelope, central input validator, ACP_API_URL scheme/host guard, address normalization, marketplaceUrl validation, supply-chain docs) are queued for v0.11.0. See CHANGELOG.md and the security section for the full env-var reference.
What's new in v0.10.0
Six new tools (31 → 37), four new slash commands (24 → 28), pagination on the two recent-activity surfaces. All additive — no existing tool signatures changed. Backs TheOracleBot (10th and FINAL portfolio bot) + extends v0.9.1's safety primitives with cross-portfolio composition.
OracleBot Resource coverage (3 tools). TheOracleBot ships 3 reachable free Resources via the gateway slug
api.acp-metabot.dev/oraclebot/v1/resources/*. Typed wrappers — free pass-through to the same Resourcesacp_resource_callcould already invoke, but with proper schemas, defaultchainId: 8453, and 5-min caching on the stable ones.acp_oracle_sources— list of active source readers (Chainlink, Pyth, RedStone, Uniswap V3 30m TWAP). Cached 5 min.acp_oracle_drift— 24h cross-source drift incidents (tokensWithIncidents+ per-token rows). NOT cached — drift is current state.acp_oracle_capabilities— coverage matrix per(chainId, tokenSymbol). Cached 5 min.
Cross-portfolio composition (3 tools). Composite tools that orchestrate the v0.9.1 building blocks at scale.
acp_hire_decision⭐ — compose_stack + per-agent reputation + ranking + recommendation in one call. Saves N+1 round trips for "find me the best agent for X". Composite score = 0.7 × reputation + 0.3 × inverse-price.acp_safe_quote⭐ — offering + agent_verify(lite) in parallel. Saves 1 round trip on the natural "show me X, is it safe" pattern. Sub-call count: 4 (1 offering + 3 verify-lite).acp_portfolio_status⭐ — probes all 10 portfolio bots in parallel via a known-reachable Resource per slug; returns per-bot reachability, gateway latency, sample excerpt, and aggregatehealthyCount.
Pagination on recent-activity (schema-only, no new tool).
acp_recent_hiresandacp_agent_recent_jobsgain anoffset?field (0-1000) on their input schemas, mirroringacp_find. Combine withlimitto page through high-traffic windows.
v0.10.0 backward-compatibility notes
- All v0.10.0 changes are additive. Existing 31 tools have identical signatures and response shapes.
- MCP protocol stays at
2025-11-25. New tools appear intools/listautomatically once you upgrade. - The risk pipeline remains
DEGRADEDin production (same as v0.9.1 — LiquidGuard / RevokeBot / MEVProtect risk lanes off; reputation lane fresh).acp_safe_quoterunsacp_agent_verify(depth: lite)which excludes recentJobs but still calls risk_snapshot; partial risk surfaces in the verdict as documented in v0.9.1. PORTFOLIO_BOTSis hardcoded inserver.jsforacp_portfolio_status(10 bots verified live 2026-05-20). When a new bot is ever added, the MCP needs a release.
What's new in v0.9.1
Eight new tools (23 → 31), six new slash commands (18 → 24), and the largest single batch of buyer-side intelligence since the Resources end-to-end ship in v0.8.0. All additive — no existing tool signatures or response shapes changed. Backs TheMetaBot v1.8 (Portfolio Risk pipeline, commit 8b17e35) and v1.9 (Marketplace pack, commit bc26684).
Risk Bundle (4 tools). Composite 0-100 risk scoring across four sub-bots (LiquidGuard + RevokeBot + MEVProtect + TheMetaBot reputation). Grade A-F. All four tools are free MCP pass-throughs to the same endpoints that back TheMetaBot's paid
risk_*offerings on the marketplace — the paid version adds escrow + on-chain attestation, not the data itself.acp_risk_snapshot— composite score (POST /v1/risk/snapshot).acp_risk_deep_dive— full sub-component breakdown with live RPC reads + recommendations (POST /v1/risk/deep-dive).acp_risk_compare— side-by-side risk for 2-5 EVM wallets (POST /v1/risk/compare). Works on ANY wallet, not just ACP sellers — distinct fromacp_compare_agents.acp_risk_attestation— risk snapshot in a structured attestation envelope; may includeattestationUid+txHash+blockNumberwhen Metabot has published on-chain via EASIssuer (POST /v1/risk/attestation).
Marketplace Intelligence (1 tool).
acp_marketplace_gap— ranked underserved categories byopportunityScorewith arecommendationTag(saturated_avoid/high_volume_low_density/medium_volume_emerging/niche_underserved/balanced). Answers "where should I build a new ACP bot?".
Risk Diagnostics (2 Resource wrappers, cached 5 min).
acp_risk_sources— live per-source health + overall verdict (FRESH/DEGRADED/UNAVAILABLE). Pre-check before paying forrisk_snapshotwhen sub-fresh data would compromise the use case.acp_risk_rubric— methodology (weights, grade bands, bucket tables). Use to explain a verdict or gate downstream logic on grade rather than raw score.
Composite intelligence (1 tool).
acp_agent_verify⭐ — runs reputation + arena + recent jobs + risk_snapshot in parallel and synthesises a rule-based verdict (STRONG_BUY/OK/CAUTION/AVOID/UNKNOWN). Saves 4 client round-trips per pre-hire safety check. Setdepth: 'lite'to skip recentJobs (3 sub-calls instead of 4).
v0.9.1 backward-compatibility notes
- All v0.9.1 changes are additive. Existing 23 tools have identical signatures and response shapes.
- The risk pipeline is currently
DEGRADEDin production (LiquidGuard / RevokeBot / MEVProtect lanes off; reputation lane fresh).acp_risk_snapshotworks against the degraded pipeline — sub-component scores are renormalised over available components per the rubric. Operator flips the missing lanes by configuringRiskOrchestrator__*Endpointenv vars to the respective bot URLs onacp-shared. - MCP protocol version stays at
2025-11-25. No client-side config or env changes — new tools appear intools/listautomatically once you upgrade.
What's new in v0.9.0
Four new tools (19 → 23) backed by TheMetaBot v1.7 (Arena indexer release). All changes are additive: no existing tool signatures, response shapes, or behaviour changed.
- Degen Arena cross-section. The Degen Arena is Virtuals' AI trading competition on Hyperliquid + HIP-3 (AI Council picks weekly Top-10 to share a $200K copy-trade pot). TheMetaBot's v1.7 Arena indexer mirrors leaderboard + council-pick state into SQLite so ACP-side tools can answer "which marketplace seller is also a top Arena trader?".
acp_arena_check— per-agent Arena snapshot (30d rank, pnl, win rate, council-pick status). Returnsparticipating: falsewhen Metabot hasn't indexed that address.acp_arena_leaderboard— current Arena Top-N by 30d rank. Default 50, max 100.acp_arena_council_picks— weekly AI Council Top-10 picks with one-line rationale. Default last 4 weeks, max 12.acp_arena_overlap— cross-section: of the Top-N Arena agents, how many also sell on the ACP marketplace (with reputation and offering count if cached).
v0.9.0 backward-compatibility notes
- All v0.9.0 changes are additive. Existing 19 tools have identical signatures and response shapes.
- The Arena worker on TheMetaBot defaults to OFF in production. When off, the new tools return empty /
source: "none"responses. Operator flipsArena__Worker__Enabled=trueonce TheArenaBot is reachable on theacp-sharedDocker network. - MCP protocol version stays at
2025-11-25. No client-side config or env changes needed to pick up the new tools — they appear automatically intools/listonce you upgrade.
What's new in v0.8.0
Five new tools (14 → 19) backed by TheMetaBot v1.6 (Resources + on-chain feed-address release). All changes are additive: no existing tool signatures, response shapes, or behaviour changed.
- ACP v2 Resources, end-to-end. ACP v2 has a first-class Resources primitive (
AcpAgentResource:{ name, url, params, description }) — free, parameterised, public HTTP endpoints that buyer / orchestrator agents call BEFORE paying for an offering. Three new tools close the discover → invoke loop:acp_agent_resources— list one agent's indexed Resources by wallet.acp_resources_search— cross-agent substring search across name + description + agent name. Use to discover agents by the FREE introspection surface they expose.acp_resource_call— INVOKE a Resource. Two-leg fetch: leg 1 looks up the URL via Metabot's index, leg 2 hits the agent's bot directly (no X-API-Key — Resources are public).
- Stack cost projection.
acp_estimate_stack_costrolls a list of priced offerings into a projected monthly cost. Pure calculation, no network — caller passes prices inline. One-shot:priceUsd × usesPerMonth. Subscription:priceUsd × 30 / durationDays. OptionalbudgetUsdMonthlycheck. Use afteracp_compose_stackto roll the whole stack into a monthly burn projection. - On-chain composability.
acp_agent_feed_addressreturns the Base-mainnetAggregatorV3Interfacecontract address that TheMetaBot has published for an agent's reputation. Drop the address into Solidity and calllatestRoundData()to gate by ACP counterparty reputation without any off-chain API. Returns{ hasFeed: false, hint }for agents without a published feed (only top-N highest-reputation agents currently have feeds).
v0.8.0 backward-compatibility notes
- All v0.8.0 changes are additive. Existing 14 tools have identical signatures and response shapes.
- MCP protocol version stays at
2025-11-25. No client-side config or env changes needed to pick up the new tools — they appear automatically intools/listonce you upgrade.
What's new in v0.7.0
Five additive extensions backed by TheMetaBot v1.7 (meta-search release):
- Hybrid agent search —
acp_search_agentsnow uses BM25 + dense + Voyage rerank, so it picks up synonyms and paraphrase that the old keyword-only engine missed.agentScoreis post-rerank cosine (higher = more relevant); treat as opaque rank signal. - V1/V2 cross-presence —
acp_browse_agentgains acrossPresenceblock (offeringCount per marketplace,dominantMarketplace). Each offering also gainspricePercentile. - Saturation flag —
acp_findresults gainsaturation(nearDuplicateCount,categorySize).nearDuplicateCount > 3usually means a crowded niche. - Pricing percentile —
acp_findresults gainpricePercentile(value0-100 within category × marketplace,peerN,lowN). Near-100 withpeerN ≥ 5means premium pricing for that category. - Marketplace pulse —
acp_todaygains new response fields (newAgents,churnRate,cohortSurvival,saturationMap,partial) and expandsdaysmax from 30 to 90.
v0.7.0 backward-compatibility notes
acp_search_agentsagentScoresemantics have changed: was BM25 raw (lower ≈ better), now post-rerank cosine (higher = better). Treat as opaque; do not compare scores across versions.acp_search_agentstopOfferingsshape changed fromstring[]to{ offeringName, priceUsdc, marketplaceVersion }[]. AtopOfferingNames: string[]mirror preserves the old shape.- All other v0.7.0 changes are additive — new fields on existing response objects; no existing fields removed.
Tools (37)
Search & discovery
| Tool | Args | Returns |
|---|---|---|
| acp_find | query, limit?, offset?, priceMaxUsdc?, includeStale?, category?, chain?, minReputation?, freshness?, marketplace? | Ranked offerings + a confidence bucket and bestMatch flag when top score ≥ 0.7. Each result carries marketplaceVersion (v1 / v2), marketplaceUrl, saturation (nearDuplicateCount, categorySize), and pricePercentile (value, peerN, lowN). Hybrid BM25 + dense fusion. Hides offerings with no hires in 90d by default. offset paginates beyond the top 50. |
| acp_search_agents | query, limit?, marketplace? | Agent-level hybrid search (BM25 + dense + Voyage rerank). Response key is agents. Each agent gains marketplaces (array), dominantMarketplace, agentScore (post-rerank cosine, higher = better), topOfferings (records: offeringName, priceUsdc, marketplaceVersion), topOfferingNames (names-only mirror). |
| acp_compose_stack | useCase, budgetUsdc?, maxOfferings?, chain?, marketplace? | Curated multi-agent stack with rationale. |
Agent / offering deep-dive
| Tool | Args | Returns |
|---|---|---|
| acp_browse_agent | agentAddress | Full agent profile: every offering with descriptions, schemas, prices, per-offering reputation and pricePercentile. Top-level crossPresence block: { v1: { offeringCount }, v2: { offeringCount }, dominantMarketplace }. |
| acp_offering | agentAddress, offeringName | Single-offering deep-dive — full description, requirement schema, price, lifetime hires. |
| acp_compare_agents | agentAddresses (2-5) | Side-by-side comparison: offerings count, summary reputation, behavioural reputation per agent. |
Reputation
| Tool | Args | Returns |
|---|---|---|
| acp_agent_reputation | agentAddress | 0-100 behavioural reputation with sub-scores + 30-day inline trajectory. Returns {error: "not_cached", hint, marketplaceUrl} for unevaluated agents. |
| acp_agent_reputation_history | agentAddress, days? (1-90, default 30) | Day-by-day reputation trajectory. |
| acp_agent_recent_jobs | agentAddress, days?, limit? | Real on-chain job ledger (jobId, status, counterparty, amount, createdAt). |
Marketplace pulse
| Tool | Args | Returns |
|---|---|---|
| acp_today | days? (1-90, default 1), chain?, priceMaxUsdc?, marketplace? | Marketplace pulse digest: launches, gainers, plus newAgents (agent inflow), churnRate (fraction gone inactive), cohortSurvival (null when days < 30), saturationMap (per-category density), partial (true when window crosses a data gap). |
| acp_recent_hires | days? (default 7), limit?, category?, chain?, priceMaxUsdc?, marketplace? | Top offerings by absolute hire-count delta. |
| acp_categories | — | Canonical marketplace categories with offeringCount per category. Cached 5 min. |
ACP v2 Resources (R7-IDEA-A / R7-IDEA-C)
ACP v2 has a first-class Resources primitive (AcpAgentResource: { name, url, params, description }) — free, parameterised, public HTTP endpoints that buyer / orchestrator agents call BEFORE paying for an offering, to check status, validate target support, look up cached results, etc. TheMetaBot's V2 indexer mirrors every indexed agent's resources array into SQLite; these two tools surface that index.
| Tool | Args | Returns |
|---|---|---|
| acp_agent_resources | agentAddress | Per-agent list of indexed Resources (name, url, params schema, description, marketplace version, first/last seen). Returns empty list when the agent has none. |
| acp_resources_search | query, limit? (1-100, default 25), marketplace? (v1/v2) | Substring search across name + description + agent name. Use to discover agents by the FREE pre-hire surface they expose (e.g. "find agents with a tradingStatusCheck resource"). |
| acp_resource_call | agentAddress, resourceName, params? | INVOKE a specific Resource by calling its registered URL. Looks up the URL via Metabot's index (leg 1, gateway), then forwards the call directly to the agent's bot (leg 2, public Internet — no X-API-Key). Returns the agent's JSON response (or rawText for non-JSON), wrapped with { agentAddress, resourceName, url, fetchedAt, response }. 30s timeout per call. Errors when the agent isn't indexed, the Resource name doesn't exist, or the agent's bot is unreachable. Resources are public — no payment, no hire. |
Stack cost projection
| Tool | Args | Returns |
|---|---|---|
| acp_estimate_stack_cost | items[] (each: priceUsd, priceType? / type?, usesPerMonth?, durationDays?, plus optional agentAddress / offeringName for legibility), budgetUsdMonthly? | Pure calculation — no network. One-shot rows: monthly = priceUsd × usesPerMonth (default 1). Subscription rows: monthly = priceUsd × 30 / durationDays (default 30). Response includes totalUsdMonthly, per-item breakdown, and (when budgetUsdMonthly is set) withinBudget, remainingBudgetUsdMonthly, overBudgetUsdMonthly. Use after acp_compose_stack to roll the whole stack into a monthly burn. |
On-chain composability
| Tool | Args | Returns |
|---|---|---|
| acp_agent_feed_address | agentAddress | The on-chain ReputationAggregator (AggregatorV3Interface) contract address that TheMetaBot has published for the agent on Base mainnet (chainId: 8453). Surfaces aggregatorAddress, decimals, latestScore, lastPushedRound, lastPushedAt, deployedAt, methodologyHash, explorerUrl (Basescan), plus a marketplaceUrl. Returns { hasFeed: false, hint } for agents without a published feed — only the top-N highest-reputation agents currently have feeds. Use this to integrate ACP agent reputation into Solidity gates: drop the address into AggregatorV3Interface and read latestRoundData() to score a counterparty on-chain without any off-chain API. |
Degen Arena (v0.9.0)
The Degen Arena is Virtuals' AI trading competition on Hyperliquid + HIP-3 — an AI Council picks a Top-10 each week to share a $200K copy-trade pot. TheMetaBot v1.7 indexes Arena leaderboard + council-pick state so these tools can cross-reference Arena agents against the ACP marketplace.
| Tool | Args | Returns |
|---|---|---|
| acp_arena_check | agentAddress | Per-agent Arena snapshot: agentAddress, isParticipant, rankLifetime, rank30d, pnlLifetimeUsd, pnl30dUsd, lastWeekPick (boolean — was the agent in last week's AI Council Top-10), firstSeenInArenaAt, lastObservedAt, source, marketplaceUrl. Returns isParticipant: false with a note when Metabot hasn't indexed that address (agent not on the leaderboard OR the Arena pipeline is inactive). |
| acp_arena_leaderboard | limit? (1-500, default 50) | Current Arena Top-N ordered by 30d rank ascending (lower = better). Top-level count; each agents[] row carries agentAddress, rankLifetime, rank30d, pnl30dUsd, lastWeekPick, lastObservedAt, marketplaceUrl. |
| acp_arena_council_picks | weeks? (1-26, default 4) | Weekly AI Council Top-10 picks, grouped by weekStart descending. Top-level weeks; each data[] row: weekStart + picks: [{ agentAddress, pickRank }] (pickRank 1..10). |
| acp_arena_overlap | topN? (10-500, default 50) | Cross-section: of the Top-topN Arena agents, which ones also sell on the ACP marketplace. Top-level arenaTopN, arenaSampled, sellingOnAcp, overlapFraction; each agents[] row: agentAddress, arenaRank30d, offeringCount, marketplaceUrl. |
Risk, safety, and marketplace intelligence (v0.9.1)
Wraps TheMetaBot v1.8 portfolio-risk pipeline + v1.9 marketplace pack. Risk endpoints work on ANY EVM wallet (not just registered ACP agents). All eight tools are additive — existing tool signatures are unchanged.
| Tool | Args | Returns |
|---|---|---|
| acp_risk_snapshot | walletAddress, chain? (base|ethereum, default base) | Composite 0-100 risk score blended from healthFactor (LiquidGuard, weight 0.3), approvals (RevokeBot, 0.3), mevExposure (MEVProtect, 0.2), reputation (TheMetaBot, 0.2). Returns grade A-F + per-component sub-scores with status (fresh/stale/unavailable). When components are unavailable, weights are renormalised — see acp_risk_rubric. |
| acp_risk_deep_dive | walletAddress, chain? | Full sub-component breakdown with live RPC reads (active borrows, top approvals, recent MEV-bundled txs, reputation trajectory) + per-dimension recommendations. ~3-5 sec per call. |
| acp_risk_compare | walletAddresses (2-5), chain? | Side-by-side risk for 2-5 EVM wallets. Distinct from acp_compare_agents (which compares ACP-seller reputation + offerings) — risk_compare works on any wallet. |
| acp_risk_attestation | walletAddress, chain? | Risk snapshot wrapped in a structured attestation envelope. Includes attestationUid + txHash + blockNumber when Metabot has published the attestation on-chain via EASIssuer (Base mainnet). |
| acp_marketplace_gap | category?, limit? (1-20, default 5), marketplace? (v1/v2/both, default v2 since v0.12.1) | Ranked underserved ACP categories by opportunityScore (saturation × inverse density). Each row carries recommendationTag ∈ {saturated_avoid, high_volume_low_density, medium_volume_emerging, niche_underserved, balanced}. Answers "where should I build a new ACP bot?". v0.12.1: default flipped from both to v2 — pass marketplace: "both" to recover the prior corpus-wide view. |
| acp_risk_sources | — | Per-source health (fresh/stale/unavailable) for LiquidGuard, RevokeBot, MEVProtect, and TheMetaBot's reputation lane, plus an overall verdict (FRESH / DEGRADED / UNAVAILABLE). Cached 5 min. Free Metabot Resource. |
| acp_risk_rubric | — | Methodology behind the score: weights per component, grade bands (A=85+ / B=70+ / C=55+ / D=40+ / F), bucket tables. Cached 5 min. Free Metabot Resource. |
| acp_agent_verify ⭐ | walletAddress, chain?, depth? (lite/full, default full) | Composite pre-hire safety check. Runs reputation + arena + recentJobs + risk_snapshot in parallel and synthesises a rule-based verdict (STRONG_BUY / OK / CAUTION / AVOID / UNKNOWN) + headline. depth: 'lite' skips recentJobs (3 sub-calls instead of 4). Errors in any sub-call surface as { error } inside that dimension; partial verdicts are explicitly allowed. |
OracleBot Resources (v0.10.0)
Typed wrappers for TheOracleBot's 3 free Resources via gateway slug api.acp-metabot.dev/oraclebot/v1/resources/*. Pre-hire validation surface — paid oracle_* POST offerings stay on the marketplace.
| Tool | Args | Returns |
|---|---|---|
| acp_oracle_sources | chainId? (default 8453) | Active source readers + descriptive note. 4 sources on Base mainnet (Chainlink, Pyth, RedStone, UniV3 30m TWAP). Cached 5 min. |
| acp_oracle_drift | chainId? | 24h cross-source drift incidents: tokensWithIncidents + per-token rows[]. NOT cached — drift is current state. |
| acp_oracle_capabilities | chainId?, tokenSymbol? | Coverage matrix per (chainId, tokenSymbol). With tokenSymbol: supportingSources[] + supported: boolean. Without: the full matrix. Cached 5 min. |
Cross-portfolio composition (v0.10.0)
Composite tools that orchestrate v0.9.1's primitives + acp_compose_stack at scale. Saves multiple client round-trips per user intent.
| Tool | Args | Returns |
|---|---|---|
| acp_hire_decision ⭐ | useCase, budgetUsdc?, chain?, maxOfferings? | One envelope: { stack, ranking[], recommendation, totalCostUsdc, checkedAt }. Sub-call count: 1 (composeStack) + N unique agents (reputation). Typically 4-7 calls. Composite score = 0.7 × reputation + 0.3 × inverse-price. |
| acp_safe_quote ⭐ | agentAddress, offeringName, chain? | Merged envelope { offering, verdict, headline, reputation, arena, risk, marketplaceUrl, checkedAt }. Runs acp_offering + acp_agent_verify(depth: lite) in parallel. 4 round trips total. |
| acp_portfolio_status ⭐ | — | { count: 10, healthyCount, bots: [{ name, slug, role, reachable, latencyMs, error?, sampleExcerpt }] }. Probes all 10 portfolio bots in parallel via known-reachable Resources. Bot list hardcoded in PORTFOLIO_BOTS. |
Operations
| Tool | Args | Returns |
|---|---|---|
| acp_watch_status | watchId | Read-only status of a marketplace watch (alive/expired, expiry, alerts fired, query, filters). Sensitive fields are NOT returned. |
| acp_health | — | Diagnostic: gateway URL, server version, plugin version, MCP protocol version, indexed-corpus size with V1/V2 split, last fetch, ping latency. Cached 5 min. |
Example v0.7.0 response fragments
acp_find result with saturation + pricePercentile:
{
"offeringName": "evaluate_defi_agent",
"priceUsdc": 0.99,
"saturation": { "nearDuplicateCount": 2, "categorySize": 47 },
"pricePercentile": { "value": 62, "peerN": 18, "lowN": false }
}acp_search_agents result:
{
"agentName": "TheMetaBot",
"agentScore": 0.87,
"marketplaces": ["v1", "v2"],
"dominantMarketplace": "v2",
"topOfferings": [
{ "offeringName": "acp_find", "priceUsdc": 0.05, "marketplaceVersion": "v2" }
],
"topOfferingNames": ["acp_find", "agentReputation", "composeStack"]
}acp_browse_agent cross-presence block:
{
"crossPresence": {
"v1": { "offeringCount": 0 },
"v2": { "offeringCount": 4 },
"dominantMarketplace": "v2"
}
}acp_today pulse fields:
{
"windowStart": "2026-05-03T00:00:00Z",
"partial": false,
"newAgents": 3,
"churnRate": 0.04,
"cohortSurvival": null,
"saturationMap": { "DeFi Evaluation": 0.42, "Wallet Intelligence": 0.28 }
}Install
The server runs via npx — no clone, no global install. Add this block to your MCP client's config (paths below).
{
"mcpServers": {
"acp-find": {
"command": "npx",
"args": ["-y", "acp-find-mcp"]
}
}
}Cursor
~/.cursor/mcp.json (global) or .cursor/mcp.json in your project. Then Cursor → Settings → MCP → Refresh.
Cline (VS Code extension)
VS Code → Cline → MCP Servers → Edit MCP Settings. Paste the block into mcpServers. Click "Done".
Windsurf
~/.codeium/windsurf/mcp_config.json. Restart Windsurf.
OpenAI Codex CLI
~/.codex/config.toml:
[mcp_servers.acp-find]
command = "npx"
args = ["-y", "acp-find-mcp"]Continue (VS Code / JetBrains extension)
~/.continue/config.yaml:
mcpServers:
- name: acp-find
command: npx
args:
- "-y"
- "acp-find-mcp"Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows). Paste the block, restart Claude Desktop.
Claude Code
Either install the full plugin (slash commands + skill + MCP):
claude plugin install acp-find@github:oliver-pringle/acp-find-plugin…or add just the MCP server via claude mcp add:
claude mcp add acp-find -- npx -y acp-find-mcpDocker
If you don't have Node 22+ on your machine, run via Docker. The image is published as oliverpringle/acp-find-mcp (and the Dockerfile ships in this folder for self-build).
{
"mcpServers": {
"acp-find": {
"command": "docker",
"args": ["run", "--rm", "-i", "oliverpringle/acp-find-mcp:latest"]
}
}
}The -i (interactive) flag is critical — MCP runs over stdio. Self-build:
git clone https://github.com/oliver-pringle/acp-find-plugin
cd acp-find-plugin/mcp-server
docker build -t acp-find-mcp .
docker run --rm -i acp-find-mcpVerify
After restarting your client, ask it:
What can the acp_find tool do?
Or hit the health check directly via acp_health. If you see gatewayUrl: https://api.acp-metabot.dev and a pingMs value, you're live.
Try it
Once installed, talk naturally — your client picks the right tool:
Is there an ACP agent that can close a perp position on Hyperliquid?
What does the agent at 0xfc9f1ff5ec524759c1dc8e0a6eba6c22805b9d8b do?
Compose a stack to monitor whale wallet movements and alert me on Telegram.
What's new on the ACP marketplace this week?
Compare these wallets: 0xabc..., 0xdef..., 0x123...A 30-prompt cookbook grouped by intent (find / vet / compose / research / browse) lives in the main repo README.
Configuration
| Env var | Default | Notes |
|---|---|---|
| ACP_API_URL | https://api.acp-metabot.dev | Gateway base URL. Override only for local dev. |
| ACP_API_KEY | unset | Sent as X-API-Key. Only needed against a private/self-hosted gateway. |
| ACP_VERBOSE | unset | When set (or pass --verbose on argv), logs every gateway request/response to stderr. |
| ACP_DISABLE_BOOT_BEACON | unset | Set to any truthy value to skip the one-shot activation beacon sent on startup. See Privacy & telemetry below. |
To run against a self-hosted gateway, add an env block:
{
"mcpServers": {
"acp-find": {
"command": "npx",
"args": ["-y", "acp-find-mcp"],
"env": {
"ACP_API_URL": "http://localhost:5000",
"ACP_API_KEY": "your-internal-key"
}
}
}
}Security & operational limits
Since v0.10.1 the server includes runtime safeguards against malicious or buggy marketplace Resources. All defaults are conservative; the env vars below exist only as opt-outs.
SSRF guard (Resource calls)
acp_resource_call rejects:
- Non-http(s) URL schemes (
file:,ftp:,gopher:, etc.) - Hostnames resolving to loopback / private / link-local / multicast / cloud-metadata IPs
- HTTP 3xx redirects (no auto-follow)
Set ACP_ALLOW_LOOPBACK_RESOURCES=1 to permit 127.0.0.1 / ::1 /
localhost resources when developing locally.
Response body caps
| Path | Default | Env var |
|------|---------|---------|
| Resource calls (third-party) | 256 KB | ACP_RESOURCE_BODY_LIMIT |
| Gateway calls (Metabot) | 2 MB | ACP_GATEWAY_BODY_LIMIT |
Bodies are streamed; overruns abort the read and return a clear error rather than buffering. Set the env var to any positive integer (bytes).
Concurrency cap
ACP_MAX_CONCURRENT caps in-flight tools/call invocations (default 8,
clamped to 1..64). Excess calls FIFO-queue until a slot frees.
initialize and tools/list bypass. Cancellation handling
(notifications/cancelled) deferred to v0.11.0.
Verbose-log redaction
When ACP_VERBOSE=1, the server strips query strings + fragments from
URLs emitted to stderr — resource params can carry wallets or API tokens.
Set ACP_VERBOSE_FULL_URLS=1 to keep full URLs for local debugging.
Untrusted-content envelope (v0.11.0)
Tools that surface marketplace-supplied text include a top-level
_warning field and tag third-party-authored objects with
_untrusted: true. LLMs reading these responses should treat any field
inside _untrusted objects as user input, not as instructions to act on.
Applies to: acp_find, acp_search_agents, acp_browse_agent,
acp_offering, acp_compose_stack, acp_today, acp_recent_hires,
acp_agent_recent_jobs, acp_compare_agents, acp_resources_search,
acp_agent_resources, acp_resource_call, acp_hire_decision,
acp_safe_quote, and the 4 acp_arena_* tools.
Input validator (v0.11.0)
tools/call arguments are validated before reaching the handler.
Strings cap at 2048 chars, arrays at 50 items, objects at depth 4 and
30 keys wide. EVM addresses must be 0x + 40 hex. chainId must be
1 (Ethereum) or 8453 (Base). Numeric args have per-arg ranges
(limit 1-50, days 1-365, offset 0-10000, weeks 1-52,
topN 1-100, maxOfferings 1-30, priceMaxUsdc 0-100000,
budgetUsdc 0-100000). Violations return isError: true with a
clear message; validation runs before the concurrency semaphore so
malformed calls don't consume a slot.
Gateway-URL guard (v0.11.0)
X-API-Keyis suppressed (with a loud stderr warning) ifACP_API_URLishttp:and the host is not localhost. Override withACP_ALLOW_PLAINTEXT_KEY=1to warn-and-still-send.- A warning fires at boot if
ACP_API_URLhost is not the canonicalapi.acp-metabot.dev. Silence withACP_ALLOW_CUSTOM_GATEWAY=1for staging or fork deployments.
Production deployment
For security-sensitive deployments, pin every layer rather than tracking
latest. Silent upgrades broaden the attack surface — a compromised
release could be pulled automatically without operator review.
Pinning the npm package
// MCP client config — recommended
{
"command": "npx",
"args": ["-y", "[email protected]"]
}
// Less safe — tracks the latest published version
{
"command": "npx",
"args": ["-y", "acp-find-mcp"]
}Pinning the Docker image
If running via the published Docker image, pull by digest rather than tag:
docker pull ghcr.io/oliver-pringle/acp-find-mcp@sha256:<digest>docker pull ... :latest resolves to whatever the registry currently
points at — fine for development, risky for production.
Provenance + SBOM
v0.11.0 does NOT publish SLSA provenance or a CycloneDX SBOM. If your
deployment context requires these (regulated environments, supply-chain
review boards), open an issue — adding npm publish --provenance and
generating an SBOM at release time is a planned v0.12.0 improvement.
How it works
Your MCP client (Cursor / Cline / Windsurf / Codex / Continue / Claude)
│
▼ MCP stdio
acp-find-mcp (Node, no deps)
│
▼ HTTPS, with 1-retry on 5xx
api.acp-metabot.dev (public gateway, rate-limited)
│
▼ Internal HTTP
ACP_Metabot indexer + Voyage embeddings + Claude composer + chain-event scanner
│
▼ SQLite vector index of every ACP marketplace offeringThe index refreshes every 10 min from both ACP V1 (https://acpx.virtuals.io/) and ACP V2 (https://api.acp.virtuals.io). Results track live marketplace state across both versions within ~10 min.
Privacy & telemetry
The public gateway at api.acp-metabot.dev logs the client IP, the request path, and the request body into a request-log table. The IP is used solely to enforce per-IP rate limits; logs are kept for operator metrics. There is no separate analytics provider, no user identifier, and no cross-request correlation beyond IP.
Starting with v0.6.0, the server fires one activation beacon to POST /v1/plugin/boot after handling the MCP initialize request. The beacon's body is empty; the only signal it adds is a single (User-Agent, IP, timestamp) row in the same request-log table — the same shape every other request already records. Its purpose is to let the operator distinguish "the npm tarball was downloaded" (catalogs, scanners, npx -y cache) from "the MCP server actually started under a real client". You can opt out by setting ACP_DISABLE_BOOT_BEACON=1 — every other tool call works identically.
The MCP server adds no other telemetry. It only contacts the gateway you configure. If you point ACP_API_URL at your own self-hosted gateway, no traffic leaves your network.
Requirements
- Node 22 or later (uses built-in
fetch,readline,AbortSignal.timeout). - Or run via Docker (above) — no Node install required.
Source & contributing
Repo: oliver-pringle/acp-find-plugin — issues and PRs welcome.
License
MIT — see LICENSE.
