Skip to main content
Glama

Finizi B4B MCP Server

by hqtrung
MIT License
  • Apple
  • Linux
CLAUDE.md7.69 kB
# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a Model Context Protocol (MCP) server implementation for the Finizi B4B API. The MCP server acts as a transparent authentication proxy, forwarding user JWT tokens to the B4B API for authentication and authorization while providing AI agents with structured tools to interact with invoice management, entities, vendors, and products. **Key Architecture**: Token pass-through model - the MCP server stores user JWT tokens in session metadata and forwards them to B4B API endpoints, relying on B4B's existing authorization logic. ## Development Commands Currently this is a planning-only repository. When implementation begins: ```bash # Install UV package manager curl -LsSf https://astral.sh/uv/install.sh | sh # Install dependencies uv sync # Run MCP server uv run python -m finizi_b4b_mcp.server # Run tests uv run pytest # Run tests with coverage uv run pytest --cov=src/finizi_b4b_mcp # Lint code uv run ruff check src/ tests/ # Format code uv run ruff format src/ tests/ ``` ## B4B API Integration ### Accessing API Documentation The B4B API documentation is essential for implementation: ```bash # Download OpenAPI specification curl http://localhost:8000/api/v1/openapi.json > docs/b4b-openapi.json # Interactive documentation available at: # - Swagger UI: http://localhost:8000/docs # - ReDoc: http://localhost:8000/redoc ``` ### Authentication Flow 1. **Login**: User provides phone/password → MCP calls `/api/v1/auth/login` → Store JWT in `ctx.session.metadata['user_token']` 2. **Tool Calls**: Extract token via `extract_user_token(ctx)` → Forward as `Authorization: Bearer {token}` header 3. **Authorization**: B4B API validates JWT and checks `UserEntityRelationship` table for entity access **Critical**: All tools (except login/logout/whoami) must call `extract_user_token(ctx)` before making API requests. ## Architecture Guidelines ### Token Management - JWT tokens expire after 120 minutes - Store tokens in `ctx.session.metadata` (in-memory, never persisted) - Never log tokens or passwords - Implement token auto-refresh when < 15 minutes remain (Phase 4) ### MCP Tool Pattern Every tool should follow this structure: ```python @mcp.tool() async def tool_name( required_param: str, optional_param: Optional[str] = None, ctx: Context = None ) -> dict: """ Clear description of what the tool does. Args: required_param: Description optional_param: Description ctx: MCP context (automatically provided) Returns: Response structure description """ # 1. Extract user token user_token = await extract_user_token(ctx) # 2. Build request parameters/payload params = {...} try: # 3. Call B4B API with token pass-through response = await api_client.get/post( "/api/v1/endpoint", headers={"Authorization": f"Bearer {user_token}"}, params=params # or json=payload ) response.raise_for_status() return response.json() except httpx.HTTPStatusError as e: # 4. Handle authorization errors with friendly messages if e.response.status_code == 403: return {"error": "User-friendly access denied message"} elif e.response.status_code == 404: return {"error": "Resource not found message"} else: return {"error": f"API error: {e.response.json().get('detail', str(e))}"} except Exception as e: logger.error(f"Error in tool_name: {str(e)}") return {"error": str(e)} ``` ### Error Handling Principles - Return `{"error": "message"}` dict for all errors (never raise exceptions to user) - 403 errors → "You don't have access to entity X" - 404 errors → "Entity/Invoice X not found" - Network errors → Automatic retry via Tenacity - Never expose internal paths, IPs, or stack traces ### Multi-Tenant Authorization - MCP server: No authorization logic (just passes token) - B4B API: Enforces all authorization via JWT + `UserEntityRelationship` table - Super admins (`is_super_admin=True`): Can access any entity - Regular users: Can only access entities where they have active relationships ## Repository Structure ``` finizi-b4b-mcp-server/ ├── src/finizi_b4b_mcp/ │ ├── server.py # MCP server entry point with lifespan management │ ├── config.py # Pydantic Settings for environment variables │ ├── auth/ │ │ └── token_handler.py # extract_user_token() helper │ ├── client/ │ │ └── api_client.py # HTTPX async client with retry logic │ ├── tools/ │ │ ├── auth.py # login, logout, whoami │ │ ├── entities.py # Entity CRUD operations │ │ ├── invoices.py # Invoice management & import │ │ ├── vendors.py # Vendor management │ │ └── products.py # Product search & matching │ └── utils/ │ ├── validators.py # Input validation (UUIDs, phone, pagination) │ └── formatters.py # Response formatting utilities ├── tests/ │ ├── test_auth.py │ ├── test_entities.py │ └── fixtures/mock_responses.json └── docs/ ├── API_MAPPING.md # B4B API endpoint → MCP tool mapping └── DEVELOPMENT.md # Implementation guide ``` ## B4B API Key Characteristics - **Token Lifetime**: 120 minutes (requires refresh logic) - **Pagination**: Use `page` and `per_page` (max 100) - **Status Codes**: Invoice status is INTEGER (0=DRAFT, 1=ACTIVE, 2=CANCELLED, 3=ARCHIVED) - **Date Filters**: ISO format YYYY-MM-DD for `date_from`/`date_to` - **Entity Context**: Most endpoints require `entity_id` path parameter - **Super Admin Bypass**: Super admins can access all entities without relationship check ## Implementation Phases ### Phase 1 - Foundation (P0) - Configuration management (Pydantic Settings) - HTTP client with retry logic (HTTPX + Tenacity) - Token extraction helper - Authentication tools: `login`, `logout`, `whoami` ### Phase 2 - Core Tools (P0) - Entity management: `list_entities`, `get_entity`, `create_entity`, `update_entity` - Invoice listing: `list_invoices`, `get_invoice`, `get_invoice_statistics` ### Phase 3 - Advanced Features (P1) - Vendor tools: `list_vendors`, `get_vendor` - Product tools: `list_products`, `search_similar_products` - Invoice import: `import_invoice_xml` ### Phase 4 - Production Readiness (P2) - Token auto-refresh before 120-minute expiry - Rate limiting (token bucket algorithm) - Comprehensive logging and metrics - Security audit ## Testing Requirements - Unit tests: Mock HTTPX responses, test token handling - Integration tests: Test 403/404 error handling, authorization flows - Fixtures: Use `tests/fixtures/mock_responses.json` for consistent mock data - Coverage target: 80%+ ## Code Quality Standards - Type hints on all functions - Structured logging with `structlog` (never `print()`) - Input validation on all parameters - Async/await for all I/O operations - Follow FastMCP patterns for tool registration ## Security Checklist - [ ] Never log JWT tokens or passwords - [ ] Validate all UUIDs before passing to API - [ ] Sanitize error messages (no internal paths/IPs) - [ ] Use HTTPS for production B4B API - [ ] Clear session metadata on logout - [ ] Validate pagination parameters (max per_page=100) - [ ] Validate phone number format for login

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hqtrung/finizi-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server