Skip to main content

A model context protocol server for interacting with Unblu deployments.

Project description

unblu-mcp

ci documentation pypi version python versions license FastMCP Ruff uv

A Model Context Protocol (MCP) server for interacting with Unblu deployments. This server provides AI assistants with token-efficient access to 300+ Unblu API endpoints through progressive disclosure.

Table of Contents

🔒 Security First: This server includes built-in safety controls. The call_api tool is marked with destructiveHint: true to trigger client confirmations, and optional Eunomia integration provides server-side policy enforcement to block destructive operations. Learn more →

Features

This server implements best practices from Anthropic's guide on building effective agents:

  • Progressive Disclosure: 5 discovery tools instead of 300+ API definitions upfront, dramatically reducing token usage
  • Clear Tool Interfaces: Descriptive parameters with examples, helpful error messages that suggest alternatives
  • Full API Coverage: Access to all Unblu REST API v4 endpoints
  • Smart Discovery: Search and browse operations by service category or keyword
  • Field Filtering: Request only the fields you need to reduce response size
  • Response Truncation: Limit response sizes to prevent token overflow

Built with FastMCP 2.14+, leveraging cutting-edge features:

  • MCP Annotations: Tools include readOnlyHint, destructiveHint, and openWorldHint metadata for smarter AI decision-making
  • Response Caching: Discovery tools cache results via FastMCP middleware for faster repeated queries
  • Policy-Based Authorization: Optional Eunomia integration for controlling which API operations are allowed
  • Built-in Logging: Automatic file-based logging with daily rotation for debugging and usage analysis
  • MCP 2025-11-25 Spec: Full support for the latest Model Context Protocol specification

Installation

This package is available on PyPI. The recommended installation method is via uv tool install:

uv tool install unblu-mcp

This installs the unblu-mcp command to ~/.local/bin/ and avoids cache locking issues that affect long-running MCP servers when using uvx.

Note: You can also run directly via uvx unblu-mcp without installation, but this will block uv cache prune operations while the server is running.

From source

git clone https://github.com/detailobsessed/unblu-mcp.git
cd unblu-mcp
uv sync

Configuration

MCP Client Configuration

Add the server to your MCP client configuration (Claude Desktop, Windsurf, etc.):

With Kubernetes Provider (recommended for internal deployments)

The K8s provider automatically manages kubectl port-forward connections to your Unblu deployment. This is the most tested configuration.

macOS (~/Library/Application Support/Claude/claude_desktop_config.json or IDE MCP config):

{
  "mcpServers": {
    "unblu": {
      "command": "unblu-mcp",
      "args": ["--provider", "k8s", "--environment", "dev"],
      "env": {
        "PATH": "/Users/YOUR_USERNAME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
      }
    }
  }
}

Windows (%APPDATA%\Claude\claude_desktop_config.json):

{
  "mcpServers": {
    "unblu": {
      "command": "unblu-mcp",
      "args": ["--provider", "k8s", "--environment", "dev"],
      "env": {
        "PATH": "C:\\Users\\YOUR_USERNAME\\.local\\bin;C:\\Program Files\\...;..."
      }
    }
  }
}

See K8s Provider Configuration below for setting up your environments.

With Environment Variables

For direct API access without Kubernetes:

{
  "mcpServers": {
    "unblu": {
      "command": "unblu-mcp",
      "args": [],
      "env": {
        "PATH": "/Users/YOUR_USERNAME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin",
        "UNBLU_BASE_URL": "https://your-instance.unblu.cloud/app/rest/v4",
        "UNBLU_API_KEY": "your-api-key"
      }
    }
  }
}

Environment Variables

Variable Required Description
UNBLU_BASE_URL No Your Unblu API base URL (default: https://unblu.cloud/app/rest/v4)
UNBLU_API_KEY One of these API key for authentication (Bearer token)
UNBLU_USERNAME One of these Username for basic authentication
UNBLU_PASSWORD With username Password for basic authentication

Available Tools

The server exposes 5 tools for progressive API discovery and execution:

Tool Description
list_services() List all API service categories (e.g., Conversations, Users, Bots)
list_operations(service) List operations in a specific service
search_operations(query) Search for operations by keyword
get_operation_schema(operation_id) Get full schema for an operation
call_api(operation_id, ...) Execute any API operation

Example Workflow

  1. Discover services: list_services() → See categories like "Conversations", "Users", "Bots"
  2. Browse operations: list_operations("Conversations") → See available conversation operations
  3. Get details: get_operation_schema("conversationsGetById") → See required parameters
  4. Execute: call_api("conversationsGetById", path_params={"conversationId": "abc123"})

Advanced Options

The call_api tool supports additional parameters for token efficiency:

call_api(
    operation_id="conversationsSearch",
    body={"query": "support"},
    fields=["id", "topic", "creationTimestamp"],  # Only return these fields
    max_response_size=10000  # Truncate response if larger than 10KB
)

Command Line Usage

# Run with stdio transport (default, for MCP clients)
unblu-mcp

# Use a custom swagger.json location
unblu-mcp --spec /path/to/swagger.json

# Run with Eunomia authorization policy (requires unblu-mcp[safety])
unblu-mcp --policy /path/to/mcp_policies.json

# Run with K8s provider (auto-starts kubectl port-forward)
unblu-mcp --provider k8s --environment dev

# Run with K8s provider using custom config file
unblu-mcp --provider k8s --environment my-env --k8s-config /path/to/k8s_environments.yaml

# Show version
unblu-mcp --version

# Show debug info
unblu-mcp --debug-info

CLI Arguments

Argument Values Default Description
--spec path auto-detect Path to swagger.json
--policy path none Eunomia policy file
--provider default, k8s default Connection provider
--environment string dev K8s environment (with --provider k8s)
--k8s-config path none Custom K8s environments YAML file

Logging & Observability

The server automatically logs all tool calls to help with debugging and usage analysis.

Log Location

Logs are written to ~/.unblu-mcp/logs/ with daily rotation:

~/.unblu-mcp/logs/
├── unblu-mcp.log              # Current log
├── unblu-mcp.log.2025-01-14   # Yesterday
├── unblu-mcp.log.2025-01-13   # Day before
└── ...

Configuration

Environment Variable Description
UNBLU_MCP_LOG_DIR Custom log directory (default: ~/.unblu-mcp/logs)
UNBLU_MCP_LOG_DISABLE Set to 1, true, or yes to disable file logging

Log Format

2025-01-15 14:30:22 | INFO     | fastmcp | tools/call request: call_api(operation_id="conversationsGetById", ...)

Logs include:

  • Timestamp (UTC)
  • Log level
  • Tool name and arguments
  • Response summaries
  • Request duration (duration_ms) for performance analysis

Logs are retained for 30 days and automatically rotated at midnight UTC.

Safety & Authorization

The call_api tool can execute any Unblu API operation, including destructive ones (DELETE, PUT, POST). This is a powerful capability that requires appropriate controls.

Two Layers of Protection

Layer Type Description
MCP Annotations Client-side destructiveHint: true signals clients to prompt for confirmation
Eunomia Policies Server-side Block unauthorized operations before they execute

Layer 1: Tool Annotations (Built-in)

The call_api tool includes these MCP annotations:

  • destructiveHint: true — Signals this tool may modify data
  • idempotentHint: false — Repeated calls may have different effects
  • openWorldHint: true — Interacts with external systems

Well-behaved MCP clients (like Claude Desktop) will prompt for user confirmation before executing tools marked as destructive.

Layer 2: Policy-Based Authorization (Optional)

For server-side enforcement, use Eunomia — a FastMCP middleware library for policy-based authorization — to define what operations are allowed:

# Install with safety features
pip install unblu-mcp[safety]

# Run with policy enforcement
unblu-mcp --policy config/mcp_policies.json

The included config/mcp_policies.json provides a sensible default:

Operation Type Policy Examples
Discovery tools ✅ Allowed list_services, list_operations, search_operations, get_operation_schema
Read-only API calls ✅ Allowed ~190 operations like *Get*, *Search*, *List*, *Read*, *Find*, *Check*
Destructive API calls ❌ Blocked ~140 operations like *Create*, *Update*, *Delete*, *Send*, *Login*, etc.

Custom Policies

To allow additional operations beyond read-only, create a custom policy file. For example, to allow creating and updating conversations:

{
  "version": "1.0",
  "name": "custom-policy",
  "default_effect": "deny",
  "rules": [
    {
      "name": "allow-all-discovery",
      "effect": "allow",
      "resource_conditions": [
        {"path": "attributes.tool_name", "operator": "in",
         "value": ["list_services", "list_operations", "search_operations", "get_operation_schema"]}
      ],
      "actions": ["execute"]
    },
    {
      "name": "allow-conversation-operations",
      "effect": "allow",
      "resource_conditions": [
        {"path": "attributes.tool_name", "operator": "eq", "value": "call_api"},
        {"path": "attributes.args.operation_id", "operator": "regex",
         "value": "^conversations(Get|Search|Read|Create|Update|Set)"}
      ],
      "actions": ["execute"]
    }
  ]
}

To allow all operations (no restrictions):

{
  "version": "1.0",
  "name": "allow-all",
  "default_effect": "allow",
  "rules": []
}

See the Eunomia documentation for advanced policy configuration.

Programmatic Usage

Connection Providers

The server supports pluggable connection providers for different deployment scenarios:

from unblu_mcp import create_server, DefaultConnectionProvider

# Default provider (uses environment variables)
server = create_server()

# Custom provider with explicit credentials
provider = DefaultConnectionProvider(
    base_url="https://my-instance.unblu.cloud/app/rest/v4",
    api_key="my-api-key",
)
server = create_server(provider=provider)

Kubernetes Port-Forward Provider

For Kubernetes deployments, use the built-in K8s provider:

Prerequisites:

  • kubectl installed and in PATH
  • Authenticated to your K8s cluster (kubectl auth login or valid kubeconfig)
  • Permissions to access services in the target namespace

The provider will check authentication before starting port-forward and provide helpful error messages if something is misconfigured.

from unblu_mcp import create_server, K8sConnectionProvider

# Connect to a K8s environment (starts kubectl port-forward automatically)
provider = K8sConnectionProvider(environment="dev")
server = create_server(provider=provider)

K8s environments are configured in ~/.unblu-mcp/k8s_environments.yaml:

environments:
  t1:
    local_port: 8084
    namespace: unblu-dev
    service: haproxy
    service_port: 8080
    api_path: /app/rest/v4

Custom Connection Providers

Implement the ConnectionProvider interface for custom connectivity:

from unblu_mcp import ConnectionProvider, ConnectionConfig

class MyProvider(ConnectionProvider):
    async def setup(self) -> None:
        # Initialize connection (e.g., start tunnel)
        pass

    async def teardown(self) -> None:
        # Clean up resources
        pass

    def get_config(self) -> ConnectionConfig:
        return ConnectionConfig(
            base_url="https://api.example.com",
            headers={"X-Custom-Header": "value"},
        )

Troubleshooting

GUI Apps Don't Inherit Shell Environment (macOS)

Problem: MCP servers fail to start in Windsurf, Claude Desktop, or other GUI apps with errors like:

  • kubectl not found in PATH
  • invalid peer certificate: UnknownIssuer (TLS/proxy issues)
  • Package installation failures from corporate PyPI mirrors

Cause: macOS GUI applications launch from launchd with a minimal environment, not from your shell. They don't inherit PATH or other environment variables from ~/.zshrc or ~/.bashrc.

Solution: Add the env block to your MCP configuration:

{
  "mcpServers": {
    "unblu": {
      "command": "uvx",
      "args": ["unblu-mcp", "--provider", "k8s", "--environment", "dev"],
      "env": {
        "PATH": "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin"
      }
    }
  }
}

Add any directories containing tools your setup needs (e.g., kubectl, docker) to the PATH.

uvx Blocks uv Cache Cleaning

Problem: If you're using uvx unblu-mcp instead of the recommended uv tool install, tools like topgrade or uv cache prune will hang with:

Cache is currently in-use, waiting for other uv processes to finish

Cause: This is a known uv limitation affecting all long-running uvx processes.

Solution: Follow the recommended Installation method using uv tool install unblu-mcp.

Corporate Proxy/PyPI Mirror Issues

Problem: When installing with uv tool install, you get TLS certificate errors or timeouts connecting to corporate PyPI mirrors.

Solution: Use --no-config to bypass uv.toml settings and --native-tls to use system certificates:

uv tool install --no-config --native-tls unblu-mcp

Finding MCP Server Logs

Different clients store logs in different locations:

Client Log Location
Windsurf Check Output panel → select "MCP" or "Windsurf"
Claude Desktop ~/Library/Logs/Claude/ (macOS)
Warp ~/Library/Group Containers/2BBY89MBSN.dev.warp/Library/Application Support/dev.warp.Warp-Stable/mcp/*.log

Testing the Server Locally

To debug without an MCP client, use the included test script:

# Test with K8s provider
uv run scripts/test_client.py --provider k8s --environment dev

# Test with default provider (requires UNBLU_BASE_URL)
UNBLU_BASE_URL=https://your-instance.unblu.cloud/app/rest/v4 \
UNBLU_API_KEY=your-key \
uv run scripts/test_client.py

Development

# Clone the repository
git clone https://github.com/detailobsessed/unblu-mcp.git
cd unblu-mcp

# Install dependencies
uv sync --all-extras --dev

# Run tests
uv run poe test

# Run linting
uv run poe lint

# Build documentation
uv run poe docs

License

ISC License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unblu_mcp-0.5.1.tar.gz (232.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unblu_mcp-0.5.1-py3-none-any.whl (235.7 kB view details)

Uploaded Python 3

File details

Details for the file unblu_mcp-0.5.1.tar.gz.

File metadata

  • Download URL: unblu_mcp-0.5.1.tar.gz
  • Upload date:
  • Size: 232.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for unblu_mcp-0.5.1.tar.gz
Algorithm Hash digest
SHA256 d5df127911fbfacb6932e4c19a94e448b0300a2c63a6198e0fd3eb97629fa78e
MD5 e9216b088cfb1dcee36431c1b61bab3c
BLAKE2b-256 63378cb780aabf1dd7dab2d3299d57b7ff8b0a7dab9f44b6a6fc86091738f95b

See more details on using hashes here.

File details

Details for the file unblu_mcp-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: unblu_mcp-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 235.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for unblu_mcp-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f441e56d4d54f033f90d95d5d60c91cbf547c9765bc713235d0a1f576114920c
MD5 146d06d83893315e9065fcf7064d6dc6
BLAKE2b-256 083974a7c71d4c519c35f79f26f9ef5074fe55a795550a468ced9fdcb2efd469

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page