Skip to content

Conversation

@AleksandrParamonoff
Copy link
Contributor

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Nov 19, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Summary by CodeRabbit

Release Notes

  • New Features

    • Inspector now runs in containerized mode with simplified port configuration.
    • Enhanced HTTP mode debugging via Docker-based inspector integration.
  • Chores

    • Build process simplified with updated entry point.
    • Improved task command structure for better automation.
    • Internal code organization and dependency management improvements.

Walkthrough

Consolidates entrypoint to cmd/main.go, reorganizes a monolithic mcpreportportal package into focused packages (analytics, middleware, mcp_handlers, utils, testutil), promotes many helpers/constants to exported utils APIs, adds a test MockCallToolRequest in internal/testutil, and updates Taskfile/Docker tasks to run a containerized inspector and build from the new entrypoint.

Changes

Cohort / File(s) Change Summary
Entrypoint & build
cmd/main.go, Dockerfile, debug.dockerfile, README.md
New cmd/main.go entrypoint added; Dockerfiles and README build commands updated to compile ./cmd/main.go.
Task automation / Inspector
Taskfile.yaml
Added public variables INSPECTOR_IMAGE/INSPECTOR_CMD; updated build targets to use cmd/main.go; docker run and inspector tasks adjusted to run inspector containerized (fixed ports, host.docker.internal), added container cleanup steps and clarified HTTP-mode port exposure.
Config / CLI orchestration
internal/config/cli.go
New AppVersion type; modularized CLI and runners (GetCommonFlags, GetHTTPFlags, GetStdioFlags, GetMCPMode, InitLogger, BuildHTTPServerConfig, NewMCPServer, HandleServerError, RunStdioServer, RunStreamingServer, RunApp) to centralize mode selection and server wiring.
Analytics package
internal/analytics/analytics.go, internal/analytics/analytics_test.go
Package renamed to analytics; added stopped int32 and idempotent Stop(); token retrieval calls use middleware.GetTokenFromContext; tests updated to import internal/middleware.
HTTP server
internal/http/http_server.go, internal/http/http_server_test.go
Package name http; HTTPServer.analytics now *analytics.Analytics; analytics initialization via analytics.NewAnalytics; tool registrations delegated to mcp_handlers; Chi middleware aliased as chimiddleware.
MCP handlers
internal/mcp_handlers/... (server.go, launches.go, items.go, tests, integration tests)
Package renamed mcp_handlers; constructors updated to accept *analytics.Analytics and project; added RegisterLaunchTools/RegisterTestItemTools; handlers refactored to use utils helpers for project extraction, pagination, response reading; tests updated to use middleware.HTTPTokenMiddleware handler and utils helpers.
Middleware
internal/middleware/... (http_token_middleware.go, middleware.go, tests)
Package renamed middleware; removed in-file project context helpers (moved to utils); introduced local context key type; token validation delegated to utils.ValidateRPToken; tests updated to use utils project/context helpers.
Utilities
internal/utils/... (utils.go, utils_test.go, utils_project_test.go, ctx_utils.go, tests)
New utils package (was mcpreportportal); many helpers/constants promoted to exported CamelCase (SetPaginationOptions, ApplyPaginationOptions, ExtractProject, ExtractResponseError, ParseTimestampToEpoch, ProcessStartTimeFilter, ProcessAttributeKeys, IsTextContent, IsAlreadyClosedError, ReadResponseBodyRaw, ReadResponseBody, FirstPage, DefaultPageSize, etc.); added RPProjectContextKey, WithProjectInContext, GetProjectFromContext; tests adapted.
Test utilities & mocks
internal/testutil/mock.go, removed internal/reportportal/mock_test.go
Added internal/testutil.MockCallToolRequest and NewMockCallToolRequest; removed legacy mock file (migrated functionality).

Sequence Diagram(s)

sequenceDiagram
    participant OS as Process (cmd/main.go)
    participant RunApp as config.RunApp
    participant CLI as CLI/Mode selector
    participant Runner as Mode runner (Stdio/HTTP)
    participant NewServer as NewMCPServer / NewServer
    participant Analytics as analytics.NewAnalytics
    participant MCP as MCP Server

    OS->>OS: create signal-aware context
    OS->>RunApp: RunApp(ctx, AppVersion)
    RunApp->>CLI: determine MCP mode
    CLI-->>Runner: call RunStdioServer or RunStreamingServer
    Runner->>NewServer: NewMCPServer(cmd, appVersion)
    NewServer->>Analytics: analytics.NewAnalytics(...) (conditional)
    Analytics-->>NewServer: analytics client or log failure
    NewServer->>MCP: register tools via RegisterLaunchTools / RegisterTestItemTools
    Runner->>MCP: start server (stdio stream or HTTP listener)
    Note right of MCP: utils and middleware used for context, token, pagination, and response helpers
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas to focus during review:

  • internal/config/cli.go — verify mode selection, flag propagation, AppVersion forwarding, and error handling.
  • Cross-package imports after package splits (analytics, middleware, mcp_handlers, utils) — ensure no missing or circular imports.
  • Consistency of exported utils APIs and renamed constants across all call sites.
  • Analytics lifecycle (initialization, Stop/cleanup) and correct usage in server startup/shutdown.
  • Test changes and new internal/testutil.MockCallToolRequest usage.

Possibly related PRs

Suggested reviewers

  • avarabyeu
  • AmsterGet

Poem

🌱 A monolith trimmed, modules in bloom,
cmd/main leads — a cleaner room.
Utils unwrapped, tests find their nook,
Inspector sails in a containerized hook.
Build, run, refactor — cheers to the prune! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.73% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive No description was provided by the author, making it impossible to assess whether it relates to the changeset. However, the substantial refactoring changes are self-evident from the file modifications and the PR title provides adequate context. Consider adding a detailed description explaining the modularization strategy, package reorganization rationale, and migration path for existing code to improve clarity for reviewers.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main purpose of the PR: a refactoring that divides the application into separate modular parts. It includes the JIRA ticket ID and is descriptive enough to convey the changeset's intent.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactoring-detach-to-modules

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 and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the application into separate packages to improve modularity and maintainability. The main changes involve moving code from a monolithic mcpreportportal package into dedicated packages: utils, middleware, mcp_handlers, analytics, http, and config.

Key changes:

  • Package name changes from mcpreportportal to specialized packages (utils, middleware, mcp_handlers, analytics, http, config)
  • Exported previously private functions/constants by capitalizing their names to enable cross-package access
  • Introduced registration functions (RegisterLaunchTools, RegisterTestItemTools) to encapsulate tool setup logic
  • Moved main application logic from internal/config/cli.go to a new cmd/main.go entry point

Reviewed Changes

Copilot reviewed 24 out of 26 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
internal/utils/*.go Changed package from mcpreportportal to utils and exported internal functions/constants
internal/middleware/*.go Changed package to middleware and moved context utilities from http_token_middleware.go to ctx_utils.go
internal/mcp_handlers/*.go Changed package to mcp_handlers, added registration functions, and updated imports
internal/http/*.go Changed package to http, renamed middleware imports, and updated to use new package structure
internal/analytics/*.go Changed package to analytics and updated imports to use middleware package
internal/config/cli.go Refactored from main package to config package, extracted functions for reusability
cmd/main.go New entry point that uses config package functions
Taskfile.yaml Updated inspector tasks for HTTP mode to use Docker networking
.gitignore Added *.exe pattern
Comments suppressed due to low confidence (1)

internal/http/http_server_test.go:264

  • Inconsistent indentation: this line and several others in this file use tabs followed by spaces. Should use consistent indentation (either tabs or spaces, not both).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (10)
internal/middleware/middleware.go (1)

3-27: Middleware correctly delegates query param extraction to utils

Moving query param lookup to utils.QueryParamsFromContext keeps the context key logic centralized and avoids duplication; the merge logic into rq.URL.Query() remains unchanged and safe. You can optionally simplify the auth branch to rely solely on GetTokenFromContext’s boolean (it already filters out empty tokens), but that’s a readability nit rather than a functional issue.

internal/analytics/analytics.go (2)

3-22: Fix gci import-formatting to satisfy the build check

The build is currently failing with a gci formatting error on this file. Please run your standard formatter (e.g. gci + goimports) over internal/analytics/analytics.go so the import groups/order match the project’s configured rules. This should clear the CI failure without changing behavior.


100-115: Make Analytics.Stop idempotent to avoid panics on repeated calls

Right now (*Analytics).Stop will panic if it’s ever called more than once because close(a.stopChan) is not guarded against multiple invocations. That’s brittle in a long-lived process where shutdown may be triggered from more than one place.

You can make Stop safely idempotent by adding a small stopped flag to the struct and guarding the shutdown with an atomic CAS:

 type Analytics struct {
 	config     *AnalyticsConfig
 	httpClient *http.Client
@@
-	// Metrics system with atomic counters
-	// Map structure: userID -> toolName -> counter
-	metrics     map[string]map[string]*int64 // userID -> (tool name -> counter)
-	metricsLock sync.RWMutex                 // protects metrics map
-
-	// Background processing
-	stopChan   chan struct{}
-	wg         sync.WaitGroup
-	tickerDone chan struct{}
+	// Metrics system with atomic counters
+	// Map structure: userID -> toolName -> counter
+	metrics     map[string]map[string]*int64 // userID -> (tool name -> counter)
+	metricsLock sync.RWMutex                 // protects metrics map
+
+	// Background processing
+	stopChan   chan struct{}
+	tickerDone chan struct{}
+	wg         sync.WaitGroup
+
+	// Ensures Stop is idempotent (safe to call multiple times)
+	stopped uint32
 }
@@
 func (a *Analytics) Stop() {
-	if a == nil || a.stopChan == nil {
+	if a == nil {
+		return
+	}
+
+	// Make Stop idempotent: only the first caller proceeds
+	if !atomic.CompareAndSwapUint32(&a.stopped, 0, 1) {
+		return
+	}
+
+	if a.stopChan == nil {
 		return
 	}

This keeps the public API the same but removes a potential panic path if shutdown is invoked more than once.

Also applies to: 367-385

internal/mcp_handlers/integration_project_test.go (1)

95-100: Rename variable to avoid shadowing the imported package.

The variable middleware shadows the imported internal/middleware package, which reduces code clarity.

Apply this diff:

 		// Apply middleware to get context with project
 		var ctx context.Context
-		middleware := middleware.HTTPTokenMiddleware(
+		handler := middleware.HTTPTokenMiddleware(
 			http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				ctx = r.Context()
 				w.WriteHeader(http.StatusOK)
 			}),
 		)

 		rr := httptest.NewRecorder()
-		middleware.ServeHTTP(rr, req)
+		handler.ServeHTTP(rr, req)
internal/mcp_handlers/items.go (1)

29-42: Consider documenting analytics nil handling.

The NewTestItemResources constructor accepts an analyticsClient *analytics.Analytics that could be nil (when analytics is disabled). While the code likely handles this through the WithAnalytics wrapper method, consider adding a comment documenting this behavior or adding a nil check if analytics is required for proper operation.

Based on learnings from the HTTP server code, analytics can be nil when disabled, and this should be properly handled.

internal/config/cli.go (3)

118-148: Harden logger initialization against bad log-level values

Right now, an invalid --log-level (or LOG_LEVEL) causes InitLogger to return an error and abort the CLI. Consider defaulting to INFO and logging a warning instead of failing the whole command; this is more user-friendly while still surfacing the misconfiguration.

For example:

 func InitLogger() func(ctx context.Context, command *cli.Command) (context.Context, error) {
   return func(ctx context.Context, command *cli.Command) (context.Context, error) {
     // Set up default logging configuration
     var logLevel slog.Level
-    if err := logLevel.UnmarshalText([]byte(command.String("log-level"))); err != nil {
-      return nil, err
-    }
+    if err := logLevel.UnmarshalText([]byte(command.String("log-level"))); err != nil {
+      slog.Warn("invalid log level, falling back to INFO", "value", command.String("log-level"), "error", err)
+      logLevel = slog.LevelInfo
+    }

150-226: Validate rp-host more strictly and consider consistent version formatting

Two small robustness improvements here:

  1. rp-host validation:
    • url.Parse(host) happily accepts values like reportportal.example.com without a scheme, which will produce a URL with empty Scheme/Host and a non-empty Path. That will likely break downstream consumers (e.g. HTTP clients expecting a proper base URL) in surprising ways.
    • Consider enforcing a scheme and host, and returning a clearer error when they’re missing:
 hostUrl, err := url.Parse(host)
 if err != nil {
   return httpserver.HTTPServerConfig{}, fmt.Errorf("invalid host URL: %w", err)
 }
+if hostUrl.Scheme == "" || hostUrl.Host == "" {
+  return httpserver.HTTPServerConfig{}, fmt.Errorf("invalid host URL %q: expected full URL like https://reportportal.example.com", host)
+}
  1. Version string consistency:
    • BuildHTTPServerConfig uses the full formatted version ("%s (%s) %s"), while NewMCPServer passes only appVersion.Version into mcp_handlers.NewServer.
    • If the commit and date are useful in stdio mode too, consider reusing the same formatted version string there for consistency across modes.

293-350: Use net.JoinHostPort to support IPv6/host formatting in HTTP mode

addr := fmt.Sprintf("%s:%d", host, port) will fail for IPv6 literals like :: (explicitly suggested in the host flag usage) and can mis-handle hosts containing colons. The idiomatic and safe approach is net.JoinHostPort, which correctly wraps IPv6 hosts in [] and formats empty hosts as :port.

Suggested change:

-import (
-  "context"
-  "errors"
-  "fmt"
-  "io"
-  "log/slog"
-  "net/http"
-  "net/url"
-  "os"
-  "runtime"
-  "strings"
-  "time"
+import (
+  "context"
+  "errors"
+  "fmt"
+  "io"
+  "log/slog"
+  "net"
+  "net/http"
+  "net/url"
+  "os"
+  "runtime"
+  "strings"
+  "time"
@@
-  // Build address from --port and --host
-  port := cmd.Int("port")
-  host := cmd.String("host")
-  addr := fmt.Sprintf("%s:%d", host, port)
+  // Build address from --port and --host (IPv4/IPv6 safe)
+  port := cmd.Int("port")
+  host := cmd.String("host")
+  addr := net.JoinHostPort(host, fmt.Sprintf("%d", port))

This fixes IPv6 binding and keeps the host flag examples valid.

internal/utils/utils.go (2)

101-127: Defensively handle nil err in ExtractResponseError

ExtractResponseError assumes err is non-nil and immediately calls err.Error(). If a nil slips through from a caller, this will panic. A small guard makes the helper safer without changing its intended behavior:

-func ExtractResponseError(err error, rs *http.Response) (errText string) {
-  errText = err.Error()
+func ExtractResponseError(err error, rs *http.Response) (errText string) {
+  if err == nil {
+    errText = "unknown error"
+  } else {
+    errText = err.Error()
+  }

You can still rely on the existing semantics while avoiding crashes from unexpected nils.


219-240: Fix IsTextContent so JSON/XML/etc. are recognized as text

The current switch only returns true for "application/csv". For values like "application/json" or "application/xml", the case bodies are empty, so control breaks out of the switch and the function returns false. That means most text-based application types are misclassified.

You can fix this by using a single case with a comma-separated list:

 func IsTextContent(mediaType string) bool {
   lowerType := strings.ToLower(mediaType)
@@
-  // Popular application types that are text-based
-  switch lowerType {
-  case "application/json":
-  case "application/xml":
-  case "application/javascript":
-  case "application/xhtml+xml":
-  case "application/yaml":
-  case "application/csv":
-    return true
-  }
+  // Popular application types that are text-based
+  switch lowerType {
+  case "application/json",
+    "application/xml",
+    "application/javascript",
+    "application/xhtml+xml",
+    "application/yaml",
+    "application/csv":
+    return true
+  }

This ensures all of the intended media types are correctly treated as text.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b21cd0 and e790a8a.

⛔ Files ignored due to path filters (1)
  • .gitignore is excluded by none and included by none
📒 Files selected for processing (24)
  • Taskfile.yaml (2 hunks)
  • cmd/main.go (1 hunks)
  • internal/analytics/analytics.go (4 hunks)
  • internal/analytics/analytics_test.go (13 hunks)
  • internal/config/cli.go (10 hunks)
  • internal/http/http_server.go (11 hunks)
  • internal/http/http_server_test.go (7 hunks)
  • internal/mcp_handlers/integration_project_test.go (4 hunks)
  • internal/mcp_handlers/items.go (27 hunks)
  • internal/mcp_handlers/items_test.go (1 hunks)
  • internal/mcp_handlers/launches.go (16 hunks)
  • internal/mcp_handlers/launches_test.go (1 hunks)
  • internal/mcp_handlers/mock_test.go (1 hunks)
  • internal/mcp_handlers/server.go (6 hunks)
  • internal/middleware/http_token_middleware.go (3 hunks)
  • internal/middleware/http_token_middleware_test.go (7 hunks)
  • internal/middleware/middleware.go (3 hunks)
  • internal/middleware/middleware_test.go (2 hunks)
  • internal/utils/ctx_utils.go (4 hunks)
  • internal/utils/ctx_utils_test.go (1 hunks)
  • internal/utils/mock_test.go (2 hunks)
  • internal/utils/utils.go (15 hunks)
  • internal/utils/utils_project_test.go (2 hunks)
  • internal/utils/utils_test.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go

⚙️ CodeRabbit configuration file

Focus on Go best practices, error handling, concurrency safety, performance, and security. Check for proper resource cleanup and context handling.

Files:

  • internal/utils/mock_test.go
  • internal/utils/utils_project_test.go
  • internal/analytics/analytics_test.go
  • internal/middleware/middleware_test.go
  • internal/middleware/http_token_middleware_test.go
  • internal/utils/utils_test.go
  • internal/utils/ctx_utils.go
  • internal/http/http_server_test.go
  • internal/mcp_handlers/mock_test.go
  • internal/mcp_handlers/server.go
  • internal/http/http_server.go
  • internal/config/cli.go
  • internal/mcp_handlers/launches.go
  • internal/mcp_handlers/launches_test.go
  • internal/mcp_handlers/items.go
  • internal/middleware/http_token_middleware.go
  • internal/mcp_handlers/items_test.go
  • cmd/main.go
  • internal/analytics/analytics.go
  • internal/mcp_handlers/integration_project_test.go
  • internal/utils/ctx_utils_test.go
  • internal/utils/utils.go
  • internal/middleware/middleware.go
**/*_test.go

⚙️ CodeRabbit configuration file

Ensure comprehensive test coverage, proper test isolation, meaningful assertions, and good test naming conventions.

Files:

  • internal/utils/mock_test.go
  • internal/utils/utils_project_test.go
  • internal/analytics/analytics_test.go
  • internal/middleware/middleware_test.go
  • internal/middleware/http_token_middleware_test.go
  • internal/utils/utils_test.go
  • internal/http/http_server_test.go
  • internal/mcp_handlers/mock_test.go
  • internal/mcp_handlers/launches_test.go
  • internal/mcp_handlers/items_test.go
  • internal/mcp_handlers/integration_project_test.go
  • internal/utils/ctx_utils_test.go
cmd/**

⚙️ CodeRabbit configuration file

Review CLI interface design, configuration handling, and application startup logic for robustness and usability.

Files:

  • cmd/main.go
🧬 Code graph analysis (16)
internal/analytics/analytics_test.go (1)
internal/middleware/http_token_middleware.go (2)
  • WithTokenInContext (92-94)
  • HTTPTokenMiddleware (22-64)
internal/middleware/middleware_test.go (1)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/middleware/http_token_middleware_test.go (1)
internal/utils/ctx_utils.go (3)
  • WithProjectInContext (35-39)
  • GetProjectFromContext (42-46)
  • RPProjectContextKey (16-16)
internal/utils/utils_test.go (1)
internal/utils/utils.go (1)
  • ProcessAttributeKeys (189-217)
internal/http/http_server_test.go (2)
internal/http/http_server.go (2)
  • HTTPServerConfig (48-60)
  • NewHTTPServer (84-142)
internal/analytics/analytics.go (2)
  • Analytics (101-114)
  • NewAnalytics (123-172)
internal/mcp_handlers/mock_test.go (2)
internal/utils/mock_test.go (2)
  • NewMockCallToolRequest (16-18)
  • MockCallToolRequest (11-13)
internal/utils/ctx_utils.go (1)
  • GetProjectFromContext (42-46)
internal/mcp_handlers/server.go (4)
internal/analytics/analytics.go (2)
  • Analytics (101-114)
  • NewAnalytics (123-172)
internal/middleware/middleware.go (1)
  • QueryParamsMiddleware (9-28)
internal/mcp_handlers/launches.go (1)
  • RegisterLaunchTools (487-502)
internal/mcp_handlers/items.go (1)
  • RegisterTestItemTools (785-800)
internal/http/http_server.go (5)
internal/analytics/analytics.go (2)
  • Analytics (101-114)
  • NewAnalytics (123-172)
internal/middleware/middleware.go (1)
  • QueryParamsMiddleware (9-28)
internal/mcp_handlers/launches.go (1)
  • RegisterLaunchTools (487-502)
internal/mcp_handlers/items.go (1)
  • RegisterTestItemTools (785-800)
internal/middleware/http_token_middleware.go (1)
  • HTTPTokenMiddleware (22-64)
internal/config/cli.go (4)
internal/http/http_server.go (2)
  • HTTPServerConfig (48-60)
  • CreateHTTPServerWithMiddleware (209-235)
internal/analytics/analytics.go (3)
  • GetAnalyticArg (328-342)
  • Analytics (101-114)
  • StopAnalytics (560-569)
internal/mcp_handlers/server.go (1)
  • NewServer (21-69)
internal/utils/ctx_utils.go (1)
  • WithProjectInContext (35-39)
internal/mcp_handlers/launches.go (3)
internal/analytics/analytics.go (1)
  • Analytics (101-114)
internal/utils/utils.go (8)
  • SetPaginationOptions (41-56)
  • DefaultSortingForLaunches (21-21)
  • ExtractProject (87-99)
  • ProcessStartTimeFilter (164-186)
  • ApplyPaginationOptions (59-84)
  • ProcessAttributeKeys (189-217)
  • ExtractResponseError (102-127)
  • ReadResponseBody (286-295)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/mcp_handlers/items.go (3)
internal/analytics/analytics.go (1)
  • Analytics (101-114)
internal/utils/utils.go (20)
  • SetPaginationOptions (41-56)
  • DefaultSortingForItems (22-22)
  • ExtractProject (87-99)
  • DefaultProviderType (25-25)
  • DefaultFilterEqHasStats (27-27)
  • DefaultFilterEqHasChildren (26-26)
  • DefaultFilterInType (28-28)
  • ProcessStartTimeFilter (164-186)
  • ApplyPaginationOptions (59-84)
  • ProcessAttributeKeys (189-217)
  • ExtractResponseError (102-127)
  • ReadResponseBody (286-295)
  • ReadResponseBodyRaw (259-281)
  • IsTextContent (220-240)
  • FirstPage (18-18)
  • DefaultPageSize (20-20)
  • DefaultSortingForLogs (24-24)
  • DefaultItemLogLevel (30-30)
  • DefaultSortingForSuites (23-23)
  • DefaultFilterInTypeSuites (29-29)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/middleware/http_token_middleware.go (1)
internal/utils/ctx_utils.go (2)
  • WithProjectInContext (35-39)
  • ValidateRPToken (50-63)
cmd/main.go (1)
internal/config/cli.go (2)
  • AppVersion (26-30)
  • RunApp (356-423)
internal/analytics/analytics.go (1)
internal/middleware/http_token_middleware.go (1)
  • GetTokenFromContext (97-100)
internal/mcp_handlers/integration_project_test.go (1)
internal/middleware/http_token_middleware.go (1)
  • HTTPTokenMiddleware (22-64)
internal/middleware/middleware.go (1)
internal/utils/ctx_utils.go (1)
  • QueryParamsFromContext (28-32)
🪛 GitHub Actions: Build
cmd/main.go

[error] 1-1: File is not properly formatted (gci).

🪛 GitHub Check: build
internal/config/cli.go

[failure] 200-200:
File is not properly formatted (gci)

cmd/main.go

[failure] 1-1:
File is not properly formatted (gci)

internal/analytics/analytics.go

[failure] 570-570:
File is not properly formatted (gci)

🪛 YAMLlint (1.37.1)
Taskfile.yaml

[error] 93-93: too many spaces inside brackets

(brackets)


[error] 93-93: too many spaces inside brackets

(brackets)


[error] 105-105: too many spaces inside brackets

(brackets)


[error] 105-105: too many spaces inside brackets

(brackets)


[error] 115-115: too many spaces inside brackets

(brackets)


[error] 115-115: too many spaces inside brackets

(brackets)

🔇 Additional comments (55)
Taskfile.yaml (2)

96-96: Verify PowerShell cleanup commands are syntactically and functionally correct.

The cleanup logic attempts to stop containers by port and image name before running new instances. However, the PowerShell pipeline on line 96 is complex:

docker ps --no-trunc | Select-String ":{{.MCP_SERVER_PORT}}->" | ForEach-Object { ($_ -split "\s+")[0] } | ForEach-Object { docker stop $_ }

A few concerns:

  1. The regex pattern :{{.MCP_SERVER_PORT}}-> assumes port mapping output format; consider whether docker ps output is guaranteed to match this pattern consistently.
  2. If the pattern doesn't match, the first pipeline command silently returns no results, causing no containers to be stopped. Error handling is implicit but not explicit.
  3. If docker stop fails (e.g., permission issues), the error propagates but may not halt the task execution depending on PowerShell's error handling mode.

Consider adding error handling or test these commands manually to ensure they work reliably across different Docker configurations. Optionally, add -ErrorAction Stop to fail fast if cleanup fails.

Also applies to: 99-99


18-19: Introduce new public variables for containerized inspector support.

The addition of INSPECTOR_IMAGE and INSPECTOR_CMD variables cleanly abstracts the Docker image and inspector command, making the setup easy to override or customize. This supports the HTTP-mode refactoring where inspector runs inside a container.

internal/middleware/middleware_test.go (1)

1-29: Query params test correctly switched to shared utils helper

Using utils.WithQueryParams here keeps the middleware test aligned with the shared context helpers in internal/utils, and the assertions still cover both preservation of existing params and addition of new ones. No changes needed.

internal/utils/ctx_utils_test.go (1)

1-111: UUID and token validation tests look solid under the utils package

Renaming the package to utils keeps the tests colocated with the production helpers, and the table-driven coverage for IsUUIDFormat and ValidateRPToken spans the right edge cases. No changes needed.

internal/utils/mock_test.go (1)

1-74: MockCallToolRequest helper cleanly models project extraction behavior

The mock request type and extractProjectWithMock helper accurately mirror the documented priority (request param, then context, then error), and moving this under the utils package keeps test scaffolding local to the utils behaviors it exercises. Looks good as-is.

internal/mcp_handlers/launches_test.go (1)

1-227: Launch MCP handler tests remain robust after package rename

The tests under mcp_handlers still exercise URI templates, list launches, and run_auto_analysis (including schema items/enum and the outgoing AnalyzeLaunchRQ) thoroughly, with correct use of httptest and mcptest lifecycles. No changes needed.

internal/utils/utils_project_test.go (1)

1-179: ExtractProject behavior is well specified and tested under utils

The move to the utils package is consistent with the underlying helpers, and the table-driven TestExtractProject thoroughly documents precedence, whitespace trimming, and error cases for HTTP vs stdio modes using the shared context APIs and mock request. No changes needed.

internal/mcp_handlers/items_test.go (1)

88-161: Make error-prefix and substring checks safer and simpler in tests

The tests cover the important JSON shapes, but two minor improvements would make them more robust and readable:

  1. Avoid slicing err.Error() by length
    Using err.Error()[:len(tt.errorMsg)] will panic if the actual message is ever shorter than tt.errorMsg. Prefer strings.HasPrefix instead:
-import (
-	"testing"
-)
+import (
+	"strings"
+	"testing"
+)
@@
-				if tt.errorMsg != "" && err.Error()[:len(tt.errorMsg)] != tt.errorMsg {
+				if tt.errorMsg != "" && !strings.HasPrefix(err.Error(), tt.errorMsg) {
  1. Simplify contains helper (optional)
    The manual substring search in contains duplicates strings.Contains. You could replace its body with a direct call:
 func contains(s, substr string) bool {
-	return len(s) >= len(substr) && (s == substr || len(substr) == 0 ||
-		func() bool {
-			for i := 0; i <= len(s)-len(substr); i++ {
-				if s[i:i+len(substr)] == substr {
-					return true
-				}
-			}
-			return false
-		}())
+	return strings.Contains(s, substr)
 }

Both changes keep behavior the same while making the tests more resilient and easier to maintain.
[ suggest_optional_refactor ]

internal/analytics/analytics.go (1)

18-22: Using middleware.GetTokenFromContext keeps analytics aligned with HTTP token handling

Switching getUserIDFromContext to use middleware.GetTokenFromContext centralizes token extraction logic in one place and keeps analytics consistent with the HTTP middleware’s context contract. The precedence (env/userID hash, then bearer token, then anonymous) remains intact, and the extra token != "" check is redundant but harmless given the helper’s current behavior.

Also applies to: 192-208

internal/mcp_handlers/integration_project_test.go (1)

1-12: LGTM! Package structure aligns with refactoring goals.

The package rename to mcp_handlers and the import of internal/middleware correctly reflect the modular architecture introduced in this PR.

internal/middleware/http_token_middleware_test.go (1)

1-274: LGTM! Excellent test refactoring.

The tests have been properly updated to use the new utils package for context handling. The test coverage is comprehensive, including:

  • Project extraction from headers
  • Context handling with whitespace
  • Middleware integration
  • Combined token and project extraction

The test structure follows Go best practices with clear test names and good use of table-driven tests.

cmd/main.go (1)

19-38: LGTM! Clean entry point with proper signal handling.

The main function correctly:

  • Sets up signal handling for graceful shutdown
  • Constructs version information
  • Delegates to config.RunApp for application logic
  • Handles errors with proper logging and exit codes

The explicit stop() call before os.Exit(1) ensures the signal context is cancelled even on error paths.

internal/http/http_server_test.go (1)

14-184: LGTM! Comprehensive test coverage.

The test suite thoroughly covers:

  • Server initialization with various token configurations
  • Analytics initialization logic
  • Default configuration values
  • Server lifecycle (start/stop)
  • Error cases

The test structure is clean and uses table-driven tests effectively.

internal/utils/utils_test.go (1)

1-172: LGTM! Excellent test coverage for exported utility function.

The tests comprehensively cover:

  • Basic attribute key processing
  • Multiple keys with various formats
  • Whitespace handling
  • Edge cases (empty strings, colons, etc.)
  • Performance testing with 1000+ keys

The function rename to ProcessAttributeKeys (exported) aligns with the modular refactoring, making this utility available to other packages.

internal/analytics/analytics_test.go (1)

1-1071: LGTM! Outstanding test coverage for analytics integration.

This test suite is exceptionally thorough, covering:

  • Token validation and hashing
  • Analytics initialization with various configurations
  • Event tracking with context integration
  • User ID precedence (env var → bearer token → custom ID → anonymous)
  • Concurrent metric increments (thread safety)
  • HTTP middleware integration
  • Edge cases and error handling

Notable strengths:

  • Proper cleanup with defer analytics.Stop()
  • Clear test names and documentation
  • Table-driven tests for maintainability
  • Verification of hash-based user identification
  • No variable shadowing issues (uses descriptive names like handler)
internal/utils/ctx_utils.go (3)

14-17: LGTM! Well-defined context key constant.

The RPProjectContextKey is properly typed as contextKey to avoid collisions, exported for cross-package use, and includes an appropriate nolint directive for the security tool.


34-46: LGTM! Robust context utilities with whitespace handling.

The context helper functions properly:

  • Trim whitespace on both storage and retrieval
  • Return false for empty strings in GetProjectFromContext
  • Follow Go conventions for context value handling

The consistent trimming prevents issues with user-provided values containing leading/trailing spaces.


48-63: LGTM! Solid token validation with UUID parsing.

The validation logic correctly:

  • Trims whitespace before validation
  • Uses proper UUID parsing via uuid.Validate
  • Falls back to length check for non-UUID tokens
  • Returns false for empty tokens

This approach handles both UUID-format tokens (preferred) and legacy token formats (16+ characters).

internal/mcp_handlers/server.go (3)

1-16: LGTM! Clean package structure with proper imports.

The package correctly imports the new modular packages (internal/analytics and internal/middleware), aligning with the PR's refactoring goals.


21-69: LGTM! Well-structured server initialization.

The refactored NewServer function demonstrates several improvements:

  • Clear separation of concerns with dedicated packages
  • Factory pattern for analytics initialization (analytics.NewAnalytics)
  • Consolidated tool registration via RegisterLaunchTools and RegisterTestItemTools
  • Proper error handling with contextual messages
  • Middleware assignment for query parameter handling

The renamed analyticsClient variable (from analytics) avoids any potential confusion with the imported package.


71-94: LGTM! Clean prompt loading with proper error handling.

The readPrompts function correctly:

  • Uses embed.FS for embedded resources
  • Handles filesystem errors
  • Uses filepath.Clean for path safety
  • Returns descriptive errors
internal/middleware/http_token_middleware.go (5)

1-10: LGTM: Clean package structure.

The package rename to middleware and the import of internal/utils align well with the modularization objectives of this refactoring.


12-19: LGTM: Proper context key typing.

Using a custom contextKey type is a Go best practice to prevent context key collisions across packages. The gosec exception is appropriately justified.


22-64: LGTM: Well-structured middleware.

The middleware correctly extracts and stores both the RP API token and project parameter in the request context, with appropriate debug logging. The use of utils.WithProjectInContext ensures consistency across the codebase.


66-89: LGTM: Centralized token validation.

Token extraction and validation is properly delegated to utils.ValidateRPToken, ensuring consistent validation logic across the application.


91-113: LGTM: Clean context helpers.

The token context helpers (WithTokenInContext, GetTokenFromContext) and project extraction function are well-implemented. The separation where token helpers remain in middleware while project helpers moved to utils reflects a logical division of responsibilities.

internal/mcp_handlers/items.go (6)

44-236: LGTM: Comprehensive utils integration.

The tool implementation correctly migrates to utils functions (ExtractProject, ProcessStartTimeFilter, WithQueryParams, ApplyPaginationOptions, ProcessAttributeKeys, ExtractResponseError, ReadResponseBody), ensuring consistency across the codebase. The analytics wrapping pattern is also properly applied.


238-268: LGTM: Clean tool implementation.

The toolGetTestItemById function follows the established pattern with proper utils integration and error handling.


270-308: LGTM: Proper resource template handling.

The resource template handler correctly validates URI parameters and handles errors appropriately. Resource handlers don't need analytics wrapping, which is correct.


310-372: LGTM: Proper attachment handling.

The attachment tool correctly handles both text and binary content types using utils.IsTextContent and appropriate encoding (base64 for binary). Error handling and resource cleanup are properly implemented.


374-782: LGTM: Consistent tool implementations.

All remaining tools (toolGetTestItemLogsByFilter, toolGetTestSuitesByFilter, toolGetProjectDefectTypes, toolUpdateDefectTypeForTestItems) follow consistent patterns with proper utils integration, error handling, and analytics wrapping. The defect type update logic correctly constructs issue definitions.


784-800: LGTM: Clean tool registration pattern.

The RegisterTestItemTools function provides a clean, centralized way to register all test item-related tools and resources. This pattern improves maintainability and makes the server initialization code cleaner.

internal/http/http_server.go (7)

1-29: LGTM: Clear import organization.

The middleware import alias (chimiddleware) effectively prevents naming conflicts with the internal middleware package. The batchSendInterval constant provides clear configuration for analytics batching.


84-142: LGTM: Proper analytics initialization.

The analytics client is correctly initialized conditionally based on configuration, with appropriate nil handling throughout. The informative logging about analytics status is helpful for debugging.


144-162: LGTM: Clean tool initialization.

The use of RegisterLaunchTools and RegisterTestItemTools provides clean, centralized tool registration. The comment about prompts being registered by the mcp_handlers package is helpful documentation. Using an empty project parameter for HTTP mode is correct since projects come from headers per-request.


172-206: LGTM: Proper lifecycle management.

The Start and Stop methods correctly manage server lifecycle with proper synchronization and nil-safe analytics handling.


208-372: LGTM: Consistent analytics client handling.

The updated function signatures (CreateHTTPServerWithMiddleware returning the analytics client, GetHTTPServerInfo accepting it as a parameter) provide better encapsulation. Nil checks for analytics are consistently applied throughout.


272-351: LGTM: Consistent middleware configuration.

All chi middleware references use the chimiddleware alias consistently. The separation between chi's built-in middleware and the internal middleware.HTTPTokenMiddleware is clear and well-structured.


374-587: LGTM: Robust request handling.

All HTTP handlers properly handle optional analytics with nil checks. The request validation logic (isMCPRequest, validateMCPPayload) correctly handles both single and batch JSON-RPC requests according to the spec. The SSE stream detection logic properly handles content negotiation per RFC 7231.

internal/mcp_handlers/launches.go (4)

1-41: LGTM: Consistent package structure.

The package structure, imports, and constructor signature are consistent with items.go, maintaining a uniform pattern across tool handlers.


43-435: LGTM: Comprehensive utils migration.

All launch tool functions (toolGetLaunches, toolRunQualityGate, toolGetLastLaunchByName, toolDeleteLaunch, toolRunAutoAnalysis, toolUniqueErrorAnalysis, toolForceFinishLaunch) correctly use utils functions for consistent project extraction, error handling, and response processing. The analytics wrapping pattern is uniformly applied.


437-484: LGTM: Proper resource template implementation.

The resourceLaunch function correctly implements the resource template pattern with proper URI parameter validation and error handling.


486-502: LGTM: Consistent tool registration pattern.

The RegisterLaunchTools function follows the same clean, centralized registration pattern as RegisterTestItemTools, improving maintainability and consistency across the codebase.

internal/config/cli.go (5)

25-116: Nice separation of common vs mode-specific flags

The split between GetCommonFlags, GetHTTPFlags, and GetStdioFlags is clear and keeps mode concerns local to their respective helpers. Flag naming, env bindings, and required/optional semantics all look consistent and will be easy to extend.


228-248: Error classification and analytics shutdown look sound

HandleServerError correctly treats nil, http.ErrServerClosed, and context cancellations/deadlines as graceful shutdowns, and centralizes analytics shutdown with an appropriate reason string. This keeps the calling code simple and avoids double‑logging normal termination paths.


250-291: Stdio runner correctly validates token and wires context

RunStdioServer does the right things: enforces that RP_API_TOKEN/--token is present, threads the optional project via utils.WithProjectInContext, and uses a buffered error channel so the listener goroutine can report failures without blocking. The shutdown path on ctx.Done() with analytics stop is also clean.


335-350: Graceful HTTP shutdown and analytics cleanup on context cancel

The shutdown path for streaming mode is well-structured: you stop analytics, then perform a bounded server.Shutdown with its own timeout, and finally stop the MCP HTTP server itself. That sequence should give in‑flight requests time to drain while keeping the process responsive to termination.


355-423: RunApp wiring is clear and mode-aware

RunApp cleanly derives mcpMode from the environment, composes the flag set based on that mode, and exposes a single cli.Command with a detailed description and usage examples. The Action switch dispatching to RunStreamingServer vs RunStdioServer is straightforward, and the default branch logging for unknown MCP_MODE is helpful for debugging misconfiguration.

internal/utils/utils.go (7)

17-56: Pagination defaults and tool options are well-structured

The exported pagination constants and SetPaginationOptions helper look good: they centralize page/page-size/sort defaults and make the MCP tool options easy to reuse across handlers. Using FirstPage and DefaultPageSize here will help keep behavior consistent between tools.


58-84: ApplyPaginationOptions clamps large values but trusts negative input

ApplyPaginationOptions correctly caps page and page-size at math.MaxInt32 before casting, which avoids overflow into the underlying API types. If you ever want to be stricter, you could also clamp or normalize non-positive values back to FirstPage / DefaultPageSize, but the current behavior (passing user-provided negatives through) is at least explicit and safe from panics.


86-99: Project extraction behavior is clear and consistent

ExtractProject prioritizes the explicit project tool argument and then falls back to the context-derived project (from headers/env via GetProjectFromContext), returning a clear error if neither is present. This is a good, predictable resolution order for multi-mode usage.


129-186: Timestamp parsing and interval filter logic look robust

ParseTimestampToEpoch sensibly tries integer Unix timestamps, RFC3339, and a few common date-time formats, and ProcessStartTimeFilter composes a validated [from,to] interval, rejecting inverted ranges or half-open intervals. The behavior is strict and should surface bad filters early.


188-217: Attribute key processing matches documented behavior

ProcessAttributeKeys correctly normalizes incoming keys by trimming whitespace, extracting postfix portions when a key:postfix form is used, and appending a : suffix otherwise before merging with existing filterAttributes. The guard rails on empty inputs keep the output predictable.


242-255: Already-closed-body detection is a useful, low-friction guard

IsAlreadyClosedError centralizes detection of common “already closed” error phrases, which keeps both logging and error-wrapping helpers from being noisy in expected shutdown paths. This is a nice bit of defensive ergonomics around HTTP body handling.


257-295: Response body helpers correctly centralize close/error handling

ReadResponseBodyRaw and ReadResponseBody enforce that the body is non-nil, always close it with a guarded defer, and provide a clean way to surface read failures as MCP tool errors. This avoids scattered defer resp.Body.Close() + error handling throughout the codebase and is a solid pattern for HTTP integration.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 28 out of 30 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

internal/http/http_server.go:160

  • The comment states "Prompts are registered by mcp_handlers package" but prompts are not actually being registered for HTTP mode. The mcp_handlers.NewServer() function registers prompts in stdio mode, but in HTTP mode, initializeTools() only calls RegisterLaunchTools() and RegisterTestItemTools() without any prompt registration. This means prompts will not be available when running the server in HTTP mode. Consider either:
  1. Creating a public RegisterPrompts() function in the mcp_handlers package and calling it here
  2. Directly calling prompt registration logic in this function similar to how it's done in mcp_handlers.NewServer()
    internal/middleware/http_token_middleware.go:13
  • The contextKey type is defined in both internal/middleware/http_token_middleware.go and internal/utils/ctx_utils.go. While Go's package scoping prevents actual collisions, having two separate contextKey type definitions in different packages can be confusing and makes the code less maintainable. Consider consolidating both type definitions into a single shared location (e.g., in internal/utils/ctx_utils.go) and importing it where needed, or use a more specific type name like middlewareContextKey to clarify the intended scope.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@AleksandrParamonoff AleksandrParamonoff force-pushed the refactoring-detach-to-modules branch from 7ccc5fa to a1ccc88 Compare November 19, 2025 14:29
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
internal/http/http_server_test.go (1)

335-361: Consider explicit analytics cleanup and avoiding panic in the test helper

Initializing analytics via analytics.NewAnalytics exercises the real setup, which is good. If NewAnalytics starts background goroutines (as its fields suggest), it’s safer for tests to explicitly stop/close the instance (e.g., via a Stop/Close method) to avoid leaking goroutines across tests. Also, instead of panicking on construction failure inside the helper, you might move the initialization into the test body and use require.NoError(t, err) so failures are reported as normal test assertions.

internal/analytics/analytics.go (1)

191-214: Minor simplification opportunity in getUserIDFromContext

middleware.GetTokenFromContext already guarantees the boolean is true only for non‑empty tokens, so the token != "" check is redundant. You can simplify without changing behavior:

-	if token, ok := middleware.GetTokenFromContext(ctx); ok && token != "" {
+	if token, ok := middleware.GetTokenFromContext(ctx); ok {
internal/mcp_handlers/server.go (1)

71-94: Fix readPrompts slice preallocation to avoid leading empty handlers

handlers := make([]promptreader.PromptHandlerPair, len(entries)) combined with handlers = append(handlers, prompts...) leaves the first len(entries) elements as zero values, so NewServer will attempt to register empty prompts before the real ones. Preallocate capacity instead of length:

-	handlers := make([]promptreader.PromptHandlerPair, len(entries))
+	handlers := make([]promptreader.PromptHandlerPair, 0, len(entries))

This keeps the returned slice free of bogus empty entries while still avoiding repeated allocations.

♻️ Duplicate comments (1)
Taskfile.yaml (1)

115-115: Fix YAML bracket spacing per linting rules.

The deps: declaration has extra spaces inside brackets, which violates YAML linting rules (as indicated by the static analysis hint). Remove the spaces for consistency with the rest of the file.

Apply this diff:

-    deps: [ docker:build-debug ]
+    deps: [docker:build-debug]
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ccc5fa and a1ccc88.

⛔ Files ignored due to path filters (1)
  • .gitignore is excluded by none and included by none
📒 Files selected for processing (28)
  • Dockerfile (1 hunks)
  • README.md (1 hunks)
  • Taskfile.yaml (3 hunks)
  • cmd/main.go (1 hunks)
  • debug.dockerfile (1 hunks)
  • internal/analytics/analytics.go (5 hunks)
  • internal/analytics/analytics_test.go (13 hunks)
  • internal/config/cli.go (9 hunks)
  • internal/http/http_server.go (11 hunks)
  • internal/http/http_server_test.go (4 hunks)
  • internal/mcp_handlers/integration_project_test.go (5 hunks)
  • internal/mcp_handlers/items.go (27 hunks)
  • internal/mcp_handlers/items_test.go (1 hunks)
  • internal/mcp_handlers/launches.go (16 hunks)
  • internal/mcp_handlers/launches_test.go (1 hunks)
  • internal/mcp_handlers/mock_test.go (1 hunks)
  • internal/mcp_handlers/server.go (5 hunks)
  • internal/middleware/http_token_middleware.go (3 hunks)
  • internal/middleware/http_token_middleware_test.go (7 hunks)
  • internal/middleware/middleware.go (2 hunks)
  • internal/middleware/middleware_test.go (2 hunks)
  • internal/testutil/mock.go (1 hunks)
  • internal/utils/ctx_utils.go (3 hunks)
  • internal/utils/ctx_utils_test.go (1 hunks)
  • internal/utils/mock_test.go (1 hunks)
  • internal/utils/utils.go (14 hunks)
  • internal/utils/utils_project_test.go (2 hunks)
  • internal/utils/utils_test.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go

⚙️ CodeRabbit configuration file

Focus on Go best practices, error handling, concurrency safety, performance, and security. Check for proper resource cleanup and context handling.

Files:

  • cmd/main.go
  • internal/mcp_handlers/items_test.go
  • internal/utils/mock_test.go
  • internal/testutil/mock.go
  • internal/middleware/http_token_middleware_test.go
  • internal/utils/utils_project_test.go
  • internal/middleware/middleware.go
  • internal/analytics/analytics.go
  • internal/middleware/middleware_test.go
  • internal/analytics/analytics_test.go
  • internal/utils/ctx_utils_test.go
  • internal/utils/utils_test.go
  • internal/mcp_handlers/server.go
  • internal/mcp_handlers/items.go
  • internal/mcp_handlers/launches.go
  • internal/middleware/http_token_middleware.go
  • internal/http/http_server_test.go
  • internal/config/cli.go
  • internal/mcp_handlers/mock_test.go
  • internal/mcp_handlers/launches_test.go
  • internal/utils/ctx_utils.go
  • internal/http/http_server.go
  • internal/mcp_handlers/integration_project_test.go
  • internal/utils/utils.go
cmd/**

⚙️ CodeRabbit configuration file

Review CLI interface design, configuration handling, and application startup logic for robustness and usability.

Files:

  • cmd/main.go
**/*_test.go

⚙️ CodeRabbit configuration file

Ensure comprehensive test coverage, proper test isolation, meaningful assertions, and good test naming conventions.

Files:

  • internal/mcp_handlers/items_test.go
  • internal/utils/mock_test.go
  • internal/middleware/http_token_middleware_test.go
  • internal/utils/utils_project_test.go
  • internal/middleware/middleware_test.go
  • internal/analytics/analytics_test.go
  • internal/utils/ctx_utils_test.go
  • internal/utils/utils_test.go
  • internal/http/http_server_test.go
  • internal/mcp_handlers/mock_test.go
  • internal/mcp_handlers/launches_test.go
  • internal/mcp_handlers/integration_project_test.go
**/Dockerfile*

⚙️ CodeRabbit configuration file

Focus on security best practices, image size optimization, proper layering, and multi-stage builds where appropriate.

Files:

  • Dockerfile
🧬 Code graph analysis (18)
cmd/main.go (1)
internal/config/cli.go (2)
  • AppVersion (26-30)
  • RunApp (356-423)
internal/utils/mock_test.go (2)
internal/testutil/mock.go (1)
  • MockCallToolRequest (8-10)
internal/utils/ctx_utils.go (1)
  • GetProjectFromContext (42-46)
internal/middleware/http_token_middleware_test.go (1)
internal/utils/ctx_utils.go (3)
  • WithProjectInContext (35-39)
  • GetProjectFromContext (42-46)
  • RPProjectContextKey (16-16)
internal/utils/utils_project_test.go (1)
internal/testutil/mock.go (1)
  • NewMockCallToolRequest (13-15)
internal/middleware/middleware.go (1)
internal/utils/ctx_utils.go (1)
  • QueryParamsFromContext (28-32)
internal/analytics/analytics.go (1)
internal/middleware/http_token_middleware.go (1)
  • GetTokenFromContext (97-100)
internal/middleware/middleware_test.go (1)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/analytics/analytics_test.go (1)
internal/middleware/http_token_middleware.go (2)
  • WithTokenInContext (92-94)
  • HTTPTokenMiddleware (22-64)
internal/utils/utils_test.go (1)
internal/utils/utils.go (1)
  • ProcessAttributeKeys (189-217)
internal/mcp_handlers/server.go (4)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/middleware/middleware.go (1)
  • QueryParamsMiddleware (9-28)
internal/mcp_handlers/launches.go (1)
  • RegisterLaunchTools (498-513)
internal/mcp_handlers/items.go (1)
  • RegisterTestItemTools (803-818)
internal/mcp_handlers/items.go (3)
internal/analytics/analytics.go (1)
  • Analytics (101-115)
internal/utils/utils.go (20)
  • SetPaginationOptions (41-56)
  • DefaultSortingForItems (22-22)
  • ExtractProject (87-99)
  • DefaultProviderType (25-25)
  • DefaultFilterEqHasStats (27-27)
  • DefaultFilterEqHasChildren (26-26)
  • DefaultFilterInType (28-28)
  • ProcessStartTimeFilter (164-186)
  • ApplyPaginationOptions (59-84)
  • ProcessAttributeKeys (189-217)
  • ExtractResponseError (102-127)
  • ReadResponseBody (286-295)
  • ReadResponseBodyRaw (259-281)
  • IsTextContent (220-240)
  • FirstPage (18-18)
  • DefaultPageSize (20-20)
  • DefaultSortingForLogs (24-24)
  • DefaultItemLogLevel (30-30)
  • DefaultSortingForSuites (23-23)
  • DefaultFilterInTypeSuites (29-29)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/mcp_handlers/launches.go (3)
internal/analytics/analytics.go (1)
  • Analytics (101-115)
internal/utils/utils.go (8)
  • SetPaginationOptions (41-56)
  • DefaultSortingForLaunches (21-21)
  • ExtractProject (87-99)
  • ProcessStartTimeFilter (164-186)
  • ApplyPaginationOptions (59-84)
  • ProcessAttributeKeys (189-217)
  • ExtractResponseError (102-127)
  • ReadResponseBody (286-295)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/middleware/http_token_middleware.go (1)
internal/utils/ctx_utils.go (2)
  • WithProjectInContext (35-39)
  • ValidateRPToken (50-63)
internal/http/http_server_test.go (1)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/config/cli.go (4)
internal/http/http_server.go (2)
  • HTTPServerConfig (48-60)
  • CreateHTTPServerWithMiddleware (209-235)
internal/analytics/analytics.go (3)
  • GetAnalyticArg (329-343)
  • Analytics (101-115)
  • StopAnalytics (569-578)
internal/mcp_handlers/server.go (1)
  • NewServer (21-69)
internal/utils/ctx_utils.go (1)
  • WithProjectInContext (35-39)
internal/mcp_handlers/mock_test.go (2)
internal/testutil/mock.go (1)
  • MockCallToolRequest (8-10)
internal/utils/ctx_utils.go (1)
  • GetProjectFromContext (42-46)
internal/http/http_server.go (5)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/middleware/middleware.go (1)
  • QueryParamsMiddleware (9-28)
internal/mcp_handlers/launches.go (1)
  • RegisterLaunchTools (498-513)
internal/mcp_handlers/items.go (1)
  • RegisterTestItemTools (803-818)
internal/middleware/http_token_middleware.go (1)
  • HTTPTokenMiddleware (22-64)
internal/mcp_handlers/integration_project_test.go (2)
internal/testutil/mock.go (1)
  • NewMockCallToolRequest (13-15)
internal/middleware/http_token_middleware.go (1)
  • HTTPTokenMiddleware (22-64)
🪛 YAMLlint (1.37.1)
Taskfile.yaml

[error] 115-115: too many spaces inside brackets

(brackets)


[error] 115-115: too many spaces inside brackets

(brackets)

🔇 Additional comments (42)
internal/utils/utils_project_test.go (1)

7-9: Centralizing mock construction via testutil.NewMockCallToolRequest looks good

Using the shared helper keeps tests consistent with other packages and avoids duplicating mock setup; the new call site and import are correct and type-safe.

Also applies to: 165-169

internal/utils/ctx_utils_test.go (1)

1-111: Tests correctly validate UUID and token handling under the new utils package

Package alignment is correct, and the existing cases give good coverage of happy paths and edge conditions for both IsUUIDFormat and ValidateRPToken.

internal/testutil/mock.go (1)

7-32: MockCallToolRequest test helper is cohesive and matches its use

The dedicated constructor and minimal method set give a clear, reusable test double for call tool requests without leaking production concerns into tests.

internal/utils/ctx_utils.go (1)

14-46: Context helpers and RP token validation follow solid, predictable semantics

Using a dedicated contextKey type and RPProjectContextKey avoids collisions, and trimming in both WithProjectInContext and GetProjectFromContext ensures whitespace-only values are treated as “no project”. ValidateRPToken’s combination of UUID check plus minimum-length fallback is simple, efficient, and well covered by the accompanying tests.

Also applies to: 48-63

Dockerfile (1)

17-19: Docker build now correctly targets the new cmd/main.go entrypoint

Switching the build target to cmd/main.go while preserving the existing binary name and ldflags keeps the container behavior intact and consistent with the new application layout.

README.md (1)

383-385: Build instructions now match the new cmd/main.go entrypoint

Updating the example to go build -o reportportal-mcp-server ./cmd/main.go keeps the README aligned with the Dockerfile and the refactored command layout.

debug.dockerfile (1)

20-20: LGTM - Build path updated correctly.

The build output path has been properly updated to use the new cmd/main.go entrypoint, aligning with the modular refactoring objectives of this PR.

internal/mcp_handlers/launches_test.go (2)

1-1: LGTM - Package rename aligns with refactoring.

The package rename from mcpreportportal to mcp_handlers is consistent with the PR's objective to modularize the codebase.


46-46: No action needed—nil analytics handling is already safely implemented.

The WithAnalytics method in internal/analytics/analytics.go includes an explicit nil receiver check (if a != nil { a.TrackMCPEvent(...) }) that safely handles nil analytics clients. The codebase has a dedicated test TestWithAnalyticsNilAnalytics that verifies this behavior, and both test cases in launches_test.go intentionally pass nil analytics, then execute the tools to confirm nil handling works end-to-end. This is intentional Go design—no nil pointer dereference risk exists.

Likely an incorrect or invalid review comment.

internal/mcp_handlers/items_test.go (1)

1-1: LGTM - Package rename and test coverage.

The package rename to mcp_handlers is consistent with the refactoring effort. The test suite provides comprehensive coverage for the getDefectTypesFromJson function, including edge cases and error scenarios.

internal/middleware/middleware_test.go (2)

1-1: LGTM - Package rename consistent.

The package rename to middleware aligns with the modular restructuring objectives.


10-10: LGTM - Proper use of utils package.

The import of internal/utils and subsequent use of utils.WithQueryParams correctly reflects the refactored utility location.

cmd/main.go (2)

13-17: LGTM - Build-time version variables.

The version variables are properly declared for ldflags injection during the build process, aligning with the build configuration in the Dockerfiles and Taskfile.


19-38: LGTM - Robust signal-aware main implementation.

The main function demonstrates Go best practices:

  • Proper signal handling with signal.NotifyContext for graceful shutdown on OS interrupts and SIGTERM
  • Deferred stop() ensures cleanup under normal flow
  • Explicit stop() call before os.Exit(1) prevents context leak on error paths
  • Structured logging with slog for error reporting
internal/middleware/http_token_middleware_test.go (3)

1-1: LGTM - Package rename consistent.

The package rename to middleware is consistent with the broader refactoring effort.


11-11: LGTM - Proper migration to utils package.

The import of internal/utils and subsequent migration of all context helper calls (WithProjectInContext, GetProjectFromContext, RPProjectContextKey) to the utils package properly centralizes these utilities and eliminates duplication.


75-90: LGTM - Comprehensive context helper tests.

The tests thoroughly verify context operations with proper assertions for both positive and negative cases.

internal/mcp_handlers/mock_test.go (1)

13-25: LGTM - Test helper implementation.

The extractProjectWithMock function correctly implements the priority order for project extraction (request parameter → context → error). The past review comments regarding duplication with internal/utils/mock_test.go were already addressed in commit eae13d0.

internal/utils/utils_test.go (2)

1-1: LGTM - Package rename and API export.

The package rename to utils and the corresponding update to test the now-exported ProcessAttributeKeys function align with Go conventions for public APIs and the broader refactoring effort.


8-147: LGTM - Comprehensive test coverage.

The test suite for ProcessAttributeKeys demonstrates excellent coverage:

  • Basic cases and edge cases
  • Whitespace handling
  • Multiple keys and mixed scenarios
  • Complex real-world scenarios
  • Performance testing with large inputs
internal/middleware/middleware.go (1)

3-7: Centralizing query param extraction via utils.QueryParamsFromContext looks good

Using utils.QueryParamsFromContext keeps context handling in one place and the middleware logic remains straightforward and side‑effect free beyond mutating the request URL, which is appropriate here.

Also applies to: 17-27

internal/analytics/analytics_test.go (2)

525-615: Good alignment between analytics tests and middleware token context behavior

Switching to middleware.WithTokenInContext in analytics tests keeps token propagation consistent with production behavior and avoids duplicated helpers. The various scenarios around env token, bearer token, and anonymous mode are clearly expressed and remain isolated per test instance.

Also applies to: 617-722, 724-887, 889-958


960-1071: HTTP middleware integration tests correctly exercise real middleware

Using middleware.HTTPTokenMiddleware with the httpHandler variable in TestHTTPTokenMiddlewareIntegrationWithAnalytics avoids package shadowing and ensures the tests run through the real HTTP middleware stack, which is exactly what you want to validate end‑to‑end behavior.

internal/analytics/analytics.go (1)

100-115: Idempotent Stop implementation with atomic flag and channels is solid

Adding the stopped int32 flag and guarding Stop with atomic.CompareAndSwapInt32 ensures the shutdown sequence (closing stopChan, waiting on tickerDone, then wg.Wait) runs exactly once, even if multiple goroutines call Stop concurrently or tests call it repeatedly. This removes the risk of double‑close panics while keeping the background processor shutdown clean.

Also applies to: 368-395

internal/mcp_handlers/server.go (1)

21-69: Server wiring for analytics and middleware is coherent

Returning (*server.MCPServer, *analytics.Analytics, error) from NewServer and wiring rpClient.APIClient.GetConfig().Middleware = middleware.QueryParamsMiddleware makes the dependencies explicit and allows the caller to control analytics lifecycle (e.g., deferred stop). Tool registration via RegisterLaunchTools and RegisterTestItemTools keeps this constructor focused on composition rather than per‑tool details.

internal/mcp_handlers/integration_project_test.go (2)

81-115: Integration test cleanly composes HTTP middleware with mock MCP request

TestIntegration_ProjectExtractionFlow now uses testutil.NewMockCallToolRequest plus middleware.HTTPTokenMiddleware to build the context, which keeps the test aligned with the real request path and removes duplicate mock construction. Capturing ctx from the wrapped handler and feeding it into extractProjectWithMock accurately exercises the header vs. request‑project precedence logic.


117-155: End‑to‑end HTTP flow test uses middleware without package shadowing

In TestIntegration_CompleteHTTPFlow, introducing the httpHandler := middleware.HTTPTokenMiddleware(handler) variable avoids shadowing the middleware package and makes the request execution (httpHandler.ServeHTTP) straightforward to read. Using testutil.NewMockCallToolRequest keeps the project parameter setup centralized and ensures the test reflects actual tool request shape.

internal/middleware/http_token_middleware.go (1)

12-19: LGTM! Proper context key type safety.

The introduction of a local contextKey type is a Go best practice that prevents context key collisions. The delegation to utils.WithProjectInContext and utils.ValidateRPToken is consistent with the refactoring goals and improves code organization.

internal/http/http_server.go (2)

109-124: LGTM! Clean analytics initialization with proper error handling.

The analytics client initialization properly handles the HTTP mode constraint (empty FallbackRPToken) and includes appropriate error handling and logging. The use of *analytics.Analytics as a parameter aligns well with the refactoring goals.


155-158: LGTM! Proper delegation of tool registration.

The tool registration is now cleanly delegated to mcp_handlers.RegisterLaunchTools and mcp_handlers.RegisterTestItemTools, which improves modularity and separation of concerns. The empty project parameter is appropriate for HTTP mode where projects come from request headers.

internal/mcp_handlers/launches.go (2)

497-513: LGTM! Clean tool registration pattern.

The new RegisterLaunchTools function provides a clean, centralized way to register all launch-related tools and resources. This improves maintainability and makes the server initialization code more readable.


52-52: LGTM! Consistent use of utils package constants.

The migration to utils.SetPaginationOptions(utils.DefaultSortingForLaunches) is consistent across all tool definitions and improves code organization by centralizing pagination logic.

internal/mcp_handlers/items.go (2)

802-818: LGTM! Consistent tool registration pattern.

The RegisterTestItemTools function follows the same clean pattern as RegisterLaunchTools, providing centralized registration of all test item-related tools and resources. This consistency improves maintainability across the codebase.


156-160: LGTM! Proper use of exported utils constants.

The use of exported constants like utils.DefaultProviderType, utils.DefaultFilterEqHasStats, etc., centralizes default values and makes them easily discoverable and maintainable.

internal/config/cli.go (4)

160-160: LGTM! Analytics secret properly retrieved.

The call to analytics.GetAnalyticArg() properly retrieves the analytics API secret. This is consistent with the analytics initialization pattern used throughout the codebase.


228-248: LGTM! Robust error handling with proper analytics cleanup.

The HandleServerError function properly distinguishes between graceful shutdowns and actual errors, ensuring analytics is stopped in both cases. The use of errors.Is for error checking is correct and follows Go best practices.


340-347: LGTM! Proper graceful shutdown with timeout.

The shutdown logic properly uses a separate context with a 5-second timeout to ensure the server stops gracefully. The defer cancel pattern and sequential shutdown of both the HTTP server and MCP components follow best practices.


355-423: LGTM! Clean mode-based server dispatch.

The RunApp function provides a clean entry point that dynamically builds flags based on MCP_MODE and dispatches to the appropriate server function. The help text is comprehensive and clearly documents the differences between modes.

internal/utils/utils.go (4)

17-31: LGTM! Proper export of public constants.

The renaming of constants from camelCase to PascalCase correctly exposes them as part of the public API. The naming is descriptive and follows Go conventions.


59-84: LGTM! Type-safe generic pagination function.

The use of generics for ApplyPaginationOptions provides type safety while avoiding code duplication. The overflow checks for math.MaxInt32 are appropriate for the int32 API constraints.


244-255: LGTM! Defensive error checking prevents log spam.

The IsAlreadyClosedError helper is a good defensive pattern that prevents unnecessary error logging when response bodies are already closed. This is a common issue in HTTP client code and the checks cover the main error message patterns.


259-281: LGTM! Proper resource cleanup with defensive error handling.

The ReadResponseBodyRaw function properly handles response body cleanup with defer, and uses IsAlreadyClosedError to avoid spurious error logs. This is a solid implementation of the cleanup pattern.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 27 out of 29 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

internal/middleware/http_token_middleware.go:13

  • The contextKey type is duplicated in both internal/middleware/http_token_middleware.go (line 13) and internal/utils/ctx_utils.go (line 12). While this doesn't cause a compilation error since they're in different packages, it's redundant and could lead to confusion.

Consider consolidating this type definition into one location (e.g., in internal/utils/ctx_utils.go) and removing it from the middleware package. The middleware package can then simply use the string type directly for its context keys, or import the type from utils if needed.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
internal/mcp_handlers/items_test.go (1)

152-162: Use strings.Contains from the standard library.

This custom implementation unnecessarily reimplements the standard library's strings.Contains function with added complexity. The standard library version is clearer, more efficient, and well-tested.

Apply this diff:

+import (
+	"strings"
+	"testing"
+)
+
 func TestGetDefectTypesFromJson_VerifyContent(t *testing.T) {
 	// ...
 	expectedStrings := []string{"NO_DEFECT", "locator", "nd001"}
 	for _, expected := range expectedStrings {
-		if !contains(result, expected) {
+		if !strings.Contains(result, expected) {
 			t.Errorf("result should contain %q, got: %s", expected, result)
 		}
 	}
 }
-
-// Helper function to check if a string contains a substring
-func contains(s, substr string) bool {
-	return len(s) >= len(substr) && (s == substr || len(substr) == 0 ||
-		func() bool {
-			for i := 0; i <= len(s)-len(substr); i++ {
-				if s[i:i+len(substr)] == substr {
-					return true
-				}
-			}
-			return false
-		}())
-}
internal/http/http_server_test.go (1)

335-361: Tighten analytics test setup and cleanup

Using analytics.NewAnalytics here is fine, but a couple of small improvements would make the test more robust:

  • Prefer require.NoError(t, err) over panic(err) so failures are reported as proper test failures rather than panics.
  • Since NewAnalytics starts background processing, consider stopping it via defer analyticsInstance.Stop() or t.Cleanup(analyticsInstance.Stop) to avoid leaking goroutines across tests.

These keep the test behavior clear and isolated while still exercising the real analytics client.

internal/mcp_handlers/server.go (1)

71-93: Fix slice preallocation bug in readPrompts to avoid empty prompt registrations

readPrompts currently does:

handlers := make([]promptreader.PromptHandlerPair, len(entries))
for _, entry := range entries {
    ...
    prompts, err := promptreader.LoadPromptsFromYAML(data)
    ...
    handlers = append(handlers, prompts...)
}

This creates a slice with len(entries) zero-valued elements, then appends all loaded prompts. When you later iterate over prompts in NewServer, the first len(entries) entries will have empty names/handlers, which can lead to invalid prompt registrations.

Adjust to start with length 0 and only append real prompts:

-func readPrompts(files embed.FS, dir string) ([]promptreader.PromptHandlerPair, error) {
+func readPrompts(files embed.FS, dir string) ([]promptreader.PromptHandlerPair, error) {
@@
-	handlers := make([]promptreader.PromptHandlerPair, len(entries))
+	// Start with an empty slice; preallocate capacity if desired
+	handlers := make([]promptreader.PromptHandlerPair, 0, len(entries))
@@
-		handlers = append(handlers, prompts...)
+		handlers = append(handlers, prompts...)
@@
-	return handlers, nil
+	return handlers, nil
 }

This ensures only valid prompt definitions are returned and registered.

internal/http/http_server.go (1)

237-248: Clarify or populate AnalyticsEnabled vs nested Analytics.Enabled

HTTPServerInfo exposes both a top-level AnalyticsEnabled and a nested Analytics.Enabled, but only the nested field is actively set:

type HTTPServerInfo struct {
    ...
    AnalyticsEnabled      bool          `json:"analytics_enabled"`
    ...
    Analytics             AnalyticsInfo `json:"analytics"`
}
...
func GetHTTPServerInfo(analyticsClient *analytics.Analytics) HTTPServerInfo {
    ...
    if analyticsClient != nil {
        info.Analytics = AnalyticsInfo{Enabled: true, Type: "batch", Interval: batchSendInterval.String()}
    } else {
        info.Analytics = AnalyticsInfo{Enabled: false}
    }
}

and later:

info.Analytics.Enabled = hs.analytics != nil

The top-level AnalyticsEnabled remains its zero value, which can be misleading for clients reading the JSON.

Consider either:

  • Populating AnalyticsEnabled (e.g., info.AnalyticsEnabled = hs.analytics != nil), or
  • Removing it and relying solely on info.Analytics.Enabled to avoid redundant/confusing fields.

This will make the /info and /metrics responses more self-consistent.

Also applies to: 353-372, 413-425

internal/mcp_handlers/launches.go (1)

21-41: Guard lr.analytics to avoid panics when analytics is disabled

LaunchResources.analytics is a *analytics.Analytics that can legitimately be nil when analytics is turned off or initialization fails. All tools currently wrap handlers with:

return mcp.NewTool("...", options...),
    lr.analytics.WithAnalytics("tool_name", func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        ...
    })

If analyticsClient is nil (as passed from NewServer / HTTP server), calling a method on a nil receiver will panic unless WithAnalytics is explicitly written to handle a nil receiver internally.

To make this robust regardless of WithAnalytics’s implementation, consider a small helper on LaunchResources:

func (lr *LaunchResources) wrapWithAnalytics(
    toolName string,
    handler server.ToolHandlerFunc,
) server.ToolHandlerFunc {
    if lr.analytics == nil {
        return handler
    }
    return lr.analytics.WithAnalytics(toolName, handler)
}

and then use it across tools:

-), lr.analytics.WithAnalytics("get_launches", func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
+), lr.wrapWithAnalytics("get_launches", func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {

Apply the same pattern to the other tool constructors (run_quality_gate, get_last_launch_by_name, launch_delete, run_auto_analysis, run_unique_error_analysis, launch_force_finish).

This keeps analytics purely optional without risking runtime panics when it’s disabled.

Also applies to: 43-45, 97-100, 167-176, 200-213, 259-268, 290-328, 371-387, 415-425

♻️ Duplicate comments (1)
Taskfile.yaml (1)

113-116: Fix remaining YAML bracket spacing for linter compliance

deps at Line 115 still has extra spaces inside the brackets, which YAMLlint flags.

Apply this minimal fix:

-    deps: [ docker:build-debug ]
+    deps: [docker:build-debug]

This aligns with the previous lint feedback and removes the remaining brackets warning.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1ccc88 and dcde972.

⛔ Files ignored due to path filters (1)
  • .gitignore is excluded by none and included by none
📒 Files selected for processing (27)
  • Dockerfile (1 hunks)
  • README.md (1 hunks)
  • Taskfile.yaml (3 hunks)
  • cmd/main.go (1 hunks)
  • debug.dockerfile (1 hunks)
  • internal/analytics/analytics.go (5 hunks)
  • internal/analytics/analytics_test.go (13 hunks)
  • internal/config/cli.go (9 hunks)
  • internal/http/http_server.go (11 hunks)
  • internal/http/http_server_test.go (4 hunks)
  • internal/mcp_handlers/integration_project_test.go (4 hunks)
  • internal/mcp_handlers/items.go (27 hunks)
  • internal/mcp_handlers/items_test.go (1 hunks)
  • internal/mcp_handlers/launches.go (16 hunks)
  • internal/mcp_handlers/launches_test.go (1 hunks)
  • internal/mcp_handlers/server.go (5 hunks)
  • internal/middleware/http_token_middleware.go (3 hunks)
  • internal/middleware/http_token_middleware_test.go (7 hunks)
  • internal/middleware/middleware.go (2 hunks)
  • internal/middleware/middleware_test.go (2 hunks)
  • internal/reportportal/mock_test.go (0 hunks)
  • internal/testutil/mock.go (1 hunks)
  • internal/utils/ctx_utils.go (3 hunks)
  • internal/utils/ctx_utils_test.go (1 hunks)
  • internal/utils/utils.go (14 hunks)
  • internal/utils/utils_project_test.go (2 hunks)
  • internal/utils/utils_test.go (4 hunks)
💤 Files with no reviewable changes (1)
  • internal/reportportal/mock_test.go
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go

⚙️ CodeRabbit configuration file

Focus on Go best practices, error handling, concurrency safety, performance, and security. Check for proper resource cleanup and context handling.

Files:

  • internal/utils/ctx_utils_test.go
  • internal/mcp_handlers/launches_test.go
  • internal/utils/ctx_utils.go
  • internal/analytics/analytics_test.go
  • internal/middleware/middleware.go
  • internal/utils/utils_project_test.go
  • internal/http/http_server_test.go
  • internal/mcp_handlers/launches.go
  • internal/mcp_handlers/server.go
  • internal/middleware/http_token_middleware.go
  • internal/utils/utils_test.go
  • internal/http/http_server.go
  • cmd/main.go
  • internal/middleware/http_token_middleware_test.go
  • internal/mcp_handlers/items_test.go
  • internal/config/cli.go
  • internal/mcp_handlers/integration_project_test.go
  • internal/utils/utils.go
  • internal/testutil/mock.go
  • internal/analytics/analytics.go
  • internal/mcp_handlers/items.go
  • internal/middleware/middleware_test.go
**/*_test.go

⚙️ CodeRabbit configuration file

Ensure comprehensive test coverage, proper test isolation, meaningful assertions, and good test naming conventions.

Files:

  • internal/utils/ctx_utils_test.go
  • internal/mcp_handlers/launches_test.go
  • internal/analytics/analytics_test.go
  • internal/utils/utils_project_test.go
  • internal/http/http_server_test.go
  • internal/utils/utils_test.go
  • internal/middleware/http_token_middleware_test.go
  • internal/mcp_handlers/items_test.go
  • internal/mcp_handlers/integration_project_test.go
  • internal/middleware/middleware_test.go
**/Dockerfile*

⚙️ CodeRabbit configuration file

Focus on security best practices, image size optimization, proper layering, and multi-stage builds where appropriate.

Files:

  • Dockerfile
cmd/**

⚙️ CodeRabbit configuration file

Review CLI interface design, configuration handling, and application startup logic for robustness and usability.

Files:

  • cmd/main.go
🧬 Code graph analysis (16)
internal/analytics/analytics_test.go (1)
internal/middleware/http_token_middleware.go (2)
  • WithTokenInContext (92-94)
  • HTTPTokenMiddleware (22-64)
internal/middleware/middleware.go (1)
internal/utils/ctx_utils.go (1)
  • QueryParamsFromContext (28-32)
internal/utils/utils_project_test.go (2)
internal/testutil/mock.go (1)
  • NewMockCallToolRequest (13-15)
internal/utils/utils_test.go (1)
  • ExtractProjectWithMock (179-194)
internal/http/http_server_test.go (1)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/mcp_handlers/launches.go (3)
internal/analytics/analytics.go (1)
  • Analytics (101-115)
internal/utils/utils.go (8)
  • SetPaginationOptions (41-56)
  • DefaultSortingForLaunches (21-21)
  • ExtractProject (87-99)
  • ProcessStartTimeFilter (164-186)
  • ApplyPaginationOptions (59-84)
  • ProcessAttributeKeys (189-217)
  • ExtractResponseError (102-127)
  • ReadResponseBody (286-295)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/mcp_handlers/server.go (4)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/middleware/middleware.go (1)
  • QueryParamsMiddleware (9-28)
internal/mcp_handlers/launches.go (1)
  • RegisterLaunchTools (498-513)
internal/mcp_handlers/items.go (1)
  • RegisterTestItemTools (803-818)
internal/middleware/http_token_middleware.go (1)
internal/utils/ctx_utils.go (2)
  • WithProjectInContext (35-39)
  • ValidateRPToken (50-63)
internal/utils/utils_test.go (2)
internal/utils/utils.go (1)
  • ProcessAttributeKeys (189-217)
internal/utils/ctx_utils.go (1)
  • GetProjectFromContext (42-46)
internal/http/http_server.go (5)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/middleware/middleware.go (1)
  • QueryParamsMiddleware (9-28)
internal/mcp_handlers/launches.go (1)
  • RegisterLaunchTools (498-513)
internal/mcp_handlers/items.go (1)
  • RegisterTestItemTools (803-818)
internal/middleware/http_token_middleware.go (1)
  • HTTPTokenMiddleware (22-64)
cmd/main.go (1)
internal/config/cli.go (2)
  • AppVersion (26-30)
  • RunApp (356-423)
internal/middleware/http_token_middleware_test.go (1)
internal/utils/ctx_utils.go (3)
  • WithProjectInContext (35-39)
  • GetProjectFromContext (42-46)
  • RPProjectContextKey (16-16)
internal/config/cli.go (4)
internal/http/http_server.go (2)
  • HTTPServerConfig (48-60)
  • CreateHTTPServerWithMiddleware (209-235)
internal/analytics/analytics.go (3)
  • GetAnalyticArg (329-343)
  • Analytics (101-115)
  • StopAnalytics (569-578)
internal/mcp_handlers/server.go (1)
  • NewServer (21-69)
internal/utils/ctx_utils.go (1)
  • WithProjectInContext (35-39)
internal/mcp_handlers/integration_project_test.go (2)
internal/middleware/http_token_middleware.go (1)
  • HTTPTokenMiddleware (22-64)
internal/utils/utils.go (1)
  • ExtractProject (87-99)
internal/analytics/analytics.go (1)
internal/middleware/http_token_middleware.go (1)
  • GetTokenFromContext (97-100)
internal/mcp_handlers/items.go (3)
internal/analytics/analytics.go (1)
  • Analytics (101-115)
internal/utils/utils.go (20)
  • SetPaginationOptions (41-56)
  • DefaultSortingForItems (22-22)
  • ExtractProject (87-99)
  • DefaultProviderType (25-25)
  • DefaultFilterEqHasStats (27-27)
  • DefaultFilterEqHasChildren (26-26)
  • DefaultFilterInType (28-28)
  • ProcessStartTimeFilter (164-186)
  • ApplyPaginationOptions (59-84)
  • ProcessAttributeKeys (189-217)
  • ExtractResponseError (102-127)
  • ReadResponseBody (286-295)
  • ReadResponseBodyRaw (259-281)
  • IsTextContent (220-240)
  • FirstPage (18-18)
  • DefaultPageSize (20-20)
  • DefaultSortingForLogs (24-24)
  • DefaultItemLogLevel (30-30)
  • DefaultSortingForSuites (23-23)
  • DefaultFilterInTypeSuites (29-29)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/middleware/middleware_test.go (1)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
🪛 YAMLlint (1.37.1)
Taskfile.yaml

[error] 115-115: too many spaces inside brackets

(brackets)


[error] 115-115: too many spaces inside brackets

(brackets)

🔇 Additional comments (35)
internal/utils/utils.go (1)

1-295: LGTM! Clean refactoring to exported API.

The refactoring from mcpreportportal package to utils with properly exported CamelCase identifiers follows Go best practices. The implementation logic remains intact, and all functions are well-structured with appropriate error handling.

Key strengths:

  • Consistent naming conventions for exported functions and constants
  • Proper error handling with context-aware messages
  • Defensive programming in IsAlreadyClosedError and ReadResponseBodyRaw to handle edge cases gracefully
  • Generic pagination interface PaginatedRequest[T] provides good type safety
Dockerfile (1)

17-18: LGTM! Build path updated correctly.

The Dockerfile correctly references the new entrypoint at cmd/main.go while maintaining the same binary output name and build flags. The change aligns with the PR's modular restructuring.

debug.dockerfile (1)

19-20: LGTM! Debug build path updated correctly.

The debug Dockerfile correctly references the new entrypoint at cmd/main.go while preserving debug flags (-gcflags "all=-N -l") and Delve integration. Consistent with the main Dockerfile changes.

README.md (1)

384-384: LGTM! Documentation updated correctly.

The build command now correctly references the new entrypoint at ./cmd/main.go, aligning with the codebase restructuring.

internal/mcp_handlers/launches_test.go (1)

1-1: LGTM! Package rename aligns with refactoring.

The package rename from mcpreportportal to mcp_handlers is consistent with the broader modular restructuring in this PR.

internal/utils/ctx_utils_test.go (1)

1-1: LGTM! Package rename aligns with refactoring.

The package rename from mcpreportportal to utils is consistent with the broader modular restructuring in this PR.

internal/mcp_handlers/items_test.go (1)

1-1: LGTM! Package rename is consistent with the refactoring.

The package name change aligns with the PR's goal of organizing code into separate modules.

internal/middleware/middleware_test.go (1)

1-29: LGTM! Clean refactoring to use the utils package.

The package rename and migration to utils.WithQueryParams is consistent with the PR's modularization objectives. The test maintains its functionality while properly using the extracted utility.

internal/utils/utils_project_test.go (1)

1-179: LGTM! Well-structured test refactoring.

The migration to use testutil.NewMockCallToolRequest and ExtractProjectWithMock centralizes test utilities and improves maintainability. The test cases comprehensively cover various project extraction scenarios including precedence, whitespace handling, and error cases.

internal/middleware/http_token_middleware_test.go (1)

1-274: LGTM! Comprehensive test coverage with proper utility usage.

The migration to use utils package functions for project context handling is well-executed. The test suite thoroughly covers various scenarios including header handling, whitespace trimming, combined token and project extraction, and edge cases.

internal/utils/utils_test.go (1)

1-194: LGTM! Excellent test coverage and useful test helper.

The test suite for ProcessAttributeKeys is comprehensive, covering basic cases, multiple keys, mixed scenarios, whitespace handling, and edge cases. The addition of ExtractProjectWithMock as an exported test helper is a good practice for enabling cross-package test usage with consistent behavior.

internal/middleware/middleware.go (1)

1-28: LGTM! Clean extraction of utility function.

The refactoring to use utils.QueryParamsFromContext properly separates concerns and makes the code more maintainable. The middleware logic remains intact while leveraging the centralized utility package.

internal/analytics/analytics_test.go (1)

1-1071: LGTM! Comprehensive analytics test suite with proper middleware integration.

The test suite is exceptionally thorough, covering:

  • Token handling (env var vs. Bearer header)
  • User ID generation and hashing
  • Concurrent metric incrementing
  • Batch sending per user
  • Analytics lifecycle management
  • Middleware integration

The migration to use middleware.WithTokenInContext and middleware.HTTPTokenMiddleware properly reflects the new package structure.

internal/analytics/analytics.go (4)

1-22: LGTM! Proper package organization with middleware integration.

The addition of the internal/middleware import and package structure aligns with the refactoring objectives to separate concerns across packages.


114-114: LGTM! Proper use of atomic flag for idempotent Stop().

The stopped field using int32 is the correct type for atomic compare-and-swap operations to ensure thread-safe, idempotent shutdown behavior.


191-214: LGTM! Clean separation of concerns with middleware package.

The use of middleware.GetTokenFromContext properly delegates token extraction to the middleware layer. The priority logic (env var → Bearer header → anonymous) is clear and well-documented.


369-394: LGTM! Excellent idempotent Stop() implementation.

The Stop() method demonstrates proper Go concurrency patterns:

  • Atomic compare-and-swap (CAS) ensures idempotency
  • Safe channel closure (only once)
  • Graceful shutdown with timeout
  • Proper goroutine synchronization with WaitGroup

This implementation is thread-safe and handles multiple Stop() calls correctly.

internal/mcp_handlers/integration_project_test.go (1)

16-119: Good end-to-end coverage of project resolution path

The updated tests exercise the full flow—from HTTP headers through HTTPTokenMiddleware into utils.ExtractProject—including precedence rules and whitespace handling. This gives solid confidence that the new context helpers and extraction logic behave as intended.

Also applies to: 121-162

internal/utils/ctx_utils.go (1)

14-17: Context and token helpers look solid

The new RPProjectContextKey plus WithProjectInContext / GetProjectFromContext correctly encapsulate project handling in context, including trimming and treating whitespace-only values as absent. Moving ValidateRPToken to use uuid.Validate with a length-based fallback is also a good balance between strictness and compatibility.

Also applies to: 34-46, 48-63

internal/middleware/http_token_middleware.go (1)

12-19: Middleware correctly delegates to shared utils and narrows context scope

Using a local contextKey + RPTokenContextKey keeps token context concerns encapsulated in this package, while delegating project handling and token validation to utils.WithProjectInContext and utils.ValidateRPToken centralizes the shared logic. The overall flow (extract → validate → enrich context → log) looks clean and security-conscious.

Also applies to: 21-63, 66-89

internal/http/http_server.go (1)

145-162: HTTP server tool + middleware wiring looks coherent

initializeTools and setupRoutes combine nicely:

  • gorp.NewClient uses the shared httpClient.
  • middleware.QueryParamsMiddleware injects token and query params per request.
  • Launch and test-item tools are registered via mcp_handlers.RegisterLaunchTools / RegisterTestItemTools.
  • HTTP routing groups MCP endpoints under chi with HTTPTokenMiddleware and your mcpMiddleware.

This keeps HTTP concerns (routing, throttling, CORS, timeout) separate from MCP/tool wiring while still allowing per-request auth and project context.

Also applies to: 320-351

internal/mcp_handlers/launches.go (1)

43-53: Nice consolidation of launch tooling via utils and RegisterLaunchTools

The launch tools now lean heavily on shared helpers in utils:

  • Pagination defaults and application (SetPaginationOptions, ApplyPaginationOptions, DefaultSortingForLaunches).
  • Project resolution via utils.ExtractProject.
  • Time-window, attribute, and response handling via ProcessStartTimeFilter, ProcessAttributeKeys, ExtractResponseError, and ReadResponseBody.

RegisterLaunchTools also centralizes the registration of all launch-related tools and the resource template, keeping server.go and the HTTP server free of low-level details.

This structure should make it much easier to maintain launch behavior and to reuse the same tooling in both HTTP and stdio modes.

Also applies to: 115-164, 221-237, 497-513

internal/mcp_handlers/items.go (4)

1-20: LGTM: Clean package structure and imports

The package rename to mcp_handlers and the introduction of separate internal/analytics and internal/utils packages improve modularity and separation of concerns.


22-42: LGTM: Clean refactoring of analytics integration

The constructor correctly uses the extracted analytics.Analytics type and clearly names the parameter analyticsClient for readability.


45-800: LGTM: Consistent refactoring to utils package

All tool handlers have been successfully refactored to use the centralized utils package functions. The error handling, pagination, filtering, and response reading logic is now consistent across all handlers.


802-818: LGTM: Clean tool registration pattern

The RegisterTestItemTools function provides a clean, modular way to wire up all test item-related tools and resources with the MCP server. This pattern improves maintainability and makes the registration process explicit.

internal/config/cli.go (9)

25-30: LGTM: Clean version information structure

The AppVersion struct provides a clear, type-safe way to pass build-time version information through the application. This is a good practice for versioned applications.


32-116: LGTM: Well-organized flag definitions

The separation of common, HTTP-specific, and stdio-specific flags is clean and maintainable. The usage strings with mode prefixes ([GLOBAL/REQUIRED], [HTTP-ONLY], etc.) provide excellent clarity for users.


129-148: LGTM: Proper logger initialization

The logger initialization follows Go best practices by writing to stderr and allowing configurable log levels. The use of a CLI Before function ensures logging is set up before command execution.


150-192: LGTM: Well-designed configuration builder

The function correctly:

  • Auto-detects maxWorkers based on CPU count when not specified
  • Validates the host URL
  • Properly constructs the version string from AppVersion
  • Ensures FallbackRPToken is empty for HTTP mode (as documented)

194-226: LGTM: Clean server creation logic

The function properly:

  • Extracts all required parameters from CLI flags
  • Validates the host URL
  • Delegates to mcp_handlers.NewServer with correct parameters
  • Handles errors appropriately

228-248: LGTM: Robust error handling

The function correctly distinguishes between graceful shutdowns and actual errors by checking for expected shutdown signals (http.ErrServerClosed, context.Canceled, context.DeadlineExceeded). Analytics cleanup is properly handled in all cases.


250-291: LGTM: Well-structured stdio server runner

The function:

  • Validates required token for stdio mode
  • Properly uses context for project information
  • Handles server lifecycle with goroutine and error channel
  • Correctly manages analytics cleanup on shutdown

293-353: LGTM: Secure and robust HTTP server implementation

The function demonstrates good practices:

  • Configures appropriate HTTP timeouts (including ReadHeaderTimeout to prevent Slowloris attacks)
  • Uses the Chi router directly with middleware
  • Implements graceful shutdown with a 5-second timeout
  • Properly stops analytics on shutdown

355-423: LGTM: Comprehensive CLI application runner

The function provides:

  • Mode-aware flag composition (common + mode-specific)
  • Extensive, well-organized help documentation covering environment variables, flag categories, authentication, and analytics
  • Clear mode dispatching with sensible default to stdio
  • Proper integration with the version information

This is a well-designed entry point for the refactored application.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (7)
internal/mcp_handlers/items_test.go (1)

151-162: Simplify with strings.Contains.

The custom contains helper unnecessarily reimplements strings.Contains with a convoluted IIFE pattern. The standard library function is clearer, more maintainable, and equally performant.

Apply this diff:

+import (
+	"strings"
+	"testing"
+)
+
 // Helper function to check if a string contains a substring
 func contains(s, substr string) bool {
-	return len(s) >= len(substr) && (s == substr || len(substr) == 0 ||
-		func() bool {
-			for i := 0; i <= len(s)-len(substr); i++ {
-				if s[i:i+len(substr)] == substr {
-					return true
-				}
-			}
-			return false
-		}())
+	return strings.Contains(s, substr)
 }

Or simply inline strings.Contains at the call sites (line 145) and remove the helper entirely.

internal/http/http_server_test.go (1)

335-361: Add defer cleanup for analytics instance to prevent goroutine leaks in tests

Two concerns in the test:

  1. Goroutine cleanup – The inline analytics.NewAnalytics() creates a background ticker goroutine (started in the factory). Without calling Stop(), this goroutine persists after the test completes, leaking across your test suite. The Analytics.Stop() method is already implemented with proper idempotent semantics (atomic flag). Use defer tt.analytics.Stop() as suggested:
for _, tt := range tests {
	t.Run(tt.name, func(t *testing.T) {
+		if tt.analytics != nil {
+			defer tt.analytics.Stop()
+		}
  1. Interval constant fragilitybatchSendInterval is defined separately in two places: internal/http/http_server.go and internal/analytics/analytics.go. The test currently uses the http package's version (line 28), while production analytics code uses its own (line 36 in analytics.go). Both are 10 * time.Second now, but this coupling is fragile. If someone updates the interval in internal/analytics, the test won't catch the drift. Consider exporting a helper from the analytics package or wiring the test to use the production constant directly.
internal/config/cli.go (2)

150-192: HTTP server config construction is correct; consider stricter URL validation

BuildHTTPServerConfig cleanly applies defaults for workers/timeouts and computes a version string from AppVersion. One small robustness improvement would be to reject rp-host values that parse without a scheme/host (e.g., url.Parse("example.com") succeeds but gives only a Path):

hostURL, err := url.Parse(host)
if err != nil || hostURL.Scheme == "" || hostURL.Host == "" {
    return httpserver.HTTPServerConfig{}, fmt.Errorf("invalid host URL (expected scheme and host): %w", err)
}

This prevents subtle misconfiguration where the URL parses but is unusable downstream.


293-353: HTTP streaming runner is well-structured; mirror MCP stop on error for symmetry

The streaming runner correctly:

  • Builds HTTPServerConfig via BuildHTTPServerConfig.
  • Creates the HTTP/MCP server with middleware.
  • Starts the MCP server before ListenAndServe.
  • Uses timeouts on http.Server and a buffered error channel.
  • Performs graceful shutdown (analytics stop, server.Shutdown, httpServer.MCP.Stop) on ctx.Done().

In the error path (case err := <-errC), you delegate to HandleServerError, which stops analytics but does not attempt an MCP shutdown. Consider adding a best-effort httpServer.MCP.Stop() in that path as well for symmetry, unless CreateHTTPServerWithMiddleware already guarantees no resources remain after ListenAndServe fails.

internal/utils/utils.go (3)

40-84: Pagination helpers look correct; consider clamping to sane minimums

SetPaginationOptions/ApplyPaginationOptions correctly wire MCP parameters and guard against values over math.MaxInt32 before casting to int32. One additional safety improvement would be to clamp to minimum sensible values (e.g., page ≥ 1, page-size ≥ 1) to avoid negative or zero values from unexpected client input:

pageInt := request.GetInt("page", FirstPage)
if pageInt < FirstPage {
    pageInt = FirstPage
}
if pageInt > math.MaxInt32 {
    pageInt = math.MaxInt32
}

pageSizeInt := request.GetInt("page-size", DefaultPageSize)
if pageSizeInt < 1 {
    pageSizeInt = 1
}
if pageSizeInt > math.MaxInt32 {
    pageSizeInt = math.MaxInt32
}

This keeps downstream APIs from seeing nonsense pagination values.


129-161: Clarify timestamp units and accepted formats in ParseTimestampToEpoch

The function sensibly tries integer epoch, then RFC3339, then a few common layouts, and always returns milliseconds. Given the multiple accepted formats and the “seconds vs milliseconds” heuristic, consider tightening the doc comment to explicitly state:

  • The accepted string formats (Unix seconds, RFC3339, YYYY-MM-DD, etc.).
  • That the return value is always Unix epoch in milliseconds.

This will help callers avoid double-converting or misinterpreting values.


101-127: Add nil guard to ExtractResponseError to prevent panic on nil error

The review is valid. While all current call sites in the codebase check if err != nil before calling ExtractResponseError, the function is exported and could be called with a nil error by external code or future callers. Calling err.Error() on a nil error interface will panic, making this a realistic robustness issue for a public utility function.

Add the nil check as suggested:

 func ExtractResponseError(err error, rs *http.Response) (errText string) {
-    errText = err.Error()
+    if err == nil {
+        errText = "request failed"
+    } else {
+        errText = err.Error()
+    }

This follows Go best practices for exported error-handling helpers—defensive guards prevent panics and make the function more usable across different code paths.

♻️ Duplicate comments (4)
internal/mcp_handlers/server.go (1)

42-57: Analytics initialization properly implements best-effort approach.

The analytics initialization now follows a best-effort pattern consistent with the HTTP server behavior. When initialization fails, it logs a warning and continues server startup rather than failing completely. This addresses the previous review feedback about alignment with HTTP server behavior.

internal/testutil/mock.go (1)

1-56: Mock implementation is functional for current needs.

The MockCallToolRequest provides basic functionality for testing project extraction. The implementation is straightforward and serves its current purpose.

As noted in the previous review, if broader test coverage is needed in the future, consider making the mock more flexible with a map-based approach to support arbitrary key-value pairs and configurable error scenarios.

Taskfile.yaml (1)

115-115: Fix YAML lint bracket spacing error.

The deps declaration has extra spaces inside brackets, violating YAML lint rules.

Apply this fix:

-    deps: [ docker:build-debug ]
+    deps: [docker:build-debug]
internal/config/cli.go (1)

118-127: Simplify GetMCPMode and avoid double ToLower

You currently lowercase twice (rawMcpMode and mcpMode). Behavior is correct but can be simplified and made a bit clearer with an early return:

-func GetMCPMode() string {
-	rawMcpMode := strings.ToLower(os.Getenv("MCP_MODE"))
-	slog.Debug("MCP_MODE env variable is set to: " + rawMcpMode)
-	mcpMode := strings.ToLower(rawMcpMode)
-	if mcpMode == "" {
-		mcpMode = "stdio"
-	}
-	return mcpMode
-}
+func GetMCPMode() string {
+	mcpMode := strings.ToLower(os.Getenv("MCP_MODE"))
+	slog.Debug("MCP_MODE env variable is set to: " + mcpMode)
+	if mcpMode == "" {
+		return "stdio"
+	}
+	return mcpMode
+}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dcde972 and b0f2865.

⛔ Files ignored due to path filters (1)
  • .gitignore is excluded by none and included by none
📒 Files selected for processing (27)
  • Dockerfile (1 hunks)
  • README.md (1 hunks)
  • Taskfile.yaml (3 hunks)
  • cmd/main.go (1 hunks)
  • debug.dockerfile (1 hunks)
  • internal/analytics/analytics.go (5 hunks)
  • internal/analytics/analytics_test.go (13 hunks)
  • internal/config/cli.go (9 hunks)
  • internal/http/http_server.go (11 hunks)
  • internal/http/http_server_test.go (4 hunks)
  • internal/mcp_handlers/integration_project_test.go (4 hunks)
  • internal/mcp_handlers/items.go (27 hunks)
  • internal/mcp_handlers/items_test.go (1 hunks)
  • internal/mcp_handlers/launches.go (16 hunks)
  • internal/mcp_handlers/launches_test.go (1 hunks)
  • internal/mcp_handlers/server.go (4 hunks)
  • internal/middleware/http_token_middleware.go (3 hunks)
  • internal/middleware/http_token_middleware_test.go (7 hunks)
  • internal/middleware/middleware.go (2 hunks)
  • internal/middleware/middleware_test.go (2 hunks)
  • internal/reportportal/mock_test.go (0 hunks)
  • internal/testutil/mock.go (1 hunks)
  • internal/utils/ctx_utils.go (3 hunks)
  • internal/utils/ctx_utils_test.go (1 hunks)
  • internal/utils/utils.go (14 hunks)
  • internal/utils/utils_project_test.go (2 hunks)
  • internal/utils/utils_test.go (4 hunks)
💤 Files with no reviewable changes (1)
  • internal/reportportal/mock_test.go
🧰 Additional context used
📓 Path-based instructions (4)
**/Dockerfile*

⚙️ CodeRabbit configuration file

Focus on security best practices, image size optimization, proper layering, and multi-stage builds where appropriate.

Files:

  • Dockerfile
**/*.go

⚙️ CodeRabbit configuration file

Focus on Go best practices, error handling, concurrency safety, performance, and security. Check for proper resource cleanup and context handling.

Files:

  • internal/mcp_handlers/launches_test.go
  • internal/middleware/middleware.go
  • internal/analytics/analytics.go
  • internal/mcp_handlers/items_test.go
  • cmd/main.go
  • internal/http/http_server_test.go
  • internal/http/http_server.go
  • internal/utils/utils_test.go
  • internal/analytics/analytics_test.go
  • internal/middleware/middleware_test.go
  • internal/mcp_handlers/server.go
  • internal/testutil/mock.go
  • internal/config/cli.go
  • internal/mcp_handlers/integration_project_test.go
  • internal/middleware/http_token_middleware.go
  • internal/utils/ctx_utils.go
  • internal/mcp_handlers/launches.go
  • internal/utils/utils_project_test.go
  • internal/utils/utils.go
  • internal/utils/ctx_utils_test.go
  • internal/mcp_handlers/items.go
  • internal/middleware/http_token_middleware_test.go
**/*_test.go

⚙️ CodeRabbit configuration file

Ensure comprehensive test coverage, proper test isolation, meaningful assertions, and good test naming conventions.

Files:

  • internal/mcp_handlers/launches_test.go
  • internal/mcp_handlers/items_test.go
  • internal/http/http_server_test.go
  • internal/utils/utils_test.go
  • internal/analytics/analytics_test.go
  • internal/middleware/middleware_test.go
  • internal/mcp_handlers/integration_project_test.go
  • internal/utils/utils_project_test.go
  • internal/utils/ctx_utils_test.go
  • internal/middleware/http_token_middleware_test.go
cmd/**

⚙️ CodeRabbit configuration file

Review CLI interface design, configuration handling, and application startup logic for robustness and usability.

Files:

  • cmd/main.go
🧬 Code graph analysis (16)
internal/middleware/middleware.go (1)
internal/utils/ctx_utils.go (1)
  • QueryParamsFromContext (28-32)
internal/analytics/analytics.go (1)
internal/middleware/http_token_middleware.go (1)
  • GetTokenFromContext (97-100)
cmd/main.go (1)
internal/config/cli.go (2)
  • AppVersion (26-30)
  • RunApp (356-423)
internal/http/http_server_test.go (1)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/http/http_server.go (5)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/middleware/middleware.go (1)
  • QueryParamsMiddleware (9-28)
internal/mcp_handlers/launches.go (1)
  • RegisterLaunchTools (498-513)
internal/mcp_handlers/items.go (1)
  • RegisterTestItemTools (803-818)
internal/middleware/http_token_middleware.go (1)
  • HTTPTokenMiddleware (22-64)
internal/utils/utils_test.go (2)
internal/utils/utils.go (1)
  • ProcessAttributeKeys (189-217)
internal/utils/ctx_utils.go (1)
  • GetProjectFromContext (42-46)
internal/analytics/analytics_test.go (1)
internal/middleware/http_token_middleware.go (2)
  • WithTokenInContext (92-94)
  • HTTPTokenMiddleware (22-64)
internal/middleware/middleware_test.go (1)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/mcp_handlers/server.go (4)
internal/analytics/analytics.go (2)
  • Analytics (101-115)
  • NewAnalytics (124-173)
internal/middleware/middleware.go (1)
  • QueryParamsMiddleware (9-28)
internal/mcp_handlers/launches.go (1)
  • RegisterLaunchTools (498-513)
internal/mcp_handlers/items.go (1)
  • RegisterTestItemTools (803-818)
internal/config/cli.go (4)
internal/http/http_server.go (2)
  • HTTPServerConfig (48-60)
  • CreateHTTPServerWithMiddleware (209-235)
internal/analytics/analytics.go (3)
  • GetAnalyticArg (329-343)
  • Analytics (101-115)
  • StopAnalytics (569-578)
internal/mcp_handlers/server.go (1)
  • NewServer (22-76)
internal/utils/ctx_utils.go (1)
  • WithProjectInContext (35-39)
internal/mcp_handlers/integration_project_test.go (2)
internal/middleware/http_token_middleware.go (1)
  • HTTPTokenMiddleware (22-64)
internal/utils/utils.go (1)
  • ExtractProject (87-99)
internal/middleware/http_token_middleware.go (1)
internal/utils/ctx_utils.go (2)
  • WithProjectInContext (35-39)
  • ValidateRPToken (50-63)
internal/mcp_handlers/launches.go (3)
internal/analytics/analytics.go (1)
  • Analytics (101-115)
internal/utils/utils.go (8)
  • SetPaginationOptions (41-56)
  • DefaultSortingForLaunches (21-21)
  • ExtractProject (87-99)
  • ProcessStartTimeFilter (164-186)
  • ApplyPaginationOptions (59-84)
  • ProcessAttributeKeys (189-217)
  • ExtractResponseError (102-127)
  • ReadResponseBody (286-295)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/utils/utils_project_test.go (2)
internal/testutil/mock.go (1)
  • NewMockCallToolRequest (13-15)
internal/utils/utils_test.go (1)
  • ExtractProjectWithMock (179-194)
internal/mcp_handlers/items.go (3)
internal/analytics/analytics.go (1)
  • Analytics (101-115)
internal/utils/utils.go (20)
  • SetPaginationOptions (41-56)
  • DefaultSortingForItems (22-22)
  • ExtractProject (87-99)
  • DefaultProviderType (25-25)
  • DefaultFilterEqHasStats (27-27)
  • DefaultFilterEqHasChildren (26-26)
  • DefaultFilterInType (28-28)
  • ProcessStartTimeFilter (164-186)
  • ApplyPaginationOptions (59-84)
  • ProcessAttributeKeys (189-217)
  • ExtractResponseError (102-127)
  • ReadResponseBody (286-295)
  • ReadResponseBodyRaw (259-281)
  • IsTextContent (220-240)
  • FirstPage (18-18)
  • DefaultPageSize (20-20)
  • DefaultSortingForLogs (24-24)
  • DefaultItemLogLevel (30-30)
  • DefaultSortingForSuites (23-23)
  • DefaultFilterInTypeSuites (29-29)
internal/utils/ctx_utils.go (1)
  • WithQueryParams (23-26)
internal/middleware/http_token_middleware_test.go (1)
internal/utils/ctx_utils.go (3)
  • WithProjectInContext (35-39)
  • GetProjectFromContext (42-46)
  • RPProjectContextKey (16-16)
🪛 YAMLlint (1.37.1)
Taskfile.yaml

[error] 115-115: too many spaces inside brackets

(brackets)


[error] 115-115: too many spaces inside brackets

(brackets)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Agent
🔇 Additional comments (54)
internal/middleware/middleware_test.go (1)

1-29: LGTM! Clean refactoring to use the new utils package.

The test correctly adopts the new package structure and uses the public utils.WithQueryParams API. The test logic remains unchanged and appropriate.

internal/utils/ctx_utils.go (1)

14-46: LGTM! Well-designed context utilities with defensive checks.

The new project context helpers are well-implemented:

  • RPProjectContextKey appropriately uses nolint:gosec for a context key constant
  • WithProjectInContext defensively trims whitespace before storing
  • GetProjectFromContext correctly returns false not only when the value is missing but also when it's empty after trimming, preventing empty-string pollution in downstream code

The defensive trimming in both directions ensures consistent handling of whitespace.

Dockerfile (1)

17-18: LGTM! Entrypoint consolidation is correct.

The build command now targets the consolidated cmd/main.go entrypoint while preserving all build flags and the output binary name. This aligns with the PR's refactoring objectives.

README.md (1)

384-384: LGTM! Documentation updated to match the new entrypoint.

The build instruction correctly references ./cmd/main.go, consistent with the Dockerfile changes and the PR's consolidation of the application entrypoint.

internal/mcp_handlers/items_test.go (1)

1-1: LGTM! Package rename aligns with refactoring.

The package declaration correctly updates to mcp_handlers as part of the broader reorganization.

internal/mcp_handlers/launches_test.go (1)

1-1: LGTM! Package rename aligns with refactoring.

The package declaration correctly updates to mcp_handlers as part of the broader codebase reorganization.

internal/utils/ctx_utils_test.go (1)

1-1: LGTM! Package rename aligns with refactoring.

The package declaration correctly updates to utils as part of the broader reorganization. The comprehensive test coverage for UUID validation and token validation remains intact.

debug.dockerfile (1)

19-20: LGTM! Debug build updated for new entrypoint.

The debug build correctly targets cmd/main.go while preserving all debug compiler flags (-gcflags "all=-N -l"). This is consistent with the regular Dockerfile changes.

cmd/main.go (1)

19-37: Signal-aware main entrypoint looks solid

Using signal.NotifyContext and passing the derived context into config.RunApp is idiomatic and gives you clean cancellation on SIGINT/SIGTERM; the error path logging + explicit exit code are also appropriate here. No changes needed from a correctness or context-handling standpoint.

internal/analytics/analytics_test.go (1)

525-653: Good reuse of shared middleware for token-in-context behavior

Switching to middleware.WithTokenInContext and middleware.HTTPTokenMiddleware in these tests keeps the analytics behavior aligned with the real HTTP/middleware stack and exercises the exact token→context→analytics flow (env var vs bearer vs anonymous) very thoroughly. This is a solid improvement in realism and coverage.

internal/middleware/http_token_middleware_test.go (1)

75-144: Project context tests correctly target the shared utils helpers

Updating these tests to use utils.WithProjectInContext, utils.GetProjectFromContext, and utils.RPProjectContextKey ensures they exercise the same context machinery as production code. The table-driven cases around empty/whitespace and missing keys give good confidence in project extraction behavior.

internal/utils/utils_project_test.go (1)

165-179: Mock request wiring for project extraction is appropriate

Using testutil.NewMockCallToolRequest and passing &request into ExtractProjectWithMock fits the interface-based helper and keeps the tests decoupled from the concrete mock type. The table covers all key precedence paths (request vs header vs env) and whitespace handling well.

internal/middleware/middleware.go (1)

9-27: QueryParamsMiddleware correctly reuses shared query-param context helper

Reading query params via utils.QueryParamsFromContext and merging into rq.URL.Query() is a clean way to keep HTTP behavior in sync with the shared context utilities while preserving any existing query string. Token propagation via GetTokenFromContext remains straightforward and idiomatic.

internal/analytics/analytics.go (1)

191-214: Idempotent Stop and shared token-context helper improve analytics robustness

Routing token extraction through middleware.GetTokenFromContext keeps analytics aligned with the HTTP middleware’s context contract, and the updated getUserIDFromContext logic still enforces the intended precedence (env/custom ID → bearer token → anonymous).

The new stopped flag with atomic.CompareAndSwapInt32 in Stop makes shutdown idempotent and safe even under concurrent or repeated calls, while the existing stopChan/tickerDone/wg usage still ensures the background ticker goroutine exits cleanly. This is a solid upgrade for lifecycle and concurrency safety.

Also applies to: 368-394

internal/mcp_handlers/integration_project_test.go (1)

82-117: ---

Integration tests now mirror the real MCP + HTTP flow with verified API usage

Switching to mcp.CallToolRequest with Params.Arguments["project"] and running requests through middleware.HTTPTokenMiddleware before calling utils.ExtractProject gives these tests much closer fidelity to the actual end-to-end flow. The mcp-go library safely supports assigning a map to Params.Arguments on zero-valued structs, so this pattern is sound. The cases around precedence (request vs header) and trimming are clear and match the ExtractProject contract well.

internal/utils/utils_test.go (1)

1-174: LGTM! Comprehensive test coverage.

The test suite for ProcessAttributeKeys is well-structured with thorough edge case coverage, including whitespace handling, empty values, and complex scenarios. The addition of a performance test is a good practice.

internal/middleware/http_token_middleware.go (4)

12-19: LGTM! Proper context key pattern.

The introduction of a dedicated contextKey type follows Go best practices for avoiding context key collisions. The nolint:gosec comment is appropriately justified.


21-64: LGTM! Clean middleware implementation.

The middleware properly extracts tokens and project parameters from HTTP headers, with appropriate delegation to the utils package for context management.


66-89: LGTM! Robust token extraction with validation.

The Bearer token extraction properly validates tokens using utils.ValidateRPToken before processing, with appropriate debug logging for troubleshooting.


91-113: LGTM! Clean context management helpers.

The context management functions follow standard Go patterns for storing and retrieving values from context, with proper validation.

internal/mcp_handlers/server.go (2)

22-41: LGTM! Clean server initialization.

The server initialization properly sets up the MCP server with the required capabilities and configures the ReportPortal client with the appropriate middleware.


59-76: LGTM! Clean tool registration.

The tool registration is properly consolidated using RegisterLaunchTools and RegisterTestItemTools, with the analytics client correctly passed through.

Taskfile.yaml (5)

18-19: LGTM! Inspector containerization variables added.

The new variables properly configure the containerized inspector with a reasonable Node.js base image and the correct npx command.


53-65: LGTM! Build paths updated to new entrypoint.

The build tasks correctly reference the new consolidated entrypoint at cmd/main.go, consistent with the PR's refactoring objectives.


91-101: LGTM! Container cleanup improves development workflow.

The pre-run container cleanup commands prevent port conflicts and stale containers, improving the development experience.


103-112: LGTM! Inspector containerization for HTTP mode.

The inspector tasks properly run in containers for HTTP mode with correct host.docker.internal mapping for Linux compatibility.


113-121: LGTM! Consistent inspector-debug configuration.

The debug inspector task follows the same containerization pattern as the regular inspector, with proper configuration for HTTP mode.

internal/http/http_server.go (6)

1-29: LGTM! Clean package structure and constants.

The package declaration and constants are well-organized. The chimiddleware alias clearly distinguishes Chi middleware from the application's middleware package.


47-74: LGTM! Struct definitions properly updated.

The server configuration and struct definitions correctly integrate the analytics package type.


106-142: LGTM! Consistent best-effort analytics initialization.

The analytics initialization follows the same best-effort pattern as the stdio mode server, with proper error handling that logs warnings without preventing server startup.


144-162: LGTM! Clean tool initialization.

The tool initialization properly delegates to the mcp_handlers package functions and configures middleware correctly. The empty project string is appropriate for HTTP mode where projects come from request headers.


208-235: LGTM! Consistent server creation pattern.

The server creation function properly returns the analytics client for lifecycle management, consistent with the stdio mode implementation.


287-351: LGTM! Well-structured middleware stack.

The Chi router setup properly layers standard middleware with custom middleware, maintaining clean separation between framework and application concerns.

internal/mcp_handlers/launches.go (4)

1-41: LGTM! Clean package structure and constructor.

The LaunchResources struct and constructor properly integrate the analytics package and accept the necessary parameters for initialization.


43-165: LGTM! Clean utils integration.

The tool properly uses utility functions from the utils package, maintaining clean separation of concerns and consistent error handling patterns.


167-495: LGTM! Consistent refactoring across all launch tools.

All tool functions properly use utility functions from the utils package and integrate analytics consistently. The refactoring maintains proper error handling throughout.


497-513: LGTM! Well-designed tool registration function.

The RegisterLaunchTools function properly consolidates all launch-related tool and resource registration, making the codebase more maintainable and consistent with the RegisterTestItemTools pattern.

internal/mcp_handlers/items.go (5)

1-42: LGTM! Consistent structure with launches.

The TestItemResources struct and constructor follow the same pattern as LaunchResources, maintaining consistency across the codebase.


44-243: LGTM! Thorough utils integration.

The tool properly uses utility functions and constants from the utils package throughout, maintaining clean separation of concerns and consistent patterns.


245-379: LGTM! Proper handling of text and binary content.

The attachment tool correctly uses utils.IsTextContent to determine content type and handles both text and binary responses appropriately.


381-800: LGTM! Consistent refactoring across all test item tools.

All tool functions properly integrate with the utils package and maintain consistent error handling and analytics patterns throughout.


802-818: LGTM! Well-designed registration function.

The RegisterTestItemTools function follows the same pattern as RegisterLaunchTools, providing a clean and maintainable way to register all test item-related tools and resources.

internal/config/cli.go (6)

32-104: Flag grouping and env-driven configuration look solid

Splitting common vs mode-specific flags and wiring them to env vars (RP_HOST, RP_PROJECT, LOG_LEVEL, etc.) is clear and keeps CLI ergonomics good. The “HTTP-ONLY” vs “STDIO-ONLY” usage text aligns with the behavior enforced later in RunApp/runners.


129-148: Logger init is fine; consider slightly richer error for bad log-levels

InitLogger correctly parses the log-level flag and configures a global slog handler. If you want to improve UX further, you could wrap the error from UnmarshalText with the offending value to make CLI failures more self-explanatory, but the current behavior is already acceptable.


194-226: NewMCPServer wiring matches handler expectations

Flag extraction, URL parsing, and the call into mcp_handlers.NewServer are consistent with the referenced server constructor (version, host URL, token, userID, project, analytics secret, analyticsOn). Error wrapping is appropriate and preserves context.


228-248: Server error handling and analytics shutdown behavior

HandleServerError correctly treats nil, http.ErrServerClosed, and context cancellations/deadlines as graceful shutdowns and ensures analytics.StopAnalytics is called in both graceful and error cases. This centralization should keep the runners simpler and avoids analytics clients leaking.


250-291: Stdio runner: goroutine + context handling are reasonable

RunStdioServer validates token, injects project into the context when present, then starts Listen in a goroutine and selects on ctx.Done() vs an error channel. As long as server.NewStdioServer(...).Listen respects the passed context, this pattern gives a clean shutdown path and avoids blocking the caller. No obvious race or leak stands out here.


355-423: RunApp orchestrator cleanly separates modes and flags

Using MCP_MODE to decide which flag set to expose, while still defaulting to stdio for unknown/empty values, gives predictable behavior and clear help text. The long description documenting env vars, categories, and auth/analytics semantics is very helpful for users.

internal/utils/utils.go (6)

86-99: Project extraction priority is sensible and robust

ExtractProject correctly prefers the explicit project tool argument, then falls back to GetProjectFromContext, and finally returns a clear error when nothing is available. This ordering matches typical expectations (explicit > ambient) and should work well with both HTTP headers and env-based defaults.


163-187: Start time filter construction is consistent and validates ranges

ProcessStartTimeFilter correctly:

  • Requires both from/to or neither.
  • Uses ParseTimestampToEpoch for both sides.
  • Enforces from < to.
  • Returns the comma-separated form expected by the ReportPortal API.

This is a nice, self-contained helper for building the filter string.


188-217: Attribute key post-processing logic is reasonable

ProcessAttributeKeys handles trimming, optional : suffixing, and combining with existing attributes. The branch that strips the prefix up to : (key[colonIndex+1:]) is a little domain-specific; as long as this matches the backend’s expectations (using postfix-only keys in some modes), the implementation looks fine.


242-255: IsAlreadyClosedError heuristic is reasonable

The string-based checks for common “already closed” error forms are pragmatic and should effectively suppress noisy logs in both ExtractResponseError and ReadResponseBodyRaw. Good balance between robustness and simplicity.


257-295: HTTP response body helpers handle cleanup and logging well

ReadResponseBodyRaw properly guards against nil responses, always closes the body with a defer, and filters out “already closed” errors using IsAlreadyClosedError before logging. ReadResponseBody then wraps this into an MCP CallToolResult, converting I/O failures into NewToolResultError, which is appropriate for tool-level error reporting.

This centralization should reduce duplicated defer/close logic in callers.


219-240: I'll verify the actual implementation in the repository to confirm the review comment's claim about Go switch semantics.

The review comment is based on a misunderstanding of Go switch semantics and should be disregarded.

Go switch statements break implicitly, and when you want to use multiple values in the same case, you use a comma-separated list. However, the code structure shown—with multiple empty case labels followed by a final case with the return statement—is also correct Go. In this pattern, the empty cases don't require explicit fallthrough; they naturally execute the code associated with the next case that contains a statement.

Go allows combining duplicated logic by separating each case value with a comma in the case clause declaration. While both approaches (comma-separated or stacked empty cases) work correctly, your current code already functions as intended: all listed media types (application/json, application/xml, etc.) return true. The function is correct and requires no changes.

Likely an incorrect or invalid review comment.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 27 out of 29 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (5)

internal/utils/utils_test.go:194

  • The ExtractProjectWithMock function is placed in a production test file (utils_test.go) and is exported, which is unusual. Test helpers should typically be in test-only files or test utility packages. Consider moving this function to the internal/testutil package alongside MockCallToolRequest since:
  1. It's specifically designed to work with test mocks (testutil.MockCallToolRequest)
  2. It's a test helper function, not production code
  3. It would be more discoverable and maintainable in the testutil package

This would improve separation of concerns and make it clearer that this is a testing utility.
internal/config/cli.go:30

  • The AppVersion struct should have documentation comments for its exported fields to explain what each field represents. For example:
// AppVersion holds build-time version information
type AppVersion struct {
	Version string // Semantic version (e.g., "1.0.0")
	Commit  string // Git commit hash
	Date    string // Build date in ISO format
}

This improves code documentation and makes it clear what format is expected for each field.
internal/mcp_handlers/server.go:57

  • The analytics initialization logic has changed from returning an error to just logging a warning when analytics initialization fails. However, this inconsistency should be documented:

The comment at line 43-44 mentions "consistent with HTTP server behavior", but it would be helpful to explicitly document that:

  1. Analytics failures are non-fatal and won't prevent server startup
  2. The server will continue to function without analytics if initialization fails
  3. This is by design to ensure the server remains operational even if analytics is misconfigured

Consider updating the comment to explicitly state: "Analytics initialization failures are non-fatal - the server will continue to operate without analytics rather than failing to start."
internal/http/http_server.go:161

  • The comment states "Prompts are registered by mcp_handlers package", but this is misleading. Looking at the mcp_handlers.NewServer function, prompts ARE registered there for stdio mode, but in HTTP mode (this code path), the prompts are not being registered at all since we're only calling RegisterLaunchTools and RegisterTestItemTools.

Either:

  1. Update the comment to clarify that prompts are not registered in HTTP mode (if that's intentional), OR
  2. Actually register the prompts by calling the appropriate function from mcp_handlers

This appears to be a missing feature rather than just a documentation issue - prompts should likely be available in HTTP mode as well.
internal/analytics/analytics.go:114

  • The new stopped atomic field is properly used with atomic.CompareAndSwapInt32 for idempotent shutdown, which is a good improvement. However, the field should be explicitly documented to indicate it requires atomic access. Consider adding a comment like:
stopped    int32 // atomic flag: 0 = running, 1 = stopped (must use atomic operations)

This makes it clear to future maintainers that this field requires atomic operations and should not be accessed directly.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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