Skip to main content

docs_mcp/tools/
crate_version_get.rs

1use 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    /// Crate name
45    pub name: String,
46    /// Exact version string (e.g. "1.0.197")
47    pub version: String,
48}
49
50pub async fn execute(state: &AppState, params: CrateVersionGetParams) -> Result<CallToolResult, ErrorData> {
51    let name = &params.name;
52    let version = &params.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}