1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// mcp-server/src/completion_handler.rs
use anyhow::{anyhow, Result};
use mcp_protocol::{
constants::error_codes,
messages::JsonRpcMessage,
types::completion::{CompleteRequest, CompleteResponse, CompletionReference, CompletionResult},
};
use serde_json::json;
use crate::server::Server;
impl Server {
/// Handle completion/complete request
pub(crate) async fn handle_completion_complete(&self, message: JsonRpcMessage) -> Result<()> {
match message {
JsonRpcMessage::Request { id, params, .. } => {
// Parse parameters
let params: CompleteRequest = match params {
Some(params) => match serde_json::from_value(params) {
Ok(params) => params,
Err(err) => {
// Send error response
self.transport()
.send(JsonRpcMessage::error(
id,
error_codes::INVALID_PARAMS,
&format!("Invalid completion parameters: {}", err),
None,
))
.await?;
return Ok(());
}
},
None => {
// Send error response
self.transport()
.send(JsonRpcMessage::error(
id,
error_codes::INVALID_PARAMS,
"Missing completion parameters",
None,
))
.await?;
return Ok(());
}
};
// Based on the reference type, dispatch to the correct handler
match ¶ms.r#ref {
CompletionReference::Resource { uri } => {
// This is for resource template completion
// Extract parameter name from URI template
// This is a simple implementation - in reality you'd need more robust parsing
if let Some(param_name) =
extract_parameter_from_uri(uri, ¶ms.argument.name)
{
match self
.resource_manager()
.get_completions(
uri,
¶m_name,
Some(params.argument.value.clone()),
)
.await
{
Ok(items) => {
// Convert CompletionItem array to string array for the standard API
let values = items
.iter()
.map(|item| item.label.clone())
.collect::<Vec<String>>();
// Create completion result
let completion_result = CompletionResult {
values,
total: Some(items.len()),
has_more: false,
};
// Create response
let response = CompleteResponse {
completion: completion_result,
};
// Send response
self.transport()
.send(JsonRpcMessage::response(id, json!(response)))
.await?;
}
Err(err) => {
// Send error response
self.transport()
.send(JsonRpcMessage::error(
id,
error_codes::INTERNAL_ERROR,
&format!("Completion error: {}", err),
None,
))
.await?;
}
}
} else {
// Parameter not found in URI template
// Create empty completion result
let completion_result = CompletionResult {
values: vec![],
total: Some(0),
has_more: false,
};
// Create response
let response = CompleteResponse {
completion: completion_result,
};
self.transport()
.send(JsonRpcMessage::response(id, json!(response)))
.await?;
}
}
CompletionReference::Prompt { name } => {
// Check if we have a completion provider for this prompt
let prompt_manager = self.prompt_manager();
if let Ok(completions) = prompt_manager
.get_completions(
name,
¶ms.argument.name,
Some(params.argument.value.clone()),
)
.await
{
// Create completion result
let completion_result = CompletionResult {
values: completions,
total: None,
has_more: false,
};
// Create response
let response = CompleteResponse {
completion: completion_result,
};
self.transport()
.send(JsonRpcMessage::response(id, json!(response)))
.await?;
return Ok(());
}
// Prompt not found or parameter not found, return empty result
let completion_result = CompletionResult {
values: vec![],
total: Some(0),
has_more: false,
};
// Create response
let response = CompleteResponse {
completion: completion_result,
};
self.transport()
.send(JsonRpcMessage::response(id, json!(response)))
.await?;
}
}
Ok(())
}
_ => Err(anyhow!("Expected request message for completion/complete")),
}
}
}
/// Helper function to extract a parameter from a URI template
/// This is a very simple implementation and would need to be more robust in a real system
fn extract_parameter_from_uri(uri: &str, param_name: &str) -> Option<String> {
// Look for {param_name} in the URI
if uri.contains(&format!("{{{}}}", param_name)) {
Some(param_name.to_string())
} else {
None
}
}