Skip to main content
Glama

deputy-mcp

Ask Claude "what's my next shift?" or "who's clocked in right now?" and get the answer straight from your Deputy roster — no app, no dashboard.

CI license: MIT python 3.11+ MCP writes: opt-in, off by default

deputy-mcp connects Deputy — the workforce scheduling and timesheet platform — to Claude and any other MCP client. If your work life runs through Deputy, this lets you ask about your own shifts, timesheets, and who's on right now in plain language, instead of opening the app. It runs on your machine and only ever talks to your own Deputy install.


Example

"When do I work next?" Fri 18 Jul, 09:00–17:00 · Cloud Nine Cafe

"Am I clocked in right now?" Yes — since 20:27, still in progress.

"Who else is on with me tonight?" Sam O'Brien, rostered until 23:27.

(Fictional example data — Cloud Nine Cafe and its staff aren't real; see examples/mock_deputy.py.)


Related MCP server: SmartSuite MCP Server

Installation

Needs uv (or anything that can run uvx).

Get a token. In Deputy: Business settings → Integrations → API access → New OAuth Client → Get an Access Token (shown once — copy it). This needs an admin access level in Deputy. No admin access? Skip to No token? Use your calendar feed below.

Get your base URL. The address you see in the browser when logged in to Deputy, e.g. https://your-company.eu.deputy.com.

Claude Code

claude mcp add deputy \
  -e DEPUTY_API_TOKEN=your-deputy-token \
  -e DEPUTY_BASE_URL=https://your-company.eu.deputy.com \
  -- uvx --from git+https://github.com/augbastos/deputy-mcp deputy-mcp

Add -e DEPUTY_ALLOW_WRITES=true to also enable the write tools (off by default).

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "deputy": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/augbastos/deputy-mcp", "deputy-mcp"],
      "env": {
        "DEPUTY_API_TOKEN": "your-deputy-token",
        "DEPUTY_BASE_URL": "https://your-company.eu.deputy.com"
      }
    }
  }
}

Any other MCP client

deputy-mcp speaks MCP over stdio. Point your client at uvx --from git+https://github.com/augbastos/deputy-mcp deputy-mcp and set the same DEPUTY_* environment variables (full list in Configuration).

No token? Use your calendar feed

Not a Deputy admin? Every employee has a personal iCal feed of their own roster, and that's enough to run deputy-mcp with no API token. In Deputy, open My Schedule → Subscribe / Export to calendar and copy the link. Set it as DEPUTY_CALENDAR_URL instead of DEPUTY_API_TOKEN / DEPUTY_BASE_URL.

This mode is read-only and roster-only — deputy_get_my_roster, deputy_next_shift, deputy_whoami, deputy_get_my_calendar_url. The feed link is a secret (it carries your personal token); never commit it.


Tools

Every tool accepts response_format"markdown" (default) or "json". ? marks an optional argument.

Read — always on

Self-service tools work on any employee token. Team/manager tools need an elevated access level — on a plain employee token they fail with a clear "needs manager/admin access" message rather than a cryptic error.

Tool

Arguments

Returns

deputy_whoami

Who the token authenticates as, your location and timezone, whether you're clocked in, and your calendar feed URL. Run this first.

deputy_get_my_roster

start_date?, end_date?

Your scheduled shifts in a date range (default: today → +7 days).

deputy_next_shift

employee?

Your next upcoming shift. Naming someone else needs manager/admin.

deputy_get_my_timesheets

start_date?, end_date?

Your worked timesheets, with a total (default: last 7 days).

deputy_get_my_calendar_url

Your personal iCal feed — add it once to Google/Apple/Outlook Calendar.

deputy_get_areas

Areas (work locations) you work, with ids.

deputy_get_my_colleagues

same_workplace_only?

People you work with, grouped by location — names only, never contact details.

deputy_get_team_roster (manager)

date?, start_date?, end_date?, area_id?

Every scheduled shift in a range, optionally scoped to one area.

deputy_who_is_working (manager)

at?

Snapshot at an instant (default now): who's clocked in vs rostered.

deputy_get_employee_info (manager)

name_or_id

Profile(s) matching a name or id.

deputy_search_shifts (manager)

employee?, area_id?, start_date?, end_date?, open_only?, limit?, offset?

Shifts filtered by person, area, date, open status — paginated.

Write — opt-in, off by default

This is a deliberate security default, not a limitation: write tools only get registered when you set DEPUTY_ALLOW_WRITES=true. Until then, a model can't see them, let alone call them. Every write acts as the signed-in token holder; none of them delete anything.

Tool

Arguments

Returns

deputy_claim_open_shift

shift_id

Assigns you to an open shift.

deputy_request_shift_swap

shift_id, note?

Offers one of your shifts for swap, pending manager approval.

deputy_set_unavailability

start, end, reason?, repeat?

Records an unavailability window (one-off or recurring).

deputy_clock_in

area_id?

Starts a live timesheet.

deputy_clock_out

mealbreak_minutes?

Ends your in-progress timesheet.


How it works

flowchart LR
    A["Claude / any MCP client"] -->|"MCP, stdio"| B["deputy-mcp<br/>(runs on your machine)"]

    T1["DEPUTY_API_TOKEN"] --> B
    T2["DEPUTY_CALENDAR_URL<br/>(no token)"] --> B

    B --> R["Read tools<br/>always on"]
    B -.->|"DEPUTY_ALLOW_WRITES=true"| W["Write tools<br/>off by default"]

    R --> API["Your Deputy install"]
    W -.-> API

Reads are always registered. Writes only exist as callable tools once you opt in — otherwise the model can't see them at all.


Privacy & security

Runs locally as a stdio process — no hosted backend, no telemetry. Its only network traffic is HTTPS to your own Deputy install (or your personal iCal feed); nothing passes through a third party. deputy-mcp does exactly what your Deputy token can do, no more — the token is held in memory, redacted from logs, and never printed.


Configuration

All settings are DEPUTY_* environment variables. Provide one credential set: DEPUTY_API_TOKEN + DEPUTY_BASE_URL for the full API, or DEPUTY_CALENDAR_URL alone for iCal mode. Copy .env.example to .env and fill it in (never commit .env).

Variable

Required

Default

Description

DEPUTY_API_TOKEN

API mode

Deputy permanent or OAuth access token (stored redacted).

DEPUTY_BASE_URL

API mode

Your install origin, e.g. https://your-company.eu.deputy.com.

DEPUTY_CALENDAR_URL

iCal mode

Your personal iCal feed URL (token-free, roster-only, stored redacted).

DEPUTY_ALLOW_WRITES

No

false

Enable the write tools.

DEPUTY_ALLOW_CUSTOM_HOST

No

false

Allow a base URL host outside *.deputy.com (enterprise custom domains).

DEPUTY_CACHE_TTL

No

30

In-memory read-cache lifetime, seconds. 0 disables caching.

DEPUTY_TIMEOUT

No

30

Per-request HTTP timeout, seconds.

DEPUTY_MAX_RETRIES

No

3

Automatic retries on 429/5xx (with backoff).

DEPUTY_ENV_FILE

No

Path to a dotenv file to load DEPUTY_* values from.


CLI (bonus)

The same client ships as a small standalone CLI, for a quick check without an MCP client:

deputy-mcp whoami     # who you're authenticated as
deputy-mcp roster     # your roster (--team for everyone, --area ID to scope)
deputy-mcp who        # who's working right now
deputy-mcp next       # your next shift

Add --json for raw output. With no subcommand, deputy-mcp starts the MCP server.


Development

See CONTRIBUTING.md for setup, project layout, and the PR checklist. Short version:

uv sync
uv run pytest          # full suite, mocked, no live calls
uv run ruff check .
uv run mypy

The Deputy client has no MCP dependency and works standalone:

import asyncio
from deputy_mcp.client import DeputyClient

async def main() -> None:
    async with DeputyClient.from_env() as deputy:
        print(await deputy.next_shift())

asyncio.run(main())

Planned work lives in ROADMAP.md.

License

MIT © Augusto Bastos.

Available Tools

4 tools
deputy_get_my_calendar_urlA
Read-only

Return the signed-in user's personal Deputy calendar (iCal) subscription URL.

Deputy publishes a per-user, read-only iCal feed of your roster (the CalendarURL on /api/v1/me). Add the returned link to any calendar app (Google Calendar, Apple Calendar, Outlook) to see your shifts there; it stays in sync as your roster changes. Works at any access level — it reads only your own /me record.

When NOT to use: to read the shifts themselves here (use deputy_get_my_roster or deputy_next_shift) — this only returns the subscription link.

Returns markdown (the subscription link, or a note that this install exposes none) or, with response_format="json", an object {"calendar_url"} whose value is a string or null. In iCal mode the feed URL is the configured secret and is never printed; the tool confirms it is configured without revealing it.

ParametersJSON Schema
NameRequiredDescriptionDefault
response_formatNoOutput format: 'markdown' (human-readable, default) or 'json' (raw records).markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Although annotations already declare readOnlyHint=true, the description adds substantial behavioral context: it reads only the caller's own /me record, works at any access level, stays in sync with roster changes, returns markdown or a JSON object, and never prints the secret iCal feed URL. No contradiction with annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded, and every subsequent sentence adds distinct operational, security, or output-format context. There is no filler or redundant restatement of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description fully covers tool selection, read-only behavior, access-level guarantees, output format variants, null handling, and the security nuance around the secret iCal URL. An agent has everything needed to call this tool correctly and avoid misuse.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already fully documents response_format with enum values and a default description, so the baseline is 3. The description goes beyond by specifying the exact JSON shape ({'calendar_url'}), the null possibility, and the markdown-mode behavior, which adds meaningful semantic value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: return the signed-in user's personal Deputy calendar (iCal) subscription URL. It also explicitly distinguishes this from sibling tools like deputy_get_my_roster and deputy_next_shift, which read shifts rather than return a subscription link.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description contains an explicit 'When NOT to use' section that names the alternative tools for reading shifts and clarifies that this tool only returns the subscription link. This gives the agent clear selection criteria with no inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

deputy_get_my_rosterA
Read-only

List the signed-in user's own upcoming shifts in a date range.

Defaults to today through the next 7 days, computed in UTC; dates are ISO YYYY-MM-DD.

When NOT to use: for other people's shifts (use deputy_get_team_roster) or for worked time (use deputy_get_my_timesheets) — this returns your scheduled shifts.

Returns markdown (a shift list, times in the install timezone) or, with response_format="json", a list of Roster records. The output is identical whether the roster came from the Deputy API or, in iCal mode, from your calendar feed.

ParametersJSON Schema
NameRequiredDescriptionDefault
end_dateNoEnd date (ISO).
start_dateNoStart date (ISO).
response_formatNoOutput format: 'markdown' (human-readable, default) or 'json' (raw records).markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses the default date range, UTC computation, ISO date format, output format behavior, timezone rendering, and the source-agnostic nature of the output (Deputy API or iCal feed). It does not contradict the readOnlyHint/openWorldHint annotations and actually enriches them with meaningful runtime behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is organized with clear sections: what it does, defaults/format, when not to use, and return behavior. Every sentence carries useful information, and the most critical purpose statement is front-loaded. It is detailed without being bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, read-only, all-optional-parameter tool with a full output schema, this description covers everything an agent needs: the resource, the scope, default behavior, alternatives, output format selection, timezone handling, and data source nuance. No critical context is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already describes all 3 parameters with 100% coverage, so the description does not need to re-document them. It adds value by explaining the default range when start_date/end_date are omitted, and by describing what response_format changes about the returned output. Baseline is 3; the added context justifies 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List the signed-in user's own upcoming shifts in a date range.' It clearly distinguishes the tool from alternatives by naming deputy_get_team_roster and deputy_get_my_timesheets, and states what it does NOT return. This is unambiguous and immediately actionable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit 'When NOT to use' guidance names the sibling tools and the exact conditions that route elsewhere: other people's shifts go to deputy_get_team_roster, worked time goes to deputy_get_my_timesheets. It also specifies default behavior when date parameters are omitted, leaving no ambiguity about invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

deputy_next_shiftA
Read-only

Return the single next upcoming shift for an employee (name or id).

Omit 'employee' to get your own next shift. A name must resolve to exactly one active person; otherwise the matches are listed for you to retry by id.

When NOT to use: for a full range of upcoming shifts (use deputy_get_my_roster or deputy_search_shifts) — this returns only the earliest one.

Returns markdown (one shift, or a 'none scheduled' note) or, with response_format="json", a single Roster record or null. In iCal mode only your own next shift is available (naming another employee needs an API token).

ParametersJSON Schema
NameRequiredDescriptionDefault
employeeNoEmployee name or id.
response_formatNoOutput format: 'markdown' (human-readable, default) or 'json' (raw records).markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With readOnlyHint=true already covering safety, the description adds valuable behavioral context: ambiguous-name handling, markdown vs. json return semantics, the 'none scheduled' note, and the iCal-mode auth limitation. No contradiction with annotations is present.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose, then uses clear sections for usage and exclusions. Each sentence delivers distinct information—scope, edge cases, alternatives, and output behavior—with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has only two optional parameters and a read-only annotation. The description covers the essential usage scenarios, output formats, failure modes, and auth caveats. An output schema exists, so return value structure is already handled, making this complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema by explaining that a name must resolve to exactly one active person, that matches are listed for retry by id, and that json returns a single Roster record or null. This justifies a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Return the single next upcoming shift for an employee (name or id).' It clearly distinguishes itself from sibling tools by noting it returns only the earliest one, contrasting with deputy_get_my_roster and deputy_search_shifts for full ranges.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is an explicit 'When NOT to use' section naming alternatives (deputy_get_my_roster, deputy_search_shifts) and the condition that selects this tool. It also gives guidance on omitting 'employee' for your own shift and handling ambiguous names, leaving no inference burden on the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

deputy_whoamiA
Read-only

Verify the Deputy connection and confirm which identity the token uses.

Returns who the API token authenticates as, the company/location and its timezone, whether that user is clocked in right now (from their in-progress timesheet), and their personal iCal calendar subscription URL when the install exposes one. Run this first to confirm setup before other tools.

When NOT to use: to read schedules or people (use deputy_get_my_roster or deputy_get_employee_info) — this only checks the connection and identity.

Returns markdown (a connection summary: signed-in name, company, timezone, whether clocked in, and the calendar feed) or, with response_format="json", an object {"whoami", "company", "timezone", "company_name", "clocked_in", "calendar_url"} where clocked_in is a bool and calendar_url is a string or null. In iCal mode there is no API identity, so this reports mode=iCal and that only your roster is available.

ParametersJSON Schema
NameRequiredDescriptionDefault
response_formatNoOutput format: 'markdown' (human-readable, default) or 'json' (raw records).markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal read-only and open-world behavior, so the bar is lower. The description adds useful context: markdown vs JSON output, the exact JSON fields, clocked_in being a bool, calendar_url being nullable, and the special iCal mode with no API identity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well organized with clear paragraphs for purpose, usage, and return behavior. Some redundancy exists between the opening summary and the later markdown/JSON explanation, but each section adds detail and the purpose is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, one-optional-parameter read-only tool, this description covers the key aspects: what it returns, when to run it, when not to use it, alternatives, and a non-obvious iCal limitation. The output schema also exists to carry return-type details, so nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single response_format parameter, so the baseline is 3. The description adds value by explaining what json mode returns, including the object shape and field types, which is not fully captured by the schema's 'raw records' phrasing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Verify the Deputy connection and confirm which identity the token uses.' It also distinguishes itself from sibling schedule/people-reading tools by stating 'this only checks the connection and identity.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit guidance is given: 'Run this first to confirm setup before other tools.' The description also states when not to use it and names alternatives: 'to read schedules or people (use deputy_get_my_roster or deputy_get_employee_info).'

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 4 tool updatesv0.1.0
    • First observeddeputy_get_my_calendar_url
    • First observeddeputy_get_my_roster
    • First observeddeputy_next_shift
    • First observeddeputy_whoami

TDQS

A4.3/5.0

Scored across 4 tools

Disambiguation4/5

Each tool has a clear primary purpose, and the explicit 'When NOT to use' notes help separate roster listing from next-shift lookup. There is minor overlap where whoami also returns the calendar URL and next_shift is a single-item subset of the roster, but these are not likely to cause serious misselection.

Naming Consistency4/5

All tools share the deputy_ prefix and use snake_case, and three of the four follow a get_my_* pattern. deputy_whoami and deputy_next_shift break the verb-first convention, but the naming remains predictable and readable.

Tool Count4/5

Four tools is a reasonable, compact set for a personal roster/identity assistant. It feels slightly thin for a general Deputy integration, especially since several missing tools are referenced in descriptions, but the count itself is not excessive.

Completeness2/5

The self-service schedule workflow is covered, but the descriptions reference four tools that do not exist in this server: deputy_get_employee_info, deputy_get_team_roster, deputy_get_my_timesheets, and deputy_search_shifts. There are also no leave, timesheet, or shift-management tools, so common Deputy queries will hit dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers