UNPKG

@chinchillaenterprises/mcp-upwork

Version:

Modular Upwork MCP server for job search and proposal management via Upwork API

110 lines (97 loc) 3.22 kB
import axios, { AxiosInstance, AxiosError } from "axios"; import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"; export class UpworkClient { private static instance: UpworkClient; private client: AxiosInstance; private apiKey: string; private apiSecret: string; private accessToken: string; constructor() { // Get credentials from environment variables this.apiKey = process.env.UPWORK_API_KEY || ""; this.apiSecret = process.env.UPWORK_API_SECRET || ""; this.accessToken = process.env.UPWORK_ACCESS_TOKEN || ""; if (!this.apiKey || !this.apiSecret) { throw new Error("UPWORK_API_KEY and UPWORK_API_SECRET environment variables are required"); } // Initialize Upwork API client this.client = axios.create({ baseURL: "https://www.upwork.com/api", timeout: 30000, headers: { "Authorization": `Bearer ${this.accessToken}`, "Content-Type": "application/json", "User-Agent": "ChillMCP-Upwork/1.0.0" }, }); } public getClient(): AxiosInstance { return this.client; } public static getInstance(): UpworkClient { if (!UpworkClient.instance) { UpworkClient.instance = new UpworkClient(); } return UpworkClient.instance; } public async get(endpoint: string, params?: any): Promise<any> { try { const response = await this.client.get(endpoint, { params }); return response.data; } catch (error) { throw this.handleError(error); } } public async post(endpoint: string, data?: any): Promise<any> { try { const response = await this.client.post(endpoint, data); return response.data; } catch (error) { throw this.handleError(error); } } public handleError(error: any): McpError { if (axios.isAxiosError(error)) { const axiosError = error as AxiosError; if (axiosError.response) { const status = axiosError.response.status; const data = axiosError.response.data as any; switch (status) { case 401: return new McpError( ErrorCode.InvalidRequest, "Authentication failed. Please check your API credentials." ); case 403: return new McpError( ErrorCode.InvalidRequest, "Access forbidden. Please check your API permissions." ); case 404: return new McpError( ErrorCode.InvalidRequest, "Resource not found." ); case 429: return new McpError( ErrorCode.InvalidRequest, "Rate limit exceeded. Please try again later." ); default: return new McpError( ErrorCode.InternalError, `Upwork API error: ${data?.message || axiosError.message}` ); } } return new McpError( ErrorCode.InternalError, `Network error: ${axiosError.message}` ); } return new McpError( ErrorCode.InternalError, `Unexpected error: ${error instanceof Error ? error.message : String(error)}` ); } }