# Epoch (npm · @kyanitelabs/epoch)

Epoch time estimation MCP server for PERT, COCOMO, Monte Carlo, calibration, cost, and risk.

- Trust score: 79/100 (medium)
- Change this week: 0
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- npm · `@kyanitelabs/epoch`: 79/100 (this document), [markdown](https://verifymcp.io/servers/tech-kyanitelabs-epoch/kyanitelabs-epoch.md), [page](https://verifymcp.io/servers/tech-kyanitelabs-epoch/kyanitelabs-epoch)

## Channel facts

- Registry: `npm`
- Package: `@kyanitelabs/epoch`
- Version: `0.6.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Supply Chain Security**: 98/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - 31 of 95 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 100/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to KyaniteLabs/Epoch).
  - Clear OSI-approved license (Apache-2.0).
  - Actively maintained (last published 8 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 64/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 5366 tokens (~206/item across 26 items; 26 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 26 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 26 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the Epoch MCP server?

Epoch runs locally as an npm package, launched with npx -y @kyanitelabs/epoch. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add tech-kyanitelabs-epoch -- npx -y @kyanitelabs/epoch
```

### Cursor

```json
{
  "mcpServers": {
    "tech-kyanitelabs-epoch": {
      "command": "npx",
      "args": [
        "-y",
        "@kyanitelabs/epoch"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "tech-kyanitelabs-epoch": {
      "command": "npx",
      "args": [
        "-y",
        "@kyanitelabs/epoch"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add tech-kyanitelabs-epoch -- npx -y @kyanitelabs/epoch
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "tech-kyanitelabs-epoch": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "@kyanitelabs/epoch"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add tech-kyanitelabs-epoch --command npx --arg -y --arg @kyanitelabs/epoch
```

### Hermes

```yaml
mcp_servers:
  tech-kyanitelabs-epoch:
    command: "npx"
    args: ["-y", "@kyanitelabs/epoch"]
```

### Netclaw

```json
{
  "McpServers": {
    "tech-kyanitelabs-epoch": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "@kyanitelabs/epoch"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add tech-kyanitelabs-epoch -t stdio -c npx -a -y @kyanitelabs/epoch
```

### Other

```json
{
  "mcpServers": {
    "tech-kyanitelabs-epoch": {
      "command": "npx",
      "args": [
        "-y",
        "@kyanitelabs/epoch"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-10-28 (score 79, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-10-27 (score 64)

First indexed and scored.

## MCP tools (26)

### `get_current_time` (~74 tokens)

Returns the current date and time in the specified IANA timezone. Useful for grounding the LLM in the user's local time. Example timezones: 'UTC', 'America/New_York', 'Europe/London', 'Asia/Tokyo'.

Input parameters:

- `timezone` (string): IANA timezone identifier. Defaults to "UTC".

### `convert_timezone` (~93 tokens)

Converts an ISO-8601 timestamp to a target IANA timezone. The input timestamp must include timezone information or be in UTC. Returns the localised time, UTC offset, and human-readable format. Use when you need to display or compare a moment in another region's local time.

Input parameters:

- `target_tz` (string, required): Target IANA timezone identifier.
- `timestamp` (string, required): ISO-8601 timestamp to convert.

### `parse_duration` (~120 tokens)

Parses a human-readable duration string into structured seconds. Supports combinations of y (years), mo (months), w (weeks), d (days), h (hours), m (minutes), s (seconds). Examples: '2h30m', '1d6h', '1w3d', '45m'. Returns the total seconds for the duration. Use when normalising a free-text duration for arithmetic or comparison.

Input parameters:

- `duration_string` (string, required): Duration string like "2h30m", "1d6h", "45m".

### `wait_bound` (~431 tokens)

Derives a deadline from the mechanism a wait actually rides (three-clock law v1.1 A2): fleet = k x cycle_seconds + PERT(turn) + 1 sd; world = PERT(turn) with a REQUIRED named external anchor; ceo = the named ladder rung (machine time never consumes a CEO rung). Returns the bound in seconds, the deadline in UTC and local (PT by default), and an envelope-ready TTL integer. Round human hours are unexamined slack.

Input parameters:

- `ceo_rung` (string): CEO only REQUIRED: ladder rung (pass=15m, burst=1h, sleep=1d, cycle=1wk, season=1mo). The rung IS the bound.
- `clock_class` (string, required): Which of the three clocks this wait rides: fleet = agent-only (mechanism cycle math), world = external 1:1 (requires external_anchor), ceo = the named ladder (requires ceo_rung). Three-clock law v1.1…
- `cycle_seconds` (number): Fleet only: the mechanism cycle in seconds the wait rides (org bus sweep = 40). Default 40.
- `cycles_k` (integer): Fleet only: cycle multiplier, 1..5 by law (more cycles = broken mechanism, not generous deadline). Default 2.
- `external_anchor` (string): World only REQUIRED: the named external event this wait is bound to (1:1, no dilation).
- `from_timestamp` (string): ISO 8601 start instant; omit for now.
- `time_zone` (string): IANA timezone for the rendered deadline. Default America/Los_Angeles (PT display law).
- `turn_most_likely_minutes` (number): Turn-time PERT most-likely in minutes. Default 45.
- `turn_optimistic_minutes` (number): Turn-time PERT optimistic in minutes. Default 15.
- `turn_pessimistic_minutes` (number): Turn-time PERT pessimistic in minutes (busy/turn-driven seats). Default 120.

### `time_math` (~129 tokens)

Performs compound time-math operations. Dispatches to the appropriate sub-operation based on the 'operation' parameter. Operations: add_days, add_business_days, diff, convert_tz, parse_nl, format_duration. Use this for multi-step or dynamic time operations; for single-purpose calls use get_current_time, convert_timezone, parse_duration, add_business_days, or count_business_days.

Input parameters:

- `operands` (object, required): Key-value pairs matching the chosen operation's expected fields. See operation documentation for required keys.
- `operation` (string, required): The time arithmetic operation to perform. Each operation expects specific operands.

### `add_business_days` (~154 tokens)

Adds N business (working) days to a start date, skipping weekends and country-specific public holidays. Supports US, UK, FR, DE, and JP holidays. Returns the resulting date. Use when computing a deadline that excludes non-working days.

Input parameters:

- `country` (string): ISO-3166-1-alpha-2 country code for holiday calendar. Supported holiday sets: US, UK, FR, DE, JP; other valid 2-letter codes fall back to weekend-only counting and say so in holidaySupport.
- `days` (integer, required): Number of business days to add (negative to subtract). Integer between -100000 and 100000.
- `start_date` (string, required): ISO date string for the start date.

### `count_business_days` (~145 tokens)

Counts the number of business (working) days between two dates, excluding weekends and country-specific public holidays. The count is exclusive of the start date and inclusive of the end date. Returns the integer day count. Use when measuring working-time span between two dates.

Input parameters:

- `country` (string): ISO-3166-1-alpha-2 country code for holiday calendar. Supported holiday sets: US, UK, FR, DE, JP; other valid 2-letter codes fall back to weekend-only counting and say so in holidaySupport.
- `end_date` (string, required): ISO date string for the end date.
- `start_date` (string, required): ISO date string for the start date.

### `pert_estimate` (~367 tokens)

Calculate PERT expected duration from three-point estimates using Beta distribution.

Formula: E = (O + 4M + P) / 6. Returns expected value, variance, standard deviation,
and 95%/99% confidence bounds with urgency categorization.
Use when estimating task duration with uncertain outcomes.

Input parameters:

- `ai_native`: Degree of AI assistance: 0.0 = fully human, 1.0 = fully AI-native, 0.5 = hybrid. Accepts boolean for backward compatibility (true=1.0, false=0.0).
- `complexity` (number): Optional complexity hint from 1 (trivial) to 5 (extreme). Reserved for future per-complexity correction-factor conditioning; not yet applied to the headline estimate.
- `most_likely` (number, required): Mode of the distribution — the single most probable outcome.
- `optimistic` (number, required): Best-case duration. Do NOT use your initial optimistic guess — this should be the absolute minimum if everything goes perfectly.
- `pessimistic` (number, required): Worst-case duration accounting for known risks and unknown unknowns.
- `project` (string): Optional project/repo identifier this estimate belongs to, for cross-project analytics.
- `session_id` (string): Optional session identifier (minted by a calling agent/hook) used to deduplicate repeated estimate calls for the same task within a session.
- `task_label` (string): Optional free-text label identifying the task this estimate is for (e.g. an issue key or short title). Surfaced on get_pending_estimates output for triage.
- `task_type` (string): Optional task type for feedback matching. Enables per-task-type accuracy tracking.
- `unit` (string): Time unit for all three PERT estimates.

### `cocomo_estimate` (~616 tokens)

LLM-adapted COCOMO II parametric effort estimation.

Replaces traditional 17 human-labor cost drivers with 5 LLM-specific factors:
reasoning complexity, context completeness, transformation impact, iterative cycles,
and human oversight. Returns both nominal and LLM-adjusted person-months. Use when estimating effort for a codebase you can size in KLOC.
iterative_cycles: values <= 2.0 are literal multipliers (0.5 = one-shot,
1.0 = typical debug loop, 2.0 = heavy back-and-forth); values above 2.0 are
literal cycle counts, each additional cycle adding 0.1 of multiplier anchored
at 2.0 (2.0 -> 2.0x, 3 -> 2.1x, 10 -> 2.8x) — monotonic with no cliff at 2.0.

Input parameters:

- `ai_native`: Degree of AI assistance: 0.0 = fully human, 1.0 = fully AI-native, 0.5 = hybrid. Accepts boolean for backward compatibility (true=1.0, false=0.0).
- `context_completeness` (number): How complete is the context provided to the LLM? 0.5 = exhaustive specs, 1.0 = typical, 2.0 = vague requirements.
- `human_oversight` (number): Human review overhead multiplier. 0.5 = auto-merged, 1.0 = standard PR review, 2.0 = compliance/security review.
- `iterative_cycles` (number): Iteration overhead multiplier or literal cycle count. Multiplier scale: 0.5 = one-shot, 1.0 = typical debug loop, 2.0 = heavy back-and-forth. Values above 2.0 are accepted as literal cycle counts and…
- `kloc` (number, required): Estimated thousands of lines of code. Count actual code, not comments/blank lines.
- `project` (string): Optional project/repo identifier this estimate belongs to, for cross-project analytics.
- `reasoning_complexity` (number): Multiplier for reasoning complexity of the codebase. 0.5 = trivial CRUD, 1.0 = average, 2.0 = novel algorithm/R&D.
- `session_id` (string): Optional session identifier (minted by a calling agent/hook) used to deduplicate repeated estimate calls for the same task within a session.
- `task_label` (string): Optional free-text label identifying the task this estimate is for (e.g. an issue key or short title). Surfaced on get_pending_estimates output for triage.
- `task_type` (string): Optional task type for feedback matching.
- `transformation_impact` (number): Scale of transformation relative to existing code. 0.5 = small patch, 1.0 = new module, 2.0 = architectural rewrite.

### `sprint_forecast` (~311 tokens)

Forecast sprint completion date from backlog size and historical velocity.

Computes average velocity from sprint history, converts story points to hours,
and returns required sprints with pessimistic estimate based on velocity variance. Use when planning a sprint completion date from backlog size and velocity history.

Input parameters:

- `ai_native`: Degree of AI assistance: 0.0 = fully human, 1.0 = fully AI-native, 0.5 = hybrid. Accepts boolean for backward compatibility (true=1.0, false=0.0).
- `backlog_points` (number, required): Total story points or effort units remaining in the backlog.
- `hours_per_sprint` (number): Total productive engineering hours available per sprint (accounts for meetings, overhead).
- `project` (string): Optional project/repo identifier this estimate belongs to, for cross-project analytics.
- `session_id` (string): Optional session identifier (minted by a calling agent/hook) used to deduplicate repeated estimate calls for the same task within a session.
- `sprint_length_days` (number): Calendar days in a single sprint cycle.
- `task_label` (string): Optional free-text label identifying the task this estimate is for (e.g. an issue key or short title). Surfaced on get_pending_estimates output for triage.
- `task_type` (string): Optional task type for feedback matching.
- `velocity_history` (array, required): Historical velocities from completed sprints. Minimum 1 data point; 3+ recommended for meaningful forecasts.

### `critical_path` (~211 tokens)

Compute critical path with merge-bias adjustment for project schedules.

Performs forward/backward pass to identify critical tasks and slack.
Applies merge bias: tasks with >2 predecessors get 5% duration increase per extra predecessor. Returns the critical path, task slack, and project duration. Use when sequencing dependent tasks to find the longest path and available slack.

Input parameters:

- `project` (string): Optional project/repo identifier this estimate belongs to, for cross-project analytics.
- `session_id` (string): Optional session identifier (minted by a calling agent/hook) used to deduplicate repeated estimate calls for the same task within a session.
- `task_label` (string): Optional free-text label identifying the task this estimate is for (e.g. an issue key or short title). Surfaced on get_pending_estimates output for triage.
- `task_type` (string): Optional task type for feedback matching.
- `tasks` (array, required): All tasks in the project graph. Each task must have a unique name.

### `monte_carlo_schedule` (~308 tokens)

Run Monte Carlo simulation for probabilistic schedule risk analysis.

Samples task durations from triangular distributions and returns P10/P50/P80/P95
completion estimates with identified risk events. Use seed for reproducible results.
Supply target_hours (working hours; durations are 8-hour days) to get
criticalPathProbability = P(total <= target_hours); without it that field is null.

Input parameters:

- `iterations` (number): Number of Monte Carlo simulation iterations (1–100,000). Higher = more stable percentiles.
- `project` (string): Optional project/repo identifier this estimate belongs to, for cross-project analytics.
- `seed` (integer): Optional seed for reproducible results.
- `session_id` (string): Optional session identifier (minted by a calling agent/hook) used to deduplicate repeated estimate calls for the same task within a session.
- `target_hours` (number): Optional deadline in working hours (task durations are in 8-hour days). When supplied, criticalPathProbability reports P(total <= target_hours); when omitted it is null instead of a fabricated value.
- `task_label` (string): Optional free-text label identifying the task this estimate is for (e.g. an issue key or short title). Surfaced on get_pending_estimates output for triage.
- `task_type` (string): Optional task type for feedback matching. Enables per-task-type accuracy tracking.
- `tasks` (array, required): Task list with PERT-style three-point estimates and dependency edges.

### `reference_class_estimate` (~361 tokens)

Data-driven estimate using reference class forecasting.

Applies historical correction factors based on actual-vs-estimated ratios.
When no historical data exists, uses industry averages (1.3-2.2x for software tasks).
Prioritize this over algorithmic models when historical data is available.

Input parameters:

- `ai_native`: Degree of AI assistance: 0.0 = fully human, 1.0 = fully AI-native, 0.5 = hybrid. Accepts boolean for backward compatibility (true=1.0, false=0.0).
- `complexity` (number): Fine-tuning complexity from 1 (trivial) to 5 (extreme). Adjusts within the scope band: low complexity shortens, high complexity lengthens the estimate.
- `project` (string): Optional project/repo identifier this estimate belongs to, for cross-project analytics.
- `scope` (string): Rough size of the task: small=tiny fix/tweak, medium=typical task, large=significant effort, xl=epic-scale. When omitted, inferred from complexity (1-2=small, 3=medium, 4=large, 5=xl).
- `session_id` (string): Optional session identifier (minted by a calling agent/hook) used to deduplicate repeated estimate calls for the same task within a session.
- `task_label` (string): Optional free-text label identifying the task this estimate is for (e.g. an issue key or short title). Surfaced on get_pending_estimates output for triage.
- `task_type` (string, required): Category of work being estimated for reference-class lookup.
- `team_id` (string): Optional team identifier to scope historical data to a specific team.

### `calibrate_estimates` (~117 tokens)

Recalculate team-specific correction factors from historical estimation data.

Compares estimated vs actual hours to compute a correction multiplier.
Requires PM system integration for best results. Returns recommendations
for improving estimation accuracy. Use when you have accumulated actuals and want to refresh team calibration factors.

Input parameters:

- `minimum_samples` (number): Minimum number of completed tasks required before producing a calibration factor.
- `period_days` (number): Lookback window in calendar days for calibration data.
- `team_id` (string, required): Team identifier whose historical accuracy data should be analysed.

### `token_time_bridge` (~276 tokens)

Map LLM token budgets to estimated wall-clock time.

Uses model-specific calibration data (tokens/second, reasoning overhead,
tool-call latency) to estimate how long a task will actually take.
Bridges the gap between token-space (how agents reason) and time-space (what humans need).
Use token_cost_estimate instead when dollar cost matters too.

Input parameters:

- `model` (string, required): LLM model identifier. Unknown models fall back to generic estimates.
- `project` (string): Optional project/repo identifier this estimate belongs to, for cross-project analytics.
- `reasoning_depth` (string): Expected depth of chain-of-thought reasoning. Deep reasoning adds significant per-token latency.
- `session_id` (string): Optional session identifier (minted by a calling agent/hook) used to deduplicate repeated estimate calls for the same task within a session.
- `task_label` (string): Optional free-text label identifying the task this estimate is for (e.g. an issue key or short title). Surfaced on get_pending_estimates output for triage.
- `task_type` (string): Optional task type for feedback matching.
- `tokens` (number, required): Total number of tokens in the LLM request (prompt + completion).
- `tool_calls` (number): Number of tool calls expected in the agentic loop. Each adds overhead latency.

### `token_cost_estimate` (~153 tokens)

Estimate wall-clock time AND dollar cost for LLM token usage.

Combines token-to-time mapping with model-specific pricing data.
Returns cost breakdown (input/output/overhead) alongside the time estimate.
Use token_time_bridge when you only need wall-clock time and not dollar cost.

Input parameters:

- `model` (string, required): LLM model identifier. Unknown models fall back to generic estimates.
- `reasoning_depth` (string): Expected depth of chain-of-thought reasoning.
- `task_type` (string): Optional task type for feedback matching.
- `tokens` (number, required): Total number of tokens in the LLM request (prompt + completion).
- `tool_calls` (number): Number of tool calls expected in the agentic loop.

### `compare_models` (~111 tokens)

Compare all LLM models side-by-side for a given token budget.

Ranks models by estimated cost or time. Shows quality tier for each model.
Use when choosing which model to use for a task.

Input parameters:

- `reasoning_depth` (string): Expected depth of chain-of-thought reasoning.
- `sort_by` (string): Sort models by cost (default) or estimated time.
- `tokens` (number, required): Total number of tokens to estimate across all models.
- `tool_calls` (number): Number of tool calls expected.

### `accuracy_trend` (~102 tokens)

Track estimation accuracy improvement over time.

Computes sliding-window MAPE and compares against industry baseline (25%).
Shows whether your estimates are improving, degrading, or stable.
Industry research shows estimation accuracy does NOT improve with experience (Cao 2022) — self-correcting systems like Epoch can buck this trend.

Input parameters:

- `team_id` (string): Optional team identifier to scope historical data.
- `window_size` (number): Number of records per sliding window.

### `schedule_risk` (~289 tokens)

Assess schedule risk for an estimate using historical accuracy data.

Computes confidence intervals (p50/p80/p95) based on your team's MAPE.
Returns risk level and actionable recommendations.
Uses industry baseline (25% MAPE) when no historical data is available.

Input parameters:

- `ai_native`: Degree of AI assistance: 0.0 = fully human, 1.0 = fully AI-native, 0.5 = hybrid. Accepts boolean for backward compatibility (true=1.0, false=0.0).
- `complexity` (number): Task complexity from 1 (trivial) to 5 (extreme). Higher complexity widens confidence intervals.
- `estimated_hours` (number, required): The estimated effort in hours to assess risk for.
- `project` (string): Optional project/repo identifier this estimate belongs to, for cross-project analytics.
- `session_id` (string): Optional session identifier (minted by a calling agent/hook) used to deduplicate repeated estimate calls for the same task within a session.
- `task_label` (string): Optional free-text label identifying the task this estimate is for (e.g. an issue key or short title). Surfaced on get_pending_estimates output for triage.
- `task_type` (string): Optional task type to refine historical accuracy lookup.
- `team_id` (string): Optional team identifier to scope historical data.

### `cocomo_validate` (~103 tokens)

Validate COCOMO estimation model against 195 real historical projects.

Runs the COCOMO Basic formula against projects from NASA93, COCOMO81, Albrecht, and Kemerer datasets.
Reports overall MAPE, bias, per-type accuracy, and recommended coefficient adjustments.
Use cocomo_ground_truth for the full multi-model benchmark across all COCOMO and AI-adjusted models.

Input parameters:

- `dataset_filter` (array): Optional filter to validate against specific datasets only.

### `cocomo_ground_truth` (~133 tokens)

Validate all COCOMO estimation models against 240 real historical projects with known effort.

Runs 6 models in parallel: COCOMO Basic, COCOMO II Nominal, COCOMO II + AI 12x speedup, and AI + developer profile at human/hybrid/ai_native gradients.
Reports MAPE, MMRE, PRED(25), PRED(50), bias per model, with breakdowns by dataset and project type.
Use cocomo_validate for a quicker Basic COCOMO-only validation pass.

Input parameters:

- `dataset_filter` (array): Optional filter to validate against specific datasets only.

### `record_actual` (~275 tokens)

Submit actual hours for a previous estimate to improve future accuracy.

Pairs with any estimation tool. The estimate_id comes from the estimate response.
Actuals feed into the self-improvement loop — after enough samples, correction factors
update automatically to reduce estimation bias.

Input parameters:

- `actual_hours` (number, required): Actual hours spent.
- `calibration_provenance` (string): Optional explicit provenance classification for this actual, consumed by the shared exclusion predicate (synthetic/smoke are excluded from calibration math). auto_wallclock marks a wall-clock-derived…
- `estimate_id` (string, required): ID of the estimate to update.
- `notes` (string): Optional context.
- `unit` (string): Unit actual_hours is expressed in. Normalized to hours at ingest (days=8h, weeks=40h workday convention, matching estimation.ts's toHours()). Defaults to hours when omitted.

### `get_pending_estimates` (~61 tokens)

List recent estimates that have not yet received actual-hour feedback.

Returns estimates awaiting actuals so you can submit feedback via record_actual.
Use this to close the estimation feedback loop and improve accuracy over time.

Input parameters:

- `limit` (integer): Max estimates to return.

### `batch_record_actuals` (~97 tokens)

Record actual hours for multiple estimates in a single call.

Efficient for bulk feedback submission — accepts 1 to 500 entries at once.
Each entry pairs an estimate ID with the actual hours spent. Returns total/succeeded/failed counts. Use when closing the feedback loop for many estimates at once; pass estimate_id values from get_pending_estimates.

Input parameters:

- `entries` (array, required): Array of actual-hour records (1–500 entries).

### `feedback_health` (~68 tokens)

Get a health report on the estimation feedback loop.

Shows total estimates, actuals, match rate, MAPE by tool and task type,
and self-improvement readiness (which types have enough data for auto-calibration). Use when checking whether you have enough recorded actuals for calibration to kick in.

### `estimate_from_context` (~261 tokens)

Classify a free-text task description and delegate to reference-class estimation.

Classifies task_type and complexity from free text (issue body, PR/diff
description, or task summary) using a LOCAL, deterministic keyword/signal
heuristic — no LLM call (see src/lib/context-estimate.ts). Caller-supplied
task_type/complexity hints always override the classification. Delegates the
resolved inputs to the same reference-class-forecasting path used by
reference_class_estimate, and returns classification provenance
(classified_task_type, classified_complexity, confidence, signals) alongside
the estimate so callers can judge how much to trust it.

Input parameters:

- `complexity` (number): Optional pre-assessed complexity hint (1-5); used once classification logic ships.
- `context` (string, required): Free-text context describing the task to estimate — issue body, PR/diff description, or task summary. Will be used to classify task_type and complexity and delegate to reference_class_estimate / PERT…
- `task_type` (string): Optional pre-classified task type hint; used once classification logic ships.
- `team_id` (string): Optional team identifier to scope historical data once classification logic ships.

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/tech-kyanitelabs-epoch/kyanitelabs-epoch#diagnostics

## Score history

- 2026-11-05: 79
- 2026-11-04: 79
- 2026-11-03: 79
- 2026-11-02: 79
- 2026-11-01: 79
- 2026-10-31: 79
- 2026-10-30: 79
- 2026-10-29: 79
- 2026-10-28: 79
- 2026-10-27: 64

## Common questions

### What is the Epoch MCP server?

Epoch is an MCP server listed in the public MCP registry as tech.kyanitelabs/epoch. Epoch time estimation MCP server for PERT, COCOMO, Monte Carlo, calibration, cost, and risk. This page covers its npm package (@kyanitelabs/epoch).

### Is the Epoch MCP server safe to use?

Epoch scores 79 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Epoch MCP server expose?

Epoch exposes 26 tools: get_current_time, convert_timezone, parse_duration, wait_bound, time_math, and 21 more. Their descriptions and schemas cost roughly 5,366 tokens of context every time the server is loaded.

### Is the Epoch MCP server still maintained?

Epoch is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the Epoch MCP server under?

Epoch declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/@kyanitelabs/epoch
- Socket report: https://socket.dev/npm/package/@kyanitelabs/epoch
- Repository: https://github.com/KyaniteLabs/Epoch
- Website: https://kyanitelabs.github.io/Epoch/
- Changelog RSS feed: https://verifymcp.io/servers/tech-kyanitelabs-epoch/kyanitelabs-epoch.xml
- Changelog JSON feed: https://verifymcp.io/servers/tech-kyanitelabs-epoch/kyanitelabs-epoch.json
- HTML version of this page: https://verifymcp.io/servers/tech-kyanitelabs-epoch/kyanitelabs-epoch
