# Crustdata MCP Server

A Model Context Protocol (MCP) server that exposes Crustdata's B2B data platform APIs to AI assistants and LLM-powered applications.

## Features

- **16 MCP tools** covering company data, people data, watchers, web search, and job listings
- **Company tools**: Identify, enrich, search companies; search LinkedIn posts
- **People tools**: Enrich, search professionals by name, company, title, skills
- **Watcher tools**: Create webhook subscriptions for events (job postings, LinkedIn posts, etc.)
- **Web tools**: Search the web, fetch page content
- **Dataset tools**: Query job listings

## Installation

```bash
# From the repository root
uv sync

# Or install with pip
pip install -e .
```

## Configuration

### Environment Variables

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `CRUSTDATA_TOKEN` | STDIO only | - | Crustdata API token |
| `CRUSTDATA_API_URL` | No | `https://api.crustdata.com` | API base URL |
| `CRUSTDATA_REQUEST_TIMEOUT` | No | `30` | Request timeout in seconds |
| `CRUSTDATA_LOG_LEVEL` | No | `INFO` | Logging level |
| `CRUSTDATA_HTTP_HOST` | No | `127.0.0.1` | HTTP server bind address |
| `CRUSTDATA_HTTP_PORT` | No | `8000` | HTTP server port |
| `CRUSTDATA_HTTP_PATH` | No | `/mcp` | HTTP endpoint path |

> **Note:** `CRUSTDATA_TOKEN` is required for STDIO transport but NOT for HTTP transport.
> HTTP clients provide their own token in each request.

## Usage

### Transport Options

The server supports two transport modes:

| Transport | Command | Use Case |
|-----------|---------|----------|
| **STDIO** | `uv run crustdata-mcp` | Local CLI apps, Claude Desktop |
| **HTTP** | `uv run crustdata-mcp-http` | Remote servers, web deployments |

### Running with STDIO Transport (Local)

```bash
CRUSTDATA_TOKEN=your_token uv run crustdata-mcp
```

### Running with HTTP Transport (Remote Server)

HTTP transport uses **per-request authentication** - each client provides their own Crustdata API token. No token is required to start the server.

```bash
# Start server (no token required!)
uv run crustdata-mcp-http

# Or bind to all interfaces for remote access
CRUSTDATA_HTTP_HOST=0.0.0.0 uv run crustdata-mcp-http
```

Clients authenticate by providing their Crustdata API token in each request:
```
Authorization: Bearer <client_crustdata_token>
```

**Multi-tenant support:** Different clients can use different Crustdata accounts - the server routes each request using the client-provided token.

> **Security Note:** The bearer token is used directly as the Crustdata API token. For production deployments, use a reverse proxy with TLS.

### MCP Client Configuration

#### STDIO Transport (Local - Claude Desktop)

```json
{
  "mcpServers": {
    "crustdata": {
      "command": "uv",
      "args": ["--directory", "/path/to/mcp-crustdata/mcp", "run", "crustdata-mcp"],
      "env": {
        "CRUSTDATA_TOKEN": "your_api_token_here"
      }
    }
  }
}
```

#### HTTP Transport (Remote Server)

Start the server on your remote host (no token required):
```bash
cd /path/to/mcp-crustdata/mcp
CRUSTDATA_HTTP_HOST=0.0.0.0 uv run crustdata-mcp-http
```

Then configure your MCP client with your Crustdata API token:

```json
{
  "mcpServers": {
    "crustdata": {
      "type": "streamable-http",
      "url": "http://your-server.com:8000/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_CRUSTDATA_TOKEN"
      }
    }
  }
}
```

> Each client can use their own Crustdata API token - the server supports multi-tenant access.

## Available Tools

### Company Tools

| Tool | Description |
|------|-------------|
| `crustdata_company_identify` | Match companies by name, domain, or LinkedIn URL |
| `crustdata_company_enrich` | Get detailed company profile data |
| `crustdata_company_search_db` | Search company database with filters |
| `crustdata_company_linkedin_posts` | Search LinkedIn posts by keyword |
| `crustdata_autocomplete_company` | Get autocomplete suggestions for company fields |

### People Tools

| Tool | Description |
|------|-------------|
| `crustdata_people_enrich` | Get detailed person profile by LinkedIn URL or email |
| `crustdata_people_search_db` | Search people database with filters |
| `crustdata_autocomplete_person` | Get autocomplete suggestions for people fields |

### Watcher Tools

| Tool | Description |
|------|-------------|
| `crustdata_watcher_create` | Create webhook subscription for events |
| `crustdata_watcher_update` | Update/pause/resume subscription |
| `crustdata_watcher_simulate` | Test webhook endpoint |
| `crustdata_watcher_list` | List all subscriptions |

### Web Tools

| Tool | Description |
|------|-------------|
| `crustdata_web_search` | Search the web for information |
| `crustdata_web_fetch` | Fetch and extract page content |

### Dataset Tools

| Tool | Description |
|------|-------------|
| `crustdata_dataset_job_listings` | Query job postings dataset |

### Utility Tools

| Tool | Description |
|------|-------------|
| `crustdata_credits_check` | Check API credit balance |

## Development

```bash
# Install development dependencies
uv sync --dev

# Run tests
.venv/bin/python -m pytest tests/ -v

# Run tests with coverage
.venv/bin/python -m pytest tests/ --cov=src/crustdata_mcp

# Lint code
.venv/bin/ruff check src/ tests/
```

## Project Structure

```
src/crustdata_mcp/
├── __init__.py
├── server.py           # FastMCP server initialization
├── config.py           # Configuration management
├── client.py           # Async HTTP client for Crustdata API
├── client_factory.py   # Per-request client management (multi-tenant)
├── auth.py             # Bearer token authentication for HTTP transport
├── tools/
│   ├── company.py      # Company tools
│   ├── people.py       # People tools
│   ├── watcher.py      # Watcher tools
│   ├── web.py          # Web tools
│   ├── dataset.py      # Dataset tools
│   └── utility.py      # Utility tools
├── models/
│   └── common.py       # Shared Pydantic models
├── resources/          # MCP resources (documentation)
└── utils/              # Utility functions
```
