@chinchillaenterprises/mcp-upwork
Version:
Modular Upwork MCP server for job search and proposal management via Upwork API
68 lines (60 loc) • 3.16 kB
text/typescript
import { Tool } from "@modelcontextprotocol/sdk/types.js";
import { SearchFreelancersArgsSchema } from "../../schemas/upwork.js";
import { UpworkClient } from "../../services/upwork-client.js";
export const searchFreelancersToolDefinition: Tool = {
name: "upwork_search_freelancers",
description: "Search for freelancers (client feature)",
inputSchema: {
type: "object",
properties: {
query: { type: "string", description: "Search query" },
skills: { type: "array", items: { type: "string" }, description: "Required skills" },
hourly_rate_min: { type: "number", description: "Minimum hourly rate" },
hourly_rate_max: { type: "number", description: "Maximum hourly rate" },
job_success_min: { type: "number", minimum: 0, maximum: 100, description: "Minimum job success score" },
earned_amount_min: { type: "number", description: "Minimum total earned" },
location: { type: "string", description: "Location filter" },
english_level: { type: "string", enum: ["basic", "conversational", "fluent", "native"], description: "English proficiency level" },
page: { type: "number", minimum: 1, default: 1, description: "Page number" },
limit: { type: "number", minimum: 1, maximum: 100, default: 20, description: "Results per page" }
}
}
};
export async function searchFreelancersHandler(args: unknown, upworkClient: UpworkClient) {
const validatedArgs = SearchFreelancersArgsSchema.parse(args);
try {
const params = new URLSearchParams();
if (validatedArgs.query) params.append('q', validatedArgs.query);
if (validatedArgs.skills?.length) params.append('skills', validatedArgs.skills.join(';'));
if (validatedArgs.hourly_rate_min) params.append('hourly_rate_min', validatedArgs.hourly_rate_min.toString());
if (validatedArgs.hourly_rate_max) params.append('hourly_rate_max', validatedArgs.hourly_rate_max.toString());
if (validatedArgs.job_success_min) params.append('job_success_min', validatedArgs.job_success_min.toString());
if (validatedArgs.earned_amount_min) params.append('earned_amount_min', validatedArgs.earned_amount_min.toString());
if (validatedArgs.location) params.append('location', validatedArgs.location);
if (validatedArgs.english_level) params.append('english_level', validatedArgs.english_level);
params.append('page', validatedArgs.page.toString());
params.append('count', validatedArgs.limit.toString());
const response = await upworkClient.getClient().get(`/profiles/v1/search/providers?${params.toString()}`);
return {
content: [
{
type: "text",
text: JSON.stringify({
success: true,
freelancers: response.data.providers || [],
total: response.data.total || 0,
page: validatedArgs.page,
limit: validatedArgs.limit
}, null, 2)
}
]
};
} catch (error) {
throw upworkClient.handleError(error);
}
}
export const searchFreelancersTool = {
definition: searchFreelancersToolDefinition,
handler: searchFreelancersHandler,
schema: SearchFreelancersArgsSchema
};