UNPKG

kokkai-meeting-mcp-server

Version:

MCP server for Japanese Diet (Kokkai) meeting records API

169 lines (167 loc) 6.92 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import axios from 'axios'; const server = new Server({ name: 'kokkai-server', version: '1.0.0', }); server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'search_kokkai_meetings', description: 'Search Japanese Diet (Kokkai) meeting records using the NDL API', inputSchema: { type: 'object', properties: { any: { type: 'string', description: 'Search term for speech content (e.g., "科学技術" for science and technology)', }, nameOfMeeting: { type: 'string', description: 'Meeting name to search for', }, maximumRecords: { type: 'number', description: 'Maximum number of records to return (up to 100)', maximum: 100, default: 30, }, recordPacking: { type: 'string', enum: ['json', 'xml'], description: 'Output format', default: 'json', }, startRecord: { type: 'number', description: 'Starting position for pagination', minimum: 1, }, sessionFrom: { type: 'number', description: 'Starting session number', minimum: 1, }, sessionTo: { type: 'number', description: 'Ending session number', minimum: 1, }, nameOfHouse: { type: 'string', enum: ['衆議院', '参議院', '両院協議会'], description: 'House name (House of Representatives, House of Councillors, or Joint Committee)', }, issueFrom: { type: 'number', description: 'Starting issue number', minimum: 1, }, issueTo: { type: 'number', description: 'Ending issue number', minimum: 1, }, }, }, }, ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === 'search_kokkai_meetings') { try { const params = request.params.arguments; // Build URL parameters const urlParams = new URLSearchParams(); if (params.any) urlParams.append('any', params.any); if (params.nameOfMeeting) urlParams.append('nameOfMeeting', params.nameOfMeeting); if (params.maximumRecords) urlParams.append('maximumRecords', params.maximumRecords.toString()); if (params.recordPacking) urlParams.append('recordPacking', params.recordPacking); if (params.startRecord) urlParams.append('startRecord', params.startRecord.toString()); if (params.sessionFrom) urlParams.append('sessionFrom', params.sessionFrom.toString()); if (params.sessionTo) urlParams.append('sessionTo', params.sessionTo.toString()); if (params.nameOfHouse) urlParams.append('nameOfHouse', params.nameOfHouse); if (params.issueFrom) urlParams.append('issueFrom', params.issueFrom.toString()); if (params.issueTo) urlParams.append('issueTo', params.issueTo.toString()); const url = `https://kokkai.ndl.go.jp/api/meeting_list?${urlParams.toString()}`; const response = await axios.get(url, { headers: { 'User-Agent': 'kokkai-mcp-server/1.0.0', }, timeout: 30000, }); // Format response for better AI parsing let formattedResponse = ''; if (params.recordPacking === 'json') { formattedResponse = JSON.stringify(response.data, null, 2); } else { // For XML, provide structured summary const xmlString = response.data.toString(); const numberOfRecords = xmlString.match(/<numberOfRecords>(\d+)<\/numberOfRecords>/)?.[1] || '0'; const numberOfReturn = xmlString.match(/<numberOfReturn>(\d+)<\/numberOfReturn>/)?.[1] || '0'; formattedResponse = `Search Results Summary: - Total records found: ${numberOfRecords} - Records returned: ${numberOfReturn} - Search URL: ${url} Raw XML Response: ${xmlString}`; } return { content: [ { type: 'text', text: formattedResponse, }, ], }; } catch (error) { if (axios.isAxiosError(error)) { return { content: [ { type: 'text', text: `Error: ${error.message}\nStatus: ${error.response?.status}\nData: ${error.response?.data}`, }, ], isError: true, }; } return { content: [ { type: 'text', text: `Unexpected error: ${error}`, }, ], isError: true, }; } } throw new Error(`Unknown tool: ${request.params.name}`); }); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('Kokkai MCP server running on stdio'); } main().catch((error) => { console.error('Server failed to start:', error); process.exit(1); });