import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import {
debugLog,
getSearchcraftConfig,
performSearchcraftRequest,
} from "../../../helpers.js";
import type { SearchcraftQuery } from "../../../types.js";
/**
* Tool: get_search_index_schema
*
* This tool provides an interface for getting the current search index schema, including schema fields and facet information.
* Gives the MCP Client additional context about how to construct search queries.
*
* @param server
*/
export const registerGetPrelimSearchDataSchema = (server: McpServer) => {
server.tool(
"get_prelim_search_data",
"Gets the schema fields and facet information for the search index in order to understand available fields and facet information for constructing a search query.",
{
index: z
.string()
.describe("The name of the index to get search data on."),
readKey: z.string().describe("A read key for this index."),
},
async ({ index, readKey }) => {
debugLog("[Tool Call] get-search-index-schema");
const config = getSearchcraftConfig();
if (config.error) {
return config.error;
}
const { endpointUrl: baseUrl } = config;
if (!readKey) {
return {
content: [
{
type: "text",
text: "❌ Error: READ_KEY environment variable is required",
},
],
isError: true,
};
}
// Get Schema Fields for this Index
const schemaFieldEndpoint = `${baseUrl}/index/${index}`;
const schemaFieldResponse = await fetch(schemaFieldEndpoint, {
headers: {
Authorization: readKey || "",
},
});
const schemaFieldResponseText = await schemaFieldResponse.text();
// Get the top-level Facets for this index if any exist
// {"limit":1, "query":{"exact":{"ctx":"*"}}}
const initialQuery: SearchcraftQuery = {
limit: 1,
query: [{ exact: { ctx: "*" } }],
};
const endpoint = `${baseUrl.replace(/\/$/, "")}/index/${index}/search`;
const initialQueryResponse = await performSearchcraftRequest(
endpoint,
initialQuery,
readKey,
);
let initialFacetsText: string | undefined;
if (initialQueryResponse.data.facets) {
initialFacetsText = JSON.stringify(
initialQueryResponse.data.facets,
);
}
const result: CallToolResult = {
content: [
{
type: "resource",
resource: {
uri: `searchcraft://schema-fields/${Date.now()}`,
mimeType: "application/json",
text: schemaFieldResponseText,
},
},
],
};
if (initialFacetsText) {
result.content.push({
type: "resource",
resource: {
uri: `searchcraft://facets/${Date.now()}`,
mimeType: "application/json",
text: initialFacetsText,
},
});
} else {
result.content.push({
type: "text",
text: "There are no facet types associated with this index. Do not include facetFilters with your search.",
});
}
result.content.push({
type: "text",
text: "The preliminary search data has been retrieved. This data represents schema fields and facets for constructing search queries. You can now begin querying for search results.",
});
return result;
},
);
};