Binner MCP Server
# Binner MCP Server
A Model Context Protocol (MCP) server and Python API client that connects AI assistants and automation tools to local [Binner](https://github.com/binner-io/binner) inventory instances and the [Binner Swarm](https://swarm.binner.io) cloud component service.
---
## What It Does
Binner is an inventory management system designed for electronics hobbyists and engineers to organize parts, bins, packages, and maker projects.
`binner-mcp` bridges Binner with AI coding assistants (Google Antigravity, Claude Desktop, Cursor, VS Code) using the Model Context Protocol. Once connected, your assistant can directly query stock, track bin locations, update part counts, manage Bills of Materials (BOM), and fetch pinouts or datasheets.
### Example Prompts
Once configured, you can interact with your inventory using natural language:
* **Stock & Bin Lookups**:
* *"Do we have any 10k 0805 resistors in stock, and what bin are they in?"*
* *"List all components stored in bin shelf A1."*
* **Low-Stock & Reorders**:
* *"Check inventory for low-stock components and list parts below their threshold."*
* **Maker Projects & BOM Deductions**:
* *"What parts are needed for the USB-C Power Supply project?"*
* *"Deduct inventory for building 5 units of the ESP32 Gateway project."*
* **Cloud Intelligence**:
* *"Fetch the pinout, package footprint, and datasheet for part NE555P."*
* **Stock Adjustments**:
* *"Add 25 units to 2N3904 transistors."*
---
## 2-Minute Quickstart
### 1. Prerequisites
* **Python:** Version 3.10 or higher.
* **Binner Instance:** A running local Binner server (default: `http://127.0.0.1:8090`).
### 2. Installation
Install the package in editable mode using an isolated virtual environment:
```bash
# 1. Create and activate virtual environment
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 2. Install package
pip install -e .
```
### 3. Add to Your AI Assistant
Add the `binner` server definition to your client's MCP configuration file:
```json
{
"mcpServers": {
"binner": {
"command": "/path/to/.venv/bin/binner-mcp",
"env": {
"BINNER_BASE_URL": "http://127.0.0.1:8090",
"BINNER_USERNAME": "admin",
"BINNER_PASSWORD": "admin"
}
}
}
}
```
*Replace `/path/to/.venv/bin/binner-mcp` with the absolute path to `binner-mcp` in your virtual environment, and adjust credentials as needed.*
#### Configuration File Locations
* **Google Antigravity / Gemini CLI:** `~/.gemini/antigravity/mcp_config.json`
* **Claude Desktop:**
* Linux: `~/.config/Claude/claude_desktop_config.json`
* macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
* Windows: `%APPDATA%\Claude\claude_desktop_config.json`
* **Cursor:** Under **Settings > Features > MCP**, click **+ Add New MCP Server** (`Name: binner`, `Type: command`, `Command: /path/to/.venv/bin/binner-mcp`).
* **VS Code (Cline / Roo Code):** `cline_mcp_settings.json`
### 4. Verify Connection
Ask your AI assistant:
> *"Check Binner system status."*
Or run the server standalone from the terminal to verify connectivity:
```bash
binner-mcp
```
---
## Core Capabilities
* **Dual Interface**: Operate as an autonomous MCP server (supporting `stdio`, `http`, and `sse` transports) or import directly as a Python library (`BinnerAPIProxy`, `SwarmClient`).
* **Component Inventory Lifecycle**: Batch creation and updates (`save_parts`), deletion (`delete_parts`), selective field projection (`fields=['quantity', 'location', 'bin_number']`), and low-stock monitoring.
* **Strict Stock Adjustment Semantics**: Clear separation between absolute stock counts (`save_parts`, `PUT /api/part`) and additive deltas (`adjust_stock_delta`, `POST /api/part/quantity`, `/increment`, `/decrement`).
* **Hierarchical Category Management**: Delimiter-based category paths (default delimiter: `::`, e.g., `Passives::Resistors::SMD`), automatic parent node creation, and ambiguity detection.
* **Maker Projects & BOM Engineering**: Project tracking, Bill of Materials component allocation with silkscreen reference designators (e.g. `R1, R2, C1`), and optional simultaneous stock delta adjustments.
* **Production Batch Deduction with Shortage Circuit Breaker**: Automated component deduction (`consume_project_bom`) for batch assemblies. If on-hand stock is insufficient for any BOM item, execution halts immediately with zero database mutations and returns a detailed shortage matrix.
* **Swarm Cloud Component Enrichment**: Live querying of `swarm.binner.io` for pinouts, package footprints, and manufacturer datasheets via `lookup_cloud_parts`.
* **Pre-Flight Zero-Side-Effects Validation**: In batch operations (`save_parts`, `manage_bom_parts`), full payload validation runs before any mutation executes; an error on any item aborts the entire batch.
* **Strict Parameter Enforcement**: All MCP tools and models reject unknown arguments (`extra="forbid"`), preventing hallucinated arguments or subtle typos from corrupting inventory.
* **Deterministic Part Identity Resolution**: Automatic bidirectional reconciliation between numeric part IDs and alphanumeric part numbers, circumventing upstream backend query omission bugs.
* **Stdio Transport Safety**: JSON-RPC transport stream protection via strict `sys.stderr` log routing.
---
## Client Integration & Agent Skills
### Agent Skill Integration (`docs/skill-template/`)
The repository includes a domain skill conforming to the open **Agent Skills** standard in [`docs/skill-template/SKILL.md`](docs/skill-template/SKILL.md) and [`docs/skill-template/references/bin_content_typology.md`](docs/skill-template/references/bin_content_typology.md). While MCP provides the execution layer (tools and resources), the skill equips AI assistants with task-driven workflows, batch schemas, parameter constraints (`extra="forbid"`), and the automated BOM shortage circuit breaker. It leverages **progressive disclosure** (indexing metadata at startup and loading instructions on demand).
#### 1. Native Skill Clients (Antigravity, Claude Code, Cursor, Copilot)
Enables automatic discovery and progressive disclosure without manual prompt injection.
**Installation (Project or Global):**
```bash
# Workspace / Project install (shared with team via version control):
mkdir -p .agents/skills/binner
cp -r docs/skill-template/* .agents/skills/binner/
# Or Global / User install (available across all local workspaces):
mkdir -p ~/.gemini/config/skills/binner
cp -r docs/skill-template/* ~/.gemini/config/skills/binner/
```
*Symlinks are also supported: `ln -s "$(pwd)/docs/skill-template/SKILL.md" ~/.gemini/config/skills/binner/SKILL.md`.*
**Discovery Paths:**
* **Google Antigravity / Gemini CLI:**
* Workspace: `.agents/skills/binner/SKILL.md` (or `.agent/skills/binner/SKILL.md`)
* Global: `~/.gemini/config/skills/binner/SKILL.md` (or `~/.gemini/antigravity/skills/binner/SKILL.md`)
* **Claude Code:**
* Workspace: `.claude/skills/binner/SKILL.md`
* Global: `~/.claude/skills/binner/SKILL.md`
* **Cursor (Agent Mode):** `.agents/skills/binner/SKILL.md` or `.cursor/skills/binner/SKILL.md`
* **GitHub Copilot (Agent Mode):** `.agents/skills/binner/SKILL.md` or `.github/skills/binner/SKILL.md`
#### 2. Instruction & Rule-Based Clients (Claude Desktop, Cursor Rules, Cline / Roo Code)
For clients without native skill discovery directories, reference `docs/skill-template/SKILL.md` directly in configuration or rule files:
```markdown
# Include in your client instructions / rule file:
Read and adhere to the Binner domain workflows and constraints in docs/skill-template/SKILL.md
when handling electronic parts, category hierarchies, Maker projects, or BOM assembly.
```
**Configuration Paths:**
* **Cursor:** Add reference or include contents in `.cursorrules` or `.cursor/rules/binner.mdc`.
* **VS Code (Cline / Roo Code):** Include path or content in `.clinerules`.
* **Claude Desktop:** Attach `docs/skill-template/SKILL.md` to **Project Knowledge** or add reference in Project Custom Instructions.
* **GitHub Copilot:** Add reference to `.github/copilot-instructions.md`.
---
## Server Usage & Transports
All logging routes strictly to `sys.stderr` to preserve JSON-RPC stream integrity.
```bash
# 1. Run with default stdio transport (local subprocess)
binner-mcp
# 2. Run over modern Streamable HTTP transport on port 8000
binner-mcp --transport http --host 127.0.0.1 --port 8000
# 3. Run over legacy Server-Sent Events (SSE) transport on port 8000
binner-mcp --transport sse --host 127.0.0.1 --port 8000
# 4. Run via Python module with explicit config and TRACE logging
python -m binner_mcp.main --config /path/to/binnermcp_config.json --log-level TRACE
```
### Local HTTP & SSE Clients
> **Security Notice:** Binner MCP is a local private sidecar. **Never expose this server to external networks or the public internet.** Bind strictly to localhost (`127.0.0.1`).
---
## Configuration
Configuration parameters are evaluated in the following order of precedence (highest to lowest):
1. **Command-Line Arguments**
2. **Environment Variables**
3. **Configuration File (`binnermcp_config.json`)**
4. **Built-in Defaults**
### Configuration Parameters
| Parameter | CLI Flag | Environment Variable | Default | Description |
|---|---|---|---|---|
| `base_url` | — | `BINNER_BASE_URL` | `http://localhost:8090` | Base URL of local Binner instance |
| `username` | — | `BINNER_USERNAME` | `admin` | Username for Binner authentication |
| `password` | — | `BINNER_PASSWORD` | `admin` | Password for Binner authentication |
| `log_level` | `--log-level` | `BINNER_LOG_LEVEL` | `INFO` | Logging level (`TRACE`, `DEBUG`, `INFO`, `WARNING`, `ERROR`) |
| `transport` | `--transport` | `BINNER_MCP_TRANSPORT` | `stdio` | MCP transport (`stdio`, `http`, or `sse`) |
| `host` | `--host` | `BINNER_MCP_HOST` | `127.0.0.1` | Bind address for HTTP / SSE transport |
| `port` | `--port` | `BINNER_MCP_PORT` | `8000` | Port for HTTP / SSE transport |
| `category_delimiter` | `--category-delimiter` | `BINNER_CATEGORY_DELIMITER` | `::` | Delimiter for category hierarchy paths |
| `log_file` | `--log-file` | `BINNER_LOG_FILE` | `None` | Optional path to write log output in addition to stderr |
| `retry_delay` | `--retry-delay` | `BINNER_RETRY_DELAY` | `3.0` | Delay in seconds between transient retry attempts |
| `retry_count` | `--retry-count` | `BINNER_RETRY_COUNT` | `1` | Max retry attempts for transient network errors |
| *config file* | `--config` | `BINNER_MCP_CONFIG` | `./binnermcp_config.json` | Explicit path to `binnermcp_config.json` |
### Configuration File Resolution (`binnermcp_config.json`)
If no CLI flags or environment variables are provided, values are read from `binnermcp_config.json`. The server searches the following paths in order:
1. Path passed via `--config` or `BINNER_MCP_CONFIG`
2. Current working directory: `./binnermcp_config.json`
3. Project root directory
4. User configuration directory: `~/.config/binnermcp/binnermcp_config.json`
5. System-wide configuration directory: `/etc/binnermcp/binnermcp_config.json`
Example `binnermcp_config.json`:
```json
{
"base_url": "http://localhost:8090",
"username": "admin",
"password": "your-password",
"log_level": "INFO",
"transport": "stdio",
"host": "127.0.0.1",
"port": 8000,
"category_delimiter": "::",
"retry_delay": 3.0,
"retry_count": 1
}
```
---
## MCP API Reference
### Tools Directory (15 Registered Tools)
All tools enforce strict argument checking (`extra="forbid"`) and execute through a single-thread FIFO proxy queue.
| Tool Name | Domain | Primary Parameters | Summary |
|---|---|---|---|
| `get_system_status` | System | `check_cloud: bool = False` | Probe Binner connectivity, version, identity, and inventory statistics. |
| `lookup_cloud_parts` | Cloud | `part_numbers: str[]` | Query Binner Swarm cloud for pinouts, package footprints, and datasheets. |
| `list_parts` | Inventory | `query`, `part_type`, `bin_number`, `location`, `package_type`, `manufacturer`, `low_stock_only`, `fields`, `page`, `limit`, `sort_by`, `direction` | Paginated component search with metadata filtering and field projection. |
| `get_parts` | Inventory | `part_numbers: str[]`, `part_ids: int[]`, `fields: str[]` | Batch component inspection returning details, bin locations, and datasheets. |
| `save_parts` | Inventory | `parts: PartSaveInput[]` | Batch create or update components with strict pre-flight validation. |
| `delete_parts` | Inventory | `part_numbers: str[]`, `part_ids: int[]` | Batch component deletion by part number or ID. |
| `list_part_types` | Categories | `depth`, `root_id`, `root_name`, `include_descriptions`, `include_part_counts` | Hierarchical category tree optimized for minimal LLM context usage. |
| `save_part_types` | Categories | `part_types: PartTypeSaveInput[]` | Batch create or update category hierarchy nodes. |
| `delete_part_types` | Categories | `ids: int[]`, `names: str[]` | Batch category deletion by ID or name. |
| `list_projects` | Projects | `query`, `page`, `limit`, `sort_by`, `direction` | Paginated search of maker projects. |
| `get_projects` | Projects | `project_ids: int[]`, `names: str[]`, `include_bom: bool = False` | Batch maker project retrieval with optional normalized BOM breakdown. |
| `save_projects` | Projects | `projects: ProjectSaveInput[]` | Batch create or update maker projects. |
| `delete_projects` | Projects | `project_ids: int[]`, `names: str[]` | Batch project deletion by ID or name. |
| `manage_bom_parts` | BOM | `project_id: int`, `parts: BomPartInput[]` | Batch allocate, modify, or remove BOM line items for a project. |
| `consume_project_bom` | BOM | `project_id: int`, `name: str`, `build_quantity: int = 1` | Deduct component stock for board unit assembly with shortage circuit breaker. |
---
### Dynamic Resources Directory (5 Registered Resources)
| Resource URI | MIME Type | Description |
|---|---|---|
| `binner://status` | `application/json` | System health, version, auth identity, and aggregate inventory summary. |
| `binner://categories` | `application/json` | Hierarchical category tree with resolved category paths. |
| `binner://low-stock` | `application/json` | Filtered snapshot of components at or below low-stock thresholds. |
| `binner://projects/{project_id}/bom` | `application/json` | Complete Bill of Materials item breakdown for a specified project ID. |
| `binner://parts/{identifier}` | `application/json` | Complete specifications and category path for a part (by ID or part number). |
---
## Python API Quickstart
`binner-mcp` can also be used as a standalone Python library:
```python
from binner_mcp.api.client import BinnerAPIProxy
from binner_mcp.swarmer.client import SwarmClient
# 1. Connect to local Binner instance
client = BinnerAPIProxy(base_url="http://localhost:8090", username="admin", password="admin")
if client.ping():
client.login()
print(f"Logged in as: {client.get_identity().name}")
# 2. Query low-stock parts
low_stock = client.get_low_stock(results=5)
for part in low_stock.items:
print(f"Low stock: {part.part_number} (Qty: {part.quantity}, Min: {part.low_stock_threshold})")
# 3. Add additive stock delta
client.increment_quantity(part_number="NE555P", quantity=10)
# 4. Query cloud datasheets & pinouts from Binner Swarm
swarm = SwarmClient()
result = swarm.search_parts(part_number="2N3904")
if result.is_success and result.response:
for part in result.response.parts:
print(f"Swarm part: {part.name} - {len(part.part_number_manufacturers)} manufacturers found")
```
---
## System Architecture
The codebase implements a decoupled dual-layered architecture with a common foundation core:
```
+-----------------------------------------------------------------------------------+
| Layer 2: MCP Protocol Binding Layer |
| |
| - MCP Server Setup (binner_mcp.mcp.server.BinnerMCPServer) |
| - Transports: stdio (JSON-RPC), http (Streamable HTTP), sse (Legacy SSE) |
| - 15 Registered Tools (System, Cloud, Inventory, Categories, Projects, BOM) |
| - 5 Dynamic Resources (Status, Categories, Low-Stock, Project BOM, Part Details) |
| - Single-Thread FIFO Task Queue (ThreadPoolExecutor(max_workers=1)) |
| - Pre-Flight Zero-Side-Effects Validation & extra="forbid" Safety Guard |
+-----------------------------------------------------------------------------------+
|
v
+-----------------------------------------------------------------------------------+
| Layer 1: Python API Client Interfaces |
| |
| Layer 1A: Local Binner API Client Layer 1B: Swarmer Cloud Client |
| (binner_mcp.api.client.BinnerAPIProxy) (binner_mcp.swarmer.SwarmClient) |
| ├── PartsComp (CRUD, stock deltas, labels) ├── Pinouts, Footprints, Schematics|
| ├── ProjectsComp (Maker projects, BOM items) ├── Direct PDF Datasheet URLs |
| ├── PartTypesComp (Category tree management) └── Quota Rate-Limit Tracking |
| ├── DataComp (CSV bulk import, ZIP export) |
| ├── SystemComp (Ping, version, server logs) |
| ├── PartCacheComp (Bidirectional ID <-> PN) |
| └── BaseBinnerClient (JWT + HttpOnly cookie) |
+-----------------------------------------------------------------------------------+
|
v
+-----------------------------------------------------------------------------------+
| Common Core & Upstream Services |
| |
| binner_mcp.common: |
| - BaseHttpClient (requests.Session pooling, threading.RLock re-entrant safety) |
| - logging (sys.stderr routing, custom TRACE level 5, sensitive data redaction) |
| - Pydantic v2 Base Models & Unified Exception Hierarchy |
| |
| Upstream Targets: |
| - Local Binner Instance (.NET 8 / Kestrel, default: http://127.0.0.1:8090) |
| - Binner Swarm Cloud Service (https://swarm.binner.io) |
+-----------------------------------------------------------------------------------+
```
### Layer Breakdown
1. **Layer 1A: Binner Python API Interface (`binner_mcp.api`)**:
* Programmatic, MCP-agnostic REST client (`BinnerAPIProxy`) for local Binner instances.
* Composed from modular domain components (`PartsComp`, `ProjectsComp`, `PartTypesComp`, `DataComp`, `SystemComp`).
* **In-Memory Identity Cache (`PartCacheComp`)**: Bidirectional mapping (`_part_id_to_number`, `_part_number_to_id`) that automatically resolves missing part numbers or IDs, eliminating upstream EF Core omission bugs.
* **Dual-Token Authentication (`BaseBinnerClient`)**: Manages JWT Bearer tokens and HttpOnly refresh cookies via `POST /api/authentication/refresh-token`, with 1-second timestamp granularity handling and automatic login fallback.
2. **Layer 1B: Swarmer Cloud API Interface (`binner_mcp.swarmer`)**:
* Dedicated REST client (`SwarmClient`) for the Binner Swarm cloud service (`https://swarm.binner.io`).
* Searches and retrieves pinout diagrams, package footprints, and direct PDF datasheets.
* Automatic rate-limit tracking via response headers (`x-rate-limit-limit`, `x-rate-limit-remaining`, `x-rate-limit-reset`) and error classification (`SwarmRateLimitError`, `SwarmTimeoutError`).
3. **Common Core Foundation (`binner_mcp.common`)**:
* `BaseHttpClient`: Connection-pooled HTTP session manager guarded by `threading.RLock`, ensuring thread safety for cookie jars and token rotation.
* `logging`: Stdio transport-safe logging strictly targeting `sys.stderr`, supporting custom `TRACE` level (level 5) and recursive credential/token redaction (`sanitize_for_trace`).
4. **Layer 2: MCP Protocol Binding Layer (`binner_mcp.mcp`)**:
* `BinnerMCPServer` exposes 15 tools and 5 dynamic resources using Python MCP SDK 2.
* Multi-transport support: Standard I/O (`stdio`), modern Streamable HTTP (`http`), and legacy Server-Sent Events (`sse`).
* Single-thread FIFO task queue (`ThreadPoolExecutor(max_workers=1)`) executing sync proxy operations sequentially to eliminate race conditions on session cookies or access tokens.
* Strict argument validation (`extra="forbid"`) and category path delimiter resolution (e.g. `Passives::Resistors::SMD`).
---
## Development & Testing
```bash
# Run full test suite
virtenv/bin/python -m pytest tests/ -v
# Format with Black (100-char line length)
black --line-length 100 src/ tests/
```
---
## License
MIT License - see [LICENSE.txt](LICENSE.txt).
TDQS
Scored across 15 tools
Most tools have clearly distinct purposes: parts, projects, part types, BOM operations, cloud lookup, and system status are largely separate concerns. The main potential confusion is between list_parts (search by keyword/filter) and get_parts (fetch by ID/number), and between manage_bom_parts and consume_project_bom, but the descriptions draw workable boundaries.
All names follow a consistent verb_noun snake_case pattern (list_parts, get_parts, save_parts, delete_parts, list_projects, save_part_types, etc.). The upsert verb 'save' is applied uniformly, and resource suffixes are consistent across the parts/projects/part_types families.
15 tools is well-scoped for a parts/inventory management server spanning parts, projects, part types, BOM, and cloud lookup. Each family (parts, projects, part types) has a coherent CRUD-style cluster with no redundant or filler tools.
Parts and projects have full list/get/save/delete coverage, and BOM plus cloud lookup round out the lifecycle. Minor gaps: part types lack a dedicated get (though list_part_types can scope a subtree), and there is no direct tool for managing bins/locations despite parts referencing them.