import { Tool } from "@modelcontextprotocol/sdk/types.js"; import { ListContractsArgsSchema } from "../../schemas/upwork.js"; import { UpworkClient } from "../../services/upwork-client.js"; import { z } from "zod"; export const toolDefinition: Tool = { name: "upwork_list_contracts", description: "List all freelancer contracts with filtering options", inputSchema: { type: "object", properties: { status: { type: "string", enum: ["active", "ended", "cancelled"], description: "Filter contracts by status" }, type: { type: "string", enum: ["hourly", "fixed-price"], description: "Filter by contract type" }, limit: { type: "number", minimum: 1, maximum: 100, default: 20, description: "Maximum number of contracts to return" } } } }; export const handler = async (args: z.infer, upworkClient: UpworkClient) => { try { // Use proper GraphQL vendorContracts query const vendorContractsQuery = ` query vendorContracts($filter: VendorContractSearchFilter!, $paging: ContractPagingInput) { vendorContracts(filter: $filter, paging: $paging) { paging { count offset total } contracts { id title status startDate endDate totalAmount paymentType hourlyRate client { id name country avgPaymentTime } vendor { id name } assignment { id title description jobPosting { id title category subcategory } } earnings { totalAmount totalHours weeklyAmount weeklyHours } } } } `; // Build filter based on parameters const filter: any = {}; const paging: any = { limit: args.limit || 20, offset: 0 }; if (args.status) { filter.status = args.status.toUpperCase(); } if (args.type) { filter.paymentType = args.type === 'hourly' ? 'HOURLY' : 'FIXED_PRICE'; } const variables = { filter, paging }; const response = await upworkClient.graphqlQuery(vendorContractsQuery, variables); if (response.data?.vendorContracts) { const contracts = response.data.vendorContracts.contracts; const pagination = response.data.vendorContracts.paging; return { content: [ { type: "text", text: `📋 **Upwork Contracts**\n\n` + `**Total Contracts**: ${pagination.total || contracts.length}\n` + `**Showing**: ${contracts.length} contracts\n\n` + contracts.map((contract: any, index: number) => `**${index + 1}. ${contract.assignment?.title || contract.title || 'Untitled Contract'}**\n` + `🆔 **ID**: ${contract.id}\n` + `📊 **Status**: ${contract.status || 'Unknown'}\n` + `💰 **Type**: ${contract.paymentType === 'HOURLY' ? 'Hourly' : 'Fixed Price'}\n` + `💵 **Rate/Amount**: ${contract.paymentType === 'HOURLY' ? `$${contract.hourlyRate || 0}/hr` : `$${contract.totalAmount || 0}`}\n` + `🏢 **Client**: ${contract.client?.name || 'Unknown'}\n` + `🌍 **Location**: ${contract.client?.country || 'Unknown'}\n` + `📅 **Started**: ${contract.startDate ? new Date(contract.startDate).toLocaleDateString() : 'Unknown'}\n` + (contract.endDate ? `📅 **Ended**: ${new Date(contract.endDate).toLocaleDateString()}\n` : '') + (contract.earnings ? `💸 **Earned**: $${contract.earnings.totalAmount || 0} (${contract.earnings.totalHours || 0}h)\n` : '' ) + '\n' ).join('') } ] }; } else { throw new Error('No contract data received from GraphQL response'); } } catch (error: any) { return { content: [ { type: "text", text: `❌ Error listing contracts: ${error.message}` } ], isError: true }; } }; export { ListContractsArgsSchema as schema } from "../../schemas/upwork.js";