The EP MCP Server implements a 4-layer defense-in-depth security architecture aligned with OWASP best practices, ISO 27001, NIST CSF 2.0, and GDPR requirements. Since the server operates as an MCP stdio process (not a network-exposed server), the primary security concerns are:
Input validation β prevent malformed or malicious MCP tool arguments
API abuse prevention β protect EP Open Data Portal from overuse
Data privacy β GDPR-compliant handling of MEP personal data
Audit trail β full traceability of all data access
The server does not handle authentication tokens, passwords, or payment data, significantly reducing the attack surface.
π‘οΈ 4-Layer Security Architecture
flowchart TD
MCP_IN["MCP Tool Invocation\n(args: unknown)"]
subgraph L1["Layer 1: Input Validation"]
ZOD["Zod Schema Validation\nStrict type checking, format enforcement"]
ZE["ZodError β MCP error response"]
end
subgraph L2["Layer 2: Rate Limiting"]
RL["Token Bucket Rate Limiter\n100 tokens/minute"]
RLE["Rate limit exceeded β 429 response"]
end
subgraph L3["Layer 3: Audit Logging"]
AL["Audit Logger\nTool name, params (PII-stripped), timestamp, user context"]
end
subgraph L4["Layer 4: GDPR Compliance"]
GDPR["Data Minimization\nPurpose Limitation\nStorage Limitation"]
end
EP_API["EP Open Data Portal API v2\n(HTTPS/TLS)"]
RESULT["Tool Result β MCP Client"]
MCP_IN --> ZOD
ZOD -->|"invalid"| ZE
ZOD -->|"valid"| RL
RL -->|"exceeded"| RLE
RL -->|"token available"| AL
AL --> GDPR
GDPR --> EP_API
EP_API --> RESULT
π Security Controls Inventory
Control ID
Control Name
Type
Implementation
Status
SC-001
Input Validation
Preventive
Zod schema per tool (62 schemas) with .refine() cross-field constraints, date range validation, and format-specific ID validation
β Implemented
SC-002
Rate Limiting
Preventive
Token bucket, 100 req/min
β Implemented
SC-003
Audit Logging
Detective
AuditLogger singleton, all invocations
β Implemented
SC-004
GDPR Data Minimization
Preventive
Field selection, no over-fetching
β Implemented
SC-005
TLS in Transit
Preventive
HTTPS to EP API, Node TLS defaults
β Implemented
SC-006
Dependency Scanning
Detective
Dependabot, npm audit
β Implemented
SC-007
Static Analysis
Preventive
ESLint, TypeScript strict mode
β Implemented
SC-008
Secret Detection
Preventive
No secrets in codebase; env vars only
β Implemented
SC-009
Error Sanitization
Preventive
Internal errors not leaked to MCP clients
β Implemented
SC-010
Health Monitoring
Detective
HealthService singleton
β Implemented
SC-011
Metrics Collection
Detective
MetricsService, rate/error tracking
β Implemented
SC-012
Branded Types
Preventive
Zod branded types for EP identifiers
β Implemented
SC-013
Data Quality Controls
Preventive
OSINT outputs standardize confidence level and quality warnings; data availability status is included where implemented
β Implemented
βοΈ Threat Mitigation Mapping (STRIDE)
Threat Category
Specific Threat
Likelihood
Impact
Mitigation
Spoofing
Fake MCP client identity
Low
Low
stdio transport β client is the spawning process
The EP MCP Server operates as a local stdio process spawned by the MCP client (e.g., Claude Desktop). The security model relies on OS-level process isolation:
No network authentication β the server is not network-exposed
No user credentials β the server does not handle user tokens
Process isolation β only the spawning MCP client can communicate via stdio
EP API access β public open data, no authentication required by EP
Trust Boundaries
flowchart LR
subgraph TrustHigh["High Trust Zone"]
OS["Operating System"]
User["Local User Account"]
end
subgraph TrustMedium["Medium Trust Zone"]
MCP["MCP Client Process\n(Claude Desktop / Cursor)"]
Server["EP MCP Server Process"]
end
subgraph TrustLow["Low Trust Zone"]
Input["Tool Arguments\n(from AI-generated content)"]
end
subgraph External["Untrusted External"]
EPAPI["EP Open Data Portal\n(public internet)"]
end
OS --> MCP
MCP --> Server
Server --> Input
Input -->|"Zod validation"| Server
Server -->|"HTTPS"| EPAPI
Key principle: Tool arguments are treated as untrusted input regardless of their origin, since AI models may generate unexpected parameter values.
π Session and Action Tracking
All user interactions with the MCP server are tracked through the integrated audit and metrics systems:
Session Tracking Model
flowchart LR
subgraph SessionContext["Session Context"]
STDIO["stdio Connection\n(1 session per process)"]
TC["Tool Call Counter"]
TS["Session Start Time"]
end
subgraph ActionTracking["Action Tracking"]
AL["AuditLogger\n(every tool invocation)"]
MS["MetricsService\n(aggregated counters)"]
HS["HealthService\n(process health)"]
end
STDIO --> AL
STDIO --> MS
AL --> TC
MS --> TS
HS --> TC
Tracked Actions
Action Type
Tracked Fields
Storage
Purpose
Tool invocation
Tool name, sanitized params, timestamp, duration
stderr audit log
Full traceability
API request
URL, status, duration, cache hit/miss
MetricsService
Performance monitoring
Rate limit event
Token count, refill status, rejection
stderr audit log
Abuse detection
Error occurrence
Error type (no stack trace), tool context
stderr audit log
Incident response
Cache operation
Key, hit/miss, eviction
MetricsService
Efficiency tracking
Action Tracking Implementation
No persistent session storage β session state is in-memory only (process-scoped)
PII stripping β all logged parameters have personal data fields removed before logging
Structured logging β JSON format on stderr for machine-parseable audit trail
Per-tool metrics β invocation count, error count, average duration per tool
π Data Integrity and Auditing
Data Integrity Controls
Control
Implementation
Verification
Source integrity
All data sourced from official EP API over HTTPS/TLS
TLS certificate validation
Transport integrity
HTTPS with TLS 1.2+ for all API calls
Node.js default TLS verification
Cache integrity
In-memory LRU cache (no persistent storage) β no disk tampering risk
Process isolation
Cache key integrity
Deterministic cache key generation via sorted parameter keys
Prevents cache misses from property insertion order
Schema validation
Zod schemas validate all API responses before processing
TypeScript strict mode + runtime validation
Data quality integrity
OSINT outputs include DataAvailability and dataQualityWarnings (SC-013)
Consumers distinguish "zero" from "unavailable"
Audit immutability
Audit logs written to stderr (append-only within process)
No log modification API exposed
Package integrity
npm lockfile with exact versions, SLSA Level 3 provenance
Provenance attestations, Sigstore signing
Audit Trail Architecture
flowchart TD
ToolCall["Tool Invocation"] --> AuditLog["AuditLogger.logToolCall()"]
AuditLog --> PIIStrip["PII Stripping\n(remove personal data fields)"]
PIIStrip --> Format["JSON Structured Format"]
Format --> Stderr["stderr Output\n(append-only)"]
Stderr --> External["External Log Collection\n(host-managed)"]
Audit Log Fields
Field
Type
Description
timestamp
ISO 8601
Event occurrence time
toolName
string
MCP tool identifier
parameters
object
Sanitized input parameters (PII removed)
resultStatus
enum
success, error, rate_limited
durationMs
number
Execution duration
errorType
string?
Error category (no stack traces)
cacheHit
boolean?
Whether result came from cache
π‘οΈ Data Protection and GDPR
Personal Data Inventory
Data Category
EP API Endpoint
GDPR Basis
Retention in Cache
Minimization Applied
MEP Names
/meps/{id}
Public role (Art. 6.1.e)
15 min TTL
Name, group only
MEP Contact
/meps/{id}
Legitimate interest
15 min TTL
Official EP address only
MEP Votes
/votes
Public interest
15 min TTL
Vote record, no commentary
MEP Attendance
/plenary-sessions
Public interest
15 min TTL
Session data only
MEP Declarations
/meps/{id}/declarations
Public role
15 min TTL
Official declarations only
GDPR Principles Implementation
Principle
Implementation
Lawfulness
Processing public parliamentary records per Art. 6.1.e (public interest)
Purpose Limitation
Data used solely for parliamentary intelligence queries
Data Minimization
Field selection queries β only request needed attributes
Accuracy
Data sourced directly from official EP API
Storage Limitation
LRU cache with 15-min TTL; no persistent storage
Integrity and Confidentiality
HTTPS transport, no local file system writes
Accountability
Audit logging of all data access requests
π Network Security and Perimeter Protection
Outbound Connections
Destination
Protocol
Port
TLS
Purpose
data.europarl.europa.eu
HTTPS
443
TLS 1.2+
EP Open Data Portal API v2
EP Vocabulary endpoints
HTTPS
443
TLS 1.2+
AT4EU taxonomy lookups
Security Headers (Outbound Requests)
// Applied to all EP API requests headers: { 'Accept': 'application/json', 'User-Agent': 'European-Parliament-MCP-Server/1.1', 'Accept-Encoding': 'gzip, deflate, br' }
No Inbound Network Exposure
Server operates exclusively via stdio (no listening sockets)
No HTTP server, no WebSocket server in current v1.1
All tool errors are reported via the ToolError class which carries toolName, operation, isRetryable, and optional cause β ensuring structured error reporting without leaking internal implementation details. Success responses use buildToolResponse() for consistent JSON formatting.
Error Type
Response to Client
Logged Internally
Zod validation error
Structured field errors
Full error details
EP API error (4xx)
Generic "API error" message
Status code, URL, response body
EP API error (5xx)
Generic "service unavailable"
Full error details
Network timeout
"Request timeout"
URL, timeout duration
Rate limit exceeded
"Rate limit exceeded"
Token state, request details
Unexpected error
"Internal error"
Full stack trace (internal only)
π Defense-in-Depth Strategy
Security Layer Architecture
flowchart TD
subgraph Layer1["Layer 1: Process Isolation"]
OS["OS Process Boundaries"]
STDIO["stdio Transport\n(no network exposure)"]
end
subgraph Layer2["Layer 2: Input Validation"]
ZOD["Zod Schema Validation\n(62 tool schemas)"]
BT["Branded Types\n(type-safe identifiers)"]
end
subgraph Layer3["Layer 3: Rate Limiting & Caching"]
RL["Token Bucket Rate Limiter"]
LRU["LRU Cache\n(bounded memory)"]
end
subgraph Layer4["Layer 4: Transport Security"]
TLS["HTTPS/TLS 1.2+\n(to EP API)"]
CERT["Certificate Validation\n(Node.js defaults)"]
end
subgraph Layer5["Layer 5: Audit & Monitoring"]
AUDIT["Audit Logger\n(PII-stripped)"]
METRICS["MetricsService\n(performance + errors)"]
HEALTH["HealthService\n(availability)"]
end
subgraph Layer6["Layer 6: Supply Chain Security"]
SLSA["SLSA Level 3 Provenance"]
DEPS["Minimal Dependencies (4)"]
LOCK["Lockfile Pinning"]
SCAN["Dependabot + CodeQL"]
end
Layer1 --> Layer2 --> Layer3 --> Layer4 --> Layer5 --> Layer6