sqlserver-mcp 0.5.3

SQL Server 2025/2022/2019/2017 - master/msdb/sandbox combined catalog MCP server, generated by mcpify.
Documentation
// SQL Server 2025 - master/msdb/sandbox combined catalog MCP server — generated by mcpify. Do not hand-edit.

use rusqlite::Connection;

use crate::data::store::search_endpoints;
use crate::services::embedding_service::embed;

/// Cheap diagnostic: compares `semantic_endpoints` row count against
/// `endpoints` row count for the store behind `conn`. A store can end up
/// with `endpoints` rows but no matching `semantic_endpoints` rows if the
/// `populate-embeddings` step silently skipped or partially failed some
/// rows — this surfaces that as a warning without changing the
/// success/`[]` return contract for legitimately-empty search results.
fn warn_if_embeddings_incomplete(conn: &Connection) {
    let counts: rusqlite::Result<(i64, i64)> = conn.query_row(
        "SELECT (SELECT COUNT(*) FROM endpoints), (SELECT COUNT(*) FROM semantic_endpoints)",
        [],
        |row| Ok((row.get(0)?, row.get(1)?)),
    );
    if let Ok((endpoints_count, semantic_count)) = counts
        && semantic_count < endpoints_count
    {
        tracing::warn!(
            endpoints_count,
            semantic_count,
            "semantic_endpoints is missing {} row(s) compared to endpoints — search results \
             may be incomplete; re-run populate-embeddings for this store",
            endpoints_count - semantic_count
        );
    }
}

/// Semantic similarity lookup matching a natural-language query against
/// candidate API operations (PRD §1.5) — so an LLM never needs the full
/// OpenAPI spec in context to find the right operation.
pub fn search_operations(
    conn: &Connection,
    query: &str,
    limit: usize,
) -> anyhow::Result<serde_json::Value> {
    warn_if_embeddings_incomplete(conn);
    let query_embedding = embed(query)?;
    let results = search_endpoints(conn, &query_embedding, limit)?;
    Ok(serde_json::to_value(results)?)
}