Port Detection Pattern

Best practice pattern for dynamic port configuration

Overview

The AI Platform uses a centralized port registry combined with fallback defaults to enable flexible port configuration across all services. This pattern allows services to:

  1. Read their assigned port from a central registry
  2. Fall back to hardcoded defaults if registry is unavailable
  3. Allow environment variable overrides
  4. Log which configuration source was used

Reference Implementation

The ai-voicememo project (ai-voicememo/web/server.py) implements this pattern excellently. Here’s the complete implementation:

def get_port_from_ai_platform():
    """Get port assigned by ai-platform for this project."""
    import json
    from pathlib import Path

    # Try to find ai-platform projects registry
    platform_paths = [
        Path.home() / "ai-platform" / "projects" / "registry.json",
        Path.home() / "Library" / "CloudStorage" / "Dropbox" / "202x" / "2026project" / "ai-platform" / "projects" / "registry.json",
    ]

    for registry_path in platform_paths:
        if registry_path.exists():
            try:
                with open(registry_path, 'r', encoding='utf-8') as f:
                    registry = json.load(f)
                    projects = registry.get('projects', [])
                    for project in projects:
                        if project.get('id') == 'ai-voicememo':
                            ports = project.get('ports', {})
                            web_port = ports.get('web')
                            if web_port:
                                logger.info(f"Using port {web_port} from ai-platform registry")
                                return web_port
            except Exception as e:
                logger.warning(f"Could not read ai-platform registry: {e}")

    # Fallback to default
    logger.info("Using default port 5200 (ai-platform registry not found)")
    return 5200


def main():
    """Run the application."""
    import uvicorn
    import os
    os.chdir(WEB_DIR)
    port = get_port_from_ai_platform()
    uvicorn.run("server:app", host="0.0.0.0", port=port, reload=True)

Pattern Components

2. Project-Specific Lookup

Each service looks up its own configuration:

for project in projects:
    if project.get('id') == 'ai-voicememo':  # Use your project ID
        ports = project.get('ports', {})
        web_port = ports.get('web')  # Or 'api', 'docs', etc.

3. Graceful Fallback

If registry read fails or port not found:

# Fallback to default
logger.info("Using default port 5200 (ai-platform registry not found)")
return 5200  # Your assigned default port

4. Logging

Always log which configuration source was used:

logger.info(f"Using port {web_port} from ai-platform registry")
# or
logger.info("Using default port 5200 (ai-platform registry not found)")

Registry Schema

The central registry follows this schema:

{
  "version": "1.0.0",
  "last_updated": "2026-02-07",
  "projects": [
    {
      "id": "ai-voicememo",
      "name": "AI Voice Memo",
      "ports": {
        "web": 5200,
        "docs": 5201,
        "api": 5210
      },
      "server_type": "FastAPI",
      "status": "active",
      "urls": {
        "local": "http://localhost:5200",
        "network": "http://studio-3.local:5200"
      }
    }
  ]
}

Implementation Steps

For New Services

  1. Choose your port range from the port assignments

  2. Add entry to registry.json:

    {
      "id": "your-project-id",
      "name": "Your Project Name",
      "ports": {
        "web": 5XXX
      },
      "server_type": "FastAPI",
      "status": "active"
    }
  3. Implement port detection function (copy from ai-voicememo)

  4. Update project ID in the lookup code

  5. Set fallback default to your assigned port

For Existing Services

  1. Add registry reading logic before uvicorn.run()

  2. Keep existing default as fallback

  3. Add comment explaining migration:

    port = 5400  # ai-lector (was 8000, migrated 2026-02-07)

Benefits

  • Centralized Management: Single source of truth for all port assignments
  • Zero Downtime: Services continue working if registry unavailable
  • Flexibility: Easy to reassign ports by updating registry
  • Discoverability: Other services can discover ports programmatically
  • Documentation: Registry serves as live documentation

Environment Variable Override

For advanced use cases, you can add environment variable support:

def get_port_from_ai_platform():
    # Check environment variable first
    env_port = os.getenv("AI_VOICEMEMO_PORT")
    if env_port:
        logger.info(f"Using port {env_port} from environment variable")
        return int(env_port)

    # Then check registry...
    # (rest of implementation)

Testing

Test the pattern by:

  1. With registry: Verify service reads correct port from registry
  2. Without registry: Rename/move registry, verify fallback works
  3. Invalid registry: Corrupt JSON, verify graceful degradation
  4. Logging: Check logs show which source was used

See Also

  • Port Assignments - Complete port allocation table
  • Service registry: platform/projects/registry.json (central registry file)
  • Reference implementation: ~/ai-mac-studio/agents/management/ai-voicememo/web/server.py