Timr
Model Context Protocol server for the timr time-tracking API
Ask AI about Timr
Powered by Claude Β· Grounded in docs
I know everything about Timr. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
timr-client
A fully typed TypeScript SDK, CLI, and MCP server for the timr time-tracking API. Unofficial, community-maintained.
Why
The timr API ships a clean OpenAPI spec but no first-party TypeScript client. This repo fills that gap:
timr-sdk- fully typed client generated from the spec. One runtime dependency (openapi-fetch). Tree-shakeable, ESM, works in Node and edge runtimes.timr-cli- scriptable wrapper for common workflows. Prints JSON so you can pipe throughjq.timr-mcp- Model Context Protocol (stdio) server for AI agents. Uses Cloudflare-style Code Mode β agents write JavaScript against the spec instead of calling one tool per endpoint.
Typical use cases:
- Reconcile tracked hours against an issue tracker (Jira, Linear, GitHub Issues)
- Export month-end project times for invoicing or controlling
- Audit which team members haven't booked time in a given period
- Feed a dashboard or BI tool with live data
Packages
| Package | Version | Description |
|---|---|---|
timr-sdk | Typed SDK with built-in OAuth (client_credentials) or static bearer token | |
timr-cli | Command-line interface built on the SDK | |
timr-mcp | MCP (stdio) server using Cloudflare-style Code Mode β two tools (search, execute) instead of 80+ per-endpoint tools | |
jira-forge | private | Atlassian Forge app that syncs developer time from Jira issues to timr. Private install only, not on npm or the Atlassian Marketplace. |
All published packages track timr API version 0.2.14 (pinned in openapi.json).
API reference
The timr API is documented by troii on SwaggerHub. Use it as the authoritative reference for endpoints, field semantics, and error codes:
- Interactive docs: https://app.swaggerhub.com/apis-docs/troii/timr/0.2.13?view=elementsDocs
- Raw OpenAPI spec (current pinned version): https://api.swaggerhub.com/apis/troii/timr/0.2.14
- All published versions: https://app.swaggerhub.com/apis/troii/timr
See docs/spec.md for how the spec is sourced, pinned, and bumped in this repo.
SDK quickstart
pnpm add timr-sdk
import { createTimrClient } from "timr-sdk";
// OAuth2 client_credentials (recommended)
const timr = createTimrClient({
clientId: process.env.TIMR_CLIENT_ID!,
clientSecret: process.env.TIMR_CLIENT_SECRET!,
});
// ...or a static bearer token
// const timr = createTimrClient({ token: process.env.TIMR_TOKEN! });
const { data } = await timr.GET("/project-times", {
params: {
query: {
start_from: "2026-04-01",
start_to: "2026-04-30",
limit: 500,
},
},
});
for (const pt of data?.data ?? []) {
// every field is typed - hover in your editor to see the real shape
console.log(pt.id, pt.duration);
}
Every request, response, and query parameter is typed - hover any field in your editor to see what the API returns.
See the SDK README for auth options, custom fetch, and error handling.
CLI quickstart
pnpm dlx timr-cli --help
# One-time setup: store OAuth client_id + client_secret
timr auth login
timr auth status
# Every resource in the spec has a matching subcommand
timr --help
timr project-times list --start-from 2026-04-01 --start-to 2026-04-30
timr tasks list --name "Website" --bookable
Every list endpoint returns { data: T[], next_page_token: string | null }. Field names for T are documented in the auto-generated packages/cli/skills/timr/SCHEMA.md - or inspect live with jq '.data[0] | keys'.
See the CLI README for commands and the SDK README for TypeScript usage.
AI agent integration
Two options, pick whichever your agent supports:
- Claude Code skill β ships inside
timr-cliand auto-installs to~/.claude/skills/timr/onnpm install -g timr-cli. Use/timr(or just ask naturally) in any Claude Code session. Also usable with other runners that honor the sameSKILL.mdformat. - MCP server β
timr-mcpexposes the full API via two Code-Mode tools (search,execute) over stdio. Add withclaude mcp add --scope user timr npx -- -y timr-mcp, or point any MCP client atnpx -y timr-mcp. See the MCP README for auth and examples.
Reconciling against an issue tracker
The typical workflow the CLI was built for:
# 1. pull all tracked hours for a period
timr project-times list --start-from 2026-04-01 --start-to 2026-04-30 > timr.json
# 2. pull issues from your tracker (Jira, Linear, ...)
acli jira workitem search --jql "updated >= 2026-04-01" --output json > issues.json
# 3. diff them with your favourite tool
jq -s 'your rules here' timr.json issues.json
A ready-made reconciliation tool is not part of this repo on purpose - this SDK stays tracker-agnostic. Build your own, or watch for a companion repo.
Development
pnpm install
pnpm generate # regenerate SDK types + CLI commands from openapi.json
pnpm build
pnpm test
pnpm typecheck
Requires Node 20+ and pnpm 10+. Turborepo orchestrates workspace tasks.
Testing the CLI locally
Before publishing to npm you can run the CLI straight from the workspace.
# 1. install + build the workspace
pnpm install
pnpm build
# 2. run the CLI directly (no global install needed)
node packages/cli/dist/index.js --help
For convenience, alias it for the session:
alias timr-dev="node $(pwd)/packages/cli/dist/index.js"
timr-dev --help
timr-dev auth login # stores ~/.config/timr-cli/credentials.json
timr-dev auth status
timr-dev users list --limit 5
timr-dev project-times list --start-from 2026-04-01 --start-to 2026-04-30 | jq '.data | length'
Or symlink it globally:
cd packages/cli && pnpm link --global # exposes `timr` on your PATH
timr --help
pnpm unlink --global timr-cli # undo when you're done
Hot-reload during development (rebuilds on every file change):
pnpm --filter timr-cli dev
# in another shell
node packages/cli/dist/index.js --help
Regenerate CLI commands after editing openapi.json:
pnpm --filter timr-cli generate && pnpm build
Authentication for local runs
The CLI auth flow is identical to the published version:
- Create an OAuth client in timr (
Settings > API Access, grantclient_credentials, scopetimrclient openid). timr-dev auth loginand paste theclient_id+client_secret. The CLI does a token exchange before saving, so a wrong secret fails fast.- Subsequent commands reuse the stored credentials and cache the access token in memory.
Shortcuts if you don't want to store credentials:
# one-shot static bearer
timr-dev --token "eyJ..." users list
# one-shot OAuth via env
TIMR_CLIENT_ID=... TIMR_CLIENT_SECRET=... timr-dev users list
# target staging or a self-hosted instance
timr-dev --base-url https://api.staging.timr.com/v0.2/ users list
Smoke test checklist
timr-dev auth status # exits 2 until login
timr-dev auth login && timr-dev auth status # should succeed
timr-dev --help # 13 resources + auth
timr-dev users list --limit 1 | jq '.data[0] | keys' # proves a real API call
timr-dev cars list --help # proves generated flags
If any of those fail, re-run pnpm build and check pnpm -r typecheck.
Updating the spec
curl -s "https://api.swaggerhub.com/apis/troii/timr/<version>" -o openapi.json
pnpm generate
pnpm build
The release is driven by the commit messages β feat(sdk): bump spec to 0.2.15 is enough; Release Please picks it up on the next merge to main.
Project layout
timr-client/
βββ openapi.json # pinned timr spec
βββ packages/
β βββ sdk/ # timr-sdk
β β βββ src/
β β β βββ client.ts # openapi-fetch wrapper + auth middleware
β β β βββ oauth.ts # client_credentials token provider
β β β βββ generated.ts # types (generated, do not edit)
β β β βββ index.ts # public surface
β β βββ test/
β βββ cli/ # timr-cli
β β βββ scripts/
β β β βββ generate-commands.mjs # emits commands/generated/* from spec
β β βββ src/
β β βββ index.ts # citty entry
β β βββ lib/credentials.ts # ~/.config/timr-cli/credentials.json
β β βββ commands/
β β βββ _shared.ts # globalArgs, resolveClient, helpers
β β βββ auth.ts # login / logout / status
β β βββ generated/ # one file per resource (do not edit)
β βββ mcp/ # timr-mcp
β βββ scripts/
β β βββ copy-spec.mjs # bundles openapi.json for runtime search
β βββ src/
β βββ index.ts # stdio MCP server (openApiMcpServer)
β βββ executor.ts # AsyncFunction-based Code Mode executor
β βββ lib/request.ts # bridges codemode.request β timr-sdk
βββ release-please-config.json # release automation
Contributing
Issues and pull requests are welcome. A few ground rules:
- Conventional Commits drive releases -
feat:bumps minor,fix:patches,feat!:majors (via Release Please). Enforced locally by acommit-msghusky hook running commitlint. - Generated code stays generated - don't hand-edit
packages/sdk/src/generated.ts. - Spec drift should be a PR on its own - bump
openapi.json, regenerate, and ship that alone so downstream consumers see the diff clearly. - Lowercase commit subjects.
Disclaimer
Unofficial and not affiliated with troii Software GmbH, the maintainers of timr. "timr" is their trademark.
Support
Built by Michael Jauk. If this saves you time, consider buying me a coffee.
License
MIT Β© Michael Jauk

