Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
If you have suggestions for how this project could be improved, or want to report a bug, open an issue! We'd love all and any contributions. If you have questions, too, we'd love to hear them.
We'd also love PRs. If you're thinking of a large PR, we advise opening up an issue first to talk about it, though! Look at the links below if you're not sure how to open a PR.
| Requirement | Minimum Version | Check |
|---|---|---|
| Node.js | 25.0.0 | node --version |
| npm | 10.0.0 | npm --version |
| Git | 2.x | git --version |
# 1. Fork the repository, then clone your fork
git clone https://github.com/<your-username>/European-Parliament-MCP-Server.git
cd European-Parliament-MCP-Server
# 2. Install dependencies (uses package-lock.json for reproducibility)
npm install
# 3. Verify build works
npm run build
# 4. Run all unit tests to confirm your environment is healthy
npm test
# 5. Optional: run type-checking separately
npm run type-check
# Start the server in watch mode (auto-recompile on change)
npm run dev
# Run unit tests in watch mode
npm run test:watch
# Run unit tests with coverage report
npm run test:coverage
# Lint source files
npm run lint
# Auto-fix linting issues
npm run lint:fix
# Check code formatting
npm run format
# Check for dead code / unused exports
npm run knip
# Security audit
npm audit
# License compliance check
npm run test:licenses
Create a .env.test file for integration testing:
# Set to 'true' to run tests against the real EP API (rate-limited)
EP_INTEGRATION_TESTS=false
# Optional: override API base URL for testing against a mirror
EP_API_URL=https://data.europarl.europa.eu/api/v2
⚠️ Never commit
.envfiles — they are listed in.gitignore.
All branches must follow the pattern: <type>/<short-description>
| Type | Purpose | Example |
|---|---|---|
feature/ |
New functionality | feature/add-budget-tool |
fix/ |
Bug fix | fix/rate-limiter-race-condition |
docs/ |
Documentation only | docs/improve-jsdoc-getMEPs |
chore/ |
Maintenance, deps, CI | chore/upgrade-vitest-4 |
test/ |
Test improvements | test/add-e2e-coalition-tool |
perf/ |
Performance improvements | perf/cache-key-normalization |
security/ |
Security fixes | security/upgrade-undici |
npm installnpm testgit checkout -b feature/my-branch-nameHere are a few things you can do that will increase the likelihood of your pull request being accepted:
npm run lint and npm run format before committingWhen you submit a pull request, our automated labeler will automatically apply labels based on the files you've changed:
mcp-tools - Changes to MCP tool implementations (src/tools/)mcp-resources - Changes to MCP resources (src/resources/)mcp-prompts - Changes to MCP prompts (src/prompts/)mcp-protocol - MCP protocol changesep-api - European Parliament API integrationep-data - European Parliament data handlingmeps - MEP-related changesplenary - Plenary session featurescommittees - Committee featuresdocuments - Document handlingfeature - New features or functionalityenhancement - Improvements to existing featuresbug - Bug fixesdocumentation - Documentation updatesdependencies - Dependency updatessecurity - Security improvementsperformance - Performance optimizationstesting - Test improvementsgdpr - GDPR compliance changesisms-compliance - ISMS policy compliancesecurity - Security enhancementsYou can also manually add labels by including them in your PR description using checkboxes:
- [x] 🚀 New Feature/Enhancement
- [x] 🔌 MCP Tools
- [x] 🏛️ European Parliament API
We follow Conventional Commits specification:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, missing semicolons, etc)refactor: Code refactoringperf: Performance improvementstest: Adding or updating testsbuild: Changes to build system or dependenciesci: CI/CD changeschore: Other changes that don't modify src or test filesExamples:
feat(mcp-tools): add getMEPs tool for fetching MEP information
fix(ep-api): handle rate limiting in European Parliament API calls
docs: update README with new MCP tools documentation
test: add unit tests for plenary session tools
build(deps): update @modelcontextprotocol/sdk to v1.0.5
Work in Progress pull requests are also welcome to get feedback early on, or if there is something blocked you.
See docs/TOOL_DEVELOPMENT.md for the full step-by-step guide. Here is the quick summary:
# Create src/tools/myNewTool.ts
# Use an existing tool (e.g., getMEPs.ts) as a template
Add the input schema to src/schemas/europeanParliament.ts:
export const MyNewToolSchema = z.object({
subjectId: z.string().min(1).max(200).describe('Subject identifier'),
limit: z.number().int().min(1).max(100).default(50),
});
Follow the two-layer error pattern:
export async function handleMyNewTool(args: unknown): Promise<ToolResult> {
const params = MyNewToolSchema.parse(args); // Layer 1: Zod validation
try {
const result = await epClient.someMethod(params);
return buildToolResponse(result);
} catch (error) {
const msg = error instanceof Error ? error.message : 'Unknown error';
throw new Error(`Failed to fetch data: ${msg}`);
}
}
export const myNewToolMetadata = {
name: 'my_new_tool',
description: 'One paragraph explaining what this tool does and its parameters.',
inputSchema: { type: 'object' as const, properties: { ... } },
};
Then add the import and routing case to the server's tool registry.
Create src/tools/myNewTool.test.ts covering:
ToolResultZodError thrownThe server uses a lightweight Dependency Injection (DI) container defined in src/di/.
src/di/tokens.ts)import { TOKENS } from './di/tokens.js';
// Available tokens:
TOKENS.EPClient // EuropeanParliamentClient singleton
TOKENS.RateLimiter // Token-bucket rate limiter
TOKENS.MetricsService // Performance metrics collector
TOKENS.AuditLogger // GDPR-compliant audit logger
TOKENS.HealthService // Server health-check service
import { createDefaultContainer } from './di/container.js';
import { TOKENS } from './di/tokens.js';
import type { MetricsService } from './services/MetricsService.js';
// In server startup:
const container = createDefaultContainer();
// Resolve a singleton:
const metrics = container.resolve<MetricsService>(TOKENS.MetricsService);
metrics.recordRequest('get_meps', 42);
createDefaultContainer() in src/di/container.tsepClient singleton imported directly from
src/clients/europeanParliamentClient.ts (it is wired into the container internally)All PRs must maintain these coverage thresholds:
| Metric | Minimum |
|---|---|
| Lines | 80% |
| Statements | 80% |
| Functions | 80% |
| Branches | 70% |
| Security-critical code | 95% |
# Unit tests (fast, no external dependencies)
npm run test:unit
# Unit tests with coverage report
npm run test:coverage
# Integration tests against real EP API (opt-in)
EP_INTEGRATION_TESTS=true npm run test:integration
# Integration tests with fixture capture
EP_INTEGRATION_TESTS=true EP_SAVE_FIXTURES=true npm run test:integration
# End-to-end tests via MCP stdio client
npm run test:e2e
# Performance benchmarks
npm run test:performance
# All test suites
npm run test:all
# Watch mode for TDD
npm run test:watch
src/tools/myTool.test.ts # Unit tests co-located with tool
tests/integration/ # Integration tests (EP API)
tests/e2e/ # End-to-end MCP client tests
tests/performance/ # Performance benchmarks
tests/fixtures/ # Shared mock data
tests/helpers/ # Test utilities (retry, measureTime, etc.)
Reviewers will check:
any, no unvalidated unknown beyond the handler entry point@param, @returns, @throws, @examplebuildToolResponse, schema naming, etc.)Before requesting a review on any PR touching src/:
.parse(args) as first handler line)min() and max() length constraintsconsole.log of sensitive data (MEP personal data, error internals)npm audit — zero high/critical findingsSC-002 (Input Validation), AC-003 (Least Privilege)This project generates a Software Bill of Materials (SBOM) for every release and implements SLSA Level 3 build provenance to ensure supply chain transparency and security.
Build Attestations (SLSA Level 3):
gh attestation verify <artifact> --owner Hack23 --repo European-Parliament-MCP-Servernpm view european-parliament-mcp-server dist.attestationsSBOM Generation:
Accessing Security Artifacts:
sbom.spdx.json and sbom.cyclonedx.jsonprovenance.intoto.jsonlchecksums.txtFor more details, see: