A Model Context Protocol (MCP) server for interacting with Microsoft 365 and Office services through the Graph API
When I Work is installed from its publisher's own source and answers where it runs, so this marketplace is not in the path of a single call. There is no address here to send one to, and a panel that pretended otherwise would be showing you an answer we made up. Install it and call it from your own client — the Installation tab has the entry for each one.
What it does
Check shifts, time clock entries, time-off requests, swaps and availability, and manage shifts.
Quickstart
# 1 — add it to Claude Code
claude mcp add --scope user --transport http when-i-work-mcp https://when-i-work.usefulapi.io/mcp
# 2 — ask your agent for something these tools do
# wheniwork_get_account, wheniwork_list_users, wheniwork_get_user and 18 more
When I Work costs nothing on mcprush: there is no plan to choose here, no cap to set and nothing mcprush can bill you for.
Collected from a public index. Nobody has claimed this account, so nothing here was written by its author — claim it if it is yours.
Where are you running it?
Every route below installs the same thing and ends at the same approval screen. Nothing here runs on your machine and nothing runs on ours: this server answers at its publisher’s own address, and what you install is the connection straight to it.
This is a public server: it answers at its publisher’s own address and this marketplace is not in the path. Claude Code registers it in one command; --scope user makes it available in every project. The transport below is http, as the publisher's own manifest declares it.
claude mcp add --scope user --transport http when-i-work-mcp https://when-i-work.usefulapi.io/mcpReconnect, or start a new session, and the tools appear in the model’s tool list.
One config entry pointing straight at the publisher’s own address — this marketplace is not in the path, and nothing from this listing executes on your machine.
21 tools, with what each one reads, writes and reaches shown before you agree — the same list on every route above. Read the tool surface.
Tool surface
What the model actually sees. Descriptions are diffed on every release — see version history.
Fetch the When I Work account (workplace) the token acts on — company name, plan and settings; for a parent account also its child accounts. A cheap way to confirm the credentials work. When I Work: GET /2/account.
No parameter schema on file.
List the employees, supervisors, managers and admins in the account, optionally limited to some schedules or searched by name/email. Role codes: 1 admin, 2 manager, 3 employee, 5 supervisor. When I Work: GET /2/users.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| location_id | array | no | One or more schedule (location) ids. |
| search | string | no | Search first name, last name or email. |
| show_pending | boolean | no | Include users who have not accepted their invite (default true). |
| only_pending | boolean | no | Only pending users. |
| show_deleted | boolean | no | Include deleted users (supervisor or above). |
| only_deleted | boolean | no | Only deleted/archived users (supervisor or above). |
Fetch one user by id — name, email, role, positions, schedules, wage. When I Work: GET /2/users/{id}.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| user_id | integer | yes | The user id. |
List the schedules in the account. The API calls a schedule a "location"; its id is the location_id every shift belongs to. When I Work: GET /2/locations.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| only_unconfirmed | boolean | no | Only schedules whose address is unconfirmed. |
List the positions (job roles such as Cashier or Dishwasher) in the account. When I Work: GET /2/positions.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| show_deleted | boolean | no | Include deleted positions. |
List scheduled shifts in a time window — who works when, where and in which position — optionally including open shifts and unpublished drafts. Answers "who is on on Friday?" and "what open shifts are left?". When I Work: GET /2/shifts.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| start | string | no | Start of the window. Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| end | string | no | End of the window. Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| user_id | integer | no | Only this user's shifts. |
| location_id | array | no | One or more schedule (location) ids. |
| all_locations | boolean | no | Include shifts from all schedules. |
| unpublished | boolean | no | Include unpublished (draft) shifts — supervisor or above. |
| include_open | boolean | no | Include open (unassigned) shifts from the user's schedules. |
| include_onlyopen | boolean | no | Return only open shifts. |
| include_allopen | boolean | no | Include open shifts across all schedules — manager or admin. |
| include_swaps | boolean | no | Include swap requests attached to the shifts. |
| deleted | boolean | no | Also return deleted_ids: shifts deleted in the window. |
| include_repeating_shifts_to | string | no | Also expand repeating shift series up to this date. Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| limit | integer | no | Maximum number of results. |
Fetch one shift by id, including its breaks and publish state. When I Work: GET /2/shifts/{id}.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| shift_id | integer | yes | The shift id. |
| include_repeating_shifts_to | string | no | Also expand the shift's repeating series up to this date. Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
Find who could take an open shift — either an existing shift (shift_id) or a hypothetical one (start, end, position_id and location_id all required). When I Work: GET /2/shifts/eligible.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| shift_id | integer | no | An existing shift's id. |
| start | string | no | Start of the potential shift (required without shift_id). Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| end | string | no | End of the potential shift (required without shift_id). Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| position_id | integer | no | Position of the potential shift (required without shift_id). |
| location_id | integer | no | Schedule of the potential shift (required without shift_id). |
| is_shared | boolean | no | Whether it is a shared open shift. |
| include_objects | boolean | no | Include the users' schedules and positions in the output. |
List clocked time entries — actual hours worked, clock-in/out times, length and approval state. Use only_open to see who is clocked in right now. When I Work: GET /2/times.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| start | string | no | Start of the window. Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| end | string | no | End of the window. Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| user_id | array | no | One or more user ids. |
| only_open | boolean | no | Only times with no end yet (people currently clocked in). |
| updated_at | string | no | Only times updated since this timestamp. Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
List time-off requests in a date range, with the requesting users. Status: 0 pending, 1 canceled, 2 accepted, 3 expired, 4 denied. When I Work: GET /2/requests.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| start | string | no | Start date, yyyy-mm-dd. |
| end | string | no | End date, yyyy-mm-dd. |
| user_id | array | no | One or more user ids. |
| location_id | integer | no | Only requests for this schedule. |
| status | integer | no | Only requests with this status. |
| type | integer | no | Only this request type. |
| sortby | string | no | 'created' sorts newest first; anything else sorts by status then last update. |
| include_deleted_users | boolean | no | Include requests made by deleted users. |
| since_id | integer | no | Only requests created after this request id. |
| max_id | integer | no | Only requests created before this request id. |
| limit | integer | no | Maximum number of results. |
| page | integer | no | Page of results to load (the response says whether there are more). |
Fetch one time-off request by id, with its message thread and users. When I Work: GET /2/requests/{request_id}.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| request_id | integer | yes | The time-off request id. |
List the time-off types (e.g. Personal, Sick, Holiday) and whether each allows paid time. Their ids are the type_id for a new request. When I Work: GET /2/requesttypes.
No parameter schema on file.
List shift requests: swaps, drops and alerts, with the shifts and users involved. Status: 0 pending, 1 approved, 2 declined, 3 completed, 4 canceled, 5 expired. Type: 1 swap, 2 drop, 3 alert. start and end must be given together. When I Work: GET /2/swaps.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| start | string | no | Start of the shift window (give with end). Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| end | string | no | End of the shift window (give with start). Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| user_id | array | no | One or more user ids. |
| shift_id | array | no | One or more shift ids. |
| status | array | no | One or more statuses. |
| type | array | no | One or more types. |
| open_only | boolean | no | Only open swaps. |
| limit | integer | no | Maximum number of results. |
| page | integer | no | Page of results to load (the response says whether there are more). |
List availability events — when people said they can or cannot work, including recurring patterns that fall in the window. Defaults to the caller, from now to two weeks out. When I Work: GET /2/availabilityevents.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| start | string | no | Start of the window (default now). Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| end | string | no | End of the window (default two weeks from now). Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| user_id | integer | no | Whose availability (default the calling user). |
| include_all | boolean | no | Everyone's availability, not just one user's — managers only. |
List schedule annotations — announcements, business-closed days and blackout dates when time off is not allowed. Defaults to today through one year out. When I Work: GET /2/annotations.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| start_date | string | no | Start of the range (default the start of today). Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| end_date | string | no | End of the range (default one year after start). Date-time, e.g. 2026-10-05T08:00:00-05:00 (When I Work's own examples also use RFC 2822, e.g. "Mon, 05 Oct 2026 08:00:00 -0500"). |
| no_time_off | boolean | no | Only annotations that block time off. |
Create one shift on a schedule — assigned to a user, or open (user_id 0). Created as a draft unless published is true. Undo by editing it or unpublishing. When I Work: POST /2/shifts.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| location_id | integer | yes | The schedule (location) the shift belongs to id. |
| start_time | string | yes | Shift start, date-time with offset, e.g. 2026-10-05T08:00:00-05:00. |
| end_time | string | yes | Shift end, date-time with offset. |
| user_id | integer | no | The user to assign. 0 (or omitted on create) makes it an open shift. |
| position_id | integer | no | Position for the shift. |
| site_id | integer | no | Job site for the shift. |
| break_time | number | no | Unpaid break length in hours, e.g. 0.5. |
| notes | string | no | Shift notes shown to the employee. |
| color | string | no | Hex colour without #, e.g. cc0000. |
| published | boolean | no | Publish it immediately (default: draft). |
| is_shared | boolean | no | For an open shift: a shared open shift. |
Change a shift — reassign it, move it, change position or notes. When I Work requires start_time, end_time and location_id on every update, so fetch the shift first and pass them back. This tool never sends a breaks array; When I Work documents that breaks omitted from an update's breaks list are removed, so re-check the shift's breaks afterwards. When I Work: PUT /2/shifts/{id}.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| shift_id | integer | yes | The shift id. |
| location_id | integer | yes | The schedule (location) id. |
| start_time | string | yes | Shift start (required by the API even if unchanged). |
| end_time | string | yes | Shift end (required by the API even if unchanged). |
| user_id | integer | no | The user to assign. 0 (or omitted on create) makes it an open shift. |
| position_id | integer | no | Position for the shift. |
| site_id | integer | no | Job site for the shift. |
| break_time | number | no | Unpaid break length in hours, e.g. 0.5. |
| notes | string | no | Shift notes shown to the employee. |
| color | string | no | Hex colour without #, e.g. cc0000. |
| published | boolean | no | Publish it immediately (default: draft). |
| is_shared | boolean | no | For an open shift: a shared open shift. |
Publish draft shifts so employees can see them. Publishing does not itself send notifications. Undo with wheniwork_unpublish_shifts. When I Work: POST /2/shifts/publish.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| ids | array | yes | The shift ids to publish. |
Return published shifts to draft, hiding them from employees. Undo with wheniwork_publish_shifts. When I Work: POST /2/shifts/unpublish.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| ids | array | yes | The shift ids to unpublish. |
Create a time-off request for a user (default the calling user). It starts pending; cancel it with wheniwork_update_time_off_request (status 1). Get type ids from wheniwork_list_time_off_types. When I Work: POST /2/requests.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| start_time | string | yes | Start of the time off, full date-time. |
| end_time | string | yes | End of the time off, full date-time. |
| user_id | integer | no | Who is taking time off (default the calling user). |
| type_id | integer | no | Time-off type id (Personal, Sick, Holiday...). |
| paid | boolean | no | Whether it is paid time off. |
| hours | number | no | Hours of paid time off to use. |
Change a time-off request: set its status (0 pending, 1 canceled, 2 accepted/approved, 3 expired, 4 denied) and/or its dates or hours. Reversible — set the status back. start_time and end_time must be given together. When I Work: PUT /2/requests/{request_id}.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| request_id | integer | yes | The time-off request id. |
| status | integer | no | New status. |
| start_time | string | no | New start, full date-time (give with end_time). |
| end_time | string | no | New end, full date-time (give with start_time). |
| hours | number | no | Hours of paid time off to use. |
- Every tool — any call limit is its publisher’s, not ours
- No card, and mcprush charges nothing for it
- Runs at its publisher’s own address — this marketplace is not in the path
- Nothing to cap, because mcprush bills nothing
What counts against your monthly calls
| Tool | Unit | Calls used | Out of the allowance |
|---|
Nothing here is billable: mcprush charges nothing to install When I Work or to call it, at any volume.
Two independent axes, because powerful and malicious are different questions. The grade is threat only. The capability level is blast radius, and it is never a penalty on the grade — it is priced as one subtract-only term in the score, where you can see it.
This listing is an address its publisher runs, and you connect to it directly — this marketplace is not in the path. The scanner reads packages and public source, and an address is neither: the repository linked on this page is where this record was collected from, not a copy of what the address serves, so it is not graded in its place. So there is no grade — not a withheld one, an unmeasured one.
Release history
This is an address its publisher runs: which release it serves is theirs to choose, so there is nothing here to pin. The history below is for reading; the current release on file is 1.11.1.
No release note was published with this version.
One review per account, from a signed-in account that does not publish this listing. Nothing else is asked — you can say what you think before you install it. Publishers can reply once per review, and a review can be edited or deleted by whoever wrote it.
Any signed-in account that does not publish When I Work can review it, once — before installing it or after. A review from an account that has installed it is marked as one.
Nobody has reviewed this listing. The rating on the card is the mean of the reviews written here and nothing else, so there is no rating until somebody writes the first — which takes a signed-in account that does not publish it, and nothing else.