mcp-timely
This server lets an MCP client answer read-only questions about your Timely time tracking—projects, time rollups, and work logs—using server-side aggregation.
projects_overview: see what's on your plate—every project with client, logged hours, budget burn, and unbilled amounts (optionally include inactive projects).time_spent: roll up time for a date range grouped by project, client, label, or day, with total, billable, and non-billable hours.work_log: fetch individual entries with notes for a date range—standup, diary, and invoicing material—including hours, project, billable/billed status, and timer status.All tools are read-only and scoped to the authorized Timely user; there are no write tools and no user or team parameters.
Works as an MCP server over stdio or streamable HTTP for clients like Claude.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-timelyWhat's on my plate?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-timely
An MCP server for Timely time tracking, built for asking questions rather than wrapping endpoints. It is for Timely users who want Claude, or any other MCP client, to answer "where did my time go?" reliably. Its three questions are each answered in a single upstream call with Timely doing the aggregation server-side, so the model never pages through raw entries to sum hours (and never gets the sum wrong). Three write tools log time and correct entries that were logged wrong.
Tool | The question it answers |
| What's on my plate? Projects with client, logged hours, budget burn, unbilled amounts |
| Where did my time go? Date-range rollups grouped by project, client, label or day, with billable split |
| What did I actually do? Individual entries (with their |
| Log time I already spent. One entry on a project and day; |
| Fix an entry. Move it to another project, or change its minutes, note, day, labels or billable flag; returns it before and after |
| Remove an entry, e.g. a duplicate. Does nothing unless |
Everything is scoped to the authorized user; there are no user or team
parameters. update_entry and delete_entry refuse entries that are billed,
invoiced, locked, running a timer, or belong to someone else. When Timely
rejects a change, the error carries Timely's reason (for example labels the
target project does not allow).
Requirements
Python 3.12 or newer and uv
FastMCP 4 (
fastmcp>=4.0.10,<5.0.0, installed byuv sync)A Timely account and a Timely OAuth application
Docker, only for the containerized HTTP deployment
Related MCP server: time-tracker-mcp
Setup
Create a Timely OAuth app at
https://app.timelyapp.com/<account>/oauth_applicationswith callback URLurn:ietf:wg:oauth:2.0:oob.Configure
cp .env.example .env # fill in TIMELY_CLIENT_ID and TIMELY_CLIENT_SECRETAuthorize (once)
uv sync uv run mcp-timely authOpen the printed URL, authorize, paste the code. Tokens land in
TIMELY_TOKEN_FILE(defaulttimely_tokens.json) and refresh themselves from then on.Add to Claude Code (stdio)
claude mcp add timely -- uv run --directory /path/to/mcp-timely mcp-timely
Configuration
Settings come from environment variables (see .env.example).
Variable | Default | Purpose |
| empty | Timely OAuth application ID. |
| empty | Timely OAuth application secret. |
|
| Where the token pair is stored. Must be writable and persistent. |
|
| Timely API base URL. |
|
|
|
|
| Bind address for |
|
| Listen port for |
| empty | Bearer token for the MCP endpoint. Required when |
| unset | Version string reported by |
Authentication
There are two separate credentials:
Upstream (Timely): OAuth 2.0, bootstrapped once with
mcp-timely auth. Timely rotates refresh tokens on every refresh and its access tokens carry no expiry. The server uses the access token until a 401, then refreshes once, writes the new pair atomically before continuing, and retries the request once. The token file is the only state. Runningmcp-timely authagain rotates the token family, so any other running instance needs the new file. Otherwise re-authorization is only needed if the grant is revoked.Clients (HTTP only): with
TRANSPORT=http, every request needsAuthorization: Bearer <MCP_API_KEY>(constant-time compare). The server refuses to start over HTTP without a key.
HTTP deployment
TRANSPORT=http serves streamable HTTP on /mcp and liveness on /health
(also /healthz). The Dockerfile builds a non-root image with the token file
at /data/timely_tokens.json; compose.yaml runs the published image on host
port 8011 with a persistent timely-data volume. Run mcp-timely auth first
and place the resulting token file in that volume.
docker compose upUsage telemetry
A small middleware (src/mcp_timely/usage.py) writes one JSON line per tool
call to stderr: server name, tool name, duration, outcome and MCP protocol
version. It never records arguments or results. Tool failures raise
ToolError, so they are logged with outcome: error.
Development
uv sync
uv run pytest # in-memory MCP client, no network
uv run ruff check .CI (.github/workflows/ci.yml) runs ruff and the tests as the test check,
which is required before a pull request can merge into main.
Releases
Every push to main that touches non-doc files releases automatically: tests
and a security audit run, the next vX.Y.Z tag is pushed (no version-bump
commit), and a multi-arch image is published to ghcr.io/caseyro/mcp-timely
with that version baked in (reported by /health). Consequences:
The git tag is the version;
versioninpyproject.tomlis not bumped.Add
[skip ci]to a commit message to skip a release.Markdown-only and test-only changes don't trigger a release.
Support
If this server saves you time, you can buy me a coffee.
License
MIT, see LICENSE.
Available Tools
3 toolsprojects_overviewProjects overviewARead-onlyIdempotent
[timely] What's on my plate? Every project with client, logged hours, budget burn, and unbilled amounts, sorted by hours logged.
| Name | Required | Description | Default |
|---|---|---|---|
| include_inactive | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| summary | Yes | |
| projects | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, openWorld, and idempotent hints. The description adds behavioral details such as sorting by hours logged and specifying output fields (client, budget burn, unbilled amounts), providing additional context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that front-loads the purpose with '[timely] What's on my plate?' followed by a clear list of outputs. Every word is informative, with no wasted content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has one optional parameter and an output schema, the description covers the main purpose and output fields. However, it omits guidance on the include_inactive parameter, leaving a minor completeness gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, meaning the parameter include_inactive has no description in the schema. The tool description does not mention this parameter or explain when to set it to true, failing to compensate for the low schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns every project with client, logged hours, budget burn, and unbilled amounts, sorted by hours logged. It specifies the resource (projects overview) and the action (list/retrieve), making it distinct from sibling tools like time_spent and work_log.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage through '[timely] What's on my plate?' suggesting a quick overview, but it does not explicitly provide when to use this tool versus alternatives or conditions when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
time_spentTime spentARead-onlyIdempotent
[timely] Where did my time go? Server-side rollups for a date range (YYYY-MM-DD), grouped by project, client, label, or day, with billable split. Totals are computed by Timely, not client-side. Day buckets follow the Timely account's timezone (a day's bucket equals the sum of that day's entries).
| Name | Required | Description | Default |
|---|---|---|---|
| since | Yes | ||
| until | Yes | ||
| group_by | No | project |
Output Schema
| Name | Required | Description |
|---|---|---|
| since | Yes | |
| until | Yes | |
| groups | Yes | |
| summary | Yes | |
| group_by | Yes | |
| total_hours | Yes | |
| billable_hours | Yes | |
| total_formatted | Yes | |
| non_billable_hours | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent behavior. The description adds value by disclosing that totals are computed server-side by Timely and that day buckets follow the account's timezone. This provides clarity beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, containing a few clear sentences. It front-loads the purpose and critical details without unnecessary words. The informal lead phrase 'Where did my time go?' adds personality but is still efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (3 params, output schema present), the description covers the main aspects: date range, grouping, timezone behavior, and server-side computation. It provides sufficient context for an agent to use the tool effectively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description should compensate. It mentions the date range format (YYYY-MM-DD) and the group_by options, but does not elaborate on the meaning of 'since' and 'until' beyond the schema. Some value added but incomplete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool computes server-side rollups for time spent, grouped by project/client/label/day, with billable split. It distinguishes from siblings by focusing on aggregated rollups rather than detailed logs or overviews.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for aggregated time data, mentioning server-side rollups and grouping options. However, it does not explicitly state when to use this tool over siblings like work_log or projects_overview, leaving the agent to infer based on the 'rollup' nature.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
work_logWork logARead-onlyIdempotent
[timely] What did I actually do? Individual entries with notes for a date range (YYYY-MM-DD) — standup, diary, and invoicing raw material.
| Name | Required | Description | Default |
|---|---|---|---|
| upto | Yes | ||
| since | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| upto | Yes | |
| since | Yes | |
| entries | Yes | |
| summary | Yes | |
| total_hours | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, openWorldHint, idempotentHint; description adds date range format (YYYY-MM-DD) and notes about entries, but does not mention pagination, size limits, or other behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Compact single sentence with a clarifying bracketed prefix, though the '[timely]' may be ambiguous; front-loaded with purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Description covers key output (entries with notes), references use cases (standup, diary, invoicing), and pairs well with existing annotations and output schema, making it mostly complete for a data retrieval tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% parameter description coverage. Description only indicates date range format but does not explain the 'since' and 'upto' parameters individually or their constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool retrieves individual work log entries with notes for a date range, explicitly distinguishing from sibling tools like projects_overview and time_spent by calling it 'raw material' for standup, diary, and invoicing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage for raw activity entries, but no explicit guidance on when to use this versus siblings, nor when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.2- First observed
projects_overview - First observed
time_spent - First observed
work_log
TDQS
Scored across 3 tools
Each tool serves a clearly distinct purpose: projects_overview provides project-level summaries, time_spent aggregates time data, and work_log returns raw entries. No overlap or ambiguity.
All tool names follow a consistent pattern of [noun]_[descriptor] (e.g., projects_overview, time_spent, work_log), making them predictable and easy to understand.
Three tools are appropriate for a read-only time tracking reporting server, covering high-level overview, aggregated time, and detailed logs without unnecessary bloat.
The tools cover the main read operations for time tracking reporting, but lack write/update actions. For a reporting-focused server, this is acceptable, though a tool for client or user listing could enhance coverage.
Maintenance
Related MCP Connectors
timesheet.io MCP server - manage timers, projects, tasks and reports
Manage Timequip projects, tasks, comments, members, and dashboards through MCP.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceMCP server for Timely time tracking API. Connects Claude Code to your Timely account for reading and creating time entries, projects, tasks, and users.6MIT
- FlicenseNot gradedqualityCmaintenanceA local MCP server that reads logged hours from an internal time tracker, providing tools to list time entries, projects, and the active timer. It is read-only, enabling Claude Code to see time-tracking data without writing.-
- AlicenseNot gradedqualityAmaintenanceRead-only MCP server for Clockify time tracking, exposing 60 raw read tools and five workflows for status, workspace overview, and review of days/weeks.MIT
- FlicenseNot gradedqualityBmaintenanceRead-only MCP server for Hubstaff Time Tracking and Tasks APIs, providing tasks, comments, hours, and project data. Supports OAuth 2.1 for ChatGPT integration.-