github-mcp 0.5.0

GitHub v3 REST API MCP server, generated by mcpify.
Documentation
// GitHub v3 REST API MCP server — generated by mcpify. Do not hand-edit.

use std::collections::HashMap;
use std::time::Duration;

use github_mcp::auth::auth_manager::AuthManager;
use github_mcp::core::api_url_builder::build_api_url;
use github_mcp::core::config_manager::load_config;
use github_mcp::core::config_schema::Transport;

async fn probe(
    config: &github_mcp::core::config_schema::Config,
    headers: HashMap<String, String>,
) -> anyhow::Result<()> {
    let url = build_api_url(&config.url, "/", &[])?;
    let client = reqwest::Client::new();
    let mut request = client
        .get(&url)
        .timeout(Duration::from_millis(config.timeout_ms));
    for (key, value) in headers {
        request = request.header(key, value);
    }

    let response = request.send().await?;
    if response.status().is_success() {
        println!("connection OK");
        Ok(())
    } else {
        anyhow::bail!("connection failed: HTTP {}", response.status())
    }
}

pub async fn run() -> anyhow::Result<()> {
    let config = load_config(serde_json::Map::new())?;
    let mut auth_manager = AuthManager::new(config.auth_method);
    let headers = auth_manager
        .apply_auth_headers(HashMap::new(), "GET", &config.url, Transport::Stdio, None)
        .await?;

    probe(&config, headers).await
}

#[cfg(test)]
mod tests {
    use super::*;
    use tokio::io::{AsyncReadExt, AsyncWriteExt};
    use tokio::net::TcpListener;

    async fn server(status: &'static str) -> String {
        let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
        let address = listener.local_addr().unwrap();
        tokio::spawn(async move {
            let (mut stream, _) = listener.accept().await.unwrap();
            let mut request = [0u8; 2048];
            let _ = stream.read(&mut request).await.unwrap();
            let response =
                format!("HTTP/1.1 {status}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n");
            stream.write_all(response.as_bytes()).await.unwrap();
        });
        format!("http://{address}")
    }

    fn config(url: String) -> github_mcp::core::config_schema::Config {
        serde_json::from_value(serde_json::json!({
            "url": url,

            "auth_method": "pat",

            "timeout_ms": 500
        }))
        .unwrap()
    }

    #[tokio::test]
    async fn probe_accepts_success_and_rejects_error_statuses() {
        assert!(
            probe(&config(server("204 No Content").await), HashMap::new())
                .await
                .is_ok()
        );
        let error = probe(
            &config(server("503 Service Unavailable").await),
            HashMap::new(),
        )
        .await
        .unwrap_err();
        assert!(error.to_string().contains("HTTP 503"));
    }
}