Metadata-Version: 2.4
Name: wl-registry
Version: 0.1.0
Summary: Python SDK for Watchlight AI Registry — AI agent and MCP server registry
Project-URL: Homepage, https://www.watchlight.ai
Project-URL: Documentation, https://github.com/watchlight-ai-beacon/Watchlight-Beacon/tree/main/wl-registry/wl-registry-python#readme
Project-URL: Source, https://github.com/watchlight-ai-beacon/Watchlight-Beacon/tree/main/wl-registry/wl-registry-python
Project-URL: Issues, https://github.com/watchlight-ai-beacon/Watchlight-Beacon/issues
Author-email: Watchlight AI Team <team@watchlight.ai>
License-Expression: LicenseRef-Proprietary
License-File: LICENSE
Keywords: agents,ai,discovery,mcp,model-context-protocol,registry,watchlight
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: mypy>=1.9.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest-httpx>=0.30.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.3.0; extra == 'dev'
Description-Content-Type: text/markdown

# wl-registry

Python SDK for [Watchlight AI Registry](https://www.watchlight.ai) — AI agent and MCP server registry.

Register, discover, and manage AI agents, MCP servers, scanners, and permissions through a type-safe Python client.

## Installation

```bash
pip install wl-registry
```

## Quick Start

### Public Client (No Auth)

```python
from wl_registry import WlRegistryClient, SelfRegisterAgentRequest

# Check service health
async with WlRegistryClient("http://localhost:8080/api/v1") as client:
    healthy = await client.health()

    # Self-register an agent
    resp = await client.register_agent(
        SelfRegisterAgentRequest(
            name="my-agent",
            agent_type="autonomous",
            description="My autonomous agent",
        )
    )
    print(f"Agent ID: {resp.id}, API Key: {resp.api_key}")
```

### Scanner Client

Register and manage MCP servers discovered by scanners:

```python
from wl_registry import WlRegistryScannerClient, RegisterServerRequest

async with WlRegistryScannerClient(
    scanner_id="scanner-uuid",
    api_key="scanner-api-key",
    base_url="http://localhost:8080/api/v1",
) as client:
    resp = await client.register_server(
        RegisterServerRequest(
            host_id="host-1",
            address="http://localhost:4000",
            transport="http",
            server_name="my-mcp-server",
            lease_ttl_seconds=300,
        )
    )
    print(f"Server {resp.server_id} registered")

    # Keep alive
    await client.heartbeat(resp.server_id)
```

### Agent Client

Query accessible servers from the agent's perspective:

```python
from wl_registry import WlRegistryAgentClient

async with WlRegistryAgentClient(
    agent_id="agent-uuid",
    api_key="agent-api-key",
) as client:
    servers = await client.get_accessible_servers()
    for srv in servers.servers:
        print(f"Can access: {srv.server_name} at {srv.address}")

    await client.heartbeat()
```

### Admin Client

Full CRUD operations for managing the registry:

```python
from wl_registry import (
    WlRegistryAdminClient,
    CreateAgentRequest,
    GrantPermissionRequest,
)

async with WlRegistryAdminClient(admin_key="admin-key") as client:
    # List all agents
    agents = await client.list_agents()
    print(f"Total agents: {agents.total}")

    # Create an agent
    agent = await client.create_agent(
        CreateAgentRequest(
            name="new-agent",
            agent_type="workflow",
            description="A workflow orchestrator",
        )
    )

    # Grant permission to access a server
    await client.grant_permission(
        agent.agent_id,
        GrantPermissionRequest(
            server_id="srv-uuid",
            allowed_tools=["read_file", "search"],
        ),
    )

    # Get agent statistics
    stats = await client.get_agent_stats()
    print(f"Active: {stats.active_agents}, Trusted: {stats.trusted_agents}")
```

## Synchronous Clients

All clients have synchronous counterparts:

```python
from wl_registry import WlRegistrySyncClient, WlRegistryAdminSyncClient

# Public
with WlRegistrySyncClient() as client:
    healthy = client.health()

# Admin
with WlRegistryAdminSyncClient(admin_key="key") as client:
    agents = client.list_agents()
```

Also available: `WlRegistryScannerSyncClient`, `WlRegistryAgentSyncClient`.

## Error Handling

All exceptions inherit from `WlRegistryError`:

```python
from wl_registry import (
    WlRegistryError,
    AuthenticationError,
    NotFoundError,
    ValidationError,
    ConflictError,
    ServiceUnavailable,
)

try:
    agent = await client.get_agent("nonexistent")
except NotFoundError as e:
    print(f"Agent not found: {e}")
except AuthenticationError:
    print("Invalid credentials")
except WlRegistryError as e:
    print(f"Registry error: {e}")
```

| Exception | HTTP Status | Description |
|-----------|-------------|-------------|
| `AuthenticationError` | 401, 403 | Invalid or missing credentials |
| `NotFoundError` | 404 | Resource not found |
| `ValidationError` | 400, 422 | Invalid request data |
| `ConflictError` | 409 | Resource conflict (e.g., duplicate name) |
| `ServiceUnavailable` | Connection error | Service unreachable |

## Client Reference

| Client | Auth | Key Methods |
|--------|------|-------------|
| `WlRegistryClient` | None | `health`, `get_registration_config`, `register_agent` |
| `WlRegistryScannerClient` | Scanner | `register_server`, `heartbeat`, `update_trust` |
| `WlRegistryAgentClient` | Agent | `get_accessible_servers`, `heartbeat` |
| `WlRegistryAdminClient` | Admin | Full CRUD: servers, agents, permissions, scanners, tokens |

## Requirements

- Python 3.10+
- httpx >= 0.27.0
- pydantic >= 2.0.0

## License

Proprietary. See [LICENSE](LICENSE) for details.
