# UseHourly (npm · usehourly-mcp)

Freelancer time tracking for AI assistants: log time, timers, timesheets, sign-off links, invoices.

- Trust score: 80/100 (high trust)
- Change this week: +3
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- remote · `usehourly.app`: 38/100, [markdown](https://verifymcp.io/servers/app-usehourly-usehourly/api-mcp.md), [page](https://verifymcp.io/servers/app-usehourly-usehourly/api-mcp)
- npm · `usehourly-mcp`: 80/100 (this document), [markdown](https://verifymcp.io/servers/app-usehourly-usehourly/usehourly-mcp.md), [page](https://verifymcp.io/servers/app-usehourly-usehourly/usehourly-mcp)

## Channel facts

- Registry: `npm`
- Package: `usehourly-mcp`
- Version: `1.1.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Supply Chain Security**: 100/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - No production dependencies, so there is no dependency health to assess.
- **Provenance & Transparency**: 48/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 15 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 85/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (good).
  - Tool/resource definitions use about 2956 tokens (~86/item across 34 items; 32 tools + 2 resources), lean.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 63/100
  - Stability observed for 19 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - All 3 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.
  - An AI judge read all 34 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 60/100
  - Spec-recency check failed: implements MCP spec 2025-06-18; the latest is 2026-07-28.

## Install

### How do I install the UseHourly MCP server?

UseHourly runs locally as an npm package, launched with npx -y usehourly-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add app-usehourly-usehourly -- npx -y usehourly-mcp
```

### Cursor

```json
{
  "mcpServers": {
    "app-usehourly-usehourly": {
      "command": "npx",
      "args": [
        "-y",
        "usehourly-mcp"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "app-usehourly-usehourly": {
      "command": "npx",
      "args": [
        "-y",
        "usehourly-mcp"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add app-usehourly-usehourly -- npx -y usehourly-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "app-usehourly-usehourly": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "usehourly-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add app-usehourly-usehourly --command npx --arg -y --arg usehourly-mcp
```

### Hermes

```yaml
mcp_servers:
  app-usehourly-usehourly:
    command: "npx"
    args: ["-y", "usehourly-mcp"]
```

### Netclaw

```json
{
  "McpServers": {
    "app-usehourly-usehourly": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "usehourly-mcp"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add app-usehourly-usehourly -t stdio -c npx -a -y usehourly-mcp
```

### Other

```json
{
  "mcpServers": {
    "app-usehourly-usehourly": {
      "command": "npx",
      "args": [
        "-y",
        "usehourly-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-04 (score 80, +1)

No change was recorded against any check on this day. Stability & Change Management went from 57 to 60. That category is still filling its 30-day observation window: 17 days of observed history at the previous scan, 18 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-11-02 (score 79, +1)

No change was recorded against any check on this day. Stability & Change Management went from 50 to 53. That category is still filling its 30-day observation window: 15 days of observed history at the previous scan, 16 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-31 (score 78, +1)

No change was recorded against any check on this day. Stability & Change Management went from 43 to 47. That category is still filling its 30-day observation window: 13 days of observed history at the previous scan, 14 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-29 (score 77, +1)

No change was recorded against any check on this day. Stability & Change Management went from 37 to 40. That category is still filling its 30-day observation window: 11 days of observed history at the previous scan, 12 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-26 (score 76, +1)

No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-24 (score 75, +1)

No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-22 (score 74, +1)

No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-10-21 (score 73, +15)

- [security improvement] Malware scan: unverified → pass

## MCP tools (32)

### `whoami` (~44 tokens)

Who am I

The signed-in account (name, email, currency, business details printed on invoices) and what this token may do (read or write). Call this first to confirm the connection.

Output parameters:

- `business` (object)
- `currency` (string): ISO 4217 code every amount is in, e.g. USD or EUR
- `email` (string)
- `id` (string)
- `member_since` (string): ISO time the account was made
- `name` (string|null)
- `token_access` (string): What this token may do

### `list_projects` (~61 tokens)

List projects

Every active project with its client and hourly rate. Use the "label" ("Client / Project") or the id wherever a project is asked for. Set include_archived to also see archived ones.

Input parameters:

- `include_archived` (boolean): Also list archived projects

Output parameters:

- `archived` (array)
- `projects` (array)

### `list_clients` (~35 tokens)

List clients

Active clients, each with its currency and its active projects. Rates are in the client's currency (its own, else the account's).

Output parameters:

- `clients` (array)

### `get_client` (~36 tokens)

Get client billing details

One client's billing details: full legal name and address as printed on invoices.

Input parameters:

- `client` (string, required): Client id or exact client name

Output parameters:

- `address` (string|null)
- `currency` (string): The currency this client's rates and invoices are in
- `has_logo` (boolean)
- `id` (string)
- `legal_name` (string|null)
- `name` (string)

### `list_entries` (~103 tokens)

List time entries

Time entries between two dates (inclusive), newest first, with totals per project and per day. Optionally limited to one project. Use this for 'what did I log last week' and to check a day before adding time.

Input parameters:

- `from` (string, required): First day to include, YYYY-MM-DD
- `project` (string): Only this project: id or "Client / Project"
- `to` (string, required): Last day to include (inclusive), YYYY-MM-DD

Output parameters:

- `entries` (array): Newest first, at most 500
- `from` (string)
- `summary` (object)
- `to` (string)
- `truncated` (boolean): True when more than 500 entries matched

### `project_totals` (~61 tokens)

Hours per project

Logged hours per project: all time and within a date range (for example this month).

Input parameters:

- `from` (string, required): First day of the range, YYYY-MM-DD
- `to` (string, required): Last day of the range (inclusive), YYYY-MM-DD

Output parameters:

- `from` (string)
- `projects` (array)
- `to` (string)

### `get_running_timer` (~27 tokens)

Running timer

The timer that is running now, with elapsed minutes, or null when none is running.

Output parameters:

- `running`: The running timer, or null

### `annual_report` (~52 tokens)

Year summary for taxes

One calendar year: hours and earnings by quarter, month, client and project, plus invoices issued and paid (cash and accrual views).

Input parameters:

- `year` (integer, required): Calendar year, e.g. 2026

Output parameters:

- `clients` (array)
- `invoices` (object): Invoices issued in the year (accrual view)
- `months` (array)
- `outstanding` (object): Issued this year and still unpaid at year end
- `projects` (array)
- `quarters` (array)
- `received` (object): Payments received in the year (cash view)
- `totals` (object)
- `year` (number)

### `list_invoices` (~164 tokens)

List invoices

Invoice history (newest 200 at most), each with the currency it was issued in. Filter by text, client, paid status or issue-date range. unpaid_totals has one figure per currency; unpaid_total is only set when every match is in one currency.

Input parameters:

- `client` (string): Only this client: id or exact name
- `issued_from` (string): Only invoices issued on or after this date
- `issued_to` (string): Only invoices issued on or before this date
- `query` (string): Matches number, client, notes, project names and entry notes
- `sort` (string): newest/oldest by issue date, highest/lowest by total
- `status` (string): Filter by whether the invoice has been paid

Output parameters:

- `count` (number)
- `invoices` (array)
- `unpaid_total` (number|null): Still unpaid across the matches, in their currency; null when the matches use more than one currency
- `unpaid_totals` (object): Still unpaid per currency code, e.g. { USD: 150 }

### `get_invoice` (~76 tokens)

Get an invoice

The frozen invoice as issued: seller, client, lines per project and totals. Set include_detail for the per-entry breakdown. Logos are left out.

Input parameters:

- `include_detail` (boolean): Include the per-entry breakdown under the lines
- `invoice` (string, required): Invoice id or invoice number, e.g. INV-2026-004

Output parameters:

- `id` (string)
- `snapshot` (object)

### `next_invoice_number` (~47 tokens)

Next invoice number

The suggested next invoice number for a year, such as INV-2026-004.

Input parameters:

- `year` (integer, required): Year of the invoice issue date, e.g. 2026

Output parameters:

- `number` (string): For example INV-2026-004

### `get_timesheet` (~148 tokens)

Get a timesheet

The timesheet for a date range as a grid: one row per project, hours per day, totals per project and per day, and the weekdays with nothing logged. Optionally for one client or one project. Use this to 'show me my timesheet for last week' or to check a sheet before sharing it. Days marked non-billable still count here.

Input parameters:

- `client` (string): Only this client: id or exact name
- `from` (string, required): First day to include, YYYY-MM-DD
- `project` (string): Only this project: id or "Client / Project"
- `to` (string, required): Last day to include (inclusive), YYYY-MM-DD

Output parameters:

- `day_totals` (object): Hours per date across the rows
- `days` (array): The dates that have time logged, oldest first
- `from` (string)
- `rows` (array)
- `scope` (string): The client or project the sheet is for, or All clients
- `to` (string)
- `total_hours` (number)
- `weekdays_without_time` (array): Monday to Friday dates in the range with nothing logged

### `parse_duration` (~58 tokens)

Parse a duration

Turn text like "1h30", "1:30" or "2.5" into whole minutes, the way UseHourly reads it.

Input parameters:

- `text` (string, required): The duration text to read, e.g. 1h30

Output parameters:

- `error` (string)
- `hours` (number)
- `minutes` (number|null): Whole minutes, or null when the text could not be read

### `log_time` (~156 tokens)

Log time

Add one time entry: a project, a date, how long, and what was done. Give minutes or a duration text. This adds a new entry; it never merges with an existing one. Check list_entries first if the day may already be logged.

Input parameters:

- `date` (string, required): The day the work was done, YYYY-MM-DD
- `duration` (string): Duration text such as "1h30" (use this or minutes)
- `minutes` (integer): Whole minutes worked (use this or duration)
- `note` (string): What was done (max 2,000 characters)
- `project` (string, required): Project id, or "Client / Project" (just the project name works when it is unique)

Output parameters:

- `logged` (object)

### `log_time_on_days` (~170 tokens)

Log the same time on several days

Add the same entry (project, minutes, note) on up to 31 dates. Days that already have time for this project are skipped and reported unless skip_existing is false.

Input parameters:

- `dates` (array, required): The days to log, YYYY-MM-DD (1 to 31 dates)
- `duration` (string): Duration text per day, such as "1h30" (use this or minutes)
- `minutes` (integer): Whole minutes per day (use this or duration)
- `note` (string): What was done (max 2,000 characters)
- `project` (string, required): Project id, or "Client / Project" (just the project name works when it is unique)
- `skip_existing` (boolean): Skip days that already have time for this project (default true)

Output parameters:

- `created` (number): Days that got an entry
- `minutes` (number): Minutes logged on each day
- `project` (string): "Client / Project"
- `skipped` (array): Days skipped because they already had time

### `set_day_totals` (~127 tokens)

Set a project's total for days

Set one project's total minutes for up to 31 days: more than 0 creates or updates that day's single entry, 0 clears it. Days that hold several entries or a running timer are skipped and reported, never merged. A note, when given, is applied to every day written.

Input parameters:

- `cells` (array, required): One item per day to set (1 to 31 days)
- `note` (string): Description applied to every day written
- `project` (string, required): Project id, or "Client / Project" (just the project name works when it is unique)

Output parameters:

- `created` (number)
- `deleted` (number)
- `project` (string): "Client / Project"
- `skipped` (array): Days skipped: several entries or a running timer
- `updated` (number)

### `update_entry` (~131 tokens)

Edit an entry

Change an entry's project, date, minutes or note. Only the fields you pass change.

Input parameters:

- `date` (string): Move the entry to this day, YYYY-MM-DD
- `duration` (string): New duration text such as "1h30" (use this or minutes)
- `id` (string, required): The entry id (from list_entries)
- `minutes` (integer): New whole minutes (use this or duration)
- `note` (string): New description (max 2,000 characters)
- `project` (string): Move the entry to this project: id or "Client / Project"

Output parameters:

- `updated` (object)

### `merge_entries` (~65 tokens)

Merge entries

Fold several entries (same project, same day) into the first one: minutes are added and notes joined. The others are removed.

Input parameters:

- `ids` (array, required): Ids of the entries to merge; the first one is kept (2 to 20, same project and day)

Output parameters:

- `id` (string): The kept entry
- `merged` (number): How many entries were folded together
- `minutes` (number): Its new total

### `delete_entry` (~37 tokens)

Delete an entry

Permanently delete one time entry. Confirm with the user before calling this.

Input parameters:

- `id` (string, required): The entry id (from list_entries)

Output parameters:

- `ok` (boolean)

### `start_timer` (~95 tokens)

Start the timer

Start a timer on a project. A timer that is already running is stopped first, so only one runs at a time.

Input parameters:

- `date` (string, required): The day the timer starts on, YYYY-MM-DD
- `note` (string): What is being worked on (max 2,000 characters)
- `project` (string, required): Project id, or "Client / Project" (just the project name works when it is unique)

Output parameters:

- `started` (object)

### `stop_timer` (~29 tokens)

Stop the timer

Stop the running timer. Elapsed time is rounded up to the next minute (at least 1).

Output parameters:

- `stopped` (object)

### `create_client` (~53 tokens)

Create a client

Add a client. Names are unique per account.

Input parameters:

- `color` (string): Hex colour such as #6366f1
- `name` (string, required): The client's name (unique per account, max 80 characters)

Output parameters:

- `client` (object)

### `update_client` (~81 tokens)

Edit a client

Rename a client or change the legal name and address printed on its invoices. Only the fields you pass change; the logo is kept.

Input parameters:

- `address` (string): Empty string clears it
- `client` (string, required): Client id or exact client name
- `legal_name` (string): Empty string clears it
- `name` (string): New display name

Output parameters:

- `client` (string): The client's name now
- `ok` (boolean)

### `archive_client` (~35 tokens)

Archive a client

Hide a client from the lists. Its time and invoices are kept.

Input parameters:

- `client` (string, required): Client id or exact client name

Output parameters:

- `archived` (string): The client's name
- `ok` (boolean)

### `create_project` (~122 tokens)

Create a project

Add a project under a client, with an hourly rate in the client's currency (its own, else the account's) and whether it is billable.

Input parameters:

- `billable` (boolean): Whether the time goes on invoices (default true)
- `client` (string, required): Client id or exact client name
- `hourly_rate` (number): Amount per hour in the client's currency (its own, else the account's), e.g. 85 or 62.5 (default 0)
- `name` (string, required): The project's name (max 80 characters)

Output parameters:

- `project` (object)

### `update_project` (~132 tokens)

Edit a project

Rename a project, move it to another client, or change its rate or billable flag. Only the fields you pass change.

Input parameters:

- `billable` (boolean): Whether the time goes on invoices
- `client` (string): Move the project to this client
- `hourly_rate` (number): New amount per hour in the client's currency (its own, else the account's), e.g. 85 or 62.5
- `name` (string): New project name
- `project` (string, required): Project id, or "Client / Project" (just the project name works when it is unique)

Output parameters:

- `project` (object)

### `archive_project` (~48 tokens)

Archive a project

Hide a project from the lists. Its time and invoices are kept.

Input parameters:

- `project` (string, required): Project id, or "Client / Project" (just the project name works when it is unique)

Output parameters:

- `archived` (string): "Client / Project"
- `ok` (boolean)

### `unarchive_project` (~38 tokens)

Restore a project

Bring an archived project (and its client, if archived) back.

Input parameters:

- `project` (string, required): Archived project id or "Client / Project"

Output parameters:

- `ok` (boolean)
- `restored` (string): "Client / Project"

### `create_invoice` (~214 tokens)

Create an invoice

Issue an invoice for a client from billable time between two dates. Totals are computed on the server from the logged entries (one line per project). The number defaults to the next INV-<year>-NNN. This creates a permanent record; confirm the client, period and dates with the user first.

Input parameters:

- `client` (string, required): Client id or exact client name
- `compact_notes` (boolean): Shorten entry descriptions to about 100 characters
- `due_date`: Payment due date, YYYY-MM-DD, or null for none
- `from` (string, required): First day of the billed period
- `include_detail` (boolean): Print each entry under the lines
- `issue_date` (string, required): The invoice date, YYYY-MM-DD
- `notes` (string): Notes printed on the invoice (max 1,000 characters)
- `number` (string): Invoice number; defaults to the next INV-<year>-NNN
- `to` (string, required): Last day of the billed period

Output parameters:

- `client` (string)
- `hours` (number)
- `id` (string)
- `lines` (array): One line per project
- `number` (string)
- `period` (string): "YYYY-MM-DD to YYYY-MM-DD"
- `total` (number): Dollars

### `mark_invoice_paid` (~70 tokens)

Mark an invoice paid or unpaid

Record the date an invoice was paid (this matters for cash-basis taxes), or pass null to mark it unpaid again.

Input parameters:

- `invoice` (string, required): Invoice id or invoice number, e.g. INV-2026-004
- `paid_date` (required): YYYY-MM-DD, or null for unpaid

Output parameters:

- `ok` (boolean)
- `paidDate` (string|null): The paid date, or null when marked unpaid

### `delete_invoice` (~50 tokens)

Delete an invoice

Permanently delete an invoice record. The time entries stay. Confirm with the user before calling this.

Input parameters:

- `invoice` (string, required): Invoice id or invoice number, e.g. INV-2026-004

Output parameters:

- `ok` (boolean)

### `share_timesheet` (~240 tokens)

Create a timesheet link for a client

Freeze the hours of a date range (optionally one client or project) into a private link a client can open without an account, read, print and approve. The link shows hours and, unless include_notes is false, the work descriptions; never rates or amounts. Anyone with the link can read it until it expires, so confirm the range, the client and whether to include notes with the user before calling. The link is returned only once: pass it on to the user. Not available on demo accounts.

Input parameters:

- `client` (string): Only this client: id or exact name
- `expires_in_days` (number): How long the link works: 7, 30, 90 days (default 30)
- `from` (string, required): First day to include, YYYY-MM-DD
- `include_notes` (boolean): Show the work descriptions to the client (default true)
- `project` (string): Only this project: id or "Client / Project"
- `title` (string): A heading for the sheet (default: client and dates)
- `to` (string, required): Last day to include (inclusive), YYYY-MM-DD

Output parameters:

- `expires_in_days` (number)
- `from` (string)
- `includes_notes` (boolean)
- `note` (string)
- `to` (string)
- `url` (string): The private link to send to the client. Shown only once

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/app-usehourly-usehourly/usehourly-mcp#diagnostics

## Score history

- 2026-11-05: 80
- 2026-11-04: 80
- 2026-11-03: 79
- 2026-11-02: 79
- 2026-11-01: 78
- 2026-10-31: 78
- 2026-10-30: 77
- 2026-10-29: 77
- 2026-10-28: 76
- 2026-10-27: 76
- 2026-10-26: 76
- 2026-10-25: 75
- 2026-10-24: 75
- 2026-10-23: 74
- 2026-10-22: 74
- 2026-10-21: 73
- 2026-10-20: 58
- 2026-10-19: 71
- 2026-10-18: 71
- 2026-10-17: 56

## Common questions

### What is the UseHourly MCP server?

UseHourly is an MCP server listed in the public MCP registry as app.usehourly/usehourly. Freelancer time tracking for AI assistants: log time, timers, timesheets, sign-off links, invoices. This page covers its npm package (usehourly-mcp).

### Is the UseHourly MCP server safe to use?

UseHourly scores 80 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the UseHourly MCP server expose?

UseHourly exposes 32 tools: whoami, list_projects, list_clients, get_client, list_entries, and 27 more. Their descriptions and schemas cost roughly 2,805 tokens of context every time the server is loaded.

### Is the UseHourly MCP server still maintained?

UseHourly is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the UseHourly MCP server under?

UseHourly declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

### What did VerifyMCP test on the UseHourly MCP server?

VerifyMCP ran 16 checks on UseHourly, covering Malware scan, Known CVEs, Install scripts, Dependency health and 12 more. Endpoint Security and Transport & Reachability do not apply to an npm package, so they were not tested. The score does not measure everything, and the scoring documentation lists what it leaves out.

## Links

- npm package: https://www.npmjs.com/package/usehourly-mcp
- Socket report: https://socket.dev/npm/package/usehourly-mcp
- Repository: https://github.com/Zontak-LLC/usehourly
- Website: https://usehourly.app/
- Changelog RSS feed: https://verifymcp.io/servers/app-usehourly-usehourly/usehourly-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/app-usehourly-usehourly/usehourly-mcp/changelog.json
- Trust report (JSON): https://verifymcp.io/servers/app-usehourly-usehourly/usehourly-mcp.json
- HTML version of this page: https://verifymcp.io/servers/app-usehourly-usehourly/usehourly-mcp
