feat(api): NLgov ADR compliance and multi-tenant reporting MCP server#56
Open
rawand-shakir-draad wants to merge 4 commits into
Open
feat(api): NLgov ADR compliance and multi-tenant reporting MCP server#56rawand-shakir-draad wants to merge 4 commits into
rawand-shakir-draad wants to merge 4 commits into
Conversation
…oning, RFC 9457 errors) Brings /api/project/:projectId/reports/* in line with the Dutch government API Design Rules: version the path (/v1), publish a generated OpenAPI 3.x spec at /openapi.json, and reshape every error response (400/401/403/500) into application/problem+json (RFC 9457), collecting all validation errors found on a request into a single response instead of one at a time.
New apps/mcp-server: a thin, stateless MCP (Model Context Protocol) server wrapping /api/project/:projectId/reports/v1/* as 12 curated tools (one per endpoint, no generic passthrough), so LLM clients can query reporting data without the bearer token ever entering their context. The token and project id are held server-side and injected per request. Includes a shared-secret auth gate on /mcp (required whenever the server binds beyond localhost), safe cleanup of the per-request McpServer/transport on both success and error paths, and problem+json error detail folded into the message text so it reaches the model instead of being silently dropped.
…RS on openapi.json Two NLgov ADR gaps found during a manual audit against developer.overheid.nl: - API-Version was missing on 403s from api-token-scope-guard.js, which is mounted globally before routes/api/reports/index.js and never reached that router's own header middleware. Extracted the version string into a shared module and set the header directly in the guard too. - /openapi.json only got a wildcard Access-Control-Allow-Origin in local dev (via a dev-only config override), not guaranteed in production. Hardcoded '*' on that one route, and cleared Access-Control-Allow-Credentials there too (security-headers.js sets it unconditionally elsewhere, and the Fetch/CORS spec forbids combining it with a wildcard origin).
…equest Replace the single-tenant, process-per-project design with a shared server that holds no reporting credentials of its own. Each /mcp request now carries its own Authorization: Bearer <token> and X-Reporting-Project-Id header, extracted per request into a request-scoped config; missing/invalid credentials surface as an MCP tool error instead of rejecting the connection. Drops the now-unneeded shared-secret auth gate and its fail-closed localhost guard, since the server no longer holds a secret worth gating. Validates X-Reporting-Project-Id as numeric before it reaches URL construction, since it's interpolated into the outbound reporting API path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
API-Versionheader on all responses, RFC 9457 (problem+json) error format, wildcard CORS onopenapi.jsonapps/mcp-server: exposes the reporting API as curated MCP tools so an LLM client (e.g. Claude Desktop) can query reporting data without the model ever seeing a bearer tokenAuthorization: Bearer <token>+X-Reporting-Project-Idheader, extracted per-request into a request-scoped config, so one deployment can serve every municipality