npm package: @nexbid/mcp-server
Description: Nexbid MCP Server — AI agent product discovery via Model Context Protocol
Latest version: 1.0.1

# Nexbid MCP Server

[![npm version](https://img.shields.io/npm/v/@nexbid/mcp-server.svg)](https://www.npmjs.com/package/@nexbid/mcp-server)
[![MCP](https://img.shields.io/badge/MCP-1.6-blue)](https://modelcontextprotocol.io)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)

AI agent product discovery via [Model Context Protocol](https://modelcontextprotocol.io). Connect any MCP-compatible AI agent to search, discover, and retrieve product data from the Nexbid open marketplace.

## Quick Start

### Claude Desktop / Claude.ai

Add to your MCP client configuration:

```json
{
  "mcpServers": {
    "nexbid": {
      "url": "https://nexbid.dev/mcp"
    }
  }
}
```

With API key authentication:

```json
{
  "mcpServers": {
    "nexbid": {
      "url": "https://nexbid.dev/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

The server is live at `https://nexbid.dev/mcp` and ready to accept connections immediately.

## Available Tools

| Tool | Description | Required Params | Optional Params |
|------|-------------|-----------------|-----------------|
| `nexbid_search` | Search and discover products with natural language | `query` (string, 1-500 chars) | `intent`, `budget_min_cents`, `budget_max_cents`, `currency`, `geo`, `category`, `brand`, `max_results` |
| `nexbid_product` | Get detailed product info by ID | `product_id` (UUID) | -- |
| `nexbid_categories` | List product categories with counts | -- | `geo` |

All tools carry `readOnlyHint: true` and `openWorldHint: true` safety annotations -- they only read data and access an open marketplace.

### Parameter Details

**nexbid_search**

| Parameter | Type | Description |
|-----------|------|-------------|
| `query` | `string` | Natural language product query (required, 1-500 chars) |
| `intent` | `enum` | User intent: `purchase`, `compare`, `research`, `browse` |
| `budget_min_cents` | `integer` | Minimum budget in cents (e.g. 5000 = CHF 50) |
| `budget_max_cents` | `integer` | Maximum budget in cents (e.g. 20000 = CHF 200) |
| `currency` | `enum` | `CHF`, `EUR`, `USD`, `GBP` |
| `geo` | `string` | ISO 3166-1 alpha-2 country code (default: `CH`) |
| `category` | `string` | Filter by product category |
| `brand` | `string` | Filter by brand name |
| `max_results` | `integer` | Number of results, 1-50 (default: 10) |

**nexbid_product**

| Parameter | Type | Description |
|-----------|------|-------------|
| `product_id` | `string` | Product UUID (required) |

**nexbid_categories**

| Parameter | Type | Description |
|-----------|------|-------------|
| `geo` | `string` | ISO 3166-1 alpha-2 country code to filter categories |

## Authentication

The server supports optional API key authentication via two methods:

- **Bearer token:** `Authorization: Bearer YOUR_API_KEY`
- **Header:** `x-api-key: YOUR_API_KEY`

When no `NEXBID_MCP_API_KEY` environment variable is configured on the server, authentication is disabled and the endpoint is openly accessible. API keys use timing-safe comparison to prevent timing attacks.

## Rate Limits

- **100 requests per minute** per client
- Rate limit headers included in every response: `X-RateLimit-Limit`, `X-RateLimit-Policy`, `Retry-After`
- Production rate limiting enforced via Vercel Firewall rules
- Exceeding the limit returns a `Retry-After: 60` header

## Examples

### Search for products

```bash
curl -X POST https://nexbid.dev/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "nexbid_search",
      "arguments": {
        "query": "wireless headphones",
        "intent": "purchase",
        "budget_max_cents": 20000,
        "currency": "CHF",
        "geo": "CH",
        "max_results": 5
      }
    }
  }'
```

### Get product by ID

```bash
curl -X POST https://nexbid.dev/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "nexbid_product",
      "arguments": {
        "product_id": "550e8400-e29b-41d4-a716-446655440000"
      }
    }
  }'
```

### List categories

```bash
curl -X POST https://nexbid.dev/mcp \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "nexbid_categories",
      "arguments": {
        "geo": "CH"
      }
    }
  }'
```

## Response Format

The server implements **JSON-RPC 2.0** over **MCP Streamable HTTP** transport.

All requests are `POST` to `/mcp` with `Content-Type: application/json`. Responses follow the standard MCP content format:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Found 12 products (showing 5) in 42ms.\n\n1. **Sony WH-1000XM5** (Sony)\n   Price: 299.00 CHF\n   Availability: in_stock\n   Score: 87%\n   Link: https://example.com/product/wh1000xm5"
      }
    ]
  }
}
```

Error responses use `isError: true` in the result or standard JSON-RPC error codes:

| Code | Meaning |
|------|---------|
| `-32000` | Authentication error (401) |
| `-32600` | Invalid request |
| `-32601` | Method not found |
| `-32603` | Internal server error |

## Health Check

```bash
curl https://nexbid.dev/health
```

Returns:

```json
{
  "status": "ok",
  "server": "nexbid",
  "version": "1.0.0",
  "transport": "streamable-http",
  "database": "connected",
  "timestamp": "2026-02-22T10:00:00.000Z"
}
```

When the database is unreachable, returns HTTP 503 with `"status": "degraded"` and `"database": "disconnected"`.

## Local Development

```bash
# Clone the repository
git clone https://github.com/Baldri/nexbid.git
cd nexbid

# Install dependencies
npm install

# Set environment variables
export DATABASE_URL="postgresql://user:pass@host/nexbid"

# Start local dev server
cd packages/mcp-server
npx vercel dev
```

The MCP endpoint will be available at `http://localhost:3000/mcp` and health check at `http://localhost:3000/health`.

### Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `DATABASE_URL` | Yes | Neon Postgres connection string |
| `NEXBID_MCP_API_KEY` | No | API key for authentication (disabled if unset) |

### Running Tests

```bash
cd packages/mcp-server
npm test          # Watch mode
npm run test:run  # Single run
```

## Tech Stack

- **Runtime:** Node.js 20+ with TypeScript (strict mode)
- **Protocol:** [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) v1.6+
- **Transport:** Streamable HTTP (stateless, serverless-optimized)
- **Database:** [Neon](https://neon.tech) Serverless Postgres (Frankfurt, `aws-eu-central-1`)
- **Hosting:** [Vercel](https://vercel.com) Serverless Functions (Frankfurt, `fra1`)
- **Validation:** [Zod](https://zod.dev) schemas for all tool parameters
- **Testing:** [Vitest](https://vitest.dev)

## License

[MIT](https://opensource.org/licenses/MIT) -- Copyright (c) 2025 digital opua GmbH

## Links

- **Website:** [https://nexbid.dev](https://nexbid.dev)
- **MCP Endpoint:** [https://nexbid.dev/mcp](https://nexbid.dev/mcp)
- **Health Check:** [https://nexbid.dev/health](https://nexbid.dev/health)
- **GitHub:** [https://github.com/Baldri/nexbid](https://github.com/Baldri/nexbid)
- **MCP Specification:** [https://modelcontextprotocol.io](https://modelcontextprotocol.io)