> ## Documentation Index
> Fetch the complete documentation index at: https://docs.signalhire.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SignalHire MCP Server

> Connect SignalHire to AI assistants and agents via the Model Context Protocol.

The SignalHire MCP server lets AI assistants and agents query our dataset of professional profiles, company information, and contact details — directly from Claude, Cursor, Windsurf, VS Code, or any MCP-compatible client.

## Connection Details

|               |                                       |
| ------------- | ------------------------------------- |
| **Endpoint**  | `https://mcp.signalhire.services/mcp` |
| **Transport** | MCP Streamable HTTP                   |

## Authentication

The server is a stateless proxy — it stores no global key and forwards your credential per request. It detects the token type automatically.

| Mode                  | How                                                                 | When to use                                                             |
| --------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| **API key (Bearer)**  | HTTP header `Authorization: Bearer <YOUR_API_KEY>` in a JSON config | IDEs and services configured via JSON, programmatic clients, automation |
| **OAuth 2.0 (Auth0)** | Interactive login, no key handling                                  | Claude.ai / Claude Desktop connector UI                                 |

<Info>
  **OAuth details.** OAuth is handled by SignalHire's Auth0 authorization server (`https://signalhire.eu.auth0.com/`). When you add the connector, Claude discovers the authorization server via RFC 9728 metadata, you log in and consent on the SignalHire/Auth0 screen, and Claude receives a token — no API key is entered by hand. Expired tokens return `401` and Claude refreshes them automatically.
</Info>

***

## Connecting via JSON (API key)

There are two JSON connection types depending on whether your client can talk to a remote server directly.

<AccordionGroup>
  <Accordion title="Type 1 — Direct HTTP (Claude Code, Cursor, Windsurf, VS Code)">
    The client speaks MCP Streamable HTTP straight to the server. **No Node.js, no bridge.** This is the preferred type — use it whenever your client supports it.

    ```json theme={null}
    {
        "mcpServers": {
        "SignalHire": {
        "type": "http",
        "url": "https://mcp.signalhire.services/mcp",
        "headers": {
        "Authorization": "Bearer YOUR_SIGNALHIRE_API_KEY"
    }
    }
    }
    }
    ```

    **Per-client differences** (everything else stays the same):

    | Client                           | Config file                                | Difference                          |
    | -------------------------------- | ------------------------------------------ | ----------------------------------- |
    | **Claude Code**                  | `.mcp.json` (project root)                 | None — use as-is                    |
    | **Cursor**                       | `~/.cursor/mcp.json` or `.cursor/mcp.json` | Omit the `"type"` field             |
    | **Windsurf**                     | `~/.codeium/windsurf/mcp_config.json`      | Rename `"url"` → `"serverUrl"`      |
    | **VS Code** (Copilot agent mode) | `.vscode/mcp.json`                         | Rename `"mcpServers"` → `"servers"` |
  </Accordion>

  <Accordion title="Type 2 — mcp-remote bridge (Claude Desktop and stdio-only clients)">
    Some clients can only launch a local stdio process and cannot open a remote connection themselves — most notably **Claude Desktop**. For those, `npx mcp-remote` runs locally and bridges stdio to the remote HTTP endpoint. **Requires Node.js installed.**

    ```json theme={null}
    {
        "mcpServers": {
        "SignalHireMCP": {
        "command": "npx",
        "args": [
        "-y",
        "mcp-remote",
        "https://mcp.signalhire.services/mcp",
        "--header",
        "Authorization: Bearer YOUR_SIGNALHIRE_API_KEY"
        ]
    }
    }
    }
    ```

    **Claude Desktop config path:**

    * **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
    * **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
  </Accordion>
</AccordionGroup>

### Which type do I use?

| Your client                                            | Type                                     |
| ------------------------------------------------------ | ---------------------------------------- |
| Claude Code, Cursor, Windsurf, VS Code                 | **Type 1 — Direct HTTP**                 |
| Claude Desktop (JSON config), or any stdio-only client | **Type 2 — mcp-remote bridge**           |
| Claude.ai / Claude Desktop connector UI                | **Neither — use OAuth** (no JSON needed) |

***

## Claude.ai / Claude Desktop — Custom Connector (OAuth)

<Steps>
  <Step title="Open Connectors settings">
    Go to **Settings → Connectors → Add custom connector**.
  </Step>

  <Step title="Enter the endpoint URL">
    Set the URL to `https://mcp.signalhire.services/mcp`
  </Step>

  <Step title="Connect">
    Leave the advanced OAuth fields empty and click **Connect** — you'll be redirected to the SignalHire login (Auth0). After consent no API key is needed.
  </Step>
</Steps>

## Claude Code — CLI

```bash theme={null}
claude mcp add --transport http SignalHire https://mcp.signalhire.services/mcp \
  --header "Authorization: Bearer YOUR_SIGNALHIRE_API_KEY"
```

## Python SDK (programmatic)

```python theme={null}
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

url = "https://mcp.signalhire.services/mcp"
headers = {"Authorization": "Bearer YOUR_SIGNALHIRE_API_KEY"}

async with streamablehttp_client(url, headers=headers) as (read_stream, write_stream, _):
    async with ClientSession(read_stream, write_stream) as session:
        await session.initialize()
        tools = await session.list_tools()
        print(tools)
```

***

## Available Tools

Once connected, your AI assistant can call the following tools and decides which to use based on your prompt.

<Info>
  **Response format:** every tool accepts a `response_format` parameter (default `"markdown"`); set it to `"csv"` or `"json"` as needed.

  **Credits:** the remaining balance is automatically appended to the tool's response — no separate balance check is needed after each call.
</Info>

### Search & Discovery

<ParamField body="search_candidates_query" type="tool">
  Search the database using advanced filters like title, location, and keywords. Supports Boolean logic (e.g. `(Software AND Engineer)`). Parameters: `current_title`, `current_past_title`, `location`, `current_company`, `current_past_company`, `full_name`, `keywords`, `industry`, `industries`, `department` (Enum), `level` (Enum), `years_experience_from`, `years_experience_to`, `years_current_past_experience_from`, `years_current_past_experience_to`, `open_to_work`, `exclude_revealed`, `exclude_watched`, `exclude_in_lists`, `exclude_in_progress`, `exclude_emailed`, `size` (default: 10), `response_format`.

  **Credit cost:** Uses daily search quota. No contact credits.
</ParamField>

<ParamField body="scroll_search" type="tool">
  Fetch the next batch of search results for pagination. Must be called within **15 seconds** of the initial search. Parameters: `request_id`, `scroll_id`, `response_format`.

  **Credit cost:** Uses daily search quota.
</ParamField>

### Profile Retrieval

<ParamField body="retrieve_person_no_contacts" type="tool">
  Retrieve a candidate's full professional profile (experience, skills, education) **without** unlocking contact details. Parameters: `items` (array of UIDs), `response_format`.

  **Credit cost:** Uses daily search quota. No contact credits.
</ParamField>

<ParamField body="retrieve_person_profile" type="tool">
  Retrieve a full profile **including contact information** (emails, phone numbers, social links). Parameters: `items` (array of UIDs, LinkedIn URLs, or emails), `spend_credits_confirmed` (boolean), `response_format`.

  **Credit cost:** ⚠️ 1 Contact Credit per successful match.
</ParamField>

### Company

<ParamField body="find_company" type="tool">
  Look up a company by name, domain, or slug to retrieve its stable numeric ID. Parameters: `company_id_or_slug`, `response_format`.

  **Credit cost:** Free.
</ParamField>

<ParamField body="get_company_info" type="tool">
  Retrieve comprehensive company data (locations, industries, exact headcount). Parameters: `company_id` (numeric ID), `spend_credits_confirmed` (boolean), `response_format`.

  **Credit cost:** ⚠️ 1 Company Credit.
</ParamField>

### Utility

<ParamField body="check_balance" type="tool">
  Check the remaining standard Contact credits for the current API key. Does not include Company credits.

  **Credit cost:** Free.
</ParamField>

<ParamField body="check_without_contacts_credits" type="tool">
  Check the remaining daily quota for searches and profiles retrieved without revealing contact information.

  **Credit cost:** Free.
</ParamField>

<ParamField body="get_available_levels" type="tool">
  Retrieve the complete list of candidate seniority levels supported by the search API.

  **Credit cost:** Free.
</ParamField>

<ParamField body="get_available_departments" type="tool">
  Retrieve the complete list of candidate professional departments supported by the search API.

  **Credit cost:** Free.
</ParamField>

<ParamField body="get_available_industries" type="tool">
  Retrieve the full list of all 146 supported industry categories for the search API.

  **Credit cost:** Free.
</ParamField>

***

## Example Prompts

```
Find me 5 Senior Python Developers in London. Show me their skills. Do not fetch their contacts yet.
```

Uses `search_candidates_query` → `retrieve_person_no_contacts`

```
Reveal the contact information (emails and phone) for that candidate.
```

Uses `retrieve_person_profile`

```
What is the exact headcount and headquarters location of Google? Search for the company ID first.
```

Uses `find_company` → `get_company_info`

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="mcp-remote keeps failing after a config change">
    It caches per-server state. Clear it and restart the client:

    ```bash theme={null}
    rm -rf ~/.mcp-auth
    ```
  </Accordion>

  <Accordion title="401 Unauthorized">
    Missing or invalid `Authorization: Bearer` header, or an expired OAuth token (the client should refresh automatically). Check the header is present and the SignalHire API key is valid.
  </Accordion>

  <Accordion title="403 Connection Denied">
    You're connecting by IP instead of the domain. Always use `https://mcp.signalhire.services/mcp` — the server filters traffic by the `Host` header.
  </Accordion>

  <Accordion title="TLS / certificate errors">
    If your client's CA bundle is out of date, update it (`pip install -U certifi` for Python). Do **not** disable TLS verification.
  </Accordion>
</AccordionGroup>
