gryzzly-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| GRYZZLY_LOG | No | Log level, e.g. warn, debug, mcp_gryzzly=debug | info |
| GRYZZLY_API_KEY | No | The Gryzzly API key, sent as Authorization: Bearer | |
| GRYZZLY_USER_ID | No | UUID of the person whose time is logged | |
| GRYZZLY_BASE_URL | No | API root, prefix included | https://api.gryzzly.io/v1 |
| GRYZZLY_TOOLSETS | No | Toolsets to register: time,projects,directory,leaves,budget,exports | all |
| GRYZZLY_HTTP_BIND | No | Listen address for the HTTP transport | |
| GRYZZLY_READ_ONLY | No | Set to 1 to withhold every write tool | 0 |
| GRYZZLY_HTTP_TOKEN | No | Bearer token the HTTP transport requires; required when binding off loopback | |
| GRYZZLY_USER_EMAIL | No | Email of the person whose time is logged, resolved to an id at startup | |
| GRYZZLY_MAX_RETRIES | No | Retries on 429 and transient 5xx | 3 |
| GRYZZLY_API_KEY_FILE | No | A file holding the API key instead, for Docker secrets | |
| GRYZZLY_TIMEOUT_SECS | No | Per-request timeout in seconds | 30 |
| GRYZZLY_LOOKBACK_DAYS | No | How far back a declaration is searched by id | 365 |
| GRYZZLY_CACHE_TTL_SECS | No | How long name lookups are reused, in seconds | 60 |
| GRYZZLY_DEFAULT_PROJECT | No | A project name, code or id used when a tool omits one |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
| prompts | {} |
| resources | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| delete_customerA | Delete a customer. Gryzzly refuses while projects are attached to it. |
| delete_discountA | Delete a discount, which puts its amount back into the project's budget. |
| delete_leave_periodA | Delete a leave period, which frees its days for declarations again. |
| delete_projectA | Delete a project. Gryzzly refuses while declarations are attached to it,
which is the safety net; |
| delete_purchaseA | Delete a purchase, which removes its amount from the project's budget. |
| delete_taskA | Delete a task. Gryzzly refuses while declarations are attached to it. |
| delete_time_entryA | 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. |
| export_projectsA | 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. |
| export_times_and_leavesA | 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. |
| get_customerA | Read one customer: whether it is active, and who manages it. |
| get_discountA | 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. |
| get_groupA | Read one group by identifier: its name, its groupset, its manager. |
| get_groupsetA | Read one groupset by identifier, and whether its groups are exclusive. |
| get_leave_periodA | Read one leave period by identifier: its days, its half days, its reason. |
| get_projectA | 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. |
| get_project_metricsA | 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. |
| get_purchaseA | 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. |
| get_tagA | Read one tag by identifier: its name and the tagset it belongs to. |
| get_tagsetA | Read one tagset by identifier, and whether its tags are exclusive. |
| get_taskA | Read one task in full: its budget, its rate, its planned time, its place in the project's hierarchy. |
| get_userA | Read one user: their role, their groups, the date their times are approved until, and their rates when the plan exposes them. |
| 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. |
| invite_userA | Invite someone to the team by email. Gryzzly sends the invitation; the user exists from that moment, pending their acceptance. |
| list_customersA | 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. |
| list_discountsA | 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. |
| list_groupsA | List groups, the user groupings Gryzzly assigns projects and rates to. Read-only upstream: groups are managed in the Gryzzly interface. |
| list_groupsetsA | 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. |
| list_leave_periodsA | List leave periods over a week or a period. Useful before logging time: Gryzzly refuses a declaration on a day already declared as leave. |
| list_projectsA | 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 |
| list_projects_metricsA | 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. |
| list_purchasesA | 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. |
| list_tagsA | List tags, which projects and tasks are labelled with. Read-only upstream: tags are managed in the Gryzzly interface. |
| list_tagsetsA | 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. |
| list_tasksA | 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. |
| list_time_entriesA | 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. |
| list_usersA | List the users this API key can see, which is the whole team. Disabled users are left out unless asked for. |
| 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:
|
| 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. |
| timesheetA | 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. |
| update_customerA | 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. |
| update_discountA | 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. |
| update_leave_periodA | Change a leave period: move it, shorten it, turn a full day into a half one. |
| update_projectA | Change a project. Gryzzly requires a start date on every update, so the current one is sent when none is given. |
| update_purchaseA | 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. |
| update_taskA | Change a task: rename it, move its dates, set its budget or its rate, mark it completed. |
| update_time_entryA | 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. |
| whoamiA | 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. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| catch_up_timesheet | Find the working days left empty over a period and close the gaps, one approval at a time. |
| fill_my_week | Fill a week's timesheet: read what is already there, propose what is missing from real evidence, get it approved, then write it in one call. |
| weekly_review | Report on a week of declared time: totals, split per project, and what looks wrong. Reads only, writes nothing. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| me | The user this server declares time for, and what is already logged this week. |
| projects | Every project, with its status, code and customer. |
| users | Every user this API key can see, with their role. |
| customers | Every customer, with its managers. |
TDQS
Scored across 53 tools
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.
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.
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.
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.