Skip to main content
Glama
miqui

yelp-mcp-sdk

by miqui
README.md
# yelp-mcp-sdk

Yelp Fusion MCP server built on the [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).
Functionally identical to [yelp-mcp-min](https://github.com/miqui/yelp-mcp-min) (FastMCP), but uses the low-level
`Server` class directly — no framework abstractions.

## Prerequisites

- Python 3.11+
- uv 0.11+
- Docker (optional)
- A Yelp Fusion API key — https://www.yelp.com/developers/v3/manage_app

## Installation

```bash
uv sync
cp .env.example .env
# Edit .env and set YELP_API_KEY
```

## Running

```bash
# stdio transport (for use with Claude Desktop or an MCP client)
uv run python -m server.main

# Docker
docker build -t yelp-mcp-sdk .
docker buildx build -t yelp-mcp-sdk .
docker run --env-file .env yelp-mcp-sdk
```

## Environment variables

| Variable              | Required | Default                   | Description                          |
|-----------------------|----------|---------------------------|--------------------------------------|
| `YELP_API_KEY`        | Yes      | —                         | Yelp Fusion API bearer token         |
| `YELP_BASE_URL`       | No       | `https://api.yelp.com/v3` | API base URL                         |
| `HTTP_TIMEOUT`        | No       | `10.0`                    | Request timeout in seconds           |
| `HTTP_MAX_RETRIES`    | No       | `3`                       | Max retry attempts on 429/5xx        |
| `HTTP_RETRY_WAIT_MIN` | No       | `1.0`                     | Min back-off wait in seconds         |
| `HTTP_RETRY_WAIT_MAX` | No       | `10.0`                    | Max back-off wait in seconds         |
| `LOG_LEVEL`           | No       | `INFO`                    | structlog level                      |
| `JSON_LOGS`           | No       | `false`                   | Emit JSON log lines                  |

## Tools

| Tool                    | Yelp endpoint                      | Description                                    |
|-------------------------|------------------------------------|------------------------------------------------|
| `search_businesses`     | `GET /v3/businesses/search`        | Full-text + geo search with pagination         |
| `find_business_by_phone`| `GET /v3/businesses/search/phone`  | Look up a business by E.164 phone number       |
| `match_business`        | `GET /v3/businesses/matches`       | Match structured name+address to Yelp listing  |
| `get_business`          | `GET /v3/businesses/{id}`          | Full business profile by Yelp ID or alias      |
| `get_business_reviews`  | `GET /v3/businesses/{id}/reviews`  | Customer reviews with pagination               |

## Resource

`yelp://business/{id}` — Full Yelp business profile as `application/json`.
Declared via `list_resource_templates`; fetched via `read_resource`.

## Project structure

```
yelp-mcp-sdk/
  server/
    main.py              # Server("yelp-mcp", lifespan=...) + stdio run
    core/
      config.py          # pydantic-settings
      logging.py         # structlog → stderr
      client.py          # async httpx + tenacity retry
      models.py          # Pydantic output models
    handlers/
      params.py          # Pydantic input models (also generate inputSchema)
      tools.py           # list_tools() + call_tool() dispatcher
      resources.py       # list_resource_templates() + read_resource()
  tests/
    conftest.py
    test_client.py
    test_models.py
    test_handlers.py
  Dockerfile
  pyproject.toml
  .env.example
```

## Running tests

```bash
uv run pytest -v
```

## Comparison with yelp-mcp-min (FastMCP)

| Aspect             | yelp-mcp-min (FastMCP)          | yelp-mcp-sdk (official SDK)              |
|--------------------|---------------------------------|------------------------------------------|
| Tool registration  | `@mcp.tool()` decorator         | `list_tools` + `call_tool` dispatcher    |
| Input schema       | Auto-generated from func sig    | `model.model_json_schema()` explicit     |
| Output type        | Return Pydantic model directly  | `list[TextContent]` with JSON string     |
| Resources          | `@mcp.resource("uri://...")` decorator | `list_resource_templates` + `read_resource` pair |
| Dependency inject  | None (captured via closure)     | `lifespan` context → `request_context`  |
| Transport          | `mcp.run()`                     | `asyncio.run()` + `stdio_server()`      |
| Server LOC         | ~350                            | ~450                                     |

TDQS

A4.3/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: phone lookup, get full business details, get reviews, match by name/address, and general search. No overlapping functionality, making selection unambiguous.

Naming Consistency5/5

All tools follow a consistent snake_case verb_noun pattern (e.g., find_business_by_phone, get_business, search_businesses), with clear modifiers where needed. No mixing of conventions.

Tool Count5/5

Five tools is well-scoped for a Yelp API wrapper: covering search, matching, detailed lookup, reviews, and phone lookup. It's neither overly sparse nor bloated.

Completeness5/5

The tool set covers the core Yelp use cases—discovery, matching, detailed info, and reviews. There are no obvious gaps for read-only access, as mutations are not part of Yelp's public API.

Maintenance

ActivityInactive
ResponsivenessNo issues