Skip to main content
Glama

mcp-gryzzly

Your timesheet, filled by asking.

A single Rust binary that puts the whole Gryzzly time-tracking API in front of any MCP client — and makes logging time the easy part.

Rust MCP Gryzzly API Transports CI License Stars


Ask your assistant "log 2h30 on Alyxa yesterday", "what did I miss last week?", "fill my timesheet from my commits" — and have it land in the same Gryzzly your team actually reports on.

> log 2h30 on Alyxa yesterday, pairing on the importer

  log_time      2h30 on Alyxa / Development, Thursday 2026-09-17
                that day now totals 7h30

> did I miss anything last week?

  timesheet     2026-W38 · 31h30 over 5 days
                .INTERNE   16h40  47.6%
                Alyxa       9h00  28.6%
                Le14        5h50  23.8%
                Friday 2026-09-18 is short: 4h of the 7h expected

No identifiers, no seconds, no date arithmetic. You name a project, say 2h30, and the server resolves the rest.

Why

Gryzzly's API is an RPC surface of 50 actions where time is attached to tasks by UUID, durations are seconds, and a list that matches nothing answers 404. It is a fine API to integrate and a miserable one to hand a language model raw. This server is the translation layer.

  • The whole API, nothing hidden. All 50 documented actions, plus whoami, log_time_bulk and timesheet, which exist because the API has no /me, no batch and no aggregate. A test fails if that count ever drops.

  • Names, not UUIDs. Every tool takes a project, task, user or customer by name, code, email or id. A name that matches two objects comes back with the candidates rather than a guess — the one thing you never want automated is which project your afternoon went to.

  • Durations and dates as people say them. 2h30, 90m, 1.5h, 2:30; today, yesterday, monday, 2026-W38, last week.

  • Written for a model to read. Structured output with schemas on all 53 tools, annotations on every one, three prompts that stop and ask before writing, and server instructions that say up front that time hangs on tasks.

  • Fail-closed where it matters. Deletes refuse to run without confirm: true. GRYZZLY_READ_ONLY=1 withholds every write tool. GRYZZLY_TOOLSETS trims the surface to what you actually use.

  • One binary, no state. No database, no OAuth dance, no background jobs. An API key in the environment, stdio or HTTP, and Gryzzly's own rate limit respected from the client side.

Related MCP server: Timesheet MCP Server

Install

git clone https://github.com/edouard-claude/gryzzly-mcp
cd gryzzly-mcp
cargo build --release
# the binary is at target/release/mcp-gryzzly
cargo install --git https://github.com/edouard-claude/gryzzly-mcp
docker build -t mcp-gryzzly .
docker run --rm -i -e GRYZZLY_API_KEY=… mcp-gryzzly

The image runs unprivileged and speaks stdio by default; add --http for the HTTP transport. See Run it over HTTP instead.

Get an API key from Gryzzly: Administration → API keys. Then check the wiring before pointing a client at it:

GRYZZLY_API_KEY=… mcp-gryzzly --check
base url     https://api.gryzzly.io/v1
toolsets     time, projects, directory, leaves, budget, exports
read only    false
tools        53
team         6 users visible
acting as    Edouard CLAUDE <edouard@squirrel.fr>
projects     41 (41 active)

ready.

Configure

Variable

Required

Default

What it is

GRYZZLY_API_KEY

yes

The API key, sent as Authorization: Bearer …

GRYZZLY_API_KEY_FILE

A file holding the key instead, for Docker secrets

GRYZZLY_USER_ID

The UUID of the person the server acts as

GRYZZLY_USER_EMAIL

That person's email, resolved to an id at startup

GRYZZLY_BASE_URL

https://api.gryzzly.io/v1

API root, prefix included

GRYZZLY_DEFAULT_PROJECT

A project name, code or id used when a tool omits one

GRYZZLY_TOOLSETS

all

time,projects,directory,leaves,budget,exports

GRYZZLY_READ_ONLY

0

1 withholds every write tool

GRYZZLY_TIMEOUT_SECS

30

Per-request timeout

GRYZZLY_CACHE_TTL_SECS

60

How long name lookups are reused

GRYZZLY_MAX_RETRIES

3

Retries on 429 and transient 5xx

GRYZZLY_LOOKBACK_DAYS

365

How far back a declaration is searched by id

GRYZZLY_HTTP_BIND

Listen address for the HTTP transport

GRYZZLY_HTTP_TOKEN

Bearer token the HTTP transport requires

GRYZZLY_LOG

info

warn, debug, mcp_gryzzly=debug…

One key, one person. A Gryzzly API key belongs to a team, not to a user, and the API has no /me. So GRYZZLY_USER_ID or GRYZZLY_USER_EMAIL names whose timesheet is being filled. A team of exactly one user needs neither. The binary refuses to start on a malformed variable and names the one at fault.

Connect a client

claude mcp add gryzzly --scope user \
  --env GRYZZLY_API_KEY=… \
  --env GRYZZLY_USER_EMAIL=you@example.com \
  -- /absolute/path/to/mcp-gryzzly

claude_desktop_config.json:

{
  "mcpServers": {
    "gryzzly": {
      "command": "/absolute/path/to/mcp-gryzzly",
      "env": {
        "GRYZZLY_API_KEY": "…",
        "GRYZZLY_USER_EMAIL": "you@example.com"
      }
    }
  }
}

Same shape: one command pointing at the binary, the key in env. The server speaks the stdio transport and prints nothing but protocol on stdout — logs go to stderr.

Point it at http://127.0.0.1:8080/mcp after starting the server with --http 127.0.0.1:8080. See below.

Then ask "who am I in Gryzzly?". whoami should answer with your name, your role, and this week's total.

Tools

53 tools in six toolsets. GRYZZLY_TOOLSETS picks which ones are registered; GRYZZLY_READ_ONLY=1 keeps only the ones that declare themselves read-only.

time — the point of the whole thing

Tool

whoami

Who the server acts as, what it may do, and this week's total

log_time

Declare time: a duration, a task or project name, a day

log_time_bulk

A whole week in one call, with one outcome line per entry

list_time_entries

Declared time over a week or a period, names filled in

timesheet

Totals per day and per project, plus the days that fall short

update_time_entry

Change a declaration's duration, day, task or description

delete_time_entry

Remove one, with confirm: true

log_time is the one to know. {"project": "Alyxa", "duration": "2h30", "date": "yesterday", "description": "pairing on the importer"} is enough: the project is matched by name, its single declarable task is chosen (or you name one), the duration becomes seconds, and the answer repeats the day's new total so a double entry is visible immediately.

projects — the catalogue, and its administration

Tool

list_projects

Filtered by status, customer, or a fragment of name or code

get_project

One project in full

list_tasks

The tasks of a project, containers and completed ones filtered out

get_task

One task in full

get_project_metrics · list_projects_metrics

Budget and time counters

create_project · update_project · delete_project

Project administration

create_task · update_task · delete_task

Task administration

directory — people and labels

Tool

list_users · get_user · invite_user

The team

list_customers · get_customer · create_customer · update_customer · delete_customer

Customers

list_groups · get_group · list_groupsets · get_groupset

Groups (read-only upstream)

list_tags · get_tag · list_tagsets · get_tagset

Tags (read-only upstream)

leaves — days off

Tool

list_leave_periods · get_leave_period

Read

create_leave_period · update_leave_period · delete_leave_period

Write

import_leave_periods

Feed Gryzzly a CSV or XLSX, inline or from a path

budget — what a project costs beyond time

Tool

list_purchases · get_purchase · create_purchase · update_purchase · delete_purchase

Purchases

list_discounts · get_discount · create_discount · update_discount · delete_discount

Discounts

Gryzzly gates both behind its budget offer; without it every call answers no_permission, and the error says so.

exports — the two download endpoints

Tool

export_projects

Gryzzly's project export, CSV or XLSX

export_times_and_leaves

Declarations and leaves, CSV or XLSX

Both are exposed for completeness and both currently fail with an API key: see Gryzzly, as it actually behaves.

Resources and prompts

Four resources and two templates, for clients that prefer attaching context to calling a function:

URI

gryzzly://me

The current user and their week

gryzzly://projects

Every project

gryzzly://users

Every user the key can see

gryzzly://customers

Every customer

gryzzly://projects/{project}/tasks

The tasks of one project, by name or id

gryzzly://timesheet/{week}

One week, totalled — 2026-W38, this week

Three prompts drive the workflows, and all three read before they write:

  • fill_my_week — read the week, propose the missing entries from real evidence, show a table, stop and wait, then write it in one log_time_bulk call.

  • weekly_review — totals, per-project split, and what looks wrong. Writes nothing.

  • catch_up_timesheet — find the empty working days over a period and close them one approved week at a time, leave periods excluded.

Gryzzly, as it actually behaves

Everything below was found against the live API, and every line of it is handled for you. It is written down because the next person integrating Gryzzly will hit the same walls.

What happens

What this server does

A *.list action matching nothing answers 404 not_found, not an empty page

Reads that 404 as the empty page it means, so "no time logged last week" is not an error

declarations.list needs task_ids present, even as [], or it 404s

Always sends both user_ids and task_ids, empty when unfiltered

There is no /me: a key is a team key

GRYZZLY_USER_ID / GRYZZLY_USER_EMAIL, resolved once and cached; a team of one needs neither

There is no declarations.get, and no id filter on the list

update_time_entry finds the entry over GRYZZLY_LOOKBACK_DAYS and fills the fields you left out

declarations.update requires date, task and duration on every call

Reads the current values first, so a partial update stays partial

*.export authenticate a browser session, so with a key they answer 500 no cookie

Says exactly that, and points at list_time_entries for the same data

Purchases and discounts answer no_permission without the budget offer

Surfaces error_type in the error's data, so a model can tell policy from breakage

users.get on an unknown id answers 500, not 404

Reported as a configuration problem when it is GRYZZLY_USER_ID

50 requests per 10 seconds, per team

A sliding window paces the process; 429 and transient 5xx are retried with backoff, honouring Retry-After

limit caps at 1000

Walked page by page when more is needed

Safety

Filling a timesheet is a write operation on the record your employer bills from, so the defaults lean careful.

  • Deletes are fail-closed. Seven tools can destroy something; each refuses without confirm: true and says what would go. They are annotated destructiveHint, so a client can warn before running them.

  • Read-only is structural. GRYZZLY_READ_ONLY=1 drops every route that does not annotate itself readOnlyHint — not a list of names to keep in sync, so a new write tool is excluded by construction. A test asserts it.

  • Nothing is guessed. An ambiguous name is an error with candidates. A malformed duration is refused before any HTTP call. log_time reports the day's new total rather than letting a duplicate pass unnoticed.

  • The key never leaks. It is redacted in Debug, marked sensitive on the HTTP header, and never serialized into a tool answer or a log line.

  • The prompts ask first. All three stop for explicit approval before writing, and the one that proposes entries is told not to invent what it cannot see.

Run it over HTTP instead

mcp-gryzzly --http 127.0.0.1:8080
# MCP at http://127.0.0.1:8080/mcp, health at /healthz

Off loopback, the server refuses to start without GRYZZLY_HTTP_TOKEN: one API key means one identity, and an open endpoint is an open proxy to your team's timesheet. With the token set, every request to /mcp needs Authorization: Bearer <token>; /healthz stays open for probes.

docker run -d --name mcp-gryzzly -p 8080:8080 \
  -e GRYZZLY_API_KEY=… \
  -e GRYZZLY_USER_EMAIL=you@example.com \
  -e GRYZZLY_HTTP_BIND=0.0.0.0:8080 \
  -e GRYZZLY_HTTP_TOKEN="$(openssl rand -hex 32)" \
  mcp-gryzzly

Put TLS in front of it. The process speaks plain HTTP and does not pretend otherwise.

Verify

cargo test                                   # 88 tests
cargo clippy --all-targets -- -D warnings
cargo fmt --all --check
mcp-gryzzly --list-tools                     # the surface, as registered
mcp-gryzzly --check                           # the configuration, against the live API

The suite includes the protocol itself: tests/mcp_stdio.rs spawns the real binary, speaks JSON-RPC to its stdin and asserts on what comes back — the handshake, all 53 tools with their schemas, the resources, the prompts, an ambiguous name, a refused delete, read-only mode. tests/api_contract.rs holds every quirk in the table above against a fake Gryzzly, and tests/mcp_http.rs checks the HTTP transport and its bearer guard.

src/
├── client.rs      RPC over HTTP: rate limiting, retries, the empty-list 404
├── config.rs      the environment, validated once, with the key redacted
├── resolve.rs     names to identifiers, and the refusal to guess
├── duration.rs    2h30, 90m, 1.5h, 2:30
├── dates.rs       today, monday, 2026-W38
├── model.rs       the Gryzzly objects, read leniently
├── tools/         one module per toolset, one function per tool
├── resources.rs   four URIs and two templates
├── prompts.rs     three workflows that ask before writing
└── server.rs      capabilities, instructions, and the glue

Contributing

Issues and pull requests welcome. A change is ready when cargo test, cargo clippy --all-targets -- -D warnings and cargo fmt --all --check pass, and when a new tool carries a description, an annotation and an output schema — three tests will tell you if it does not.

gh repo edit edouard-claude/gryzzly-mcp --add-topic \
mcp,model-context-protocol,mcp-server,gryzzly,time-tracking,timesheet,rust,rmcp,llm-tools,ai-agents,claude,claude-desktop,claude-code,anthropic,api-client,productivity,developer-tools,automation,stdio,streamable-http

License

MIT — see LICENSE. Not affiliated with Gryzzly.

mcp-name: io.github.edouard-claude/gryzzly-mcp

Available Tools

53 tools
create_customerA

Create a customer, the organisation projects are attached to and billed for. Managers can be given by name, email or id. Use it before create_project when the customer does not exist yet; check list_customers first, since a second call creates a duplicate. Returns the new customer with its id.

NameRequiredDescriptionDefault
nameYesThe customer's name.
managersNoThe managers, by name, email or id.

Output Schema

NameRequiredDescription
idYesThe customer's identifier.
nameNoThe customer's name.
managersNoThe users managing this customer.
is_activeNoWhether the customer is active.
created_atNoWhen the customer was created.
updated_atNoWhen the customer was last updated.
create_discountA

Grant a discount on exactly one project or one task, named or identified, with a name and an amount taken off its budget. Use it to add a discount; use update_discount to change one. Each call creates a new record, so check list_discounts first to avoid granting it twice. Passing both a project and a task, or neither, is refused before any request. Requires Gryzzly's budget offer.

NameRequiredDescriptionDefault
nameYesThe discount's name.
taskNoThe task it applies to, by name or id. One of project or task.
amountNoHow much is taken off.
projectNoThe project it applies to, by name, code or id. One of project or task.

Output Schema

NameRequiredDescription
idYesThe discount's identifier.
nameNoThe discount's name.
amountNoHow much is taken off.
task_idNoThe task it applies to.
created_atNoWhen the discount was created.
project_idNoThe project it applies to.
updated_atNoWhen the discount was last updated.
create_leave_periodA

Declare a leave period (days off) for a user, the current one by default. Use it for holidays and absences; use update_leave_period to move one and list_leave_periods to check existing ones first. Half days are expressed with start_type and end_type: a single afternoon off is the same day twice, pm to pm. Gryzzly refuses a leave over days that already carry time unless delete_declarations is true, which deletes that time irreversibly.

NameRequiredDescriptionDefault
userNoWhose leave it is, by name, email or id. Defaults to the current user.
end_atNoLast day off. Defaults to `start_at`, which is one day off.
end_typeNoHow much of the last day is off. Defaults to `full`.
start_atYesFirst day off.
start_typeNoHow much of the first day is off. Defaults to `full`.
descriptionNoWhy the person is away.
delete_declarationsNoDelete the declarations already made over those days. Defaults to false, which makes Gryzzly refuse the leave when time is already declared.

Output Schema

NameRequiredDescription
idYesThe leave period's identifier.
end_atNoThe last day of the leave.
user_idNoThe user on leave.
end_typeNo`full`, `am` or `pm`.
start_atNoThe first day of the leave.
edited_byNoWho last edited the leave period.
created_atNoWhen the leave period was created.
start_typeNo`full`, `am` or `pm`.
updated_atNoWhen the leave period was last updated.
descriptionNoWhy the person is away.
create_projectA

Create a project, the container tasks and time are attached to. A customer and managers or contributors can be named rather than identified. Gryzzly needs a start date, so today is used when none is given; a private project takes contributors, a public one must not. Check list_projects first, since a second call creates a duplicate; then add tasks with create_task, because time cannot be logged on a project without one.

NameRequiredDescriptionDefault
codeNoThe project's short code.
nameYesThe project's name.
tagsNoTag identifiers to attach.
end_atNoWhen the project is supposed to end.
groupsNoGroup identifiers to assign.
customerNoThe customer, by name or id.
managersNoThe managers, by name, email or id.
start_atNoWhen the project starts. Required by Gryzzly. Defaults to today.
visibilityNo`public` (everyone) or `private` (contributors only).
is_billableNoWhether the project is billable.
contributorsNoThe contributors, by name, email or id. Must be empty on a public project.

Output Schema

NameRequiredDescription
idYesThe project's identifier.
codeNoThe project's short code.
nameNoThe project's name.
noteNoThe project note.
tagsNoThe tags attached to the project.
end_atNoWhen the project is supposed to end.
groupsNoThe groups assigned to the project.
statusNoOne of `active`, `done`, `archived`.
managersNoThe users managing the project.
start_atNoWhen the project starts.
created_atNoWhen the project was created.
updated_atNoWhen the project was last updated.
visibilityNo`public` or `private`.
customer_idNoThe customer this project belongs to, when any.
is_billableNoWhether the project is billable.
contributorsNoThe users allowed to declare on a private project.
create_purchaseA

Record a purchase (an expense outside declared time) against exactly one project or one task, both accepted by name or id. Use it to add a cost; use update_purchase to change an existing one. Creates a new record on every call, so check list_purchases first to avoid duplicates. billing_policy add counts it in the budget, ignore records it only. Requires Gryzzly's budget offer.

NameRequiredDescriptionDefault
nameYesWhat was bought.
taskNoThe task it is charged to, by name or id. One of project or task.
paid_atNoWhen it was paid.
projectNoThe project it is charged to, by name, code or id. One of project or task.
billed_atNoWhen it was billed.
paid_priceNoWhat it cost.
billed_priceNoWhat it is billed for.
billing_policyNoWhether it counts in the budget. Defaults to `add`.

Output Schema

NameRequiredDescription
idYesThe purchase's identifier.
nameNoWhat was bought.
paid_atNoWhen it was paid.
task_idNoThe task it is charged to.
billed_atNoWhen it was billed.
created_atNoWhen the purchase was created.
paid_priceNoWhat it cost.
project_idNoThe project it is charged to.
updated_atNoWhen the purchase was last updated.
billed_priceNoWhat it was billed for.
billing_policyNo`add` or `ignore`, how it weighs on the budget.
create_taskA

Create a task in a project, both named or identified. Tasks are what time is declared against, so a project needs at least one before log_time works. A task with is_container true only holds other tasks and takes no time; a subtask names its parent. planned_duration and estimated_duration accept human durations (40h, 90m). Check list_tasks first, since a second call creates a duplicate.

NameRequiredDescriptionDefault
nameYesThe task's name.
tagsNoTag names to attach.
end_atNoWhen the task is supposed to end.
groupsNoGroup identifiers to assign.
parentNoThe parent task, by name or id, when this is a subtask.
projectYesThe project it belongs to, by name, code or id.
start_atNoWhen the task starts. Required by Gryzzly. Defaults to today.
budget_typeNoHow the budget is expressed.
hourly_rateNoThe hourly rate, when the type calls for one.
is_containerNoWhether this task only holds other tasks. A container takes no time.
budget_amountNoThe budget amount, when the type calls for one.
hourly_rate_modeNoWhere the hourly rate comes from.
planned_durationNoPlanned time, as a duration (`40h`, `3600s`, `90m`).
estimated_durationNoEstimated time, as a duration.

Output Schema

NameRequiredDescription
idYesThe task's identifier.
nameNoThe task's name.
tagsNoThe tags attached to the task.
end_atNoWhen the task is supposed to end.
groupsNoThe groups assigned to the task.
start_atNoWhen the task starts.
parent_idNoThe parent task, when this task is a subtask.
created_atNoWhen the task was created.
project_idNoThe project the task belongs to.
updated_atNoWhen the task was last updated.
budget_typeNoOne of `none`, `detailed`, `global`, `time`.
hourly_rateNoThe task's hourly rate.
completed_atNoWhen the task was completed.
is_containerNoWhether the task only holds other tasks.
budget_amountNoThe task's budget.
hourly_rate_modeNoOne of `task`, `group`, `contributor`.
planned_durationNoPlanned duration, in seconds.
delete_customerA
DestructiveIdempotent

Delete a customer. Gryzzly refuses while projects are attached to it.

NameRequiredDescriptionDefault
confirmNoMust be `true` to delete. Ignored when reading.
customerYesThe customer, by name or id.

Output Schema

NameRequiredDescription
idYesWhat was deleted.
kindYesThe kind of object that was deleted.
deletedYesAlways true: a failure is an error, not a `false`.
delete_discountA
DestructiveIdempotent

Delete a discount, which puts its amount back into the project's budget.

NameRequiredDescriptionDefault
idYesThe identifier.
confirmNoMust be `true` to delete. Ignored when reading.

Output Schema

NameRequiredDescription
idYesWhat was deleted.
kindYesThe kind of object that was deleted.
deletedYesAlways true: a failure is an error, not a `false`.
delete_leave_periodA
DestructiveIdempotent

Delete a leave period, which frees its days for declarations again.

NameRequiredDescriptionDefault
idYesThe leave period's identifier.
confirmNoMust be `true` to delete. Ignored when reading.

Output Schema

NameRequiredDescription
idYesWhat was deleted.
kindYesThe kind of object that was deleted.
deletedYesAlways true: a failure is an error, not a `false`.
delete_projectA
DestructiveIdempotent

Delete a project. Gryzzly refuses while declarations are attached to it, which is the safety net; confirm: true is this server's.

NameRequiredDescriptionDefault
confirmNoMust be `true`. Without it nothing is deleted.
projectYesThe project to delete, by name, code or id.

Output Schema

NameRequiredDescription
idYesWhat was deleted.
kindYesThe kind of object that was deleted.
deletedYesAlways true: a failure is an error, not a `false`.
delete_purchaseA
DestructiveIdempotent

Delete a purchase, which removes its amount from the project's budget.

NameRequiredDescriptionDefault
idYesThe identifier.
confirmNoMust be `true` to delete. Ignored when reading.

Output Schema

NameRequiredDescription
idYesWhat was deleted.
kindYesThe kind of object that was deleted.
deletedYesAlways true: a failure is an error, not a `false`.
delete_taskA
DestructiveIdempotent

Delete a task. Gryzzly refuses while declarations are attached to it.

NameRequiredDescriptionDefault
taskYesThe task to delete, by name or id.
confirmNoMust be `true`. Without it nothing is deleted.
projectNoThe project it belongs to, to disambiguate a name.

Output Schema

NameRequiredDescription
idYesWhat was deleted.
kindYesThe kind of object that was deleted.
deletedYesAlways true: a failure is an error, not a `false`.
delete_time_entryA
DestructiveIdempotent

Delete one time declaration by its id, as returned by list_time_entries. Irreversible: Gryzzly has no undo, so the call refuses to run without confirm true, and the person should see the entry and agree first. Use update_time_entry instead to correct a duration, day, task or description.

NameRequiredDescriptionDefault
idYesThe declaration's identifier.
confirmNoMust be `true`. Without it nothing is deleted.

Output Schema

NameRequiredDescription
idYesWhat was deleted.
kindYesThe kind of object that was deleted.
deletedYesAlways true: a failure is an error, not a `false`.
export_projectsA
Read-only

Download Gryzzly's project export, as CSV or XLSX. Upstream this endpoint wants a browser session, so with an API key it usually fails with an explanation rather than a file.

NameRequiredDescriptionDefault
toNoLast day of the period.
fromNoFirst day of the period.
formatNoThe file format. Defaults to `csv`.
save_toNoA path on the machine running this server to write the file to.
projectsNoThe projects to export, by name, code or id.

Output Schema

NameRequiredDescription
noteNoSet when the file was too large to inline.
textNoThe file itself, when it is text and small enough to read here.
bytesYesHow many bytes came back.
saved_toNoWhere the file was written, when `save_to` was given.
content_typeYesThe file's media type, as Gryzzly labelled it.
export_times_and_leavesA
Read-only

Download Gryzzly's combined export of declared time and leave periods over a date range, as CSV or XLSX, optionally saved to a path on the server's machine. Prefer list_time_entries or timesheet for reading time: this endpoint authenticates a browser session upstream, so with an API key it currently fails with an explanation rather than a file. Read-only.

NameRequiredDescriptionDefault
toNoLast day of the period.
fromNoFirst day of the period.
formatNoThe file format. Defaults to `csv`.
save_toNoA path on the machine running this server to write the file to.

Output Schema

NameRequiredDescription
noteNoSet when the file was too large to inline.
textNoThe file itself, when it is text and small enough to read here.
bytesYesHow many bytes came back.
saved_toNoWhere the file was written, when `save_to` was given.
content_typeYesThe file's media type, as Gryzzly labelled it.
get_customerA
Read-only

Read one customer: whether it is active, and who manages it.

NameRequiredDescriptionDefault
confirmNoMust be `true` to delete. Ignored when reading.
customerYesThe customer, by name or id.

Output Schema

NameRequiredDescription
idYesThe customer's identifier.
nameNoThe customer's name.
managersNoThe users managing this customer.
is_activeNoWhether the customer is active.
created_atNoWhen the customer was created.
updated_atNoWhen the customer was last updated.
get_discountA
Read-only

Read one discount by its identifier: name, amount, and the project or task it applies to. Use list_discounts to find the id first. Read-only; an unknown id is reported as not found. Requires Gryzzly's budget offer.

NameRequiredDescriptionDefault
idYesThe identifier.
confirmNoMust be `true` to delete. Ignored when reading.

Output Schema

NameRequiredDescription
idYesThe discount's identifier.
nameNoThe discount's name.
amountNoHow much is taken off.
task_idNoThe task it applies to.
created_atNoWhen the discount was created.
project_idNoThe project it applies to.
updated_atNoWhen the discount was last updated.
get_groupA
Read-only

Read one group by identifier: its name, its groupset, its manager.

NameRequiredDescriptionDefault
idYesThe object's identifier.

Output Schema

NameRequiredDescription
idYesThe group's identifier.
nameNoThe group's name.
created_atNoWhen the group was created.
manager_idNoThe group's manager.
updated_atNoWhen the group was last updated.
groupset_idNoThe groupset the group belongs to.
get_groupsetA
Read-only

Read one groupset by identifier, and whether its groups are exclusive.

NameRequiredDescriptionDefault
idYesThe object's identifier.

Output Schema

NameRequiredDescription
idYesThe groupset's identifier.
nameNoThe groupset's name.
colorNoThe colour shown in the interface.
created_atNoWhen the groupset was created.
updated_atNoWhen the groupset was last updated.
is_group_uniqueNoWhether one group of this set at most may be attributed.
get_leave_periodA
Read-only

Read one leave period by identifier: its days, its half days, its reason.

NameRequiredDescriptionDefault
idYesThe leave period's identifier.
confirmNoMust be `true` to delete. Ignored when reading.

Output Schema

NameRequiredDescription
idYesThe leave period's identifier.
end_atNoThe last day of the leave.
user_idNoThe user on leave.
end_typeNo`full`, `am` or `pm`.
start_atNoThe first day of the leave.
edited_byNoWho last edited the leave period.
created_atNoWhen the leave period was created.
start_typeNo`full`, `am` or `pm`.
updated_atNoWhen the leave period was last updated.
descriptionNoWhy the person is away.
get_projectA
Read-only

Read one project in full, found by name, code or id: status, dates, visibility, contributors, managers, groups, tags, customer and note. Use list_projects to browse or search; use get_project_metrics for budget and time counters. Read-only. An ambiguous name is refused with the matching candidates rather than guessed.

NameRequiredDescriptionDefault
projectYesThe project, by name, code or id.

Output Schema

NameRequiredDescription
idYesThe project's identifier.
codeNoThe project's short code.
nameNoThe project's name.
noteNoThe project note.
tagsNoThe tags attached to the project.
end_atNoWhen the project is supposed to end.
groupsNoThe groups assigned to the project.
statusNoOne of `active`, `done`, `archived`.
managersNoThe users managing the project.
start_atNoWhen the project starts.
created_atNoWhen the project was created.
updated_atNoWhen the project was last updated.
visibilityNo`public` or `private`.
customer_idNoThe customer this project belongs to, when any.
is_billableNoWhether the project is billable.
contributorsNoThe users allowed to declare on a private project.
get_project_metricsA
Read-only

Read the budget and time counters of one project, found by name, code or id: budget amount, budget spent, planned time and elapsed (declared) time, durations in seconds. Use list_projects_metrics to compare several projects in one call, and get_project for the project's settings rather than its numbers. Read-only.

NameRequiredDescriptionDefault
projectYesThe project, by name, code or id.

Output Schema

NameRequiredDescription
project_idNoThe project these metrics belong to.
budget_spentNoHow much of the budget is spent.
time_elapsedNoDeclared time, in seconds.
time_plannedNoPlanned time, in seconds.
budget_amountNoThe project's budget.
get_purchaseA
Read-only

Read one purchase by its identifier: name, project or task it is charged to, paid and billed prices, dates and billing policy. Use list_purchases to find the id first. Read-only; an unknown id is reported as not found. Requires Gryzzly's budget offer.

NameRequiredDescriptionDefault
idYesThe identifier.
confirmNoMust be `true` to delete. Ignored when reading.

Output Schema

NameRequiredDescription
idYesThe purchase's identifier.
nameNoWhat was bought.
paid_atNoWhen it was paid.
task_idNoThe task it is charged to.
billed_atNoWhen it was billed.
created_atNoWhen the purchase was created.
paid_priceNoWhat it cost.
project_idNoThe project it is charged to.
updated_atNoWhen the purchase was last updated.
billed_priceNoWhat it was billed for.
billing_policyNo`add` or `ignore`, how it weighs on the budget.
get_tagA
Read-only

Read one tag by identifier: its name and the tagset it belongs to.

NameRequiredDescriptionDefault
idYesThe object's identifier.

Output Schema

NameRequiredDescription
idYesThe tag's identifier.
nameNoThe tag's name.
tagset_idNoThe tagset the tag belongs to.
created_atNoWhen the tag was created.
updated_atNoWhen the tag was last updated.
get_tagsetA
Read-only

Read one tagset by identifier, and whether its tags are exclusive.

NameRequiredDescriptionDefault
idYesThe object's identifier.

Output Schema

NameRequiredDescription
idYesThe tagset's identifier.
nameNoThe tagset's name.
colorNoThe colour shown in the interface.
created_atNoWhen the tagset was created.
updated_atNoWhen the tagset was last updated.
is_tag_uniqueNoWhether one tag of this set at most may be attributed.
get_taskA
Read-only

Read one task in full: its budget, its rate, its planned time, its place in the project's hierarchy.

NameRequiredDescriptionDefault
taskYesThe task, by name or id.
projectNoThe project the task belongs to, to disambiguate a name.

Output Schema

NameRequiredDescription
idYesThe task's identifier.
nameNoThe task's name.
tagsNoThe tags attached to the task.
end_atNoWhen the task is supposed to end.
groupsNoThe groups assigned to the task.
start_atNoWhen the task starts.
parent_idNoThe parent task, when this task is a subtask.
created_atNoWhen the task was created.
project_idNoThe project the task belongs to.
updated_atNoWhen the task was last updated.
budget_typeNoOne of `none`, `detailed`, `global`, `time`.
hourly_rateNoThe task's hourly rate.
completed_atNoWhen the task was completed.
is_containerNoWhether the task only holds other tasks.
budget_amountNoThe task's budget.
hourly_rate_modeNoOne of `task`, `group`, `contributor`.
planned_durationNoPlanned duration, in seconds.
get_userA
Read-only

Read one user: their role, their groups, the date their times are approved until, and their rates when the plan exposes them.

NameRequiredDescriptionDefault
userYesThe user, by name, email, id, or `me`.

Output Schema

NameRequiredDescription
idYesThe user's identifier.
codeNoThe user's code, as set by the administrators.
nameNoThe user's display name.
roleNoOne of `contributor`, `collaborator`, `manager`, `director`, `admin`.
emailNoThe user's email address.
groupsNoThe groups the user belongs to.
created_atNoWhen the user was created.
updated_atNoWhen the user was last updated.
disabled_atNoWhen the user was disabled, if they were.
hourly_costNoThe user's hourly cost. Only on the budget offer.
hourly_rateNoThe user's hourly rate. Only on the budget offer.
is_disabledNoDeprecated upstream in favour of `disabled_at`.
timesheet_approved_untilNoThe date until which this user's times are approved.
import_leave_periodsA

Import leave periods from a CSV or an XLSX. The content can be written inline, or read from a path on the machine running this server. The report names every line Gryzzly refused.

NameRequiredDescriptionDefault
formatNoThe format. Inferred from the file extension, or `csv` for inline content.
contentNoThe file's contents, for a CSV written inline.
file_pathNoA path on the machine running this server, for a CSV or an XLSX.

Output Schema

NameRequiredDescription
okNoWhether the import went through.
errorsNoEvery line the importer rejected.
invite_userA

Invite someone to the team by email. Gryzzly sends the invitation; the user exists from that moment, pending their acceptance.

NameRequiredDescriptionDefault
roleNoThe role to grant. Defaults to `contributor`.
emailYesThe email address to invite. Gryzzly sends the invitation itself.
group_idsNoGroup identifiers to put the new user in.

Output Schema

NameRequiredDescription
idYesThe user's identifier.
codeNoThe user's code, as set by the administrators.
nameNoThe user's display name.
roleNoOne of `contributor`, `collaborator`, `manager`, `director`, `admin`.
emailNoThe user's email address.
groupsNoThe groups the user belongs to.
created_atNoWhen the user was created.
updated_atNoWhen the user was last updated.
disabled_atNoWhen the user was disabled, if they were.
hourly_costNoThe user's hourly cost. Only on the budget offer.
hourly_rateNoThe user's hourly rate. Only on the budget offer.
is_disabledNoDeprecated upstream in favour of `disabled_at`.
timesheet_approved_untilNoThe date until which this user's times are approved.
list_customersA
Read-only

List customers, the organisations projects are attached to and billed for. Use it to find a customer's id or name before create_project or list_projects(customer=...); use get_customer for one customer's detail. Read-only. Filter by name fragment, active status, or managers given by name, email or id. An empty result is an empty list, not an error.

NameRequiredDescriptionDefault
limitNoHow many objects to return. Upstream maximum is 1000.
queryNoKeep only customers whose name contains this text.
offsetNoHow many objects to skip, for the next page.
managersNoKeep only customers managed by these people, by name, email or id.
is_activeNoKeep only active, or only inactive, customers.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_discountsA
Read-only

List discounts (amounts taken off a project's or task's budget) with their names and amounts. Use it to audit what was granted on a project; use get_discount when you already hold one discount id. Read-only. Filters accept project and task names, codes or ids. Without Gryzzly's budget offer every call answers no_permission.

NameRequiredDescriptionDefault
limitNoHow many objects to return. Upstream maximum is 1000.
tasksNoKeep only charges of these tasks, by name or id.
offsetNoHow many objects to skip, for the next page.
projectsNoKeep only charges of these projects, by name, code or id.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_groupsA
Read-only

List groups, the user groupings Gryzzly assigns projects and rates to. Read-only upstream: groups are managed in the Gryzzly interface.

NameRequiredDescriptionDefault
idsNoKeep only these identifiers.
limitNoHow many objects to return. Upstream maximum is 1000.
queryNoKeep only entries whose name contains this text.
offsetNoHow many objects to skip, for the next page.
set_idsNoKeep only members of these sets, by identifier.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_groupsetsA
Read-only

List groupsets, the families user groups belong to (a groupset holds groups such as teams or sites). Use it to understand how the team is organised before reading list_groups; use get_groupset for one groupset. Read-only, and read-only upstream too: groupsets are managed in the Gryzzly web app. An empty result is an empty list.

NameRequiredDescriptionDefault
idsNoKeep only these identifiers.
limitNoHow many objects to return. Upstream maximum is 1000.
queryNoKeep only entries whose name contains this text.
offsetNoHow many objects to skip, for the next page.
set_idsNoKeep only members of these sets, by identifier.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_leave_periodsA
Read-only

List leave periods over a week or a period. Useful before logging time: Gryzzly refuses a declaration on a day already declared as leave.

NameRequiredDescriptionDefault
toNoLast day of an explicit period.
fromNoFirst day of an explicit period.
weekNoA week: `this week`, `last week`, `2026-W38`, or a date inside it.
limitNoHow many objects to return. Upstream maximum is 1000.
usersNoWhose leaves to read, by name, email or id. Defaults to everyone.
offsetNoHow many objects to skip, for the next page.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_projectsA
Read-only

List projects, filtered by status, customer or a fragment of their name or code. This is the starting point for logging time: a project's name here is what log_time accepts.

NameRequiredDescriptionDefault
limitNoHow many objects to return. Upstream maximum is 1000.
queryNoKeep only projects whose name or code contains this text.
offsetNoHow many objects to skip, for the next page.
statusNoKeep only these statuses. Defaults to every status.
customerNoKeep only projects of this customer, by name or id.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_projects_metricsA
Read-only

Read budget and time counters (budget amount, budget spent, planned and elapsed time in seconds) for several projects in one call, each given by name, code or id. Use it to compare projects or build a portfolio view; use get_project_metrics for a single project. Read-only. Every name is resolved before the request: an unknown or ambiguous one fails the whole call with the candidates listed.

NameRequiredDescriptionDefault
projectsYesThe projects to measure, by name, code or id.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_purchasesA
Read-only

List purchases (extra costs such as licences or subcontracting) charged to projects or tasks, with paid and billed amounts and dates. Use it to review what a project cost beyond time; use get_purchase when you already hold one purchase id. Read-only. Filters accept project and task names, codes or ids; an unknown name is an error listing what exists. Without Gryzzly's budget offer every call answers no_permission.

NameRequiredDescriptionDefault
limitNoHow many objects to return. Upstream maximum is 1000.
tasksNoKeep only charges of these tasks, by name or id.
offsetNoHow many objects to skip, for the next page.
projectsNoKeep only charges of these projects, by name, code or id.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_tagsA
Read-only

List tags, which projects and tasks are labelled with. Read-only upstream: tags are managed in the Gryzzly interface.

NameRequiredDescriptionDefault
idsNoKeep only these identifiers.
limitNoHow many objects to return. Upstream maximum is 1000.
queryNoKeep only entries whose name contains this text.
offsetNoHow many objects to skip, for the next page.
set_idsNoKeep only members of these sets, by identifier.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_tagsetsA
Read-only

List tagsets, the families tags belong to (a tagset holds tags used to label projects and tasks). Use it before list_tags to see which tag families exist; use get_tagset for one tagset. Read-only, and read-only upstream too: tagsets are managed in the Gryzzly web app. An empty result is an empty list.

NameRequiredDescriptionDefault
idsNoKeep only these identifiers.
limitNoHow many objects to return. Upstream maximum is 1000.
queryNoKeep only entries whose name contains this text.
offsetNoHow many objects to skip, for the next page.
set_idsNoKeep only members of these sets, by identifier.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_tasksA
Read-only

List the tasks of a project, which is what time is actually declared against. Container tasks and completed tasks are filtered out by default, since neither is a place to log time.

NameRequiredDescriptionDefault
limitNoHow many objects to return. Upstream maximum is 1000.
queryNoKeep only tasks whose name contains this text.
offsetNoHow many objects to skip, for the next page.
projectNoKeep only tasks of this project, by name, code or id.
include_completedNoInclude tasks already completed. Defaults to true.
include_containersNoInclude container tasks, which hold other tasks and take no time. Defaults to false.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
list_time_entriesA
Read-only

Read declared time over a week or a period, with task and project names filled in, per-day and per-project totals, and the identifiers needed to change an entry. Read before you write.

NameRequiredDescriptionDefault
toNoLast day of an explicit period. Defaults to `from`.
fromNoFirst day of an explicit period. Ignored when `week` is set.
taskNoKeep only this task, by name or id.
userNoWhose time to read. Defaults to the user this server acts as.
weekNoA week: `this week`, `last week`, `2026-W38`, or a date inside it.
limitNoHow many objects to return. Upstream maximum is 1000.
offsetNoHow many objects to skip, for the next page.
projectNoKeep only this project, by name, code or id.

Output Schema

NameRequiredDescription
toYesLast day of the period.
daysYesOne line per day that carries time.
fromYesFirst day of the period.
userYesWhose time this is.
weekNoThe ISO week, when the period is exactly one.
totalYesThe same, human readable.
entriesNoThe declarations themselves, when the caller asked for them.
projectsYesOne line per project, largest first.
total_hoursYesThe same, in decimal hours.
total_secondsYesDeclared time over the period, in seconds.
missing_workdaysYesWorking days of the period with nothing declared.
list_usersA
Read-only

List the users this API key can see, which is the whole team. Disabled users are left out unless asked for.

NameRequiredDescriptionDefault
limitNoHow many objects to return. Upstream maximum is 1000.
queryNoKeep only users whose name or email contains this text.
offsetNoHow many objects to skip, for the next page.
include_disabledNoInclude users who have been disabled. Defaults to false.

Output Schema

NameRequiredDescription
noteNoSet when the answer is worth a word of explanation.
countYesHow many objects match the filters upstream, beyond this page.
itemsYesThe objects.
returnedYesHow many objects this answer carries.
log_timeA

Declare time. Gryzzly attaches time to a task, so name a task, or a project whose tasks can be narrowed down to one. Durations are human: 2h30, 90m, 1.5h. The answer repeats the day's new total, which is how you notice you have logged the same afternoon twice.

NameRequiredDescriptionDefault
dateNoThe day: `today` (the default), `yesterday`, a weekday, `YYYY-MM-DD`.
taskNoThe task, by name or id. Optional when the project has one task only.
userNoWhose time it is. Defaults to the user this server acts as.
projectNoThe project, by name, code or id. Narrows the task lookup.
durationYesHow long: `2h30`, `90m`, `1.5h`, `2:30`, or a bare number of minutes.
descriptionNoWhat the time was spent on. Worth filling: it is what a human reads later.

Output Schema

NameRequiredDescription
entryYesThe declaration Gryzzly created.
day_totalYesWhat the whole day now totals, so a double entry is visible at once.
day_total_secondsYesThe same, in seconds.
log_time_bulkA

Declare several time entries in one call, which is what filling a week looks like: each entry takes the same arguments as log_time. Entries are created in order; by default a refusal does not stop the others, and every outcome is reported with its position. Read the week first with timesheet: Gryzzly accepts duplicates, so calling this twice logs twice.

NameRequiredDescriptionDefault
entriesYesThe declarations to create, in order.
stop_on_errorNoStop at the first refusal instead of carrying on. Defaults to false.

Output Schema

NameRequiredDescription
totalYesTotal time created, human readable.
failedYesHow many were refused.
createdYesHow many declarations were created.
outcomesYesOne line per requested entry, in order.
timesheetA
Read-only

Summarise declared time over a week or a period for one user, the current one by default: totals per day and per project, each project's share, and the working days below the expected hours. Use it to answer how much was logged or what is missing; use list_time_entries when you need the individual entries and their ids. Read-only. Optional project and task filters narrow the totals, not just a listing.

NameRequiredDescriptionDefault
toNoLast day of an explicit period. Defaults to `from`.
fromNoFirst day of an explicit period. Ignored when `week` is set.
taskNoKeep only this task, by name or id.
userNoWhose time to read. Defaults to the user this server acts as.
weekNoA week: `this week`, `last week`, `2026-W38`, or a date inside it.
projectNoKeep only this project, by name, code or id.
expected_hours_per_dayNoHours expected on a working day, used to list the days that fall short. Defaults to 7.

Output Schema

NameRequiredDescription
toYesLast day of the period.
daysYesOne line per day that carries time.
fromYesFirst day of the period.
userYesWhose time this is.
weekNoThe ISO week, when the period is exactly one.
totalYesThe same, human readable.
entriesNoThe declarations themselves, when the caller asked for them.
projectsYesOne line per project, largest first.
total_hoursYesThe same, in decimal hours.
total_secondsYesDeclared time over the period, in seconds.
missing_workdaysYesWorking days of the period with nothing declared.
update_customerA
Idempotent

Change an existing customer, found by name or id: rename it, mark it active or inactive, or replace its managers (the list you pass replaces the current one). Fields you omit are kept; Gryzzly requires a name on every update, so the current one is resent. Use delete_customer to remove a customer instead.

NameRequiredDescriptionDefault
nameNoA new name. Gryzzly requires one on every update; the current one is sent when this is absent.
customerYesThe customer to change, by name or id.
managersNoThe managers, by name, email or id. Replaces the current list.
is_activeNoWhether the customer is active.

Output Schema

NameRequiredDescription
idYesThe customer's identifier.
nameNoThe customer's name.
managersNoThe users managing this customer.
is_activeNoWhether the customer is active.
created_atNoWhen the customer was created.
updated_atNoWhen the customer was last updated.
update_discountA
Idempotent

Change an existing discount's name or amount, by its identifier. Only the fields you pass are sent. Use create_discount for a new one and delete_discount to remove one; the project or task a discount applies to cannot be moved. Requires Gryzzly's budget offer.

NameRequiredDescriptionDefault
idYesThe discount's identifier.
nameNoA new name.
amountNoA new amount.

Output Schema

NameRequiredDescription
idYesThe discount's identifier.
nameNoThe discount's name.
amountNoHow much is taken off.
task_idNoThe task it applies to.
created_atNoWhen the discount was created.
project_idNoThe project it applies to.
updated_atNoWhen the discount was last updated.
update_leave_periodA
Idempotent

Change a leave period: move it, shorten it, turn a full day into a half one.

NameRequiredDescriptionDefault
idYesThe leave period's identifier.
end_atNoA new last day.
end_typeNoHow much of the last day is off.
start_atNoA new first day.
start_typeNoHow much of the first day is off.
descriptionNoA new description.
delete_declarationsNoDelete the declarations already made over those days.

Output Schema

NameRequiredDescription
idYesThe leave period's identifier.
end_atNoThe last day of the leave.
user_idNoThe user on leave.
end_typeNo`full`, `am` or `pm`.
start_atNoThe first day of the leave.
edited_byNoWho last edited the leave period.
created_atNoWhen the leave period was created.
start_typeNo`full`, `am` or `pm`.
updated_atNoWhen the leave period was last updated.
descriptionNoWhy the person is away.
update_projectA
Idempotent

Change a project. Gryzzly requires a start date on every update, so the current one is sent when none is given.

NameRequiredDescriptionDefault
codeNoA new code.
nameNoA new name.
tagsNoTag identifiers. Replaces the current list.
end_atNoA new end date.
groupsNoGroup identifiers. Replaces the current list.
statusNoA new status.
projectYesThe project to change, by name, code or id.
customerNoA new customer, by name or id.
managersNoThe managers, by name, email or id. Replaces the current list.
start_atNoA new start date. Gryzzly requires one on every update; the current one is sent when this is absent.
visibilityNoA new visibility.
is_billableNoWhether the project is billable.
contributorsNoThe contributors, by name, email or id. Replaces the current list.

Output Schema

NameRequiredDescription
idYesThe project's identifier.
codeNoThe project's short code.
nameNoThe project's name.
noteNoThe project note.
tagsNoThe tags attached to the project.
end_atNoWhen the project is supposed to end.
groupsNoThe groups assigned to the project.
statusNoOne of `active`, `done`, `archived`.
managersNoThe users managing the project.
start_atNoWhen the project starts.
created_atNoWhen the project was created.
updated_atNoWhen the project was last updated.
visibilityNo`public` or `private`.
customer_idNoThe customer this project belongs to, when any.
is_billableNoWhether the project is billable.
contributorsNoThe users allowed to declare on a private project.
update_purchaseA
Idempotent

Change an existing purchase: name, paid or billed price, paid or billed date, billing policy. Only the fields you pass are sent; the rest are left as they are. Use create_purchase for a new cost and delete_purchase to remove one. Dates accept YYYY-MM-DD, today or yesterday. Requires Gryzzly's budget offer.

NameRequiredDescriptionDefault
idYesThe purchase's identifier.
nameNoA new name.
paid_atNoA new paid date.
billed_atNoA new billed date.
paid_priceNoA new paid price.
billed_priceNoA new billed price.
billing_policyNoA new billing policy.

Output Schema

NameRequiredDescription
idYesThe purchase's identifier.
nameNoWhat was bought.
paid_atNoWhen it was paid.
task_idNoThe task it is charged to.
billed_atNoWhen it was billed.
created_atNoWhen the purchase was created.
paid_priceNoWhat it cost.
project_idNoThe project it is charged to.
updated_atNoWhen the purchase was last updated.
billed_priceNoWhat it was billed for.
billing_policyNo`add` or `ignore`, how it weighs on the budget.
update_taskA
Idempotent

Change a task: rename it, move its dates, set its budget or its rate, mark it completed.

NameRequiredDescriptionDefault
nameNoA new name.
tagsNoTag names. Replaces the current list.
taskYesThe task to change, by name or id.
end_atNoA new end date.
groupsNoGroup identifiers. Replaces the current list.
projectNoThe project it belongs to, to disambiguate a name.
start_atNoA new start date.
hourly_rateNoA new hourly rate.
completed_atNoWhen the task was completed. Marks it done.
budget_amountNoA new budget amount.
hourly_rate_modeNoWhere the hourly rate comes from.
planned_durationNoPlanned time, as a duration (`40h`, `90m`).

Output Schema

NameRequiredDescription
idYesThe task's identifier.
nameNoThe task's name.
tagsNoThe tags attached to the task.
end_atNoWhen the task is supposed to end.
groupsNoThe groups assigned to the task.
start_atNoWhen the task starts.
parent_idNoThe parent task, when this task is a subtask.
created_atNoWhen the task was created.
project_idNoThe project the task belongs to.
updated_atNoWhen the task was last updated.
budget_typeNoOne of `none`, `detailed`, `global`, `time`.
hourly_rateNoThe task's hourly rate.
completed_atNoWhen the task was completed.
is_containerNoWhether the task only holds other tasks.
budget_amountNoThe task's budget.
hourly_rate_modeNoOne of `task`, `group`, `contributor`.
planned_durationNoPlanned duration, in seconds.
update_time_entryA
Idempotent

Change one time entry (a declaration), by the id list_time_entries returns: its duration, its day, its task, its description. Gryzzly's update requires all of them, so whatever is left out is read back from the existing entry first. Use log_time to add time and delete_time_entry to remove an entry.

NameRequiredDescriptionDefault
idYesThe declaration's identifier, as returned by `list_time_entries`.
dateNoThe new day. Left alone when absent.
taskNoThe new task, by name or id. Left alone when absent.
userNoWhose declaration it is, when it is not the current user's.
projectNoThe project the new task belongs to, to narrow the lookup.
durationNoThe new duration. Left alone when absent.
descriptionNoThe new description. Left alone when absent.

Output Schema

NameRequiredDescription
idYesThe declaration's identifier, needed to update or delete it.
dateYesThe day, as `YYYY-MM-DD`.
taskNoThe task's name, when it could be resolved.
projectNoThe project's name, when it could be resolved.
secondsYesThe duration in seconds, which is what Gryzzly stores.
task_idYesThe task the time is declared against.
user_idYesWhose time it is.
durationYesThe duration, human readable.
project_idNoThe project the task belongs to.
descriptionNoWhat the time was spent on.
whoamiA
Read-only

Who this server declares time for, what it is allowed to do, and how much time is already logged this week. Call it first: Gryzzly API keys belong to a team, not to a person, so the person has to be named by configuration, and this is where you see which one was.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
roleNoThe user's role in Gryzzly.
userYesThe user this server declares time for.
toolsetsYesThe toolsets this server exposes.
read_onlyYesTrue when every write tool was withheld.
this_weekYesThis week, so a client knows where it stands before logging anything.
team_usersYesHow many users the API key can see.
identified_byNoWhich environment variable named this user, if any did.
default_projectNoThe project used when a tool omits one.
timesheet_approved_untilNoThe date until which this user's times are approved and locked.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 53 tool updatesv0.1.0
    • First observedcreate_customer
    • First observedcreate_discount
    • First observedcreate_leave_period
    • First observedcreate_project
    • First observedcreate_purchase
    • First observedcreate_task
    • First observeddelete_customer
    • First observeddelete_discount
    • First observeddelete_leave_period
    • First observeddelete_project
    • First observeddelete_purchase
    • First observeddelete_task
    • First observeddelete_time_entry
    • First observedexport_projects
    • First observedexport_times_and_leaves
    • First observedget_customer
    • First observedget_discount
    • First observedget_group
    • First observedget_groupset
    • First observedget_leave_period
    • First observedget_project
    • First observedget_project_metrics
    • First observedget_purchase
    • First observedget_tag
    • First observedget_tagset
    • First observedget_task
    • First observedget_user
    • First observedimport_leave_periods
    • First observedinvite_user
    • First observedlist_customers
    • First observedlist_discounts
    • First observedlist_groups
    • First observedlist_groupsets
    • First observedlist_leave_periods
    • First observedlist_projects
    • First observedlist_projects_metrics
    • First observedlist_purchases
    • First observedlist_tags
    • First observedlist_tagsets
    • First observedlist_tasks
    • First observedlist_time_entries
    • First observedlist_users
    • First observedlog_time
    • First observedlog_time_bulk
    • First observedtimesheet
    • First observedupdate_customer
    • First observedupdate_discount
    • First observedupdate_leave_period
    • First observedupdate_project
    • First observedupdate_purchase
    • First observedupdate_task
    • First observedupdate_time_entry
    • First observedwhoami

TDQS

A3.8/5.0

Scored across 53 tools

Disambiguation5/5

Each tool has a distinct action and resource, and descriptions explicitly cross-reference alternatives (e.g., list_projects vs get_project_metrics vs list_projects_metrics). The CRUD pairs and specialized tools (timesheet, log_time_bulk) are clearly delineated, leaving no real overlap.

Naming Consistency4/5

The vast majority follow a consistent verb_noun pattern (list_projects, create_customer, update_task). Minor deviations like 'timesheet' (noun) and 'whoami' (phrase) are the only exceptions.

Tool Count1/5

53 tools is excessive for any single server; even with a broad domain, this exceeds the 50-tool threshold for extreme mismatch. Many tools could be consolidated or grouped into resources.

Completeness4/5

Core entities (projects, tasks, time entries, leave, discounts, purchases, customers) have full CRUD and specialized operations. Minor gaps exist for users (no update/delete) and read-only upstream entities (groups/tags), but the surface is largely complete.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers