Skip to content
NeuroDock

mcp-chronometric

ToolWhat it takesWhat it returnsWhy your brain cares
get_time_contextnothinglocal time, day, session length, energy_zone bandremoves the executive-function tax of estimating how long you’ve been hyperfocused — the server tells you, you don’t have to guess
mark_session_start{ intent: string }session_id, started_at, optional auto-closed priormakes your intent durable across the model’s amnesia so a 3-hour session doesn’t drift from “draft the migration plan” into “tune the regex”
mark_session_endoptional summarysession_id, ended_at, ISO 8601 durationcloses the loop honestly; lets you see the real elapsed time instead of the time-blind estimate your brain produced
request_break_if_needed{ threshold_minutes }null OR { elapsed, prior_intent, suggested_action }a structured “you’ve been at this 90 minutes, you said 30” — quoted back in your own words, not a productivity lecture
idle_statusnothing{ consent_granted, os_idle_duration?, hyperfocus_signal }distinguishes “hyperfocused on another window” from “actually stepped away” so a nudge fires only when it’s useful

The hyperfocus check escalates across three rungs of elapsed session time. Defaults are 60 / 90 / 120 minutes; the profile can rebalance them.

flowchart LR
  nstart([Session start]) --> ng[60 min · gentle]
  ng --> nn[90 min · nudge]
  nn --> nh[120 min · hard]
  nstart -.-> nnone[under 60 · level: none]
  classDef gentle fill:#e6f4ea,stroke:#1b5e20,color:#1b5e20
  classDef nudge fill:#fff4e5,stroke:#7a4f01,color:#7a4f01
  classDef hard fill:#fde7e9,stroke:#7f1d1d,color:#7f1d1d
  classDef none fill:#eef2f7,stroke:#334155,color:#334155
  class ng gentle
  class nn nudge
  class nh hard
  class nnone none

When end_of_day_local is set, the same elapsed times after that clock-time read one rung harder (gentle becomes nudge; nudge becomes hard). That is the +30 and +60 collapse described in ADR 0001.

mcp-chronometric externalises time and session awareness so the LLM does not have to maintain that state across turns. It is the first substrate server and the precedent-setting design for every later substrate server.

  • Package: packages/mcp-chronometric/
  • Version: 0.0.2
  • Schemas: packages/mcp-chronometric/schemas/*.schema.json
  • ADR: 0001 — Chronometric tool design
  • Schema $id prefix: https://schemas.neurodock.org/mcp-chronometric/v0.1.0/
ToolInputOutput
get_time_contextnone{ now, day_of_week, time_since_last_prompt, current_session_length, energy_zone }
mark_session_start{ intent: string }{ session_id, started_at, auto_closed_prior_session? }
mark_session_end{ summary?: string }{ session_id, ended_at, duration }
request_break_if_needed{ threshold_minutes: integer }null OR { elapsed, prior_intent, suggested_action }
idle_statusnone{ consent_granted, os_idle_duration?, hyperfocus_signal }

Returns the current time context: wall-clock time, day of week, duration since the last prompt this server saw, length of the current open session, and a heuristic energy_zone bucket.

  • now — ISO 8601 with explicit timezone offset. Never naive.
  • energy_zone — enum: morning_peak | midday | afternoon_dip | evening_quiet | night_owl_caution | unknown. Computation is documented in ADR 0001.
  • Pure read. No side effects. Safe to call freely.

Anchors a unit of work with a stated intent. Returns a session_id (UUIDv4) and the start time. The intent string is preserved verbatim — skills like the hyperfocus nudge quote it back to the user.

If a prior session is still open, the server auto-closes it (configurable via chronometric.session_overlap_policy in the profile) and reports the auto-closed metadata in auto_closed_prior_session.

Closes the most recent open session. Takes an optional summary. Returns the session id, end time, and ISO 8601 duration.

The tool deliberately takes no session_id input — that would force the LLM to maintain state. The server tracks the active session.

Caller passes threshold_minutes. Returns null when no break is warranted, or a structured payload containing the elapsed time, the user’s verbatim prior intent, and a suggested_action enum.

null is a first-class return; callers MUST handle it.

Reads OS idle time, consent-gated. Without privacy.os_idle_consent: true in the profile, the tool returns a successful result with consent_granted: false and hyperfocus_signal: "unknown" — never an exception. Consent failures are not errors.

The hyperfocus_signal enum distinguishes hyperfocus-elsewhere (idle in this client but active on the system) from distraction-or-break (idle everywhere).

CodeMeaning
INTERNAL_CLOCK_UNAVAILABLEServer could not read system clock or timezone. Surfaced explicitly; never silent default.
PROFILE_UNREADABLEProfile YAML present but unparseable. energy_zone falls back to unknown when possible rather than failing the whole call.
SESSION_ALREADY_OPEN(Optional) mark_session_start called while a prior session is open and the profile says error instead of auto_close.
NO_OPEN_SESSIONmark_session_end called when no session is open.
INVALID_THRESHOLDrequest_break_if_needed received a non-positive threshold_minutes.
CONSENT_REQUIRED(Reserved) Future use only — idle_status does not raise this; it returns consent_granted: false instead.
  • Reads local profile and local session state only.
  • No remote calls.
  • The intent string passed to mark_session_start is treated as private user data. It is stored in the local session row and never logged in error payloads or telemetry.
  • Additive-only within the v0.1.x line.
  • Any rename, retype, removed enum value, or required-input addition is a major bump and ships under a new $id path (/v1.0.0/...).