docs_mcp/tools/
crate_version_get.rs1use rmcp::{ErrorData, model::{CallToolResult, Content}};
2use serde::{Deserialize, Serialize};
3use rmcp::schemars::{self, JsonSchema};
4
5use super::AppState;
6
7#[derive(Serialize)]
8struct PublisherOutput {
9 login: String,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 name: Option<String>,
12}
13
14#[derive(Serialize)]
15struct VersionGetOutput {
16 num: String,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 license: Option<String>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 edition: Option<String>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 rust_version: Option<String>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 has_lib: Option<bool>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 bin_names: Option<Vec<String>>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 crate_size: Option<u64>,
29 downloads: u64,
30 yanked: bool,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 yank_message: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 published_by: Option<PublisherOutput>,
35 created_at: String,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 checksum: Option<String>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 lib_links: Option<String>,
40}
41
42#[derive(Debug, Deserialize, JsonSchema)]
43pub struct CrateVersionGetParams {
44 pub name: String,
46 pub version: String,
48}
49
50pub async fn execute(state: &AppState, params: CrateVersionGetParams) -> Result<CallToolResult, ErrorData> {
51 let name = ¶ms.name;
52 let version = ¶ms.version;
53
54 let client = crate::cratesio::CratesIoClient::new(&state.client, &state.cache);
55 let v = client.get_version(name, version).await
56 .map_err(|e| ErrorData::internal_error(e.to_string(), None))?;
57
58 let output = VersionGetOutput {
59 num: v.num,
60 license: v.license,
61 edition: v.edition,
62 rust_version: v.rust_version,
63 has_lib: v.has_lib,
64 bin_names: v.bins,
65 crate_size: v.crate_size,
66 downloads: v.downloads,
67 yanked: v.yanked,
68 yank_message: v.yank_message,
69 published_by: v.published_by.map(|p| PublisherOutput { login: p.login, name: p.name }),
70 created_at: v.created_at,
71 checksum: v.checksum,
72 lib_links: v.lib_links,
73 };
74
75 let json = serde_json::to_string_pretty(&output)
76 .map_err(|e| ErrorData::internal_error(e.to_string(), None))?;
77 Ok(CallToolResult::success(vec![Content::text(json)]))
78}