Integrate SCB MCP server for statistical enrichment of news generation#652
Integrate SCB MCP server for statistical enrichment of news generation#652
Conversation
…rkflow files Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
…ntation Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
There was a problem hiding this comment.
Pull request overview
This PR integrates the SCB (Statistics Sweden) MCP server (scb-mcp.onrender.com/mcp) as an optional data source across all 10 news workflow agentic-workflow files, enabling political article generation to be enriched with official Swedish economic, demographic, and environmental statistics from 1,200+ SCB tables via PxWebAPI 2.0.
Changes:
- Added SCB MCP server entry to
.github/copilot-mcp.jsonand updated all 10news-*.mdworkflow files with network allowlist, MCP server config, and safe-outputs entries; 5 key workflows received enrichment usage examples with explicit try/catch and non-blocking guidance. - Added
SCBContext/SCBIndicatorTypeScript interfaces toscripts/data-transformers/types.tsandSCB_DOMAIN_TABLESconstant toscripts/data-transformers/policy-analysis.tsmapping all 12 policy domains to SCB table IDs and search queries. - Added 45 new integration tests in
tests/scb-mcp-integration.test.tsand updatedARCHITECTURE.mdwith SCB data source documentation, sequence/architecture diagrams, and a detailed scb-mcp server section.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
.github/copilot-mcp.json |
Adds SCB MCP server (http type, tools ["*"]) consistent with existing entries |
.github/workflows/news-*.md (×10) |
Adds scb-mcp.onrender.com to network allowlist, mcp-servers, and safe-outputs in all 10 workflow prompt files |
.github/workflows/news-evening-analysis.md |
Additionally includes detailed SCB usage examples with optional/try-catch guidance |
.github/workflows/news-{monthly-review,weekly-review,propositions,motions}.md |
Adds minimal SCB enrichment comments with try/catch guidance |
scripts/data-transformers/types.ts |
Adds SCBContext and SCBIndicator interfaces; adds scbContext? field to ArticleContentData |
scripts/data-transformers/policy-analysis.ts |
Adds exported SCB_DOMAIN_TABLES constant mapping all 12 DomainKey values to SCB queries, tables, and indicator names |
ARCHITECTURE.md |
Adds SCB to sequence diagrams, data sources table, MCP capability comparison, and new scb-mcp server documentation section |
tests/scb-mcp-integration.test.ts |
New test file with 45 tests validating SCB config across all 10 workflows, type definitions, and domain mapping |
Comments suppressed due to low confidence (1)
.github/workflows/news-article-generator.md:60
- The
.lock.ymlfiles (e.g.,news-article-generator.lock.yml) are the actual files executed by GitHub Actions, compiled from the.mdsources. They have not been updated in this PR and still lackscb-mcp.onrender.comin the firewall allowlist (line 757) and the safe-outputs allowed domains (line 840). The SCB MCP server will therefore be blocked at runtime by the gh-aw firewall and its outputs won't be trusted, making the integration non-functional despite the correct.mdconfiguration.
The lock files must be regenerated by running gh aw compile on the updated .md files before or as part of this PR. See .github/workflows/compile-agentic-workflows.yml for the compilation workflow (manual trigger).
mcp-servers:
riksdag-regering:
url: https://riksdag-regering-ai.onrender.com/mcp
scb:
url: https://scb-mcp.onrender.com/mcp
tools:
github:
toolsets:
- all
bash: true
microsoft/playwright:
command: npx
args: ["-y", "@playwright/mcp@latest", "--headless"]
env:
| export interface SCBContext { | ||
| /** Unemployment rate data (national/regional) */ | ||
| unemployment?: SCBIndicator; | ||
| /** GDP growth data */ | ||
| gdpGrowth?: SCBIndicator; | ||
| /** Inflation / CPI data */ | ||
| inflation?: SCBIndicator; | ||
| /** Population statistics */ | ||
| population?: SCBIndicator; | ||
| /** Immigration / emigration data */ | ||
| migration?: SCBIndicator; | ||
| /** Education enrollment statistics */ | ||
| education?: SCBIndicator; | ||
| /** Greenhouse gas emissions */ | ||
| emissions?: SCBIndicator; | ||
| /** Housing construction / prices */ | ||
| housing?: SCBIndicator; | ||
| /** Government revenue / expenditure */ | ||
| publicFinances?: SCBIndicator; | ||
| /** Crime statistics */ | ||
| crime?: SCBIndicator; | ||
| } |
There was a problem hiding this comment.
The SCBContext interface in types.ts is misaligned with SCB_DOMAIN_TABLES in two ways:
-
SCBContextincludesinflation?: SCBIndicatorandpopulation?: SCBIndicatorfields, but neither corresponds to any of the 12 domain keys inSCB_DOMAIN_TABLES. There is no domain mapped to inflation (CPI/KPI tables) or population data. -
SCB_DOMAIN_TABLEShas four domains (defence,healthcare,transport,eu-foreign) that have no corresponding field inSCBContext, making them inaccessible through the typedscbContextobject onArticleContentData.
Consider either adding the missing SCBContext fields (e.g., defence, healthcare, transport, euForeign) or adding corresponding domain entries in SCB_DOMAIN_TABLES for inflation and population, to keep both structures in sync.
There was a problem hiding this comment.
Fixed in bac472c. SCBContext now has fields for all 12 SCB_DOMAIN_TABLES domains: publicFinances (fiscal), defence, emissions (environment), education, healthcare, migration, euForeign (eu-foreign), crime (justice), unemployment (labour), housing, transport, gdpGrowth (trade). inflation and population are retained as cross-domain indicators.
tests/scb-mcp-integration.test.ts
Outdated
| // Should map all 12 policy domains | ||
| const domains = ['fiscal', 'defence', 'environment', 'education', 'healthcare', | ||
| 'migration', 'justice', 'labour', 'housing', 'transport', 'trade']; | ||
|
|
||
| domains.forEach(domain => { | ||
| expect(content).toContain(`${domain}:`); | ||
| }); | ||
|
|
||
| // eu-foreign uses quoted key syntax | ||
| expect(content).toContain("'eu-foreign':"); |
There was a problem hiding this comment.
The test at lines 146-154 uses a content-string search to verify all 12 domains are present in SCB_DOMAIN_TABLES. However, since policy-analysis.ts also contains the pre-existing DOMAIN_NAMES constant with the same domain keys, the test would pass even if a domain was missing from SCB_DOMAIN_TABLES (as long as it exists in DOMAIN_NAMES). For example, if healthcare: were accidentally omitted from SCB_DOMAIN_TABLES, the test would still pass because healthcare: exists at line 94 of policy-analysis.ts in DOMAIN_NAMES.
The test should narrow the search to the content after export const SCB_DOMAIN_TABLES to isolate it from the rest of the file.
| // Should map all 12 policy domains | |
| const domains = ['fiscal', 'defence', 'environment', 'education', 'healthcare', | |
| 'migration', 'justice', 'labour', 'housing', 'transport', 'trade']; | |
| domains.forEach(domain => { | |
| expect(content).toContain(`${domain}:`); | |
| }); | |
| // eu-foreign uses quoted key syntax | |
| expect(content).toContain("'eu-foreign':"); | |
| const scbDomainTablesIndex = content.indexOf('export const SCB_DOMAIN_TABLES'); | |
| expect(scbDomainTablesIndex).toBeGreaterThan(-1); | |
| const scbDomainTablesContent = content.slice(scbDomainTablesIndex); | |
| // Should map all 12 policy domains | |
| const domains = ['fiscal', 'defence', 'environment', 'education', 'healthcare', | |
| 'migration', 'justice', 'labour', 'housing', 'transport', 'trade']; | |
| domains.forEach(domain => { | |
| expect(scbDomainTablesContent).toContain(`${domain}:`); | |
| }); | |
| // eu-foreign uses quoted key syntax | |
| expect(scbDomainTablesContent).toContain("'eu-foreign':"); |
There was a problem hiding this comment.
Fixed in bac472c. The test now slices content from export const SCB_DOMAIN_TABLES before checking domain keys, preventing false positives from DOMAIN_NAMES.
|
|
||
| **See:** [SECURITY_ARCHITECTURE.md](SECURITY_ARCHITECTURE.md) for full security details | ||
|
|
||
| #### scb-mcp Server (Statistics Sweden) | ||
|
|
||
| **Purpose:** Provides access to 1,200+ statistical tables from Statistics Sweden (SCB) for enriching political analysis with official economic, demographic, and social indicators. | ||
|
|
||
| **Configuration:** | ||
| ```json | ||
| { | ||
| "scb": { | ||
| "type": "http", | ||
| "url": "https://scb-mcp.onrender.com/mcp", | ||
| "tools": ["*"] | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| **Available Tools:** | ||
|
|
||
| 1. **search_tables** — Search SCB's 1,200+ statistical tables by keyword (Swedish/English) | ||
| 2. **get_table_data** — Retrieve data from a specific table with variable selections | ||
| 3. **get_table_variables** — List available variables and value domains for a table | ||
| 4. **preview_data** — Preview first rows of a table before full retrieval | ||
| 5. **find_region_code** — Lookup region codes for geographic filtering | ||
|
|
||
| **Policy Domain Mapping:** | ||
|
|
||
| | Policy Domain | SCB Search Query | Example Tables | Key Indicators | | ||
| |---------------|-----------------|----------------|----------------| | ||
| | Fiscal Policy | skatter statsbudget | TAB1291, TAB1292 | Revenue, expenditure, budget balance | | ||
| | Labour Market | sysselsättning arbetslöshet | TAB5765, TAB5616 | Unemployment rate, employment rate | | ||
| | Migration | invandring utvandring befolkning | TAB637, TAB4230 | Immigration, emigration, net migration | | ||
| | Education | utbildning studenter | TAB4787, TAB4790 | Enrollment, graduation rates | | ||
| | Environment | växthusgaser utsläpp | TAB5404, TAB5407 | GHG emissions, renewable energy share | | ||
| | Trade & Industry | näringsliv företag BNP | TAB5802, TAB5803 | GDP growth, industrial production | | ||
| | Housing | bostäder nybyggnation | TAB2052, TAB4709 | Housing starts, price index | | ||
| | Justice | brott lagföringar | TAB1172 | Reported crimes, conviction rate | | ||
|
|
||
| **Data Source:** https://www.scb.se/ (PxWebAPI 2.0 — official Swedish statistics API) | ||
|
|
||
| **Use Cases:** | ||
| 1. **Proposition Analysis** — Enrich budget propositions with actual fiscal/economic data | ||
| 2. **Motion Context** — Add statistical evidence to opposition motion analysis | ||
| 3. **Monthly Reviews** — Include key economic indicators (GDP, unemployment, inflation) | ||
| 4. **Weekly Context** — Add trend data for economic policy discussions | ||
| 5. **Evening Analysis** — Statistical grounding for political developments | ||
|
|
||
| **Integration Pattern:** | ||
| - SCB data is **optional enrichment** — article generation never blocks on SCB failures | ||
| - All SCB MCP calls are wrapped in try/catch with graceful fallback | ||
| - SCB data adds "Statistical Context" sections to articles when available | ||
| - Domain-to-table mapping in `scripts/data-transformers/policy-analysis.ts` (`SCB_DOMAIN_TABLES`) | ||
|
|
||
| **Security Considerations:** | ||
| - **HTTP-only MCP server** — No local execution risk, remote hosting on Render | ||
| - **Public data sources only** — SCB is an official government statistics agency | ||
| - **No authentication required** — Public API access, no API keys | ||
| - **No PII** — Aggregate statistics only, no individual-level data | ||
|
|
||
| --- | ||
|
|
||
| ## 📄 Document Control |
There was a problem hiding this comment.
The Last Updated date in the Document Control table is 2026-02-20 but the ARCHITECTURE.md has been modified in this PR. This date should be updated to reflect when the SCB MCP documentation was added.
There was a problem hiding this comment.
Fixed in bac472c. Both the header and Document Control table now show 2026-02-28 (UTC).
ARCHITECTURE.md
Outdated
| - Domain-to-table mapping in `scripts/data-transformers/policy-analysis.ts` (`SCB_DOMAIN_TABLES`) | ||
|
|
||
| **Security Considerations:** | ||
| - **HTTP-only MCP server** — No local execution risk, remote hosting on Render |
There was a problem hiding this comment.
The security consideration states "HTTP-only MCP server" but the configured URL is https://scb-mcp.onrender.com/mcp, which uses HTTPS. This should be corrected to "HTTPS MCP server" or "no local execution risk" to accurately describe the security profile.
| - **HTTP-only MCP server** — No local execution risk, remote hosting on Render | |
| - **HTTPS MCP server** — No local execution risk, remote hosting on Render |
There was a problem hiding this comment.
Fixed in bac472c. Both occurrences (riksdag-regering-mcp and scb-mcp sections) now read "HTTPS MCP server".
| | Environment | växthusgaser utsläpp | TAB5404, TAB5407 | GHG emissions, renewable energy share | | ||
| | Trade & Industry | näringsliv företag BNP | TAB5802, TAB5803 | GDP growth, industrial production | | ||
| | Housing | bostäder nybyggnation | TAB2052, TAB4709 | Housing starts, price index | | ||
| | Justice | brott lagföringar | TAB1172 | Reported crimes, conviction rate | |
There was a problem hiding this comment.
The Policy Domain Mapping table in ARCHITECTURE.md only lists 8 out of the 12 domains defined in SCB_DOMAIN_TABLES (fiscal, labour, migration, education, environment, trade/industry, housing, justice). Four domains — defence, healthcare, transport, and eu-foreign — are omitted from this documentation table. This creates a discrepancy between the code and the architecture documentation, which could mislead developers about what domains are actually mapped.
| | Justice | brott lagföringar | TAB1172 | Reported crimes, conviction rate | | |
| | Justice | brott lagföringar | TAB1172 | Reported crimes, conviction rate | | |
| | Defence & Security | försvar säkerhet totalförsvar | TAB3101, TAB3102 | Defence spending, personnel, readiness indicators | | |
| | Healthcare | hälso- och sjukvård vårdkonsumtion | TAB2301, TAB2302 | Healthcare expenditure, hospital capacity, waiting times | | |
| | Transport & Infrastructure | transport infrastruktur trafik | TAB2801, TAB2802 | Passenger volume, freight volume, infrastructure investment | | |
| | EU & Foreign Policy | utrikeshandel eu politik | TAB4001, TAB4002 | Exports, imports, EU contributions, international agreements | |
There was a problem hiding this comment.
Fixed in bac472c. Added all 4 missing domains (Defence & Security, Healthcare, Transport, EU & Foreign Affairs) to the Policy Domain Mapping table.
|
@copilot apply changes based on the comments in this thread |
…isolation, update ARCHITECTURE.md Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
All 5 review comments addressed in bac472c:
|
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
.github/workflows/news-article-generator.md:56
- The
.lock.ymlfiles (e.g.,news-article-generator.lock.yml,news-evening-analysis.lock.yml, etc.) have not been regenerated after the corresponding.mdfiles were updated to add the SCB MCP server. The.lock.ymlfiles are the ones actually executed by GitHub Actions — they contain the inline MCP server configuration (theStart MCP Gatewaystep), the--allow-domainssandbox firewall list in theExecute GitHub Copilot CLIstep, and theGH_AW_ALLOWED_DOMAINSenvironment variable. None of these currently includescb-mcp.onrender.com, so at runtime the SCB MCP server will be inaccessible (blocked by the sandbox firewall) even though the.mdsource files describe it. Per the project convention, lock files must be regenerated withgh aw compileafter.mdfiles change. Thecompile-agentic-workflows.ymlworkflow can be triggered manually to do this.
mcp-servers:
riksdag-regering:
url: https://riksdag-regering-ai.onrender.com/mcp
scb:
url: https://scb-mcp.onrender.com/mcp
tools:
github:
toolsets:
- all
bash: true
| /** | ||
| * Test Suite for SCB MCP Integration | ||
| * | ||
| * Validates that the SCB (Statistics Sweden) MCP server is properly | ||
| * configured across the project for enriching political analysis | ||
| * with official Swedish statistics. | ||
| * | ||
| * SCB MCP tools: search_tables, get_table_data, get_table_variables, | ||
| * preview_data, find_region_code | ||
| * | ||
| * @author Hack23 AB | ||
| * @license Apache-2.0 | ||
| */ | ||
|
|
||
| import { describe, it, expect } from 'vitest'; | ||
| import fs from 'fs'; | ||
| import path from 'path'; | ||
| import { fileURLToPath } from 'url'; | ||
|
|
||
| const __filename = fileURLToPath(import.meta.url); | ||
| const __dirname = path.dirname(__filename); | ||
|
|
||
| const WORKFLOWS_DIR = path.join(__dirname, '..', '.github', 'workflows'); | ||
|
|
||
| /** All news workflow .md files */ | ||
| const ALL_NEWS_WORKFLOWS: readonly string[] = [ | ||
| 'news-article-generator.md', | ||
| 'news-committee-reports.md', | ||
| 'news-evening-analysis.md', | ||
| 'news-month-ahead.md', | ||
| 'news-monthly-review.md', | ||
| 'news-motions.md', | ||
| 'news-propositions.md', | ||
| 'news-realtime-monitor.md', | ||
| 'news-week-ahead.md', | ||
| 'news-weekly-review.md', | ||
| ]; | ||
|
|
||
| describe('SCB MCP Server Configuration', () => { | ||
| it('copilot-mcp.json should include scb MCP server', () => { | ||
| const configPath = path.join(__dirname, '..', '.github', 'copilot-mcp.json'); | ||
| const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); | ||
|
|
||
| expect(config.mcpServers).toHaveProperty('scb'); | ||
| expect(config.mcpServers.scb.type).toBe('http'); | ||
| expect(config.mcpServers.scb.url).toBe('https://scb-mcp.onrender.com/mcp'); | ||
| }); | ||
|
|
||
| ALL_NEWS_WORKFLOWS.forEach(workflow => { | ||
| it(`${workflow} should configure scb MCP server`, () => { | ||
| const filepath = path.join(WORKFLOWS_DIR, workflow); | ||
| const content = fs.readFileSync(filepath, 'utf-8'); | ||
|
|
||
| // Should have scb in mcp-servers section | ||
| expect(content).toContain('scb:'); | ||
| expect(content).toContain('https://scb-mcp.onrender.com/mcp'); | ||
| }); | ||
|
|
||
| it(`${workflow} should allow scb-mcp.onrender.com in network`, () => { | ||
| const filepath = path.join(WORKFLOWS_DIR, workflow); | ||
| const content = fs.readFileSync(filepath, 'utf-8'); | ||
|
|
||
| expect(content).toContain('scb-mcp.onrender.com'); | ||
| }); | ||
|
|
||
| it(`${workflow} should include scb-mcp.onrender.com in safe-outputs`, () => { | ||
| const filepath = path.join(WORKFLOWS_DIR, workflow); | ||
| const content = fs.readFileSync(filepath, 'utf-8'); | ||
|
|
||
| // The safe-outputs section should list scb-mcp.onrender.com | ||
| const safeOutputsSection = content.split('safe-outputs:')[1]?.split('steps:')[0] ?? ''; | ||
| expect(safeOutputsSection).toContain('scb-mcp.onrender.com'); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('SCB Enrichment Instructions in Key Workflows', () => { | ||
| const ENRICHED_WORKFLOWS: readonly string[] = [ | ||
| 'news-evening-analysis.md', | ||
| 'news-monthly-review.md', | ||
| 'news-weekly-review.md', | ||
| 'news-propositions.md', | ||
| 'news-motions.md', | ||
| ]; | ||
|
|
||
| ENRICHED_WORKFLOWS.forEach(workflow => { | ||
| it(`${workflow} should document SCB enrichment as optional`, () => { | ||
| const filepath = path.join(WORKFLOWS_DIR, workflow); | ||
| const content = fs.readFileSync(filepath, 'utf-8'); | ||
|
|
||
| // SCB should be documented as optional enrichment (never blocking) | ||
| const hasSCBReference = | ||
| content.includes('SCB') || | ||
| content.includes('scb') || | ||
| content.includes('search_tables'); | ||
|
|
||
| expect(hasSCBReference).toBe(true); | ||
| }); | ||
|
|
||
| it(`${workflow} should instruct try/catch for SCB calls`, () => { | ||
| const filepath = path.join(WORKFLOWS_DIR, workflow); | ||
| const content = fs.readFileSync(filepath, 'utf-8'); | ||
|
|
||
| // SCB calls should be wrapped in try/catch to avoid blocking | ||
| const hasSafetyGuidance = | ||
| content.includes('try/catch') || | ||
| content.includes('optional') || | ||
| content.includes('do not block'); | ||
|
|
||
| expect(hasSafetyGuidance).toBe(true); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('SCB Data Types', () => { | ||
| it('types.ts should export SCBContext and SCBIndicator', () => { | ||
| const typesPath = path.join(__dirname, '..', 'scripts', 'data-transformers', 'types.ts'); | ||
| const content = fs.readFileSync(typesPath, 'utf-8'); | ||
|
|
||
| expect(content).toContain('export interface SCBContext'); | ||
| expect(content).toContain('export interface SCBIndicator'); | ||
|
|
||
| // SCBContext should have fields aligned with all 12 SCB_DOMAIN_TABLES domains | ||
| expect(content).toContain('publicFinances'); // fiscal | ||
| expect(content).toContain('defence'); // defence | ||
| expect(content).toContain('emissions'); // environment | ||
| expect(content).toContain('education'); // education | ||
| expect(content).toContain('healthcare'); // healthcare | ||
| expect(content).toContain('migration'); // migration | ||
| expect(content).toContain('euForeign'); // eu-foreign | ||
| expect(content).toContain('crime'); // justice | ||
| expect(content).toContain('unemployment'); // labour | ||
| expect(content).toContain('housing'); // housing | ||
| expect(content).toContain('transport'); // transport | ||
| expect(content).toContain('gdpGrowth'); // trade | ||
| // Cross-domain indicators | ||
| expect(content).toContain('inflation'); | ||
| expect(content).toContain('population'); | ||
| }); | ||
|
|
||
| it('ArticleContentData should include scbContext field', () => { | ||
| const typesPath = path.join(__dirname, '..', 'scripts', 'data-transformers', 'types.ts'); | ||
| const content = fs.readFileSync(typesPath, 'utf-8'); | ||
|
|
||
| expect(content).toContain('scbContext?: SCBContext'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('SCB Policy Domain Mapping', () => { | ||
| it('policy-analysis.ts should export SCB_DOMAIN_TABLES', () => { | ||
| const analysisPath = path.join(__dirname, '..', 'scripts', 'data-transformers', 'policy-analysis.ts'); | ||
| const content = fs.readFileSync(analysisPath, 'utf-8'); | ||
|
|
||
| const scbDomainTablesIndex = content.indexOf('export const SCB_DOMAIN_TABLES'); | ||
| expect(scbDomainTablesIndex).toBeGreaterThan(-1); | ||
| const scbDomainTablesContent = content.slice(scbDomainTablesIndex); | ||
|
|
||
| // Should map all 12 policy domains | ||
| const domains = ['fiscal', 'defence', 'environment', 'education', 'healthcare', | ||
| 'migration', 'justice', 'labour', 'housing', 'transport', 'trade']; | ||
|
|
||
| domains.forEach(domain => { | ||
| expect(scbDomainTablesContent).toContain(`${domain}:`); | ||
| }); | ||
|
|
||
| // eu-foreign uses quoted key syntax | ||
| expect(scbDomainTablesContent).toContain("'eu-foreign':"); | ||
| }); | ||
|
|
||
| it('SCB_DOMAIN_TABLES entries should have query and indicators', () => { | ||
| const analysisPath = path.join(__dirname, '..', 'scripts', 'data-transformers', 'policy-analysis.ts'); | ||
| const content = fs.readFileSync(analysisPath, 'utf-8'); | ||
|
|
||
| // Each entry should have query (Swedish search terms) and indicators | ||
| expect(content).toContain('query:'); | ||
| expect(content).toContain('indicators:'); | ||
| expect(content).toContain('tables:'); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
The PR description claims "Add 55 tests for SCB MCP integration validation" but the test file only contains 45 test cases: 31 in describe('SCB MCP Server Configuration') (1 standalone + 10 workflows × 3 tests each), 10 in describe('SCB Enrichment Instructions in Key Workflows') (5 workflows × 2 tests each), 2 in describe('SCB Data Types'), and 2 in describe('SCB Policy Domain Mapping'). The PR description should be updated to reflect the accurate count of 45 tests.
There was a problem hiding this comment.
Corrected the PR description to accurately state 45 tests (not 55).
ARCHITECTURE.md
Outdated
| | **Last Updated** | 2026-02-20 (UTC) | | ||
| | **Next Review** | 2026-05-20 | | ||
| | **Last Updated** | 2026-02-28 (UTC) | | ||
| | **Next Review** | 2026-05-28 | |
There was a problem hiding this comment.
The ARCHITECTURE.md document has an inconsistency in the "Next Review" date. Line 20 in the document header still reads **⏰ Next Review:** 2026-05-20, while the Document Control table at line 1740 was updated in this PR to 2026-05-28. These two dates should be consistent — both should reflect the same next review date.
| | **Next Review** | 2026-05-28 | | |
| | **Next Review** | 2026-05-20 | |
There was a problem hiding this comment.
Fixed in 301a6b5. Document Control "Next Review" reverted to 2026-05-20 to match the header at line 20.
ARCHITECTURE.md
Outdated
|
|
||
| subgraph "MCP Servers" | ||
| RR[riksdag-regering-mcp<br/>HTTP: riksdag-regering-ai.onrender.com/mcp<br/>32 specialized tools] | ||
| SCB[scb-mcp<br/>HTTP: scb-mcp.onrender.com/mcp<br/>Statistics Sweden PxWebAPI 2.0] |
There was a problem hiding this comment.
The Mermaid diagram node label for the new SCB MCP server at line 1556 reads HTTP: scb-mcp.onrender.com/mcp, but the server uses HTTPS (as configured in .github/copilot-mcp.json and acknowledged in the security considerations text corrected elsewhere in this PR). The label should read HTTPS: scb-mcp.onrender.com/mcp to accurately reflect the transport protocol and be consistent with the security section.
| SCB[scb-mcp<br/>HTTP: scb-mcp.onrender.com/mcp<br/>Statistics Sweden PxWebAPI 2.0] | |
| SCB[scb-mcp<br/>HTTPS: scb-mcp.onrender.com/mcp<br/>Statistics Sweden PxWebAPI 2.0] |
There was a problem hiding this comment.
Fixed in 301a6b5. Mermaid diagram node now reads HTTPS: scb-mcp.onrender.com/mcp.
|
@copilot apply changes based on the comments in this thread |
…agram Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
All 3 review comments addressed in 301a6b5:
|
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
Adds the SCB MCP server (Statistics Sweden, 1,200+ tables via PxWebAPI 2.0) as an optional data source for enriching political analysis with official economic, labour, demographic, and environmental statistics.
MCP Configuration
scbserver (https://scb-mcp.onrender.com/mcp) to.github/copilot-mcp.jsonnews-*.mdworkflow files updated:network.allowed,mcp-servers,safe-outputs.allowed-domainsData Layer
SCBContext/SCBIndicatortypes added toscripts/data-transformers/types.tswithscbContextfield onArticleContentDataSCBContextfields aligned with all 12SCB_DOMAIN_TABLESdomains (publicFinances,defence,emissions,education,healthcare,migration,euForeign,crime,unemployment,housing,transport,gdpGrowth) plus cross-domain indicators (inflation,population)SCB_DOMAIN_TABLESconstant inpolicy-analysis.tsmaps all 12 policy domains to SCB table IDs and Swedish search queriesWorkflow Enrichment Instructions
5 key workflows (evening-analysis, monthly-review, weekly-review, propositions, motions) include SCB enrichment examples with explicit guidance that SCB is optional — all calls must be try/catch wrapped, failures never block article generation.
Architecture Documentation
ARCHITECTURE.md: SCB added to data sources table, MCP architecture diagram, news generation sequence diagram, and a new scb-mcp server section with tools/domain mapping/security considerationsTests
tests/scb-mcp-integration.test.tsvalidating SCB config across all 10 workflows, type definitions, and domain mapping completenessSCB_DOMAIN_TABLESsection to avoid false positives fromDOMAIN_NAMES🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.