xai-live-search-mcp
Version:
🔥 xAI Live Search integration for Claude Code via MCP - BEAST MODE!
153 lines • 5.97 kB
JavaScript
import { SearchParametersSchema, } from './types.js';
export class XAIClient {
config;
baseUrl = 'https://api.x.ai/v1/chat/completions';
constructor(config) {
this.config = config;
}
async testConnection() {
try {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
},
body: JSON.stringify({
model: this.config.model,
messages: [
{
role: 'user',
content: 'Test connection - respond with "OK"',
},
],
max_tokens: 10,
temperature: 0,
}),
});
if (!response.ok) {
console.error(`🔥 DEBUG: Test connection failed: ${response.status} ${response.statusText}`);
return false;
}
const data = await response.json();
console.error(`🔥 DEBUG: Test connection successful: ${JSON.stringify(data, null, 2)}`);
return true;
}
catch (error) {
console.error('🔥 DEBUG: Test connection error:', error);
return false;
}
}
async liveSearch(params) {
const searchParameters = this.buildSearchParameters(params);
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
},
body: JSON.stringify({
model: this.config.model,
messages: [
{
role: 'user',
content: `${params.query}`,
},
],
max_tokens: this.config.maxTokens,
temperature: this.config.temperature,
search_parameters: searchParameters,
}),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`xAI API error: ${response.status} ${response.statusText}: ${errorText}`);
}
const data = await response.json();
return {
response: data.choices?.[0]?.message?.content || 'No response generated',
citations: this.extractCitations(data),
usage: data.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },
};
}
async chatWithSearch(params) {
const searchParameters = this.buildSearchParameters({
query: params.message,
maxResults: params.maxSearchResults,
mode: params.searchMode,
sources: params.sources,
returnCitations: params.returnCitations,
fromDate: params.fromDate,
toDate: params.toDate,
country: params.country,
excludedWebsites: params.excludedWebsites,
safeSearch: params.safeSearch,
xHandles: params.xHandles,
rssLinks: params.rssLinks,
});
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
},
body: JSON.stringify({
model: this.config.model,
messages: [
{
role: 'user',
content: params.message,
},
],
max_tokens: this.config.maxTokens,
temperature: this.config.temperature,
search_parameters: searchParameters,
}),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`xAI API error: ${response.status} ${response.statusText}: ${errorText}`);
}
const data = await response.json();
return {
response: data.choices?.[0]?.message?.content || 'No response generated',
citations: params.returnCitations ? this.extractCitations(data) : [],
usage: data.usage || { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },
};
}
buildSearchParameters(params) {
const searchSources = params.sources?.map(sourceType => ({
type: sourceType,
country: params.country,
excluded_websites: params.excludedWebsites,
safe_search: params.safeSearch,
x_handles: params.xHandles,
links: params.rssLinks,
})) || [{ type: 'web' }];
const searchParams = {
mode: params.mode || 'on', // Changed from 'auto' to 'on' to force search execution
sources: searchSources,
return_citations: params.returnCitations ?? true,
from_date: params.fromDate,
to_date: params.toDate,
max_search_results: Math.min(params.maxResults || 20, 50),
};
return SearchParametersSchema.parse(searchParams);
}
extractCitations(data) {
// Extract citations from the response
// xAI API may include citations in various formats
const citations = [];
if (data.citations) {
citations.push(...data.citations);
}
if (data.sources) {
citations.push(...data.sources.map((source) => source.url || source.title));
}
if (data.choices?.[0]?.message?.citations) {
citations.push(...data.choices[0].message.citations);
}
return citations.filter(Boolean);
}
}
//# sourceMappingURL=xai-client.js.map