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 crate::auth::auth_manager::AuthManager;
use crate::auth::request_credentials::RequestCredentials;
use crate::core::config_schema::Config;
use crate::data::store::EndpointRecord;
use crate::services::api_client::ApiClient;
use crate::validation::validator::{validate_input, validate_output};

/// Validates arguments against the input schema, injects the active auth
/// strategy's credentials, executes the live HTTP request, and checks the
/// response against the output schema before returning it — PRD §1.5's
/// `call` pipeline (architecture.md's 4-step `call` pipeline).
///
/// An output-schema mismatch is only logged, not raised: real-world OpenAPI
/// specs (e.g. Atlassian's published Jira Data Center spec) are frequently
/// wrong about response shape — declaring a single object where the API
/// actually returns an array, or an overly narrow `additionalProperties`
/// for a free-form bag of fields — and rejecting an otherwise-successful
/// call over a documentation bug would deny the caller real data it
/// already has in hand. Input validation still hard-fails: those arguments
/// are under the caller's control, not the upstream API's.
///
/// Takes an already-looked-up `EndpointRecord` rather than a `Connection`
/// and an `operation_id` to look up itself: `rusqlite::Connection` isn't
/// `Sync`, so a `&Connection` held across this function's `.await` points
/// (the HTTP call) would make the caller's future non-`Send` — a hard
/// requirement for `#[tool]` methods (Story R6). Callers look the
/// endpoint up (a synchronous, `Connection`-scoped step) before calling
/// this function, not inside it.
pub async fn call_operation(
    endpoint: &EndpointRecord,
    config: &Config,
    auth_manager: &mut AuthManager,
    operation_id: &str,
    args: serde_json::Value,
    request_override: Option<&RequestCredentials>,
) -> anyhow::Result<serde_json::Value> {
    validate_input(&config.api_version, operation_id, &args)?;

    let client = ApiClient::new(config.clone());
    let response = client
        .execute(endpoint, &args, auth_manager, request_override)
        .await?;

    if let Err(err) = validate_output(&config.api_version, operation_id, &response) {
        tracing::warn!(
            operation_id,
            error = %err,
            "response did not match the documented schema; returning it as-is"
        );
    }
    Ok(response)
}