Skip to main content

github_mcp/tools/
search_tool.rs

1// GitHub v3 REST API MCP server — generated by mcpify. Do not hand-edit.
2
3use rusqlite::Connection;
4
5use crate::data::store::search_endpoints;
6use crate::services::embedding_service::embed;
7
8/// Semantic similarity lookup matching a natural-language query against
9/// candidate API operations (PRD §1.5) — so an LLM never needs the full
10/// OpenAPI spec in context to find the right operation.
11pub fn search_operations(
12    conn: &Connection,
13    query: &str,
14    limit: usize,
15) -> anyhow::Result<serde_json::Value> {
16    warn_if_semantic_endpoints_incomplete(conn);
17    let query_embedding = embed(query)?;
18    let results = search_endpoints(conn, &query_embedding, limit)?;
19    Ok(serde_json::to_value(results)?)
20}
21
22/// Cheap diagnostic for the "populated but missing embeddings" failure
23/// mode (Fix 8b): if a store's `semantic_endpoints` row count is below its
24/// `endpoints` row count, some operations can never be found by `search`
25/// even though they exist — warn so an operator investigating an
26/// unexpectedly-empty/sparse result set has a lead, without changing the
27/// success/`[]` return contract for legitimately-empty search results.
28fn warn_if_semantic_endpoints_incomplete(conn: &Connection) {
29    let counts: rusqlite::Result<(i64, i64)> = conn.query_row(
30        "SELECT (SELECT COUNT(*) FROM endpoints), (SELECT COUNT(*) FROM semantic_endpoints)",
31        [],
32        |row| Ok((row.get(0)?, row.get(1)?)),
33    );
34    if let Ok((endpoints_count, semantic_count)) = counts
35        && semantic_count < endpoints_count
36    {
37        tracing::warn!(
38            endpoints_count,
39            semantic_count,
40            "semantic_endpoints is missing rows relative to endpoints; search results may be \
41             incomplete — run the populate-embeddings binary to backfill"
42        );
43    }
44}