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}