A production-ready Python client library and MCP server for the StockTrim Inventory Management API.
- 🎯 Domain Helpers: Ergonomic wrapper methods for common operations (15+ convenience functions)
- 🔄 Transport-Layer Resilience: Automatic retries with exponential backoff built into HTTP transport
- ⚡ Modern Python: Fully async/await with comprehensive type hints (ty strict)
- 🔐 Custom Authentication: Automatic handling of StockTrim
api-auth-idandapi-auth-signatureheaders - 🛡️ Typed Exceptions: Structured error handling (AuthenticationError, ValidationError, ServerError, etc.)
- 📦 OpenAPI Generated: Always up-to-date with the latest StockTrim API
- 🤖 AI Integration: Natural language interface for Claude and other AI assistants
- ⚡ FastMCP: High-performance Model Context Protocol implementation
- 🔧 Production Ready: 5 tools across product, customer, and inventory domains
- 🎯 Type-Safe: Full Pydantic validation for all operations
- 📝 Well-Documented: Comprehensive usage examples and troubleshooting
# With UV (recommended)
uv add stocktrim-openapi-client
# With pip
pip install stocktrim-openapi-client
# With Poetry
poetry add stocktrim-openapi-client# With UV
uv add stocktrim-mcp-server
# With pip
pip install stocktrim-mcp-serverfrom stocktrim_public_api_client import StockTrimClient
async with StockTrimClient(
api_auth_id="your_tenant_id",
api_auth_signature="your_tenant_name"
) as client:
# Product operations
product = await client.products.find_by_code("WIDGET-001")
widgets = await client.products.search("WIDGET")
exists = await client.products.exists("WIDGET-001")
# Customer operations
customer = await client.customers.get("CUST-001")
customer = await client.customers.find_or_create(
"CUST-002",
name="New Customer",
email="customer@example.com"
)
# Inventory operations
await client.inventory.set_for_product(
product_id="123",
stock_on_hand=50.0,
stock_on_order=100.0,
location_code="WAREHOUSE-A"
)from stocktrim_public_api_client import StockTrimClient
from stocktrim_public_api_client.generated.api.products import get_api_products
from stocktrim_public_api_client.utils import unwrap
async with StockTrimClient(
api_auth_id="your_tenant_id",
api_auth_signature="your_tenant_name"
) as client:
# Direct API call with automatic retries and auth
response = await get_api_products.asyncio_detailed(client=client)
# Unwrap response or raise typed exception
products = unwrap(response) # Raises AuthenticationError, ServerError, etc.# Set environment variables
export STOCKTRIM_API_AUTH_ID=your_tenant_id
export STOCKTRIM_API_AUTH_SIGNATURE=your_tenant_name
# Run server
uvx stocktrim-mcp-serverFor Claude Desktop integration, see MCP Server README.
The client provides convenient helper classes that wrap the generated API:
find_by_code(code)- Get product by exact codesearch(code_prefix)- Find products starting with prefixexists(code)- Check if product existsget_all()- List all productscreate(...)- Create new productdelete(product_id)- Delete product
get(code)- Get customer by codeget_all()- List all customersexists(code)- Check if customer existsfind_or_create(code, **defaults)- Get or create customer (idempotent)update(customer)- Update customer
find_by_code(code)- Get supplier by code (handles API inconsistencies)create_one(supplier)- Create single supplierexists(code)- Check if supplier existsget_all()- List all supplierscreate([suppliers])- Batch create suppliersdelete(code)- Delete supplier
get_for_product(product_id)- Get orders for specific productdelete_for_product(product_id)- Delete all orders for productget_all()- List all orderscreate(...)- Create orderdelete(...)- Delete orders
find_by_reference(reference_number)- Get order by referenceexists(reference_number)- Check if order existsget_all()- List all orderscreate(...)- Create orderdelete(...)- Delete orders
set_for_product(product_id, stock_on_hand, stock_on_order, ...)- Set inventory levelsset(request)- Batch set inventory
get_all()- List all locationscreate(...)- Create location
See docs/user-guide/helper-methods.md for complete documentation.
The client provides typed exceptions for structured error handling:
from stocktrim_public_api_client.utils import (
unwrap,
AuthenticationError,
ValidationError,
NotFoundError,
ServerError
)
try:
product = unwrap(response)
except AuthenticationError:
print("Invalid credentials")
except ValidationError as e:
print(f"Validation failed: {e.validation_errors}")
except NotFoundError:
print("Product not found")
except ServerError as e:
print(f"Server error: {e.status_code}")# Required
STOCKTRIM_API_AUTH_ID=your_tenant_id
STOCKTRIM_API_AUTH_SIGNATURE=your_tenant_name
# Optional
STOCKTRIM_BASE_URL=https://api.stocktrim.com # Defaultasync with StockTrimClient(
api_auth_id="your_tenant_id",
api_auth_signature="your_tenant_name",
base_url="https://api.stocktrim.com",
timeout=30.0,
max_retries=5
) as client:
# Use client
passResilience features are implemented at the HTTP transport level:
- Automatic retries on 5xx errors for idempotent methods (GET, HEAD, OPTIONS, TRACE)
- Exponential backoff with jitter to prevent thundering herd
- Error logging with detailed response parsing
- Custom authentication injection without modifying generated code
This approach ensures:
- ✅ All generated API methods automatically get resilience features
- ✅ No code changes needed when regenerating from OpenAPI spec
- ✅ Type safety preserved throughout
- ✅ Optimal performance (resilience at lowest level)
Helper classes provide:
- Clear intent with intuitive method names
- API inconsistency handling (e.g., single vs list returns)
- Common patterns for frequent workflows
- Reduced boilerplate for simple operations
- Full type safety with comprehensive hints
The MCP server provides 5 tools for AI assistant integration:
- get_product - Retrieve product by code
- search_products - Search products by prefix
- get_customer - Retrieve customer by code
- list_customers - List all customers
- set_product_inventory - Update inventory levels
Example conversation with Claude:
You: What products do we have starting with "WID"?
Claude: [uses search_products("WID")]
Found 3 products:
- WIDGET-001: Standard Widget ($10.00)
- WIDGET-002: Premium Widget ($15.00)
- WIDGET-SPECIAL: Custom Widget ($25.00)
See stocktrim_mcp_server/README.md for detailed usage.
# Clone repository
git clone https://github.com/dougborg/stocktrim-openapi-client.git
cd stocktrim-openapi-client
# Install UV (if needed)
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
# Install dependencies
uv sync --all-extras
# Install pre-commit hooks
uv run pre-commit install# Run tests
uv run poe test
# Run linting
uv run poe lint
# Format code
uv run poe format
# Type check
uv run ty check
# Regenerate client from OpenAPI spec
uv run poe regenerate-client
# Build documentation
uv run poe docs-build
# Run all checks (format + lint + test)
uv run poe check# All tests
uv run poe test
# With coverage
uv run poe test-coverage
# Unit tests only
uv run poe test-unit
# Integration tests only
uv run poe test-integrationstocktrim-openapi-client/
├── stocktrim_public_api_client/ # Client library
│ ├── stocktrim_client.py # Main client with transport layer
│ ├── helpers/ # Domain helper classes
│ │ ├── products.py
│ │ ├── customers.py
│ │ ├── suppliers.py
│ │ ├── sales_orders.py
│ │ ├── purchase_orders.py
│ │ ├── inventory.py
│ │ └── locations.py
│ ├── utils.py # Response unwrapping & exceptions
│ └── generated/ # OpenAPI-generated code
│ ├── api/ # API endpoint methods
│ ├── models/ # Data models
│ └── client.py # Base client
├── stocktrim_mcp_server/ # MCP server package
│ └── src/stocktrim_mcp_server/
│ ├── server.py # FastMCP server
│ └── tools/ # MCP tool implementations
├── tests/ # Test suite
├── scripts/ # Development scripts
└── docs/ # Documentation
- Full Documentation: https://dougborg.github.io/stocktrim-openapi-client/
- Client Guide: docs/user-guide/client-guide.md
- Helper Methods: docs/user-guide/helper-methods.md
- Testing Guide: docs/user-guide/testing.md
- MCP Server: stocktrim_mcp_server/README.md
Contributions are welcome! Please see:
- Development Setup above
- Code of Conduct
- API Feedback - Constructive feedback for StockTrim developers
MIT License - see LICENSE for details.
- Built with httpx for modern async HTTP
- Generated with openapi-python-client
- MCP server built with FastMCP
- Architecture patterns inspired by katana-openapi-client
- Issues: GitHub Issues
- Source: GitHub Repository
- StockTrim: www.stocktrim.com