OpenTK Model Context Protocol Server
The OpenTK Model Context Protocol Server provides comprehensive access to Dutch parliamentary data through a standardized AI interface. Key capabilities include:
Data Access & Search:
Comprehensive searches across documents, activities, and cases using advanced query syntax (Boolean operators, exact phrases, proximity searches)
Targeted searches within specific categories (official documents, debates, legislative cases)
Parliamentary document retrieval with metadata, full text content, and pagination support
Parliamentary Information:
Complete Member of Parliament listings with details, party affiliations, voting records, and committee memberships
Official MP portrait photographs and birthday tracking
Committee information including members and recent activities
Recent voting results on motions and bills with party voting patterns
Activity Tracking:
Overview of recent parliamentary activities and latest documents
Upcoming debates, committee meetings, and parliamentary events
Document URL conversion to clickable links for easy access
Technical Features:
Robust error handling with fallback mechanisms
Pagination support for large datasets
Document content extraction for analysis and summarization
This server bridges AI models with Dutch parliamentary data, enabling detailed research, analysis, and information retrieval for parliamentary monitoring and governance insights.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OpenTK Model Context Protocol Server show me recent debates about housing policy"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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.
Real-World Natural Language Interaction Examples
Related MCP server: Riksdag & Regering MCP
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:
Search for parliamentary documents using complex queries
Access information about Members of Parliament
Retrieve official documents in various formats and read the full content of the documents
Analyze parliamentary activities and proceedings
Track legislative cases and government pledges
Intelligently analyze document relevance using NLP before loading full content (NEW in v1.0.16)
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 activities
Smart 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 documents
Advanced 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 support
Available 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 todaylist_persons: Complete directory of current MPs with party affiliations
Search & Filter
search_tk: Comprehensive search across all parliamentary data with advanced query syntaxsearch_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 scoringget_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 matchingfind_party_in_document: Locate all occurrences of a political party in a document
Document Metadata
get_document_details: Retrieve structured metadata about documentsget_document_links: Convert document URLs to clickable markdown links
Parliamentary Structure
get_committees: List all parliamentary committeesget_committee_details: Detailed information about specific committees
Activities & Voting
get_upcoming_activities: Upcoming parliamentary debates and meetingsget_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-mcp2. 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-mcpInstall Dependencies:
npm installBuild the Project:
npm run buildStart the Server:
npm startConfigure 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=publicNote: Scoped packages require the --access=public flag to be publicly available.
Search Functionality
The search functionality is particularly sophisticated, supporting:
Simple keyword searches:
kunstmatige intelligentieExact phrase searches:
"kunstmatige intelligentie"Exclusion searches:
Hubert NOT BrulsBoolean 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.
Available Tools
14 toolsbirthdays_todayA
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. Use this tool when a user specifically asks about birthdays, wants to know which MPs are celebrating today, or needs to create 'on this day' content. This tool takes no parameters as it always returns today's birthdays. For a more general overview that includes birthdays along with other parliamentary information, use the 'get_overview' tool instead. If you need to display an MP's photo alongside their birthday information, you can use the 'get_photo' tool with the MP's ID from this response.
Inputs: no named parameters.
get_committee_detailsA
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.
Inputs: committeeId (required).
get_committeesA
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. Use this tool when a user asks about parliamentary committees, wants to know which committees exist, or needs to find committees related to specific policy areas. Committees are specialized groups of MPs that focus on specific domains like defense, healthcare, or finance. After getting the list of committees, you can use the 'get_committee_details' tool with a specific committee ID to retrieve more detailed information about that committee, including its members and recent activities. This tool takes no parameters as it returns all active committees.
Inputs: no named parameters.
get_document_contentA
Downloads a parliamentary document and extracts its text content for use in the conversation. This tool retrieves the actual content of a document based on its ID, making it available for analysis, summarization, or direct reference in the conversation. The text is extracted from PDF or Word (DOCX) documents using professional libraries and returned in a readable format.
IMPORTANT: For longer documents, the content may be truncated. The response includes pagination information to help you retrieve the complete document:
isTruncated: Indicates whether there is more content available
totalLength: The total length of the document content
currentOffset: The starting position of the current content chunk
nextOffset: The starting position for the next content chunk (use this as the 'offset' parameter in your next call)
remainingLength: The amount of content remaining after the current chunk
To retrieve the complete document, you can make multiple calls to this tool, incrementing the offset each time:
Example usage:
First call: get_document_content({docId: '2025D18220'})
If the response shows isTruncated=true, call again with the nextOffset value: get_document_content({docId: '2025D18220', offset: 8000})
Continue until isTruncated=false or you've retrieved all the content you need.
This pagination approach allows you to analyze even very long documents within the conversation context.
Use this tool when you need to analyze or discuss the specific content of a document rather than just its metadata.
Inputs: docId (required), offset.
get_document_detailsA
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 clickable links to both the PDF version and the official Tweede Kamer webpage. This tool is ideal for getting quick information about a document and obtaining the relevant links for further access. To actually download the document content, use the 'download_document' tool instead.
Inputs: nummer (required).
get_document_linksA
Converts document URLs into clickable links. This tool takes either a direct PDF link or a Tweede Kamer webpage link and returns them as properly formatted clickable links. Use this after get_document_details to make the URLs clickable.
Inputs: pdfUrl, tkUrl.
get_overviewA
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.
Inputs: page.
get_photoA
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.
Inputs: personId (required).
get_upcoming_activitiesA
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. Use this tool when a user asks about the parliamentary agenda, wants to know what events are coming up, or needs information about specific types of parliamentary activities. The results are sorted by date with the most imminent activities first. You can limit the number of results using the optional 'limit' parameter. This tool is particularly useful for helping users plan which parliamentary sessions to follow or for providing an overview of the upcoming parliamentary schedule.
Inputs: limit.
get_voting_resultsA
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. Use this tool when a user asks about recent parliamentary votes, wants to know how parties voted on specific issues, or needs to analyze voting patterns. You can control the number of results with the 'limit' parameter and choose between 'full' or 'summary' format. The 'summary' format provides a more structured representation with renamed fields, while both formats include complete party voting information. This tool is particularly valuable for tracking political alignments, understanding coalition dynamics, and analyzing how different parties position themselves on important issues.
Inputs: format, limit.
list_personsA
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. Use this tool when a user needs comprehensive information about all MPs, wants to analyze the composition of parliament by party, or needs to find specific MPs by name or party. This tool is particularly useful for creating reports about parliamentary representation or for finding the IDs of MPs that can be used with other tools like 'get_photo'. This tool takes no parameters as it returns all current MPs. For a more targeted approach when looking for specific MPs, consider using the 'search_tk' tool with the MP's name.
Inputs: no named parameters.
search_by_categoryA
Performs a search specifically for documents of a certain category, such as questions, motions, or letters. The response contains a structured JSON object with paginated results and metadata. Use this tool when a user wants to find documents of a specific type that match certain keywords or when they need more targeted search results than the general search provides. The 'category' parameter lets you filter by document type: 'vragen' for parliamentary questions, 'moties' for motions, or 'alles' for all document types. 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 you can use 'OR' for alternatives. Results are sorted by date with the most recent documents first. This tool is particularly useful for finding specific types of parliamentary documents on a given topic.
Inputs: category (required), query (required), limit, page.
search_tkA
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.
Inputs: query (required), format, limit, page.
search_tk_filteredA
Performs a targeted search within a specific category of parliamentary data. Unlike the general search, this tool allows you to limit results to only documents, activities, or cases. Use this when you need more focused search results within a particular content type. 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.
Inputs: query (required), type (required), format, limit, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
Most tools have distinct purposes, but there is notable overlap between search_tk, search_tk_filtered, and search_by_category, which could confuse agents about which to use for document searches. Additionally, get_document_details and get_document_content serve different functions but might be misselected due to similar naming and domain overlap. The descriptions help clarify, but the boundaries are not perfectly clear.
The naming follows a consistent verb_noun pattern (e.g., get_overview, list_persons, search_tk) with minor deviations like birthdays_today (noun_verb) and get_document_links (which could be named more consistently as get_document_links or similar). Overall, the pattern is readable and mostly predictable, with only a few inconsistencies.
With 14 tools, the count is well-scoped for a parliamentary data server, covering MPs, committees, documents, activities, and searches. Each tool appears to serve a specific purpose without redundancy, fitting within the typical 3-15 range for such a domain.
The tool set provides comprehensive coverage for parliamentary data, including CRUD-like operations for documents (get, search), MPs (list, get photo), committees (list, get details), and activities (get overview, get upcoming). Minor gaps include no explicit update or delete tools, but this is reasonable for a read-only data source, and agents can work around this with the available search and retrieval tools.
Maintenance
Related MCP Connectors
Dutch Parliament (Tweede Kamer) open data MCP.
Source-anchored search and civic intelligence for Dutch municipal council records.
Verified Polish open data for AI agents: debt, budget, 460 MPs, votings, judiciary search, RAG.
Dutch legal AI for law firms: answers from Dutch case law, legislation and EU law, with citations.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides programmatic access to official German Bundestag parliamentary data, enabling LLMs to answer questions about legislation, voting records, and members.1MIT
- AlicenseNot gradedqualityCmaintenanceEnables LLMs to query and retrieve real-time open data, documents, protocols, and records from the Swedish Parliament (Riksdag) and Government Offices through 32 specialized MCP tools.31MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query Swedish Parliament open data through natural language.277 npmMIT
- AlicenseNot gradedqualityCmaintenanceProvides access to Dutch Parliament (Tweede Kamer) open data through MCP tools, enabling querying of parliamentary information via natural language.303 npmMIT