Skip to content

feat: autocompletion for prompt args and resource template URI args #428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

lariel-fernandes
Copy link

@lariel-fernandes lariel-fernandes commented Jun 20, 2025

Description

Fixes #417

  • Handle the method compeltion/complete
  • Add the Context field to the CompleteRequest
  • Allow implementations to configure autocomplete handlers for prompt argumens and arguments of resource template URIs

Example usage:

s := server.NewMCPServer(...)

// Usage with Prompt
mcpServer.AddPrompt(
  mcp.NewPrompt(
    "Tell me a {adjective} joke about {subject}",
    mcp.WithArgument(
      "adjective",
      mcp.ArgumentCompletion(func(ctx context.Context, request mcp.CompleteRequest) (*mcp.CompleteResult, error) {
        input := request.Params.Argument.Value
        // TODO: Check dictionary for adjectives, fuzzy match against input, return suggestions
      }),
    ),
  ),
  promptHandler,
)

// Usage with ResourceTemplate
s.AddResourceTemplate(
  mcp.NewResourceTemplate(
    "postgresql://{userName}@host:5432/{databaseName}", // URI template
    "Database", // Resource name
    mcp.WithTemplateArgumentCompletion(
      "databaseName",
      func(_ context.Context, request mcp.CompleteRequest) (*mcp.CompleteResult, error) {
        input := request.Params.Argument.Value
        user := request.Params.Context.Arguments["user"]
        // TODO: check available databases for user, fuzzy match against input, return matches
      }
    ),
  ),
  resourceTemplateHandler,
)

Type of Change

  • New feature (non-breaking change that adds functionality)
  • MCP spec compatibility implementation

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

  • This PR implements a feature defined in the MCP specification
  • Link to relevant spec section: Completion
  • Implementation follows the specification exactly

Additional Information

  • It was necessary to declare CompletionHandlerFunc in the mcp package instead of the server package to avoid a circular import. Any suggestions on how to solve this with a cleaner approach are welcome.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Added support for autocompletion of URI and prompt arguments, enabling dynamic suggestion capabilities.
    • Introduced new server capability for completions, automatically registered when relevant handlers are present.
    • Added hooks for handling actions before and after completion requests.
  • Improvements
    • Enhanced type safety for resource and prompt references.
    • Improved error handling and response clarity for completion requests.
  • Documentation
    • Added example demonstrating basic argument completion for prompts with a dictionary-based handler.
  • Tests
    • Added tests verifying completion request handling, including success, no results, and error scenarios.

Copy link
Contributor

coderabbitai bot commented Jun 20, 2025

Walkthrough

This change introduces structured support for autocompletion of prompt and resource template arguments in the MCP server. It adds completion handler functions, new server capabilities, completion-specific hooks, and request handling for the new "completion/complete" method. Type safety and contextual information for completions are also improved.

Changes

Files / Paths Change Summary
mcp/prompts.go, mcp/resources.go Added CompletionHandler field and functional options to associate completion handlers with prompt arguments and URI template arguments.
mcp/types.go Introduced CompletionHandlerFunc, extended URITemplate with argument completion handlers, added completion method constant, improved reference typing with RefType, and added context to completion parameters.
mcp/utils.go Added ParseCompletionReference to parse and validate completion request references into typed prompt or resource references.
server/hooks.go Added before/after completion hooks, their registration methods, and invocation logic in the server hook system.
server/request_handler.go Added handling for the new "completion/complete" method in the server's message handler with error handling and hooks.
server/server.go Added completions capability flag, implicit registration logic when adding resource templates or prompts, inclusion of completions in initialization response, and a handler method for completion requests.
www/docs/pages/servers/prompts.mdx Added example for basic argument completion demonstrating dictionary-based completion handler and prompt registration.
server/server_test.go Added tests for completion capability registration and completion request handling including success and error cases.

Assessment against linked issues

Objective Addressed Explanation
Add Context field to CompletionRequest and implement context handling in completion logic (#417)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes were identified. All changes align with the objectives of adding context-aware completion support and related features.

Suggested reviewers

  • robert-jackson-glean
  • dugenkui03

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (1.64.8)

Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf34fb2 and c16e99f.

📒 Files selected for processing (2)
  • server/server.go (8 hunks)
  • server/server_test.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/server.go
🔇 Additional comments (5)
server/server_test.go (5)

62-62: LGTM! Completion capability correctly added to test.

The addition of WithCompletions() to the "All capabilities" test case ensures that the completion functionality is properly tested alongside other capabilities.


91-91: LGTM! Completion capability assertion follows existing pattern.

The assertion assert.NotNil(t, initResult.Capabilities.Completion) is consistent with how other capabilities are validated in this test.


1463-1479: LGTM! Well-structured test setup for completion functionality.

The test setup correctly:

  • Creates a server with a prompt containing an argument with a completion handler
  • Uses a simple completion logic (appending "bar") that's easy to verify in tests
  • Follows the established pattern for prompt creation in other tests

The completion handler implementation is clean and testable.


1481-1564: Excellent test coverage for completion scenarios.

The test cases comprehensively cover:

  1. Successful completion: Validates that the completion handler is invoked and returns expected values
  2. No matching handler: Ensures graceful handling when no completion handler exists for an argument
  3. Missing prompt: Verifies proper error handling with INVALID_PARAMS error code

The JSON-RPC message structures follow the MCP specification correctly, and the assertions validate both success and error scenarios appropriately.


1567-1574: LGTM! Test execution follows established patterns.

The test execution loop and validation structure is consistent with other test functions in this file, ensuring maintainability and readability.

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@lariel-fernandes lariel-fernandes marked this pull request as ready for review June 20, 2025 19:28
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 (1)
server/server.go (1)

400-408: Consider extracting completion capability check to reduce duplication.

The logic for checking completion handlers in prompts is duplicated between AddPrompts and AddPrompt. Consider extracting this to a helper method.

Extract the completion handler check logic:

+func (s *MCPServer) checkPromptCompletionHandlers(prompts ...mcp.Prompt) {
+	for _, prompt := range prompts {
+		for _, arg := range prompt.Arguments {
+			if arg.CompletionHandler != nil {
+				s.implicitlyRegisterCompletionCapabilities()
+				return
+			}
+		}
+	}
+}

 func (s *MCPServer) AddPrompts(prompts ...ServerPrompt) {
 	s.implicitlyRegisterPromptCapabilities()

 	s.promptsMu.Lock()
 	for _, entry := range prompts {
 		s.prompts[entry.Prompt.Name] = entry.Prompt
 		s.promptHandlers[entry.Prompt.Name] = entry.Handler
 	}
 	s.promptsMu.Unlock()

-	for _, entry := range prompts {
-		for _, arg := range entry.Prompt.Arguments {
-			if arg.CompletionHandler != nil {
-				s.implicitlyRegisterCompletionCapabilities()
-				break
-			}
-		}
-	}
+	promptList := make([]mcp.Prompt, len(prompts))
+	for i, entry := range prompts {
+		promptList[i] = entry.Prompt
+	}
+	s.checkPromptCompletionHandlers(promptList...)

 	// When the list of available prompts changes, servers that declared the listChanged capability SHOULD send a notification.
 	if s.capabilities.prompts.listChanged {
 		// Send notification to all initialized sessions
 		s.SendNotificationToAllClients(mcp.MethodNotificationPromptsListChanged, nil)
 	}
 }

 func (s *MCPServer) AddPrompt(prompt mcp.Prompt, handler PromptHandlerFunc) {
 	s.AddPrompts(ServerPrompt{Prompt: prompt, Handler: handler})
-	for _, arg := range prompt.Arguments {
-		if arg.CompletionHandler != nil {
-			s.implicitlyRegisterCompletionCapabilities()
-			break
-		}
-	}
+	s.checkPromptCompletionHandlers(prompt)
 }

Also applies to: 419-425

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0fdb197 and 62131de.

⛔ Files ignored due to path filters (1)
  • server/internal/gen/data.go is excluded by !**/gen/**
📒 Files selected for processing (7)
  • mcp/prompts.go (2 hunks)
  • mcp/resources.go (1 hunks)
  • mcp/types.go (5 hunks)
  • mcp/utils.go (1 hunks)
  • server/hooks.go (3 hunks)
  • server/request_handler.go (1 hunks)
  • server/server.go (6 hunks)
🔇 Additional comments (16)
mcp/resources.go (1)

101-110: LGTM! Well-implemented functional option following established patterns.

The WithTemplateArgumentCompletion function correctly follows the functional options pattern used throughout this file. The initialization of the map when nil and the assignment are properly handled.

mcp/prompts.go (2)

71-72: Good addition of optional completion handler field.

The field is correctly defined as a pointer, making it optional and following Go conventions for optional struct fields.


174-179: Excellent functional option implementation.

The ArgumentCompletion function correctly follows the established functional options pattern for argument configuration.

mcp/utils.go (1)

517-544: Robust parsing function with comprehensive validation.

The function correctly:

  • Validates the structure of the completion reference
  • Handles both resource and prompt reference types appropriately
  • Provides clear error messages for validation failures
  • Returns the correct reference type based on the parsed data
server/request_handler.go (1)

313-337: Perfect implementation following established patterns.

The completion method handler correctly follows the exact same pattern as other method handlers in this switch statement, including:

  • Capability checking with appropriate error response
  • Request unmarshaling with error handling
  • Hook invocations (before/after/onError)
  • Proper JSON-RPC response creation
server/hooks.go (3)

94-95: Properly defined hook function types.

The function signatures correctly match the pattern used for other hook types in this file.


124-125: Correctly added fields to Hooks struct.

The new fields follow the established naming convention and type pattern used for other hook collections.


538-564: Excellent hook implementation following established patterns.

The implementation correctly:

  • Provides Add methods that append to the hook slices
  • Implements before/after methods that call generic hooks (beforeAny/onSuccess)
  • Iterates through all registered hooks appropriately
  • Uses the correct method constant (mcp.MethodCompletion)
  • Follows the exact same pattern as all other hook implementations
mcp/types.go (6)

54-57: LGTM!

The new method constant follows the established naming pattern and includes proper documentation.


77-79: Function signature looks good.

The handler function type is well-designed with proper context support and error handling.


83-85: Well-structured field addition.

The map-based approach for argument completion handlers is efficient and the JSON tag ensures backward compatibility.


979-983: Context tracking implementation is clean.

The addition of the Context field enables intelligent autocompletion based on previously completed arguments, which aligns well with the PR objectives.


1002-1003: Type safety improvement.

Converting to a strongly typed RefType improves type safety and prevents invalid reference types.

Also applies to: 1009-1010


1014-1020: Well-defined reference type constants.

The RefType definition with prefixed constants provides clear type discrimination for completion references.

server/server.go (2)

174-178: Capability field follows established pattern.

The completions capability field is correctly added as a boolean pointer, consistent with other capabilities.


469-475: Capability registration follows established pattern.

The method correctly implements the implicit registration pattern used by other capabilities.

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 (4)
www/docs/pages/servers/prompts.mdx (4)

169-177: Add descriptive preamble for Basic Argument Completion.
Without a brief explanation, readers might not immediately grasp what this example illustrates. Consider adding one or two sentences under the heading to explain that this demonstrates how to register prompt arguments with autocomplete handlers and leverage the Context field for stateful suggestions.


181-184: Clarify dictionary naming and structure.
The dictionary variable is generic—consider renaming to completionOptions or jokeArgDictionary for clarity. Also document its purpose (e.g., “maps argument names to possible suggestion values”).


186-194: Use consistent prompt argument API.
This snippet uses mcp.WithArgument and mcp.RequiredArgument(), but earlier examples rely on mcp.WithPromptArgument and mcp.Required(). Align with the established naming to avoid confusion, for example:

tellJokePrompt := mcp.NewPrompt("tell_joke",
  mcp.WithPromptArgument("adjective", mcp.ArgumentCompletion(handleCompleteFromDictionary)),
  mcp.WithPromptArgument("subject", mcp.Required(), mcp.ArgumentCompletion(handleCompleteFromDictionary)),
)

201-217: Demonstrate use of Context in completion handler.
The CompleteRequest now carries a Context field to enable stateful suggestions, but this example ignores req.Params.Context. Enhance the handler to read from req.Params.Context (e.g., previously selected arguments) and show how it steers or filters the returned suggestions.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e9b0dc5 and 72f12ff.

📒 Files selected for processing (3)
  • mcp/prompts.go (2 hunks)
  • mcp/types.go (6 hunks)
  • www/docs/pages/servers/prompts.mdx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • mcp/prompts.go
  • mcp/types.go

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.

Task: Add Context Field to CompletionRequest
1 participant