Personupplysning MCP Server
MCP server för svensk företags- och persondata via Bolagsverket API och Supabase cache
Ett HTTP MCP-server som tillhandahåller sökfunktioner för svenska företag och hämtar detaljerad finansiell data från Bolagsverket, med lokal cache i Supabase för snabbare svar.
🚀 Features
- Företagssökning - Sök bland 1.85M svenska företag i lokal databas
- Företagsdetaljer - Hämta fullständig företagsinformation från Bolagsverket
- Årsredovisningar - Ladda ner och parsera iXBRL årsredovisningar
- Smart caching - Supabase cache-first strategi (30 dagar företagsdata, 7 dagar dokument)
- HTTP MCP Server - Publikt tillgänglig via Render deployment
- Local development - Stdio mode för lokal utveckling
📋 MCP Tools
| Tool | Description | Cache |
|---|---|---|
search_companies |
Sök företag lokalt (1.85M) | Lokal DB |
get_company_details |
Hämta företagsinfo | 30 dagar |
get_company_documents |
Lista årsredovisningar | 7 dagar |
get_annual_report |
Hämta iXBRL årsredovisning | Permanent |
get_cache_stats |
Cache-statistik | - |
🏗️ Architecture
┌─────────────┐ ┌──────────────┐
│ Claude │ ◄─────► │ HTTP MCP │
│ Desktop │ SSE │ Server │
└─────────────┘ │ (Render) │
└──────┬───────┘
│
┌──────┴───────┐
│ │
┌────▼────┐ ┌─────▼────┐
│Supabase │ │Bolagsver-│
│ Cache │ │ket API │
└─────────┘ └──────────┘
🛠️ Installation
Prerequisites
- Node.js 18+ och npm
- Supabase project (gratis tier fungerar)
- Bolagsverket API credentials (portal.api.bolagsverket.se)
Local Development
- Clone repository:
git clone <repo-url>
cd personupplysning
- Install dependencies:
npm install
- Setup environment:
cp .env.example .env
# Edit .env with your credentials
- Setup database:
npm run db:setup
- Import company data (optional):
npm run db:import
- Run in stdio mode (local):
npm run dev
🌐 Render Deployment
Deploy to Render
- Push to GitHub:
git init
git add .
git commit -m "Initial commit"
git remote add origin <your-github-repo>
git push -u origin main
Create Render service:
- Go to dashboard.render.com
- Click "New +" → "Web Service"
- Connect your GitHub repository
- Render will detect
render.yamlautomatically
Configure environment variables:
Add these in Render dashboard (Environment):
NODE_ENV=production
MCP_TRANSPORT=http
SUPABASE_URL=<your-supabase-url>
SUPABASE_SERVICE_ROLE_KEY=<your-service-role-key>
BOLAGSVERKET_CLIENT_ID=<your-client-id>
BOLAGSVERKET_CLIENT_SECRET=<your-client-secret>
- Deploy:
- Render will automatically build and deploy
- Your MCP server will be available at:
https://personupplysning-mcp.onrender.com/mcp
Connect from Claude Desktop
Add to your Claude Desktop MCP config (claude_desktop_config.json):
{
"mcpServers": {
"personupplysning": {
"type": "sse",
"url": "https://personupplysning-mcp.onrender.com/sse"
}
}
}
Note: The server uses SSE (Server-Sent Events) transport with two endpoints:
GET /sse- Establishes SSE connectionPOST /messages?sessionId=<id>- Sends JSON-RPC messages
📁 Project Structure
personupplysning/
├── src/
│ ├── index.ts # HTTP/stdio MCP server
│ ├── clients/
│ │ ├── bolagsverket-api.ts # Bolagsverket API client
│ │ └── __tests__/ # API client tests
│ └── services/
│ └── company-data-service.ts # Cache-first service layer
├── scripts/
│ ├── setup-supabase.ts # Database setup
│ ├── import-parquet.ts # Import 1.85M companies
│ ├── download-annual-report.ts # Example script
│ ├── check-tables.ts # Utility: Check tables
│ ├── verify-import.ts # Utility: Verify imports
│ └── schema.sql # Database schema
├── sql/
│ ├── 002-create-cache-tables.sql # Cache tables migration
│ └── 003-create-storage-bucket.sql # Storage setup
├── tests/
│ └── test-supabase.ts # Supabase connection test
├── docs/
│ └── CACHING-ARCHITECTURE.md # Architecture documentation
├── render.yaml # Render deployment config
├── .env.example # Environment template
├── tsconfig.json # TypeScript configuration
└── package.json # Project dependencies
🔧 Configuration
Environment Variables
| Variable | Description | Required |
|---|---|---|
NODE_ENV |
Environment (production/development) |
Yes |
MCP_TRANSPORT |
Transport mode (http/stdio) |
Yes |
PORT |
HTTP server port (default: 3000) | HTTP only |
HOST |
Bind address (default: 0.0.0.0) | HTTP only |
SUPABASE_URL |
Supabase project URL | Yes |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key | Yes |
BOLAGSVERKET_CLIENT_ID |
Bolagsverket OAuth2 client ID | Yes |
BOLAGSVERKET_CLIENT_SECRET |
Bolagsverket OAuth2 client secret | Yes |
Cache TTL Configuration
Cache expiration kan konfigureras i src/services/company-data-service.ts:
this.cacheTTL = 30 * 24 * 60 * 60 * 1000; // 30 days company details
this.documentCacheTTL = 7 * 24 * 60 * 60 * 1000; // 7 days document lists
📊 Database Schema
Tables
companies- 1.85M svenska företag (lokal kopia)company_details_cache- API-svar från Bolagsverket (30 dagar TTL)company_documents_cache- Dokumentlistor (7 dagar TTL)financial_reports- Parsad finansiell data från iXBRLapi_request_log- Request logging och analytics
Storage
company-documentsbucket - Lagrar nedladdade iXBRL ZIP-filer
🧪 Testing
Run tests:
npm test
Test specific file:
npm test -- bolagsverket-api.test.ts
Test API connection:
npx tsx scripts/download-annual-report.ts
📝 Development Scripts
| Script | Description |
|---|---|
npm run build |
Compile TypeScript → dist/ |
npm run dev |
Run in stdio mode (local) |
npm start |
Run compiled JS (production) |
npm test |
Run test suite |
npm run db:setup |
Setup Supabase schema |
npm run db:import |
Import 1.85M companies |
🔒 Security
- OAuth2 tokens cached with 1-minute safety buffer before expiry
- Service role key required for Supabase (never expose publicly)
- API credentials stored in environment variables only
- GDPR compliance - EU Render region (Frankfurt)
- No personal data persisted without consent
📈 Performance
- Cache hit rate: ~95% after warm-up
- Local search: < 100ms (Supabase full-text search)
- Cached company details: < 50ms
- Fresh API call: 1-3 seconds (Bolagsverket rate limits)
- iXBRL download: 2-5 seconds (depends on file size)
🐛 Troubleshooting
Health Check Fails
Check endpoint:
curl https://personupplysning-mcp.onrender.com/health
Expected response:
{
"status": "healthy",
"server": "personupplysning-mcp",
"version": "0.1.0",
"uptime": 123.45,
"endpoint": "/mcp",
"environment": {
"SUPABASE_URL": "configured",
"BOLAGSVERKET_CLIENT_ID": "configured"
}
}
MCP Connection Issues
- Check Render logs for startup errors
- Verify all environment variables are set
- Test health endpoint first
- Check Claude Desktop logs (
~/Library/Logs/Claude/)
Database Connection Failed
# Test Supabase connection
npx tsx tests/test-supabase.ts
Bolagsverket API 401/403
- Verify credentials in Render environment
- Check token expiry (should auto-refresh)
- Ensure OAuth2 scope:
vardefulla-datamangder:ping vardefulla-datamangder:read
📜 License
MIT
🤝 Contributing
Contributions welcome! Please follow these steps:
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
📧 Support
For issues or questions:
- Open a GitHub issue
- Check existing issues first
Built with: TypeScript, MCP SDK, Supabase, Bolagsverket APIDeployed on: Render (EU region - Frankfurt)