A model context protocol server for interacting with Unblu deployments.
Project description
unblu-mcp
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
- Features
- Installation
- Configuration
- Available Tools
- Command Line Usage
- Logging & Observability
- Safety & Authorization
- Programmatic Usage
- Development
- License
🔒 Security First: This server includes built-in safety controls. The
call_apitool is marked withdestructiveHint: trueto 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, andopenWorldHintmetadata 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 and designed to be run directly via uvx - no installation required. See MCP Client Configuration below.
For development or customization, clone from source:
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": "uvx",
"args": ["unblu-mcp", "--provider", "k8s", "--environment", "dev"]
}
}
}
Windows (%APPDATA%\Claude\claude_desktop_config.json):
{
"mcpServers": {
"unblu": {
"command": "uvx",
"args": ["unblu-mcp", "--provider", "k8s", "--environment", "dev"]
}
}
}
See K8s Provider Configuration below for setting up your environments.
With Environment Variables
For direct API access without Kubernetes:
{
"mcpServers": {
"unblu": {
"command": "uvx",
"args": ["unblu-mcp"],
"env": {
"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
- Discover services:
list_services()→ See categories like "Conversations", "Users", "Bots" - Browse operations:
list_operations("Conversations")→ See available conversation operations - Get details:
get_operation_schema("conversationsGetById")→ See required parameters - 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
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 dataidempotentHint: false— Repeated calls may have different effectsopenWorldHint: 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 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:
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"},
)
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file unblu_mcp-0.3.0.tar.gz.
File metadata
- Download URL: unblu_mcp-0.3.0.tar.gz
- Upload date:
- Size: 229.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
373d235c43311b76f98a54e8d5a8db6051ad64623bfa34dda8d38d9893a58153
|
|
| MD5 |
2cd7afbb5d8ab0299941f22eb65b0481
|
|
| BLAKE2b-256 |
28c4ccaaf47f166daf0ad33956136151ee4c725584151572342c7a5be65ebcea
|
File details
Details for the file unblu_mcp-0.3.0-py3-none-any.whl.
File metadata
- Download URL: unblu_mcp-0.3.0-py3-none-any.whl
- Upload date:
- Size: 233.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da3fc9d76c4347dc2631f291f4902d1b9c03a1c7c4b49baeca7a8201b3164225
|
|
| MD5 |
1190476fae3616c2a385d73412c884d3
|
|
| BLAKE2b-256 |
5238e9d7e61f3accf1dcb47801cfd09a83be5b4433ca092af57ce5a027764310
|