Skip to content

m2avc/harvest-mcp

v0.3.0MIT

Harvest official remote MCP plus one REST stdio server for invoice update/messages/payments and user/assignment billable rates. Never commit tokens.

harvest-mcp

harvest-mcp

Agent Plugin that connects Harvest through:

  1. Harvest’s official remote MCP at https://api.harvestapp.com/mcp (streamable-http) — OAuth, 35 tools.
  2. This plugin’s harvest-rest stdio server (servers/harvest-rest) — Harvest API v2 invoice update/delete, messages, payments, user billable/cost rates, invoice item categories, read-only estimates, and project assignment hourly rates. One stdio REST entrypoint.

This is community packaging by M2 AV Consulting, LLC. It is not an official Harvest Inc listing.

Install

  1. Install this plugin (Marketplace, cursor.directory, or local ~/.cursor/plugins/local/harvest-mcp).

  2. Complete Harvest OAuth when the host prompts you for the official remote MCP. Do not paste personal access tokens into chat or into this repo.

  3. For harvest-rest (invoices + rates), set these environment variables on the host (inherited by the stdio server). Do not put secrets in mcp.json (that file is public package data):

    • HARVEST_ACCESS_TOKEN — Harvest personal access token or OAuth access token
    • HARVEST_ACCOUNT_ID — numeric Harvest account ID
    • HARVEST_USER_AGENT — optional; defaults to m2avc-harvest-mcp/<semver> (mn@m2avc.com) where <semver> is the root package.json version (integration author contact, not the end-user Harvest email). See API v2 headers.
    • DANGEROUS_SEND — leave unset. Only 1 (plus Mike GO) unlocks emailing, event_type=send, or send_thank_you=true
  4. Node.js 22+ (supported LTS) is required to run harvest-rest. Reload / reconnect MCP if tools do not appear.

Manual Cursor mcp.json equivalent (no plugin). Tokens stay in your local host env, not in the file. Launch the tracked dist binary from the workspace root (no build step in this snippet):

{
  "mcpServers": {
    "harvest": {
      "url": "https://api.harvestapp.com/mcp"
    },
    "harvest-rest": {
      "command": "node",
      "args": ["${workspaceFolder}/servers/harvest-rest/dist/index.js"]
    }
  }
}

Plugin mcp.json uses Agent Plugins schema (streamable-http + stdio).

Domain shapes (for agents)

  • TimeEntry = { id, project, task, hours, notes, spent_date, is_running }
  • Project = { id, name, client, code, is_active, billing }
  • Client = { id, name, is_active }
  • Task = { id, name, billable_by_default }
  • Expense = { id, project, category, spent_date, total_cost, notes }
  • Invoice = { id, client, state, line_items, amounts }
  • InvoiceMessage = { id, event_type, recipients, subject, body }
  • InvoicePayment = { id, amount, paid_at, paid_date, notes }
  • BillableRate = { id, amount, start_date, end_date }
  • UserAssignment (harvest-rest PATCH / API v2): { id, project, user, use_default_rates, hourly_rate }
  • Official MCP list_project_assignments uses { uses_default_rate, billable_rate } — same meaning, different field names. Do not send the official shape on update_project_user_assignment.

Official MCP creates drafts. Sending, closing, reopening, updating, deleting, and recording payments are on harvest-rest. Never claim an invoice was sent unless create_invoice_message succeeded.

Skills

SkillWhen
use-harvest-mcpBefore calling Harvest tools; auth, two-server map, invoice send rules, gaps
harvest-timers-and-timeStart/stop timers, log past time, list/edit/delete entries, time reports
harvest-projects-clients-tasksClients, projects, tasks, budgets, team assignments
harvest-expensesExpense categories, list/get/create/update expenses
harvest-invoicesList/get/create drafts (official MCP); update/delete, messages, payments (harvest-rest)
harvest-rates-and-assignmentsUser billable/cost rates + assignment use_default_rates / hourly_rate (harvest-rest)

Official remote MCP tools (35)

Account: get_account_settings, submit_feedback

Timers/time: start_timer, stop_timer, get_running_timer, log_time, list_time_entries, update_time_entry, delete_time_entry, get_time_report

Projects/clients/tasks: list_clients, create_client, update_client, list_projects, create_project, update_project, get_project_budget, list_tasks, create_task, update_task, add_task_to_project, remove_task_from_project

Team: list_users, list_project_assignments, assign_user_to_project, unassign_user_from_project

Expenses: list_expense_categories, list_expenses, get_expense, create_expense, update_expense

Invoices: list_invoices, get_invoice, create_invoice, create_invoice_from_tracked_time

harvest-rest tools (API v2)

ToolHarvest endpoint
update_invoicePATCH /v2/invoices/{INVOICE_ID} (line items: create / update / _destroy)
delete_invoiceDELETE /v2/invoices/{INVOICE_ID}
list_invoice_messagesGET /v2/invoices/{INVOICE_ID}/messages
create_invoice_messagePOST /v2/invoices/{INVOICE_ID}/messages (event_type: send | close | draft | re-open, or omit to email)
preview_invoice_messageGET /v2/invoices/{INVOICE_ID}/messages/new
delete_invoice_messageDELETE /v2/invoices/{INVOICE_ID}/messages/{MESSAGE_ID}
list_invoice_paymentsGET /v2/invoices/{INVOICE_ID}/payments
create_invoice_paymentPOST /v2/invoices/{INVOICE_ID}/payments (notes preserved verbatim)
delete_invoice_paymentDELETE /v2/invoices/{INVOICE_ID}/payments/{PAYMENT_ID}
list_contactsGET /v2/contacts (recipient lookup only)
list_user_billable_ratesGET /v2/users/{USER_ID}/billable_rates
get_user_billable_rateGET /v2/users/{USER_ID}/billable_rates/{BILLABLE_RATE_ID}
create_user_billable_ratePOST /v2/users/{USER_ID}/billable_rates
list_user_cost_ratesGET /v2/users/{USER_ID}/cost_rates
get_user_cost_rateGET /v2/users/{USER_ID}/cost_rates/{COST_RATE_ID}
create_user_cost_ratePOST /v2/users/{USER_ID}/cost_rates
list_invoice_item_categoriesGET /v2/invoice_item_categories
get_invoice_item_categoryGET /v2/invoice_item_categories/{ID}
create_invoice_item_categoryPOST /v2/invoice_item_categories
list_estimatesGET /v2/estimates
get_estimateGET /v2/estimates/{ESTIMATE_ID}
update_project_user_assignmentPATCH /v2/projects/{PROJECT_ID}/user_assignments/{USER_ASSIGNMENT_ID}

Official assign_user_to_project accepts only project_id + user_id. Set rates with update_project_user_assignment (use_default_rates / uses_default_rate + hourly_rate).

See skills/use-harvest-mcp/SKILL.md and servers/harvest-rest/COS-RUNBOOK.md.

What this is / isn’t

IsOfficial Harvest MCP URL + one REST stdio server for documented API v2 invoice, rate, and item-category gaps
Isn’tA Cursor Marketplace “official Harvest” listing by Harvest Inc
Isn’tA full Harvest REST reimplementation (timers, projects, expenses stay on the official MCP)
Isn’tCompany-specific invoicing procedures or private client data

Auth

  • Official remote MCP: OAuth through the MCP host (preferred day-to-day; least privilege is whatever Harvest ID grants that user/app).
  • harvest-rest: PAT or OAuth access token via host env only (HARVEST_ACCESS_TOKEN + HARVEST_ACCOUNT_ID + User-Agent). Prefer a PAT limited to the account you intend to use. Never commit tokens or Account IDs. Never log them.
  • Mike human GO is required before Marketplace publish or a public version tag. See servers/harvest-rest/COS-RUNBOOK.md and .github/PULL_REQUEST_TEMPLATE.md.

Harvest API v2 headers and rate limits

Rules from Overview and Authentication:

Ruleharvest-rest
Authorization: Bearer …HARVEST_ACCESS_TOKEN
Harvest-Account-IdHARVEST_ACCOUNT_ID
User-Agent required (app name + author link or email; missing → 400)Default m2avc-harvest-mcp/<semver> (mn@m2avc.com)<semver> from root package.json. Override HARVEST_USER_AGENT. Never derived from the end customer's Harvest email/company.
GET params in query string; POST/PATCH JSON needs Content-Type: application/jsonEnforced in harvest-client.ts
Errors 400 / 403 / 404 / 422 / 429 / 500HarvestApiError with status + body (errors / message)
General throttle 100 / 15s; Reports 100 / 15min; 429 sends Retry-AfterClient retries short waits; long waits are returned to the tool
Pagination links; default per_page max 2000Passed through; do not invent next-page URLs
Cache when possibleNo silent cache of writes; do not hammer reports

Endpoint coverage vs official MCP: docs/API_V2_GAP_MATRIX.md.

Extending the REST server

Further official-MCP gaps should be added to servers/harvest-rest/ — one stdio entrypoint — not a second server package.

Author

M2 AV Consulting, LLC — support@m2avc.com

License

MIT. Harvest is a trademark of its owner. This community packaging is unaffiliated with Harvest / Forecast.