Skip to content

Conversation

@ezraisw
Copy link
Contributor

@ezraisw ezraisw commented Dec 22, 2025

Description

Implements the specification for auto-completion, allowing servers to provide contextual suggestions for prompt and resource template arguments.

  • Added PromptCompletionProvider and ResourceCompletionProvider interfaces in server/completion.go
    • This is intentionally separated for better interface segregation
  • Implemented completion/complete request handler in the server
  • Added WithCompletions(), WithPromptCompletionProvider(), and WithResourceCompletionProvider() server options
  • Extracted nested struct types into its own named type
    • CompleteParams.Argument into CompleteArgument
    • CompleteResult.Completion into Completion
  • Implemented custom UnmarshalJSON for CompleteParams to handle PromptReference and ResourceReference polymorphism
  • Added example implementation in examples/everything

Fixes #657

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • MCP spec compatibility implementation
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Code refactoring (no functional changes)
  • Performance improvement
  • Tests only (no functional changes)
  • Other (please describe):

Checklist

  • My code follows the code style of this project
  • I have performed a self-review of my own code
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the documentation accordingly

MCP Spec Compliance

Additional Information

Very small unlikely breaking change

Due to some nested structs being extracted into its own named type, there is a very small possibility that it will break compilation on a certain syntax:

x := CompleteParams{}
x.Argument = struct {
	Name string `json:"name"`
	Value string `json:"value"`
}{ /* ... */ }

This should be a rare occurrence as it is an unusual way to assign a nested struct value.

Invalid ref type response

Due to the polymorphism logic contained in the CompleteParams.UnmarshalJSON, the server will respond with INVALID_REQUEST instead of INVALID_PARAMS when the ref.type is not "ref/prompt" or "ref/resource".

Summary by CodeRabbit

  • New Features

    • Added completion support: prompt and resource completion flows, server options to enable/configure providers, lifecycle hooks, and request handling.
  • Documentation

    • Expanded README with comprehensive completion guidance and a full registration example (note: some sections appear duplicated).
  • Examples

    • Added example implementations demonstrating prompt-style suggestions and ID-based resource completions.
  • Tests

    • New unit tests for completion request parsing, unmarshalling, provider integration, and default/custom provider behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Walkthrough

Adds typed completion support: new completion RPC/method and types with custom JSON unmarshalling, completion provider interfaces and defaults, server options and handler for completion requests, completion-specific hooks, example utilities and tests, and README documentation (duplicated blocks present). No public API removals.

Changes

Cohort / File(s) Summary
Types & tests
mcp/types.go, mcp/types_test.go
Add MethodCompletionComplete, ServerCapabilities.Completions; introduce CompleteArgument, CompleteContext, Completion, ResourceReference, PromptReference; change CompleteParams to use Argument/Context with custom UnmarshalJSON; update CompleteResult; add tests for UnmarshalJSON.
Server completion interfaces
server/completion.go
Add PromptCompletionProvider and ResourceCompletionProvider interfaces and default no-op implementations.
Server hooks
server/hooks.go
Add OnBeforeCompleteFunc/OnAfterCompleteFunc hook types; register/unregister helpers and invokers (AddBeforeComplete, AddAfterComplete, beforeComplete, afterComplete).
Request dispatch & handler
server/request_handler.go
Add handling for completion/complete: capability check, request unmarshalling, hook invocation, delegation to handleComplete, and JSON-RPC response/error paths.
Server core & options
server/server.go
Add server fields for providers, completions capability flag; add WithPromptCompletionProvider, WithResourceCompletionProvider, WithCompletions; initialize defaults; advertise capability; implement handleComplete routing for prompt/resource refs.
Server tests
server/server_test.go
Add adapter func types and TestMCPServer_Complete covering disabled capability, invalid ref type, default providers, and custom provider behavior (values, Total, HasMore, context).
Examples & docs
Examples: examples/everything/id.go, examples/everything/main.go
Docs: README.md
Add ID-suggestion utilities and example prompt/resource completion providers wired into example server; add extensive README completion documentation (note: duplicated blocks present).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

type: enhancement

Suggested reviewers

  • dugenkui03
  • rwjblue-glean
  • pottekkat

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Server handlers implementation for auto-completion' clearly and concisely describes the main change: adding server-side handler implementations for the auto-completion feature.
Description check ✅ Passed The PR description is comprehensive and well-structured, following the template with clear description, type of change selections, completed checklist, MCP spec compliance details, and additional information about breaking changes.
Linked Issues check ✅ Passed All coding requirements from issue #657 are met: server handler for 'completion/complete' is implemented, completion provider interfaces (PromptCompletionProvider, ResourceCompletionProvider) with default implementations are added, server options (WithCompletions, WithPromptCompletionProvider, WithResourceCompletionProvider) are provided, request parsing with polymorphic ref handling and appropriate error codes are implemented, tests cover prompt/resource completions and invalid refs, and example in examples/everything is included.
Out of Scope Changes check ✅ Passed The changes are within scope: type extractions (CompleteArgument, Completion, PromptReference, ResourceReference, custom UnmarshalJSON for CompleteParams) support the completion feature, documentation updates in README are appropriate, and example implementation demonstrates the new functionality without introducing unrelated modifications.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af408d8 and 0eb29be.

📒 Files selected for processing (1)
  • server/server.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/server.go

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.

@ezraisw ezraisw changed the title Completion server handlers argument autocompletion implementation Server handlers implementation for auto-completion Dec 22, 2025
Copy link
Contributor

@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

🧹 Nitpick comments (5)
mcp/types_test.go (1)

384-407: Consider adding a test case for CompleteContext parsing.

The current tests validate Ref and Argument parsing but don't cover the Context field (which contains Arguments map[string]string). Adding a test case with "context": {"arguments": {"key": "value"}} would improve coverage.

🔎 Suggested additional test case
{
    name: "PromptReference with context",
    inputJSON: `{
        "ref": {
            "type": "ref/prompt",
            "name": "test-prompt"
        },
        "argument": {
            "name": "test-arg",
            "value": "test-value"
        },
        "context": {
            "arguments": {
                "previous_arg": "previous_value"
            }
        }
    }`,
    expectedErr: "",
    expected: CompleteParams{
        Ref: PromptReference{
            Type: "ref/prompt",
            Name: "test-prompt",
        },
        Argument: CompleteArgument{
            Name:  "test-arg",
            Value: "test-value",
        },
        Context: CompleteContext{
            Arguments: map[string]string{
                "previous_arg": "previous_value",
            },
        },
    },
},
server/server_test.go (1)

2882-3100: Comprehensive test coverage for completion functionality.

The tests cover key scenarios:

  • Capability disabled → METHOD_NOT_FOUND
  • Invalid reference type → INVALID_REQUEST with descriptive error
  • Default providers returning empty completions
  • Custom providers with context propagation verification

Consider adding a test case for provider error handling (when a custom provider returns an error) to verify the INTERNAL_ERROR response path.

🔎 Optional: Add error handling test case
t.Run("Provider returns error", func(t *testing.T) {
    message := `{
        "jsonrpc": "2.0",
        "id": 1,
        "method": "completion/complete",
        "params": {
            "ref": {
                "type": "ref/prompt",
                "name": "code_review"
            },
            "argument": {
                "name": "language",
                "value": "py"
            }
        }
    }`
    server := NewMCPServer("test-server", "1.0.0",
        WithCompletions(),
        WithPromptCompletionProvider(
            promptCompletionProviderFunc(func(
                ctx context.Context,
                promptName string,
                argument mcp.CompleteArgument,
                context mcp.CompleteContext,
            ) (*mcp.Completion, error) {
                return nil, fmt.Errorf("provider error")
            }),
        ),
    )
    response := server.HandleMessage(context.Background(), []byte(message))
    errorResp, ok := response.(mcp.JSONRPCError)
    assert.True(t, ok)
    assert.Equal(t, mcp.INTERNAL_ERROR, errorResp.Error.Code)
})
server/completion.go (2)

9-17: Parameter name context shadows the imported context package.

The parameter name context mcp.CompleteContext shadows the context package imported on line 4. While this works because the context package is only used for context.Context (the first parameter), it can cause confusion and potential issues if the method body needs to reference the context package directly.

🔎 Rename parameter to avoid shadowing
 type PromptCompletionProvider interface {
 	// CompletePromptArgument provides completions for a prompt argument
-	CompletePromptArgument(ctx context.Context, promptName string, argument mcp.CompleteArgument, context mcp.CompleteContext) (*mcp.Completion, error)
+	CompletePromptArgument(ctx context.Context, promptName string, argument mcp.CompleteArgument, argContext mcp.CompleteContext) (*mcp.Completion, error)
 }
 
 type ResourceCompletionProvider interface {
 	// CompleteResourceArgument provides completions for a resource template argument
-	CompleteResourceArgument(ctx context.Context, uri string, argument mcp.CompleteArgument, context mcp.CompleteContext) (*mcp.Completion, error)
+	CompleteResourceArgument(ctx context.Context, uri string, argument mcp.CompleteArgument, argContext mcp.CompleteContext) (*mcp.Completion, error)
 }

19-20: GoDoc comment is misleading.

The comment says "DefaultCompletionProvider" but the struct is named DefaultPromptCompletionProvider. As per coding guidelines, GoDoc comments should start with the identifier name.

🔎 Fix GoDoc comments
-// DefaultCompletionProvider returns no completions (fallback)
+// DefaultPromptCompletionProvider returns no completions for prompt arguments (fallback).
 type DefaultPromptCompletionProvider struct{}

And for line 28:

-// DefaultResourceCompletionProvider returns no completions (fallback)
+// DefaultResourceCompletionProvider returns no completions for resource arguments (fallback).
 type DefaultResourceCompletionProvider struct{}
server/server.go (1)

241-253: Consider nil-guard for provider options.

These options accept any PromptCompletionProvider or ResourceCompletionProvider, including nil. If a caller passes nil, handleComplete will panic when calling methods on the nil provider. Consider either:

  1. Documenting that nil is not allowed, or
  2. Adding a nil-guard that falls back to the default provider.
🔎 Optional: Add nil-guard
 // WithPromptCompletionProvider sets a custom prompt completion provider
 func WithPromptCompletionProvider(provider PromptCompletionProvider) ServerOption {
 	return func(s *MCPServer) {
+		if provider == nil {
+			return
+		}
 		s.promptCompletionProvider = provider
 	}
 }
 
 // WithResourceCompletionProvider sets a custom resource completion provider
 func WithResourceCompletionProvider(provider ResourceCompletionProvider) ServerOption {
 	return func(s *MCPServer) {
+		if provider == nil {
+			return
+		}
 		s.resourceCompletionProvider = provider
 	}
 }
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e5bacc and e39af5d.

⛔ Files ignored due to path filters (1)
  • server/internal/gen/data.go is excluded by !**/gen/**
📒 Files selected for processing (10)
  • README.md
  • examples/everything/id.go
  • examples/everything/main.go
  • mcp/types.go
  • mcp/types_test.go
  • server/completion.go
  • server/hooks.go
  • server/request_handler.go
  • server/server.go
  • server/server_test.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Order imports: standard library first, then third-party, then local packages (goimports enforces this)
Follow Go naming conventions: exported identifiers in PascalCase; unexported in camelCase; acronyms uppercase (HTTP, JSON, MCP)
Error handling: return sentinel errors, wrap with fmt.Errorf("context: %w", err), and check with errors.Is/As
Prefer explicit types and strongly-typed structs; avoid using any except where protocol flexibility is required (e.g., Arguments any)
All exported types and functions must have GoDoc comments starting with the identifier name; avoid inline comments unless necessary
Functions that are handlers or long-running must accept context.Context as the first parameter
Ensure thread safety for shared state using sync.Mutex and document thread-safety requirements in comments
For JSON: use json struct tags with omitempty for optional fields; use json.RawMessage for flexible/deferred parsing

Files:

  • examples/everything/id.go
  • mcp/types_test.go
  • server/server.go
  • server/hooks.go
  • server/completion.go
  • examples/everything/main.go
  • server/server_test.go
  • mcp/types.go
  • server/request_handler.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*_test.go: Testing: use testify/assert and testify/require
Write table-driven tests using a tests := []struct{ name, ... } pattern
Go test files must end with _test.go

Files:

  • mcp/types_test.go
  • server/server_test.go
🧠 Learnings (6)
📚 Learning: 2025-08-24T00:52:47.610Z
Learnt from: semistrict
Repo: mark3labs/mcp-go PR: 495
File: server/elicitation_test.go:229-231
Timestamp: 2025-08-24T00:52:47.610Z
Learning: In Go, test files within the same package can access types and functions defined in other test files in that package. When analyzing test code that references undefined types, check other test files in the same package for shared test utilities and mock types.

Applied to files:

  • mcp/types_test.go
📚 Learning: 2025-10-13T09:35:20.180Z
Learnt from: CR
Repo: mark3labs/mcp-go PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-13T09:35:20.180Z
Learning: Applies to **/*_test.go : Testing: use testify/assert and testify/require

Applied to files:

  • mcp/types_test.go
📚 Learning: 2025-06-30T07:13:17.052Z
Learnt from: ezynda3
Repo: mark3labs/mcp-go PR: 461
File: server/sampling.go:22-26
Timestamp: 2025-06-30T07:13:17.052Z
Learning: In the mark3labs/mcp-go project, the MCPServer.capabilities field is a struct value (serverCapabilities), not a pointer, so it cannot be nil and doesn't require nil checking. Only pointer fields within the capabilities struct should be checked for nil.

Applied to files:

  • server/server.go
  • examples/everything/main.go
  • server/server_test.go
  • mcp/types.go
📚 Learning: 2025-06-20T20:39:51.870Z
Learnt from: lariel-fernandes
Repo: mark3labs/mcp-go PR: 428
File: www/docs/pages/servers/prompts.mdx:218-234
Timestamp: 2025-06-20T20:39:51.870Z
Learning: In the mcp-go library, the GetPromptParams.Arguments field is of type map[string]string, not map[string]interface{}, so direct string access without type assertions is safe and correct.

Applied to files:

  • examples/everything/main.go
📚 Learning: 2025-08-08T15:37:18.458Z
Learnt from: ezynda3
Repo: mark3labs/mcp-go PR: 0
File: :0-0
Timestamp: 2025-08-08T15:37:18.458Z
Learning: In mark3labs/mcp-go stdio transport, using bufio.Scanner without calling Scanner.Buffer imposes a 64 KiB per-line limit; to support very long lines safely, set a larger max via Scanner.Buffer or use a streaming Reader/json.Decoder approach.

Applied to files:

  • examples/everything/main.go
📚 Learning: 2025-04-21T21:26:32.945Z
Learnt from: octo
Repo: mark3labs/mcp-go PR: 149
File: mcptest/mcptest.go:0-0
Timestamp: 2025-04-21T21:26:32.945Z
Learning: In the mcptest package, prefer returning errors from helper functions rather than calling t.Fatalf() directly, giving callers flexibility in how to handle errors.

Applied to files:

  • examples/everything/main.go
  • server/server_test.go
🧬 Code graph analysis (6)
mcp/types_test.go (1)
mcp/types.go (4)
  • CompleteParams (1166-1170)
  • PromptReference (1250-1254)
  • CompleteArgument (1218-1223)
  • ResourceReference (1243-1247)
server/hooks.go (1)
mcp/types.go (3)
  • CompleteRequest (1159-1163)
  • CompleteResult (1212-1215)
  • MethodCompletionComplete (106-106)
server/completion.go (1)
mcp/types.go (3)
  • CompleteArgument (1218-1223)
  • CompleteContext (1226-1228)
  • Completion (1231-1240)
examples/everything/main.go (2)
server/server.go (3)
  • WithCompletions (396-400)
  • WithPromptCompletionProvider (242-246)
  • WithResourceCompletionProvider (249-253)
mcp/types.go (3)
  • CompleteArgument (1218-1223)
  • CompleteContext (1226-1228)
  • Completion (1231-1240)
server/server_test.go (5)
mcp/types.go (6)
  • CompleteArgument (1218-1223)
  • CompleteContext (1226-1228)
  • Completion (1231-1240)
  • JSONRPCError (380-384)
  • JSONRPCResponse (373-377)
  • Result (281-285)
server/server.go (4)
  • NewMCPServer (403-439)
  • WithCompletions (396-400)
  • WithPromptCompletionProvider (242-246)
  • WithResourceCompletionProvider (249-253)
mcp/utils.go (1)
  • NewJSONRPCErrorDetails (138-144)
client/transport/interface.go (1)
  • JSONRPCResponse (69-74)
testdata/mockstdio_server.go (1)
  • JSONRPCResponse (21-26)
server/request_handler.go (3)
mcp/types.go (5)
  • MethodCompletionComplete (106-106)
  • CompleteRequest (1159-1163)
  • CompleteResult (1212-1215)
  • METHOD_NOT_FOUND (408-408)
  • INVALID_REQUEST (405-405)
server/errors.go (1)
  • ErrUnsupported (10-10)
server/server.go (1)
  • UnparsableMessageError (103-107)
🔇 Additional comments (16)
README.md (1)

778-888: Documentation for auto-completions looks good.

The new section clearly explains:

  • How to enable completions via server.WithCompletions()
  • Provider interface implementations for prompts and resources
  • Usage of CompleteContext for multi-argument completions
  • Response constraints (max 100 items, Total, HasMore)

The code examples align well with the interfaces defined in server/completion.go and types in mcp/types.go.

examples/everything/main.go (3)

73-75: Completion providers properly wired into server configuration.

The example correctly demonstrates enabling completions and registering both prompt and resource completion providers, aligning with the new server options introduced in server/server.go.


519-539: Prompt completion provider implementation looks correct.

The fallthrough on line 533 is intentional—when the prompt is COMPLEX but the argument is not "style", it falls through to return an empty completion. This is a valid pattern for the example.


544-580: Resource completion provider demonstrates paginated completions well.

The implementation correctly handles:

  • Empty input → suggestions 0-9 with Total=maxId and HasMore=true
  • Non-numeric input → empty suggestions (graceful fallback)
  • Out-of-range input → empty suggestions
  • Valid input → next-digit suggestions with proper Total and HasMore

This provides a good reference implementation for paginated completion scenarios.

server/request_handler.go (1)

436-461: Completion request handling follows established patterns.

The new MethodCompletionComplete case correctly:

  1. Checks capability support (s.capabilities.completions == nil)
  2. Unmarshals into mcp.CompleteRequest
  3. Injects HTTP headers
  4. Invokes pre/post hooks (beforeComplete, afterComplete)
  5. Delegates to handleComplete
  6. Returns appropriate JSON-RPC responses

This is generated code (per the header comment), and the implementation is consistent with other method handlers in the file.

mcp/types_test.go (1)

377-457: Test coverage for CompleteParams unmarshalling is solid.

The table-driven test correctly validates:

  • PromptReference parsing with ref/prompt type
  • ResourceReference parsing with ref/resource type
  • Error handling for unknown reference types
examples/everything/id.go (3)

5-15: Power function implementation is correct.

The pow function uses exponentiation by squaring, which is an efficient O(log p) algorithm. The bitwise operations correctly handle the algorithm.


25-33: ID suggestion logic is correct for the intended use case.

The getIdSuggestions function generates suggestions by appending digits 0-9 to the input number. The caller in resourceCompletionProvider validates the input with isIdInRange before calling this function, so out-of-range inputs are handled properly.


27-33: The code is compatible with the project. Line 29 uses for i := range 10, a Go 1.22+ feature, and the range-over-int feature was added to Go 1.22. The project's go.mod specifies go 1.23.0, which exceeds this requirement, so there are no version compatibility concerns.

server/hooks.go (2)

106-107: Completion hook types follow established patterns.

The OnBeforeCompleteFunc and OnAfterCompleteFunc type definitions are consistent with other hook types in the file, using *mcp.CompleteRequest and *mcp.CompleteResult as expected from the types defined in mcp/types.go.


666-692: Hook registration and invocation methods are correctly implemented.

The methods follow the same pattern as other hook implementations:

  1. AddBeforeComplete/AddAfterComplete append to the respective hook slices
  2. beforeComplete calls beforeAny first, then invokes specific hooks
  3. afterComplete calls onSuccess first, then invokes specific hooks

The nil checks are consistently placed after the generic hook calls, matching the pattern established by other methods like beforeInitialize.

server/server_test.go (1)

2870-2880: Well-structured adapter types for testing.

These function type adapters follow the idiomatic Go pattern (similar to http.HandlerFunc) for bridging function signatures to interface implementations, enabling concise inline provider definitions in tests.

server/server.go (1)

178-179: Provider fields added without mutex protection.

The promptCompletionProvider and resourceCompletionProvider fields are accessed in handleComplete without mutex protection. While providers are typically set during initialization via ServerOption, if they were to be modified after server creation (e.g., via a future SetPromptCompletionProvider method), this could cause a data race.

The current design is safe if providers are only set at construction time. Consider documenting this constraint or adding a dedicated mutex if runtime modification is expected in the future.

mcp/types.go (3)

1172-1209: Well-implemented polymorphic JSON unmarshalling.

The UnmarshalJSON correctly:

  • Uses the Alias pattern to avoid infinite recursion
  • Defers Ref parsing using json.RawMessage
  • Uses a type peek to determine the concrete type
  • Returns a descriptive error for unknown reference types

This enables servers to correctly route completion requests based on the discriminator field.


1217-1254: Well-structured completion types with proper documentation.

The types are well-designed:

  • CompleteArgument holds the name and value of the argument for completion matching.
  • CompleteContext provides already-resolved arguments via a map.
  • Completion correctly uses omitempty for optional Total and HasMore fields, and documents the 100-item limit.
  • ResourceReference and PromptReference correctly require the Type field (no omitempty) for JSON discrimination.

103-107: The spec URL is correct. Version 2025-11-25 is the latest MCP specification, released on November 25, 2025 (approximately three weeks ago), so the reference date is accurate and up-to-date.

Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
server/server.go (1)

241-253: Consider adding nil guards in the provider options.

The options follow the established pattern and have proper GoDoc comments. However, if a user explicitly passes nil, it would overwrite the default provider and cause a panic when handleComplete invokes the provider methods.

This is a programming error by the user, but adding nil guards would be more defensive.

🔎 Optional nil guard
 // WithPromptCompletionProvider sets a custom prompt completion provider
 func WithPromptCompletionProvider(provider PromptCompletionProvider) ServerOption {
 	return func(s *MCPServer) {
+		if provider == nil {
+			return
+		}
 		s.promptCompletionProvider = provider
 	}
 }

 // WithResourceCompletionProvider sets a custom resource completion provider
 func WithResourceCompletionProvider(provider ResourceCompletionProvider) ServerOption {
 	return func(s *MCPServer) {
+		if provider == nil {
+			return
+		}
 		s.resourceCompletionProvider = provider
 	}
 }
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e39af5d and 64864ba.

📒 Files selected for processing (1)
  • server/server.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Order imports: standard library first, then third-party, then local packages (goimports enforces this)
Follow Go naming conventions: exported identifiers in PascalCase; unexported in camelCase; acronyms uppercase (HTTP, JSON, MCP)
Error handling: return sentinel errors, wrap with fmt.Errorf("context: %w", err), and check with errors.Is/As
Prefer explicit types and strongly-typed structs; avoid using any except where protocol flexibility is required (e.g., Arguments any)
All exported types and functions must have GoDoc comments starting with the identifier name; avoid inline comments unless necessary
Functions that are handlers or long-running must accept context.Context as the first parameter
Ensure thread safety for shared state using sync.Mutex and document thread-safety requirements in comments
For JSON: use json struct tags with omitempty for optional fields; use json.RawMessage for flexible/deferred parsing

Files:

  • server/server.go
🧠 Learnings (1)
📚 Learning: 2025-06-30T07:13:17.052Z
Learnt from: ezynda3
Repo: mark3labs/mcp-go PR: 461
File: server/sampling.go:22-26
Timestamp: 2025-06-30T07:13:17.052Z
Learning: In the mark3labs/mcp-go project, the MCPServer.capabilities field is a struct value (serverCapabilities), not a pointer, so it cannot be nil and doesn't require nil checking. Only pointer fields within the capabilities struct should be checked for nil.

Applied to files:

  • server/server.go
🧬 Code graph analysis (1)
server/server.go (3)
server/completion.go (4)
  • PromptCompletionProvider (9-12)
  • ResourceCompletionProvider (14-17)
  • DefaultPromptCompletionProvider (20-20)
  • DefaultResourceCompletionProvider (29-29)
mcp/utils.go (1)
  • ToBoolPtr (959-961)
mcp/types.go (6)
  • CompleteRequest (1159-1163)
  • CompleteResult (1212-1215)
  • Completion (1231-1240)
  • Params (212-212)
  • PromptReference (1250-1254)
  • ResourceReference (1243-1247)
🔇 Additional comments (7)
server/server.go (7)

178-179: LGTM! Completion provider fields are well-structured.

The new fields follow Go naming conventions and are appropriately unexported. They're initialized with default implementations in NewMCPServer, ensuring they're never nil during normal operation.


204-204: LGTM! Completions capability field follows established pattern.

The completions *bool field is consistent with other capability fields like logging, sampling, and elicitation, using a pointer to distinguish between unset and explicitly disabled.


395-400: LGTM! Completions option follows established patterns.

The WithCompletions() option is consistent with other capability-enabling options like WithLogging() and WithElicitation(), using mcp.ToBoolPtr(true) appropriately.


419-420: LGTM! Default provider initialization ensures robustness.

Initializing the providers with default implementations ensures they're never nil, preventing potential panics and providing sensible no-op behavior out of the box.


422-430: LGTM! Explicit nil initialization clarifies default state.

Explicitly setting all capabilities to nil makes the default (disabled) state clear and self-documenting.


802-804: LGTM! Completions capability advertisement follows the pattern.

The capability check and advertisement follows the same pattern as other capabilities, using &struct{}{} as a presence marker in the initialize response.


1563-1608: LGTM! The handleComplete function is well-implemented and addresses the previous nil-dereference concern.

The function follows Go conventions and coding guidelines:

  • Context as first parameter ✓
  • Proper error handling with appropriate error codes ✓
  • Thread-safe (read-only access to providers) ✓

The nil check at lines 1600-1603 correctly addresses the concern from the previous review about potential nil pointer dereference. If a provider returns (nil, nil), the code now safely creates an empty Completion instead of panicking.

The switch statement properly routes to the appropriate provider based on reference type, with a sensible fallback for unknown types.

Copy link
Contributor

@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

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64864ba and b7a41c2.

📒 Files selected for processing (1)
  • server/server.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Order imports: standard library first, then third-party, then local packages (goimports enforces this)
Follow Go naming conventions: exported identifiers in PascalCase; unexported in camelCase; acronyms uppercase (HTTP, JSON, MCP)
Error handling: return sentinel errors, wrap with fmt.Errorf("context: %w", err), and check with errors.Is/As
Prefer explicit types and strongly-typed structs; avoid using any except where protocol flexibility is required (e.g., Arguments any)
All exported types and functions must have GoDoc comments starting with the identifier name; avoid inline comments unless necessary
Functions that are handlers or long-running must accept context.Context as the first parameter
Ensure thread safety for shared state using sync.Mutex and document thread-safety requirements in comments
For JSON: use json struct tags with omitempty for optional fields; use json.RawMessage for flexible/deferred parsing

Files:

  • server/server.go
🧠 Learnings (1)
📚 Learning: 2025-06-30T07:13:17.052Z
Learnt from: ezynda3
Repo: mark3labs/mcp-go PR: 461
File: server/sampling.go:22-26
Timestamp: 2025-06-30T07:13:17.052Z
Learning: In the mark3labs/mcp-go project, the MCPServer.capabilities field is a struct value (serverCapabilities), not a pointer, so it cannot be nil and doesn't require nil checking. Only pointer fields within the capabilities struct should be checked for nil.

Applied to files:

  • server/server.go
🧬 Code graph analysis (1)
server/server.go (4)
server/completion.go (4)
  • PromptCompletionProvider (9-12)
  • ResourceCompletionProvider (14-17)
  • DefaultPromptCompletionProvider (20-20)
  • DefaultResourceCompletionProvider (29-29)
examples/custom_context/main.go (1)
  • MCPServer (100-102)
mcp/utils.go (1)
  • ToBoolPtr (959-961)
mcp/types.go (8)
  • CompleteRequest (1159-1163)
  • CompleteResult (1212-1215)
  • Completion (1231-1240)
  • Params (212-212)
  • PromptReference (1250-1254)
  • ResourceReference (1243-1247)
  • INVALID_PARAMS (411-411)
  • INTERNAL_ERROR (414-414)
🔇 Additional comments (7)
server/server.go (7)

178-179: LGTM: Provider fields follow established patterns.

The completion provider fields are consistent with the server's configuration pattern where options are applied during construction.


204-204: LGTM: Completions capability flag is consistent.

The completions *bool field follows the same pattern as other capability flags like logging, sampling, etc.


241-253: LGTM: Provider ServerOption functions follow conventions.

The WithPromptCompletionProvider and WithResourceCompletionProvider functions follow the established ServerOption pattern and have proper GoDoc comments.


395-400: LGTM: Completions capability enabler is consistent.

The WithCompletions function follows the same pattern as other capability enablers like WithLogging and WithElicitation.


419-420: LGTM: Default providers ensure safe nil-free operation.

Initializing both completion providers with default implementations is good defensive programming, ensuring the providers are never nil even when not explicitly configured.


802-804: LGTM: Completions capability advertisement is consistent.

The capability advertisement follows the same pattern as other empty capabilities like logging and elicitation.


1600-1602: Past review issue resolved: nil completion now handled safely.

The nil check for completion at lines 1600-1602 resolves the previous review concern about potential nil pointer dereference. When the provider returns (nil, nil), the code now safely returns an empty CompleteResult instead of panicking.

Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
server/server.go (1)

1600-1602: Nil completion handling is defensive but treats nil as valid.

The nil check prevents the panic that was previously flagged. However, a provider returning (nil, nil) is likely a bug. The current code treats it as "no completions available" by returning an empty result. Consider whether this should log a warning or return an internal error to make provider bugs more visible during development.

Based on learnings: The capabilities field is a struct value, not a pointer, so providers (also initialized in NewMCPServer) similarly should never be nil. However, custom providers might still have bugs.

💡 Optional: Add comment explaining defensive nil handling
 	if err != nil {
 		return nil, &requestError{
 			id:   id,
 			code: mcp.INTERNAL_ERROR,
 			err:  err,
 		}
 	}

+	// Defensive nil check: default providers always return non-nil completions,
+	// but custom providers might erroneously return nil. Treat as empty result.
 	if completion == nil {
 		return &mcp.CompleteResult{}, nil
 	}
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b7a41c2 and af408d8.

📒 Files selected for processing (1)
  • server/server.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Order imports: standard library first, then third-party, then local packages (goimports enforces this)
Follow Go naming conventions: exported identifiers in PascalCase; unexported in camelCase; acronyms uppercase (HTTP, JSON, MCP)
Error handling: return sentinel errors, wrap with fmt.Errorf("context: %w", err), and check with errors.Is/As
Prefer explicit types and strongly-typed structs; avoid using any except where protocol flexibility is required (e.g., Arguments any)
All exported types and functions must have GoDoc comments starting with the identifier name; avoid inline comments unless necessary
Functions that are handlers or long-running must accept context.Context as the first parameter
Ensure thread safety for shared state using sync.Mutex and document thread-safety requirements in comments
For JSON: use json struct tags with omitempty for optional fields; use json.RawMessage for flexible/deferred parsing

Files:

  • server/server.go
🧠 Learnings (1)
📚 Learning: 2025-06-30T07:13:17.052Z
Learnt from: ezynda3
Repo: mark3labs/mcp-go PR: 461
File: server/sampling.go:22-26
Timestamp: 2025-06-30T07:13:17.052Z
Learning: In the mark3labs/mcp-go project, the MCPServer.capabilities field is a struct value (serverCapabilities), not a pointer, so it cannot be nil and doesn't require nil checking. Only pointer fields within the capabilities struct should be checked for nil.

Applied to files:

  • server/server.go
🔇 Additional comments (4)
server/server.go (4)

178-179: LGTM: Completion provider fields are correctly initialized.

The provider fields are properly initialized with default implementations in NewMCPServer, ensuring they're never nil. Since these are set during construction and only read during request handling, no synchronization is required.

Also applies to: 419-420


241-253: LGTM: ServerOption functions follow established patterns.

The completion provider options and capability enabler follow the same pattern as existing server options, with proper GoDoc comments and consistent naming.

Also applies to: 395-400


204-204: LGTM: Completions capability integration is consistent.

The completions capability field and advertisement logic follow the same pattern as other simple capabilities (logging, sampling, roots, etc.).

Also applies to: 802-804


1563-1607: handleComplete implementation looks solid.

The handler correctly:

  • Routes completion requests to the appropriate provider based on reference type
  • Returns INVALID_REQUEST for unknown reference types (addressing previous feedback)
  • Handles provider errors with INTERNAL_ERROR
  • Guards against nil completion results to prevent panics

The implementation follows Go conventions and integrates well with the existing request handling pattern.

@ezynda3 ezynda3 merged commit 74f5edb into mark3labs:main Jan 6, 2026
4 checks passed
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.

Implement completion server handlers for argument autocompletion

2 participants