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