Skip to content

mcpx doctor: slow-remote check from measured call stats (#1936) - #2597

Merged
dezren39 merged 1 commit into
mainfrom
queue/3233-1936-doctor-slow-remote
Nov 2, 2026
Merged

dezren39 merged 1 commit into
mainfrom
queue/3233-1936-doctor-slow-remote

Conversation

@dezren39

@dezren39 dezren39 commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

The #1936 best item (queue task 3233): a doctor check built from evidence mcpx already collects.

What changed

  • New internal/cli/doctor_remote.go, wired into CmdDoctor:
    • For each configured remote (url) server, aggregates the log store's per-tool call stats (logstore.Calls) into per-server figures: calls, errors, error rate, and the slowest tool's p95.
    • Gates (stated in the code, not tuned in secret): volume floor 50 calls; slow at p95 ≥ 500ms or error rate ≥ 5%. Above the floor and slow → a remote latency warning naming the server, its URL, and its measured numbers.
    • Only for a flagged server, the registry is asked (same client/settings as /v1/registry/search) whether an entry under that exact name carries an installable package; if so the fix recommends local hosting with the package (mcpx registry add <name> --write installs …). Registry failure costs the recommendation, never the report.
    • Read-only: the check builds check rows and nothing else; it never edits config.
  • Tests (doctor_remote_test.go) cover the four named cases — slow remote with a local package (recommendation fires, numbers named), slow remote without one (report only), local command server (never flagged, even with terrible stats), low-volume remote (silent below the floor) — plus the per-tool→per-server aggregation.

Tests (laptop)

go test ./internal/cli/ -run 'TestSlowRemote|TestLocalCommand|TestLowVolume|TestAggregateRemote' — all pass. Full go test ./... runs in CI.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@dezren39
dezren39 requested a review from a team as a code owner October 30, 2026 06:15
@coderabbitai

coderabbitai Bot commented Oct 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 38 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1feaa47f-a506-4801-93d7-883f3dc64664
Commits

Reviewing files that changed from the base of the PR and between efeea69 and 5125d38.

Files selected for processing: 3
  • pkgs/mcpx/internal/cli/doctor.go
  • pkgs/mcpx/internal/cli/doctor_remote.go
  • pkgs/mcpx/internal/cli/doctor_remote_test.go
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-30T06:20:42.702588Z 5125d38 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5125d38c4d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +166 to +167
if !strings.EqualFold(srv.Name, name) {
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Resolve registry identity from the configured local name

For remotes added through mcpx registry add, this comparison rejects the corresponding registry entry: registry.ToInstall derives the config key using registry.Namespace, so io.github.user/weather is configured as weather, which is also the name recorded in call statistics. Searching for weather can return the correct entry, but it will never equal the full registry name here. Consequently, normally registry-installed remotes receive no local-package recommendation even when one exists. Resolve the registry identity while accounting for namespace ambiguity, and retain its full name for the suggested command.

Useful? React with 👍 / 👎.

Comment on lines +94 to +95
fix = fmt.Sprintf("host it locally instead: `mcpx registry add %s --write` installs %s; "+
"the numbers above are what the round trip costs today", s.Name, pkg)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Select local installation in the recommended command

When a matching registry entry offers both a remote endpoint and a local package, this command does not install the advertised package. The --local flag's help in internal/cli/registry.go says “prefer an installable package over a remote”; without it, the add handler calls ToInstall(false), whose implementation selects an SSE or streamable-HTTP remote before considering packages. Include --local in the recommendation so following the local-hosting advice does not configure another remote endpoint.

Useful? React with 👍 / 👎.

Comment on lines +131 to +135
rows, err := st.Calls(logstore.Query{})
if err != nil {
return nil
}
stats := aggregateRemoteStats(rows)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Scope measured calls to the configured server instance

When two project configurations use the same server name, this query combines their histories and attributes the result to the current project's URL. daemon.Paths.ForConfig changes only the socket and info paths, leaving the default State/logs directory shared; the log store ingests all JSONL files there, and Calls groups records solely by server name and tool. Thus 50 slow calls to a local weather server in one project can produce a remote-latency warning for an entirely uncalled remote weather server in another project, bypassing the intended volume floor and reporting unrelated measurements. Associate the records with the relevant configuration/server identity before applying the thresholds.

Useful? React with 👍 / 👎.

Comment on lines +113 to +115
servers, err := cfg.ResolveAll()
if err != nil {
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Apply resolved pool settings before resolving servers

For a supported configuration such as "pool":{"sharing":"SHARED"}, this helper silently skips all remote-latency checks. The settings layer normalizes enum values case-insensitively, and both the daemon and the existing doctor configuration check call config.ApplyPoolSettings before resolving servers, so that configuration otherwise works. This helper instead reloads the raw configuration and passes the unnormalized value to ResolveAll, which rejects it and triggers the early return. Apply the resolved pool settings here as well, or reuse the configuration already resolved by CmdDoctor.

Useful? React with 👍 / 👎.

@dezren39
dezren39 merged commit 6f8f93c into main Nov 2, 2026
7 of 8 checks passed
@dezren39
dezren39 deleted the queue/3233-1936-doctor-slow-remote branch November 2, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant