npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@stellarsight/agent

v0.1.0

Published

STELLARSIGHT agent surface — MCP server + x402 payment client for the Stellar Bazaar

Readme

STELLARSIGHT — agent surface

Find what to pay for on Stellar.

apps/agent is the agent-facing half of STELLARSIGHT: an MCP server that drops the Stellar Bazaar directly into an AI agent's runtime. The agent searches the bazaar in natural language, reads a resource's exact call contract, and then actually pays for it — the full discover → 402 → sign → retry → settle x402 loop happens inside a single tool call.

No API key. No vendor account. No human in the loop. Just a wallet.

This is RFP requirement 3.3.

| File | What it is | |---|---| | src/mcp-server.mjs | MCP server over stdio (@modelcontextprotocol/sdk v1.30) exposing four tools | | src/pay.mjs | Reusable x402 payment client — payAndFetch(url, opts) | | src/bazaar.mjs | Fail-soft HTTP client for the discovery index (/discovery/*) | | src/cli.mjs | Narrated terminal demo of the whole loop | | src/replay-guard.test.mjs | node:test proof that replays and expired auth entries are refused with a reason |

Testnet only. No relayer, no third-party channel service — the payment is signed locally with @x402/stellar and settled by the STELLARSIGHT facilitator on stellar:testnet.


Quick start

npm install
npm run setup                       # writes /.env with the funded testnet keys
npm run dev:all                     # facilitator :4021 · index :4022 · seller :4023

node apps/agent/src/cli.mjs "usd to brl exchange rate"

Everything here starts and degrades cleanly with the stack down. If the index or the seller is not reachable you get a coded rejection with an explanation, never a stack trace.


Wiring it into Claude

Claude Desktop — claude_desktop_config.json

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "stellarsight": {
      "command": "node",
      "args": ["/absolute/path/to/repo/apps/agent/src/mcp-server.mjs"],
      "env": {
        "STELLAR_NETWORK": "stellar:testnet",
        "STELLAR_RPC_URL": "https://soroban-testnet.stellar.org",
        "INDEX_URL": "http://localhost:4022",
        "FACILITATOR_URL": "http://localhost:4021",
        "PAYER_SECRET": "S...."
      }
    }
  }
}

Claude Code

claude mcp add stellarsight -- node /absolute/path/to/repo/apps/agent/src/mcp-server.mjs

or in .mcp.json at the project root:

{
  "mcpServers": {
    "stellarsight": {
      "command": "node",
      "args": ["apps/agent/src/mcp-server.mjs"]
    }
  }
}

PAYER_SECRET and friends are read from the repo-root /.env when they are not in env, so the plain form above works once scripts/setup-testnet.mjs has run. Diagnostics go to stderr only — stdout is the JSON-RPC transport.


Tools

All four tools return both a JSON text block (for the model) and structuredContent (for the host). Every result is { ok: true, ... } or { ok: false, code, reason }. reason is never null on a rejection.

stellarsight_search

Ranked natural-language search over the bazaar. Each candidate carries the index's _explain breakdown, so the ranking is auditable rather than a black box.

// input
{
  "query":    "string, required — what the agent needs",
  "limit":    "integer 1-50, optional (default 5)",
  "network":  "string, optional — CAIP-2 filter, e.g. stellar:testnet",
  "maxPrice": "string, optional — budget ceiling in atomic units"
}

// output
{
  "ok": true,
  "query": "usd to brl exchange rate",
  "items": [{
    "id": "http://localhost:4023/v1/fx/usd-brl",
    "url": "...", "serviceName": "stellarsight-fx", "description": "...", "tags": ["fx"],
    "type": "http", "network": "stellar:testnet", "scheme": "exact",
    "payTo": "G...", "asset": "C...", "maxAmountRequired": "100000",
    "settlements": 1,
    "score": 0.4982,
    "_explain": { "bm25": 3.51, "terms": [...], "matchedFields": [...], "quality": {...} }
  }],
  "partialResults": false,
  "pagination": { "limit": 5, "cursor": null },
  "source": "http://localhost:4022"
}

stellarsight_browse

Unranked catalogue listing. Use it to see what exists, or to enumerate one seller's endpoints.

// input
{ "type": "http | mcp, optional", "payTo": "G..., optional",
  "network": "string, optional", "limit": "1-100, default 20", "offset": "integer, default 0" }

// output
{ "ok": true, "items": [ /* same summary shape as search, without score */ ],
  "total": 4, "limit": 20, "offset": 0, "source": "http://localhost:4022" }

stellarsight_describe

Full discovery metadata for one resource, flattened into a call-construction brief: every parameter with its type, whether it is required, and its description — so the agent can build a valid call with no external documentation.

// input
{ "id": "string, required — resource id from search/browse (url, or url#toolName for MCP)" }

// output
{
  "ok": true,
  "id": "http://localhost:4023/v1/fx/usd-brl",
  "resource": { "url": "...", "serviceName": "...", "description": "...", "tags": [...] },
  "type": "http", "network": "stellar:testnet", "scheme": "exact",
  "payTo": "G...", "asset": "C...", "maxAmountRequired": "100000",
  "routeTemplate": "/v1/fx/{pair}",
  "input":  { "type": "http", "method": "GET", "queryParams": {...} },
  "output": { "type": "json", "example": {...} },
  "parameters": [
    { "name": "pair", "in": "query", "type": "string", "required": true,
      "description": "Currency pair", "enum": null, "example": "USD/BRL" }
  ],
  "howToCall": { "tool": "stellarsight_pay", "url": "...", "method": "GET", "params": {...},
                 "methodHint": "Pass params as the query string (stellarsight_pay defaults to GET).",
                 "note": "..." },
  "source": "http://localhost:4022"
}

stellarsight_pay

The whole x402 loop in one call: request → 402 challenge → sign the Soroban auth entry with the operator's PAYER_SECRET → retry with the payment header → return the unlocked body plus the settled transaction hash and its explorer link.

Spends real testnet funds. Set maxPrice to cap it.

// input
{
  "url":       "string, required — absolute URL of the paid resource",
  "params":    "object, optional — query string for GET, JSON body for POST/PUT/PATCH",
  "method":    "GET | POST | PUT | PATCH | DELETE, optional (default GET)",
  "maxPrice":  "string, optional — spend ceiling in atomic units",
  "timeoutMs": "integer 1000-120000, optional (default 30000)"
}

// output
{
  "ok": true,
  "paid": true,
  "status": 200,
  "body": { "pair": "USD/BRL", "bid": 5.4312, "ask": 5.4389, "mid": 5.435 },
  "txHash": "9f2c…",
  "explorerUrl": "https://stellar.expert/explorer/testnet/tx/9f2c…",
  "payer": "G...", "network": "stellar:testnet",
  "amount": "100000", "asset": "C...", "payTo": "G...",
  "timings": { "challengeMs": 12, "signMs": 640, "settleMs": 2180, "totalMs": 2832 }
}

A free resource is not an error: it returns { ok: true, paid: false, body }. timings is always present, including on rejections — the UI reads it.


Error codes

Every rejection is { ok: false, code, reason } with a non-null, human-readable reason. Nothing throws out of a tool handler.

| Code | Meaning | Typical fix | |---|---|---| | STELLARSIGHT_CONFIG_MISSING | PAYER_SECRET absent or not a valid S... seed | run scripts/setup-testnet.mjs, or set it in the MCP env block | | STELLARSIGHT_BAD_REQUEST | malformed argument (empty url/query/id, non-integer maxPrice) | fix the argument named in the reason | | STELLARSIGHT_INDEX_UNREACHABLE | the discovery index did not answer | start the stack (npm run dev:all) or set INDEX_URL | | STELLARSIGHT_INDEX_ERROR | index answered non-2xx or non-JSON | check the index logs; the HTTP status is in the reason | | STELLARSIGHT_NO_RESULTS | nothing matched the query or the filters | broaden the query, or raise maxPrice | | STELLARSIGHT_NOT_FOUND | no resource with that id is registered | get a valid id from stellarsight_search / stellarsight_browse | | STELLARSIGHT_RESOURCE_UNREACHABLE | the seller endpoint refused the connection | the seller is down, or the URL is wrong | | STELLARSIGHT_402_MALFORMED | 402 with no decodable PAYMENT-REQUIRED header and no accepts body | the seller is not speaking x402 v2 | | STELLARSIGHT_UNSUPPORTED_NETWORK | resource wants a network/scheme this agent is not configured for | testnet only; check STELLAR_NETWORK | | STELLARSIGHT_PRICE_EXCEEDS_BUDGET | quoted price is above the caller's maxPrice | raise maxPrice, or pick a cheaper resource | | STELLARSIGHT_SIGN_FAILED | the Soroban auth entry could not be built or signed | check RPC reachability and the payer account | | STELLARSIGHT_INSUFFICIENT_BALANCE | payer lacks the asset, or has no trustline | fund the payer / add the trustline | | STELLARSIGHT_REPLAY_REJECTED | the payment authorization had already been consumed | sign a fresh payment; never reuse a header | | STELLARSIGHT_AUTH_EXPIRED | the auth entry's ledger bounds had passed | retry — signing is cheap | | STELLARSIGHT_SETTLE_FAILED | facilitator returned success: false for another reason | the facilitator's errorReason is quoted in the reason | | STELLARSIGHT_UPSTREAM_ERROR | unexpected non-402 HTTP error, or an internal throw | read the reason; the HTTP status is included | | STELLARSIGHT_TIMEOUT | the resource or index exceeded the timeout | raise timeoutMs |

The enum is exported as ERROR_CODES from src/pay.mjs, and facilitator failure strings are mapped onto it deterministically by classifySettleFailure().


The terminal demo

node apps/agent/src/cli.mjs "usd to brl exchange rate"
node apps/agent/src/cli.mjs "an agent that reads invoices" --dry-run
node apps/agent/src/cli.mjs "usd to brl exchange rate" --max-price 200000 --limit 3

Four movements, narrated live:

01  QUERY             the natural-language ask, and the wallet behind it
02  SIGHTS TAKEN      ranked candidates with score meters and _explain breakdowns
03  BEARING FIXED     the chosen resource, its price, its payee
04  PAYMENT SETTLED   402 challenge · auth-entry signing · settled tx · explorer link
    UNLOCKED PAYLOAD  the data the agent just bought

| Flag | Effect | |---|---| | --dry-run, -n | discovery and ranking only; never signs, never spends | | --max-price N | refuse to pay above N atomic units | | --limit N | number of candidates to sight (default 5) |


Using the payment client directly

import { payAndFetch, ERROR_CODES } from './apps/agent/src/pay.mjs';

const res = await payAndFetch('http://localhost:4023/v1/fx/usd-brl', {
  params: { pair: 'USD/BRL' },
  maxPrice: '200000',
  onEvent: (e) => console.log(e.stage)   // request · challenge · signed · settled
});

if (!res.ok) console.error(res.code, res.reason);
else console.log(res.body, res.txHash, res.explorerUrl, res.timings);

payAndFetch never throws for a protocol or network failure — it resolves to a coded result.


Tests

node --test apps/agent/src/replay-guard.test.mjs

Proves that a replayed PAYMENT-SIGNATURE header and an expired authorization entry are both refused, each with a non-null reason and the right code, and that no rejection path in the client can produce a null reason. The first three tests are hermetic (local stub seller, throwaway keypair, no network). The fourth exercises the live facilitator and skips cleanly when it is not running.


Environment

Read from the repo-root /.env, overridable by process.env or the MCP env block.

| Variable | Default | Used for | |---|---|---| | STELLAR_NETWORK | stellar:testnet | CAIP-2 network id passed to createEd25519Signer | | STELLAR_RPC_URL | https://soroban-testnet.stellar.org | Soroban RPC for simulation/signing | | INDEX_URL | http://localhost:4022 | discovery index | | FACILITATOR_URL | http://localhost:4021 | facilitator (/supported, /verify, /settle) | | SELLER_URL | http://localhost:4023 | demo seller | | PAYER_SECRET | — | the agent's wallet; required for stellarsight_pay | | PAYER_PUBLIC | — | display only | | ASSET_CODE | SXT | display only |

Protocol notes

Verified against the installed @x402/[email protected] build, not assumed:

  • 402 challenge arrives in the PAYMENT-REQUIRED response header (base64 JSON). STELLARSIGHT also accepts the same object in the JSON body, which is what several v2 servers emit.
  • The signed payload goes out as PAYMENT-SIGNATURE (x402 v2); STELLARSIGHT mirrors it onto X-PAYMENT so v1-shaped sellers work unchanged.
  • Settlement comes back in PAYMENT-RESPONSE / X-PAYMENT-RESPONSE as { success, errorReason, transaction, network, payer }.
  • Bazaar extension status rides on EXTENSION-RESPONSES (base64 JSON) and is surfaced as extensions.bazaar on the result.