Skip to main content
Glama
baskcart

W3Ship MCP Server

by baskcart

create_order

Convert shopping carts into confirmed orders and initiate fulfillment by providing the cart ID.

Instructions

Convert a Shopping Cart into a confirmed Order (TMF622) and initiate fulfillment.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cartIdYesThe ID of the shopping cart to convert

Implementation Reference

  • The handler for the create_order tool, which validates the cart, creates an order via orderService, handles P2P payments or simulated shipments, and clears the cart.
    case 'create_order': {
        const { orderService } = await import('./orders/service.js');
        const { shipmentService } = await import('./shipment/service.js');
        const cartId = (args?.cartId as string) || CONFIGURED_KEY;
        if (!cartId) {
            return { content: [{ type: 'text', text: 'Error: No cart ID. Set W3SHIP_PUBLIC_KEY or provide a cartId.' }], isError: true };
        }
    
        // 1. Validate Cart
        const cart = await valkeyService.getCart(cartId);
        if (!cart) {
            return { content: [{ type: 'text', text: `Error: Cart not found: ${cartId}` }], isError: true };
        }
        if (!cart.cartItem || cart.cartItem.length === 0) {
            return { content: [{ type: 'text', text: `Error: Cart is empty.` }], isError: true };
        }
    
        // 2. Check if cart contains P2P listing items
        let merchantWallet: string | undefined;
        let totalPrice = 0;
        let isP2P = false;
        const listingIds: string[] = [];
    
        for (const item of cart.cartItem) {
            const offId = item.productOffering?.id || '';
            if (offId.startsWith('LST-')) {
                isP2P = true;
                listingIds.push(offId);
                // Fetch listing to get seller wallet and price
                try {
                    const lstRes = await fetch(`${W3SHIP_API}/api/listing?id=${encodeURIComponent(offId)}`);
                    const lstData = await lstRes.json() as any;
                    if (lstRes.ok && lstData.listing) {
                        merchantWallet = lstData.listing.sellerAddress;
                        totalPrice += lstData.listing.price * (item.quantity?.amount || 1);
                    }
                } catch { /* continue */ }
            }
        }
    
        // 3. Create Order
        const orderId = `ord_${Math.random().toString(36).substring(2, 10)}`;
        const order: any = {
            id: orderId,
            orderDate: new Date().toISOString(),
            state: isP2P ? 'Pending Payment' : 'Confirmed',
            orderItem: cart.cartItem.map(item => ({
                id: item.id,
                quantity: item.quantity?.amount || 1,
                productOffering: item.productOffering,
                state: isP2P ? 'Pending' : 'Allocated'
            })),
            totalPrice,
            relatedParty: [{ id: cart.id, role: 'Customer' }],
        };
    
        // Add payment fields for P2P orders
        if (isP2P && merchantWallet) {
            order.merchantWallet = merchantWallet;
            order.paymentStatus = 'awaiting_payment';
            order.paymentToken = 'USDC';
            order.paymentChainId = 8453; // Base
            order.paymentAmount = totalPrice;
        }
    
        await orderService.createOrder(order);
    
        // 4. Mark listings as sold
        for (const lstId of listingIds) {
            try {
                await fetch(`${W3SHIP_API}/api/listing`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ id: lstId, status: 'sold' }),
                });
            } catch { /* best effort */ }
        }
    
        // 5. For non-P2P (demo), create simulated shipment. For P2P, seller adds tracking later.
        let shipmentInfo: any = null;
        if (!isP2P) {
            const shipmentId = `shp_${Math.random().toString(36).substring(2, 10)}`;
            const shipment = {
                id: shipmentId,
                orderId: orderId,
                trackingNumber: `TRK-${Math.random().toString(10).substring(2, 12)}`,
                carrier: 'QuantumLogistics',
                status: 'Label Created',
                origin: { address: 'Distribution Center 1', city: 'Satoshi City', country: 'Digital Nation' },
                destination: { address: 'Customer Address', city: 'Unknown', country: 'Unknown' },
                events: [{ timestamp: new Date().toISOString(), status: 'Label Created', description: 'Shipment info received' }]
            };
            await shipmentService.createShipment(shipment as any);
            shipmentInfo = { shipmentId, trackingNumber: shipment.trackingNumber };
        }
    
        // 6. Clear Cart
        await valkeyService.deleteCart(cartId);
    
        // 7. Return appropriate response
        if (isP2P) {
            return {
                content: [{
                    type: 'text', text: JSON.stringify({
                        success: true,
                        message: `Order created! Send ${totalPrice} USDC to ${merchantWallet} on Base chain, then use confirm_payment with the transaction hash.`,
                        orderId,
                        paymentStatus: 'awaiting_payment',
                        payTo: merchantWallet,
                        amount: `${totalPrice} USDC`,
                        chainId: 8453,
                        nextStep: `After paying, call confirm_payment(orderId: "${orderId}", txHash: "0x...")`,
                    }, null, 2)
                }]
            };
        }
    
        return {
            content: [{
                type: 'text', text: JSON.stringify({
                    success: true,
                    message: "Order confirmed and shipment initiated.",
                    orderId,
                    ...shipmentInfo,
                }, null, 2)
            }]
        };
    }
  • The implementation of the createOrder function that persists the order data in the Valkey (Redis) database.
    async createOrder(order: Order): Promise<void> {
        await this.getClient().set(`order:${order.id}`, JSON.stringify(order));
    }
  • src/index.ts:135-144 (registration)
    The registration of the 'create_order' tool in the ListTools request handler.
        name: 'create_order',
        description: 'Convert a Shopping Cart into a confirmed Order (TMF622) and initiate fulfillment.',
        inputSchema: {
            type: 'object',
            properties: {
                cartId: { type: 'string', description: 'The ID of the shopping cart to convert' },
            },
            required: ['cartId'],
        },
    },
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full disclosure burden. It successfully indicates side effects ('initiate fulfillment') and state change ('confirmed Order'), but omits critical mutation details: idempotency behavior, whether the cart is deleted post-conversion, error handling, or payment prerequisites.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence with zero waste. Information is front-loaded with the action ('Convert'), followed by input/output resources, standard reference (TMF622), and side effects ('initiate fulfillment'). Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Adequate for the simple single-parameter schema, but gaps remain given the lack of annotations and output schema. The description omits what the operation returns (order ID? full object?) and the cart lifecycle outcome (persistence vs. deletion), which are important for a state-changing operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, establishing a baseline of 3. The description references 'Shopping Cart' which conceptually aligns with the 'cartId' parameter, but adds no specific syntax, format constraints, or guidance on obtaining the ID beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses specific verbs ('Convert', 'initiate') and clearly identifies the resource transformation (Shopping Cart → confirmed Order). It distinguishes effectively from siblings like 'create_cart' (creates empty carts) and 'get_order' (retrieves orders) by specifying this converts existing carts into confirmed orders.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies prerequisites by referencing 'Shopping Cart,' suggesting a cart must exist first, but lacks explicit workflow guidance. It does not clarify the sequence relative to siblings like 'confirm_payment' or 'add_item,' nor does it state when NOT to use it (e.g., empty carts, unpaid carts).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/baskcart/w3ship-mcp-server'

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