get_overview
Retrieve a paginated overview of recent Dutch parliamentary activities, including latest documents and MPs celebrating birthdays today. Use structured data for research or further exploration.
Instructions
Provides a comprehensive overview of recent parliamentary activities, including the most recent documents and MPs celebrating birthdays today. This is the ideal starting point for any parliamentary data exploration. The response contains structured data with two main sections: 'recentDocuments' (listing the latest parliamentary documents with their IDs, titles, types, dates, and URLs) and 'birthdays' (listing MPs celebrating birthdays today). The results are paginated with 10 documents per page, and you can navigate through pages using the 'page' parameter. The tool can be used iteratively to retrieve subsequent pages of results - first call with page=1, then check the pagination.hasMoreDocuments field in the response, and if true, call again with page=2, and so on. This allows you to 'scroll' through all available documents when needed. The response includes pagination information showing the current page, whether more documents are available, and the total number of documents retrieved. Use this tool first when a user asks for general information about recent parliamentary activities or needs a starting point for research. After getting this overview, you can use other tools like 'get_document_details' to retrieve more information about specific documents, 'search_tk' to find documents on specific topics, or 'get_photo' to retrieve photos of MPs mentioned in the birthdays section.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for paginated results (default: 1). Each page contains 10 documents. |
Implementation Reference
- src/index.ts:26-55 (registration)MCP tool registration for 'get_overview', defining the tool name, long description, input schema (optional page number), and thin async handler that validates input and calls apiService.getOverview() to execute the logic, returning formatted text content.mcp.tool( "get_overview", "Provides a comprehensive overview of recent parliamentary activities, including the most recent documents and MPs celebrating birthdays today. The response contains structured data with two main sections: 'recentDocuments' (listing the latest parliamentary documents with their IDs, titles, types, dates, and URLs) and 'birthdays' (listing MPs celebrating birthdays today). The results are paginated with 10 documents per page. The tool supports iterative pagination - check the pagination.hasMoreDocuments field in the response to determine if additional pages are available. The response includes pagination information showing the current page, whether more documents are available, and the total number of documents retrieved. Applicable when general information about recent parliamentary activities is needed.", { page: z.number().optional().describe("Page number for paginated results (default: 1). Each page contains 10 documents.") }, async ({ page = 1 }) => { try { // Validate page number const validatedPage = Math.max(1, page); // Get overview data with pagination const overview = await apiService.getOverview(validatedPage); return { content: [{ type: "text", text: JSON.stringify(overview, null, 2) }] }; } catch (error: any) { return { content: [{ type: "text", text: `Error fetching overview: ${error.message || 'Unknown error'}` }] }; } } );
- src/services/api.ts:558-583 (handler)Primary handler function in ApiService class that fetches the main '/' HTML page, extracts structured overview data (recent documents and birthdays) using the html-parser utility with pagination support, and handles errors by returning empty data with error message.async getOverview(page: number = 1): Promise<any> { try { // Validate page number const validatedPage = Math.max(1, page); // Fetch the HTML of the main page const html = await this.fetchHtml("/"); // Extract overview data from the HTML with pagination const overviewData = extractOverviewFromHtml(html, BASE_URL, validatedPage); return overviewData; } catch (error) { return { recentDocuments: [], birthdays: [], lastUpdated: new Date().toISOString(), pagination: { currentPage: page, hasMoreDocuments: false, totalDocumentsRetrieved: 0 }, error: (error as Error).message || 'Unknown error' }; } }
- src/index.ts:29-31 (schema)Zod input schema for the get_overview tool, defining an optional 'page' parameter (number) for pagination with descriptive documentation.{ page: z.number().optional().describe("Page number for paginated results (default: 1). Each page contains 10 documents.") },
- src/utils/html-parser.ts:646-809 (helper)Key helper utility that parses raw HTML from the main tkconv page to extract paginated recent documents (id, title, type, date, etc.) from table rows and today's birthdays from special section, returning structured OverviewData interface with pagination metadata. Used by apiService.getOverview.export function extractOverviewFromHtml(html: string, baseUrl: string, page: number = 1): OverviewData { if (!html) { return { recentDocuments: [], birthdays: [], lastUpdated: new Date().toISOString(), pagination: { currentPage: 1, hasMoreDocuments: false, totalDocumentsRetrieved: 0 } }; } const recentDocuments: RecentDocument[] = []; const birthdays: BirthdayPerson[] = []; let lastUpdated = new Date().toISOString(); // Extract the table containing recent documents const tableRegex = /<table[^>]*>[\s\S]*?<tbody>([\s\S]*?)<\/tbody>/i; const tableMatch = html.match(tableRegex); if (tableMatch && tableMatch[1]) { const tableContent = tableMatch[1]; // Extract each row (document) from the table const rowRegex = /<tr[^>]*>([\s\S]*?)<\/tr>/gi; let rowMatch; while ((rowMatch = rowRegex.exec(tableContent)) !== null) { if (!rowMatch[1]) continue; const rowContent = rowMatch[1]; // Extract cells const cellRegex = /<td[^>]*>([\s\S]*?)<\/td>/gi; const cells: string[] = []; let cellMatch; while ((cellMatch = cellRegex.exec(rowContent)) !== null) { if (cellMatch[1]) { cells.push(cellMatch[1].trim()); } } // Need at least date, updated, committee, subject, and title/type if (cells.length < 5) continue; // Extract date const date = cells[0] ? cells[0].replace(/<[^>]+>/g, "").trim() : ""; if (!date) continue; // Extract updated date const updated = cells[1] ? cells[1].replace(/<[^>]+>/g, "").trim() : ""; // Extract committee const committee = cells[2] ? cells[2].replace(/<[^>]+>/g, "").trim() : undefined; // Extract subject const subject = cells[3] ? cells[3].replace(/<[^>]+>/g, "").trim() : undefined; // Extract title, type, and document ID from the last cell const titleCell = cells[4] || ""; // Extract document ID and title from the link if present const docLinkMatch = titleCell.match(/<a href="document\.html\?nummer=([^"]+)">([\s\S]*?)<\/a>/i); let id = ""; let title = ""; let url = ""; if (docLinkMatch && docLinkMatch[1] && docLinkMatch[2]) { id = docLinkMatch[1]; title = docLinkMatch[2].trim(); url = new URL(`document.html?nummer=${id}`, baseUrl).href; } else { // If no link, just use the text content title = titleCell.replace(/<[^>]+>/g, "").trim(); // Generate a placeholder ID id = `unknown-${Date.now()}-${Math.floor(Math.random() * 1000)}`; url = baseUrl; } // Extract document type (usually on the next line after the title) const typeMatch = titleCell.match(/<br\s*\/?>\s*(.*?)(?:<|$)/i); const type = typeMatch && typeMatch[1] ? typeMatch[1].trim() : "Unknown"; // Add the document to the list recentDocuments.push({ id, title, type, date, updated, committee, subject, url }); // Limit to 20 documents to avoid overwhelming the response if (recentDocuments.length >= 20) break; } } // Extract birthdays const birthdayRegex = /Jarig vandaag\s*((?:<a[^>]*>[^<]*<\/a>\s*)+)/i; const birthdayMatch = html.match(birthdayRegex); if (birthdayMatch && birthdayMatch[1]) { const birthdayContent = birthdayMatch[1]; const birthdayLinkRegex = /<a href="persoon\.html\?nummer=([^"]+)">([\s\S]*?)<\/a>/gi; let birthdayLinkMatch; while ((birthdayLinkMatch = birthdayLinkRegex.exec(birthdayContent)) !== null) { if (birthdayLinkMatch[1] && birthdayLinkMatch[2]) { const id = birthdayLinkMatch[1]; const nameWithParty = birthdayLinkMatch[2].trim(); // Extract name and party if in format "Name (Party)" const namePartyMatch = nameWithParty.match(/(.*?)\s*\((.*?)\)\s*$/); let name = nameWithParty; let party = undefined; if (namePartyMatch && namePartyMatch[1] && namePartyMatch[2]) { name = namePartyMatch[1].trim(); party = namePartyMatch[2].trim(); } const url = new URL(`persoon.html?nummer=${id}`, baseUrl).href; birthdays.push({ id, name, party, url }); } } } // For pagination, we would normally need to fetch different pages from the server // Since the tkconv site doesn't have explicit pagination, we're simulating it by // limiting the number of documents per page and tracking which ones we've shown const documentsPerPage = 10; const startIndex = (page - 1) * documentsPerPage; const endIndex = startIndex + documentsPerPage; // Get the documents for the current page const paginatedDocuments = recentDocuments.slice(startIndex, endIndex); // Check if there are more documents available const hasMoreDocuments = endIndex < recentDocuments.length; return { recentDocuments: paginatedDocuments, birthdays, // Birthdays are always shown regardless of page lastUpdated, pagination: { currentPage: page, hasMoreDocuments, totalDocumentsRetrieved: recentDocuments.length } }; }
- src/utils/html-parser.ts:86-95 (schema)TypeScript interface defining the output structure/schema of the overview data returned by extractOverviewFromHtml and getOverview, including arrays of recent documents and birthdays with pagination info.interface OverviewData { recentDocuments: RecentDocument[]; birthdays: BirthdayPerson[]; lastUpdated: string; pagination: { currentPage: number; hasMoreDocuments: boolean; totalDocumentsRetrieved: number; }; }