dsh-search-mcp/lib/catalog.js
oliver d5c4d2006c Publish dsh-search-mcp fork for newer DSH and Bailian WebSearch MCP.
Based on gxpppp/dsh-search-mcp; includes DSH web settings fixes, Clash fake-IP URL policy, and Bailian default server patch.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-12 08:51:32 +08:00

137 lines
4.2 KiB
JavaScript

/**
* Search-MCP provider catalog.
*
* Known providers are intentionally connection-opaque to Settings clients: the
* host owns their endpoint, transport, authentication contract and tool name.
* `custom` is the only kind whose connection details come from the user.
*/
export const SEARCH_MCP_CATALOG = {
tavily: {
transport: 'http',
url: 'https://mcp.tavily.com/mcp/',
authStyle: 'query',
authParam: 'tavilyApiKey',
toolName: 'tavily_search',
countArg: 'max_results',
minResults: 5,
maxResultsLimit: 20,
apiKeyEnv: 'TAVILY_API_KEY',
needsKey: true,
},
brave: {
transport: 'stdio',
command: 'npx',
args: ['-y', '@brave/brave-search-mcp-server@2.1.3'],
authStyle: 'env',
authParam: 'BRAVE_API_KEY',
toolName: 'brave_web_search',
countArg: 'count',
minResults: 1,
maxResultsLimit: 20,
apiKeyEnv: 'BRAVE_API_KEY',
needsKey: true,
},
exa: {
transport: 'http',
url: 'https://mcp.exa.ai/mcp',
authStyle: 'header',
authParam: 'x-api-key',
toolName: 'web_search_exa',
countArg: 'numResults',
apiKeyEnv: 'EXA_API_KEY',
needsKey: true,
},
perplexity: {
transport: 'http',
url: 'https://api.perplexity.ai/mcp',
authStyle: 'header',
authParam: 'Authorization',
authPrefix: 'Bearer ',
toolName: 'perplexity_search',
countArg: 'max_results',
minResults: 1,
maxResultsLimit: 20,
apiKeyEnv: 'PERPLEXITY_API_KEY',
needsKey: true,
},
duckduckgo: {
transport: 'stdio',
command: 'npx',
args: ['-y', 'duckduckgo-mcp-server@0.1.2'],
authStyle: 'env',
authParam: '',
toolName: 'duckduckgo_web_search',
countArg: 'count',
minResults: 1,
maxResultsLimit: 20,
needsKey: false,
},
custom: {
transport: 'http',
url: '',
authStyle: 'query',
authParam: '',
authPrefix: '',
toolName: '',
countArg: '',
needsKey: false,
},
};
/** The provider ids offered in the settings UI. */
export const KNOWN_KINDS = Object.keys(SEARCH_MCP_CATALOG);
export function clampSearchResults(server, value) {
const minimum = server.minResults ?? 1;
const maximum = server.maxResultsLimit ?? value;
return Math.min(maximum, Math.max(minimum, value));
}
/** Resolve a stored entry without allowing known-provider connection overrides. */
export function resolveServer(server) {
const kind = typeof server?.kind === 'string' && Object.hasOwn(SEARCH_MCP_CATALOG, server.kind)
? server.kind
: 'custom';
const preset = SEARCH_MCP_CATALOG[kind];
if (kind !== 'custom') {
return {
id: typeof server.id === 'string' ? server.id : '',
kind,
apiKey: typeof server.apiKey === 'string' ? server.apiKey : undefined,
apiKeyEnv: typeof server.apiKeyEnv === 'string' ? server.apiKeyEnv : '',
maxResults: server.maxResults,
transport: preset.transport,
url: preset.url ?? '',
command: preset.command ?? '',
args: [...(preset.args ?? [])],
authStyle: preset.authStyle ?? '',
authParam: preset.authParam ?? '',
authPrefix: preset.authPrefix ?? '',
toolName: preset.toolName ?? '',
countArg: preset.countArg ?? '',
minResults: preset.minResults,
maxResultsLimit: preset.maxResultsLimit,
needsKey: preset.needsKey ?? false,
};
}
return {
id: typeof server.id === 'string' ? server.id : '',
kind: 'custom',
apiKey: typeof server.apiKey === 'string' ? server.apiKey : undefined,
apiKeyEnv: typeof server.apiKeyEnv === 'string' ? server.apiKeyEnv : '',
maxResults: server.maxResults,
transport: server.transport || preset.transport || 'http',
url: server.url || preset.url || '',
command: server.command || preset.command || '',
args: Array.isArray(server.args) ? [...server.args] : [...(preset.args ?? [])],
authStyle: server.authStyle || preset.authStyle || '',
authParam: server.authParam || preset.authParam || '',
authPrefix: server.authPrefix || preset.authPrefix || '',
toolName: server.toolName || preset.toolName || '',
countArg: preset.countArg || '',
minResults: preset.minResults,
maxResultsLimit: preset.maxResultsLimit,
needsKey: preset.needsKey ?? false,
};
}