API_MAPPING.md•12.5 kB
# API Mapping Reference
This document provides comprehensive mapping between MCP tools and B4B API endpoints, including all 15 implemented tools with their complete specifications.
## Overview
The Finizi B4B MCP Server implements 15 tools that map to various B4B API endpoints. All API requests (except login) require JWT authentication via Bearer token in the Authorization header.
## Authentication Flow Diagram
```mermaid
sequenceDiagram
participant User as User/AI Assistant
participant MCP as MCP Server
participant Session as Session Store
participant B4B as B4B API
User->>MCP: login(phone, password)
MCP->>B4B: POST /api/v1/auth/login
B4B-->>MCP: {access_token, refresh_token, user_info}
MCP->>Session: Store tokens in metadata
MCP-->>User: {success: true, user_info}
User->>MCP: Any authenticated request
MCP->>Session: Extract token
MCP->>B4B: Request with Bearer token
B4B-->>MCP: Response data
MCP-->>User: Formatted response
```
## Complete Tool-to-Endpoint Mapping
### Authentication Tools (3)
| MCP Tool | HTTP Method | B4B API Endpoint | Description | Authentication Required |
|----------|-------------|------------------|-------------|------------------------|
| `login` | POST | `/api/v1/auth/login` | Authenticate user with phone and password | No |
| `logout` | N/A | Local session clear | Clear stored tokens from session | No |
| `whoami` | GET | `/api/v1/users/me` | Get current authenticated user info | Yes |
### Entity Management Tools (4)
| MCP Tool | HTTP Method | B4B API Endpoint | Description | Authentication Required |
|----------|-------------|------------------|-------------|------------------------|
| `list_entities` | GET | `/api/v1/entities` | List entities with pagination and search | Yes |
| `get_entity` | GET | `/api/v1/entities/{entity_id}` | Get detailed entity information | Yes |
| `create_entity` | POST | `/api/v1/entities` | Create new business entity | Yes |
| `update_entity` | PUT | `/api/v1/entities/{entity_id}` | Update existing entity | Yes |
### Invoice Management Tools (4)
| MCP Tool | HTTP Method | B4B API Endpoint | Description | Authentication Required |
|----------|-------------|------------------|-------------|------------------------|
| `list_invoices` | GET | `/api/v1/entities/{entity_id}/invoices` | List invoices with filtering | Yes |
| `get_invoice` | GET | `/api/v1/entities/{entity_id}/invoices/{invoice_id}` | Get detailed invoice | Yes |
| `import_invoice_xml` | POST | `/api/v1/entities/{entity_id}/invoices/import/xml` | Import invoice from XML | Yes |
| `get_invoice_statistics` | GET | `/api/v1/entities/{entity_id}/invoices/statistics` | Get invoice analytics | Yes |
### Vendor Management Tools (2)
| MCP Tool | HTTP Method | B4B API Endpoint | Description | Authentication Required |
|----------|-------------|------------------|-------------|------------------------|
| `list_vendors` | GET | `/api/v1/entities/{entity_id}/vendors` | List vendors with search | Yes |
| `get_vendor` | GET | `/api/v1/entities/{entity_id}/vendors/{vendor_id}` | Get vendor details | Yes |
### Product Management Tools (2)
| MCP Tool | HTTP Method | B4B API Endpoint | Description | Authentication Required |
|----------|-------------|------------------|-------------|------------------------|
| `list_products` | GET | `/api/v1/entities/{entity_id}/products` | List products with filtering | Yes |
| `search_similar_products` | POST | `/api/v1/entities/{entity_id}/products/search/similar` | AI-powered similar product search | Yes |
## Detailed Tool Specifications
### Authentication Tools
#### login
```python
async def login(phone: str, password: str, ctx: Context) -> dict
```
**Request Body:**
```json
{
"phone": "+84909495665",
"password": "SecurePass123@"
}
```
**Response:**
```json
{
"success": true,
"message": "Successfully logged in as user@example.com",
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"is_super_admin": false
}
```
#### logout
```python
async def logout(ctx: Context) -> dict
```
**Response:**
```json
{
"success": true,
"message": "Successfully logged out (was: user@example.com)"
}
```
#### whoami
```python
async def whoami(ctx: Context) -> dict
```
**Response:**
```json
{
"success": true,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"phone": "+84909495665",
"is_super_admin": false,
"entities": [...]
}
}
```
### Entity Management Tools
#### list_entities
```python
async def list_entities(
page: int = 1,
per_page: int = 20,
search: Optional[str] = None,
ctx: Context = None
) -> dict
```
**Query Parameters:**
- `page`: Page number (default: 1)
- `per_page`: Items per page, max 100 (default: 20)
- `search`: Search in entity name or tax code
**Response:**
```json
{
"items": [...],
"total": 150,
"page": 1,
"per_page": 20,
"pages": 8
}
```
#### get_entity
```python
async def get_entity(entity_id: str, ctx: Context) -> dict
```
**Path Parameters:**
- `entity_id`: UUID of the entity
**Response:**
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Tech Corp Ltd",
"entity_type": "COMPANY",
"tax_code": "1234567890",
"address": "123 Tech Street",
"city": "San Francisco",
"country": "USA",
"created_at": "2024-01-01T00:00:00Z"
}
```
#### create_entity
```python
async def create_entity(
name: str,
entity_type: str,
tax_code: str,
address: str,
city: str,
country: str,
ctx: Context
) -> dict
```
**Request Body:**
```json
{
"name": "New Tech Corp",
"entity_type": "COMPANY",
"tax_code": "9876543210",
"address": "456 Innovation Ave",
"city": "San Francisco",
"country": "USA"
}
```
#### update_entity
```python
async def update_entity(
entity_id: str,
name: Optional[str] = None,
address: Optional[str] = None,
city: Optional[str] = None,
country: Optional[str] = None,
ctx: Context = None
) -> dict
```
**Request Body:** (partial update supported)
```json
{
"name": "Updated Tech Corp",
"address": "789 New Street"
}
```
### Invoice Management Tools
#### list_invoices
```python
async def list_invoices(
entity_id: str,
page: int = 1,
per_page: int = 20,
date_from: Optional[str] = None,
date_to: Optional[str] = None,
status: Optional[int] = None,
search: Optional[str] = None,
ctx: Context = None
) -> dict
```
**Query Parameters:**
- `entity_id`: UUID of the entity (required)
- `page`: Page number
- `per_page`: Items per page
- `date_from`: Start date (ISO format: YYYY-MM-DD)
- `date_to`: End date (ISO format: YYYY-MM-DD)
- `status`: Invoice status (0=DRAFT, 1=ACTIVE, 2=CANCELLED, 3=ARCHIVED)
- `search`: Search in invoice number or vendor name
#### get_invoice
```python
async def get_invoice(
entity_id: str,
invoice_id: str,
ctx: Context
) -> dict
```
**Path Parameters:**
- `entity_id`: UUID of the entity
- `invoice_id`: UUID of the invoice
#### import_invoice_xml
```python
async def import_invoice_xml(
entity_id: str,
xml_content: str,
ctx: Context = None
) -> dict
```
**Request Body:**
```json
{
"xml_content": "<?xml version='1.0'?><Invoice>...</Invoice>"
}
```
#### get_invoice_statistics
```python
async def get_invoice_statistics(
entity_id: str,
date_from: Optional[str] = None,
date_to: Optional[str] = None,
ctx: Context = None
) -> dict
```
**Response:**
```json
{
"total_count": 150,
"total_amount": 250000.00,
"by_status": {
"DRAFT": 10,
"ACTIVE": 120,
"CANCELLED": 5,
"ARCHIVED": 15
},
"by_month": [...],
"top_vendors": [...]
}
```
### Vendor Management Tools
#### list_vendors
```python
async def list_vendors(
entity_id: str,
page: int = 1,
per_page: int = 20,
search: Optional[str] = None,
ctx: Context = None
) -> dict
```
**Query Parameters:**
- `entity_id`: UUID of the entity
- `page`: Page number
- `per_page`: Items per page
- `search`: Search in vendor name or tax ID
#### get_vendor
```python
async def get_vendor(
entity_id: str,
vendor_id: str,
ctx: Context
) -> dict
```
**Path Parameters:**
- `entity_id`: UUID of the entity
- `vendor_id`: UUID of the vendor
### Product Management Tools
#### list_products
```python
async def list_products(
entity_id: str,
page: int = 1,
per_page: int = 20,
category: Optional[str] = None,
search: Optional[str] = None,
ctx: Context = None
) -> dict
```
**Query Parameters:**
- `entity_id`: UUID of the entity
- `page`: Page number
- `per_page`: Items per page
- `category`: Product category filter
- `search`: Search in product name or description
#### search_similar_products
```python
async def search_similar_products(
entity_id: str,
query: str,
max_results: int = 10,
ctx: Context = None
) -> dict
```
**Request Body:**
```json
{
"query": "15-inch laptop with 16GB RAM",
"max_results": 10
}
```
**Response:**
```json
{
"results": [
{
"product_id": "...",
"name": "Dell XPS 15",
"similarity_score": 0.95,
"price": 1500.00,
"category": "Electronics"
}
]
}
```
## Authorization Model
### Token Types
- **Access Token**: Short-lived JWT for API authentication (expires in 1 hour)
- **Refresh Token**: Long-lived token for obtaining new access tokens (expires in 30 days)
### Permission Levels
1. **Super Admin**: Full access to all entities and operations
2. **Entity Admin**: Full access to assigned entities
3. **Entity User**: Read/write access to assigned entities
4. **Entity Viewer**: Read-only access to assigned entities
### Token Storage
Tokens are stored in MCP session metadata:
```python
ctx.session.metadata = {
"user_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "refresh_token_here",
"user_email": "user@example.com",
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"is_super_admin": false
}
```
## Error Handling Patterns
### HTTP Status Code Mapping
| HTTP Status | MCP Exception | Description |
|-------------|---------------|-------------|
| 400 | MCPValidationError | Invalid request parameters |
| 401 | MCPAuthenticationError | Invalid or expired token |
| 403 | MCPAuthorizationError | Insufficient permissions |
| 404 | MCPNotFoundError | Resource not found |
| 409 | MCPConflictError | Resource conflict (duplicate) |
| 422 | MCPValidationError | Unprocessable entity |
| 429 | MCPRateLimitError | Too many requests |
| 500+ | MCPServerError | Server error |
### Error Response Format
```json
{
"success": false,
"error": "Detailed error message",
"error_code": "ERROR_CODE",
"details": {
"field_errors": {...}
}
}
```
## Response Formats
### Paginated Response
```json
{
"items": [...],
"total": 1000,
"page": 1,
"per_page": 20,
"pages": 50,
"has_next": true,
"has_prev": false
}
```
### Single Resource Response
```json
{
"id": "uuid",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
...resource_fields
}
```
### Operation Result Response
```json
{
"success": true,
"message": "Operation completed successfully",
"data": {...}
}
```
## Rate Limiting
The B4B API implements rate limiting per user:
- **Default**: 100 requests per minute
- **Authenticated**: 1000 requests per minute
- **Super Admin**: 5000 requests per minute
Rate limit headers:
- `X-RateLimit-Limit`: Maximum requests allowed
- `X-RateLimit-Remaining`: Requests remaining
- `X-RateLimit-Reset`: Unix timestamp for limit reset
## Best Practices
1. **Always authenticate first**: Call `login` before any other operations
2. **Handle token expiration**: Implement token refresh logic
3. **Use pagination**: For large datasets, always use pagination parameters
4. **Implement retry logic**: Handle transient failures with exponential backoff
5. **Validate UUIDs**: Ensure all entity/invoice/vendor IDs are valid UUIDs
6. **Log errors**: Capture error responses for debugging
7. **Clean up sessions**: Always call `logout` when done
## API Versioning
The API version is specified in the URL path:
- Current version: `v1`
- Base URL format: `https://api.finizi.com/api/v1/...`
Version compatibility:
- Breaking changes require new major version
- Minor versions add features without breaking existing ones
- Patch versions fix bugs without changing functionality
---
**Last Updated**: October 2024
**API Version**: v1
**MCP Server Version**: 1.0.0