NOTE: ZakonOnline references below are legacy. The env var
ZAKONONLINE_API_TOKENis being deprecated. There is no staging environment -- only local and prod.
{
"mcpServers": {
"SecondLayerMCP": {
"url": "https://mcp.legal.org.ua/v1/sse",
"headers": {
"Authorization": "Bearer YOUR_API_KEY_PROD"
}
}
}
}{
"mcpServers": {
"SecondLayerMCP": {
"url": "https://legal.org.ua/api/tools/get_legal_advice/stream",
"headers": {
"Authorization": "Bearer YOUR_API_KEY_PROD"
}
}
}
}From mcp_backend/.env:
SECONDARY_LAYER_KEYS=test-key-123,dev-key-456,YOUR_API_KEY_PRODValid API Keys:
test-key-123(development)dev-key-456(development)YOUR_API_KEY_PROD(production)
- Use case: Claude Desktop, MCP clients, automated tools
- Format: Plain string (no dots)
- Example:
Bearer YOUR_API_KEY_PROD - Expiry: Never expires
- Access: MCP tools only (
/api/tools/*)
- Use case: Web browser users (Google OAuth)
- Format: JWT with dots (header.payload.signature)
- Example:
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... - Expiry: 7 days
- Access: Admin panel (
/api/documents,/api/patterns, etc.)
Your configuration had:
{
"Authorization": "Bearer YOUR_JWT_TOKEN_HERE"
}Issues:
- ❌ JWT token instead of API key - MCP clients should use API keys
- ❌ Endpoint might be wrong - Depends on which SSE endpoint is active
# Test old MCP endpoint
curl -I https://mcp.legal.org.ua/v1/sse
# Test new tool streaming endpoint
curl -I https://legal.org.ua/api/tools/get_legal_advice/stream# Test with valid API key
curl -X POST https://legal.org.ua/api/tools/get_legal_advice \
-H "Authorization: Bearer YOUR_API_KEY_PROD" \
-H "Content-Type: application/json" \
-d '{
"query": "Test query",
"reasoning_budget": "standard"
}'Expected response: 200 OK with tool response
# Test with JWT token (your current token)
curl -X POST https://legal.org.ua/api/tools/get_legal_advice \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"query": "Test query"
}'Expected result: Might work if dual auth is enabled, but API keys are recommended
For Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"secondlayer": {
"command": "node",
"args": [
"<project-root>/mcp_backend/dist/index.js"
],
"env": {
"DATABASE_URL": "postgresql://secondlayer:secondlayer_password@localhost:5432/secondlayer_db",
"QDRANT_URL": "http://localhost:6333",
"REDIS_URL": "redis://localhost:6379",
"OPENAI_API_KEY": "sk-proj-...",
"ZAKONONLINE_API_TOKEN": "YOUR_ZAKONONLINE_TOKEN (legacy, optional)"
}
}
}
}OR for remote SSE connection:
{
"mcpServers": {
"secondlayer-remote": {
"url": "https://mcp.legal.org.ua/v1/sse",
"headers": {
"Authorization": "Bearer YOUR_API_KEY_PROD"
}
}
}
}- Using API key (not JWT token) for MCP clients
- Correct endpoint URL (check which SSE endpoint is active)
- API key is in
SECONDARY_LAYER_KEYSlist - Header format:
Authorization: Bearer <api-key> - Test with curl before using in MCP client
Cause: Using JWT token instead of API key
Fix: Replace JWT with API key from SECONDARY_LAYER_KEYS
Cause: Wrong endpoint URL
Fix: Check if /v1/sse or /api/tools/*/stream is the correct endpoint
Cause: API key not in allowed list
Fix: Verify API key exists in mcp_backend/.env SECONDARY_LAYER_KEYS
If you need a new API key:
# Generate random API key
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Add to mcp_backend/.env
SECONDARY_LAYER_KEYS=test-key-123,dev-key-456,<new-key>
# Restart backend
pm2 restart secondlayerUse this for MCP clients:
{
"mcpServers": {
"SecondLayerMCP": {
"url": "https://mcp.legal.org.ua/v1/sse",
"headers": {
"Authorization": "Bearer YOUR_API_KEY_PROD"
}
}
}
}Key points:
- ✅ Use API keys for MCP clients
- ✅ Use JWT tokens for web browser users (OAuth2)
- ✅ API keys never expire
- ✅ JWT tokens expire in 7 days