Harvest MCP

Live

OAUTH 2.1

TIME TRACKING

Productivity

Harvest MCP gives agents authenticated access to your time tracking: log hours, run billable reports, watch budgets, and turn tracked time into invoices.

  • Per-user credentials: each call uses the actual user's token, never a shared bot.
  • Encrypted per-tenant vault: AES-256, resolved at request time, never in LLM context.
  • Scoped before every call: pre-call scope check, 90-day SIEM-exportable audit chain.
Harvest MCP
agent · Acme Q3
Run
How many billable hours did the team log this week, and is the Acme redesign on budget?
S
harvestmcp_get_time_report
88ms
Harvest agent
142.5 billable hours this week across 4 projects. Acme redesign: 96 of 120 budgeted hours used, 24 remain. 31.5 hours are still uninvoiced.
Sources: 4 projects, 6 users, Jul 20 to Jul 26
harvestmcp
4 projects
18:29
Message Claude...

Tools your time agent reaches for on Harvest, scoped per user.

CALL ANY TOOL
Run time tracking end to end: start timers, log hours, report billable time, watch project budgets, and invoice tracked work.
harvestmcp_list_time_entries
List time entries
List time entries, most recent first, defaulting to the last 30 days. Filter by project, user, date range, or invoiced status; paginate via cursor.
Parameters
Name
Type
Required
Description
from
string
Optional
Inclusive start date (YYYY-MM-DD).
to
string
Optional
Inclusive end date (YYYY-MM-DD).
project_id
integer
Optional
Filter to a single project. Omit for all projects.
user_id
integer
Optional
Filter to a single user. Omit to default to yourself.
is_invoiced
boolean
Optional
true for invoiced only, false for uninvoiced only. Omit for both.
harvestmcp_get_time_report
Get time report
harvestmcp_start_timer
Start timer
harvestmcp_log_time
Log time
harvestmcp_list_projects
List projects
harvestmcp_get_project_budget
Get project budget
harvestmcp_create_invoice_from_tracked_time
Invoice tracked time
harvestmcp_list_invoices
List invoices
Build your Agent
Same auth pattern across LangChain, OpenAI, Anthropic, and Google ADK.
Python · LlamaIndex
import { ScalekitClient } from "@scalekit-sdk/node";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

// Harvest tools scoped to this user
const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["harvestmcp"], toolNames: [
    "harvestmcp_list_time_entries",
    "harvestmcp_get_time_report",
    "harvestmcp_get_project_budget"] },
  pageSize: 100,
});

const agent = createReactAgent({ llm, tools });
await agent.invoke({ messages: [{ role: "user", content: "How many billable hours did the team log this week?" }] });
import OpenAI from "openai";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const openai = new OpenAI();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["harvestmcp"] }, pageSize: 100,
});

const res = await openai.chat.completions.create({
  model: "gpt-5",
  messages: [{ role: "user", content: "Which projects are close to their budget?" }],
  tools,
});

// Execute the tool call with the user's vaulted Harvest credential
await sk.tools.executeTool(res.choices[0].message.tool_calls[0], "user_123");
import Anthropic from "@anthropic-ai/sdk";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const anthropic = new Anthropic();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["harvestmcp"] }, pageSize: 100,
});

const msg = await anthropic.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Draft an invoice from Acme's uninvoiced June time." }],
  tools,
});

// Tool call runs with the user's vaulted Harvest credential
await sk.tools.executeTool(msg.content, "user_123");
import { Agent } from "@google/adk/agents";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["harvestmcp"] }, pageSize: 100,
});

const agent = new Agent({
  name: "harvest_time_agent",
  model: "gemini-2.5-pro",
  instruction: "Track time and manage Harvest projects for the signed-in user.",
  tools,
});

await agent.run("Is the website redesign project over budget?");
Try these prompts
Copy any prompt into your agent. Each maps directly to a Harvest tool. Click to copy, paste into your agent, done.
Track time
Copy the prompt
Copied
Start a timer on the Acme redesign, design task.
Copy the prompt
Copied
Log 1.5 hours to internal meetings for today.
Copy the prompt
Copied
Is a timer running right now? Stop it if so.
Copy the prompt
Copied
Submit my timesheet for this week.
Reports and budgets
Copy the prompt
Copied
How many billable hours did the team log this week?
Copy the prompt
Copied
Which projects have used more than 80 percent of their budget?
Copy the prompt
Copied
Show uninvoiced hours by client for June.
Invoices and clients
Copy the prompt
Copied
Draft an invoice from Acme's uninvoiced June time.
Copy the prompt
Copied
List open invoices due this month.
Copy the prompt
Copied
Which invoices are late, and for how much?
SEE HOW AUTH WORKS
Your users connect once. Their Harvest credentials stay vaulted, every call is scope-checked, and every action is logged.
1
Authorize
Your user connects
Harvest MCP
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Harvest MCP
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Harvest MCP
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Harvest MCP
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
See the same per-user auth pattern across other productivity connectors.
OPS
Email-to-calendar scheduling agent
Parse scheduling intent from Gmail threads and create Google Calendar events with the right attendees and timezone.
ENGINEERING
Engineering standup agent
Aggregate GitHub and GitLab activity, link to Jira, and post a daily standup digest to Slack. No async updates.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
Other connector libraries treat auth as a demo afterthought. Scalekit starts with identity, scope enforcement, and audit. Connectors follow.
01.
Shared tokens break per-user analytics
A shared Harvest token looks fine in a demo. In production every logged hour, timer, and invoice looks like one service account, and you cannot tell who tracked the time or drafted the bill. Scalekit resolves the credential of the actual user who triggered the agent, never a shared bot.
// shared token
audit → bot_service_account

// scalekit
audit → user_abc ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Harvest today. Ten connectors tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does the agent access Harvest as the user or through a shared key?
As the user. Scalekit resolves the credential of the person who triggered the agent at request time, so every timer, logged hour, and invoice in your audit trail is attributed to a real user, not a shared service account.
Where is the Harvest token stored?
In an AES-256 encrypted vault with per-tenant namespacing. Tokens are resolved at request time, never enter LLM context, refresh automatically, and can be revoked from one dashboard.
Can I limit what the agent does in Harvest?
Yes. Filter by tool name in listScopedTools to expose only what you want, for example time reports and budget reads without create_invoice or delete_time_entry. Scalekit also enforces scope checks before every API call.
What happens when a user revokes access?
The credential is invalidated at the next tool call. The call fails closed, other users' connections are unaffected, and the revocation is logged in the audit chain.
Can the agent delete time entries or send invoices on its own?
Only if you allow it. delete_time_entry is permanent in Harvest, so most teams exclude it via the toolNames filter, and invoices the agent creates land as drafts for a human to review and send. Every write is scope-checked and logged either way.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""harvestmcp"": {
""url"": ""https://mcp.scalekit.com/harvestmcp"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.harvestmcp]
url = ""https://mcp.scalekit.com/harvestmcp""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""harvestmcp"": {
""url"": ""https://mcp.scalekit.com/harvestmcp"",
""type"": ""http""
}
}
}