kagi_summarizer
Generate concise summaries or bullet-point takeaways from any document, video, or audio by providing a URL. Supports multiple languages and integrates with Kagi's API for efficient content extraction.
Instructions
Summarize content from a URL using the Kagi Summarizer API. The Summarizer can summarize any document type (text webpage, video, audio, etc.)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| summary_type | No | Type of summary to produce. Options are 'summary' for paragraph prose and 'takeaway' for a bulleted list of key points. | summary |
| target_language | No | Desired output language using language codes (e.g., 'EN' for English). If not specified, the document's original language influences the output. | |
| url | Yes | A URL to a document to summarize. |
Input Schema (JSON Schema)
{
"properties": {
"summary_type": {
"default": "summary",
"description": "Type of summary to produce. Options are 'summary' for paragraph prose and 'takeaway' for a bulleted list of key points.",
"enum": [
"summary",
"takeaway"
],
"type": "string"
},
"target_language": {
"description": "Desired output language using language codes (e.g., 'EN' for English). If not specified, the document's original language influences the output.",
"type": "string"
},
"url": {
"description": "A URL to a document to summarize.",
"type": "string"
}
},
"required": [
"url"
],
"type": "object"
}
Implementation Reference
- src/index.ts:163-212 (handler)Handler for the 'kagi_summarizer' tool. Validates parameters, determines the summarization engine, calls the KagiClient's summarize method, and formats the response.if (name === 'kagi_summarizer') { const url = args?.url as string | undefined; if (!url) { throw new McpError( ErrorCode.InvalidParams, 'Summarizer called with no URL.' ); } const summaryType = args?.summary_type as 'summary' | 'takeaway' | undefined; const targetLanguage = args?.target_language as string | undefined; const engine = process.env.KAGI_SUMMARIZER_ENGINE || 'cecil'; const validEngines = ['cecil', 'agnes', 'daphne', 'muriel']; if (!validEngines.includes(engine)) { throw new McpError( ErrorCode.InvalidParams, `Summarizer configured incorrectly, invalid summarization engine set: ${engine}. Must be one of the following: ${validEngines.join(', ')}` ); } try { const summary = await kagiClient.summarize({ url, engine: engine as 'cecil' | 'agnes' | 'daphne' | 'muriel', summary_type: summaryType, target_language: targetLanguage, }); return { content: [ { type: 'text', text: summary.data.output, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }
- src/index.ts:44-67 (schema)Tool schema definition including name, description, and input schema for the kagi_summarizer tool.const SUMMARIZER_TOOL: Tool = { name: 'kagi_summarizer', description: 'Summarize content from a URL using the Kagi Summarizer API. The Summarizer can summarize any document type (text webpage, video, audio, etc.)', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'A URL to a document to summarize.', }, summary_type: { type: 'string', enum: ['summary', 'takeaway'], default: 'summary', description: 'Type of summary to produce. Options are \'summary\' for paragraph prose and \'takeaway\' for a bulleted list of key points.', }, target_language: { type: 'string', description: 'Desired output language using language codes (e.g., \'EN\' for English). If not specified, the document\'s original language influences the output.', }, }, required: ['url'], }, };
- src/index.ts:69-73 (registration)Registration of the kagi_summarizer tool by including it in the list returned by ListToolsRequestSchema handler.server.setRequestHandler(ListToolsRequestSchema, async (): Promise<ListToolsResult> => { return { tools: [SEARCH_TOOL, SUMMARIZER_TOOL], }; });
- src/kagi-client.ts:84-120 (helper)The KagiClient.summarize method that makes the API call to Kagi's /summarize endpoint and handles the response and errors.async summarize(options: SummarizerOptions): Promise<SummarizerResponse> { try { const response = await this.axios.post('/summarize', { url: options.url, engine: options.engine || 'cecil', summary_type: options.summary_type, target_language: options.target_language, }); return response.data; } catch (error) { if (axios.isAxiosError(error)) { let errorMessage = 'Unknown error'; if (error.response?.data) { if (typeof error.response.data === 'string') { errorMessage = error.response.data; } else if (error.response.data.error) { // Kagi API returns error as an array if (Array.isArray(error.response.data.error)) { errorMessage = error.response.data.error.map((e: any) => e.msg).join('; '); } else { errorMessage = error.response.data.error; } } else if (error.response.data.message) { errorMessage = error.response.data.message; } else { errorMessage = JSON.stringify(error.response.data); } } else { errorMessage = error.response?.statusText || error.message; } const statusCode = error.response?.status; throw new Error(`Kagi summarizer error (${statusCode}): ${errorMessage}`); } throw error; } }