{
  "markdown": "# MCP Trust Registry\n\n<!-- mcp-name: io.github.saagpatel/mcp-trust -->\n\n[![CI](https://github.com/saagpatel/mcp-trust/actions/workflows/ci.yml/badge.svg)](https://github.com/saagpatel/mcp-trust/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n> Check before you connect. A neutral, public danger grade for the MCP servers\n> your AI agents rely on.\n\n**Live:** [mcp-trust.vercel.app](https://mcp-trust.vercel.app)\n\n> **Not yet published to PyPI.** Install from source using the Quickstart below.\n\n## Use as an MCP server\n\n`mcp-trust` runs as a read-only MCP server so an agent can check a server's\ndanger grade *before connecting* — it serves a baked snapshot of real scan\ngrades with explicit per-record provenance, so no database or network is needed.\n\n```bash\nmcp-trust mcp-serve          # from a source/dev install (works today)\nuvx mcp-trust mcp-serve      # once published to PyPI\n```\n\n| Tool | Description |\n|---|---|\n| `list_servers` | Every graded MCP server with its A-F grade, transparency, and danger score. |\n| `check_server` | Full grade, risk dimensions, and findings for one server by slug. |\n| `get_methodology` | How the A-F grade and transparency axis are computed, plus the honesty model. |\n\nThe MCP runtime admits the packaged catalog only after deterministic schema-v2\nvalidation, including duplicate-key rejection, required field/type checks, unique\nslugs and source coordinates, supported enums, sandbox/scan-mode agreement, and\ntimezone-aware scan timestamps. Admission also binds grade to danger score,\ntransparency to annotation coverage, and critical findings to the grade cap.\nRaw JSON is limited to 1 MiB, with deterministic server, finding, tool, and\npublic-string ceilings. Schema v2 preserves additive unknown fields; missing or\ninvalid required fields and unknown schema versions fail closed.\n\nIf catalog admission fails, `list_servers` and `check_server` serve zero records\nand return `mcp-trust-mcp-error.v1` with status `UNKNOWN`, error code\n`CATALOG_SNAPSHOT_INVALID`, sorted reason codes, and `server_count_served: 0`.\n`get_methodology` remains available. This boundary checks internal consistency;\nit does not prove snapshot authenticity, authorship, immutability, or freshness.\n\nOffline consumers can add those missing publication checks with\n`mcp-trust verify-snapshot`: a detached Ed25519 statement binds the exact\nsnapshot bytes, publisher ID, bounded issue/expiry window, monotonic publication\nID, and prior consumer checkpoint. The consumer must independently pin the\ntrust-root SHA-256 and preserve the returned checkpoint for rollback resistance.\nInvalid, expired, unknown-signer, forked, or rolled-back inputs return only\n`UNKNOWN` reason codes and no grades. See\n[`docs/OFFLINE-SNAPSHOT-TRUST-V1.md`](docs/OFFLINE-SNAPSHOT-TRUST-V1.md).\nStatement freshness proves recent publication authorization, not a recent scan;\nthe per-record scan timestamp and 90-day stale policy remain separate checks.\n\nNo production trust root, signing key, statement, or checkpoint ships today, so\nthe built-in MCP snapshot remains structural-only unless a consumer separately\nsupplies and pins those inputs. Test fixture keys are not publication keys.\n\nConnecting an MCP server hands it influence over what your agent does. Tool\npoisoning, prompt injection, over-broad permissions, and rug-pull tool\nmutations are documented attack classes -- and today there's no quick way to vet\na server before you wire it in. **MCP Trust Registry** scans public MCP servers\nand gives each one a single readable danger grade (A-F), a separate\ntransparency signal, and the findings behind them.\n\nThink OSV.dev / Socket.dev / haveibeenpwned, scoped to MCP servers.\n\n## Prerequisites\n\n- Python >= 3.11\n- [`uv`](https://docs.astral.sh/uv/) (used for dependency management and running the project)\n\n## MCP config portability studio\n\nRender one versioned, secret-placeholder-only MCP connection intent into staged\nCodex, Claude Code, Claude Desktop, or VS Code configuration and receive an\nexplicit semantic loss/widening report:\n\n```bash\nuv run --frozen --extra dev mcp-trust portability validate \\\n  tests/fixtures/portability/local-stdio.json\nuv run --frozen --extra dev mcp-trust portability round-trip \\\n  tests/fixtures/portability/local-stdio.json --host codex\n```\n\nThe studio is local-only. It never discovers or edits a real host config,\nlaunches an MCP server, contacts a URL, or emits modeled secret values. Generated\nconfiguration proves only documented host-format compatibility, not a runtime\nconnection or adoption. See\n[`docs/MCP-CONFIG-PORTABILITY-STUDIO.md`](docs/MCP-CONFIG-PORTABILITY-STUDIO.md).\n\n## How it works\n\n```\nregister a server  ->  scan via engine  ->  derive grade  ->  persist  ->  serve at a stable URL\n```\n\nThe registry does **not** reimplement vulnerability detection. It orchestrates a\npluggable scan engine -- the shipping backend wraps the public\n[`mcp-audits`](https://pypi.org/project/mcp-audits/) (>=2.1) package -- and owns the\ncatalog, the public trust-grade normalization, persistence, and the lookup API.\n\n## Quickstart\n\n```bash\ngit clone https://github.com/saagpatel/mcp-trust.git && cd mcp-trust\nuv pip install -e \".[dev]\"      # core + dev deps (runs on the built-in StubEngine)\nmcp-trust seed                  # load the seed catalog\nmcp-trust scan mcp-reference-time   # scan a catalog server, print its grade\nmcp-trust check mcp-reference-time  # look up the latest stored grade\nmcp-trust serve                 # serve the API on http://127.0.0.1:8000\n```\n\nFor real scanning install the engine extra and select it:\n\n```bash\nuv pip install -e \".[dev,engine]\"\nMCP_TRUST_ENGINE=mcpaudit mcp-trust scan mcp-reference-time\n```\n\nScanning launches the server's process. For **untrusted** servers, isolate\nexecution in a locked-down container (no network, read-only fs, dropped caps,\nresource limits):\n\n```bash\nMCP_TRUST_ENGINE=mcpaudit MCP_TRUST_SANDBOX=docker mcp-trust scan mcp-reference-time\n```\n\nThe default is no sandbox (safe only for servers you trust).\n\n## API\n\n| Method | Path | Purpose |\n|---|---|---|\n| `GET`  | `/` | **web** -- public catalog page (grade + transparency per server) |\n| `GET`  | `/ui/servers/{slug}` | **web** -- server detail page + README badge-embed snippet |\n| `GET`  | `/healthz` | liveness |\n| `GET`  | `/servers` | catalog + latest grade, provenance, and staleness per server (JSON) |\n| `GET`  | `/servers/{slug}` | full latest scan record + provenance/staleness and metadata (JSON) |\n| `POST` | `/servers/{slug}/scan` | operator scan trigger; public deployments disable this route |\n| `GET`  | `/servers/{slug}/badge.json` | shields.io-compatible README badge |\n\nEvery server has two orthogonal signals: a **danger grade** (A-F) and a\n**transparency level** (high/medium/low, from annotation coverage). Automated\ngrades are not endorsements, certifications, or claims that a server is\nmalicious. A low grade on a low-transparency server means \"cannot verify safe,\"\nnot \"known dangerous.\"\n\nHTTP scan triggering is fail-closed by default. Public deployments should set\n`MCP_TRUST_PUBLIC_READONLY=1`, which makes `POST /servers/{slug}/scan` return\n403 before any engine can run. Operator scans should normally run through the\nCLI against the persistent registry DB, not through public traffic.\n\nFor local API demos with the deterministic `StubEngine`, set\n`MCP_TRUST_ALLOW_UNAUTHENTICATED_STUB_SCANS=1`. Do **not** set that in public.\nToken-gated API scan triggering is still available for private operator surfaces\nby setting `MCP_TRUST_SCAN_TOKEN` and passing it as `Authorization: Bearer\n<token>` or `X-MCP-Trust-Scan-Token`.\n\nIf the newest stored scan row is unreadable, API, web, static, badge, and\nsnapshot projections fail closed to `UNKNOWN`; they never resurrect an older\ngrade. Stored source/risk/finding/evidence JSON has a 1 MiB per-field admission\nceiling, with bounded finding/tool collections and content-free diagnostics.\nAn unreadable older row leaves a readable latest grade intact but makes scan\nhistory and grade-change claims explicitly `UNKNOWN`. Snapshot construction\nstops until unreadable history is repaired or dispositioned.\n\nAll public surfaces use one fail-closed freshness projection. Exactly 90 days\nafter a scan is still `FRESH`; any later instant is `STALE`. Missing, malformed,\nor future scan times are `UNKNOWN`, with verdict fields withheld. Unscanned\nentries are `NOT_APPLICABLE`. Operator masking applies even when no scan exists\nand is never inferred from scan state. Static pages and badges are immutable\nhistorical evidence with a scan date or validity boundary; they do not promise\nrequest-time freshness. Danger, transparency, and evidence quality remain\nseparate signals, and a grade is never an endorsement.\n\nSet `MCP_TRUST_RECEIPTS_DIR=/data/mcp-trust/receipts` during real scan runs to\narchive a JSON receipt for each scan and store its portable artifact filename in\n`report_ref`.\n\n## Remote authorization metadata preflight\n\nRemote Registry candidates can be checked for discoverable MCP authorization\nmetadata without contacting the MCP endpoint or handling credentials. First\nbuild a candidate manifest from a previously saved official Registry response,\nthen select one exact `stable_id`:\n\n```bash\nuv run python scripts/plan_registry_corpus.py \\\n  --input path/to/saved-registry-response.json > /tmp/registry-candidates.json\n\nuv run mcp-trust auth-posture com.example/remote@1.0.0 \\\n  --manifest /tmp/registry-candidates.json \\\n  --pretty\n```\n\nIf a public `WWW-Authenticate: Bearer` challenge has already been obtained by a\nseparate operator workflow, pass its value with `--www-authenticate`. Otherwise\nthe command tries the MCP-required protected-resource well-known paths, followed\nby RFC 8414 and OpenID Connect authorization-server discovery in specification\norder.\n\nThe command emits `McpAuthorizationPostureV1` JSON. Exit 0 and\n`state=metadata-ready` mean only that at least one authorization server exposes\nthe endpoints and PKCE `S256` metadata needed for policy review. They do **not**\nprove authorization, credential availability, runtime security, scan\neligibility, or a trust grade. Unknown or invalid evidence exits 1 and stays\nblocked; an invalid local manifest binding exits 2.\n\nThe network boundary is deliberately narrow: HTTPS metadata GETs only, no\nambient proxies, redirects, credentials, endpoint session, or writes. DNS is\nresolved once per request; every answer must be globally routable, and the\nconnection is pinned to an accepted address while TLS validation and SNI remain\nbound to the original hostname. Response bodies are size-bounded, validated,\nand represented in output only by byte count and SHA-256. Successful metadata\nresponses must also carry a valid HTTP `Date`; declared cache freshness is\nhonored up to a 24-hour policy cap, while missing, future-dated, or stale source\nevidence remains unknown. The implementation is based on the\n[MCP authorization specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization),\n[RFC 9728](https://www.rfc-editor.org/rfc/rfc9728.html),\n[RFC 8414](https://www.rfc-editor.org/rfc/rfc8414.html), and\n[OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html).\n\n## Reusable web release readback\n\nThis repository owns the language-neutral `WebReleaseReadbackV1` contract and\nits standard-library reference verifier. A consumer supplies an explicit HTTPS\norigin plus a versioned route-sentinel manifest:\n\n```bash\npython scripts/web_release_readback.py \\\n  --manifest path/to/release-routes.json \\\n  --target-url https://preview.example.com \\\n  --pretty\n```\n\nThe command emits one structured receipt to stdout and exits nonzero when any\nstatus, required or forbidden sentinel, exact body, digest, body bound, timeout,\nor redirect assertion fails. It implements only GET and HEAD, ignores ambient\nproxies, accepts no credentials, and has no deployment, alias, DNS, promotion,\nor rollback capability. The schemas, deterministic artifact manifest, versioning\npolicy, and rollback boundary live under\n`contracts/web-release-readback-v1/`.\n\nThe owner repository also consumes the contract through\n`deploy/web-release-readback.json`. `deploy/smoke-readonly.sh` emits the shared\nroute receipt before running the registry-specific health, API, badge, portable\nreceipt-reference, and denied scan-POST assertions. This self-adoption is a\nrelease readback check only; it neither deploys nor changes an alias.\n\nThis generic receipt is additive. Product-specific API, badge, privacy, release\nlineage, and denied-mutation checks remain owned by each consumer until proven\nreceipt parity justifies removing only their duplicated HTTP assertion plumbing.\n\n## Evidence lineage decisions\n\n`EvidenceLineageLedgerV1` is a metadata-only, fail-closed contract for MCP\ncorpus admit, refresh, publish, and withdraw decisions. It binds exact identity,\ndigests, portable receipt references, freshness, rights evidence, public\nprojections, supersession, and retention without storing raw logs or secrets.\nThe read-only assessor requires an explicit observation time and emits stable\nreason codes; only an explicit `ALLOWED` status can authorize admit or publish.\n\nSee [`docs/EVIDENCE-LINEAGE-LEDGER-V1.md`](docs/EVIDENCE-LINEAGE-LEDGER-V1.md)\nfor the schema, decision semantics, three-record packaged-catalog pilot, claim\nceiling, and rollback boundary. This source capability does not itself migrate\nthe catalog, publish or withdraw records, run scans, or change deployment state.\n\n## Manual refresh candidates\n\nFirst emit the no-execution inventory, exact source/tool/image preflight, and\ndeterministic repeated fixture receipt:\n\nRuntime refresh commands require a separately prepared frozen `[engine]`\nenvironment. They use its exact interpreter and never hydrate dependencies as\npart of preflight or candidate creation:\n\n```bash\nPYTHON=./.venv/bin/python\ntest -x \"$PYTHON\"\n\n\"$PYTHON\" scripts/grade_refresh.py engine-materialization \\\n  --repo-root \"$PWD\" \\\n  --out ./dist/grade-refresh/engine-materialization.json\n\"$PYTHON\" scripts/grade_refresh.py inventory \\\n  --out ./dist/grade-refresh/inventory.json\n\"$PYTHON\" scripts/grade_refresh.py host-capacity \\\n  --anchor \"$PWD\" \\\n  --out ./dist/grade-refresh/host-capacity.json\n\n# Stop unless the two-reading receipt is READY. Start the separately approved\n# Colima instance only after this point, then create the bound preflight.\n\"$PYTHON\" scripts/grade_refresh.py preflight \\\n  --repo-root \"$PWD\" \\\n  --engine-materialization ./dist/grade-refresh/engine-materialization.json \\\n  --host-capacity ./dist/grade-refresh/host-capacity.json \\\n  --out ./dist/grade-refresh/preflight.json\nuv run --frozen --extra dev python scripts/grade_refresh.py fixture-repeat \\\n  --out ./dist/grade-refresh/fixture-repeatability.json\n```\n\nThe capacity receipt requires at least 5 GiB available and less than 100 percent\ncapacity in two readings at least 30 seconds apart. It is revalidated before\nDocker, MCP, or registry-database work, expires after 120 seconds, and binds the\nhost filesystem device without recording a host path. The source contract does\nnot itself prove that an operator kept Colima stopped until the receipt passed,\nor authenticate the observation against same-user replacement; provenance\nwithout a separately sealed operator binding remains `UNKNOWN`.\nOffline image qualification requires one newly observed, cohort-scoped receipt\nper invocation. The set is append-only; use the same new reviewed set name for\nall five cohorts, but never reuse a capacity receipt across cohorts:\n\n```bash\n: \"${MCP_TRUST_QUALIFICATION_RECEIPT_SET:?set a new reviewed task-owned receipt-set name}\"\nfor cohort in reference live-batch batch3 batch4 basic-memory; do\n  uv run --frozen python scripts/grade_refresh.py qualification-capacity \\\n    --operation qualification \\\n    --receipt-set \"${MCP_TRUST_QUALIFICATION_RECEIPT_SET}\" \\\n    --cohort \"$cohort\" \\\n    --out \"./dist/grade-refresh/qualification-capacity-$cohort.json\"\n  uv run --frozen python scripts/qualify_refresh_images.py \\\n    --cohort \"$cohort\" \\\n    --host-capacity \"./dist/grade-refresh/qualification-capacity-$cohort.json\" \\\n    --receipt-set \"${MCP_TRUST_QUALIFICATION_RECEIPT_SET}\"\ndone\n```\n\nThe five exact `qualification_receipt` paths in\n`src/mcp_trust/catalog/refresh_policy.json` are authoritative; a version label\nin documentation is never authority.\n\nThe qualifier creates an immutable source/input-bound set manifest and writes a\npessimistic append-only attempt intent before the first Docker mutation. It\nrevalidates the bound receipt immediately before every Docker or Buildx\nsubprocess and never renews it. If capacity expires or regresses, no\nqualification receipt is emitted and the intent remains unresolved, so Docker\nstate and qualification are `UNKNOWN`. Before retrying that cohort, issue a new\nreceipt with `--operation cleanup` and run the qualifier with\n`--cleanup-cohort \"$cohort\"`; cleanup acts only on the exact recorded tags and\noutputs and must append a successful readback receipt. Existing sets without\nthe immutable manifest, unknown artifacts, overwritten receipts, and source or\ninput drift are refused. A successful build appends a qualification completion\nbinding; cleanup completion is required only for an interrupted attempt. A\nqualification manifest preserves its originating revision as provenance but\nreopens against a qualification-specific digest map. That map includes the\nqualifier and its runtime modules, Dockerfiles, dependency inputs, locks,\nartifact descriptors, and nested source-build evidence. Generated\n`docker/refresh/qualification/` evidence and `refresh_policy.json` receipt\npointers are adoption metadata, so tracking them does not self-invalidate a\ncompleted set; dependency-bundle bytes are independently revalidated against\ntheir descriptor digests before each build, and receipt and graph integrity\nremains independently mandatory.\nAny executable or build-input drift still fails closed. A\nper-set process lock and attempt-unique temporary tag prevent concurrent\nqualification from sharing mutation state. Interruption cleanup removes only\nthe intent-recorded OCI, validation-receipt, and digest-bound tool-snapshot\nresidue. It never rewrites the final tag: readback must show either the recorded\nbaseline or the exact task-owned image ID, and any other value remains\nambiguous and blocked.\nDo not execute a catalog server unless preflight returns `READY`. The receipt\nbinds the 31-entry classification, including the exact derived 22 scannable and\n9 blocked execution boundary, source and policy digests, tool versions,\nlocal Docker authority, immutable image IDs, and explicit network, filesystem,\nresource, and secret controls. See\n[`docs/GRADE-REFRESH-PROGRAM.md`](docs/GRADE-REFRESH-PROGRAM.md) and the\n[`operator runbook`](docs/GRADE-REFRESH-OPERATOR-RUNBOOK.md).\n\nCreate a review candidate without mutating the canonical registry, baked\nsnapshot, static site, schedule, or deployment:\n\n```bash\n\"$PYTHON\" scripts/refresh_candidate.py create \\\n  --db ./registry.db \\\n  --out-dir ./dist/refresh-candidates \\\n  --qualification-receipt ./dist/grade-refresh/preflight.json\n```\n\nThe command refuses local-process scans unless the bound preflight receipt is\ncurrent and READY, and Docker and every catalog-pinned image are available\nlocally at the recorded immutable IDs. Those sources run through the existing\nnetwork-off, read-only, capability-dropped, resource-bounded sandbox. Each local\ncontainer is pre-created and the connector is bound to start only that immutable\nID; scan evidence is accepted only after the bound daemon proves it absent. A\ntimeout without that readback remains `UNKNOWN`. Remote\nendpoints are probed over their live network transport without a local process\nsandbox and are labeled accordingly. New immutable bundles use\n`RefreshCandidateV2` and contain self-digested execution-bound receipts, catalog\nidentity, scan times and ages, blocked/masked/failed/timeout/unknown evidence\nstates, attributed scan drift, an honest\nstatic snapshot, source/tool bindings, freshness counts and earliest expiry,\nsemantic projection digests, and a content-bound manifest. Legacy V1 bundles\nremain structurally inspectable but are publication-ineligible.\n\nCandidate creation has no publication or deployment authority. Structural\nverification reports schema and publication eligibility separately; a valid V1\nartifact cannot acquire V2 authority by self-assertion. A current, complete,\nreviewed-input-bound V2 candidate is only an input to later local admission.\nEligibility never grants approval, publication, deployment, rollback,\nscheduling, or outreach authority.\n\nA separately supplied `McpTrustPublicationApprovalV1` can be verified and used\nto build a deterministic local copy-only package:\n\n```bash\nuv run --frozen python scripts/build_publication_package.py \\\n  --verify-approval ./dist/publication-approval.json \\\n  --candidate ./dist/site-candidates/<name>\nuv run --frozen python scripts/build_publication_package.py --build \\\n  --candidate ./dist/site-candidates/<name> \\\n  --approval ./dist/publication-approval.json \\\n  --out ./dist/publication-packages/<name>\nuv run --frozen python scripts/build_publication_package.py \\\n  --verify-package ./dist/publication-packages/<name> \\\n  --approval ./dist/publication-approval.json\n```\n\nThis admission is provider-free and local-only. It binds the V2 candidate,\nrepeatability and triage lineage, exact V38 review, current provider evidence,\nrollback target, operator statement digest, and the minimum freshness expiry.\nEvery mutation authority remains false. A package is not deployment authority,\npublication proof, rollback authority, scheduler authority, endorsement, or\nproduction-freshness evidence.\n\nThe manual static deploy lane requires a separate short-lived\n`McpTrustProductionDeployAuthorizationV4` binding that exact package, content\napproval, provider and operator receipts, retained rollback bytes, source\nrevision, output, and tool digests. It revalidates before and after live TTY\nconfirmation. After any provider call, freshness remains `UNKNOWN` until a\nprovider/source-bound `McpTrustProductionPublicationReceiptV1` verifies the\nexact all-route readback receipt. A missing provider artifact digest can never\nbe promoted to `FRESH`.\n\nSnapshot signing is a separate authority after candidate approval/staging. The\nrefresh process never receives a signing or recovery key, and its SHA-256\nmanifest is not a publisher identity. Production signing remains disabled until\nan operator chooses the root, custody, thresholds, publication counter, and\ncheckpoint owner described in the offline trust contract.\n\n## Status\n\n**Live** at [mcp-trust.vercel.app](https://mcp-trust.vercel.app) as a statically\ngenerated catalog, regenerated from the local registry. The bundled catalog\nsnapshot contains 23 visible real `mcp-audits` grades; eight reviewed entries\nare withheld by `masked-grades.json` and are absent from the public snapshot.\nThe bundled snapshot labels the visible local-process grades' network and\nsandbox provenance as unknown; only a receipt-verified refresh candidate may\nclaim network-off execution. Every grade is labeled by provenance, so\ndemo/stub data can never read as a real scan, and an unscanned server never\nshows a letter grade. The current production deployment is the 31-server\nstatic catalog; grades are static since 2026-07-11, when the weekly re-scan\nlane was disabled and its deploy authority removed (see\n`docs/CAPABILITY-RULING-2026-07-10.md`).\n\nThe static front door is the low-ops launch path (see\n[`DEPLOY-VERCEL.md`](DEPLOY-VERCEL.md)); a weekly `launchd` job under\n[`deploy/launchd/`](deploy/launchd/) is persistently disabled and current host\nreadback shows it unloaded. A dormant installed plist remains and differs from\nthe repository template; treat it as configuration drift and do not load or\nenable it. The compatibility entrypoint can create a local review candidate\nonly, after no-execution preflight; it cannot publish or deploy. The live FastAPI\nservice + VM path remains\ndocumented in [`DEPLOY-VM.md`](DEPLOY-VM.md) as an alternative. See\n[`SPEC.md`](SPEC.md) for the full contract and [`LAUNCH-GATE.md`](LAUNCH-GATE.md)\nfor launch history. The deployed catalog reports scan timestamps as its\nfreshness authority; static HTML does not claim to attest machine-local\nscheduler state.\n\n## Contributing\n\n`uv.lock` is intentionally committed to the repository to ensure reproducible\ninstalls across environments. When adding or updating dependencies, commit the\nupdated `uv.lock` alongside your `pyproject.toml` changes.\n\n## License\n\nMIT\n",
  "bytes": 24720,
  "sha": "d09d6df83fc0c0ab0c417579f9ff07e926586df11ea1d664b25259d768920d74",
  "repo_slug": "saagpatel/mcp-trust",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_saagpatel_mcp_trust_fb141eba/readme"
}