507 lines
14 KiB
Markdown
507 lines
14 KiB
Markdown
# KISC MCP Server - MCPF Integration Deployment Guide
|
|
|
|
**Project:** MCPF (MCP Trust Framework) Integration for KISC MCP Server
|
|
**Target Server:** llm.kis.gov.lv
|
|
**DID:** `did:web:llm.kis.gov.lv`
|
|
**Date:** 2026-01-30
|
|
|
|
---
|
|
|
|
## 📋 Table of Contents
|
|
|
|
1. [Overview](#overview)
|
|
2. [Package Contents](#package-contents)
|
|
3. [Prerequisites](#prerequisites)
|
|
4. [Part A: Local Implementation](#part-a-local-implementation)
|
|
5. [Part B: VeriTrust Integration](#part-b-veritrust-integration)
|
|
6. [Validation & Testing](#validation--testing)
|
|
7. [Troubleshooting](#troubleshooting)
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
This package integrates MCPF (MCP Trust Framework) into the KISC MCP Server, providing:
|
|
|
|
✅ **Cryptographic Identity** — `did:web:llm.kis.gov.lv` with Ed25519 signing
|
|
✅ **Verifiable Credentials** — VeriTrust-issued MCPServerCredential
|
|
✅ **Trust Metadata** — Discoverable at `/.well-known/mcp-trust-registry.json`
|
|
✅ **Standards Compliance** — W3C DID Core, VC Data Model, MCPF Specification
|
|
|
|
---
|
|
|
|
## Package Contents
|
|
|
|
```
|
|
kisc-mcpf-deploy/
|
|
├── README.md # This file
|
|
├── keypair-SECURE.json # ⚠️ PRIVATE KEY (secure handling!)
|
|
├── public-key.json # Public key reference
|
|
│
|
|
├── wellknown/ # .well-known files for nginx
|
|
│ ├── did.json # DID Document
|
|
│ ├── jwks.json # JWK Set (public keys)
|
|
│ ├── mcp-trust-registry.json # MCPF registry discovery
|
|
│ ├── security.txt # RFC 9116 security contact
|
|
│ ├── mcp/
|
|
│ │ └── manifest.json # MCP server capabilities
|
|
│ └── credentials/
|
|
│ └── mcp-server.json # VC placeholder (VeriTrust will replace)
|
|
│
|
|
├── scripts/ # Deployment automation
|
|
│ ├── deploy-wellknown.sh # Deploy .well-known to server
|
|
│ ├── validate-endpoints.sh # Test all endpoints
|
|
│ └── update-env.sh # Add MCPF_PRIVATE_KEY to .env
|
|
│
|
|
├── nginx/ # nginx configuration
|
|
│ └── wellknown.conf # nginx config for .well-known
|
|
│
|
|
├── docs/ # Documentation
|
|
│ ├── DEPLOYMENT.md # Step-by-step deployment
|
|
│ ├── INTEGRATION.md # start.sh/status.sh updates
|
|
│ └── TESTING.md # Validation procedures
|
|
│
|
|
└── veritrust/ # VeriTrust submission
|
|
├── README-VERITRUST.md # Instructions for VeriTrust
|
|
├── mcp-server-request.json # Credential request payload
|
|
└── install-credential.sh # Install received VC
|
|
```
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
Before deployment, ensure:
|
|
|
|
- [ ] SSH access to `llm.kis.gov.lv` (10.20.30.96)
|
|
- [ ] Sudo privileges or ownership of `/opt/kisc-llm/`
|
|
- [ ] POC stack running (`/opt/kisc-llm/poc/deploy/`)
|
|
- [ ] nginx container (kisc-nginx) operational
|
|
- [ ] Let's Encrypt certificates valid
|
|
- [ ] Git access to `kisc-gov-lv/MCP-KISC-architecture`
|
|
|
|
---
|
|
|
|
## Part A: Local Implementation
|
|
|
|
### Step 1: Secure Private Key Storage
|
|
|
|
**⚠️ CRITICAL: Handle `keypair-SECURE.json` securely!**
|
|
|
|
```bash
|
|
# On your local machine (NOT on server yet)
|
|
cat keypair-SECURE.json
|
|
# Contains: private_key_pem, public_key_pem, multibase, jwk_x
|
|
|
|
# Verify integrity
|
|
sha256sum keypair-SECURE.json
|
|
```
|
|
|
|
**DO NOT:**
|
|
- ❌ Commit to Git
|
|
- ❌ Send via unencrypted email
|
|
- ❌ Store in Slack/Teams
|
|
- ❌ Print to logs
|
|
|
|
**DO:**
|
|
- ✅ Transfer via encrypted channel (scp with key auth, 1Password, etc.)
|
|
- ✅ Store in `/opt/kisc-llm/poc/deploy/.env` only
|
|
- ✅ Backup offline (encrypted USB/vault)
|
|
- ✅ Document who has access
|
|
|
|
---
|
|
|
|
### Step 2: Deploy .well-known Files to Server
|
|
|
|
```bash
|
|
# On llm.kis.gov.lv server
|
|
|
|
# 1. Create .well-known directory
|
|
sudo mkdir -p /opt/kisc-llm/poc/deploy/.well-known/{mcp,credentials}
|
|
sudo chown -R "$USER":"$USER" /opt/kisc-llm/poc/deploy/.well-known
|
|
|
|
# 2. Copy .well-known files
|
|
cd /opt/kisc-llm/poc/deploy
|
|
rsync -av /path/to/kisc-mcpf-deploy/wellknown/ .well-known/
|
|
|
|
# 3. Verify structure
|
|
tree .well-known/
|
|
# Expected:
|
|
# .well-known/
|
|
# ├── did.json
|
|
# ├── jwks.json
|
|
# ├── mcp-trust-registry.json
|
|
# ├── security.txt
|
|
# ├── mcp/
|
|
# │ └── manifest.json
|
|
# └── credentials/
|
|
# └── mcp-server.json
|
|
|
|
# 4. Set permissions (read-only for nginx)
|
|
chmod -R 644 .well-known/**/*
|
|
find .well-known -type d -exec chmod 755 {} \;
|
|
```
|
|
|
|
---
|
|
|
|
### Step 3: Add Private Key to .env
|
|
|
|
```bash
|
|
# On llm.kis.gov.lv server
|
|
cd /opt/kisc-llm/poc/deploy
|
|
|
|
# Extract private key from keypair-SECURE.json
|
|
PRIVATE_KEY_PEM=$(cat /path/to/keypair-SECURE.json | jq -r '.private_key_pem')
|
|
|
|
# Add to .env (replace newlines with \n)
|
|
echo "MCPF_PRIVATE_KEY=\"$PRIVATE_KEY_PEM\"" >> .env
|
|
|
|
# Verify (should show -----BEGIN PRIVATE KEY-----)
|
|
grep MCPF_PRIVATE_KEY .env | head -c 100
|
|
|
|
# Secure the .env file
|
|
chmod 600 .env
|
|
```
|
|
|
|
---
|
|
|
|
### Step 4: Update nginx Configuration
|
|
|
|
```bash
|
|
# On llm.kis.gov.lv server
|
|
cd /opt/kisc-llm/poc/deploy/nginx/conf.d
|
|
|
|
# Backup existing config
|
|
cp default.conf default.conf.backup-$(date +%Y%m%d)
|
|
|
|
# Add .well-known location block (insert after line 30, before "location /")
|
|
cat >> default.conf << 'EOF'
|
|
|
|
# ==========================================================================
|
|
# MCPF .well-known endpoints
|
|
# ==========================================================================
|
|
location /.well-known/ {
|
|
alias /opt/kisc-llm/poc/deploy/.well-known/;
|
|
|
|
# CORS headers for trust framework discovery
|
|
add_header Access-Control-Allow-Origin * always;
|
|
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
|
add_header Access-Control-Allow-Headers "Content-Type" always;
|
|
|
|
# Cache DID documents for 1 hour (they rarely change)
|
|
add_header Cache-Control "public, max-age=3600" always;
|
|
|
|
# Serve JSON files
|
|
location ~ \.(json)$ {
|
|
add_header Content-Type application/json;
|
|
}
|
|
|
|
# Serve text files
|
|
location ~ \.(txt)$ {
|
|
add_header Content-Type text/plain;
|
|
}
|
|
|
|
# No directory listing
|
|
autoindex off;
|
|
}
|
|
|
|
EOF
|
|
|
|
# Validate nginx config
|
|
docker exec kisc-nginx nginx -t
|
|
|
|
# If validation passes, reload
|
|
docker exec kisc-nginx nginx -s reload
|
|
```
|
|
|
|
---
|
|
|
|
### Step 5: Update start.sh Script
|
|
|
|
Add MCPF integration steps to `/opt/kisc-llm/poc/deploy/scripts/start.sh`:
|
|
|
|
```bash
|
|
# Insert after Step 3 (TLS cert handling), before Step 4 (OpenGateLLM start)
|
|
|
|
# =============================================================================
|
|
# Step 3.5: MCPF .well-known Files
|
|
# =============================================================================
|
|
log_step "Step 3.5: Checking MCPF .well-known files..."
|
|
|
|
if [[ ! -f "$DEPLOY_DIR/.well-known/did.json" ]]; then
|
|
log_error "MCPF .well-known files not found!"
|
|
log_error "Run: rsync -av /path/to/wellknown/ $DEPLOY_DIR/.well-known/"
|
|
exit 1
|
|
fi
|
|
|
|
# Verify critical files exist
|
|
REQUIRED_FILES=(
|
|
".well-known/did.json"
|
|
".well-known/jwks.json"
|
|
".well-known/mcp-trust-registry.json"
|
|
".well-known/mcp/manifest.json"
|
|
".well-known/credentials/mcp-server.json"
|
|
)
|
|
|
|
for file in "${REQUIRED_FILES[@]}"; do
|
|
if [[ ! -f "$DEPLOY_DIR/$file" ]]; then
|
|
log_warn "Missing: $file"
|
|
fi
|
|
done
|
|
|
|
log_info "MCPF .well-known files OK"
|
|
```
|
|
|
|
---
|
|
|
|
### Step 6: Update status.sh Script
|
|
|
|
Add MCPF health checks to `/opt/kisc-llm/poc/deploy/scripts/status.sh`:
|
|
|
|
```bash
|
|
# Insert at the end, before final completion message
|
|
|
|
# =============================================================================
|
|
# MCPF ENDPOINTS STATUS
|
|
# =============================================================================
|
|
echo -e "${CYAN}MCPF Endpoints:${NC}"
|
|
echo "----------------------------------------"
|
|
|
|
check_wellknown() {
|
|
local endpoint=$1
|
|
local name=$2
|
|
local response
|
|
response=$(curl -sS -k --connect-timeout 2 "https://localhost$endpoint" 2>/dev/null || echo "")
|
|
|
|
if [[ -n "$response" ]] && echo "$response" | grep -q "@context\|keys\|mcpfVersion"; then
|
|
echo -e " ${GREEN}✅${NC} $name"
|
|
else
|
|
echo -e " ${RED}❌${NC} $name (HTTP error or empty response)"
|
|
fi
|
|
}
|
|
|
|
check_wellknown "/.well-known/did.json" "DID Document"
|
|
check_wellknown "/.well-known/jwks.json" "JWKS"
|
|
check_wellknown "/.well-known/mcp-trust-registry.json" "MCPF Registry Discovery"
|
|
check_wellknown "/.well-known/mcp/manifest.json" "MCP Manifest"
|
|
check_wellknown "/.well-known/credentials/mcp-server.json" "MCP Credential"
|
|
|
|
echo ""
|
|
```
|
|
|
|
---
|
|
|
|
### Step 7: Validate Deployment
|
|
|
|
```bash
|
|
# On llm.kis.gov.lv server
|
|
cd /opt/kisc-llm/poc/deploy
|
|
|
|
# Test .well-known endpoints
|
|
./scripts/validate-endpoints.sh
|
|
|
|
# Expected output:
|
|
# ✅ DID Document: https://llm.kis.gov.lv/.well-known/did.json
|
|
# ✅ JWKS: https://llm.kis.gov.lv/.well-known/jwks.json
|
|
# ✅ MCPF Registry: https://llm.kis.gov.lv/.well-known/mcp-trust-registry.json
|
|
# ✅ MCP Manifest: https://llm.kis.gov.lv/.well-known/mcp/manifest.json
|
|
# ✅ MCP Credential: https://llm.kis.gov.lv/.well-known/credentials/mcp-server.json
|
|
```
|
|
|
|
---
|
|
|
|
## Part B: VeriTrust Integration
|
|
|
|
### Step 8: Submit to VeriTrust for Credential Issuance
|
|
|
|
**KISC already has a VeriTrust profile!**
|
|
|
|
Existing KISC DID in VeriTrust:
|
|
- `did:key:z6Mkuwv1z6y2yorbBf4LEkNzJCg16ERVfWE3bJEPKXtQm7a9` (Holder DID)
|
|
- `did:web:veritrust.vc:portal:company:df0684bd-b54a-4684-b3d6-93a3b1c4bcb9` (Public Alias)
|
|
|
|
**Action Required:**
|
|
|
|
1. **Contact VeriTrust** via existing relationship
|
|
2. **Request MCPServerCredential** for `did:web:llm.kis.gov.lv`
|
|
3. **Provide:**
|
|
- DID: `did:web:llm.kis.gov.lv`
|
|
- Public Key (multibase): `z6MkjWGNnJsdyvutfbsytFJhkwDwyHkMkfWVL8X1fS1yBm2w`
|
|
- MCP Endpoint: `https://llm.kis.gov.lv/mcp`
|
|
- Manifest URL: `https://llm.kis.gov.lv/.well-known/mcp/manifest.json`
|
|
- Organization: KISC (Kultūras informācijas sistēmu centrs)
|
|
- Owner: Kultūras ministrija
|
|
- Compliance: GDPR, NIS2, Latvian Data Protection Act
|
|
|
|
**Submission Payload:** See `veritrust/mcp-server-request.json`
|
|
|
|
---
|
|
|
|
### Step 9: Install VeriTrust-Issued Credential
|
|
|
|
Once VeriTrust issues the credential:
|
|
|
|
```bash
|
|
# On llm.kis.gov.lv server
|
|
cd /opt/kisc-llm/poc/deploy
|
|
|
|
# Backup placeholder
|
|
cp .well-known/credentials/mcp-server.json .well-known/credentials/mcp-server.json.placeholder
|
|
|
|
# Install VeriTrust credential (replace PLACEHOLDER with actual credential)
|
|
cat > .well-known/credentials/mcp-server.json << 'EOF'
|
|
{
|
|
"@context": [
|
|
"https://www.w3.org/2018/credentials/v1",
|
|
"https://mcpf.dev/credentials/v1"
|
|
],
|
|
"id": "https://llm.kis.gov.lv/.well-known/credentials/mcp-server.json",
|
|
... (VeriTrust-provided credential JSON) ...
|
|
}
|
|
EOF
|
|
|
|
# Verify signature (use MCPF-python or manual verification)
|
|
# The credential MUST be signed by did:web:veritrust.vc
|
|
|
|
# Reload nginx to pick up new credential
|
|
docker exec kisc-nginx nginx -s reload
|
|
```
|
|
|
|
---
|
|
|
|
## Validation & Testing
|
|
|
|
### Local Tests (from server)
|
|
|
|
```bash
|
|
# Test DID Document
|
|
curl https://llm.kis.gov.lv/.well-known/did.json | jq
|
|
|
|
# Test MCPF Registry Discovery
|
|
curl https://llm.kis.gov.lv/.well-known/mcp-trust-registry.json | jq
|
|
|
|
# Test MCP Manifest
|
|
curl https://llm.kis.gov.lv/.well-known/mcp/manifest.json | jq
|
|
|
|
# Test credential (placeholder until VeriTrust issues)
|
|
curl https://llm.kis.gov.lv/.well-known/credentials/mcp-server.json | jq
|
|
```
|
|
|
|
### External Tests (from any machine)
|
|
|
|
```bash
|
|
# DID Resolution (W3C standard)
|
|
curl https://llm.kis.gov.lv/.well-known/did.json
|
|
|
|
# Should return:
|
|
# {
|
|
# "@context": [...],
|
|
# "id": "did:web:llm.kis.gov.lv",
|
|
# "verificationMethod": [...],
|
|
# ...
|
|
# }
|
|
```
|
|
|
|
### AI Agent Discovery Test
|
|
|
|
```python
|
|
import requests
|
|
|
|
# Agent discovers MCPF-enabled MCP server
|
|
registry_response = requests.get("https://llm.kis.gov.lv/.well-known/mcp-trust-registry.json")
|
|
print(registry_response.json())
|
|
|
|
# Agent fetches credential for verification
|
|
credential_url = registry_response.json()["services"]["mcp"]["credential"]
|
|
credential = requests.get(credential_url).json()
|
|
|
|
# Agent verifies signature against did:web:veritrust.vc
|
|
# (Use MCPF-python for full verification)
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Issue: 404 on .well-known endpoints
|
|
|
|
**Cause:** nginx not serving .well-known directory
|
|
|
|
**Fix:**
|
|
```bash
|
|
# Check nginx volume mount
|
|
docker inspect kisc-nginx | grep .well-known
|
|
|
|
# If missing, update docker-compose.yml:
|
|
volumes:
|
|
- ./.well-known:/opt/kisc-llm/poc/deploy/.well-known:ro
|
|
|
|
# Restart
|
|
docker restart kisc-nginx
|
|
```
|
|
|
|
---
|
|
|
|
### Issue: CORS errors when agents try to fetch DID
|
|
|
|
**Cause:** Missing CORS headers
|
|
|
|
**Fix:** Ensure nginx config has:
|
|
```nginx
|
|
add_header Access-Control-Allow-Origin * always;
|
|
```
|
|
|
|
---
|
|
|
|
### Issue: Private key not found in .env
|
|
|
|
**Cause:** MCPF_PRIVATE_KEY not set
|
|
|
|
**Fix:**
|
|
```bash
|
|
# Check .env
|
|
grep MCPF_PRIVATE_KEY /opt/kisc-llm/poc/deploy/.env
|
|
|
|
# If missing, extract from keypair-SECURE.json and add
|
|
```
|
|
|
|
---
|
|
|
|
## Security Checklist
|
|
|
|
Before going to production:
|
|
|
|
- [ ] `keypair-SECURE.json` deleted from server (only in `.env`)
|
|
- [ ] `.env` has permissions `600` (read/write by owner only)
|
|
- [ ] `.well-known` files have permissions `644` (world-readable)
|
|
- [ ] Private key backed up offline (encrypted)
|
|
- [ ] Access control documented (who has private key)
|
|
- [ ] VeriTrust credential installed (not placeholder)
|
|
- [ ] All endpoints accessible via HTTPS only
|
|
- [ ] nginx TLS configured correctly (Let's Encrypt)
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
1. **Deploy locally** (Part A) — Complete Steps 1-7
|
|
2. **Submit to VeriTrust** (Part B) — Step 8
|
|
3. **Install credential** — Step 9 (after VeriTrust response)
|
|
4. **Test with AI agents** — Validate MCPF discovery workflow
|
|
5. **Monitor** — Check logs, status.sh output
|
|
6. **Document** — Update KISC internal documentation
|
|
|
|
---
|
|
|
|
## Support
|
|
|
|
- **MCPF Specification:** https://github.com/MCPTrustFramework/MCPF-specification
|
|
- **VeriTrust:** https://veritrust.vc
|
|
- **Questions:** Contact Rihards (Veritrust relationship) or KISC IT team
|
|
|
|
---
|
|
|
|
**Version:** 1.0
|
|
**Last Updated:** 2026-01-30
|
|
**Status:** Ready for Deployment
|