isakskogstad

Personupplysning MCP Server

Community isakskogstad
Updated

MCP server för svensk företags- och persondata via Bolagsverket API och Supabase cache

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

Local Development

  1. Clone repository:
git clone <repo-url>
cd personupplysning
  1. Install dependencies:
npm install
  1. Setup environment:
cp .env.example .env
# Edit .env with your credentials
  1. Setup database:
npm run db:setup
  1. Import company data (optional):
npm run db:import
  1. Run in stdio mode (local):
npm run dev

🌐 Render Deployment

Deploy to Render

  1. Push to GitHub:
git init
git add .
git commit -m "Initial commit"
git remote add origin <your-github-repo>
git push -u origin main
  1. Create Render service:

    • Go to dashboard.render.com
    • Click "New +" → "Web Service"
    • Connect your GitHub repository
    • Render will detect render.yaml automatically
  2. 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>
  1. 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 connection
  • POST /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 iXBRL
  • api_request_log - Request logging och analytics

Storage

  • company-documents bucket - 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

  1. Check Render logs for startup errors
  2. Verify all environment variables are set
  3. Test health endpoint first
  4. 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:

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. 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)

MCP Server · Populars

MCP Server · New