14 KiB
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
- Overview
- Package Contents
- Prerequisites
- Part A: Local Implementation
- Part B: VeriTrust Integration
- Validation & Testing
- 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!
# 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/.envonly - ✅ Backup offline (encrypted USB/vault)
- ✅ Document who has access
Step 2: Deploy .well-known Files to Server
# 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
# 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
# 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:
# 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:
# 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
# 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:
- Contact VeriTrust via existing relationship
- Request MCPServerCredential for
did:web:llm.kis.gov.lv - 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
- DID:
Submission Payload: See veritrust/mcp-server-request.json
Step 9: Install VeriTrust-Issued Credential
Once VeriTrust issues the credential:
# 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)
# 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)
# 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
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:
# 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:
add_header Access-Control-Allow-Origin * always;
Issue: Private key not found in .env
Cause: MCPF_PRIVATE_KEY not set
Fix:
# 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.jsondeleted from server (only in.env).envhas permissions600(read/write by owner only).well-knownfiles have permissions644(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
- Deploy locally (Part A) — Complete Steps 1-7
- Submit to VeriTrust (Part B) — Step 8
- Install credential — Step 9 (after VeriTrust response)
- Test with AI agents — Validate MCPF discovery workflow
- Monitor — Check logs, status.sh output
- 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