OpenTK Model Context Protocol Server
About
A Model Context Protocol (MCP) server providing access to Dutch parliamentary data (Tweede Kamer) through OpenTK . This server enables AI assistants to search, retrieve, and analyze parliamentary documents, activities, and information as published by parliament..
Details
- Author
- r-huijts
- GitHub stars
- 21
- Downloads
- 171
- Categories
- Database, Other
Jump to
- Search parliamentary documents with advanced query syntax (quotes, NOT, OR, NEAR)
- Access comprehensive MP profiles and committee memberships
- Retrieve full document content from PDF/Word with smart chunking
- NLP-powered relevance analysis and keyword extraction (v1.0.16)
- Dutch-optimized entity recognition for persons, parties, and organizations
- Track legislative cases, voting results, and upcoming activities
Setting up with Highlight
This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:
- Download and install Highlight from highlightai.com/download
- Navigate to the plugins tab and select "Add Custom Plugin"
-
Configure the plugin with the settings below
Plugin Name
OpenTK Model Context Protocol ServerCommand (node, npx, python, etc.)Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.
- Enable "Start Automatically" if you want the plugin to start when Highlight launches
From the repository
Run instantly with npx @r-huijts/opentk-mcp. For Claude Desktop, add the server to your claude_desktop_config.json using the npx command. Once configured, Claude can use all 17 tools to search, analyze, and retrieve parliamentary data.
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.
birthdays_today
Lists all Members of Parliament celebrating their birthday today, including their names, political parties, and birth dates. The response is a JSON array where each entry contains the MP's ID, name, party affiliation, and other details. This tool takes no parameters as it always returns today's birthdays. Applicable when information about MPs' birthdays is needed.
list_persons
Provides a complete directory of current Members of Parliament with their IDs, names, titles, party affiliations, and faction memberships. The response is a JSON array where each entry contains an MP's full details including unique MP IDs that can be referenced by other tools. This tool takes no parameters as it returns all current MPs. Applicable when comprehensive information about all MPs is needed or when analyzing the composition of parliament by party.
search_tk
Performs a comprehensive search across all parliamentary data including documents, activities, and cases. Returns results matching the provided keyword or phrase. Use this for general searches when you need information on any topic discussed in parliament, regardless of document type or context. Search syntax: Searching for 'Joe Biden' finds documents containing both 'Joe' and 'Biden' anywhere in the text. Searching for "Joe Biden" (with quotes) finds only documents where these words appear next to each other. Searching for 'Hubert NOT Bruls' finds documents containing 'Hubert' but not 'Bruls'. The capital letters in 'NOT' are important. You can also use 'OR' and 'NEAR()' operators.
search_tk_filtered
Performs a search within a specific category of parliamentary data, allowing results to be limited to only documents, activities, or cases. Returns paginated results sorted by date (most recent first). Search syntax supports: keyword searches ('Joe Biden' finds both terms), exact phrase searches ("Joe Biden" with quotes finds the exact phrase), exclusion ('Hubert NOT Bruls' excludes documents with 'Bruls'), and boolean operators ('OR', 'NEAR()'). Results can be returned in 'full' or 'summary' format.
get_photo
Retrieves the official portrait photograph of a Member of Parliament. Returns the image as a binary resource that can be displayed or saved. Use this when you need to include a visual representation of an MP in reports, presentations, or profiles.
get_document_details
Retrieves metadata about a parliamentary document in a structured JSON format, without downloading the actual document content. Returns information including title, type, document number, dates, version number, and links to both the PDF version and the official Tweede Kamer webpage.
get_document_links
Converts document URLs into clickable markdown-formatted links. This tool takes either a direct PDF link or a Tweede Kamer webpage link and returns them as properly formatted clickable links.
get_committees
Retrieves a list of all parliamentary committees with their IDs, names, and URLs. The response is a JSON array where each entry represents a committee with its unique identifier and name. Committees are specialized groups of MPs that focus on specific domains like defense, healthcare, or finance. This tool takes no parameters as it returns all active committees.
get_committee_details
Retrieves detailed information about a specific parliamentary committee, including its members, recent activities, and description. This provides deeper insight into the committee's composition, leadership roles, and recent work. Use this when you need comprehensive information about a particular committee's structure and activities.
get_upcoming_activities
Retrieves a list of upcoming parliamentary activities including debates, committee meetings, and other events. The response contains a structured JSON object with both a chronological list of activities and activities grouped by date. Each activity includes details like date, time, location, committee, type, and a URL for more information. The results are sorted by date with the most imminent activities first. The optional 'limit' parameter controls the number of results returned (default: 20, max: 100).
get_voting_results
Retrieves recent voting results on parliamentary motions and bills. The response contains a structured JSON object with voting results sorted by date (newest first). Each result includes detailed information such as the title of the motion/bill, the date of the vote, the submitter, whether it was accepted or rejected, the vote counts (for/against), and which political parties voted for or against. The 'limit' parameter controls the number of results (default: 20, max: 100) and 'format' parameter allows choosing between 'full' or 'summary' format. The 'summary' format provides a more structured representation with renamed fields, while both formats include complete party voting information.
search_by_category
Performs a search for documents of a certain category, such as questions ('vragen'), motions ('moties'), or all document types ('alles'). The response contains a structured JSON object with paginated results and metadata. The search syntax supports advanced queries: 'Joe Biden' finds documents with both terms anywhere, '"Joe Biden"' (with quotes) finds exact phrases, 'Hubert NOT Bruls' finds documents with 'Hubert' but not 'Bruls' (capital NOT is required), and 'OR' for alternatives. Results are sorted by date with the most recent documents first.
get_document_content
Retrieves the content of a parliamentary document (PDF or DOCX). This tool supports three modes of operation depending on parameters provided: 1. TARGETED RETRIEVAL (with offset): Provide docId + offset (+ optional maxLength, default 3000). Returns text centered around the offset position, extracting approximately 1,500 chars before and 1,500 chars after the offset. Finds natural paragraph boundaries for clean extraction. 2. SEQUENTIAL READING (with maxLength, no offset): Provide docId + maxLength (no offset). Returns first maxLength characters from document start. Includes nextOffset for pagination to continue reading. 3. FULL DOCUMENT RETRIEVAL (no offset, no maxLength): Provide docId only. Returns complete document text (may be 100KB+). Note: May use significant context window space. PARAMETERS: - docId: Document ID to retrieve (required) - offset (optional): Character position to center extraction around. Can be obtained from find_person_in_document or from the nextOffset value in previous responses. - maxLength (optional): Maximum characters to return. Default is 3000 when offset is provided, no limit when offset is not provided. RESPONSE FORMAT: - text: Extracted document content - textLength: Length of returned text - offset: Starting position in full document - nextOffset: Position to continue reading (null if at end) - prevOffset: Position to read backwards (null if at start) - hasMoreBefore: Boolean indicating more content exists before - hasMoreAfter: Boolean indicating more content exists after - note: Instructions for retrieving more content
find_person_in_document
Searches for all occurrences of a person's name within a parliamentary document and returns their precise locations. This tool efficiently navigates large documents by identifying where specific persons speak, are mentioned, or are referenced without loading the entire document. The tool uses fuzzy matching, so partial names work well: - Searching for "Wilders" will find "Geert Wilders", "de heer Wilders", "Minister Wilders", etc. - Searching for "Rutte" will find "Mark Rutte", "Premier Rutte", "Minister-president Rutte", etc. - Searching for "Van der" will find "Van der Staaij", "Van der Plas", etc. The response includes: - Total number of occurrences found - For each occurrence: - Line range (e.g., lines 45-47) showing where in the document the name appears - Character offset in the full document text (can be used with get_document_content) - A brief snippet (preview) of the surrounding text to verify context Particularly valuable for debate transcripts, committee meetings, and lengthy parliamentary documents where multiple people speak.
find_party_in_document
Searches for all occurrences of a political party within a parliamentary document and returns their precise locations. This tool efficiently navigates large documents by identifying where specific political parties are mentioned, referenced, or their positions are discussed without loading the entire document. The tool uses fuzzy matching with party abbreviations: - Searching for "VVD" will find "VVD", "de VVD", "VVD-fractie", "VVD-kamerlid", etc. - Searching for "PVV" will find "PVV", "de PVV", "PVV-fractie", "PVV-kamerlid", etc. - Searching for "CDA" will find "CDA", "de CDA", "CDA-fractie", "CDA-kamerlid", etc. - Searching for "D66" will find "D66", "de D66", "D66-fractie", "D66-kamerlid", etc. The response includes: - Total number of occurrences found - For each occurrence: - Line range (e.g., lines 45-47) showing where in the document the party appears - Character offset in the full document text (can be used with get_document_content) - A brief snippet (preview) of the surrounding text to verify context Particularly valuable for debate transcripts, committee meetings, and lengthy parliamentary documents where multiple parties' positions are discussed.
analyze_document_relevance
Performs intelligent pre-analysis of a parliamentary document to determine its relevance WITHOUT loading the full content into your context window. This is a lightweight reconnaissance tool that extracts key information about a document's content before you commit to reading the full text. Use this to efficiently assess whether a document is worth reading in detail, especially when you're uncertain about relevance or need to triage multiple documents. WHAT THIS TOOL RETURNS: - **Keywords**: Top 10-15 most important terms extracted via TF-IDF analysis, revealing the document's main subjects (e.g., 'klimaat', 'belasting', 'migratie', 'gezondheidszorg') - **Named Entities**: Structured lists of people mentioned (MPs, ministers, officials), political parties (VVD, PVV, CDA, D66, GroenLinks, etc.), and organizations - **Statistics**: Document length (character count, word count), estimated reading time, and structural information about the document format - **Preview**: The first ~500 characters of the document for immediate context - **Topics**: Main themes and subject areas identified through content analysis - **Relevance Score** (optional): If you provide the searchTerms parameter, returns a 0-100 score indicating how well the document matches those specific terms, helping you rank multiple documents by relevance WHEN TO USE THIS TOOL: - When you need to understand what a document is about before reading it in full - When you have multiple candidate documents and need to determine which ones are most relevant - When you want to verify a document contains specific topics or entities before loading its full content - When context window efficiency is important and you want to avoid loading large documents that may not be relevant - When a user asks about document content but you're uncertain if it matches their query - When you need to filter or triage search results before committing to detailed reading WHEN NOT TO USE THIS TOOL: - When the user explicitly requests the full content or specific quotes from a document - When you already have high confidence the document is relevant and need to read it anyway - When you specifically need to locate where a person appears in a document (find_person_in_document is optimized for this) - When you only need structural metadata like title, date, and links RELATIONSHIP TO OTHER DOCUMENT TOOLS: - **get_document_content**: This analysis tool is lighter weight (~1-2KB) compared to reading full documents (10-50KB). Both tools access document content but serve different purposes: analysis for triage and overview, get_document_content for detailed reading. - **find_person_in_document**: The analysis tool identifies IF a person is mentioned; find_person_in_document locates WHERE they appear with character offsets. Analysis provides presence information, find_person provides location information. - **get_document_details**: Details provides structural metadata (title, type, date, links); this tool provides content intelligence (keywords, entities, topics). They offer complementary information about documents. - **search_tk/search_tk_filtered**: Search identifies candidate documents; this tool provides detailed content analysis of those candidates. CONTEXT WINDOW EFFICIENCY: This tool returns approximately 1-2KB of analysis data versus 10-50KB for reading full documents. Using this tool before get_document_content can reduce context usage by 80-90% when documents turn out to be irrelevant. It's particularly valuable when evaluating multiple documents or when a user's query is exploratory rather than specific. The searchTerms parameter is powerful for ranking documents by relevance: when provided, it calculates a 0-100 relevance score based on how well the document matches your search terms, allowing you to objectively compare multiple documents before deciding which to read in full.
Claude Desktop / Cursor
Paste into your MCP client config file to install this server.
{
"mcpServers": {
"opentk model context protocol server": {
"opentk-mcp": {
"command": "npx",
"args": [
"@r-huijts/opentk-mcp"
]
}
}
}
}
McpServers
{
"opentk-mcp": {
"command": "npx",
"args": [
"@r-huijts/opentk-mcp"
]
}
}
OpenTK Model Context Protocol Server
> Important Attribution: This MCP server is built as a wrapper around the excellent OpenTK project created by Bert Hubert. The OpenTK project provides unprecedented access to Dutch parliamentary data through a user-friendly interface. Learn more about the project in Bert's article: Welkom bij OpenTK. All credit for the underlying data access and processing goes to Bert Hubert and his contributions to open government data.
A bridge between large language models (LLMs) and Dutch parliamentary data through a standardized interface. This MCP server provides access to Dutch parliamentary documents, debates, and member information from the Tweede Kamer.
<a href="https://glama.ai/mcp/servers/@r-huijts/opentk-mcp">
</a>
Real-World Natural Language Interaction Examples
Example 1: Comparing Party Positions on AI Policies
User Query: "When comparing the activities of opposition parties PvdA, GroenLinks, and Volt with government party BBB in the Dutch House of Representatives in the field of AI, what are actions they can undertake together in the short term that align with the positions and views they have demonstrated over the past year? Please use sources from OpenTK."Example 2: Researching Parliamentary Discussions on Climate Policy
User Query: "I'd like to analyze recent parliamentary debates on climate policy and emission reduction targets in the Netherlands. Can you help me identify key discussions and the main positions taken by different parties over the past six months?"Example 3: Information About a Specific MP's Voting Record
User Query: "What is MP Pieter Omtzigt's voting record on healthcare reform legislation, and how does his position differ from other independent members? Has he introduced any motions on this topic?"Example 4: Finding Recent Housing Legislation Developments
User Query: "What are the most significant parliamentary documents and debates about affordable housing legislation from the past year? I'm particularly interested in proposals addressing the rental market crisis."Example 5: Efficiently Triaging Multiple Documents (NEW - Smart Analysis)
User Query: "I found 15 documents about climate policy from the last month. Can you quickly identify which 3 documents are most relevant to renewable energy subsidies and wind power legislation, without reading all of them in full?"Example 6: Extracting Key Topics from Parliamentary Documents (NEW - Smart Analysis)
User Query: "What are the main topics, keywords, and political parties mentioned in document 2024D39058? I want to understand what it's about before diving into the full text."Example 7: Finding MPs with Specific Committee Memberships
User Query: "Which MPs currently serve on both the Finance Committee and the Economic Affairs Committee? What parties do they represent, and have they recently submitted any joint initiatives?"Example 8: Identifying Upcoming Parliamentary Activities on Digital Security
User Query: "Are there any scheduled committee meetings or debates about cybersecurity and digital infrastructure planned for the next month? Which ministers will be participating and what specific topics will be addressed?"Project Concept
The OpenTK project is a Model Context Protocol (MCP) server that provides access to Dutch parliamentary data through a standardized interface. It serves as a bridge between large language models (LLMs) and the Dutch Parliament's information systems, allowing AI assistants to search, retrieve, and analyze parliamentary documents, debates, and member information.
The server uses the @modelcontextprotocol/sdk to implement the MCP specification, which enables structured communication between AI models and external data sources. By exposing parliamentary data through well-defined tools and endpoints, OpenTK makes it possible for AI assistants to:
1. Search for parliamentary documents using complex queries
2. Access information about Members of Parliament
3. Retrieve official documents in various formats and read the full content of the documents
4. Analyze parliamentary activities and proceedings
5. Track legislative cases and government pledges
6. Intelligently analyze document relevance using NLP before loading full content (NEW in v1.0.16)
7. Extract keywords, entities, and topics for efficient document triage (NEW in v1.0.16)
The project leverages Bert Hubert's tkconv service as its primary data source, which provides a more accessible API than the official Dutch Parliament APIs.
Features
Core Parliamentary Data Access
- Search parliamentary documents with advanced query capabilities (quotes, NOT, OR, NEAR operators) - Access comprehensive MP information and committee memberships - Retrieve full document content (PDF, Word) with smart chunking - Track legislative cases, government activities, and voting results - Real-time access to parliamentary proceedings and upcoming activitiesSmart Document Analysis (NEW in v1.0.16) 🎯
- NLP-Powered Relevance Analysis: Intelligently analyze documents before loading full content - TF-IDF Keyword Extraction: Identify the top 10-15 most important terms in any document - Dutch-Optimized Entity Recognition: Automatically detect persons (MPs, ministers), political parties (VVD, PVV, CDA, D66, etc.), and organizations - Topic Categorization: Classify documents across 10 major political themes (Climate, Economy, Healthcare, Education, etc.) - Relevance Scoring: Rank documents by relevance to specific search terms (0-100 score) - Context-Efficient Triage: Reduce context window usage by 80-90% when evaluating multiple documentsAdvanced Document Navigation
- Find specific person occurrences with fuzzy matching - Find party mentions with fuzzy matching - Navigate large documents efficiently with character offsets - Sequential reading with pagination supportAvailable Tools
OpenTK provides 17 specialized tools for accessing Dutch parliamentary data:
Overview & Discovery
-get_overview: Comprehensive overview of recent parliamentary activities and MP birthdays (paginated)
- birthdays_today: List MPs celebrating birthdays today
- list_persons: Complete directory of current MPs with party affiliations
Search & Filter
-search_tk: Comprehensive search across all parliamentary data with advanced query syntax
- search_tk_filtered: Search within specific categories (Document, Activiteit, Zaak)
- search_by_category: Search for specific document types (questions, motions, all)
Document Intelligence (NEW) 🎯
-analyze_document_relevance: NLP-powered document analysis with keyword extraction, entity recognition, and relevance scoring
- get_document_content: Retrieve document content (PDF/DOCX) with three reading modes (targeted, sequential, full)
- find_person_in_document: Locate all occurrences of a person in a document with fuzzy matching
- find_party_in_document: Locate all occurrences of a political party in a document
Document Metadata
-get_document_details: Retrieve structured metadata about documents
- get_document_links: Convert document URLs to clickable markdown links
Parliamentary Structure
-get_committees: List all parliamentary committees
- get_committee_details: Detailed information about specific committees
Activities & Voting
-get_upcoming_activities: Upcoming parliamentary debates and meetings
- get_voting_results: Recent voting results with party positions
Media
-get_photo: Retrieve official MP portrait photographs
Installation
1. Quick Start with NPM Package (Recommended)
The fastest way to get started is using the published npm package:
npx @r-huijts/opentk-mcp
2. Using Claude Desktop with NPM Package
Update your Claude configuration file (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"opentk": {
"command": "npx",
"args": [
"-y",
"@r-huijts/opentk-mcp"
]
}
}
}
Alternative configurations:
For MultiServerMCPClient (Python):
mcp_client = MultiServerMCPClient({
"opentk": {
"command": "npx",
"args": ["-y", "@r-huijts/opentk-mcp"],
"transport": "stdio",
}
})
3. From Source (Development)
If you want to modify the code or contribute to development:
Clone Repository:
git clone https://github.com/r-huijts/opentk-mcp.git
cd opentk-mcp
Install Dependencies:
npm install
Build the Project:
npm run build
Start the Server:
npm start
Configure Claude Desktop for local development:
Update your Claude configuration file:
{
"mcpServers": {
"opentk-local": {
"command": "node",
"args": [
"/absolute/path/to/your/opentk-mcp/dist/index.js"
]
}
}
}
Make sure to replace /absolute/path/to/your/opentk-mcp/ with the actual path to your installation.
4. Publishing (for maintainers)
To publish a new version of the scoped package:
npm run build
npm publish --access=public
Note: Scoped packages require the --access=public flag to be publicly available.
Search Functionality
The search functionality is particularly sophisticated, supporting:
- Simple keyword searches: kunstmatige intelligentie
- Exact phrase searches: "kunstmatige intelligentie"
- Exclusion searches: Hubert NOT Bruls
- Boolean operators: OR, NEAR()
The implementation handles various edge cases:
- Preserves quotes in search queries
- Uses proper content type headers
- Implements fallback mechanisms for API errors
- Provides meaningful error messages
Error Handling
The API service includes robust error handling:
- Graceful handling of API errors (4xx, 5xx)
- Fallback to simplified queries when complex ones fail
- Detailed error messages for debugging
- Proper logging to stderr (not stdout, which would break the stdio transport)
Configuration
The server connects to Bert Hubert's tkconv service as its primary data source, which provides a more accessible API than the official Dutch Parliament APIs. This service, created by Bert Hubert, does the heavy lifting of collecting, organizing, and making available Dutch parliamentary data in a developer-friendly format. Our MCP server builds upon this foundation to create a standardized interface for AI assistants to interact with this valuable data.
License
MIT
Conclusion
The OpenTK MCP server provides a robust and well-structured interface to Dutch parliamentary data, making it accessible to AI assistants through the Model Context Protocol. Its modular design, comprehensive API, NLP-powered document analysis (v1.0.16), and thorough testing ensure reliable access to parliamentary information for AI-assisted research, analysis, and information retrieval.
Once configured, Claude will be able to access Dutch parliamentary data through the OpenTK MCP server using all 17 specialized tools for search, document analysis, MP information, committee tracking, voting results, and more.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





