Skip to content

Conversation

bug-ops
Copy link
Contributor

@bug-ops bug-ops commented Aug 27, 2025

Implements context-aware completion specification from modelcontextprotocol/modelcontextprotocol#598, enabling intelligent completion suggestions based on previously resolved arguments with significant performance optimizations.
Closes #395

Motivation and Context

Current MCP completion requests lack context about previously resolved variables, limiting completion intelligence for multi-argument scenarios.

This enhancement addresses the limitation by adding optional CompletionContext to completion requests, allowing servers to provide contextually relevant suggestions based on previously resolved arguments.

How Has This Been Tested?

  • comprehensive unit tests covering all completion scenarios
  • Integration tests with client-server completion workflows
  • Performance benchmarking with datasets up to 10,000 candidates
  • Schema compliance testing against MCP 2025-06-18 specification
  • Memory profiling

Breaking Changes

None. This is a fully backwards-compatible enhancement:

  • context field in CompleteRequestParam is optional
  • All existing completion implementations continue working unchanged
  • Servers without context support gracefully degrade to current behavior
  • All existing tests pass without modification

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Key Implementation Details

  • CompletionProvider trait: Async trait with Pin<Box<dyn Future>> for dyn compatibility
  • Zero-allocation fuzzy matching: Index-based scoring eliminates string allocations
  • Top-k selection optimization: select_nth_unstable instead of full sorting (O(n + k log k))
  • Comprehensive validation: MAX_VALUES limit and input validation per MCP spec
  • Extensible architecture: DefaultCompletionProvider is default implementation. Trait-based design allows custom completion algorithms: database, API, ML-powered, or hybrid approaches

API Design

// Context-aware completion
client.complete_prompt_argument(
    "weather_prompt", "location", "San",
    Some(CompletionContext::with_arguments([
        ("country", "USA")
    ].into()))
).await?;

// Simple completion (backwards compatible)
client.complete_prompt_simple("prompt", "arg", "value").await?;

Complete implementation of MCP completion specification with performance optimizations:

Core Features:
- Add CompletionContext for context-aware completion with previously resolved arguments
- Implement CompletionProvider trait with async support and dyn compatibility
- Create DefaultCompletionProvider with optimized fuzzy matching algorithm
- Add comprehensive validation and helper methods to CompletionInfo
- Update ServerHandler to handle completion/complete requests
- Add client convenience methods for prompt and resource completion

Performance Optimizations:
- Zero-allocation fuzzy matching using index-based scoring
- Top-k selection with select_nth_unstable instead of full sorting
- Pre-allocated vectors to avoid reallocations during matching
- Char-based case-insensitive matching to minimize string operations
- 5-8x performance improvement for large candidate sets

API Design:
- Context-aware completion supporting multi-argument scenarios
- Type-safe validation with MAX_VALUES limit (100 per MCP spec)
- Helper methods: with_all_values, with_pagination, validate
- Reference convenience methods: for_prompt, for_resource
- Client methods: complete_prompt_argument, complete_resource_argument

Testing:
- 17 comprehensive tests covering all functionality
- Schema compliance tests for MCP 2025-06-18 specification
- Performance tests with <100ms target for 1000 candidates
- Edge case and validation tests

Schema Updates:
- Add CompletionContext to JSON schema
- Update CompleteRequestParam with optional context field
- Maintain backward compatibility with existing API
@github-actions github-actions bot added T-test Testing related changes T-config Configuration file changes T-core Core library changes T-handler Handler implementation changes T-service Service layer changes labels Aug 27, 2025
Add three new test cases to enhance coverage of fuzzy matching algorithm:

- test_fuzzy_matching_with_typos_and_missing_chars: Tests subsequence matching
  with real-world scenarios including abbreviated patterns, case-insensitive
  matching, and complex file/package name completion

- test_fuzzy_matching_scoring_priority: Validates scoring system prioritizes
  exact matches > prefix matches > substring matches > subsequence matches

- test_fuzzy_matching_edge_cases: Covers boundary conditions including
  single character queries, oversized queries, and repeated characters

These tests ensure robust fuzzy search functionality for MCP completion
specification implementation with proper handling of user typos and
incomplete input patterns.
- Enhance fuzzy matching algorithm with acronym support for multi-word entries
- Add comprehensive scoring system for better relevance ranking
- Implement multi-level matching: exact, prefix, word prefix, acronym, substring
- Add context-aware completion scoring with proper priority ordering
- Optimize performance through efficient character-by-character matching
- Support case-insensitive acronym matching
- Improve code quality with clippy fixes and async fn syntax
- Add comprehensive test suite covering edge cases and acronym matching
- Create completion example server demonstrating weather-related prompts
@github-actions github-actions bot added T-dependencies Dependencies related changes T-examples Example code changes labels Aug 28, 2025
argument_name: &'a str,
current_value: &'a str,
context: Option<&'a CompletionContext>,
) -> Pin<Box<dyn Future<Output = Result<CompletionInfo, McpError>> + Send + 'a>>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

just use futures::future::BoxFuture

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no longer relevant

argument_name: &'a str,
current_value: &'a str,
context: Option<&'a CompletionContext>,
) -> Pin<Box<dyn Future<Output = Result<CompletionInfo, McpError>> + Send + 'a>>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

just use futures::future::BoxFuture

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no longer relevant


/// Default completion provider with optimized fuzzy matching
#[derive(Debug, Clone, Default)]
pub struct DefaultCompletionProvider {
Copy link
Collaborator

@4t145 4t145 Sep 1, 2025

Choose a reason for hiding this comment

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

Do we really need a default implementation here? Should we move it to example?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi, @4t145! Good point. The fuzzy matching comes from a side project and covers ~60% of common completion use cases (exact, prefix, acronym matching like "LA" → "Los Angeles"). Of course, users can implement their own custom provider.

Rationale: Provides immediate usability + serves as a reference implementation for different patterns.

Trade-off: It's substantial (~200 lines) - perhaps too complex for examples but not essential enough for core.

Happy to refactor based on project needs - would you prefer minimal core with examples, or "batteries included" approach? Easy to move or remove if it doesn't fit the library's scope.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

moved to example

) -> Pin<Box<dyn Future<Output = Result<CompletionInfo, McpError>> + Send + 'a>> {
Box::pin(async move {
// Default implementation provides basic completion examples
let candidates = vec![
Copy link
Collaborator

Choose a reason for hiding this comment

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

these are just hard coded values for no reason

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no longer relevant

@4t145 4t145 requested a review from Copilot September 1, 2025 04:00
Copy link
Contributor

@Copilot 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 implements context-aware completion functionality according to the MCP 2025-06-18 specification, enabling intelligent completion suggestions based on previously resolved arguments with performance optimizations.

Key changes include:

  • Added CompletionContext type for providing previously resolved argument values to completion requests
  • Implemented DefaultCompletionProvider with optimized fuzzy matching algorithms
  • Added convenience client methods for completion requests with proper validation

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
examples/servers/src/completion_stdio.rs Complete example server demonstrating completion functionality with weather query prompt
examples/servers/Cargo.toml Added new completion example configuration
crates/rmcp/tests/test_message_schema/client_json_rpc_message_schema.json Updated JSON schema to include CompletionContext type
crates/rmcp/tests/test_completion.rs Comprehensive test suite covering completion functionality, fuzzy matching, and performance
crates/rmcp/src/service/client.rs Added client convenience methods for completion requests
crates/rmcp/src/model.rs Core completion types including CompletionContext, CompletionInfo validation, and Reference helpers
crates/rmcp/src/handler/server/completion.rs DefaultCompletionProvider implementation with optimized fuzzy matching
crates/rmcp/src/handler/server.rs Updated to include completion module and default handler

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 1130 to 1134
/// Get all argument names
pub fn argument_names(&self) -> Vec<&str> {
self.arguments
.as_ref()
.map_or_else(Vec::new, |args| args.keys().map(|k| k.as_str()).collect())
Copy link
Preview

Copilot AI Sep 1, 2025

Choose a reason for hiding this comment

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

This method allocates a new Vec on every call. Consider returning an iterator instead: impl Iterator<Item = &str> to avoid unnecessary allocations when the caller only needs to iterate over the names.

Suggested change
/// Get all argument names
pub fn argument_names(&self) -> Vec<&str> {
self.arguments
.as_ref()
.map_or_else(Vec::new, |args| args.keys().map(|k| k.as_str()).collect())
/// Get all argument names as an iterator
pub fn argument_names(&self) -> impl Iterator<Item = &str> {
self.arguments
.as_ref()
.map_or_else(|| std::iter::empty(), |args| args.keys().map(|k| k.as_str()))

Copilot uses AI. Check for mistakes.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agree with that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@bug-ops bug-ops marked this pull request as draft September 3, 2025 07:45
…uilder

- Remove DefaultCompletionProvider from library core
- Move completion logic to examples following review feedback
- Update CompletionContext.argument_names() to return Iterator for better performance
- Replace tech search example with SQL query builder demonstrating progressive completion
- Add context-aware completion that adapts based on filled arguments
- Use proper Option types for optional SQL fields (columns, where_clause, values)
- Demonstrate real-world value of argument_names() method for dynamic completion flow

The SQL query builder showcases:
• Progressive field availability based on operation type
• Context validation using argument_names()
• Proper Optional field handling
• Smart completion that guides user through multi-step form
@bug-ops bug-ops marked this pull request as ready for review September 6, 2025 09:52
@bug-ops bug-ops requested a review from 4t145 September 6, 2025 09:52
Copy link
Collaborator

@4t145 4t145 left a comment

Choose a reason for hiding this comment

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

Looks good to me.

@4t145 4t145 merged commit 452fe2c into modelcontextprotocol:main Sep 8, 2025
11 checks passed
@github-actions github-actions bot mentioned this pull request Sep 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-config Configuration file changes T-core Core library changes T-dependencies Dependencies related changes T-examples Example code changes T-handler Handler implementation changes T-service Service layer changes T-test Testing related changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature request: Context-Aware Completion Enhancement (MCP 2025-06-18)
2 participants