Skip to content

feat(mcp): REST routes + CLI resource mirrors for finding-taxonomy and enrichment-analyzers - #6709

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
dhgoal:feat/taxonomy-rest-cli
Jul 16, 2026
Merged

feat(mcp): REST routes + CLI resource mirrors for finding-taxonomy and enrichment-analyzers#6709
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
dhgoal:feat/taxonomy-rest-cli

Conversation

@dhgoal

@dhgoal dhgoal commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #6620

loopover_finding_taxonomy and loopover_enrichment_analyzers were exposed only as remote MCP resources — no REST route, no local stdio CLI mirror — unlike loopover_compatibility, which already has both. This adds them, following that resource's established pattern exactly.

  • Two unauthenticated GET routes in src/api/routes.ts, next to /v1/mcp/compatibility: GET /v1/mcp/finding-taxonomybuildFindingTaxonomyDocument(), GET /v1/mcp/enrichment-analyzersbuildEnrichmentAnalyzersTaxonomyDocument(). The builders are reused as-is (not reimplemented). Both paths are added to requiresApiToken's exclusion list, so they're public the same way /v1/mcp/compatibility is — the documents carry only committed public enums / analyzer metadata (no DB/env/private data).
  • Two server.registerResource(...) blocks in packages/loopover-mcp/bin/loopover-mcp.js after loopover_compatibility, reusing the exact URIs the remote server already registers (loopover://finding-taxonomy and the legacy gittensory://enrichment-analyzers — not new URIs), each proxying its new route via apiGet with the same { status: "unavailable" } try/catch fallback.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves (Closes #6620).

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck (type-safe by construction — see note; local root typecheck OOMs)
  • npm run test:coverage (every changed route line + branch is covered — see below)
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

If any required check was skipped, explain why:

  • Route coverage (the codecov/patch-gated surface). test/integration/api.test.ts now requests both new routes unauthenticated (empty init, no api token) and asserts each returns its builder's shape (finding-taxonomy: non-empty categories/severities; enrichment-analyzers: non-empty analyzers with name/costClass). Hitting each path unauthenticated exercises both the route handler and its new requiresApiToken(...) === false branch (the middleware calls requiresApiToken on every /v1/ request), so there is no uncovered line or branch in the route change.
  • CLI coverage. packages/loopover-mcp/bin/loopover-mcp.js is not in vitest.config.ts's coverage.include, so it isn't codecov-gated. test/unit/mcp-discovery.test.ts (which drives the real --stdio server) now asserts both new URIs are discoverable via listResources() and that reading each returns parseable JSON — the fixture doesn't serve these paths, so the read exercises the { status: "unavailable" } fallback branch, matching the compatibility resource's own test.
  • Ran green: the two route assertions (api.test.ts "serves health and OpenAPI openly"), the CLI discovery/read suite (mcp-discovery.test.ts, 21 tests), and the unchanged builder tests (mcp-finding-taxonomy + mcp-enrichment-analyzers, 4 tests) confirming no regression.
  • Typecheck. Each route is a one-liner byte-identical in shape to the adjacent /v1/mcp/compatibility route (c.json(builder())), and both builders return typed documents; the root typecheck OOMs locally but CI runs it in full.
  • No hand-curated OpenAPI entry is needed (these /v1/mcp/* routes aren't in src/openapi/spec.ts, same as /v1/mcp/compatibility). Prettier isn't a CI gate (no format script; absent from test:ci); all touched files are already non-prettier-clean on main.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized and low-noise.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests.
  • API/OpenAPI/MCP behavior is updated and tested where needed.
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks.
  • Visible UI changes include a UI Evidence section.
  • Public docs/changelogs are updated where needed.

Both routes are deliberately unauthenticated, matching the existing remote resources (neither registration has a requireRepoAccess/requireContributorAccess call) and /v1/mcp/compatibility. The documents are static, committed, public taxonomy — category/severity enums and analyzer names/cost classes — with no DB, env, or per-contributor data.

Notes

The builders (buildFindingTaxonomyDocument, buildEnrichmentAnalyzersTaxonomyDocument) and the remote MCP resources are unchanged; this only adds the missing HTTP + CLI reach, completing the same pattern loopover_compatibility already has. enrichment-analyzers intentionally keeps its legacy gittensory:// resource URI to match what the remote server registers today.

Closes #6620

…d enrichment-analyzers

The finding-taxonomy and enrichment-analyzers documents were exposed only as
remote MCP resources, with no REST route or local stdio CLI mirror — unlike
loopover_compatibility, which already has both. This adds them, following that
resource's established pattern exactly.

- Two unauthenticated GET routes in src/api/routes.ts alongside
  /v1/mcp/compatibility: /v1/mcp/finding-taxonomy returns
  buildFindingTaxonomyDocument(), /v1/mcp/enrichment-analyzers returns
  buildEnrichmentAnalyzersTaxonomyDocument() — reusing the builders as-is.
  Both are added to requiresApiToken's exclusion list, so they are public the
  same way /v1/mcp/compatibility is (the documents carry only committed public
  enums/analyzer metadata, no DB/env/private data).
- Two server.registerResource blocks in packages/loopover-mcp/bin/loopover-mcp.js
  after loopover_compatibility, reusing the exact URIs the remote server
  registers (loopover://finding-taxonomy and the legacy gittensory://enrichment-analyzers),
  each proxying its new route via apiGet with the same { status: "unavailable" }
  try/catch fallback.

Tests: unauthenticated route-level assertions of each document's shape (api.test.ts),
and stdio-server discovery + read assertions for both new resources (mcp-discovery.test.ts).

Closes JSONbored#6620
@dhgoal
dhgoal requested a review from JSONbored as a code owner July 16, 2026 19:59
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.65%. Comparing base (3acc512) to head (d66f743).
⚠️ Report is 22 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6709   +/-   ##
=======================================
  Coverage   93.65%   93.65%           
=======================================
  Files         681      682    +1     
  Lines       68098    68122   +24     
  Branches    18695    18704    +9     
=======================================
+ Hits        63775    63798   +23     
  Misses       3347     3347           
- Partials      976      977    +1     
Flag Coverage Δ
shard-1 43.89% <50.00%> (-0.01%) ⬇️
shard-2 36.93% <50.00%> (+0.08%) ⬆️
shard-3 32.46% <50.00%> (+0.07%) ⬆️
shard-4 34.65% <50.00%> (+<0.01%) ⬆️
shard-5 31.71% <50.00%> (+0.77%) ⬆️
shard-6 45.40% <100.00%> (-0.26%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/api/routes.ts 94.61% <100.00%> (+0.06%) ⬆️

... and 1 file with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 16, 2026
@loopover-orb

loopover-orb Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Warning

⏸️ LoopOver review result - manual review recommended

Review updated: 2026-07-16 20:15:43 UTC

4 files · 1 AI reviewer · no blockers · CI pending · unknown

⏸️ Suggested Action - Manual Review

Review summary
This PR adds two unauthenticated GET routes (finding-taxonomy, enrichment-analyzers) that reuse existing builder functions, exclusion-lists them in requiresApiToken, and mirrors them as CLI stdio resources using the same URIs the remote MCP server already registers, following the loopover_compatibility pattern exactly. The change is small, mechanical, and well-tested (integration test for the routes, discovery test for the resources, both asserting real payload shape rather than just status codes). It closes issue #6620 as claimed and the diff matches the description closely — no scope creep visible.

Nits — 5 non-blocking
  • src/api/routes.ts: confirm buildFindingTaxonomyDocument and buildEnrichmentAnalyzersTaxonomyDocument genuinely emit only public/static data as claimed, since these routes are unauthenticated by design.
  • packages/loopover-mcp/bin/loopover-mcp.js: the two new registerResource blocks duplicate the try/catch-fallback-to-{status:unavailable} pattern verbatim; consider extracting a small helper given three near-identical call sites (compatibility + these two) now exist.
  • test/unit/mcp-discovery.test.ts: the it.each test accepts either the real parsed document or the {status:'unavailable'} fallback as success, so it can't actually catch a broken proxy path in CI — worth asserting the real shape when the fixture server is expected to serve the route.
  • Consider adding an explicit unit test asserting the exact JSON shape returned by the CLI mirror (not just parseable JSON) to catch proxy wiring regressions.
  • Extract the repeated apiGet + try/catch + JSON.stringify pattern in loopover-mcp.js into a small shared helper to reduce duplication across the three static-document resources.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #6620
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 128 registered-repo PR(s), 75 merged, 35 issue(s).
Contributor context ✅ Confirmed Gittensor contributor dhgoal; Gittensor profile; 128 PR(s), 35 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: minor
Review context
  • Author: dhgoal
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 128 PR(s), 35 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Add a concise scope and risk note.
  • Then work through the remaining 1 step in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit b0677cd into JSONbored:main Jul 16, 2026
16 checks passed
thomasalvaedison7777-lgtm pushed a commit to thomasalvaedison7777-lgtm/loopover that referenced this pull request Jul 17, 2026
src/api/routes.ts imported buildFindingTaxonomyDocument and
buildEnrichmentAnalyzersTaxonomyDocument twice (introduced by JSONbored#6709), which
broke `tsc --noEmit` with TS2300 duplicate-identifier errors and red-CI'd
typecheck for any branch built on top of main. No behavior change -- both
route handlers using these functions are unaffected.
This was referenced Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP: add REST routes + CLI resource mirrors for finding-taxonomy and enrichment-analyzers

1 participant