Sandtime.io MCP Server

The Model Context Protocol (MCP) lets AI clients like Claude, ChatGPT, and Claude Code talk to Sandtime.io directly. Connect once and create, review, and report on time entries from the tools you already use.

What is MCP?

The Model Context Protocol is an open standard for connecting AI assistants to external tools and data. The Sandtime.io MCP server exposes your time tracking workspace - activities, projects, reports, timesheets, and more - as a set of tools an assistant can call on your behalf.

Read actions return clean, materialized data with formatted durations and local times. Destructive actions, like deleting a project or removing a member, deliberately hand off to a human by returning a deep link to the right page in the app.

New to logging time from your editor? See how developers use Sandtime.io day to day.

Need plain HTTP or cURL instead? See the REST API for the lower-level integration surface.

What you can ask

Talk to your assistant in plain language. It resolves the right user, project, and dates, then calls the tools for you.

Log 8 hours on the Acme project for yesterday.
Fill in last week with my usual hours and skip the public holiday.
What did I track this week, broken down by project?
Stop my running timer.
Build a report of billable hours by client for last month.
Which weeks are still locked on my timesheet?

Connect your assistant

Every client below talks to the same server, so the only thing that changes is where the entry goes. Replace YOUR_API_KEY with your own key.

Check your plan. Access to MCP can depend on the assistant and the plan you are on, which is outside Sandtime.io. If nothing connects even though the setup looks right, start by checking what your plan allows.

Create a key first. Keys come from Settings > Integrations > API in the app, or from Settings > Integrations > MCP. A key is shown once, at creation, and can be revoked any time from the API page.

Rather not connect anything?

Sandbot is the assistant built into Sandtime.io, so there is no connector, no server URL, and no client to configure. Ask it to log time, summarize your week, or pull a report from inside the app. AI time tracking covers what it does and how to switch it on.

Building an agent of your own? Many agentic systems work happily against the plain Sandtime.io REST API, authenticated with an API key you create in Settings > Integrations > API.

Claude Desktop

Claude Desktop connects to Sandtime.io through mcp-remote, which npx fetches on demand, so Node has to be on the machine. Everything else is one JSON file.

Open the config file

Claude Desktop opens it for you from Settings > Developer > Edit Config. If that menu is not there, or the file will not open, the direct path to the file is below.

macOS
~/Library/Application Support/Claude/claude_desktop_config.json
Windows
%APPDATA%\Claude\claude_desktop_config.json

Add the server

The file holds the rest of your Claude Desktop settings, so add to it rather than replacing it. Which snippet you need depends on whether the file already has an mcpServers block.

If there is no mcpServers block yet, add this as a new key next to your other settings, with a comma in between.

"mcpServers": {
  "sandtime": {
    "command": "npx",
    "args": [
      "mcp-remote",
      "https://mcp.sandtime.io/mcp",
      "--header",
      "Authorization:${AUTH}"
    ],
    "env": { "AUTH": "Bearer YOUR_API_KEY" }
  }
}

If mcpServers exists already, paste this inside it, with a comma before any server currently listed.

"sandtime": {
  "command": "npx",
  "args": [
    "mcp-remote",
    "https://mcp.sandtime.io/mcp",
    "--header",
    "Authorization:${AUTH}"
  ],
  "env": { "AUTH": "Bearer YOUR_API_KEY" }
}

A Windows gotcha

On Windows, check the Authorization:${AUTH} line above for a stray space. A space after the colon breaks the connection, and Claude Desktop returns a 401 authentication error that gives no clue why.

Restart, then check

MCP servers only load at startup and are never checked again, so the new one will not work until you quit the app completely and reopen it, not just close the window. Then ask it something simple about the app, like your projects or tracked hours. A sensible answer back means the key, the URL and the header are all fine.

A Claude Code session started inside the desktop app reads this same file, so one entry covers both the chat and the Code tab. The standalone CLI in your terminal does not read it and has its own section below.

Claude Code

For the CLI in your terminal. A Claude Code session started from inside the desktop app reads the desktop config instead, so use the Claude Desktop section above for that one. What separates the options below is their scope.

A project file that gets committed should reference an environment variable instead of a literal key. Set SANDTIME_API_KEY locally and use Bearer ${SANDTIME_API_KEY} for Authorization. Real keys should never live in a repository, so revoke and replace one if it ever ends up there.

Per user

Writes the configuration to ~/.claude.json (~ is %USERPROFILE% on Windows), so the server is waiting for you in every project you open on this machine.

claude mcp add --transport http --scope user sandtime https://mcp.sandtime.io/mcp --header "Authorization: Bearer YOUR_API_KEY"

Per project

The same command with --scope project, which writes .mcp.json in the current directory, so Claude Code only finds it in this one project. That file is meant to be committed. Prefer the per-user scope if you want the server available everywhere instead.

claude mcp add --transport http --scope project sandtime https://mcp.sandtime.io/mcp --header "Authorization: Bearer YOUR_API_KEY"

Manual installation

The entry is the same wherever it goes, only the file decides how far it reaches. Each of these files holds other settings too, so add to it rather than replacing it.

Per user (macOS, Linux)
~/.claude.json
Per user (Windows)
%USERPROFILE%\.claude.json
Per project
.mcp.json

If there is no mcpServers block yet, add this as a new key next to your other settings, with a comma in between.

"mcpServers": {
  "sandtime": {
    "type": "http",
    "url": "https://mcp.sandtime.io/mcp",
    "headers": {
      "Authorization": "Bearer YOUR_API_KEY"
    }
  }
}

If mcpServers exists already, paste this inside it, with a comma before any server currently listed.

"sandtime": {
  "type": "http",
  "url": "https://mcp.sandtime.io/mcp",
  "headers": {
    "Authorization": "Bearer YOUR_API_KEY"
  }
}

If something does not work, claude mcp list shows every server and whether it connected, which is the quickest way to tell a rejected key from a wrong URL. claude mcp remove sandtime takes the entry back out.

ChatGPT / Codex

For the ChatGPT desktop app, the Codex CLI, and the IDE extension, which share one configuration. ChatGPT on the web reads none of it, so nothing set up here reaches a browser conversation.

Or send this to your AI agent and it will set up the connection for you:

Set up the Sandtime.io MCP server for Codex. First run codex mcp get sandtime to check whether it already exists. If it does not, add it as a Streamable HTTP server at https://mcp.sandtime.io/mcp with the header Authorization set to "Bearer ${SANDTIME_API_KEY}". If SANDTIME_API_KEY is not set, ask me to create a Sandtime.io API key in Settings > Integrations > API and export it. Current Codex releases can reject OAuth, so use this API key path rather than browser sign-in.

Committing the project file? Use bearer_token_env_var with SANDTIME_API_KEY instead of a literal header. Real keys should never live in a repository, so revoke and replace one if it ever ends up there.

Connect a custom MCP

Open Settings > Plugins > MCPs, click Add, then Add MCP server to reach the connect screen. Pick Streamable HTTP over STDIO. The URL below goes in the address field, and the header name and value together under Headers. The screen also has Bearer token env var and Headers from environment variables fields, but those pass secrets a different way, so leave them empty.

URL
https://mcp.sandtime.io/mcp
Header name
Authorization
Header value
Bearer YOUR_API_KEY

Save and switch it on

Save, then switch the entry on in the list. Adding a server does not enable it. There is no scope to choose on this screen, so this always lands in the per-user file. A chat or task already open before you added the server will not see it either - start a new one. If the server still does not show up, restarting the app usually helps.

In config.toml, per user or per project

The same entry added by hand, appended to whatever the file already holds. The per-user file works the same way in the desktop app, the CLI, and the IDE extension. The per-project file is narrower: it only works in the CLI and the IDE extension, only in a project you trust.

Per user (macOS, Linux)
~/.codex/config.toml
Per user (Windows)
%USERPROFILE%\.codex\config.toml
Per project
.codex/config.toml
[mcp_servers.sandtime]
url = "https://mcp.sandtime.io/mcp"

[mcp_servers.sandtime.http_headers]
Authorization = "Bearer YOUR_API_KEY"

How the files layer

Project files are read from the repository root down to your current directory, with the closest one winning, and the per-user file underneath them all. If CODEX_HOME is set, the per-user file lives there instead of in your home directory.

The trust catch

Codex reads project files only in a project you have marked as trusted; in an untrusted one it skips them without saying anything. If a server never shows up, check trust before checking the config itself.

The codex mcp add command is no help for a key like this. It writes only to the per-user file, and it cannot set a static header at all, just the name of an environment variable to read later. That leaves the app screen and the file as the two ways in.

If the server still will not connect after this, turning on Developer mode in ChatGPT settings might fix it.

Any other client that speaks MCP over Streamable HTTP works the same way, as long as it can send a custom header. Ask your assistant to list your projects: if real project names come back, the connection is working.

Where it runs

One HTTP server, every AI surface you use. Connect once and work from wherever you already are.

Claude Code

Add the server to your .mcp.json and log time from the terminal where you ship code.

Claude Desktop

Connect the server and ask the desktop app to track and report your time.

Codex

Wire the server into Codex and turn coding sessions into clean time records.

Any MCP client

Any client that speaks the Model Context Protocol and supports HTTP servers with custom headers can connect.

Available tools

The server exposes 37 tools across your whole workspace. Assistants chain them together - for example, resolving the current user, checking the calendar, then filling empty days.

Activities

  • list_activitiesList time entries, filtered by user, project, or a whole week. Returns formatted durations and local times.
  • get_activityGet the full details of a single time entry by its ID.
  • create_activityLog a new time entry on a project, with automatic overlap detection against existing entries.
  • update_activityEdit a time entry’s name, times, project, or billable status, or stop and resume a running timer.
  • delete_activityPermanently remove a time entry. Requires ownership or administrator permissions.
  • stop_activityStop a running timer by setting its end time to now.

Projects

  • list_projectsList the projects in your organization, optionally including archived ones.
  • get_projectGet detailed information about a specific project.
  • create_projectCreate a new project. Requires administrator permissions.
  • update_projectRename a project, change its billable default, archive it, or edit its notes.
  • delete_projectReturns a deep link to the project settings, where a human confirms the deletion.

Project members

  • list_project_membersList the members assigned to a specific project.
  • add_project_memberReturns a deep link to the project members section, where a human adds the member.
  • remove_project_memberReturns a deep link to the project members section, where a human removes the member.

Users

  • list_usersList the users in your organization.
  • get_userGet detailed information about a specific user.
  • get_current_userGet the caller’s ID, timezone, and the server-resolved current date and week. Usually the first call in a workflow.
  • create_userReturns a deep link to the member invite page.
  • update_userReturns a deep link to the user profile page.
  • delete_userReturns a deep link to the delete account section. Removing a user is destructive, so the assistant hands it back to a human.

Organization

  • get_organizationGet information about your organization, including its settings.
  • update_organizationReturns a deep link to the organization settings page.
  • delete_organizationReturns a deep link to the organization settings page. This is the most destructive action in the product, so the assistant never performs it.

Calendar

  • get_calendarGet a server-computed calendar with workdays, expected hours, weekends, and public holidays. The source of truth before logging time across days.

Reports

  • list_reportsList the saved reports in your organization.
  • get_reportGet the details of a specific report.
  • create_reportBuild a saved report with custom dimensions, metrics, periods, and project or member filters.
  • update_reportChange a saved report by ID. Only the fields you pass are touched. Requires being its creator or an administrator.
  • delete_reportDelete a saved report by ID. It removes the report configuration only and leaves tracked time untouched.

Timesheets

  • get_timesheet_statusCheck the lock status of timesheets for a specific week.
  • lock_timesheetLock a week’s timesheet for a user. Requires administrator permissions.
  • unlock_timesheetRemove an existing timesheet lock. Requires administrator permissions.

Requests

  • list_requestsList approval requests such as timesheet unlocks and role changes. Defaults to pending requests.
  • request_timesheet_unlockAsk an administrator to unlock a locked week so the timesheet can be edited.
  • approve_unlock_requestApprove a pending unlock request, giving the user a short window to edit. Requires administrator permissions.
  • reject_unlock_requestReject a pending unlock request. The user is notified.

Summary and analytics

  • get_time_summarySummarize tracked time over a period, grouped by day, week, month, project, or user.

Try the AI features free

The MCP server and Sandbot are free for eligible organizations during early access. Tell us about your team and we will switch it on.

See the early access offer