Metadata-Version: 2.3
Name: canonical-search
Version: 0.1.0
Summary: Python SDK and MCP server for Canonical company search — find companies using natural language
License: MIT
Author: Synaptic
Author-email: hello@synaptic.com
Requires-Python: >=3.11,<4.0
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Provides-Extra: mcp
Requires-Dist: fastmcp (>=2.0.0) ; extra == "mcp"
Requires-Dist: httpx (>=0.27.0,<0.28.0)
Requires-Dist: pydantic (>=2.5.0,<3.0.0)
Requires-Dist: pydantic-settings (>=2.1.0,<3.0.0)
Description-Content-Type: text/markdown

# canonical-search

Python SDK and MCP server for [Canonical](https://trycanonical.ai) company search. Find companies using natural language.

## Install

### SDK only (for use in your Python code)

```bash
pip install canonical-search
```

### MCP server (for Claude Desktop, Cursor, Windsurf, Claude Code)

We recommend `pipx` which installs in an isolated environment and avoids conflicts with system Python:

```bash
pipx install "canonical-search[mcp]"
```

Alternatively, with pip:

```bash
pip install "canonical-search[mcp]"
```

## Quick Start

```python
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

# Sync
results = client.search("AI healthcare startups")
for company in results.results:
    print(f"{company.name} — {company.domain}")

# Async
results = await client.asearch("B2B fashion tech companies")
```

### Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `query` | str | required | Natural language search query |
| `top_k` | int | 20 | Number of results (1-100) |
| `verified` | bool | False | LLM verification for higher accuracy (uses 2 credits) |

### Environment-Based Config

Instead of passing `api_key` directly, you can use environment variables:

```bash
export CANONICAL_API_KEY=sk_your_key
export CANONICAL_API_BASE_URL=https://trycanonical.ai  # optional
export CANONICAL_TIMEOUT=30.0  # optional
```

```python
from canonical_search.config import client_from_env

client = client_from_env()
results = client.search("fintech companies in Europe")
```

## MCP Server

For AI tools that support MCP (Claude Desktop/Cowork, Cursor, Windsurf, Claude Code).

First, find the absolute path to the binary:

```bash
which canonical-mcp
```

### Claude Desktop / Cowork

Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "canonical": {
      "command": "/full/path/to/canonical-mcp",
      "env": {
        "CANONICAL_API_KEY": "sk_your_key"
      }
    }
  }
}
```

Then fully quit and restart Claude Desktop.

### Claude Code

```bash
claude mcp add canonical -- canonical-mcp
# Set your API key in the environment:
export CANONICAL_API_KEY=sk_your_key
```

### Cursor

Add to `.cursor/mcp.json` in your project or `~/.cursor/mcp.json` globally:

```json
{
  "mcpServers": {
    "canonical": {
      "command": "/full/path/to/canonical-mcp",
      "env": {
        "CANONICAL_API_KEY": "sk_your_key"
      }
    }
  }
}
```

> **Note:** Always use the absolute path from `which canonical-mcp`. Relative paths are the most common cause of MCP connection failures.

## Framework Integration

The SDK works with any Python-based AI agent framework with minimal glue code.

### AutoGen

```python
from autogen import register_function
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

def search_companies(query: str, top_k: int = 20) -> str:
    """Search for companies using natural language."""
    return client.search(query, top_k).model_dump_json()

register_function(
    search_companies,
    caller=assistant,
    executor=executor,
    description="Search for companies using natural language",
)
```

### LangChain

```python
from langchain_core.tools import tool
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

@tool
def search_companies(query: str, top_k: int = 20) -> str:
    """Search for companies using natural language."""
    return client.search(query, top_k).model_dump_json()
```

### Agno

```python
from agno.tools import tool
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

@tool
def search_companies(query: str, top_k: int = 20) -> str:
    """Search for companies using natural language."""
    return client.search(query, top_k).model_dump_json()
```

### CrewAI

```python
from crewai.tools import tool
from canonical_search import CanonicalClient

client = CanonicalClient(api_key="sk_your_key")

@tool("Company Search")
def search_companies(query: str, top_k: int = 20) -> str:
    """Search for companies using natural language."""
    return client.search(query, top_k).model_dump_json()
```

## Response Schema

```python
SearchResponse:
    results: list[Company]  # List of matching companies
    count: int              # Number of results
    query: str              # Original query
    credits_used: int       # Credits consumed
    credits_remaining: int  # Remaining credits (if available)

Company:
    id: int
    name: str
    website: str
    logo_url: str | None
    domain: str
    description: str
    verdict: str | None         # Only when verified=True
    verdict_reason: str | None  # Only when verified=True
```

## Get an API Key

1. Sign up at [trycanonical.ai](https://trycanonical.ai)
2. Go to Dashboard → API Keys
3. Create a new key (starts with `sk_`)

