turbomcp_client/client/operations/
completion.rs

1//! Completion operations for MCP client
2//!
3//! This module provides autocompletion functionality for prompts and resources,
4//! supporting the MCP completion protocol with context and argument validation.
5
6use std::sync::atomic::Ordering;
7use turbomcp_protocol::types::{
8    ArgumentInfo, CompleteRequestParams, CompleteResult, CompletionContext, CompletionReference,
9    CompletionResponse, PromptReferenceData, ResourceTemplateReferenceData,
10};
11use turbomcp_protocol::{Error, Result};
12
13use crate::with_plugins;
14
15impl<T: turbomcp_transport::Transport + 'static> super::super::core::Client<T> {
16    /// Internal helper for completion operations - DRYed up common logic
17    async fn complete_internal(
18        &self,
19        argument_name: &str,
20        argument_value: &str,
21        reference: CompletionReference,
22        context: Option<CompletionContext>,
23    ) -> Result<CompletionResponse> {
24        if !self.inner.initialized.load(Ordering::Relaxed) {
25            return Err(Error::bad_request("Client not initialized"));
26        }
27
28        let request_params = CompleteRequestParams {
29            argument: ArgumentInfo {
30                name: argument_name.to_string(),
31                value: argument_value.to_string(),
32            },
33            reference,
34            context,
35        };
36
37        let serialized_params = serde_json::to_value(&request_params)?;
38
39        with_plugins!(self, "completion/complete", serialized_params, {
40            let result: CompleteResult = self
41                .inner
42                .protocol
43                .request("completion/complete", Some(serialized_params))
44                .await?;
45
46            Ok(CompletionResponse {
47                completion: result.completion,
48                _meta: result._meta,
49            })
50        })
51    }
52
53    /// Request completion suggestions from the server
54    ///
55    /// Simple completion interface for basic autocompletion needs.
56    /// Uses a prompt-based reference with hardcoded "partial" argument name.
57    ///
58    /// # Arguments
59    ///
60    /// * `handler_name` - The completion handler name
61    /// * `argument_value` - The partial value to complete
62    ///
63    /// # Examples
64    ///
65    /// ```rust,no_run
66    /// # use turbomcp_client::Client;
67    /// # use turbomcp_transport::stdio::StdioTransport;
68    /// # async fn example() -> turbomcp_protocol::Result<()> {
69    /// let mut client = Client::new(StdioTransport::new());
70    /// client.initialize().await?;
71    ///
72    /// let result = client.complete("complete_path", "/usr/b").await?;
73    /// println!("Completions: {:?}", result.completion.values);
74    /// # Ok(())
75    /// # }
76    /// ```
77    pub async fn complete(
78        &self,
79        handler_name: &str,
80        argument_value: &str,
81    ) -> Result<CompletionResponse> {
82        let reference = CompletionReference::Prompt(PromptReferenceData {
83            name: handler_name.to_string(),
84            title: None,
85        });
86
87        self.complete_internal("partial", argument_value, reference, None)
88            .await
89    }
90
91    /// Complete a prompt argument with full MCP protocol support
92    ///
93    /// This method provides access to the complete MCP completion protocol,
94    /// allowing specification of argument names, prompt references, and context.
95    ///
96    /// # Arguments
97    ///
98    /// * `prompt_name` - Name of the prompt to complete for
99    /// * `argument_name` - Name of the argument being completed
100    /// * `argument_value` - Current value for completion matching
101    /// * `context` - Optional context with previously resolved arguments
102    ///
103    /// # Examples
104    ///
105    /// ```rust,no_run
106    /// # use turbomcp_client::Client;
107    /// # use turbomcp_transport::stdio::StdioTransport;
108    /// # use turbomcp_protocol::types::CompletionContext;
109    /// # use std::collections::HashMap;
110    /// # async fn example() -> turbomcp_protocol::Result<()> {
111    /// let mut client = Client::new(StdioTransport::new());
112    /// client.initialize().await?;
113    ///
114    /// // Complete with context
115    /// let mut context_args = HashMap::new();
116    /// context_args.insert("language".to_string(), "rust".to_string());
117    /// let context = CompletionContext { arguments: Some(context_args) };
118    ///
119    /// let completions = client.complete_prompt(
120    ///     "code_review",
121    ///     "framework",
122    ///     "tok",
123    ///     Some(context)
124    /// ).await?;
125    ///
126    /// for completion in completions.completion.values {
127    ///     println!("Suggestion: {}", completion);
128    /// }
129    /// # Ok(())
130    /// # }
131    /// ```
132    pub async fn complete_prompt(
133        &self,
134        prompt_name: &str,
135        argument_name: &str,
136        argument_value: &str,
137        context: Option<CompletionContext>,
138    ) -> Result<CompletionResponse> {
139        let reference = CompletionReference::Prompt(PromptReferenceData {
140            name: prompt_name.to_string(),
141            title: None,
142        });
143
144        self.complete_internal(argument_name, argument_value, reference, context)
145            .await
146    }
147
148    /// Complete a resource template URI with full MCP protocol support
149    ///
150    /// This method provides completion for resource template URIs, allowing
151    /// servers to suggest values for URI template variables.
152    ///
153    /// # Arguments
154    ///
155    /// * `resource_uri` - Resource template URI (e.g., "/files/{path}")
156    /// * `argument_name` - Name of the argument being completed
157    /// * `argument_value` - Current value for completion matching
158    /// * `context` - Optional context with previously resolved arguments
159    ///
160    /// # Examples
161    ///
162    /// ```rust,no_run
163    /// # use turbomcp_client::Client;
164    /// # use turbomcp_transport::stdio::StdioTransport;
165    /// # async fn example() -> turbomcp_protocol::Result<()> {
166    /// let mut client = Client::new(StdioTransport::new());
167    /// client.initialize().await?;
168    ///
169    /// let completions = client.complete_resource(
170    ///     "/files/{path}",
171    ///     "path",
172    ///     "/home/user/doc",
173    ///     None
174    /// ).await?;
175    ///
176    /// for completion in completions.completion.values {
177    ///     println!("Path suggestion: {}", completion);
178    /// }
179    /// # Ok(())
180    /// # }
181    /// ```
182    pub async fn complete_resource(
183        &self,
184        resource_uri: &str,
185        argument_name: &str,
186        argument_value: &str,
187        context: Option<CompletionContext>,
188    ) -> Result<CompletionResponse> {
189        let reference = CompletionReference::ResourceTemplate(ResourceTemplateReferenceData {
190            uri: resource_uri.to_string(),
191        });
192
193        self.complete_internal(argument_name, argument_value, reference, context)
194            .await
195    }
196}