Metadata-Version: 2.4
Name: brp-mcp
Version: 0.2.0
Summary: MCP server exposing LanternBRP Gateway APIs as AI-agent tools.
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: fastmcp>=2.0.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.7.0
Provides-Extra: dev
Requires-Dist: pytest>=8.2.0; extra == "dev"

# LanternBRP MCP Server

MCP server that exposes LanternBRP Gateway APIs as AI-agent tools. Works with Cursor, Claude Desktop, and any MCP-compatible AI host.

## Build & Publish (for maintainers)

```bash
cd brp_mcp_python_package/

# Install build tools (one-time)
pip install build twine

# Build the package
python -m build

# Upload to PyPI
twine upload dist/*
```

This creates `dist/brp_mcp-<version>-py3-none-any.whl` and `dist/brp_mcp-<version>.tar.gz`. After publishing, all users get the update via `uvx --upgrade brp-mcp`.

To bump the version before a release, edit `version` in `pyproject.toml`:

```toml
[project]
version = "0.2.1"
```

## Quick Start (for AI-agent users)

Add this to your MCP config (e.g. Cursor's `mcp.json` or Claude Desktop's config):

```json
{
  "brp_mcp_server": {
    "command": "uvx",
    "args": ["--upgrade", "brp-mcp"],
    "env": {
      "BRP_ENV": "dev",
      "BRP_AUTH0_CLIENT_ID": "<your-client-id>",
      "BRP_AUTH0_CLIENT_SECRET": "<your-client-secret>"
    }
  }
}
```

That's it. The server auto-resolves gateway URLs, Auth0 domain, audience, tool descriptions, and visibility from the bundled config based on `BRP_ENV`.

## How It Works

```
AI Agent (Cursor / Claude Desktop)
    ↕  MCP Protocol (stdio)
brp-mcp server (local subprocess)
    ↕  HTTPS (Auth0 bearer token)
LanternBRP Gateway API
```

1. The AI host spawns `brp-mcp` as a child process via `uvx`
2. The server fetches the LanternBRP Gateway's OpenAPI spec over HTTP
3. It registers one MCP tool per visible API endpoint
4. Tool descriptions are enriched with N8N-style domain instructions
5. When the AI calls a tool, the server makes an authenticated HTTP request to the Gateway
6. Auth0 M2M tokens are obtained automatically using the provided client credentials

### Bundled Config

All config files are shipped inside the Python package:

| File | Purpose |
|------|---------|
| `bundled_config/env_profiles.json` | Gateway URLs + Auth0 domain/audience per environment |
| `bundled_config/n8n_description_enrichments.json` | Rich tool descriptions with domain-specific instructions |
| `bundled_config/mcp_visibility_policy.json` | Controls which API endpoints are exposed as tools |
| `bundled_config/n8n_system_prompt.txt` | System prompt for the BRP AI assistant |

### Config Resolution Priority

Each config value is resolved in this order (first match wins):

```
1. Environment variable      (BRP_OPENAPI_URL, BRP_AUTH0_DOMAIN, etc.)
2. CWD-relative .config/     (for local dev when running from project dir)
3. Bundled config in package  (ships with the PyPI wheel)
4. Hardcoded fallback         (safety net in source code)
```

## Environment Variables

### Required (in mcp.json `env` block)

| Variable | Description |
|----------|-------------|
| `BRP_ENV` | Environment: `dev`, `stage`, or `prod` |
| `BRP_AUTH0_CLIENT_ID` | Auth0 M2M application client ID |
| `BRP_AUTH0_CLIENT_SECRET` | Auth0 M2M application client secret |

### Optional Overrides

| Variable | Default | Description |
|----------|---------|-------------|
| `BRP_AUTH0_DOMAIN` | From profile | Auth0 tenant domain (auto-resolved from `BRP_ENV`) |
| `BRP_AUTH0_AUDIENCE` | From profile | Auth0 API audience (auto-resolved from `BRP_ENV`) |
| `BRP_OPENAPI_URL` | From profile | Override the OpenAPI spec URL |
| `BRP_GATEWAY_BASE_URL` | From profile | Override the gateway base URL |
| `BRP_API_TOKEN` | _(none)_ | Direct bearer token (skips Auth0 flow) |
| `BRP_MCP_NAME` | `LanternBRP Gateway MCP` | Display name for the MCP server |
| `BRP_TRANSPORT` | `stdio` | Transport: `stdio` or `sse` |
| `BRP_HOST` | `0.0.0.0` | Bind host for SSE mode |
| `BRP_PORT` | `6010` | Bind port for SSE mode |
| `BRP_HTTP_TIMEOUT_SECONDS` | `30` | Gateway HTTP request timeout |
| `BRP_LOG_LEVEL` | `INFO` | Log level |
| `BRP_LOG_FILE` | _(none)_ | Write logs to file instead of stderr |
| `BRP_DEFAULT_VISIBILITY` | `false` | Default visibility for unlisted endpoints |
| `BRP_ENRICHMENTS_PATH` | _(bundled)_ | Override path to enrichments JSON |
| `BRP_VISIBILITY_POLICY_PATH` | _(bundled)_ | Override path to visibility policy JSON |
| `BRP_ENV_CONFIG_PATH` | _(bundled)_ | Override path to env profiles JSON |

### Environment Profiles

| Environment | Gateway URL | OpenAPI Spec URL |
|-------------|-------------|------------------|
| `dev` | `https://api.dev.lanternbrp.com` | `https://api.dev.lanternbrp.com/api/docs/swagger.json` |
| `stage` | `https://api.stage.lanternbrp.com` | `https://api.stage.lanternbrp.com/api/docs/swagger.json` |
| `prod` | `https://api-prod.lanternbrp.com` | `https://api-prod.lanternbrp.com/api/docs/swagger.json` |

## How to Enhance (Add New API Endpoints)

When the LanternBRP Gateway adds new APIs, follow these steps to expose them as AI tools:

### Step 1: Add tool description enrichment

Edit `src/brp_mcp/bundled_config/n8n_description_enrichments.json`:

```json
{
  "GET /api/new-endpoint": {
    "n8n_node": "get New Endpoint",
    "description": "Describe what this tool does, its mandatory fields, validation rules, etc."
  },
  "POST /api/new-endpoint": {
    "n8n_node": "create New Endpoint",
    "description": "Creates a new record. Required fields: name, type."
  }
}
```

**Key format**: `METHOD /api/path` with `{*}` for path parameters (e.g. `PUT /api/items/{*}`).

### Step 2: Add visibility entry

Edit `src/brp_mcp/bundled_config/mcp_visibility_policy.json`:

```json
{
  "operations": {
    "GET /api/new-endpoint": true,
    "POST /api/new-endpoint": true
  }
}
```

Use `{id}`, `{tenantId}`, etc. for path parameters here (matching the OpenAPI spec format).

### Step 3: Add hardcoded fallback

Edit `src/brp_mcp/main.py` and add entries to `_INTERNAL_DEFAULT_VISIBLE_OPERATIONS`:

```python
_INTERNAL_DEFAULT_VISIBLE_OPERATIONS = {
    # ... existing entries ...
    "GET /api/new-endpoint",
    "POST /api/new-endpoint",
}
```

### Step 4: Build and publish

See the Build & Publish section below.

## How to Build the Package

### Prerequisites

```bash
pip install build twine
```

### Build

From inside the `brp_mcp_python_package/` directory:

```bash
python -m build
```

This creates two files in `dist/`:

- `brp_mcp-0.2.0-py3-none-any.whl` — the wheel (binary distribution)
- `brp_mcp-0.2.0.tar.gz` — source distribution

### Verify bundled configs are included

```bash
unzip -l dist/brp_mcp-*.whl | grep bundled_config
```

You should see all JSON and TXT files listed inside `brp_mcp/bundled_config/`.

## How to Publish to PyPI

### Test upload (recommended first time)

```bash
twine upload --repository testpypi dist/*
```

Verify with:

```bash
uvx --index-url https://test.pypi.org/simple/ brp-mcp --help
```

### Production upload

```bash
twine upload dist/*
```

After upload, users get the new version automatically:

```bash
uvx --upgrade brp-mcp
```

### Version bumping

Before building a new release, update the version in `pyproject.toml`:

```toml
[project]
version = "0.2.1"  # bump this
```

## Local Development

### Editable install

```bash
cd brp_mcp_python_package/
pip install -e .
```

Now `brp-mcp` runs from your local source. Changes to `.py` files take effect immediately.

### Run from source

```bash
# Using the console script
brp-mcp

# Or directly
python src/brp_mcp/main.py
```

### CWD overrides during development

When running from a directory that contains `.config/`, those files take priority over bundled configs. This lets you test enrichment/visibility changes without rebuilding the package:

```
your-project/
├── .config/
│   ├── n8n_description_enrichments.json   ← used instead of bundled
│   └── mcp_visibility_policy.json         ← used instead of bundled
└── ...
```

## Troubleshooting

### "BRP MCP startup failed: Failed to load remote spec"

The server couldn't reach the OpenAPI spec URL. Check:
- Network connectivity to the LanternBRP gateway
- `BRP_ENV` is set correctly
- If using URL overrides, verify `BRP_OPENAPI_URL` is correct

### "Incomplete Auth0 configuration"

Missing credentials. Ensure your `mcp.json` includes:
- `BRP_AUTH0_CLIENT_ID`
- `BRP_AUTH0_CLIENT_SECRET`

Domain and audience are auto-resolved from `BRP_ENV` profile.

### "Auth0 token exchange failed"

The credentials are wrong or the Auth0 application doesn't have the right permissions. Verify:
- Client ID and secret are correct for the target environment
- The Auth0 application has `client_credentials` grant enabled
- The audience matches the API identifier in Auth0

### "Missing or invalid Authorization bearer token"

No authentication method succeeded. The server tried (in order):
1. HTTP headers from MCP context
2. OAuth access token from MCP context
3. Meta authorization from request context
4. `BRP_API_TOKEN` environment variable
5. Auth0 M2M client credentials

Ensure at least one method is configured.

### Tools not appearing

Check visibility:
- The endpoint must exist in the OpenAPI spec
- It must be marked `true` in the enrichments, visibility policy, or internal allowlist
- Run with `BRP_LOG_LEVEL=DEBUG` to see which endpoints are filtered and why
