sourcegraph-mcp-server
Version:
A Model Context Protocol (MCP) server that connects AI assistants to Sourcegraph code search with natural language capabilities
192 lines (191 loc) • 5.9 kB
JavaScript
;
/**
* Natural language processing for search queries
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.naturalLanguageSearch = void 0;
const axios_1 = __importDefault(require("axios"));
const formatter_1 = require("../utils/formatter");
/**
* Executes a search based on a natural language query
*/
async function naturalLanguageSearch(naturalQuery, sourcegraphConfig) {
try {
// Extract structured query parameters from natural language using LLM
const { type = 'file', query, author, after, repos = [], originalQuery } = await (0, formatter_1.analyzeQuery)(naturalQuery);
// For clarity in logs, show the transformation
console.log(`Natural query: "${naturalQuery}" → Sourcegraph: "${query}" (type: ${type})`);
// Base search query
let searchQuery = query;
// Add type filter
searchQuery += ` type:${type}`;
// Add author filter for commit and diff searches
if (author && (type === 'commit' || type === 'diff')) {
searchQuery += ` author:${author}`;
}
// Add date filter
if (after && (type === 'commit' || type === 'diff')) {
searchQuery += ` after:${after}`;
}
// Add repository filters
if (repos.length > 0) {
const repoFilters = repos.map(repo => {
// If it looks like a GitHub repo (contains a slash), format accordingly
if (repo.includes('/')) {
return `repo:^github\\.com/${repo}$`;
}
// Otherwise use as-is
return `repo:${repo}`;
});
searchQuery += ` ${repoFilters.join(' ')}`;
}
// Add result count limit
searchQuery += ' count:20';
// Select the appropriate GraphQL query based on search type
let graphqlQuery;
if (type === 'file') {
graphqlQuery = getFileSearchQuery();
}
else if (type === 'commit') {
graphqlQuery = getCommitSearchQuery();
}
else if (type === 'diff') {
graphqlQuery = getDiffSearchQuery();
}
else {
throw new Error(`Unsupported search type: ${type}`);
}
// Headers for Sourcegraph API
const headers = {
'Authorization': `token ${sourcegraphConfig.token}`,
'Content-Type': 'application/json'
};
// Make the request to Sourcegraph API
const response = await axios_1.default.post(`${sourcegraphConfig.url}/.api/graphql`, { query: graphqlQuery, variables: { query: searchQuery } }, { headers });
// Check for API errors
if (response.data.errors) {
return {
content: [{
type: "text",
text: `Sourcegraph API Error: ${JSON.stringify(response.data.errors)}`
}],
isError: true
};
}
// Prepare results for formatting
const results = response.data.data.search.results;
// Generate a natural language response
const naturalResponse = (0, formatter_1.formatSearchResults)(results, { query, type });
return {
content: [{
type: "text",
text: naturalResponse
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: `Error processing natural language search: ${error.message || 'Unknown error'}`
}],
isError: true
};
}
}
exports.naturalLanguageSearch = naturalLanguageSearch;
// GraphQL query for file search
function getFileSearchQuery() {
return `
query FileSearch($query: String!) {
search(query: $query, version: V3) {
results {
matchCount
results {
__typename
... on FileMatch {
repository { name }
file { path }
lineMatches {
lineNumber
preview
}
}
}
}
}
}
`;
}
// GraphQL query for commit search
function getCommitSearchQuery() {
return `
query CommitSearch($query: String!) {
search(query: $query, version: V3) {
results {
matchCount
results {
__typename
... on CommitSearchResult {
commit {
oid
message
author {
person {
name
email
}
date
}
repository { name }
}
}
}
}
}
}
`;
}
// GraphQL query for diff search
function getDiffSearchQuery() {
return `
query DiffSearch($query: String!) {
search(query: $query, version: V3) {
results {
matchCount
results {
__typename
... on CommitSearchResult {
commit {
oid
message
author {
person {
name
email
}
date
}
repository { name }
}
diff {
fileDiffs {
oldPath
newPath
hunks {
body
oldRange { start, lines }
newRange { start, lines }
}
}
}
}
}
}
}
}
`;
}