searchMeetingsWithSpeechText
Search Japanese Diet meeting records with full speech transcripts using keywords, dates, speakers, or meeting details to analyze parliamentary proceedings.
Instructions
Searches for meetings and includes the full text of ALL speeches within those meetings from the Kokkai API (会議単位出力). Returns meeting info and all speech texts. Max 10 records.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| startRecord | No | Start position for retrieving search results (1-based). Default is 1. | |
| nameOfHouse | No | Name of the House (e.g., '衆議院' for House of Representatives, '参議院' for House of Councillors). '両院' and '両院協議会' yield the same results. | |
| nameOfMeeting | No | Name of the meeting (e.g., plenary session, committee). Partial match. Multiple terms separated by space for OR search. | |
| any | No | Keywords to search in speech content. Partial match. Multiple terms separated by space for AND search. | |
| speaker | No | Speaker's name. Partial match. Multiple names separated by space for OR search. | |
| from | No | Start date for meeting search (YYYY-MM-DD). Default '0000-01-01'. | |
| until | No | End date for meeting search (YYYY-MM-DD). Default '9999-12-31'. | |
| supplementAndAppendix | No | Limit search to supplements and appendices. Default false. | |
| contentsAndIndex | No | Limit search to table of contents and index. Default false. | |
| searchRange | No | Specifies where to search for keywords from 'any' parameter: '冒頭' (opening), '本文' (body), or '冒頭・本文' (both). Default '冒頭・本文'. | |
| closing | No | Limit search to meetings held during recess. Default false. | |
| speechNumber | No | Exact match for speech number (e.g., 10). | |
| speakerPosition | No | Speaker's position/title. Partial match. | |
| speakerGroup | No | Speaker's affiliated political group. Partial match. | |
| speakerRole | No | Speaker's role: '証人' (witness), '参考人' (expert witness/referential speaker), '公述人' (public speaker). | |
| speechID | No | Unique ID for a speech (format: issueID_paddedSpeechNumber, e.g., '100105254X00119470520_000'). Exact match. | |
| issueID | No | Unique ID for a meeting record (21 alphanumeric characters, e.g., '100105254X00119470520'). Exact match. | |
| sessionFrom | No | Starting Diet session number (up to 3 digits). | |
| sessionTo | No | Ending Diet session number (up to 3 digits). | |
| issueFrom | No | Starting issue number (up to 3 digits, 0 for TOC/index/appendix/supplement). | |
| issueTo | No | Ending issue number (up to 3 digits, 0 for TOC/index/appendix/supplement). | |
| maximumRecords | No | Maximum number of records to retrieve (1-10) for meetings with speech text. Default is 3. |
Implementation Reference
- src/index.ts:256-276 (handler)Handler function for the 'searchMeetingsWithSpeechText' tool. Invokes the private _callKokkaiApi helper with the 'meeting' endpoint, handles errors by returning formatted text, and returns the API response as pretty-printed JSON text.async (params) => { const result = await this._callKokkaiApi("meeting", params); if (result.error) { return { content: [ { type: "text", text: `Error fetching meetings with speech text: ${result.message} ${result.details || ""}`, }, ], }; } return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; }
- src/index.ts:244-255 (schema)Tool-specific input schema for 'searchMeetingsWithSpeechText', extending the common Kokkai search parameters with a maximumRecords field limited to 1-10.{ ...kokkaiCommonSearchParams, maximumRecords: z .number() .int() .min(1) .max(10) .optional() .describe( "Maximum number of records to retrieve (1-10) for meetings with speech text. Default is 3." ), },
- src/index.ts:241-277 (registration)MCP server tool registration for 'searchMeetingsWithSpeechText', including name, description, input schema, and inline handler function.this.server.tool( "searchMeetingsWithSpeechText", "Searches for meetings and includes the full text of ALL speeches within those meetings from the Kokkai API (会議単位出力). Returns meeting info and all speech texts. Max 10 records.", { ...kokkaiCommonSearchParams, maximumRecords: z .number() .int() .min(1) .max(10) .optional() .describe( "Maximum number of records to retrieve (1-10) for meetings with speech text. Default is 3." ), }, async (params) => { const result = await this._callKokkaiApi("meeting", params); if (result.error) { return { content: [ { type: "text", text: `Error fetching meetings with speech text: ${result.message} ${result.details || ""}`, }, ], }; } return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } );
- src/index.ts:146-197 (helper)Core private helper method used by the tool handler to construct query parameters, make HTTP requests to the Kokkai API, parse JSON responses, and handle both API and network errors uniformly.private async _callKokkaiApi( endpoint: string, params: Record<string, any> ): Promise<any> { const queryParams = new URLSearchParams(); for (const key in params) { if (params[key] !== undefined && params[key] !== null) { queryParams.append(key, String(params[key])); } } queryParams.append("recordPacking", "json"); // Always request JSON const url = `${KOKKAI_API_BASE_URL}/${endpoint}?${queryParams.toString()}`; console.log(`Calling Kokkai API: ${url}`); try { const response = await fetch(url, { headers: { "User-Agent": "MCP Agent Kokkai Client/1.0", }, }); const responseData = (await response.json()) as any; if (!response.ok) { const errorMessage = responseData.message || "Unknown API error"; const errorDetails = responseData.details ? responseData.details.join("; ") : ""; console.error( `Kokkai API Error: ${errorMessage} ${errorDetails}`, responseData ); return { error: true, status: response.status, message: errorMessage, details: errorDetails, rawResponse: responseData, }; } return responseData; } catch (error: any) { console.error("Network or parsing error calling Kokkai API:", error); return { error: true, message: error.message || "Failed to fetch or parse API response.", }; } }
- src/index.ts:6-134 (schema)Shared Zod schema definitions for common Kokkai API search parameters, spread into the tool's input schema.const kokkaiCommonSearchParams = { startRecord: z .number() .int() .min(1) .optional() .describe( "Start position for retrieving search results (1-based). Default is 1." ), nameOfHouse: z .enum(["衆議院", "参議院", "両院", "両院協議会"]) .optional() .describe( "Name of the House (e.g., '衆議院' for House of Representatives, '参議院' for House of Councillors). '両院' and '両院協議会' yield the same results." ), nameOfMeeting: z .string() .optional() .describe( "Name of the meeting (e.g., plenary session, committee). Partial match. Multiple terms separated by space for OR search." ), any: z .string() .optional() .describe( "Keywords to search in speech content. Partial match. Multiple terms separated by space for AND search." ), speaker: z .string() .optional() .describe( "Speaker's name. Partial match. Multiple names separated by space for OR search." ), from: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format") .optional() .describe( "Start date for meeting search (YYYY-MM-DD). Default '0000-01-01'." ), until: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format") .optional() .describe( "End date for meeting search (YYYY-MM-DD). Default '9999-12-31'." ), supplementAndAppendix: z .boolean() .optional() .describe( "Limit search to supplements and appendices. Default false." ), contentsAndIndex: z .boolean() .optional() .describe("Limit search to table of contents and index. Default false."), searchRange: z .enum(["冒頭", "本文", "冒頭・本文"]) .optional() .describe( "Specifies where to search for keywords from 'any' parameter: '冒頭' (opening), '本文' (body), or '冒頭・本文' (both). Default '冒頭・本文'." ), closing: z .boolean() .optional() .describe("Limit search to meetings held during recess. Default false."), speechNumber: z .number() .int() .nonnegative() .optional() .describe("Exact match for speech number (e.g., 10)."), speakerPosition: z .string() .optional() .describe("Speaker's position/title. Partial match."), speakerGroup: z .string() .optional() .describe("Speaker's affiliated political group. Partial match."), speakerRole: z .enum(["証人", "参考人", "公述人"]) .optional() .describe( "Speaker's role: '証人' (witness), '参考人' (expert witness/referential speaker), '公述人' (public speaker)." ), speechID: z .string() .optional() .describe( "Unique ID for a speech (format: issueID_paddedSpeechNumber, e.g., '100105254X00119470520_000'). Exact match." ), issueID: z .string() .optional() .describe( "Unique ID for a meeting record (21 alphanumeric characters, e.g., '100105254X00119470520'). Exact match." ), sessionFrom: z .number() .int() .positive() .optional() .describe("Starting Diet session number (up to 3 digits)."), sessionTo: z .number() .int() .positive() .optional() .describe("Ending Diet session number (up to 3 digits)."), issueFrom: z .number() .int() .nonnegative() .optional() .describe( "Starting issue number (up to 3 digits, 0 for TOC/index/appendix/supplement)." ), issueTo: z .number() .int() .nonnegative() .optional() .describe( "Ending issue number (up to 3 digits, 0 for TOC/index/appendix/supplement)." ), // recordPacking is handled internally, always 'json' };