The Harvest MCP connector routes your AI agent's tool calls to Harvest's own MCP server through Scalekit. Each user signs in to Harvest once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 37 tools.
- Tools
- 37
- What they doRead · write · destructive
- 16 · 18 · 316 read18 write3 destructive
- Users sign in with
- OAuth
- OAuth app
- Scalekit's or your own
Setup
Install the SDK
Terminal window npm install @scalekit-sdk/node dotenvTerminal window pip install scalekit-sdk-python python-dotenvSet your credentials
Add your Scalekit credentials to your
.envfile. Find values in app.scalekit.com > Developers > API Credentials..env SCALEKIT_ENVIRONMENT_URL=<your-environment-url>SCALEKIT_CLIENT_ID=<your-client-id>SCALEKIT_CLIENT_SECRET=<your-client-secret>Create the Harvest MCP connection
In AgentKit > Connections, create a Harvest MCP connection. The name you give it is the
connection_nameyour code passes. See Configure connections.Scalekit credentials are available for Harvest MCP server, so you don't need to register an OAuth app.
Authorize a user and make your first call
quickstart.mts import { ScalekitClient } from '@scalekit-sdk/node'import 'dotenv/config'import { createInterface } from 'node:readline/promises'const scalekit = new ScalekitClient(process.env.SCALEKIT_ENVIRONMENT_URL,process.env.SCALEKIT_CLIENT_ID,process.env.SCALEKIT_CLIENT_SECRET,)const actions = scalekit.actionsconst connector = 'harvestmcp'const identifier = 'user_123'// Generate an authorization link for the userconst { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })console.log('Authorize Harvest MCP:', link)const rl = createInterface({ input: process.stdin, output: process.stdout })await rl.question('Press Enter after authorizing...')rl.close()// Make your first callconst result = await actions.executeTool({connector,identifier,toolName: 'harvestmcp_get_account_settings',toolInput: {},})console.log(result)Terminal window npx tsx quickstart.mtsquickstart.py import osfrom scalekit import ScalekitClientfrom dotenv import load_dotenvload_dotenv()scalekit_client = ScalekitClient(env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),client_id=os.getenv("SCALEKIT_CLIENT_ID"),client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),)actions = scalekit_client.actionsconnection_name = "harvestmcp"identifier = "user_123"# Generate an authorization link for the userlink_response = actions.get_authorization_link(connection_name=connection_name,identifier=identifier,)print("Authorize Harvest MCP:", link_response.link)input("Press Enter after authorizing...")# Make your first callresult = actions.execute_tool(tool_input={},tool_name="harvestmcp_get_account_settings",connection_name=connection_name,identifier=identifier,)print(result)Terminal window python quickstart.pyEach user signs in once. See Authorize a user for the full flow and statuses.
Tools
Pass the exact name toexecute_toolharvestmcp_get_account_settingsReturn account-level settings: company name, plan, timezone, week start day, hour rounding configuration, and other preferences.Read-onlyGetAccountSettings
Return account-level settings: company name, plan, timezone, week start day, hour rounding configuration, and other preferences.
Inputs
This tool takes no inputs.
harvestmcp_get_expenseReturn a single expense by id, including category, project, and receipt info.Read-onlyGetExpense
Return a single expense by id, including category, project, and receipt info.
Inputs
idintegerrequired- Expense id.
harvestmcp_get_invoiceReturn a single invoice with its header and full line_items.Read-onlyGetInvoice
Return a single invoice with its header and full line_items. Use list_invoices first to find the id.
Inputs
idintegerrequired- Invoice id.
harvestmcp_get_project_budgetReturn the budget status for a project: total budget, hours/amount spent, and remaining.Read-onlyGetProjectBudget
Return the budget status for a project: total budget, hours/amount spent, and remaining. project_id is required.
Inputs
project_idintegerrequired- Project id.
harvestmcp_get_running_timerReturn the currently running timer for the authenticated user, or null if no timer is running.Read-onlyGetRunningTimer
Return the currently running timer for the authenticated user, or null if no timer is running.
Inputs
user_idinteger- Positive integer id of a user whose running timer to check. Requires manager/admin permission for that user; defaults to the authenticated user.
harvestmcp_get_time_reportAggregate time entries over a date range, grouped by project, client, or user.Read-onlyGetTimeReport
Aggregate time entries over a date range, grouped by project, client, or user. Returns billable/non-billable hours, invoiced/uninvoiced hours per group. from and to are required.
Inputs
fromstringrequired- Inclusive start date (YYYY-MM-DD, e.g. 2026-06-01).
tostringrequired- Inclusive end date (YYYY-MM-DD, e.g. 2026-06-30).
group_bystring- Grouping dimension. Defaults to project.one of
projectclientuser include_zero_hour_usersboolean- Only with group_by=user. When true, also returns zero-hour rows for visible team members who logged nothing.
harvestmcp_list_clientsList clients in the user's Harvest account, ordered by name.Read-onlyListClients
List clients in the user's Harvest account, ordered by name. Returns up to 100 clients per page; `total_count` is how many clients match the filter in full, so when `truncated` is true you can tell how many are missing — refine `search` or `is_active` to narrow the result.
Inputs
is_activeboolean- Filter to active (true) or archived (false) clients. Omit for all.
searchstring- Case-insensitive prefix match on client name.
harvestmcp_list_expense_categoriesList expense categories in the account, ordered by name.Read-onlyListExpenseCategories
List expense categories in the account, ordered by name. Used to look up expense_category_id before creating an expense.
Inputs
is_activeboolean- Filter to active (true) or archived (false) categories. Omit for active categories only — pass false explicitly to see archived ones.
harvestmcp_list_expensesList expenses, most recent first.Read-onlyListExpenses
List expenses, most recent first. Filter by project_id, user_id, date range, or billable status.
Inputs
billableboolean- Filter to billable (true) or non-billable (false) expenses. Omit to include both.
cursorstring- Opaque pagination token. Omit on the first request; on later pages pass back the exact `next_cursor` string from the prior response. Never construct or send an empty cursor.
fromstring- Earliest spent-on date, inclusive (YYYY-MM-DD).
limitinteger- Page size, whole number 1–500. Omit to use the default of 100.
project_idinteger- Filter to expenses on this project id. Omit to include all projects.
tostring- Latest spent-on date, inclusive (YYYY-MM-DD).
user_idinteger- Filter to expenses for this user id. Omit to include everyone you're allowed to see. Reading other users requires manager/admin permissions.
harvestmcp_list_invoicesList invoices, most recent first.Read-onlyListInvoices
List invoices, most recent first. Filter by status (draft/open/sent/paid/late), client_id, issue-date range, due_date, or search term. Paginate via cursor.
Inputs
client_idinteger- Filter to invoices for this client id.
cursorstring- Opaque pagination token. Omit on the first request; on later pages pass back the exact `next_cursor` string from the prior response. Never construct or send an empty cursor.
due_datestring- Filter to invoices due on this exact date (YYYY-MM-DD).
issued_fromstring- Earliest issue date, inclusive (YYYY-MM-DD).
issued_tostring- Latest issue date, inclusive (YYYY-MM-DD).
limitinteger- Page size, whole number 1–500. Omit to use the default of 100.
searchstring- Case-insensitive match on invoice number, subject, or PO number.
statusstring- Filter to a single invoice status: draft, approved (a draft the company approved internally but has not sent — only for companies using invoice approval, where such drafts are excluded from `draft`), open, sent (open, not past due), paid, or late (open, past due).one of
draftapprovedopensentpaidlate
harvestmcp_list_project_assignmentsList users assigned to a project, with their roles and billing rates.Read-onlyListProjectAssignments
List users assigned to a project, with their roles and billing rates. project_id is required.
Inputs
project_idintegerrequired- Positive integer id of the project (from list_projects).
assignment_typestring- Which roster to return: `users` (default) or `tasks`.one of
userstasks cursorstring- Opaque pagination token. Omit on the first request; on later pages pass back the exact `next_cursor` string from the prior response. Never construct or send an empty cursor.
limitinteger- Page size, whole number 1–500. Omit to use the default of 100.
harvestmcp_list_projectsList projects in the user's Harvest account, ordered by client name then project name.Read-onlyListProjects
List projects in the user's Harvest account, ordered by client name then project name. Returns up to 100 projects per page; refine `search`, `client_ids`, or `is_active` to narrow the result.
Inputs
client_idsarray- Filter to projects belonging to any of these client ids.
cursorstring- Opaque pagination token. Omit on the first request; on later pages pass back the exact `next_cursor` string from the prior response. Never construct or send an empty cursor.
is_activeboolean- Filter to active (true) or archived (false) projects. Omit for all.
limitinteger- Projects per page. Defaults to 100.
searchstring- Case-insensitive substring match on project name, code, or client name; ignores punctuation and spacing.
harvestmcp_list_tasksList tasks in the user's Harvest account, ordered by name.Read-onlyListTasks
List tasks in the user's Harvest account, ordered by name. Returns up to 100 tasks per page; refine `search` or `is_active` to narrow the result.
Inputs
is_activeboolean- Filter to active (true) or deactivated (false) tasks. Omit for active tasks only — pass false explicitly to see deactivated ones.
searchstring- Case-insensitive prefix match on task name.
harvestmcp_list_time_entriesList time entries, most recent first.Read-onlyListTimeEntries
List time entries, most recent first. Defaults to the last 30 days when `from`/`to` are omitted. `hours` is the raw tracked duration. `billable` = can be billed; `is_invoiced` = has been invoiced. Paginate via `cursor`/`next_cursor`.
Inputs
cursorstring- Opaque pagination token. Omit on the first request; on later pages pass back the exact `next_cursor` string from the prior response. Never construct or send an empty cursor.
fromstring- Inclusive start date (YYYY-MM-DD, e.g. 2026-06-01).
is_invoicedboolean- Filter by invoiced status. true returns only invoiced entries (on an invoice), false only uninvoiced entries. Omit to include both.
limitinteger- Page size, whole number 1–500. Omit to use the default of 100.
project_idinteger- Deprecated single-id alias of `project_ids`; prefer `project_ids`. Folded into `project_ids` when both are given.
project_idsarray- Positive integer project ids to filter to. Omit to include all projects.
tostring- Inclusive end date (YYYY-MM-DD, e.g. 2026-06-01).
user_idinteger- Deprecated single-id alias of `user_ids`; prefer `user_ids`. Folded into `user_ids` when both are given.
user_idsarray- Positive integer user ids to filter to. Omit to include everyone you're allowed to see.
harvestmcp_list_usersList team members in the user's Harvest account, ordered by id.Read-onlyListUsers
List team members in the user's Harvest account, ordered by id. Returns up to 100 users per page; refine `search` or `is_active` to narrow the result. Field availability follows the caller's role.
Inputs
cursorstring- Opaque pagination token. Omit on the first request; on later pages pass back the exact next_cursor from the prior response.
is_activeboolean- Filter to active (true) or deactivated (false) users. Omit for all.
searchstring- Case-insensitive prefix match on user name or email.
harvestmcp_search_help_centerSearch the Harvest Help Center for product documentation: how a feature works, setup steps, integrations, billing, permissions, and troubleshooting.Read-onlySearch Help Center
Search the Harvest Help Center for product documentation: how a feature works, setup steps, integrations, billing, permissions, and troubleshooting. Returns article excerpts with the article title, the section heading, and the canonical Help Center URL to cite back to the user. Relevance-ranked semantic search, so wording matters and there is no relevance floor: a response always carries up to `top_k` excerpts even when none are related, and `relevance_score` only orders them within that one response — read the excerpts, and rephrase and search again before concluding a topic is not documented. Documentation only: it never reads the account's own data, so answer questions about the caller's clients, projects, time, or invoices with the tools that read those instead. When `available` is false nothing is indexed and no search ran — say so and point the user at help.getharvest.com rather than retrying.
Inputs
querystringrequired- Natural-language question or focused keywords to search the Help Center.
top_kinteger- Maximum number of article excerpts to return. Defaults to 5.
harvestmcp_add_task_to_projectAdd an existing task to a project.WriteAddTaskToProject
Add an existing task to a project. project_id and task_id are required.
Inputs
project_idintegerrequired- Project to add the task to.
task_idintegerrequired- Task to add.
harvestmcp_assign_user_to_projectAssign a user to a project.WriteAssignUserToProject
Assign a user to a project. project_id and user_id are required.
Inputs
project_idintegerrequired- Project to assign the user to.
user_idintegerrequired- User to assign.
harvestmcp_create_clientCreate a new client.WriteCreateClient
Create a new client. name is required.
Inputs
namestringrequired- Client name.
addressstring- Client mailing address.
currency_codestring- ISO 4217 currency code (e.g. USD).
harvestmcp_create_expenseLog a new expense.WriteCreateExpense
Log a new expense. project_id and expense_category_id are required. Provide total_cost for amount-based categories, or units for unit-based categories.
Inputs
expense_category_idintegerrequired- Expense category id (from list_expense_categories).
project_idintegerrequired- Project id the expense belongs to.
billableboolean- Whether the expense is billable to the client. Defaults to true.
notesstring- Optional notes.
spent_atstring- Date the expense was incurred (YYYY-MM-DD). Defaults to today in the user's timezone.
total_costnumber- Total cost as a decimal. Use for amount-based categories.
unitsnumber- Number of units. Use for unit-based categories; cost is computed from the category's unit price.
user_idinteger- Create on behalf of another user. Requires manager/admin permissions; defaults to the authenticated user.
harvestmcp_create_invoiceCreate a free-form draft invoice for a client.WriteCreateInvoice
Create a free-form draft invoice for a client. client_id is required; supply line_items for the invoice content. Invoice number is assigned automatically; invoice is created as draft.
Inputs
client_idintegerrequired- Client id the invoice is for (required).
currencystring- ISO 4217 currency code (e.g. USD, EUR). Defaults to the client or company currency.
discountnumber- Optional discount as a percentage.
due_datestring- Due date (YYYY-MM-DD). Takes precedence over payment_term when both are given.
issue_datestring- Issue date (YYYY-MM-DD). Defaults to today in the company timezone.
line_itemsarray- Invoice line items.
notesstring- Optional notes shown on the invoice.
payment_optionsarray- Online payment methods to accept. Defaults to the company's default accepted methods.
payment_termstring- Payment term (e.g. "net 30", "upon receipt"); ignored when due_date is given.
purchase_orderstring- Optional purchase order reference.
subjectstring- Optional invoice subject line.
taxnumber- Optional first tax rate as a percentage.
tax2number- Optional second tax rate as a percentage.
harvestmcp_create_invoice_from_tracked_timeCreate a draft invoice for a client by importing uninvoiced billable tracked time and/or expenses.WriteCreateInvoiceFromTrackedTime
Create a draft invoice for a client by importing uninvoiced billable tracked time and/or expenses. client_id and project_ids are required, plus at least one of `time` or `expenses`.
Inputs
client_idintegerrequired- Client id the invoice is for (required).
project_idsarrayrequired- Billable project ids (for this client) to import activity from (required).
currencystring- ISO 4217 currency code (e.g. USD, EUR). Defaults to the client or company currency.
discountnumber- Optional discount as a percentage.
due_datestring- Due date (YYYY-MM-DD). Takes precedence over payment_term when both are given.
expensesobject- Import expenses. Omit from/to to pull all uninvoiced billable expenses.
issue_datestring- Issue date (YYYY-MM-DD). Defaults to today in the company timezone.
notesstring- Optional notes shown on the invoice.
payment_optionsarray- Online payment methods to accept. Defaults to the company's default accepted methods.
payment_termstring- Payment term (e.g. "net 30", "upon receipt"); ignored when due_date is given.
purchase_orderstring- Optional purchase order reference.
subjectstring- Optional invoice subject line.
taxnumber- Optional first tax rate as a percentage.
tax2number- Optional second tax rate as a percentage.
timeobject- Import tracked time. Omit from/to to pull all uninvoiced billable time.
harvestmcp_create_projectCreate a new project.WriteCreateProject
Create a new project. client_id and name are required.
Inputs
client_idintegerrequired- Id of the client this project belongs to (from list_clients).
namestringrequired- Project name (required).
bill_bystring- How the project bills (Tasks, People, Project, none). Requires billable-rate permission. Defaults to "Project" when hourly_rate is set, otherwise "none" (the project bills at no level).one of
TasksPeopleProjectnone codestring- Optional project code.
currencystring- Billing currency as an ISO 4217 code (e.g. "EUR"). Stored as a relabel — amounts are not converted. Omit it, or pass the client's own code, to inherit the client's currency.
hourly_ratenumber- Default hourly rate, billed when bill_by is "Project". Requires billable-rate permission; ignored otherwise.
is_billableboolean- Whether the project is billable. Defaults to the account's project defaults.
is_fixed_feeboolean- Whether the project bills a fixed fee.
harvestmcp_create_taskCreate a new task in the account.WriteCreateTask
Create a new task in the account. name is required.
Inputs
namestringrequired- Task name.
add_to_all_projectsboolean- Also assign this task to every active project. Runs asynchronously.
billable_by_defaultboolean- Whether the task is billable when added to a project. Defaults to true.
default_hourly_ratenumber- Default hourly rate for this task.
is_defaultboolean- If true, this task is automatically added to new projects.
harvestmcp_log_timeLog a completed time entry.WriteLogTime
Log a completed time entry. project_id and task_id are required, plus either hours or a started_time/ended_time pair.
Inputs
project_idintegerrequired- Project id.
task_idintegerrequired- Task id (must be assigned to the project).
ended_timestring- Clock-out time in the same format as started_time (e.g. "11:00am"). Required alongside started_time.
hoursnumber- Hours worked as a decimal. Use at least 0.01 (e.g. 1.5), the smallest stored increment; positive values that would be stored as 0 are rejected. Provide this OR started_time + ended_time, not both.
notesstring- Notes describing the work. Required when `get_account_settings` reports `notes_required` — the entry will not save without them.
spent_atstring- Date the work was performed (YYYY-MM-DD). Defaults to today in the user's timezone.
started_timestring- Clock-in time, e.g. "9:00am" or "14:30". Provide together with ended_time instead of hours. On a decimal-hours account the duration is derived from the interval but no start or end time is stored.
user_idinteger- Log on behalf of another user. Requires manager/admin permission for that user; defaults to the authenticated user.
harvestmcp_start_timerStart a running timer for the authenticated user on a project+task.WriteStartTimer
Start a running timer for the authenticated user on a project+task. project_id and task_id are required. At most one timer can run at a time; starting a new one stops the previous.
Inputs
project_idintegerrequired- Project id.
task_idintegerrequired- Task id (must be assigned to the project).
notesstring- Notes describing the work. Required when `get_account_settings` reports `notes_required` — the entry will not save without them.
user_idinteger- Start the timer on behalf of another user. Requires manager/admin permission for that user; defaults to the authenticated user.
harvestmcp_stop_timerStop the currently running timer for the authenticated user.WriteStopTimer
Stop the currently running timer for the authenticated user. Returns the stopped time entry. No-ops if no timer is running.
- Idempotent
Inputs
time_entry_idinteger- Specific time entry to stop. Optional.
harvestmcp_submit_feedbackSubmit feedback or a support message to Harvest.WriteSubmitFeedback
Submit feedback or a support message to Harvest. feedback is required.
Inputs
feedbackstringrequired- The feedback message, in the user's own words. Up to 2000 characters.
harvestmcp_submit_timesheetSubmit a timesheet period for approval.WriteSubmitTimesheet
Submit a timesheet period for approval. period_start and period_end are required (YYYY-MM-DD).
- Idempotent
Inputs
period_endstringrequired- Last day of the range to submit (YYYY-MM-DD).
period_startstringrequired- First day of the range to submit (YYYY-MM-DD).
user_idinteger- Submit on behalf of another user. Requires manager/admin permissions; defaults to the authenticated user.
harvestmcp_update_clientUpdate an existing client.WriteUpdateClient
Update an existing client. id is required. Only provided fields are changed.
- Idempotent
Inputs
idintegerrequired- Positive integer id of the client to update (from list_clients).
addressstring- New postal address. Pass an empty string to clear it.
currency_codestring- New ISO 4217 currency code (e.g. USD, EUR).
is_activeboolean- Set false to archive the client, true to reactivate an archived one.
namestring- New client name.
harvestmcp_update_expenseUpdate an existing expense.WriteUpdateExpense
Update an existing expense. id is required. Only provided fields are changed.
- Idempotent
Inputs
idintegerrequired- Id of the expense to update.
billableboolean- Whether the expense is billable to the client.
delete_receiptboolean- Remove the attached receipt.
expense_category_idinteger- Move to a different expense category.
notesstring- Replacement notes.
project_idinteger- Move to a different project.
spent_atstring- Move to a different date (YYYY-MM-DD).
total_costnumber- New total cost.
unitsnumber- New number of units.
harvestmcp_update_projectUpdate an existing project.WriteUpdateProject
Update an existing project. id is required. Only provided fields are changed.
- Idempotent
Inputs
idintegerrequired- Positive integer id of the project to update (from list_projects).
bill_bystring- How the project bills (Tasks, People, Project, none).one of
TasksPeopleProjectnone codestring- New project code. A blank or whitespace-only value is ignored (it leaves the existing code unchanged); clearing a code is not supported by this tool.
currencystring- Billing currency as an ISO 4217 code (e.g. "EUR"). Stored as a relabel — amounts are not converted. A blank value is ignored (it leaves the existing currency unchanged); to clear a project's own currency so it inherits the client's again, pass the client's currency code.
hourly_ratenumber- Hourly rate when bill_by is Project. Requires billable-rate permission.
is_activeboolean- Set false to archive the project, true to reactivate an archived one.
namestring- New project name.
project_typestring- Project type.one of
hourlyfixed_feenon_billable
harvestmcp_update_taskUpdate an existing task.WriteUpdateTask
Update an existing task. id is required. Only provided fields are changed.
- Idempotent
Inputs
idintegerrequired- Positive integer id of the task (from list_tasks).
default_hourly_ratenumber- New default billable rate for the task. Retroactively re-prices all existing time entries on this task (no date limit). Ignored unless you have billable-rate permission — see rate_status in the response.
is_activeboolean- Set false to archive the task, true to reactivate an archived one.
namestring- New task name (must be unique in the account).
harvestmcp_update_time_entryUpdate an existing time entry.WriteUpdateTimeEntry
Update an existing time entry. id is required. Only provided fields are changed.
- Idempotent
Inputs
idintegerrequired- Positive integer id of the time entry to update (from list_time_entries).
ended_timestring- New clock-out time in the same format as started_time (e.g. "11:00am"). Required alongside started_time.
hoursnumber- New hours value. Use at least 0.01, the smallest stored increment; the server rejects 0, negative, or positive values that would be stored as 0. Use delete_time_entry to remove an entry. Provide this OR started_time + ended_time, not both.
notesstring- Replacement notes.
project_idinteger- Move to a different project.
spent_atstring- Move to a different date (YYYY-MM-DD).
started_timestring- New clock-in time, e.g. "9:00am" or "14:30". Provide together with ended_time instead of hours. On a decimal-hours account the duration is derived from the interval but no start or end time is stored.
task_idinteger- Move to a different task.
harvestmcp_delete_time_entryPermanently delete a time entry.DestructiveDeleteTimeEntry
Permanently delete a time entry. id is required. This cannot be undone.
Inputs
idintegerrequired- Positive integer id of the time entry to delete (from list_time_entries).
harvestmcp_remove_task_from_projectRemove a task from a project.DestructiveRemoveTaskFromProject
Remove a task from a project. project_id and task_id are required.
Inputs
project_idintegerrequired- Project to remove the task from.
task_idintegerrequired- Task to remove.
harvestmcp_unassign_user_from_projectRemove a user from a project.DestructiveUnassignUserFromProject
Remove a user from a project. project_id and user_id are required.
Inputs
project_idintegerrequired- Project to remove the user from.
user_idintegerrequired- User to unassign.
No tools match.