@chinchillaenterprises/mcp-upwork
Version:
Modular Upwork MCP server for job search and proposal management via Upwork API
60 lines (54 loc) • 2.27 kB
text/typescript
import { Tool } from "@modelcontextprotocol/sdk/types.js";
import { SubmitProposalArgsSchema, SubmitProposalArgs } from "../../schemas/upwork.js";
import { UpworkClient } from "../../services/upwork-client.js";
export const submitProposalToolDefinition: Tool = {
name: "upwork_submit_proposal",
description: "Submit a proposal for a job",
inputSchema: {
type: "object",
properties: {
job_id: { type: "string", description: "Upwork job ID to submit proposal for" },
cover_letter: { type: "string", description: "Cover letter text" },
rate: { type: "number", description: "Proposed hourly rate or fixed price" },
estimated_duration: { type: "string", description: "Estimated project duration" },
milestone_description: { type: "string", description: "Milestone description for fixed-price projects" },
connects_to_use: { type: "number", minimum: 1, maximum: 10, default: 2, description: "Number of connects to spend" },
boost_proposal: { type: "boolean", default: false, description: "Use boosted proposal for top placement" }
},
required: ["job_id", "cover_letter"]
}
};
export async function submitProposalHandler(args: unknown, upworkClient: UpworkClient) {
const validatedArgs = SubmitProposalArgsSchema.parse(args);
try {
const proposalData = {
job_id: validatedArgs.job_id,
cover_letter: validatedArgs.cover_letter,
rate: validatedArgs.rate,
estimated_duration: validatedArgs.estimated_duration,
milestone_description: validatedArgs.milestone_description,
connects_used: validatedArgs.connects_to_use,
boost: validatedArgs.boost_proposal
};
const response = await upworkClient.getClient().post('/profiles/v1/contractors/actions/apply', proposalData);
return {
content: [
{
type: "text",
text: JSON.stringify({
success: true,
proposal: response.data,
message: "Proposal submitted successfully"
}, null, 2)
}
]
};
} catch (error) {
throw upworkClient.handleError(error);
}
}
export const submitProposalTool = {
definition: submitProposalToolDefinition,
handler: submitProposalHandler,
schema: SubmitProposalArgsSchema
};