/**
* HTTP client for Searchfox API
*/
import type { SearchfoxResponse } from "../types.js";
import { SEARCHFOX_BASE_URL } from "../constants.js";
export class SearchfoxClient {
private userAgent: string;
constructor() {
// Construct user-agent with optional magic word from environment
const magicWord =
process.env.SEARCHFOX_MCP_MAGIC_WORD || "sésame ouvre toi";
this.userAgent = `searchfox-mcp/1.0.0 (+https://github.com/canova/searchfox-mcp; ${magicWord})`;
}
/**
* Perform a search request to Searchfox
*/
async search(
repo: string,
query: string,
options?: {
case?: boolean;
regexp?: boolean;
path?: string;
}
): Promise<SearchfoxResponse> {
const searchParams = new URLSearchParams({
q: query,
});
if (options?.case) {
searchParams.append("case", "true");
}
if (options?.regexp) {
searchParams.append("regexp", "true");
}
if (options?.path) {
searchParams.append("path", options.path);
}
const url = `${SEARCHFOX_BASE_URL}/${repo}/search?${searchParams}`;
const response = await fetch(url, {
headers: {
Accept: "application/json",
"User-Agent": this.userAgent,
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return (await response.json()) as SearchfoxResponse;
}
}
// Singleton instance
export const searchfoxClient = new SearchfoxClient();