Skip to content

ideabosque/mcp_rfq_processor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MCP RFQ Processor

Model Context Protocol (MCP) server for processing Request for Quotation (RFQ) operations, providing AI assistants with tools to manage the complete RFQ lifecycle.

Overview

The MCP RFQ Processor connects AI assistants to the ai_rfq_engine GraphQL backend, enabling intelligent automation of:

  • RFQ Request Management: Submit, update, and track customer quotation requests with flexible item management
  • Item & Inventory Search: Find available items and provider inventory with batch tracking
  • Quote Generation: Create and manage detailed quotes with flexible item operations, pricing, and discounts
  • Installment Planning: Set up payment schedules for quotes
  • Document Management: Upload and track RFQ-related files
  • Segment Management: Organize customers and providers into pricing segments

Current Version: 0.1.1 Total MCP Tools: 28 (implemented in mcp_configuration.py)

Current Feature Highlights

  • Status-Aware Workflow Controls
    • Requests, quotes, and installments enforce validated transitions with guard rails
    • Auto-update request status to in_progress when items change
    • Quotes auto-transition to in_progress when items are created
  • Automatic Business Rules
    • Auto-disapprove quotes when a request is marked modified
    • Auto-complete quotes when all installments are paid, then auto-complete the request
    • When one quote is confirmed, competing quotes are disapproved (unless already terminal)
  • Provider Assignment Helpers
    • assign_provider_item_to_request_item and remove_provider_item_from_request_item manage provider links on requests
    • Quote creation pulls assigned provider items to build quote items automatically
  • Pricing Intelligence with Batch Optimization
    • calculate_quote_pricing uses email-based batch loaders to efficiently group request items by provider
    • Single GraphQL query retrieves all price tiers for all items using DataLoader pattern
    • get_item_price_tiers supports batch queries with email + quote_items array
    • get_discount_prompts efficiently loads discount prompts from all hierarchical scopes
  • Workflow Convenience
    • confirm_request_and_create_quotes and confirm_quote_and_create_installments wrap multi-step flows for quicker automation

See DEVELOPMENT_PLAN.md for complete workflow documentation.

Architecture

High-Level Architecture

graph TB
    subgraph Clients
        AI[AI Assistant<br/>Claude, etc.]
        Browser[Browser / Custom Client]
    end

    subgraph MCP_Layer
        MCPServer[MCP RFQ Processor<br/>this package]
        Processors[Layered Processors<br/>Request | Item | Quote | Pricing | Installment]
    end

    subgraph Backend_Layer
        GraphQL[ai_rfq_engine<br/>GraphQL API<br/>AWS Lambda]
        Batch[Batch Loaders<br/>DataLoader Pattern]
    end

    subgraph Data_Layer
        DDB[(DynamoDB<br/>RFQ Tables)]
        S3[(S3<br/>File Storage)]
    end

    AI -->|MCP Protocol| MCPServer
    Browser -->|MCP Protocol| MCPServer
    MCPServer --> Processors
    Processors -->|GraphQL Queries/Mutations| GraphQL
    GraphQL --> Batch
    Batch -->|Optimized Queries| DDB
    GraphQL -->|Store/Retrieve Files| S3
Loading

Component Flow

AI Assistant (Claude, etc.)
    ↓ MCP Protocol (28 Tools)
MCP RFQ Processor (this package)
    ├── Request Processor (8 tools)
    ├── Item Processor (4 tools)
    ├── Quote Processor (5 tools)
    ├── Pricing Processor (3 tools)
    ├── Installment Processor (4 tools)
    ├── File Processor (2 tools)
    └── Segment Processor (1 tool)
    ↓ GraphQL over AWS Lambda
ai_rfq_engine (backend)
    ├── Batch Loaders (v0.1.1)
    ├── Status Managers
    └── Business Rules Engine
    ↓
DynamoDB Tables + S3 Storage

Installation

Prerequisites

  • Python >= 3.8
  • AWS credentials with Lambda execution permissions
  • Access to deployed ai_rfq_engine GraphQL endpoint

Install from Source

cd mcp_rfq_processor
pip install -e .

Install Dependencies

pip install boto3 humps pendulum silvaengine-utility

Configuration

MCP Server Configuration

Add to your MCP settings file (e.g., claude_desktop_config.json):

{
  "mcpServers": {
    "rfq_processor": {
      "command": "python",
      "args": ["-m", "mcp_rfq_processor"],
      "env": {
        "ENDPOINT_ID": "your-endpoint-id",
        "AWS_REGION": "us-east-1",
        "AWS_ACCESS_KEY_ID": "your-access-key",
        "AWS_SECRET_ACCESS_KEY": "your-secret-key"
      }
    }
  }
}

Module Settings

When using as a Python module:

from mcp_rfq_processor import MCPRfqProcessor
import logging

logger = logging.getLogger(__name__)

processor = MCPRfqProcessor(
    logger=logger,
    region_name="us-east-1",
    aws_access_key_id="your-access-key",
    aws_secret_access_key="your-secret-key",
    execute_mode="aws_lambda",  # or "local" for testing
    default_batch_expiration_filter_days=90,  # Default: 90 days (~3 months)
    installment_scheduled_day=15,  # Default: 15th day of month for installment schedules
)

processor.endpoint_id = "your-endpoint-id"

Configuration Options:

Setting Type Default Description
region_name string - AWS region where Lambda functions are deployed
aws_access_key_id string - AWS access key ID
aws_secret_access_key string - AWS secret access key
execute_mode string - Execution mode: aws_lambda or local
default_batch_expiration_filter_days integer 90 Default minimum expiration days for get_provider_item_batches. When no expiration filters are provided, only returns batches expiring this many days or more in the future.
installment_scheduled_day integer 15 Day of month (1-31) for scheduled installment dates in create_installments. If day doesn't exist in a month (e.g., Feb 31), uses last day of that month.

Available MCP Tools

All 28 tools are defined in mcp_configuration.py and exposed by MCPRfqProcessor.

Tool Organization

graph TB
    subgraph Request_Management[Request Management - 8 Tools]
        R1[submit_rfq_request]
        R2[update_rfq_request]
        R3[get_rfq_request]
        R4[search_rfq_requests]
        R5[add_item_to_rfq_request]
        R6[remove_item_from_rfq_request]
        R7[assign_provider_item_to_request_item]
        R8[remove_provider_item_from_request_item]
    end

    subgraph Item_Management[Item & Inventory - 4 Tools]
        I1[search_items]
        I2[get_item]
        I3[get_provider_items]
        I4[get_provider_item_batches]
    end

    subgraph Quote_Management[Quote Management - 5 Tools]
        Q1[create_quote]
        Q2[update_quote]
        Q3[get_quote]
        Q4[search_quotes]
        Q5[update_quote_item]
    end

    subgraph Pricing[Pricing & Discounts - 3 Tools]
        P1[get_item_price_tiers<br/>Batch-Optimized]
        P2[get_discount_prompts<br/>Hierarchical Scopes]
        P3[calculate_quote_pricing<br/>Groups by Provider]
    end

    subgraph Installment[Installment Management - 4 Tools]
        IN1[create_installment]
        IN2[update_installment]
        IN3[create_installments]
        IN4[get_installments]
    end

    subgraph Workflow[Workflow Helpers - 2 Tools]
        W1[confirm_request_and_create_quotes]
        W2[confirm_quote_and_create_installments]
    end

    subgraph Files[File Management - 2 Tools]
        F1[upload_rfq_file]
        F2[get_rfq_files]
    end

    subgraph Segments[Segment Management - 1 Tool]
        S1[get_segment_contacts]
    end

    style Request_Management fill:#e1f5ff
    style Item_Management fill:#fff4e1
    style Quote_Management fill:#e1ffe1
    style Pricing fill:#ffe1f5
    style Installment fill:#f5e1ff
    style Workflow fill:#e1fff4
    style Files fill:#ffe1e1
    style Segments fill:#f5ffe1
Loading

1. Request Management (8 tools)

submit_rfq_request

Submit a new RFQ request from a customer.

Default Status: initial - Request has been created but not yet being worked on.

Input:

{
  "email": "customer@example.com",
  "request_title": "Need 500 units of Product X",
  "request_description": "Detailed requirements...",
  "billing_address": {},
  "shipping_address": {},
  "items": [],
  "notes": "Urgent order",
  "expired_at": "2025-12-31T23:59:59Z",
  "status": "initial"
}

Output:

{
  "request_uuid": "generated-uuid",
  "status": "initial",
  "created_at": "2025-11-05T10:30:00Z",
  "items": []
}

update_rfq_request

Update an existing RFQ request (title, description, addresses, items, status, etc.).

Status Transitions: All status changes are validated according to the request status flow.

Automatic Business Rules:

  • When status changes to modified, all related quotes are automatically set to disapproved
  • When items are modified while in modified status, automatically transitions to in_progress

Input:

{
  "request_uuid": "request-uuid-string",
  "request_title": "Updated title",
  "items": [...],
  "status": "confirmed"
}

Output: Updated request object.

add_item_to_rfq_request

Convenience method to add a single item to an existing request.

Input:

{
  "request_uuid": "request-uuid-string",
  "item": {
    "item_uuid": "item-uuid",
    "quantity": 100
  }
}

Output: Updated request with new item added.

remove_item_from_rfq_request

Convenience method to remove a single item from an existing request.

Input:

{
  "request_uuid": "request-uuid-string",
  "item_uuid": "item-uuid-to-remove"
}

Output: Updated request with item removed.

assign_provider_item_to_request_item

Attach a provider item (and optional batch/quantity) to a request item. Validates that the provider item belongs to the specified provider and updates status to in_progress when needed.

remove_provider_item_from_request_item

Remove provider assignments from a request item. Can target a specific provider item/batch or clear all provider items for the request item.

get_rfq_request

Retrieve details of an existing RFQ request.

Input:

{
  "request_uuid": "request-uuid-string"
}

Output: Complete request object with contact info and associated quotes.

search_rfq_requests

Search and filter RFQ requests.

Input:

{
  "contact_uuid": "optional-contact-uuid",
  "statuses": ["pending", "quoted"],
  "from_expired_at": "2025-01-01T00:00:00Z",
  "to_expired_at": "2025-12-31T23:59:59Z",
  "page_number": 1,
  "limit": 20
}

Output: Paginated list of matching requests.


2. Item & Inventory Management (4 tools)

search_items

Search for available items in the catalog.

Input:

{
  "item_type": "product",
  "item_name": "Widget",
  "uoms": ["EA", "BOX"],
  "page_number": 1,
  "limit": 50
}

Output: List of items with descriptions, types, and UOM options.

get_item

Get detailed information about a specific item.

Input:

{
  "item_uuid": "item-uuid-string"
}

Output: Complete item details including pricing tiers.

get_provider_items

Search provider inventory with batch information merged.

For each provider item, automatically fetches and merges batch information including:

  • batches: Array of batch details with slow_move_item flags and guardrail pricing
  • Each batch includes: batch_no, expired_at, produced_at, slow_move_item, guardrail_price_per_uom

Optional batch filters (applied when fetching batches):

  • expired_at_gt: Filter batches expiring after this date
  • expired_at_lt: Filter batches expiring before this date
  • slow_move_item: Filter for slow-moving inventory (default: false)
  • in_stock: Filter for in-stock batches (default: true)

Input:

{
  "item_uuid": "optional-item-uuid",
  "provider_corp_external_id": "PROVIDER-001",
  "min_base_price_per_uom": 10.00,
  "max_base_price_per_uom": 50.00,
  "expired_at_gt": "2025-11-05T00:00:00Z",
  "slow_move_item": false,
  "in_stock": true,
  "page_number": 1,
  "limit": 50
}

Output: List of provider items with pricing, availability, and merged batch information.

Note: If no expiration filters provided, defaults to batches expiring 90+ days from now.

get_provider_item_batches

Get batch/lot information for provider items including slow_move_item flag and guardrail pricing.

Input:

{
  "provider_item_uuid": "provider-item-uuid",
  "in_stock": true,
  "expired_at_gt": "2025-11-05T00:00:00Z"
}

Output: List of batches with lot numbers, expiry dates, and stock levels.

Note: If neither expired_at_gt nor expired_at_lt is provided, defaults to filtering batches expiring 90+ days from now.


3. Quote Management (5 tools)

create_quote

Generate a new quote for an RFQ request.

Default Status: initial - Quote has been created but not yet being worked on.

Requirements:

  • Request must be in confirmed status to create quotes

Note:

  • shipping_method and shipping_amount cannot be set during creation - use update_quote after creation
  • rounds (negotiation rounds) is auto-calculated by the backend
  • Quote items are created automatically from the provider assignments on the request for the selected provider

Input:

{
  "request_uuid": "request-uuid",
  "provider_corp_external_id": "PROVIDER-001",
  "sales_rep_email": "sales@provider.com",
  "status": "initial",
  "notes": "Initial quote"
}

Output:

{
  "quote_uuid": "generated-quote-uuid",
  "request_uuid": "request-uuid",
  "rounds": 0,
  "total_quote_amount": 0.00,
  "status": "initial"
}

get_quote

Retrieve quote details.

Input:

{
  "request_uuid": "request-uuid",
  "quote_uuid": "quote-uuid"
}

Output: Complete quote with line items, totals, and discount information.

update_quote

Update quote metadata (shipping, status, notes).

Status Transitions: All status changes are validated according to the quote status flow.

Note: rounds (negotiation rounds) is auto-calculated by the backend and cannot be manually set.

Input:

{
  "request_uuid": "request-uuid",
  "quote_uuid": "quote-uuid",
  "shipping_method": "express",
  "shipping_amount": 75.00,
  "status": "confirmed",
  "notes": "Updated pricing and shipping"
}

Output: Updated quote object with auto-calculated rounds.

search_quotes

Search and filter quotes.

Input:

{
  "request_uuid": "optional-request-uuid",
  "provider_corp_external_id": "PROVIDER-001",
  "statuses": ["confirmed", "completed"],
  "min_total_quote_amount": 1000.00,
  "page_number": 1,
  "limit": 20
}

Output: Paginated list of matching quotes.

update_quote_item

Update an existing quote item (discount amount only). Used to apply discounts after quote items are created.

Requirements:

  • Quote must be in in_progress status to apply discounts
  • Only discount modifications are allowed (discount amount adjustments)

Note: Only discount_amount can be updated. Other fields (qty, provider_item_uuid, etc.) are read-only after creation.

Input:

{
  "quote_uuid": "quote-uuid",
  "quote_item_uuid": "quote-item-uuid",
  "discount_amount": 75.00
}

Output: Updated quote item with recalculated totals.


4. Pricing & Discounts (3 tools)

get_item_price_tiers

Get tiered pricing for multiple items using batch loader optimization.

Batch-Optimized Approach: Uses customer email for segment lookup and efficiently loads price tiers for quote items with automatic quantity filtering. Returns only tiers matching each item's quantity range. Preferred for processing multiple items efficiently.

Input:

{
  "email": "customer@example.com",
  "quote_items": [
    {
      "item_uuid": "item-uuid",
      "provider_item_uuid": "provider-item-uuid",
      "qty": 100
    }
  ]
}

Parameters:

  • email: Customer email address for segment lookup (required)
  • quote_items: List of quote items with item_uuid, provider_item_uuid, and qty. Each item will have its applicable price tiers returned based on quantity thresholds.

Output: List of price tiers with provider_item_batches merged.

{
  "item_price_tiers": [
    {
      "item_uuid": "...",
      "provider_item_uuid": "...",
      "quantity_greater_then": 50,
      "quantity_less_then": 200,
      "price_per_uom": 10.5,
      "margin_per_uom": 2.0,
      "provider_item_batches": [
        {
          "batch_no": "LOT-2025-001",
          "price_per_uom": 10.0
        }
      ]
    }
  ]
}

Updated in v0.1.1: Refactored to use batch loaders with email-based segment lookup for better performance.

get_discount_prompts

Get discount prompts for items using batch loader optimization.

Batch-Optimized Approach: Loads prompts from all hierarchical scopes (GLOBAL, SEGMENT, ITEM, PROVIDER_ITEM) and deduplicates. Returns combined discount prompts with conditions and rules. Preferred for processing multiple items efficiently.

Input:

{
  "email": "customer@example.com",
  "quote_items": [
    {
      "item_uuid": "item-uuid",
      "provider_item_uuid": "provider-item-uuid"
    }
  ]
}

Parameters:

  • email: Customer email address for segment lookup (required)
  • quote_items: List of quote items with item_uuid and provider_item_uuid to determine applicable prompts

Output: Combined discount prompts from all hierarchical scopes.

{
  "discount_prompts": [
    {
      "scope": "SEGMENT",
      "prompt": "Apply 5% discount for slow-moving items",
      "conditions": "slow_move_item=true",
      "max_discount_percentage": 5.0
    }
  ]
}

New in v0.1.1: Replaces get_discount_rules with batch-optimized prompt loading across hierarchical scopes.

calculate_quote_pricing

Calculate pricing information for an RFQ request using batch-optimized queries.

Batch-Optimized Approach: Groups items by provider and provides subtotals and price tiers. Uses batch loaders for efficient multi-item processing. Returns pricing structure for decision-making.

Note: This reads from REQUEST (not quote) and groups items by provider_corp_external_id. Use this BEFORE creating quotes (Step 7 in workflow).

Input:

{
  "request_uuid": "request-uuid",
  "email": "customer@example.com"
}

Parameters:

  • request_uuid: UUID of the RFQ request (required)
  • email: Customer email for segment lookup and batch-optimized price tier queries (required)

Output: Grouped pricing structure with items grouped by provider.

{
  "request_uuid": "req-uuid",
  "groups": [
    {
      "provider_corp_external_id": "PROVIDER-001",
      "items": [
        {
          "provider_item_uuid": "prov-item-uuid",
          "item_uuid": "item-uuid",
          "batch_no": "LOT-2025-001",
          "qty": 500,
          "price_per_uom": 9.50,
          "guardrail_price_per_uom": 9.50,
          "slow_move_item": true,
          "expired_at": "2026-03-15T00:00:00Z",
          "subtotal": 4750.00
        }
      ],
      "group_subtotal": 4750.00
    }
  ]
}

Key Features:

  • Uses single batch-optimized GraphQL query for all price tiers
  • Groups items by provider_corp_external_id for multi-provider comparison
  • Includes batch-specific pricing with slow_move_item flags and guardrail pricing
  • Returns pricing structure WITHOUT applying discounts (LLM can use get_discount_prompts separately)

Updated in v0.1.1: Refactored to use email-based batch loaders instead of segment_uuid. Price tiers and discount prompts now fetched separately via dedicated batch-optimized functions.


5. Installment Management (4 tools)

create_installment

Set up a payment installment for a quote.

Requirements:

  • Quote must be in confirmed status to create installments

Workflow:

  • Create installments with status=pending when quote status changes to confirmed
  • Update installment status=paid when payment is received
  • When all installments are paid, quote status is automatically set to completed

Automatic Behavior:

  • Amount: If installment_amount not provided, uses full remaining balance. If provided, uses min(requested_amount, remaining_balance) (auto-caps at remaining balance)
  • Priority: Automatically set to max(existing_priorities) + 1 for sequential ordering (starts at 0 for first installment)
  • Due Date: Automatically sets to current time (no need to specify)
  • installment_ratio: Auto-calculated by backend based on installment_amount / final_total_quote_amount
  • Auto-Capping: Requested amount > remaining balance automatically uses remaining balance instead

Input Options:

Option 1: Full remaining balance (automatic)

{
  "quote_uuid": "quote-uuid",
  "request_uuid": "request-uuid",
  "status": "pending"
}

Option 2: Partial installment (custom amount)

{
  "quote_uuid": "quote-uuid",
  "request_uuid": "request-uuid",
  "installment_amount": 3000.00,
  "status": "pending"
}

Installment Status Values:

  • pending: Payment scheduled but not yet received (default when quote is confirmed)
  • paid: Payment has been received and verified
  • cancelled: Payment was cancelled or refunded

Validation Rules:

  • Without installment_amount: Uses full remaining balance (final_total_quote_amount - existing_pending_paid_total)
  • With installment_amount: Must be > 0. If exceeds remaining balance, automatically capped at remaining balance
  • If remaining balance ≤ 0 (quote fully covered), installment creation is blocked
  • Cancelled installments are not counted in the total
  • Supports multiple partial installments that add up to quote total
  • Auto-capping ensures you can never exceed quote total (safe to request any amount)

Output: Installment record with auto-calculated amount, due_date, and installment_ratio.

update_installment

Update installment status and sales order number.

Status Transitions: All status changes are validated according to the installment status flow.

Automatic Business Rules:

  • When all installments are marked as paid, the quote is automatically set to completed

Use Cases:

  • Mark installment as paid when payment is received
  • Mark installment as cancelled if payment is cancelled or refunded
  • Link installment to a sales order number for tracking

Input:

{
  "quote_uuid": "quote-uuid",
  "installment_uuid": "installment-uuid",
  "status": "paid",
  "salesorder_no": "SO-12345"
}

Common Usage:

// Mark as paid (triggers auto-complete check)
{
  "quote_uuid": "quote-uuid",
  "installment_uuid": "installment-uuid",
  "status": "paid"
}

// Link to sales order
{
  "quote_uuid": "quote-uuid",
  "installment_uuid": "installment-uuid",
  "salesorder_no": "SO-12345"
}

// Both at once
{
  "quote_uuid": "quote-uuid",
  "installment_uuid": "installment-uuid",
  "status": "paid",
  "salesorder_no": "SO-12345"
}

Output: Updated installment record.

create_installments

Create multiple payment installments for a quote based on a payment schedule. Automates the process of setting up installment plans (e.g., monthly payments over a year).

Workflow:

  • Calculates remaining balance (final_total_quote_amount - existing_pending_paid_total)
  • Divides remaining balance equally across interval_num installments
  • Calculates scheduled dates based on interval_num and total_pay_period
  • Creates all installments with status=pending
  • Auto-increments priority for sequential ordering

Automatic Behavior:

  • Amount per installment: remaining_balance / interval_num (equal distribution)
  • Scheduled dates: First installment scheduled for the next payment period (not current period), then subsequent installments follow at regular intervals. All scheduled on the configured day of month (default: 15th) using installment_scheduled_day setting. If the day doesn't exist in a month (e.g., Feb 31), uses the last day of that month. Uses pendulum library for accurate date calculations.
  • Priority: Auto-increments sequentially for each installment
  • Status: All installments created with pending status

Input:

{
  "quote_uuid": "quote-uuid",
  "request_uuid": "request-uuid",
  "interval_num": 12,
  "total_pay_period": 12
}

Examples:

12 monthly payments over 1 year:

{
  "quote_uuid": "quote-uuid",
  "request_uuid": "request-uuid",
  "interval_num": 12,
  "total_pay_period": 12
}
// Creates 12 installments, scheduled monthly (every 1 month)
// First installment: Next month on 15th (or configured day)
// Last installment: 12 months from now on 15th
// Amount per installment: remaining_balance / 12

6 bi-monthly payments over 1 year:

{
  "quote_uuid": "quote-uuid",
  "request_uuid": "request-uuid",
  "interval_num": 6,
  "total_pay_period": 12
}
// Creates 6 installments, scheduled bi-monthly (every 2 months)
// First installment: 2 months from now on 15th
// Last installment: 12 months from now on 15th
// Amount per installment: remaining_balance / 6

4 quarterly payments over 2 years:

{
  "quote_uuid": "quote-uuid",
  "request_uuid": "request-uuid",
  "interval_num": 4,
  "total_pay_period": 24
}
// Creates 4 installments, scheduled every 6 months
// First installment: 6 months from now on 15th
// Last installment: 24 months from now on 15th
// Amount per installment: remaining_balance / 4

Validation Rules:

  • interval_num must be > 0
  • total_pay_period must be > 0
  • Remaining balance must be > 0 (quote not already fully covered)
  • If any installment creation fails, returns error with details of what was created

Output:

{
  "installments": [ /* array of created installment objects */ ],
  "total_created": 12,
  "installment_amount_per": 833.33,
  "total_installment_amount": 10000.00
}

get_installments

Retrieve installments for a quote.

Input:

{
  "quote_uuid": "quote-uuid"
}

Output: List of installments with payment schedule.


6. Workflow Convenience (2 tools)

These helpers combine multiple operations and enforce the same business rules described above.

confirm_request_and_create_quotes

Sets a request to confirmed and creates quotes for a list of providers in one call. Uses provider assignments on the request to generate quote items. Sales rep emails can be supplied via settings (sales_rep_emails mapping).

confirm_quote_and_create_installments

Confirms a quote, disapproves competing quotes for the same request, and creates a single installment or an installment schedule.


7. Document Management (2 tools)

upload_rfq_file

Upload a document related to an RFQ request.

Input:

{
  "request_uuid": "request-uuid",
  "file_name": "specifications.pdf",
  "file_url": "s3://bucket/path/to/file",
  "file_type": "application/pdf",
  "email": "requester@company.com",
  "notes": "Technical specifications"
}

Output: File record with metadata.

get_rfq_files

Retrieve files associated with a request.

Input:

{
  "request_uuid": "request-uuid"
}

Output: List of uploaded files with download URLs.


8. Segment Management (1 tool)

Note: Segments are typically managed through the backend admin interface. This tool provides read-only access to segment-contact associations for pricing lookups.

get_segment_contacts

List contacts in a segment by consumer corporation or email.

Input:

{
  "consumer_corp_external_id": "CUSTOMER-001",
  "email": "buyer@customer.com",
  "page_number": 1,
  "limit": 50
}

Output: List of contacts with their segment associations.


Usage Examples

Complete RFQ to Quote Workflow

For the detailed 14-step workflow from customer inquiry to final quote confirmation, see DEVELOPMENT_PLAN.md - Complete RFQ to Quote Workflow.

Quick Overview: 0. Find Customer Segment

  1. Submit RFQ Request
  2. Lookup Items with End User
  3. Add Items to Request
  4. Lookup Provider Items for Each Item
  5. Lookup Batches for Each Provider Item (Optional)
  6. Assign Provider Items to Request Items
  7. Calculate Quote Pricing (NEW - groups by provider/segment, returns discount rules)
  8. Generate Quotes by Confirmation
  9. Negotiate with End User
  10. Apply Discounts with User Confirmation
  11. Update Quote with Shipping
  12. Confirm Quote and Generate Installment Plan
  13. Complete Quote and Process Payment

Practical Example: End-to-End Quote Generation

# Step 0: Find customer segment
segment_contacts = processor.get_segment_contacts(
    consumer_corp_external_id="CUSTOMER-001",
    email="buyer@customer.com"
)
segment_uuid = segment_contacts[0]["segment_uuid"]

# Step 1-3: Create request and add items
request = processor.submit_rfq_request(
    email="buyer@customer.com",
    request_title="Q1 Production Materials",
    items=[]
)
request_uuid = request["request_uuid"]

processor.add_item_to_rfq_request(
    request_uuid=request_uuid,
    item={"item_uuid": "item-uuid-1", "qty": 500}
)

# Step 4-6: Assign provider items to request
current_request = processor.get_rfq_request(request_uuid=request_uuid)
updated_items = current_request["items"].copy()
updated_items[0]["provider_items"] = [
    {
        "provider_corp_external_id": "PROVIDER-001",
        "provider_item_uuid": "prov-item-uuid-1",
        "batch_no": "LOT-2025-001",
        "qty": 500
    }
]
processor.update_rfq_request(request_uuid=request_uuid, items=updated_items)

# Step 7: Calculate pricing with batch optimization (NEW)
pricing = processor.calculate_quote_pricing(
    request_uuid=request_uuid,
    email="buyer@customer.com"  # Uses email instead of segment_uuid
)
# Returns grouped pricing structure with items by provider
# {
#   "groups": [{
#     "provider_corp_external_id": "PROVIDER-001",
#     "items": [{
#       "provider_item_uuid": "prov-item-uuid-1",
#       "item_uuid": "item-uuid-1",
#       "batch_no": "LOT-2025-001",
#       "qty": 500,
#       "price_per_uom": 9.50,
#       "guardrail_price_per_uom": 9.50,
#       "slow_move_item": true,
#       "expired_at": "2026-03-15T00:00:00Z",
#       "subtotal": 4750.00
#     }],
#     "group_subtotal": 4750.00
#   }]
# }

# Optional: Get discount prompts separately
discount_prompts = processor.get_discount_prompts(
    email="buyer@customer.com",
    quote_items=[{
        "item_uuid": "item-uuid-1",
        "provider_item_uuid": "prov-item-uuid-1"
    }]
)

# Step 8-10: Create quote (quote items are auto-created from provider assignments)
quote = processor.create_quote(
    request_uuid=request_uuid,
    provider_corp_external_id="PROVIDER-001",
    sales_rep_email="sales@provider1.com"
)

# Apply discount to the created quote item
full_quote = processor.get_quote(
    request_uuid=request_uuid,
    quote_uuid=quote["quote_uuid"],
)
first_quote_item_uuid = full_quote["quote_items"][0]["quote_item_uuid"]

processor.update_quote_item(
    quote_uuid=quote["quote_uuid"],
    quote_item_uuid=first_quote_item_uuid,
    request_uuid=request_uuid,
    discount_amount=237.50  # 5% slow-move discount (user confirmed)
)

# Step 11: Add shipping
processor.update_quote(
    request_uuid=request_uuid,
    quote_uuid=quote["quote_uuid"],
    shipping_method="express",
    shipping_amount=75.00
)

# Step 12-13: Create installment plan and submit
# Installment automatically uses quote's final_total_quote_amount
processor.create_installment(
    request_uuid=request_uuid,
    quote_uuid=quote["quote_uuid"],
    status="pending"  # Default status when quote is confirmed
)

processor.update_quote(
    request_uuid=request_uuid,
    quote_uuid=quote["quote_uuid"],
    status="confirmed"
)

Key Principles

  • LLM-Driven: LLM asks user questions at each step
  • Segment-Based: Always identify customer segment first for correct pricing
  • Information Provider: calculate_quote_pricing provides discount rules; LLM makes decisions with user input
  • User Confirmation: Apply discounts only after user confirms
  • Multi-Provider: Create separate quotes per provider for comparison

AI Assistant Conversation Example

User: I need a quote for 500 units of part ABC-123

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages