@chinchillaenterprises/mcp-upwork
Version:
Modular Upwork MCP server for job search and proposal management via Upwork API
202 lines (180 loc) • 9.57 kB
text/typescript
import { z } from "zod";
// Job Search & Discovery Schemas
export const SearchJobsArgsSchema = z.object({
query: z.string().optional().describe("Search query for job titles/descriptions"),
category: z.string().optional().describe("Job category filter"),
skills: z.array(z.string()).optional().describe("Required skills"),
budget_min: z.number().optional().describe("Minimum budget"),
budget_max: z.number().optional().describe("Maximum budget"),
hourly_rate_min: z.number().optional().describe("Minimum hourly rate"),
hourly_rate_max: z.number().optional().describe("Maximum hourly rate"),
duration: z.enum(["1-7 days", "1-4 weeks", "1-3 months", "3-6 months", "6+ months"]).optional().describe("Project duration"),
workload: z.enum(["less-than-30", "30-plus"]).optional().describe("Hours per week"),
client_hires: z.number().optional().describe("Minimum client hire rate percentage"),
client_spent: z.number().optional().describe("Minimum client total spent"),
sort: z.enum(["recency", "client_rating", "payment_verified"]).optional().describe("Sort order"),
page: z.number().min(1).default(1).describe("Page number for pagination"),
limit: z.number().min(1).max(100).default(20).describe("Number of results per page")
});
export const GetJobDetailsArgsSchema = z.object({
job_id: z.string().describe("Upwork job ID")
});
// Proposal Management Schemas
export const SubmitProposalArgsSchema = z.object({
job_id: z.string().describe("Upwork job ID to submit proposal for"),
cover_letter: z.string().describe("Cover letter text"),
rate: z.number().optional().describe("Proposed hourly rate or fixed price"),
estimated_duration: z.string().optional().describe("Estimated project duration"),
milestone_description: z.string().optional().describe("Milestone description for fixed-price projects"),
connects_to_use: z.number().min(1).max(10).default(2).describe("Number of connects to spend"),
boost_proposal: z.boolean().default(false).describe("Use boosted proposal for top placement")
});
export const ListProposalsArgsSchema = z.object({
status: z.enum(["active", "submitted", "interviewing", "offered", "hired", "ended", "declined"]).optional().describe("Filter by proposal status"),
page: z.number().min(1).default(1).describe("Page number"),
limit: z.number().min(1).max(100).default(20).describe("Results per page")
});
// Contract Management Schemas
export const ListContractsArgsSchema = z.object({
status: z.enum(["active", "ended", "cancelled"]).optional().describe("Filter by contract status"),
type: z.enum(["hourly", "fixed-price"]).optional().describe("Filter by contract type"),
page: z.number().min(1).default(1).describe("Page number"),
limit: z.number().min(1).max(100).default(20).describe("Results per page")
});
export const GetContractDetailsArgsSchema = z.object({
contract_id: z.string().describe("Contract ID")
});
// Time Tracking Schemas
export const GetWorkDiaryArgsSchema = z.object({
contract_id: z.string().describe("Contract ID"),
date: z.string().describe("Date in YYYY-MM-DD format"),
freelancer_id: z.string().optional().describe("Freelancer ID (for clients)")
});
export const LogTimeArgsSchema = z.object({
contract_id: z.string().describe("Contract ID"),
date: z.string().describe("Date in YYYY-MM-DD format"),
hours: z.number().min(0.01).max(24).describe("Hours worked"),
description: z.string().describe("Work description"),
screenshot_url: z.string().optional().describe("Screenshot URL")
});
// Message & Communication Schemas
export const ListMessagesArgsSchema = z.object({
thread_id: z.string().optional().describe("Filter by conversation thread"),
unread_only: z.boolean().default(false).describe("Show only unread messages"),
page: z.number().min(1).default(1).describe("Page number"),
limit: z.number().min(1).max(100).default(20).describe("Results per page")
});
export const SendMessageArgsSchema = z.object({
recipient_id: z.string().describe("Recipient user ID"),
subject: z.string().describe("Message subject"),
body: z.string().describe("Message body"),
thread_id: z.string().optional().describe("Thread ID for replies")
});
// Earnings & Reports Schemas
export const GetEarningsArgsSchema = z.object({
period: z.enum(["this_week", "last_week", "this_month", "last_month", "this_year", "last_year", "custom"]).describe("Earnings period"),
start_date: z.string().optional().describe("Start date for custom period (YYYY-MM-DD)"),
end_date: z.string().optional().describe("End date for custom period (YYYY-MM-DD)")
});
// Profile Management Schemas
export const GetProfileArgsSchema = z.object({});
export const UpdateProfileArgsSchema = z.object({
title: z.string().optional().describe("Professional title"),
overview: z.string().optional().describe("Profile overview/summary"),
hourly_rate: z.number().optional().describe("Hourly rate"),
skills: z.array(z.string()).optional().describe("Skills list"),
location: z.object({
country: z.string().optional(),
city: z.string().optional(),
timezone: z.string().optional()
}).optional().describe("Location information")
});
// Milestone Schemas
export const CreateMilestoneArgsSchema = z.object({
contract_id: z.string().describe("Contract ID"),
description: z.string().describe("Milestone description"),
amount: z.number().min(5).describe("Milestone amount"),
due_date: z.string().optional().describe("Due date (YYYY-MM-DD)")
});
export const ReleaseMilestoneArgsSchema = z.object({
milestone_id: z.string().describe("Milestone ID"),
rating: z.number().min(1).max(5).describe("Rating (1-5 stars)"),
feedback: z.string().optional().describe("Feedback text")
});
// Connects Management Schemas
export const GetConnectsBalanceArgsSchema = z.object({});
export const PurchaseConnectsArgsSchema = z.object({
quantity: z.number().min(10).max(200).describe("Number of connects to purchase (increments of 10)")
});
// Client Tools Schemas
export const SearchFreelancersArgsSchema = z.object({
query: z.string().optional().describe("Search query"),
skills: z.array(z.string()).optional().describe("Required skills"),
hourly_rate_min: z.number().optional().describe("Minimum hourly rate"),
hourly_rate_max: z.number().optional().describe("Maximum hourly rate"),
job_success_min: z.number().min(0).max(100).optional().describe("Minimum job success score"),
earned_amount_min: z.number().optional().describe("Minimum total earned"),
location: z.string().optional().describe("Location filter"),
english_level: z.enum(["basic", "conversational", "fluent", "native"]).optional().describe("English proficiency level"),
page: z.number().min(1).default(1).describe("Page number"),
limit: z.number().min(1).max(100).default(20).describe("Results per page")
});
export const PostJobArgsSchema = z.object({
title: z.string().describe("Job title"),
description: z.string().describe("Job description"),
category: z.string().describe("Job category"),
skills: z.array(z.string()).describe("Required skills"),
job_type: z.enum(["hourly", "fixed"]).describe("Job type"),
budget: z.number().optional().describe("Fixed price budget"),
hourly_rate_min: z.number().optional().describe("Minimum hourly rate"),
hourly_rate_max: z.number().optional().describe("Maximum hourly rate"),
duration: z.enum(["1-7 days", "1-4 weeks", "1-3 months", "3-6 months", "6+ months"]).describe("Project duration"),
workload: z.enum(["less-than-30", "30-plus"]).describe("Hours per week"),
experience_level: z.enum(["entry", "intermediate", "expert"]).describe("Required experience level")
});
// Type exports
export type SearchJobsArgs = z.infer<typeof SearchJobsArgsSchema>;
export type GetJobDetailsArgs = z.infer<typeof GetJobDetailsArgsSchema>;
export type SubmitProposalArgs = z.infer<typeof SubmitProposalArgsSchema>;
export type ListProposalsArgs = z.infer<typeof ListProposalsArgsSchema>;
export type ListContractsArgs = z.infer<typeof ListContractsArgsSchema>;
export type GetContractDetailsArgs = z.infer<typeof GetContractDetailsArgsSchema>;
export type GetWorkDiaryArgs = z.infer<typeof GetWorkDiaryArgsSchema>;
export type LogTimeArgs = z.infer<typeof LogTimeArgsSchema>;
export type ListMessagesArgs = z.infer<typeof ListMessagesArgsSchema>;
export type SendMessageArgs = z.infer<typeof SendMessageArgsSchema>;
export type GetEarningsArgs = z.infer<typeof GetEarningsArgsSchema>;
export type GetProfileArgs = z.infer<typeof GetProfileArgsSchema>;
export type UpdateProfileArgs = z.infer<typeof UpdateProfileArgsSchema>;
export type CreateMilestoneArgs = z.infer<typeof CreateMilestoneArgsSchema>;
export type ReleaseMilestoneArgs = z.infer<typeof ReleaseMilestoneArgsSchema>;
export type GetConnectsBalanceArgs = z.infer<typeof GetConnectsBalanceArgsSchema>;
export type PurchaseConnectsArgs = z.infer<typeof PurchaseConnectsArgsSchema>;
export type SearchFreelancersArgs = z.infer<typeof SearchFreelancersArgsSchema>;
export type PostJobArgs = z.infer<typeof PostJobArgsSchema>;
// Contract Response Types
export interface UpworkContract {
id: string;
title: string;
status: string;
freelancer_id?: string;
client_id?: string;
start_date: string;
end_date?: string;
budget?: number;
weekly_limit?: number;
total_hours?: number;
total_cost?: number;
}
export interface UpworkWorkDiary {
date: string;
hours: number;
earnings: number;
tasks: Array<{
time_slot: string;
hours: number;
description: string;
screenshot_url?: string;
activity_level: number;
}>;
}