Skip to main content
Glama
egegungordu

Kokkai Minutes MCP Agent

by egegungordu

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
NameRequiredDescriptionDefault
startRecordNoStart position for retrieving search results (1-based). Default is 1.
nameOfHouseNoName of the House (e.g., '衆議院' for House of Representatives, '参議院' for House of Councillors). '両院' and '両院協議会' yield the same results.
nameOfMeetingNoName of the meeting (e.g., plenary session, committee). Partial match. Multiple terms separated by space for OR search.
anyNoKeywords to search in speech content. Partial match. Multiple terms separated by space for AND search.
speakerNoSpeaker's name. Partial match. Multiple names separated by space for OR search.
fromNoStart date for meeting search (YYYY-MM-DD). Default '0000-01-01'.
untilNoEnd date for meeting search (YYYY-MM-DD). Default '9999-12-31'.
supplementAndAppendixNoLimit search to supplements and appendices. Default false.
contentsAndIndexNoLimit search to table of contents and index. Default false.
searchRangeNoSpecifies where to search for keywords from 'any' parameter: '冒頭' (opening), '本文' (body), or '冒頭・本文' (both). Default '冒頭・本文'.
closingNoLimit search to meetings held during recess. Default false.
speechNumberNoExact match for speech number (e.g., 10).
speakerPositionNoSpeaker's position/title. Partial match.
speakerGroupNoSpeaker's affiliated political group. Partial match.
speakerRoleNoSpeaker's role: '証人' (witness), '参考人' (expert witness/referential speaker), '公述人' (public speaker).
speechIDNoUnique ID for a speech (format: issueID_paddedSpeechNumber, e.g., '100105254X00119470520_000'). Exact match.
issueIDNoUnique ID for a meeting record (21 alphanumeric characters, e.g., '100105254X00119470520'). Exact match.
sessionFromNoStarting Diet session number (up to 3 digits).
sessionToNoEnding Diet session number (up to 3 digits).
issueFromNoStarting issue number (up to 3 digits, 0 for TOC/index/appendix/supplement).
issueToNoEnding issue number (up to 3 digits, 0 for TOC/index/appendix/supplement).
maximumRecordsNoMaximum number of records to retrieve (1-10) for meetings with speech text. Default is 3.

Implementation Reference

  • 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),
          },
        ],
      };
    }
  • 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),
            },
          ],
        };
      }
    );
  • 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.",
        };
      }
    }
  • 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'
    };
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It adds some context: it specifies the source (Kokkai API), the output includes meeting info and all speech texts, and a max record limit of 10. However, it lacks details on permissions, rate limits, pagination (beyond the 'startRecord' parameter), error handling, or the exact format of returned data. For a tool with 22 parameters and no annotations, this leaves significant gaps in understanding its behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise and front-loaded, consisting of only two sentences that efficiently convey the tool's purpose, scope, and key constraint (max 10 records). Every word earns its place, with no redundant or vague language, making it easy for an AI agent to quickly understand the tool's core functionality.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (22 parameters, no annotations, no output schema), the description is incomplete. It adequately states the purpose and output scope but lacks details on behavioral aspects like error handling, data format, or usage constraints beyond the record limit. While it meets the minimum for clarity and conciseness, it does not provide enough context for an agent to fully anticipate how to handle results or potential issues, especially with such a rich parameter set.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, meaning all parameters are documented in the schema itself. The description does not add any specific parameter semantics beyond what the schema provides, such as explaining interactions between parameters or providing examples. Since the schema does the heavy lifting, the baseline score of 3 is appropriate, as the description does not compensate with additional insights but also does not detract.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Searches for meetings'), the resource ('meetings and includes the full text of ALL speeches'), the source ('from the Kokkai API'), and the scope ('Max 10 records'). It distinguishes from sibling tools by specifying it returns speech texts, unlike 'searchMeetingList' (likely just meeting metadata) and 'searchSpeeches' (likely focused on speeches rather than meetings with speeches).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool: when you need meeting information along with all speech texts, with a limit of 10 records. It implies usage by specifying the output includes speech texts, which differentiates it from siblings. However, it does not explicitly state when not to use it or name alternatives, such as using 'searchMeetingList' if only meeting metadata is needed or 'searchSpeeches' for speech-focused searches.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/egegungordu/kokkaikaigiroku-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server