Skip to content

Server Identity Registration

This guide covers setting up a verifiable identity for your MCP server.

Why Server Identity?

MCP servers expose powerful tools—file systems, databases, APIs. But how do clients know they're connecting to the real server and not an imposter?

Server identity registration solves this by:

  • Generating a keypair for cryptographic signing
  • Creating a DID (Decentralized Identifier) for the server
  • Registering with the CapiscIO Registry for discoverability

Quick Start

from capiscio_mcp import setup_server_identity

# One-step setup: generate keys + register with registry
result = await setup_server_identity(
    server_id="550e8400-e29b-41d4-a716-446655440000",  # From dashboard
    api_key="sk_live_...",  # Registry API key
    output_dir="./keys",
)

print(f"Server DID: {result['did']}")
# did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK

Prerequisites

  1. Create your MCP server in the CapiscIO Dashboard
  2. Go to dashboard.capisc.io
  3. Navigate to Servers → Create Server
  4. Copy the server UUID

  5. Get an API key

  6. In the dashboard, go to Settings → API Keys
  7. Create a key with servers:write permission

  8. capiscio-core must be running

  9. Either embedded (auto-downloaded) or external

Step-by-Step Registration

Step 1: Generate Keypair

Generate an Ed25519 keypair for your server:

from capiscio_mcp import generate_server_keypair

keys = await generate_server_keypair(output_dir="./keys")

print(f"DID: {keys['did_key']}")
print(f"Private key: {keys['private_key_path']}")

Returns:

Key Description
key_id Unique key identifier
did_key The derived did:key:z6Mk... URI
public_key_pem PEM-encoded public key
private_key_pem PEM-encoded private key
private_key_path Path to saved key file (if output_dir provided)

Step 2: Register with Registry

Register the DID with the CapiscIO registry:

from capiscio_mcp import register_server_identity

await register_server_identity(
    server_id="550e8400-e29b-41d4-a716-446655440000",
    api_key="sk_live_...",
    did=keys["did_key"],
    public_key=keys["public_key_pem"],
)

Combined: setup_server_identity

For convenience, use the combined function:

from capiscio_mcp import setup_server_identity

result = await setup_server_identity(
    server_id="550e8400-e29b-41d4-a716-446655440000",
    api_key="sk_live_...",
    output_dir="./keys",
)

# Returns everything you need
print(f"DID: {result['did']}")
print(f"Private key: {result['private_key_path']}")

Synchronous API

All functions have sync wrappers:

from capiscio_mcp import (
    generate_server_keypair_sync,
    register_server_identity_sync,
    setup_server_identity_sync,
)

# Sync version
result = setup_server_identity_sync(
    server_id="550e8400-e29b-41d4-a716-446655440000",
    api_key="sk_live_...",
    output_dir="./keys",
)

Using the Identity

After registration, use the DID and private key for server identity disclosure:

With CapiscioMCPServer

from capiscio_mcp.integrations.mcp import CapiscioMCPServer

server = CapiscioMCPServer(
    name="filesystem",
    did=result["did"],
    private_key_path=result["private_key_path"],
)

@server.tool(min_trust_level=2)
async def read_file(path: str) -> str:
    """Server identity is automatically disclosed."""
    with open(path) as f:
        return f.read()

Manual Disclosure

Add identity headers to responses:

from fastapi import FastAPI, Response

app = FastAPI()

@app.middleware("http")
async def add_server_identity(request, call_next):
    response = await call_next(request)
    response.headers["Capiscio-Server-DID"] = SERVER_DID
    response.headers["Capiscio-Server-Badge"] = SERVER_BADGE
    return response

Error Handling

from capiscio_mcp import (
    setup_server_identity,
    RegistrationError,
    KeyGenerationError,
)
from capiscio_mcp.errors import CoreConnectionError

try:
    result = await setup_server_identity(
        server_id="550e8400-e29b-41d4-a716-446655440000",
        api_key="sk_live_...",
    )
except CoreConnectionError as e:
    print("Could not connect to capiscio-core")
    print("Ensure it's running: capiscio mcp serve")
except KeyGenerationError as e:
    print(f"Key generation failed: {e}")
except RegistrationError as e:
    print(f"Registration failed: {e}")
    if e.status_code == 401:
        print("Invalid API key")
    elif e.status_code == 404:
        print("Server not found - create it in the dashboard first")

Environment Variables

Variable Description
CAPISCIO_SERVER_ID Server UUID from dashboard
CAPISCIO_API_KEY Registry API key
CAPISCIO_SERVER_URL Registry URL (default: production)
CAPISCIO_SERVER_DOMAIN Domain for badge issuance
CAPISCIO_SERVER_PRIVATE_KEY_PEM PEM-encoded Ed25519 private key (ephemeral environments)
CAPISCIO_CORE_ADDR External core address (default: embedded)
CAPISCIO_SERVER_DID Pre-configured server DID
CAPISCIO_SERVER_PRIVATE_KEY Path to private key PEM

Deploying to containers or serverless?

See the Deployment Guide for Docker, Lambda, Cloud Run, and Kubernetes examples using CAPISCIO_SERVER_PRIVATE_KEY_PEM for ephemeral identity persistence.

Security Best Practices

  1. Never commit private keys

    # .gitignore
    *.pem
    keys/
    capiscio_keys/
    

  2. Use restrictive permissions

    chmod 600 ./keys/*.pem
    

  3. Rotate keys periodically

  4. Generate new keypair
  5. Update registry with new DID
  6. Keep old key for transition period

  7. Store API keys securely

    # Use environment variables
    export CAPISCIO_REGISTRY_API_KEY="sk_live_..."
    

Next Steps