### Install Harvest MCP Server Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Install the server globally using npm or run it directly using npx. No specific setup is required beyond installation. ```bash # Install globally npm install -g @ianaleck/harvest-mcp-server # Or use without installing via npx npx @ianaleck/harvest-mcp-server ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Clone the repository, navigate to the project directory, and install all necessary npm packages. ```bash git clone https://github.com/ianaleck/harvest-mcp-server.git cd harvest-mcp-server npm install ``` -------------------------------- ### Start Development Server Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Launch the development server for local development and testing. ```bash npm run dev ``` -------------------------------- ### Start Harvest MCP Server with HTTP Transport Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Start the server using HTTP transport by setting environment variables for port and API key. Includes examples for health checks and calling tools over HTTP. ```bash # HTTP transport (e.g., for Docker deployments) MCP_TRANSPORT=http PORT=3000 MCP_API_KEY=secret HARVEST_ACCESS_TOKEN=... HARVEST_ACCOUNT_ID=... npx @ianaleck/harvest-mcp-server # Health check curl http://localhost:3000/health # {"status":"ok","name":"harvest-mcp-server","transport":"http"} # Call a tool over HTTP curl -s -X POST http://localhost:3000/mcp \ -H "Content-Type: application/json" \ -H "x-api-key: secret" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_company", "arguments": {} } }' ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Copy the example environment file and edit it with your Harvest API credentials. ```bash cp .env.example .env # Edit .env with your Harvest API credentials ``` -------------------------------- ### Start Timer - Create Time Entry Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new time entry with a running timer. The timer starts immediately and accumulates hours automatically. Requires project and task IDs, date, and optional notes. ```typescript { "name": "start_timer", "arguments": { "project_id": 98765, "task_id": 8083365, "spent_date": "2024-01-15", "notes": "Working on landing page animations" } } ``` ```typescript { "id": 636800100, "is_running": true, "hours": 0.0, "spent_date": "2024-01-15", "timer_started_at": "2024-01-15T10:00:00Z", "notes": "Working on landing page animations", "project": { "id": 98765, "name": "Website Redesign" }, "task": { "id": 8083365, "name": "Development" } } ``` -------------------------------- ### Install Harvest MCP Server Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Install the Harvest MCP Server globally or locally using npm. Ensure Node.js 18+ is installed. ```bash # Install globally npm install -g @ianaleck/harvest-mcp-server # Or install locally npm install @ianaleck/harvest-mcp-server ``` -------------------------------- ### Get Project Budget Report Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Generates a budget utilization report for projects, identifying over-budget projects or listing all projects for a client. ```typescript // Find all over-budget active projects { "name": "get_project_budget_report", "arguments": { "is_active": true, "over_budget": true } } // All projects for a specific client { "name": "get_project_budget_report", "arguments": { "client_id": 11223 } } // Expected response: { "results": [ { "project_id": 98765, "project_name": "Website Redesign", "client_name": "Acme Corp", "budget_is_monthly": false, "budget": 200.0, "budget_spent": 174.5, "budget_remaining": 25.5 } ] } ``` -------------------------------- ### Get Current User Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves the profile and permissions of the currently authenticated user. This tool requires a valid HARVEST_ACCESS_TOKEN and takes no arguments. ```typescript { "name": "get_current_user", "arguments": {} } // Expected response: { "id": 1782959, "first_name": "Alice", "last_name": "Smith", "email": "alice@acme.com", "is_admin": true, "is_project_manager": true, "can_see_rates": true, "can_create_projects": true, "can_create_invoices": true } ``` -------------------------------- ### Build for Production Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Compile and bundle the project for production deployment. ```bash npm run build ``` -------------------------------- ### start_timer Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new time entry with a running timer for the specified project and task. The timer begins immediately and accumulates hours automatically until stopped. ```APIDOC ## Tool — `start_timer` Creates a new time entry with a running timer for the specified project and task. The timer begins immediately and accumulates hours automatically until stopped. ```typescript { "name": "start_timer", "arguments": { "project_id": 98765, "task_id": 8083365, "spent_date": "2024-01-15", "notes": "Working on landing page animations" } } // Expected response — note is_running: true and timer_started_at populated: { "id": 636800100, "is_running": true, "hours": 0.0, "spent_date": "2024-01-15", "timer_started_at": "2024-01-15T10:00:00Z", "notes": "Working on landing page animations", "project": { "id": 98765, "name": "Website Redesign" }, "task": { "id": 8083365, "name": "Development" } } ``` ``` -------------------------------- ### Run All Tests Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Execute all unit, integration, and contract tests for the project. ```bash npm test ``` -------------------------------- ### Contribute to the Project Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Steps for contributing to the project, including forking, branching, making changes, testing, committing, and creating a pull request. ```bash git checkout -b feature/amazing-feature # ... make changes ... git commit -m 'Add amazing feature' git push origin feature/amazing-feature ``` -------------------------------- ### stop_timer Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Stops a currently running timer, finalizing the hours elapsed. The `id` is the time entry ID returned when the timer was started. ```APIDOC ## Tool — `stop_timer` Stops a currently running timer, finalizing the hours elapsed. The `id` is the time entry ID returned when the timer was started. ```typescript { "name": "stop_timer", "arguments": { "id": 636800100 } } // Expected response — hours now reflects elapsed time: { "id": 636800100, "is_running": false, "hours": 1.75, "spent_date": "2024-01-15" } ``` ``` -------------------------------- ### create_client Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new client. Requires only a `name`; optionally accepts `is_active`, `address`, and a 3-letter ISO `currency` code. ```APIDOC ## Tool — `create_client` ### Description Creates a new client. Requires only a `name`; optionally accepts `is_active`, `address`, and a 3-letter ISO `currency` code. ### Arguments - `name` (string) - Required - The name of the client. - `is_active` (boolean) - Optional - Whether the client is active. - `address` (string) - Optional - The address of the client. - `currency` (string) - Optional - The 3-letter ISO currency code for the client. ### Response Example ```json { "id": 11301, "name": "TechStart Ltd", "is_active": true, "currency": "USD", "created_at": "2024-01-15T09:00:00Z" } ``` ``` -------------------------------- ### Create Project - New Client Project Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new project associated with a client. Requires project name and client ID. Supports detailed configuration for billing, budgets, and notifications. ```typescript { "name": "create_project", "arguments": { "name": "Mobile App v2", "client_id": 11223, "code": "MA-2024", "is_active": true, "is_billable": true, "bill_by": "Tasks", "budget": 500, "budget_by": "project", "budget_is_monthly": false, "notify_when_over_budget": true, "over_budget_notification_percentage": 80, "show_budget_to_all": false, "starts_on": "2024-02-01", "ends_on": "2024-08-31", "notes": "Native iOS and Android rebuild" } } ``` -------------------------------- ### create_project Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new project associated with a client. Requires `name` and `client_id`. Supports comprehensive billing configuration including fixed-fee, task-based, or person-based billing, budget tracking, and monthly budget resets. ```APIDOC ## Tool — `create_project` Creates a new project associated with a client. Requires `name` and `client_id`. Supports comprehensive billing configuration including fixed-fee, task-based, or person-based billing, budget tracking, and monthly budget resets. ```typescript { "name": "create_project", "arguments": { "name": "Mobile App v2", "client_id": 11223, "code": "MA-2024", "is_active": true, "is_billable": true, "bill_by": "Tasks", "budget": 500, "budget_by": "project", "budget_is_monthly": false, "notify_when_over_budget": true, "over_budget_notification_percentage": 80, "show_budget_to_all": false, "starts_on": "2024-02-01", "ends_on": "2024-08-31", "notes": "Native iOS and Android rebuild" } } ``` ``` -------------------------------- ### Get Time Report Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Generates time tracking reports with filtering and grouping options. Useful for monthly summaries or user-specific analysis. ```typescript // Monthly billable hours report grouped by project { "name": "get_time_report", "arguments": { "from": "2024-01-01", "to": "2024-01-31", "billable": true, "group_by": "project" } } // User-specific report for a client { "name": "get_time_report", "arguments": { "from": "2024-01-01", "to": "2024-03-31", "client_id": 11223, "user_id": 1782959, "group_by": "task" } } // Expected response: { "results": [ { "project_id": 98765, "project_name": "Website Redesign", "client_id": 11223, "client_name": "Acme Corp", "total_hours": 87.5, "billable_hours": 82.0, "currency": "USD", "billable_amount": 12300.0 } ], "per_page": 2000, "total_pages": 1, "total_entries": 1 } ``` -------------------------------- ### Get Expense Report Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Generates an expense report within a date range, supporting filters and grouping by various dimensions like client, project, or category. ```typescript { "name": "get_expense_report", "arguments": { "from": "2024-01-01", "to": "2024-03-31", "client_id": 11223, "billable": true, "group_by": "expense_category" } } ``` -------------------------------- ### Run Tests with Coverage Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Execute all tests and generate a code coverage report. ```bash npm run test:coverage ``` -------------------------------- ### Create Client Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new client with a required name and optional active status, address, and currency. The expected response includes the new client's ID and details. ```typescript { "name": "create_client", "arguments": { "name": "TechStart Ltd", "is_active": true, "address": "456 Innovation Drive, Austin TX", "currency": "USD" } } // Expected response: { "id": 11301, "name": "TechStart Ltd", "is_active": true, "currency": "USD", "created_at": "2024-01-15T09:00:00Z" } ``` -------------------------------- ### Create Account-Level Task Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Use this tool to create a new task that can be assigned to any project. It accepts a name and optional default billing settings. ```typescript { "name": "create_task", "arguments": { "name": "UI/UX Design", "billable_by_default": true, "default_hourly_rate": 120.0, "is_default": false, "is_active": true } } ``` -------------------------------- ### Configure Claude Desktop for Harvest MCP Server Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Configure Claude Desktop by specifying the command, arguments, and environment variables for the Harvest MCP server in its configuration file. ```json // Claude Desktop config: ~/Library/Application Support/Claude/claude_desktop_config.json { "mcpServers": { "harvest": { "command": "npx", "args": ["-y", "@ianaleck/harvest-mcp-server"], "env": { "HARVEST_ACCESS_TOKEN": "your_personal_access_token", "HARVEST_ACCOUNT_ID": "your_account_id" } } } } ``` -------------------------------- ### Run Specific Test Suites Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Execute specific test suites such as unit, integration, or contract tests. ```bash npm run test:unit npm run test:integration npm run test:contract ``` -------------------------------- ### Programmatic HarvestMCPServer Lifecycle Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Instantiate and manage the HarvestMCPServer programmatically for testing or custom integrations. Supports listing tools, retrieving tools by category, and starting/stopping the server over stdio or HTTP. ```typescript import { HarvestMCPServer } from './server'; // Programmatic instantiation (e.g., for testing) const server = new HarvestMCPServer({ harvest: { accessToken: 'pat_xxx', accountId: '123456', }, }); // List all registered tools const tools = await server.listTools(); console.log(tools.map(t => t.name)); // ['get_company', 'list_time_entries', 'get_time_entry', 'create_time_entry', ...] // Get tools by category const timeTools = server.getToolsByCategory('time_entries'); // Returns tools with .execute() method unwrapped from MCP format for direct use // Start over stdio (default, for Claude Desktop) await server.run(); // Start over HTTP await server.runHttp({ port: 3000, apiKey: 'secret' }); // Graceful shutdown await server.close(); ``` -------------------------------- ### create_invoice Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new invoice for a client. Requires `client_id`; accepts subject, dates, payment terms, taxes, and discounts. ```APIDOC ## Tool — `create_invoice` ### Description Creates a new invoice for a client. Requires `client_id`; accepts subject, dates, payment terms, taxes, and discounts. ### Arguments - `client_id` (number) - Required - The ID of the client for whom the invoice is created. - `subject` (string) - Optional - The subject of the invoice. - `issue_date` (string) - Optional - The date the invoice is issued (YYYY-MM-DD). - `due_date` (string) - Optional - The date the invoice is due (YYYY-MM-DD). - `payment_term` (string) - Optional - The payment terms for the invoice (e.g., "Net 30"). - `tax` (number) - Optional - The tax rate for the invoice. - `notes` (string) - Optional - Additional notes for the invoice. - `currency` (string) - Optional - The currency of the invoice (3-letter ISO code). - `purchase_order` (string) - Optional - The purchase order number for the invoice. ### Request Example ```typescript { "name": "create_invoice", "arguments": { "client_id": 11223, "subject": "Website Redesign - February 2024", "issue_date": "2024-02-29", "due_date": "2024-03-30", "payment_term": "Net 30", "tax": 8.875, "notes": "Thank you for your business!", "currency": "USD", "purchase_order": "PO-2024-0042" } } ``` ``` -------------------------------- ### create_task Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new account-level task with optional default billing settings. Once created, the task can be assigned to any project. ```APIDOC ## Tool — `create_task` ### Description Creates a new account-level task with optional default billing settings. Once created, the task can be assigned to any project. ### Arguments - `name` (string) - Required - The name of the task. - `billable_by_default` (boolean) - Optional - Whether the task is billable by default. - `default_hourly_rate` (number) - Optional - The default hourly rate for the task. - `is_default` (boolean) - Optional - Whether this is the default task. - `is_active` (boolean) - Optional - Whether the task is active. ``` -------------------------------- ### Configure MCP Client for Harvest Source: https://github.com/ianaleck/harvest-mcp-server/blob/master/README.md Configure your MCP-compatible client, such as Claude Desktop, to use the Harvest MCP Server. This involves specifying the command to run the server and providing Harvest API credentials via environment variables. ```json { "mcpServers": { "harvest": { "command": "npx", "args": ["-y", "@ianaleck/harvest-mcp-server"], "env": { "HARVEST_ACCESS_TOKEN": "your_harvest_personal_access_token", "HARVEST_ACCOUNT_ID": "your_harvest_account_id" } } } } ``` -------------------------------- ### get_project_budget_report Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Generates a budget utilization report across projects, showing hours/costs spent versus budgeted amounts. ```APIDOC ## get_project_budget_report ### Description Generates a budget utilization report across projects, showing hours/costs spent versus budgeted amounts. Useful for identifying projects at risk of going over budget. ### Arguments - **client_id** (number) - Optional - Filter by client ID. - **is_active** (boolean) - Optional - Filter by active projects. - **over_budget** (boolean) - Optional - Filter for projects that are over budget. ### Request Example ```json // Find all over-budget active projects { "name": "get_project_budget_report", "arguments": { "is_active": true, "over_budget": true } } // All projects for a specific client { "name": "get_project_budget_report", "arguments": { "client_id": 11223 } } ``` ### Response Example ```json { "results": [ { "project_id": 98765, "project_name": "Website Redesign", "client_name": "Acme Corp", "budget_is_monthly": false, "budget": 200.0, "budget_spent": 174.5, "budget_remaining": 25.5 } ] } ``` ``` -------------------------------- ### Create Estimate Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new estimate for a client. Supports optional subject, taxes, discounts, currency, notes, and purchase order. ```typescript { "name": "create_estimate", "arguments": { "client_id": 11223, "subject": "Mobile App Development Proposal", "issue_date": "2024-01-20", "tax": 8.875, "discount": 5.0, "currency": "USD", "notes": "Estimate valid for 30 days. Scope may vary based on final requirements.", "purchase_order": "RFP-2024-007" } } ``` -------------------------------- ### create_estimate Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new estimate (proposal) for a client with optional subject, taxes, discounts, and currency. ```APIDOC ## create_estimate ### Description Creates a new estimate (proposal) for a client with optional subject, taxes, discounts, and currency. ### Arguments - **client_id** (number) - Required - The ID of the client for whom the estimate is created. - **subject** (string) - Optional - The subject line of the estimate. - **issue_date** (string) - Optional - The date the estimate is issued (YYYY-MM-DD). - **tax** (number) - Optional - The tax rate to apply to the estimate. - **discount** (number) - Optional - The discount percentage to apply. - **currency** (string) - Optional - The currency of the estimate (e.g., "USD"). - **notes** (string) - Optional - Additional notes for the estimate. - **purchase_order** (string) - Optional - The associated purchase order number. ``` -------------------------------- ### Create Invoice Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new invoice for a client, requiring a client ID. Optional arguments include subject, dates, payment terms, taxes, and discounts. ```typescript { "name": "create_invoice", "arguments": { "client_id": 11223, "subject": "Website Redesign - February 2024", "issue_date": "2024-02-29", "due_date": "2024-03-30", "payment_term": "Net 30", "tax": 8.875, "notes": "Thank you for your business!", "currency": "USD", "purchase_order": "PO-2024-0042" } } ``` -------------------------------- ### create_time_entry Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new time entry. Requires `project_id`, `task_id`, and `spent_date`. Time can be specified as decimal `hours` or as `started_time` + `ended_time` in `HH:MM` 24-hour format. Supports optional notes and an external reference object for third-party integrations. ```APIDOC ## Tool — `create_time_entry` ### Description Creates a new time entry. Requires `project_id`, `task_id`, and `spent_date`. Time can be specified as decimal `hours` or as `started_time` + `ended_time` in `HH:MM` 24-hour format. Supports optional notes and an external reference object for third-party integrations. ### Method Call Examples Decimal hours entry: ```json { "name": "create_time_entry", "arguments": { "project_id": 98765, "task_id": 8083365, "spent_date": "2024-01-15", "hours": 3.25, "notes": "Code review and PR feedback" } } ``` Start/end time entry with external reference (e.g., linked to a Jira ticket): ```json { "name": "create_time_entry", "arguments": { "project_id": 98765, "task_id": 8083365, "spent_date": "2024-01-15", "started_time": "09:00", "ended_time": "11:30", "notes": "Feature implementation", "external_reference": { "id": "PROJ-123", "group_id": "PROJ", "account_id": "jira-account", "permalink": "https://myorg.atlassian.net/browse/PROJ-123" } } } ``` ### Response Example ```json { "id": 636799001, "spent_date": "2024-01-15", "hours": 3.25, "notes": "Code review and PR feedback", "is_running": false, "project": { "id": 98765, "name": "Website Redesign" }, "task": { "id": 8083365, "name": "Development" } } ``` ``` -------------------------------- ### List Expenses with Filters Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves expenses, allowing filtering by project, billing status, and date range. Useful for tracking unbilled items. ```typescript // Unbilled expenses for a project in Q1 { "name": "list_expenses", "arguments": { "project_id": 98765, "is_billed": false, "from": "2024-01-01", "to": "2024-03-31" } } // Expected response: { "expenses": [ { "id": 15296112, "notes": "Adobe CC subscription", "total_cost": 54.99, "billable": true, "is_billed": false, "spent_date": "2024-01-05", "expense_category": { "id": 4197501, "name": "Software" }, "project": { "id": 98765, "name": "Website Redesign" }, "user": { "id": 1782959, "name": "Alice Smith" } } ] } ``` -------------------------------- ### List Projects - Filter by Client and Status Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves a paginated list of projects. Supports filtering by client ID and active status. Useful for finding projects to associate time entries with. ```typescript // List all active projects for a specific client { "name": "list_projects", "arguments": { "client_id": 11223, "is_active": true, "per_page": 100 } } ``` ```typescript { "projects": [ { "id": 98765, "name": "Website Redesign", "code": "WR-2024", "is_active": true, "is_billable": true, "is_fixed_fee": false, "bill_by": "Tasks", "budget": 200, "budget_by": "project", "hourly_rate": 150.0, "starts_on": "2024-01-01", "ends_on": "2024-03-31", "client": { "id": 11223, "name": "Acme Corp" } } ], "total_entries": 1 } ``` -------------------------------- ### Create Project Task Assignment - Assign Task to Project Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Assigns an existing task to a project, making it available for time logging. Allows setting a specific billing rate and budget for the task within that project. ```typescript { "name": "create_project_task_assignment", "arguments": { "project_id": 98765, "task_id": 8083370, "billable": true, "hourly_rate": 175.0, "budget": 50 } } ``` -------------------------------- ### list_projects Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves a paginated list of projects with optional filtering by active status, client ID, and last-updated timestamp. ```APIDOC ## Tool — `list_projects` Retrieves a paginated list of projects with optional filtering by active status, client ID, and last-updated timestamp. ```typescript // List all active projects for a specific client { "name": "list_projects", "arguments": { "client_id": 11223, "is_active": true, "per_page": 100 } } // Expected response: { "projects": [ { "id": 98765, "name": "Website Redesign", "code": "WR-2024", "is_active": true, "is_billable": true, "is_fixed_fee": false, "bill_by": "Tasks", "budget": 200, "budget_by": "project", "hourly_rate": 150.0, "starts_on": "2024-01-01", "ends_on": "2024-03-31", "client": { "id": 11223, "name": "Acme Corp" } } ], "total_entries": 1 } ``` ``` -------------------------------- ### create_expense Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new expense entry. Requires project_id, expense_category_id, spent_date, and total_cost. ```APIDOC ## create_expense ### Description Creates a new expense entry. Requires `project_id`, `expense_category_id`, `spent_date`, and `total_cost`. ### Arguments - **project_id** (number) - Required - The ID of the project the expense belongs to. - **expense_category_id** (number) - Required - The ID of the expense category. - **spent_date** (string) - Required - The date the expense was incurred (YYYY-MM-DD). - **total_cost** (number) - Required - The total cost of the expense. - **notes** (string) - Optional - Additional notes for the expense. - **billable** (boolean) - Optional - Whether the expense is billable to a client. - **user_id** (number) - Optional - The ID of the user who incurred the expense. ``` -------------------------------- ### BaseHarvestClient Configuration Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt The abstract base for all domain clients, configuring an axios instance with authentication, logging, and error handling. Domain clients extend it for specific endpoints. ```typescript import { BaseHarvestClient, HarvestAPIOptions } from './client/base-client'; // Custom domain client example class MyCustomClient extends BaseHarvestClient { constructor(options: HarvestAPIOptions) { super(options, 'my-custom-client'); } async getSomeResource(id: number) { const query = this.buildQueryString({ include_archived: false }); const res = await this.client.get(`/some_resource/${id}?${query}`); return res.data; } } // HarvestAPIOptions interface const options: HarvestAPIOptions = { accessToken: 'pat_xxx', accountId: '123456', baseUrl: 'https://api.harvestapp.com/v2', // optional override timeout: 30000, // optional override (ms) httpClient: mockAxiosInstance, // optional injection for testing }; ``` -------------------------------- ### List Clients Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves a paginated list of clients. Supports filtering by active status and last-updated timestamp. The expected response includes a list of clients and the total number of entries. ```typescript { "name": "list_clients", "arguments": { "is_active": true, "per_page": 200 } } // Expected response: { "clients": [ { "id": 11223, "name": "Acme Corp", "is_active": true, "address": "123 Main Street, Springfield", "currency": "USD" } ], "total_entries": 1 } ``` -------------------------------- ### List Invoices Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves invoices with optional filtering by client, project, state, and date range. The expected response includes invoice details. ```typescript // Find all open invoices for a client { "name": "list_invoices", "arguments": { "client_id": 11223, "state": "open" } } // Expected response: { "invoices": [ { "id": 13150453, "number": "INV-0042", "subject": "Website Redesign - January", "state": "open", "amount": 4500.0, "due_amount": 4500.0, "issue_date": "2024-01-31", "due_date": "2024-02-29", "currency": "USD", "client": { "id": 11223, "name": "Acme Corp" } } ] } ``` -------------------------------- ### list_tasks Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves all account-level tasks with optional filtering. Tasks are global resources that can be assigned to multiple projects. ```APIDOC ## Tool — `list_tasks` Retrieves all account-level tasks with optional filtering. Tasks are global resources that can be assigned to multiple projects. ```typescript { "name": "list_tasks", "arguments": { "is_active": true } } // Expected response: { "tasks": [ { "id": 8083365, "name": "Development", "billable_by_default": true, "default_hourly_rate": 100.0, "is_default": true, "is_active": true } ] } ``` ``` -------------------------------- ### Harvest Pagination Utilities Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Helpers for working with Harvest's paginated responses. All list tools accept 'page' and 'per_page' parameters (max 2000 per page). ```typescript import { buildPaginatedResponse, extractPaginationInfo, hasNextPage, getAllPages, PaginatedResponse, } from './utils/pagination'; // Check if more pages are available const pagination = extractPaginationInfo(apiResponse); if (hasNextPage(pagination)) { console.log(`Next page: ${pagination.next_page} of ${pagination.total_pages}`); } // Fetch all pages automatically (wraps any page-fetching function) const allEntries = await getAllPages( async (page, perPage) => { const res = await harvestClient.getTimeEntries({ page, per_page: perPage }); return buildPaginatedResponse(res.time_entries, res); }, 2000 // entries per page ); console.log(`Total entries fetched: ${allEntries.length}`); ``` -------------------------------- ### Pagination Utilities Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Provides helper functions for managing paginated responses from the Harvest API, including fetching all pages. ```APIDOC ## Pagination Utilities ### Description The `src/utils/pagination.ts` module provides helpers for working with Harvest's paginated responses. All list tools accept `page` and `per_page` parameters (max 2000 per page). ### Functions - `extractPaginationInfo(apiResponse)`: Extracts pagination details from an API response. - `hasNextPage(pagination)`: Checks if there are more pages available. - `getAllPages(pageFetcher, perPage)`: Fetches all pages of a paginated resource. - `buildPaginatedResponse(items, response)`: Builds a paginated response object. ### Usage Example ```typescript import { extractPaginationInfo, hasNextPage, getAllPages, buildPaginatedResponse } from './utils/pagination'; // Check if more pages are available const pagination = extractPaginationInfo(apiResponse); if (hasNextPage(pagination)) { console.log(`Next page: ${pagination.next_page} of ${pagination.total_pages}`); } // Fetch all pages automatically const allEntries = await getAllPages( async (page, perPage) => { const res = await harvestClient.getTimeEntries({ page, per_page: perPage }); return buildPaginatedResponse(res.time_entries, res); }, 2000 // entries per page ); console.log(`Total entries fetched: ${allEntries.length}`); ``` ``` -------------------------------- ### Create New Time Entry Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Creates a new time entry, requiring `project_id`, `task_id`, and `spent_date`. Time can be specified as decimal hours or using `started_time` and `ended_time`. Optional fields include notes and an external reference object. ```typescript // Decimal hours entry { "name": "create_time_entry", "arguments": { "project_id": 98765, "task_id": 8083365, "spent_date": "2024-01-15", "hours": 3.25, "notes": "Code review and PR feedback" } } ``` ```typescript // Start/end time entry with external reference (e.g., linked to a Jira ticket) { "name": "create_time_entry", "arguments": { "project_id": 98765, "task_id": 8083365, "spent_date": "2024-01-15", "started_time": "09:00", "ended_time": "11:30", "notes": "Feature implementation", "external_reference": { "id": "PROJ-123", "group_id": "PROJ", "account_id": "jira-account", "permalink": "https://myorg.atlassian.net/browse/PROJ-123" } } } // Expected response: { "id": 636799001, "spent_date": "2024-01-15", "hours": 3.25, "notes": "Code review and PR feedback", "is_running": false, "project": { "id": 98765, "name": "Website Redesign" }, "task": { "id": 8083365, "name": "Development" } } ``` -------------------------------- ### List Estimates with Filters Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves estimates, allowing filtering by client and state (draft, sent, accepted, declined). ```typescript { "name": "list_estimates", "arguments": { "client_id": 11223, "state": "sent" } } ``` -------------------------------- ### list_invoices Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves invoices with optional filtering by client, project, state (`draft`, `open`, `paid`, `closed`), and date range. ```APIDOC ## Tool — `list_invoices` ### Description Retrieves invoices with optional filtering by client, project, state (`draft`, `open`, `paid`, `closed`), and date range. ### Arguments - `client_id` (number) - Optional - Filter invoices by client ID. - `project_id` (number) - Optional - Filter invoices by project ID. - `state` (string) - Optional - Filter invoices by state (e.g., `draft`, `open`, `paid`, `closed`). - `issued_after` (string) - Optional - Filter invoices issued after a specific date (YYYY-MM-DD). - `issued_before` (string) - Optional - Filter invoices issued before a specific date (YYYY-MM-DD). ### Request Example ```typescript // Find all open invoices for a client { "name": "list_invoices", "arguments": { "client_id": 11223, "state": "open" } } ``` ### Response Example ```json { "invoices": [ { "id": 13150453, "number": "INV-0042", "subject": "Website Redesign - January", "state": "open", "amount": 4500.0, "due_amount": 4500.0, "issue_date": "2024-01-31", "due_date": "2024-02-29", "currency": "USD", "client": { "id": 11223, "name": "Acme Corp" } } ] } ``` ``` -------------------------------- ### List Tasks - Global Account Tasks Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves all account-level tasks. Tasks are global resources that can be assigned to multiple projects. Supports filtering by active status. ```typescript { "name": "list_tasks", "arguments": { "is_active": true } } ``` ```typescript { "tasks": [ { "id": 8083365, "name": "Development", "billable_by_default": true, "default_hourly_rate": 100.0, "is_default": true, "is_active": true } ] } ``` -------------------------------- ### restart_timer Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Restarts a previously stopped time entry, creating a new running timer based on that entry's project and task context. ```APIDOC ## Tool — `restart_timer` Restarts a previously stopped time entry, creating a new running timer based on that entry's project and task context. ```typescript { "name": "restart_timer", "arguments": { "id": 636800100 } } // Returns a new time entry with is_running: true ``` ``` -------------------------------- ### Harvest MCP Server Environment Variables Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Configuration for the Harvest MCP Server is managed through environment variables, which are validated using Zod at startup. Required variables include Harvest access token and account ID. ```bash # Required HARVEST_ACCESS_TOKEN=your_personal_access_token # Harvest PAT from Settings → Developers HARVEST_ACCOUNT_ID=your_account_id # Visible in Harvest URL or account settings # Optional NODE_ENV=production # development | production | test (default: development) LOG_LEVEL=info # error | warn | info | debug (default: info) HARVEST_API_BASE_URL=https://api.harvestapp.com/v2 REQUEST_TIMEOUT_MS=30000 # HTTP timeout in ms (default: 30000) MAX_RETRIES=3 # Max retry count (default: 3) RATE_LIMIT_REQUESTS_PER_SECOND=100 RATE_LIMIT_BURST_SIZE=200 PORT=3000 # HTTP transport port (default: 3000) MCP_TRANSPORT=stdio # stdio | http (default: stdio) MCP_API_KEY=secret # Optional API key for HTTP transport auth ``` -------------------------------- ### list_expenses Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves expenses with filtering by user, client, project, billing status, closed status, and date range. ```APIDOC ## list_expenses ### Description Retrieves expenses with filtering by user, client, project, billing status, closed status, and date range. ### Arguments - **project_id** (number) - Optional - The ID of the project to filter expenses by. - **is_billed** (boolean) - Optional - Filter by billing status (true for billed, false for unbilled). - **from** (string) - Optional - The start date for the filtering range (YYYY-MM-DD). - **to** (string) - Optional - The end date for the filtering range (YYYY-MM-DD). ### Request Example ```json { "name": "list_expenses", "arguments": { "project_id": 98765, "is_billed": false, "from": "2024-01-01", "to": "2024-03-31" } } ``` ### Response Example ```json { "expenses": [ { "id": 15296112, "notes": "Adobe CC subscription", "total_cost": 54.99, "billable": true, "is_billed": false, "spent_date": "2024-01-05", "expense_category": { "id": 4197501, "name": "Software" }, "project": { "id": 98765, "name": "Website Redesign" }, "user": { "id": 1782959, "name": "Alice Smith" } } ] } ``` ``` -------------------------------- ### list_time_entries Source: https://context7.com/ianaleck/harvest-mcp-server/llms.txt Retrieves a paginated list of time entries with optional filtering by user, client, project, task, billing status, running status, and date range. Returns up to 2000 entries per page. ```APIDOC ## Tool — `list_time_entries` ### Description Retrieves a paginated list of time entries with optional filtering by user, client, project, task, billing status, running status, and date range. Returns up to 2000 entries per page. ### Method Call Examples Filter this week's running timers for a specific project: ```json { "name": "list_time_entries", "arguments": { "project_id": 98765, "is_running": true, "from": "2024-01-08", "to": "2024-01-14", "per_page": 50 } } ``` Filter unbilled entries for a client: ```json { "name": "list_time_entries", "arguments": { "client_id": 11223, "is_billed": false, "from": "2024-01-01", "to": "2024-01-31" } } ``` ### Response Example ```json { "time_entries": [ { "id": 636718192, "spent_date": "2024-01-10", "user": { "id": 1782959, "name": "Alice Smith" }, "project": { "id": 98765, "name": "Website Redesign" }, "task": { "id": 8083365, "name": "Development" }, "hours": 2.5, "notes": "Built homepage component", "is_running": false, "is_billed": false, "billable": true, "billable_rate": 150.0, "cost_rate": 75.0, "created_at": "2024-01-10T14:00:00Z" } ], "per_page": 2000, "total_pages": 1, "total_entries": 1, "page": 1 } ``` ```