Skip to content

types(mcp): type the stdio CLI end to end, from options to request bodies (#9773) - #9785

Merged
JSONbored merged 4 commits into
mainfrom
types/stdio-server-no-any-9773
Jul 29, 2026
Merged

types(mcp): type the stdio CLI end to end, from options to request bodies (#9773)#9785
JSONbored merged 4 commits into
mainfrom
types/stdio-server-no-any-9773

Conversation

@JSONbored

@JSONbored JSONbored commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Closes #9773.

The stdio CLI read every API response as any and every option as string | boolean | string[] | undefined, and picked fields out by optional-chaining guesswork. That is not a style problem — it hid three reproducible crashes and four published request schemas that disagreed with the handlers they described.

1. The option plumbing, and the three crashes it hid

TypeError: (options[key] ?? []) is not iterable
repoFullName.includes is not a function
LoopOver API 404: {"error":"not_found"}
Invocation Was
preflight --issue --issue 5 A bare repeatable flag is stored as true, and the accumulator spread it. Anything not already a list now starts a fresh one — the only sane reading of a flag carrying no value.
maintain list --repo true passed the !repoFullName truthiness guard, then died on a string method, where Pass --repo owner/repo. was intended.
decision-pack --login Read as the literal string "true", so it requested a contributor named "true" and reported them not found instead of saying the value was missing.

Options are read through optionText() now, which treats a valueless flag as absent — and every one of those call sites already had an env or profile fallback for absent. CliOptions is derived from CLI_FLAG_SPEC rather than restated, so a new flag is typed by declaring it.

2. Parameterised paths: the reason the rest stayed any

CLI_RESPONSE_SCHEMAS covered only the 24 static paths. Every per-repo and per-contributor call — /v1/repos/{owner}/{repo}/…, /v1/contributors/{login}/… — missed the typed overload and fell through to the untyped one, while the published document described most of them precisely.

The generator now resolves a composed path (${repoBase}/settings) through the base's declared template-literal type, and emits CLI_PARAMETERISED_RESPONSE_SCHEMAS keyed by "METHOD path" — method-keyed because /agent/pending-actions lists on GET and proposes on POST, and a path-keyed table had to guess between them.

  • 30 parameterised response schemas, 23 static, 10 request schemas.
  • any occurrences in the bin: 245 → 185, and the remainder is now only endpoints the document does not describe a 200 for.

3. The request bodies, and four schemas that lied

apiPost's body is typed as ApiRequestBody<"POST", Path>, so sending a field the route does not accept is a compile error rather than a 400 at runtime. Making that compile surfaced that ValidateLinkedIssueRequest, CheckBeforeStartRequest, CheckSlopRiskRequest and ValidateFocusManifestRequest were hand-written approximations of their handlers' real schemas — they are now built from those schemas directly, and openapi.json is regenerated accordingly.

The fallback overload had to be taught to refuse paths the typed overloads cover; without that it silently absorbed every call that failed the typed ones, and the new types did nothing.

4. Closed-set guards, and one more hand-maintained list

LIST.includes(value) returns a boolean and narrows nothing, so a validated <action>/<level> still reached the API as string. isOneOf is the same check as a type predicate.

The generator resolved a copied schema's constants against a hardcoded pair of contract modules — a hand-maintained list by another name, which fails silently when a constant moves between modules. It reads the contract's source directory now.

Contract gaps closed

LoopoverConfig was missing session, telemetryEnabled, and profile createdAt — all read and written by the CLI with nothing checking they existed. The legacy top-level session is still written on the default profile so an older CLI reading the same file keeps working, which is precisely why it cannot be left undeclared.

Validation

  • npx vitest run --changed=origin/main: 3729 passed, 275 files. tsc --noEmit clean at package and root level. contract:api-schemas:check and ui:openapi:check both clean.
  • The three regressions are pinned in test/unit/mcp-cli-bool-flag-parsing.test.ts and verified failing against main by checking out the pre-fix sources and re-running.
  • The generator's new behaviour is pinned in test/unit/mcp-api-client.test.ts: method disambiguation, base-path resolution, coverage, constant discovery, and the prose false-positive that an earlier cut produced.

@loopover-orb

loopover-orb Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - fixes required

Review updated: 2026-07-29 11:24:37 UTC

12 files · 1 AI reviewer · no blockers · CI failing · unstable

🛑 Suggested Action - Manual Review

Review summary
This narrows `parseOptions`'s return type from `any` to a `CliOptions` type derived from `CLI_FLAG_SPEC`, adds an `optionText()` helper that treats a bare (valueless) flag as absent rather than the literal `true`/`"true"`, and threads that through the call sites that previously read `options.repo`/`options.login`/etc. directly. The three reproduced crashes (spreading `true` as an accumulator, `.includes` on a boolean, and treating `--login` with no value as the string `"true"`) are genuinely fixed at the sites shown, and the new test file exercises each one against the real CLI dispatcher rather than a synthetic payload. One inconsistency survives the sweep: `explainReviewRiskCli` (loopover-mcp.ts) upgrades `repoFullName` to use `optionText()` but leaves `contributorLogin = options.login ?? options.contributorLogin` unwrapped, so a bare `--login` there still resolves to boolean `true` instead of falling through to the env-var fallback — the exact bug class this PR fixes everywhere else.

Nits — 6 non-blocking
  • packages/loopover-mcp/bin/loopover-mcp.ts: in explainReviewRiskCli, `const contributorLogin = options.login ?? options.contributorLogin;` (unlike the sibling `repoFullName` line two above it) is not wrapped in `optionText()`, so a bare `--login` with no value still resolves to boolean `true` rather than falling through to `options.contributorLogin`/absent — worth confirming this doesn't reproduce the same class of bug the rest of the PR fixes.
  • packages/loopover-mcp/bin/loopover-mcp.ts (slopRiskCli/lintPrTextCli/etc.): `if (options.bodyFile) prBody = readCliTextFile(optionText(options.bodyFile) ?? "", "Body")` still gates on the raw truthy value, so a bare `--body-file` (no value) enters the branch and calls `readCliTextFile("", ...)` instead of hitting a clean 'pass a path' error — the pattern applied to `--repo`/`--login` elsewhere wasn't extended to this flag.
  • Only 3 new test cases were added for a diff that rewires option-typing at ~25+ call sites; most of the `optionText()` call sites (e.g. doctor, agent packet, repo-decision) rely on existing tests still passing rather than new coverage of the bare-flag path specifically.
  • Wrap `options.login` in `optionText()` in `explainReviewRiskCli` for consistency with every other login-resolving function in this file.
  • Consider a shared guard (e.g. `if (typeof options.bodyFile !== 'string')`) instead of truthiness checks before `readCliTextFile` calls, matching the `typeof repoFullName !== "string"` pattern already used for `--repo`.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

CI checks failing

  • codecov/patch — 86.14% of diff hit (target 99.00%)

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 #9773
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low 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: 14 registered-repo PR(s), 13 merged, 357 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 14 PR(s), 357 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Linked issue satisfaction

Partially addressed
The PR description describes exactly the required changes (CliOptions derived from CLI_FLAG_SPEC, optionText() narrowing, parameterised-path typed responses, three named defects fixed), but the provided diff excerpt is entirely confined to packages/loopover-contract/src/api-schemas.ts and never shows the actual packages/loopover-mcp/bin/loopover-mcp.ts changes, so the core acceptance criteria (zer

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is registered but has no active allocation in the current snapshot.
  • Public profile languages: Python, TypeScript, Ruby, Go, MDX, Shell, Solidity, JavaScript
  • Official Gittensor activity: 14 PR(s), 357 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • 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.

Decision record
  • action: hold · clause: success
  • config: 3fd6ed08c5a4ce36096056a0441bf09716983788c9b0204dcc1ee78c50407f45 · pack: oss-anti-slop · ci: failed
  • record: 8b1d78064a862d8f1237d93df78e72cf1125fcfd58770425475553dfed6f24ae (schema v5, head 239b705)
Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before /
before /
after /
after /
/ mobile before / (mobile)
before / (mobile)
after / (mobile)
after / (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

Scroll preview
Route Before (production) After (this PR's preview)
/ before / (scroll)
before / (scroll)
after / (scroll)
after / (scroll)

A short scroll-through clip (desktop) — click either thumbnail to open the full animation. Evidence for scroll-linked behavior a single screenshot can't show.

🟩 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

@superagent-security

Copy link
Copy Markdown
Contributor

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

@JSONbored JSONbored self-assigned this Jul 29, 2026
@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 29, 2026
@JSONbored
JSONbored force-pushed the types/stdio-server-no-any-9773 branch 2 times, most recently from 4e8800a to 08eb323 Compare July 29, 2026 09:22
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 29, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
loopover-ui 239b705 Commit Preview URL

Branch Preview URL
Jul 29 2026, 10:06 AM

…s it hid (#9773)

`parseOptions` is now typed from CLI_FLAG_SPEC -- repeatable flags as arrays, boolean flags as
booleans, anything else as `string | boolean` behind an index signature, because the parser
genuinely accepts any `--flag` and a closed record would be a lie. That type flows into every
`options` parameter, every argv parameter becomes `readonly string[]`, and the config parameters
take the contract's LoopoverConfig.

Three defects fell out immediately, each reproduced against main before the fix:

  TypeError: (options[key] ?? []) is not iterable
  repoFullName.includes is not a function
  LoopOver API 404: {"error":"not_found"}

The first is `--issue --issue 5`: a bare repeatable flag is stored as `true` by the no-value
branch, and the accumulator then spread it. Anything not already a list now starts a fresh one --
the only sane reading of a flag that carried no value to keep.

The second is `maintain <sub> --repo` with no value. `true` passed the `!repoFullName` truthiness
guard and then died on a string method, where "Pass --repo owner/repo." was intended.

The third is a bare `--login`, read as the literal string "true", so `decision-pack --login`
requested a contributor NAMED "true" and reported them not found instead of saying the value was
missing. Options are read through optionText() now, which treats a valueless flag as absent -- and
every one of those call sites already had an env or profile fallback for absent.

Also: the contract's LoopoverConfig was missing `session`, `telemetryEnabled`, and profile
`createdAt`, all three read and written by the CLI with nothing checking they existed. The legacy
top-level `session` is still written on the default profile so an older CLI reading the same file
keeps working, which is exactly why it cannot be left undeclared.

277 -> 184 `: any` occurrences in the bin. The remainder is a long tail of callbacks over API
payloads that stay untyped for a structural reason worth its own issue: CLI_RESPONSE_SCHEMAS
covers only the 24 STATIC paths, so all 53 parameterised calls fall through to the untyped
overload. #9773 stays open for that.
… document (#9773)

The second tranche. #9521 built the typed accessors; its scanner rejected any template containing an
interpolation, so every per-repo and per-contributor call -- the majority of the CLI -- missed the
typed overload and read its payload as `any`. The document already described most of them.

Three things had to change for a composed call to resolve.

The path builders now DECLARE their shape. `toolRepoBase` returned `string`, which erases the path
at the type level, so `apiGet(`${toolRepoBase(o, r)}/settings`)` could never match anything; it and
the 24 locally-built bases now carry template-literal types. That is also what lets the generator's
scanner resolve them: it reads the same declarations the type checker does, so the two cannot
disagree about what a base is.

The tables are keyed by METHOD, not by path. `/v1/repos/{owner}/{repo}/agent/pending-actions` lists
on GET and proposes on POST, and those return different shapes -- a path-keyed table had to guess,
and the first version of this guessed `post`, handing the GET call site the POST response type. The
CLI's own `payload.pendingActions` read is what contradicted it, the moment a schema was attached at
all. Caught by the type checker before it shipped.

And the generated copy now carries what a copied schema REFERENCES. `closure` followed only
`*Schema` names, so a schema depending on a plain value beside it (`AGENT_ACTION_CLASS_VALUES`)
emitted a file that would not compile. Values declared in the source are copied; anything else is
imported from the contract's limits.ts, where it is restated and pinned -- and a bound missing there
fails the contract build rather than emitting something broken.

30 parameterised calls are typed now, up from 8, and the guards are in mcp-api-client.test.ts:
method disambiguation, base-path resolution, the copied-value closure, and the prose false-positive
the first cut of the constant scanner hit (it emitted imports for DELETE, REQUIRED and REST, read
out of doc comments).

Still `any` at the fallback overload, for the endpoints whose 200 the document does not describe
with a named schema. Flipping that to `unknown` leaves 72 narrowing sites, and the honest fix for
them is to describe those endpoints -- #9773 stays open for it.
…emas that lied (#9773)

A review found a contributor login being sent to the API as boolean `true` -- a bare `--login`
that my sweep had missed. The first answer was a test that grepped the source for the shape;
that is a guard against one spelling, not against the defect, so it is gone.

The defect is now a compile error. `apiPost`'s body is typed from the request schemas the
published document names, so an option value -- `string | boolean | string[]`, because a bare flag
is `true` -- cannot reach a field the API declares as a string. Verified by reverting one fix and
watching tsc say `Type 'boolean' is not assignable to type 'string'`.

Making the types BINDING mattered as much as adding them. The fallback overloads accepted
`path: string, body: unknown`, so a call that failed a typed overload did not error -- it fell
through and was accepted unchecked. They now refuse any path the typed overloads cover.

That found three more instances of the reviewer's class, each in a different command:
`lint-pr-text` sent `--body` as `true`, `check-slop-risk` sent `--description` as `true`, and
`validate-focus-manifest` sent `--source` as an unchecked free string where the API takes three
literals -- its `.includes()` guard never narrowed, so the body kept the raw value. The last is
now parsed against the contract's own enum, so the accepted values and the error naming them come
from the schema the route validates with.

And four published request schemas were wrong. ValidateLinkedIssueRequest required `owner` and
`repo` in the BODY though both are path params; CheckSlopRiskRequest required `changedFiles` the
handler has optional; ValidateFocusManifestRequest typed an enum as a free string. They were
hand-written parallels of the schemas the handlers actually parse with, and they had drifted --
so they are now built from those schemas. Rebuilt via `z.object(shape)` rather than used directly,
because `.openapi()` exists only after `extendZodWithOpenApi` and the contract must never run it.

The generator carries what a copied schema references, resolved against what each module really
exports: bounds from limits.ts, request schemas from api-requests.ts. A name in neither fails the
contract build instead of emitting a dangling reference.
…ract's modules (#9773)

Two things the merge with #9762 exposed, now that the action-class and autonomy-level lists are
readonly literal tuples rather than `string[]`:

- The CLI validated `<action>` and `<level>` with `LIST.includes(value)` and then passed the still-
  `string` value to a typed request. `includes` returns a boolean and narrows nothing, so the check
  ran and the type system learned nothing from it. `isOneOf` is the same check written as a type
  predicate, so a validated value arrives at the API as the union it was just proved to be.

- The generator resolved a copied schema's constants against a hardcoded pair of contract modules.
  That is a hand-maintained list by another name, and it fails in the quietest way available: a
  constant that moves between modules yields a generated file referencing a name it never imported.
  It now reads the contract's source directory, so a constant can move -- or a module can appear --
  without this script knowing anything about it.

Regression test pins the discovery against wherever PUBLIC_SURFACE_SKIP_REASONS lives, rather than
against the module it happens to live in today.
@JSONbored
JSONbored force-pushed the types/stdio-server-no-any-9773 branch from 5f89c79 to 239b705 Compare July 29, 2026 10:04
@JSONbored JSONbored changed the title types(mcp): type the stdio CLI's option plumbing, fixing three crashes it hid (#9773) types(mcp): type the stdio CLI end to end, from options to request bodies (#9773) Jul 29, 2026
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 503 bytes (0.01%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
loopover-ui 7.89MB 503 bytes (0.01%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: loopover-ui

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/add-scalar-classes-BLsB253y.js (New) 2.16MB 2.16MB 100.0% 🚀
assets/tanstack-vendor-DYr1q804.js (New) 928.53kB 928.53kB 100.0% 🚀
openapi.json 321 bytes 746.46kB 0.04%
assets/docs.fumadocs-spike-api-reference-CyinySx6.js (New) 443.45kB 443.45kB 100.0% 🚀
assets/AgentScalarChatInterface.vue-Ju995Di8.js (New) 201.7kB 201.7kB 100.0% 🚀
assets/modal-DpySB8Xl.js (New) 184.5kB 184.5kB 100.0% 🚀
assets/client-xK1BqAAX.js (New) 151.47kB 151.47kB 100.0% 🚀
assets/maintainer-panel-Bnnzc2aN.js (New) 78.99kB 78.99kB 100.0% 🚀
assets/routes-BcCrkmTL.js (New) 35.96kB 35.96kB 100.0% 🚀
assets/owner-panel-kTWN9uYI.js (New) 27.97kB 27.97kB 100.0% 🚀
assets/app-BG24oJ1s.js (New) 25.78kB 25.78kB 100.0% 🚀
assets/ui-vendor-BAcl6sRy.js (New) 24.57kB 24.57kB 100.0% 🚀
assets/miner-panel-BP53Hdmg.js (New) 20.24kB 20.24kB 100.0% 🚀
assets/app.runs-B9UHRfou.js (New) 20.22kB 20.22kB 100.0% 🚀
assets/api._op-C-mPQHBu.js (New) 17.57kB 17.57kB 100.0% 🚀
assets/self-hosting-docs-audit-Dhbv-yRt.js (New) 16.6kB 16.6kB 100.0% 🚀
assets/docs._slug-CrWRPsbe.js (New) 15.52kB 15.52kB 100.0% 🚀
assets/playground-panel-BS-iF84a.js (New) 14.42kB 14.42kB 100.0% 🚀
assets/fairness-De-r2RhN.js (New) 13.98kB 13.98kB 100.0% 🚀
assets/app.audit-CdL26hBg.js (New) 10.08kB 10.08kB 100.0% 🚀
assets/app.config-generator-VOt6fxUu.js (New) 10.06kB 10.06kB 100.0% 🚀
assets/maintainers-BrmYLpNZ.js (New) 8.06kB 8.06kB 100.0% 🚀
assets/miners-CJMg1YpR.js (New) 7.91kB 7.91kB 100.0% 🚀
assets/agents-CnRUS1tK.js (New) 7.74kB 7.74kB 100.0% 🚀
assets/commands-panel-C-q3yf1N.js (New) 6.65kB 6.65kB 100.0% 🚀
assets/maintainer-workflow-DzRRhSLx.js (New) 6.52kB 6.52kB 100.0% 🚀
assets/digest-panel-RA8qOpbq.js (New) 6.15kB 6.15kB 100.0% 🚀
assets/repos._owner._repo.quality-CHZ3oERC.js (New) 6.14kB 6.14kB 100.0% 🚀
assets/docs-nav-CeDlTWjA.js (New) 6.01kB 6.01kB 100.0% 🚀
assets/docs.index-COxq3iPB.js (New) 5.95kB 5.95kB 100.0% 🚀
assets/api.index-_dw2yj1t.js (New) 4.7kB 4.7kB 100.0% 🚀
assets/docs-yevxZtOO.js (New) 2.7kB 2.7kB 100.0% 🚀
assets/api-CZOcigvV.js (New) 2.69kB 2.69kB 100.0% 🚀
assets/docs-page-BnWVgn-H.js (New) 2.1kB 2.1kB 100.0% 🚀
assets/table-C202rpYz.js (New) 1.75kB 1.75kB 100.0% 🚀
assets/app.workbench-CzvVHHzq.js (New) 1.58kB 1.58kB 100.0% 🚀
assets/tabs-BzL1nm0j.js (New) 1.39kB 1.39kB 100.0% 🚀
assets/app.repos-DFAZxo4R.js (New) 1.07kB 1.07kB 100.0% 🚀
assets/input-DIUy8y0A.js (New) 796 bytes 796 bytes 100.0% 🚀
assets/file-cog-ob6qbw_4.js (New) 758 bytes 758 bytes 100.0% 🚀
assets/app.maintainer-Bj6WdjB5.js (New) 502 bytes 502 bytes 100.0% 🚀
assets/app.owner-CmUF5nVj.js (New) 474 bytes 474 bytes 100.0% 🚀
assets/app.commands-Ch4umlng.js (New) 455 bytes 455 bytes 100.0% 🚀
assets/app.playground-RG3xyBz8.js (New) 442 bytes 442 bytes 100.0% 🚀
assets/index-C0VDbrrU.js (New) 438 bytes 438 bytes 100.0% 🚀
assets/app.digest-Bb-Cy6um.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/eye-off-BcbIxCem.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/app.miner-BEmu8Pig.js (New) 422 bytes 422 bytes 100.0% 🚀
assets/key-round-C7v3KKv5.js (New) 355 bytes 355 bytes 100.0% 🚀
assets/bot-WSQa5w3J.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/trash-2-Cq7O_bM2.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/save-CX5WP4Fq.js (New) 327 bytes 327 bytes 100.0% 🚀
assets/git-pull-request-arrow-DcnCTPeM.js (New) 321 bytes 321 bytes 100.0% 🚀
assets/list-checks-Bjnq6UUK.js (New) 279 bytes 279 bytes 100.0% 🚀
assets/compass-og4HrF12.js (New) 251 bytes 251 bytes 100.0% 🚀
assets/history-Bkf8Pvvu.js (New) 237 bytes 237 bytes 100.0% 🚀
assets/message-square-DGPt0jjz.js (New) 233 bytes 233 bytes 100.0% 🚀
assets/lock-BZiTFyh-.js (New) 206 bytes 206 bytes 100.0% 🚀
assets/rotate-cw-CvGvsLZc.js (New) 201 bytes 201 bytes 100.0% 🚀
assets/play-BSYZvJl_.js (New) 190 bytes 190 bytes 100.0% 🚀
assets/circle-check-_ILHSR-1.js (New) 178 bytes 178 bytes 100.0% 🚀
assets/search-B_shjFfK.js (New) 174 bytes 174 bytes 100.0% 🚀
assets/add-scalar-classes-Co4bxscz.js (Deleted) -2.16MB 0 bytes -100.0% 🗑️
assets/tanstack-vendor-BrLkyrp7.js (Deleted) -928.35kB 0 bytes -100.0% 🗑️
assets/docs.fumadocs-spike-api-reference-DfTn6R6t.js (Deleted) -443.45kB 0 bytes -100.0% 🗑️
assets/AgentScalarChatInterface.vue-NOan_aMG.js (Deleted) -201.7kB 0 bytes -100.0% 🗑️
assets/modal-WOXR3gUX.js (Deleted) -184.5kB 0 bytes -100.0% 🗑️
assets/client-DuA7DV3N.js (Deleted) -151.47kB 0 bytes -100.0% 🗑️
assets/maintainer-panel-D2txyoLr.js (Deleted) -78.99kB 0 bytes -100.0% 🗑️
assets/routes-BUD43Duw.js (Deleted) -35.96kB 0 bytes -100.0% 🗑️
assets/owner-panel-D1grqkVY.js (Deleted) -27.97kB 0 bytes -100.0% 🗑️
assets/app-BUEzAAxm.js (Deleted) -25.78kB 0 bytes -100.0% 🗑️
assets/ui-vendor-C5Zk7cdo.js (Deleted) -24.57kB 0 bytes -100.0% 🗑️
assets/miner-panel-B9ZOgJfW.js (Deleted) -20.24kB 0 bytes -100.0% 🗑️
assets/app.runs-Ekyd81-a.js (Deleted) -20.22kB 0 bytes -100.0% 🗑️
assets/api._op-B9v07T4F.js (Deleted) -17.57kB 0 bytes -100.0% 🗑️
assets/self-hosting-docs-audit-Dl24X7Sh.js (Deleted) -16.6kB 0 bytes -100.0% 🗑️
assets/docs._slug-Laux4Rro.js (Deleted) -15.52kB 0 bytes -100.0% 🗑️
assets/playground-panel-DclhOVAD.js (Deleted) -14.42kB 0 bytes -100.0% 🗑️
assets/fairness-Biy4-HRq.js (Deleted) -13.98kB 0 bytes -100.0% 🗑️
assets/app.audit-_RqbGU90.js (Deleted) -10.08kB 0 bytes -100.0% 🗑️
assets/app.config-generator-iDSNNebO.js (Deleted) -10.06kB 0 bytes -100.0% 🗑️
assets/maintainers-C3GJwuNu.js (Deleted) -8.06kB 0 bytes -100.0% 🗑️
assets/miners-D1zyYrMj.js (Deleted) -7.91kB 0 bytes -100.0% 🗑️
assets/agents-DmTYsj0e.js (Deleted) -7.74kB 0 bytes -100.0% 🗑️
assets/commands-panel-YM6uCe0t.js (Deleted) -6.65kB 0 bytes -100.0% 🗑️
assets/maintainer-workflow-HKB2HzUv.js (Deleted) -6.52kB 0 bytes -100.0% 🗑️
assets/digest-panel-IfWFF3ds.js (Deleted) -6.15kB 0 bytes -100.0% 🗑️
assets/repos._owner._repo.quality-C2P3mODQ.js (Deleted) -6.14kB 0 bytes -100.0% 🗑️
assets/docs-nav-BZW4wpMx.js (Deleted) -6.01kB 0 bytes -100.0% 🗑️
assets/docs.index-Rcc5TwxR.js (Deleted) -5.95kB 0 bytes -100.0% 🗑️
assets/api.index-DJCuwmYz.js (Deleted) -4.7kB 0 bytes -100.0% 🗑️
assets/docs-D3CkX6Y3.js (Deleted) -2.7kB 0 bytes -100.0% 🗑️
assets/api-DGUNEAEd.js (Deleted) -2.69kB 0 bytes -100.0% 🗑️
assets/docs-page-jawKODwl.js (Deleted) -2.1kB 0 bytes -100.0% 🗑️
assets/table-BOvRRjKc.js (Deleted) -1.75kB 0 bytes -100.0% 🗑️
assets/app.workbench-BQ61iCDh.js (Deleted) -1.58kB 0 bytes -100.0% 🗑️
assets/tabs-Cr7FkTc-.js (Deleted) -1.39kB 0 bytes -100.0% 🗑️
assets/app.repos-Bb4hCDDr.js (Deleted) -1.07kB 0 bytes -100.0% 🗑️
assets/input-BeAeWi4a.js (Deleted) -796 bytes 0 bytes -100.0% 🗑️
assets/file-cog-CxWOBttH.js (Deleted) -758 bytes 0 bytes -100.0% 🗑️
assets/app.maintainer-SV2QZgE-.js (Deleted) -502 bytes 0 bytes -100.0% 🗑️
assets/app.owner-BZcFkBha.js (Deleted) -474 bytes 0 bytes -100.0% 🗑️
assets/app.commands-Cf7Jgc82.js (Deleted) -455 bytes 0 bytes -100.0% 🗑️
assets/app.playground-BtOEQUHd.js (Deleted) -442 bytes 0 bytes -100.0% 🗑️
assets/index-BzAArDB0.js (Deleted) -438 bytes 0 bytes -100.0% 🗑️
assets/app.digest-DYxtqglb.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/eye-off-BFKMYgZr.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/app.miner-OJ6QJjbG.js (Deleted) -422 bytes 0 bytes -100.0% 🗑️
assets/key-round-hI5MoUun.js (Deleted) -355 bytes 0 bytes -100.0% 🗑️
assets/bot-DbcCDqdg.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/trash-2-Cfk4PTpD.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/save-COPHD__w.js (Deleted) -327 bytes 0 bytes -100.0% 🗑️
assets/git-pull-request-arrow-BIq6V7ox.js (Deleted) -321 bytes 0 bytes -100.0% 🗑️
assets/list-checks-DKhy3zDq.js (Deleted) -279 bytes 0 bytes -100.0% 🗑️
assets/compass-D1D2dVCC.js (Deleted) -251 bytes 0 bytes -100.0% 🗑️
assets/history-C7_c8eS9.js (Deleted) -237 bytes 0 bytes -100.0% 🗑️
assets/message-square-pqmOfA5s.js (Deleted) -233 bytes 0 bytes -100.0% 🗑️
assets/lock-DYpBx3vw.js (Deleted) -206 bytes 0 bytes -100.0% 🗑️
assets/rotate-cw-BNWX5pjV.js (Deleted) -201 bytes 0 bytes -100.0% 🗑️
assets/play-UKVcci2r.js (Deleted) -190 bytes 0 bytes -100.0% 🗑️
assets/circle-check-D8Bv-iR2.js (Deleted) -178 bytes 0 bytes -100.0% 🗑️
assets/search-C71-2cOv.js (Deleted) -174 bytes 0 bytes -100.0% 🗑️

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.14458% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.34%. Comparing base (f5711a3) to head (239b705).
⚠️ Report is 6 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/loopover-mcp/bin/loopover-mcp.ts 73.86% 5 Missing and 18 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #9785   +/-   ##
=======================================
  Coverage   90.33%   90.34%           
=======================================
  Files         918      918           
  Lines      113936   114012   +76     
  Branches    26975    26979    +4     
=======================================
+ Hits       102926   103006   +80     
+ Misses       9681     9680    -1     
+ Partials     1329     1326    -3     
Flag Coverage Δ
backend 95.58% <86.14%> (+0.01%) ⬆️

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

Files with missing lines Coverage Δ
packages/loopover-contract/src/api-schemas.ts 100.00% <100.00%> (ø)
packages/loopover-contract/src/cli-config.ts 100.00% <ø> (ø)
packages/loopover-contract/src/limits.ts 100.00% <100.00%> (ø)
src/openapi/schemas.ts 100.00% <100.00%> (ø)
packages/loopover-mcp/bin/loopover-mcp.ts 67.42% <73.86%> (+0.21%) ⬆️

@JSONbored
JSONbored merged commit f01c2d4 into main Jul 29, 2026
10 of 11 checks passed
@JSONbored
JSONbored deleted the types/stdio-server-no-any-9773 branch July 29, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

types(mcp): the stdio server is TypeScript in name only — 213 : any annotations

1 participant