tools

package
v1.2.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2026 License: MIT Imports: 29 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Tier2Groups = map[string]Tier2Group{}

Tier2Groups is the global registry of Tier 2 tool groups.

Functions

func Tier2GroupForTool added in v1.2.1

func Tier2GroupForTool(toolName string) (string, bool)

func Tier2GroupNames added in v1.2.1

func Tier2GroupNames() []string

Types

type ActivationResult

type ActivationResult struct {
	Kind  string `json:"kind"`
	Name  string `json:"name"`
	Group string `json:"group,omitempty"`
	// ToolCount is len(ActivatedTools); kept as a separate field for
	// backwards compatibility with clients that read it directly.
	ToolCount int `json:"toolCount"`
	// ActivatedTools enumerates every tool name brought online by this
	// activation. For Tier-2 tool-name activations, this is the full
	// containing group — the LLM sees exactly what other capabilities
	// it just gained alongside the requested one. Empty for Tier-1
	// single-tool activation by design.
	ActivatedTools []string `json:"activatedTools,omitempty"`
	// TotalVisibleTools is the post-activation tools/list count after
	// bootstrap and policy filtering. Zero means the activator could not
	// compute the session total and activationPayload omits it.
	TotalVisibleTools int `json:"totalVisibleTools,omitempty"`
	// VisibleActivatedTools is ActivatedTools filtered through the same
	// post-activation tools/list visibility gate. nil preserves legacy
	// activation callbacks; non-nil means activationPayload should expose
	// this filtered set as activated_tools.
	VisibleActivatedTools []string `json:"visibleActivatedTools,omitempty"`
	// ActivatedToolsHiddenByBootstrap names activated tools that remained
	// hidden because the active bootstrap config did not expose them.
	ActivatedToolsHiddenByBootstrap []string `json:"activatedToolsHiddenByBootstrap,omitempty"`
	// ActivatedToolsBlockedByPolicy names activated tools that remained
	// hidden because policy enforcement filtered them from tools/list.
	ActivatedToolsBlockedByPolicy []string `json:"activatedToolsBlockedByPolicy,omitempty"`
}

ActivationResult is the payload returned by a Service activator (ActivateGroup / ActivateTool) describing which tools came online. The shape feeds activationPayload + activationMessage so the MCP response envelope carries a self-describing list of newly-visible tools rather than a bare "ok".

type DateRange

type DateRange struct {
	Start string `json:"start"`
	End   string `json:"end"`
}

DateRange is the inclusive [Start, End] window used by every summary / report payload to describe the period the rollup spans.

type DaySummary

type DaySummary struct {
	Date         string  `json:"date"`
	Entries      int     `json:"entries"`
	TotalSeconds int64   `json:"totalSeconds"`
	TotalHours   float64 `json:"totalHours"`
}

DaySummary is the per-day rollup row used by WeeklySummaryData. Date is RFC 3339 YYYY-MM-DD in the configured timezone.

type DeactivationResult added in v1.2.1

type DeactivationResult struct {
	Kind              string   `json:"kind"`
	Name              string   `json:"name"`
	Group             string   `json:"group,omitempty"`
	ToolCount         int      `json:"toolCount"`
	DeactivatedTools  []string `json:"deactivatedTools,omitempty"`
	TotalVisibleTools int      `json:"totalVisibleTools,omitempty"`
}

DeactivationResult mirrors ActivationResult for the deactivation path: the Service.DeactivateGroup callback returns one of these to describe which tools were removed from the visible tools/list.

type EffectiveRate added in v1.2.2

type EffectiveRate struct {
	Hourly      *clockify.Rate `json:"hourly,omitempty"`
	Cost        *clockify.Rate `json:"cost,omitempty"`
	HourlyScope RateScope      `json:"hourly_scope"`
	CostScope   RateScope      `json:"cost_scope"`
}

EffectiveRate is the resolved hourly + cost rate that should be applied to a given (workspace, project, task, entry, user) combination. The Scope fields tell the caller which layer of the hierarchy supplied the rate so the model can explain its answer.

func ResolveEffectiveRate added in v1.2.2

func ResolveEffectiveRate(
	ws *clockify.Workspace,
	proj *clockify.Project,
	task *clockify.Task,
	entry *clockify.TimeEntry,
	userID string,
) EffectiveRate

ResolveEffectiveRate walks the Clockify rate hierarchy:

entry > task > project-member (matched on userID) > project >
workspace-member (matched on userID) > workspace

Any of the inputs may be nil. The returned EffectiveRate.Scope is RateScopeNone when no layer supplied a rate. Hourly and Cost are resolved independently because a workspace can legitimately set a cost rate without a billable rate (and vice versa).

type EntryRateView added in v1.2.2

type EntryRateView struct {
	EntryHourly      *clockify.Rate `json:"entry_hourly,omitempty"`
	EntryCost        *clockify.Rate `json:"entry_cost,omitempty"`
	EffectiveHourly  *clockify.Rate `json:"effective_hourly,omitempty"`
	EffectiveCost    *clockify.Rate `json:"effective_cost,omitempty"`
	HourlyScope      RateScope      `json:"hourly_scope"`
	CostScope        RateScope      `json:"cost_scope"`
	DurationSeconds  int64          `json:"duration_seconds"`
	BillableEarnings MoneyView      `json:"billable_earnings,omitempty"`
	Cost             MoneyView      `json:"cost,omitempty"`
}

EntryRateView is the LLM-facing block we attach to every time-entry row across tool outputs. It bundles the raw entry-level rates (so the caller can see what Clockify itself stored) with the resolved effective rate and the derived per-entry money.

func BuildEntryRateView added in v1.2.2

func BuildEntryRateView(
	ws *clockify.Workspace,
	proj *clockify.Project,
	task *clockify.Task,
	entry *clockify.TimeEntry,
) EntryRateView

BuildEntryRateView is the canonical adapter from a (workspace, project, task, entry, user) tuple to the EntryRateView envelope. Callers pass whatever context they have; nils are tolerated.

type FindAndUpdateEntryData

type FindAndUpdateEntryData struct {
	Entry          clockify.TimeEntry      `json:"entry"`
	MatchedBy      map[string]any          `json:"matchedBy"`
	UpdatedFields  []string                `json:"updatedFields"`
	MatchedEntryID string                  `json:"matched_entry_id,omitempty"`
	Current        *TimeEntryUpdatePreview `json:"current,omitempty"`
	Proposed       map[string]any          `json:"proposed_changes,omitempty"`
	DryRun         bool                    `json:"dry_run,omitempty"`
	Note           string                  `json:"note,omitempty"`
}

FindAndUpdateEntryData is the structured payload for clockify_find_and_update_entry. Entry is the matched time entry; MatchedBy explains which finder predicate identified it; UpdatedFields lists the fields that actually changed. When dry_run:true is set, Current + Proposed + DryRun carry the preview-only diff so a downstream confirmation step can stage the mutation before applying.

type IdentityData

type IdentityData struct {
	User        clockify.User `json:"user"`
	WorkspaceID string        `json:"workspaceId"`
}

IdentityData pairs the upstream Clockify user with the resolved workspace so a single clockify_whoami response carries everything an agent needs to ground subsequent tool calls.

type LogTimeData

type LogTimeData struct {
	Entry           clockify.TimeEntry `json:"entry"`
	ResolvedProject string             `json:"resolvedProject,omitempty"`
}

LogTimeData is the structured payload for clockify_log_time. Entry is the created TimeEntry; ResolvedProject names the project the agent supplied (by name or ID) so the caller can confirm name resolution succeeded.

type MoneyView added in v1.2.2

type MoneyView struct {
	AmountCents   int64  `json:"amount_cents"`
	AmountDecimal string `json:"amount_decimal"`
	Currency      string `json:"currency,omitempty"`
	Display       string `json:"display,omitempty"`
}

MoneyView is the LLM-facing envelope for any monetary value the MCP surfaces. The model receives all four fields:

  • amount_cents: int64 minor units (authoritative).
  • amount_decimal: string, two dp, signed (audit / direct render).
  • currency: ISO code from the source.
  • display: pre-rendered symbol form (e.g. "€43.21 EUR").

Callers that have only a JSON-number from the reports host should use MoneyFromReportNumber; callers with an int-cents value (the primary API) should use MoneyFromCents.

func DerivedEarnings added in v1.2.2

func DerivedEarnings(eff EffectiveRate, durationSeconds int64) (billable, cost MoneyView)

DerivedEarnings multiplies the effective hourly + cost rates by the given duration (in seconds) and returns the per-entry billable earnings and cost as MoneyViews. Both come back zero when no rate is set for that side. Rounding is to the nearest cent.

Math: rate is cents-per-hour; duration is seconds; result is

cents = round(rateCents * durationSeconds / 3600)

We use float intermediates and math.Round for the final cent — matching `CentsFromReportNumber`'s half-away-from-zero behaviour so the MCP-derived number agrees with Clockify's own.

func MoneyFromCents added in v1.2.2

func MoneyFromCents(cents int64, currency string) MoneyView

MoneyFromCents wraps an int64 cents value into a MoneyView.

func MoneyFromRate added in v1.2.2

func MoneyFromRate(r *clockify.Rate) MoneyView

MoneyFromRate is a nil-tolerant adapter for `*clockify.Rate`. A nil rate or an inherited sentinel returns the zero MoneyView so callers can decide whether to emit the field at all.

func MoneyFromReportNumber added in v1.2.2

func MoneyFromReportNumber(v float64, currency string) MoneyView

MoneyFromReportNumber converts a JSON-number cents value coming from the reports.api host (always integer-cents-as-float in practice) to MoneyView. Banker's rounding to int64 cents.

func (MoneyView) IsZero added in v1.2.2

func (m MoneyView) IsZero() bool

IsZero reports whether the MoneyView carries no information. Used by tool envelopes to decide whether to omit a money field rather than emit "$0.00" when no rate is actually known.

type ProjectSummary

type ProjectSummary struct {
	ProjectID    string  `json:"projectId,omitempty"`
	ProjectName  string  `json:"projectName"`
	Entries      int     `json:"entries"`
	TotalSeconds int64   `json:"totalSeconds"`
	TotalHours   float64 `json:"totalHours"`
}

ProjectSummary is the per-project rollup row used by SummaryData and WeeklySummaryData. ProjectID is omitempty so entries that did not resolve to a project (e.g. tracked with no project tag) still appear in the rollup keyed only by ProjectName.

type QuickReportData

type QuickReportData struct {
	Range               DateRange            `json:"range"`
	Totals              SummaryTotals        `json:"totals"`
	TopProject          *ProjectSummary      `json:"topProject,omitempty"`
	RunningEntries      []clockify.TimeEntry `json:"runningEntries,omitempty"`
	EntriesSample       []clockify.TimeEntry `json:"entriesSample,omitempty"`
	ProjectsRepresented int                  `json:"projectsRepresented"`
	SuggestedActions    []ToolSuggestion     `json:"suggestedActions"`
}

QuickReportData powers clockify_quick_report: a single-glance snapshot with totals, the top project, any running entries, and a short entry sample so an agent can answer "what did I just do?" without a full detailed report round-trip.

type RateScope added in v1.2.2

type RateScope string

RateScope identifies which layer of the Clockify rate hierarchy supplied the effective rate for a given time entry. Returned to the model so it can explain *why* a particular earning amount is what it is, rather than only the final number.

const (
	RateScopeEntry         RateScope = "ENTRY"
	RateScopeTask          RateScope = "TASK"
	RateScopeProjectMember RateScope = "PROJECT_MEMBER"
	RateScopeProject       RateScope = "PROJECT"
	RateScopeWorkspace     RateScope = "WORKSPACE"
	RateScopeNone          RateScope = "NONE"
)

type ResultEnvelope

type ResultEnvelope struct {
	OK     bool           `json:"ok"`
	Action string         `json:"action"`
	Data   any            `json:"data,omitempty"`
	Meta   map[string]any `json:"meta,omitempty"`
}

ResultEnvelope is the canonical shape every Tier 1 / Tier 2 tool handler returns. OK is the boolean success flag, Action mirrors the tool name for client-side dispatch, Data carries the typed payload (struct or map) and Meta is reserved for cross-cutting metadata (pagination cursors, fingerprint hashes, etc.). Wire-locked by the per-tool outputSchemas in output_schemas.go; mutate this struct and every schemaFor[T] surface has to be reviewed for drift.

type Service

type Service struct {
	Client          *clockify.Client
	WorkspaceID     string
	DefaultTimezone *time.Location        // from CLOCKIFY_TIMEZONE; nil falls back to time.Now().Location() for flexible date/time inputs.
	DedupeConfig    *dedupe.Config        // optional, set during wiring
	PolicyDescribe  func() map[string]any // set during wiring; returns policy description
	Bootstrap       *bootstrap.Config     // set during wiring; describes current bootstrap visibility
	ActivateGroup   func(context.Context, string) (ActivationResult, error)
	ActivateTool    func(context.Context, string) (ActivationResult, error)
	DeactivateGroup func(context.Context, string) (DeactivationResult, error)
	GroupActivation func(string) (allowed bool, reason string)
	// WebhookValidateDNS, when true, makes CreateWebhook/UpdateWebhook
	// resolve the webhook host via the system resolver and reject any
	// reply that contains a private/reserved IP. Config defaults this
	// on for every profile so a hostname pointing at 169.254.169.254
	// (cloud-metadata) or 10.0.0.x cannot turn the Clockify webhook
	// delivery into an SSRF probe. Operators can explicitly opt out
	// for trusted air-gapped tests.
	WebhookValidateDNS bool
	// WebhookHostResolver overrides the LookupIPAddr call for tests.
	// nil = use net.DefaultResolver.
	WebhookHostResolver func(context.Context, string) ([]netip.Addr, error)
	// WebhookAllowedDomains is an optional escape-hatch list of webhook
	// hostnames that bypass the WebhookValidateDNS private-IP check.
	// Each entry is matched against the parsed URL's host (lowercased)
	// either by exact equality (`webhook.example.com`) or by suffix
	// when the entry begins with a dot (`.example.com` matches
	// `webhook.example.com` and `api.example.com` but NOT
	// `attacker.example.com.evil.com`). Empty list = no bypass; the
	// DNS check applies to every host. Operators use this to admit
	// known-trusted hostnames in split-horizon DNS environments where
	// the hostname legitimately resolves to a private IP only on the
	// control-plane network. See `docs/runbooks/webhook-dns-validation.md`
	// §4b for the use case. Production wiring (env var + Config field)
	// follows in a later commit; tests inject this field directly.
	WebhookAllowedDomains []string
	// Notifier delivers server→client notifications (progress, resource updates,
	// etc.) emitted by tool handlers. nil = drop silently.
	Notifier mcp.Notifier
	// EmitResourceUpdate publishes notifications/resources/updated for a URI
	// with an optional delta envelope. Wired from runtime.go to
	// Server.NotifyResourceUpdated so the subscription gate lives in the
	// protocol core rather than in every mutation handler. nil = drop silently
	// (tests without a Server wired).
	EmitResourceUpdate func(uri string, delta mcp.ResourceUpdateDelta)
	// SubscriptionGate reports whether any client is currently subscribed
	// to a URI. When wired (runtime.go sets it to
	// Server.HasResourceSubscription), emitResourceUpdate short-circuits
	// before the ReadResource round-trip so unsubscribed mutations don't
	// pay for a redundant fetch. nil = gate disabled; every emit pays for
	// the re-read (W3-era behaviour, preserved for tests).
	SubscriptionGate func(uri string) bool
	// ReportMaxEntries is the hard cap on the number of time entries a report
	// tool will aggregate. 0 disables the cap. Wired from CLOCKIFY_REPORT_MAX_ENTRIES.
	ReportMaxEntries int
	// DeltaFormat selects the diff algorithm for resource notifications.
	// "merge" (default) uses RFC 7396 merge patch; "jsonpatch" uses RFC 6902.
	DeltaFormat string
	// contains filtered or unexported fields
}

func New

func New(client *clockify.Client, workspaceID string) *Service

func (*Service) ActivateNamedTool added in v1.2.1

func (s *Service) ActivateNamedTool(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ActivateToolGroup added in v1.2.1

func (s *Service) ActivateToolGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) AddEntry

func (s *Service) AddEntry(ctx context.Context, args map[string]any) (ResultEnvelope, error)

AddEntry creates a new time entry.

func (*Service) AddUserToGroup

func (s *Service) AddUserToGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

AddUserToGroup adds a user to a user group.

func (*Service) ArchiveProjects

func (s *Service) ArchiveProjects(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) AssignProjectMemberships added in v1.2.2

func (s *Service) AssignProjectMemberships(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) AttendanceReport added in v1.2.2

func (s *Service) AttendanceReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CallDocumentedDeleteAPI added in v1.2.2

func (s *Service) CallDocumentedDeleteAPI(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CallDocumentedReadAPI added in v1.2.2

func (s *Service) CallDocumentedReadAPI(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CallDocumentedWriteAPI added in v1.2.2

func (s *Service) CallDocumentedWriteAPI(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateClient

func (s *Service) CreateClient(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateCustomField

func (s *Service) CreateCustomField(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateHoliday

func (s *Service) CreateHoliday(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateProject

func (s *Service) CreateProject(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateProjectFromTemplate added in v1.2.2

func (s *Service) CreateProjectFromTemplate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateProjectTemplate

func (s *Service) CreateProjectTemplate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateTag

func (s *Service) CreateTag(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateTask

func (s *Service) CreateTask(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateUserGroup

func (s *Service) CreateUserGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

CreateUserGroup creates a new user group.

func (*Service) CreateUserGroupAdmin

func (s *Service) CreateUserGroupAdmin(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) CreateWebhook

func (s *Service) CreateWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

CreateWebhook creates a new webhook with URL validation.

func (*Service) CurrentUser

func (s *Service) CurrentUser(ctx context.Context) (ResultEnvelope, error)

func (*Service) DeactivateToolGroup added in v1.2.1

func (s *Service) DeactivateToolGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) DeactivateUser

func (s *Service) DeactivateUser(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeactivateUser deactivates a user. Supports dry-run (confirm pattern).

func (*Service) DeleteClient added in v1.2.2

func (s *Service) DeleteClient(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteClient archives the client if it is still active, then deletes it. Clockify rejects DELETE on active clients (the active rule is the same as for projects), and the PUT archive validator additionally requires the existing name in the body. The implementation mirrors the rawArchiveAndDeleteClient cleanup helper in tests/.

func (*Service) DeleteCustomField

func (s *Service) DeleteCustomField(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) DeleteEntry

func (s *Service) DeleteEntry(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteEntry deletes a time entry by ID.

func (*Service) DeleteHoliday

func (s *Service) DeleteHoliday(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) DeleteProject added in v1.2.2

func (s *Service) DeleteProject(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteProject archives the project if still active, then deletes it. Clockify rejects DELETE on active projects (the archive validator additionally requires the existing name in the body). Mirrors clients.DeleteClient's archive-first pattern; both resources share the same upstream constraint.

func (*Service) DeleteTag added in v1.2.2

func (s *Service) DeleteTag(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteTag deletes a tag by ID or exact name. Clockify's DELETE /workspaces/{ws}/tags/{id} works directly on active tags — no archive step is required (unlike clients). Supports dry_run.

func (*Service) DeleteTask added in v1.2.2

func (s *Service) DeleteTask(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteTask deletes a task by project + task reference (ID or name). Clockify requires tasks to be DONE before DELETE, so active tasks are first updated with the existing full-replacement shape plus status=DONE.

func (*Service) DeleteUserGroup

func (s *Service) DeleteUserGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteUserGroup deletes a user group. Supports dry-run (minimal fallback).

func (*Service) DeleteUserGroupAdmin

func (s *Service) DeleteUserGroupAdmin(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) DeleteWebhook

func (s *Service) DeleteWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

DeleteWebhook deletes a webhook. Supports dry-run (preview via GET).

func (*Service) DetailedReport

func (s *Service) DetailedReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) EmitProgress

func (s *Service) EmitProgress(ctx context.Context, progress, total float64, message string)

EmitProgress publishes a notifications/progress if a progressToken was supplied with the current tools/call and the Service has a Notifier wired. No-op otherwise. total < 0 signals an indeterminate total.

func (*Service) FindAndUpdateEntry

func (s *Service) FindAndUpdateEntry(ctx context.Context, args map[string]any) (any, error)

func (*Service) GetClient added in v1.2.2

func (s *Service) GetClient(ctx context.Context, clientRef string) (ResultEnvelope, error)

func (*Service) GetCustomField

func (s *Service) GetCustomField(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetEntry

func (s *Service) GetEntry(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetEntry retrieves a single time entry by ID.

func (*Service) GetMemberProfile added in v1.2.5

func (s *Service) GetMemberProfile(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetMemberProfile returns a workspace-scoped member profile for a user.

func (*Service) GetProject

func (s *Service) GetProject(ctx context.Context, projectRef string) (ResultEnvelope, error)

func (*Service) GetProjectTemplate

func (s *Service) GetProjectTemplate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetTag added in v1.2.2

func (s *Service) GetTag(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetTag fetches a single tag by ID or exact name.

func (*Service) GetTask added in v1.2.2

func (s *Service) GetTask(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetTask fetches a single task by ID or exact name within a project. project (name or ID) and task (ID or name) are both required.

func (*Service) GetUserGroup

func (s *Service) GetUserGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) GetWebhook

func (s *Service) GetWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

GetWebhook retrieves a single webhook by ID.

func (*Service) GetWorkspace

func (s *Service) GetWorkspace(ctx context.Context) (ResultEnvelope, error)

func (*Service) ListClients

func (s *Service) ListClients(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListCustomFields

func (s *Service) ListCustomFields(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListDocumentedAPIOperations added in v1.2.2

func (s *Service) ListDocumentedAPIOperations(_ context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListEntries

func (s *Service) ListEntries(ctx context.Context, args map[string]any) (ResultEnvelope, error)

ListEntries returns recent time entries with optional filtering by date range, project, and pagination.

func (*Service) ListHolidays

func (s *Service) ListHolidays(ctx context.Context) (ResultEnvelope, error)

func (*Service) ListProjectTemplates

func (s *Service) ListProjectTemplates(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListProjects

func (s *Service) ListProjects(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListResourceTemplates

func (s *Service) ListResourceTemplates(_ context.Context) ([]mcp.ResourceTemplate, error)

ListResourceTemplates returns the parametric URI templates clients can dereference by substituting concrete IDs.

func (*Service) ListResources

func (s *Service) ListResources(ctx context.Context) ([]mcp.Resource, error)

ListResources returns a small, immediately-navigable set of concrete resources pinned to the Service's current workspace. Parametric resources (per-id entry, project, weekly report) live in ListResourceTemplates.

func (*Service) ListTags

func (s *Service) ListTags(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListTasks

func (s *Service) ListTasks(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListTools added in v1.2.1

func (s *Service) ListTools(_ context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListUserGroups

func (s *Service) ListUserGroups(ctx context.Context, args map[string]any) (ResultEnvelope, error)

ListUserGroups returns user groups for the workspace.

func (*Service) ListUserGroupsAdmin

func (s *Service) ListUserGroupsAdmin(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListUsers

func (s *Service) ListUsers(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ListWebhookEvents

func (s *Service) ListWebhookEvents(ctx context.Context, _ map[string]any) (ResultEnvelope, error)

ListWebhookEvents returns the static enum of webhook event types the Clockify webhooks API accepts. The upstream exposes no listing endpoint — see findings/webhooks.md (#15).

func (*Service) ListWebhooks

func (s *Service) ListWebhooks(ctx context.Context, args map[string]any) (ResultEnvelope, error)

ListWebhooks returns webhooks for the workspace.

func (*Service) ListWorkspaces

func (s *Service) ListWorkspaces(ctx context.Context) (ResultEnvelope, error)

func (*Service) LogTime

func (s *Service) LogTime(ctx context.Context, args map[string]any) (any, error)

func (*Service) PolicyInfo

func (s *Service) PolicyInfo(ctx context.Context) (ResultEnvelope, error)

func (*Service) QuickReport

func (s *Service) QuickReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ReadResource

func (s *Service) ReadResource(ctx context.Context, uri string) ([]mcp.ResourceContents, error)

ReadResource parses a clockify:// URI and fetches the underlying entity from Clockify, returning it as a single JSON-encoded ResourceContents entry. Unknown or malformed URIs return a -32602-equivalent error.

func (*Service) Registry

func (s *Service) Registry() []mcp.ToolDescriptor

func (*Service) RemoveUserFromGroup

func (s *Service) RemoveUserFromGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

RemoveUserFromGroup removes a user from a user group. Supports dry-run (minimal fallback).

func (*Service) ResolveDebug

func (s *Service) ResolveDebug(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ResolveName added in v1.2.1

func (s *Service) ResolveName(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) ResolveWorkspaceID

func (s *Service) ResolveWorkspaceID(ctx context.Context) (string, error)

func (*Service) SearchTools

func (s *Service) SearchTools(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) SetCustomFieldValue

func (s *Service) SetCustomFieldValue(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) SetProjectMemberships

func (s *Service) SetProjectMemberships(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) StartTimer

func (s *Service) StartTimer(ctx context.Context, projectID, projectRef, description string) (ResultEnvelope, error)

func (*Service) StartTimerArgs added in v1.2.1

func (s *Service) StartTimerArgs(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) StopTimer

func (s *Service) StopTimer(ctx context.Context, args map[string]any) (any, error)

func (*Service) SummaryReport

func (s *Service) SummaryReport(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) SwitchProject

func (s *Service) SwitchProject(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) TestWebhook

func (s *Service) TestWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

TestWebhook sends a test delivery to a webhook.

func (*Service) Tier2Handlers

func (s *Service) Tier2Handlers(groupName string) ([]mcp.ToolDescriptor, bool)

Tier2Handlers returns the descriptors for a named Tier 2 group. Every returned descriptor has its Tool.OutputSchema populated with at least envelopeOpaque so MCP clients see a consistent envelope shape across all 96 lazy-loaded tools.

func (*Service) TimerStatus

func (s *Service) TimerStatus(ctx context.Context) (ResultEnvelope, error)

func (*Service) TimesheetFillGap added in v1.2.1

func (s *Service) TimesheetFillGap(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) TimesheetReview added in v1.2.1

func (s *Service) TimesheetReview(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) TodayEntries

func (s *Service) TodayEntries(ctx context.Context, args map[string]any) (ResultEnvelope, error)

TodayEntries returns time entries for the current day.

func (*Service) UpdateClient added in v1.2.2

func (s *Service) UpdateClient(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateClient performs a fetch-then-merge update of a client. Clockify's PUT /clients/{id} is a full replacement (omitted fields get nulled server-side), so we GET the existing client, layer caller-provided changes over the fetched object, and PUT the complete merged shape back. Caller-supplied empty strings are treated as "do not change" (use the dedicated `archived` boolean flag to flip archival state).

func (*Service) UpdateCustomField

func (s *Service) UpdateCustomField(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateEntry

func (s *Service) UpdateEntry(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateEntry performs a fetch-then-update of a time entry, merging caller fields over the existing values.

func (*Service) UpdateMemberProfile added in v1.2.5

func (s *Service) UpdateMemberProfile(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateMemberProfile updates live-supported workspace member profile fields.

func (*Service) UpdateProject added in v1.2.2

func (s *Service) UpdateProject(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateProject performs a fetch-then-merge update of a project. Clockify's PUT /projects/{id} replaces the full record (omitted optional fields are nulled), so we GET the existing project, layer caller-provided changes over it, and PUT the merged shape back. Caller-supplied empty strings are treated as "do not change"; flip archival state through the dedicated `archived` boolean instead.

func (*Service) UpdateProjectEstimate

func (s *Service) UpdateProjectEstimate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateProjectMemberships added in v1.2.2

func (s *Service) UpdateProjectMemberships(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateProjectTemplate added in v1.2.2

func (s *Service) UpdateProjectTemplate(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateProjectUserRate added in v1.2.2

func (s *Service) UpdateProjectUserRate(ctx context.Context, args map[string]any, endpoint string) (ResultEnvelope, error)

func (*Service) UpdateTag added in v1.2.2

func (s *Service) UpdateTag(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateTag performs a fetch-then-merge update of a tag. Clockify's PUT /workspaces/{ws}/tags/{id} is a full replacement; we GET the existing tag, layer caller changes on top, then PUT the merged shape back. The archived boolean can be toggled explicitly.

func (*Service) UpdateTask added in v1.2.2

func (s *Service) UpdateTask(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateTask performs a fetch-then-merge update of a task. Clockify's PUT /projects/{pid}/tasks/{tid} is a full replacement; we GET the existing task, layer caller changes on top, then PUT the merged shape back. Empty-string caller args are treated as "no change".

func (*Service) UpdateTaskRate added in v1.2.2

func (s *Service) UpdateTaskRate(ctx context.Context, args map[string]any, endpoint string) (ResultEnvelope, error)

func (*Service) UpdateUserGroup

func (s *Service) UpdateUserGroup(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateUserGroup updates a user group's name.

func (*Service) UpdateUserGroupAdmin

func (s *Service) UpdateUserGroupAdmin(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) UpdateUserRole

func (s *Service) UpdateUserRole(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateUserRole updates a user's workspace role.

func (*Service) UpdateWebhook

func (s *Service) UpdateWebhook(ctx context.Context, args map[string]any) (ResultEnvelope, error)

UpdateWebhook updates an existing webhook.

func (*Service) WeeklySummary

func (s *Service) WeeklySummary(ctx context.Context, args map[string]any) (ResultEnvelope, error)

func (*Service) WhoAmI

func (s *Service) WhoAmI(ctx context.Context) (ResultEnvelope, error)

type SummaryData

type SummaryData struct {
	Range            DateRange            `json:"range"`
	Totals           SummaryTotals        `json:"totals"`
	ByProject        []ProjectSummary     `json:"byProject"`
	SuggestedActions []ToolSuggestion     `json:"suggestedActions"`
	Entries          []clockify.TimeEntry `json:"entries,omitempty"`
}

SummaryData is the structured payload for clockify_summary_report and clockify_detailed_report: per-project rollups plus optional raw entries. The WeeklySummaryData variant adds a per-day axis on top.

type SummaryTotals

type SummaryTotals struct {
	Entries        int     `json:"entries"`
	RunningEntries int     `json:"runningEntries"`
	TotalSeconds   int64   `json:"totalSeconds"`
	TotalHours     float64 `json:"totalHours"`
}

SummaryTotals aggregates entry counts and tracked time across the containing DateRange. RunningEntries is the subset of Entries that are still in progress (no End yet); TotalSeconds is the canonical duration, TotalHours is the convenience float derived from it.

type Tier2Group

type Tier2Group struct {
	Name        string
	Description string
	Keywords    []string
	ToolNames   []string
	Builder     func(s *Service) []mcp.ToolDescriptor
}

Tier2Group defines a lazily-activated group of related tools.

type TimeEntryDraft added in v1.2.1

type TimeEntryDraft struct {
	Start       string `json:"start"`
	End         string `json:"end"`
	ProjectID   string `json:"projectId,omitempty"`
	Project     string `json:"project,omitempty"`
	Description string `json:"description"`
	Billable    *bool  `json:"billable,omitempty"`
}

type TimeEntryRef added in v1.2.1

type TimeEntryRef struct {
	ID          string `json:"id"`
	Description string `json:"description,omitempty"`
	ProjectID   string `json:"projectId,omitempty"`
	ProjectName string `json:"projectName,omitempty"`
	Start       string `json:"start,omitempty"`
	End         string `json:"end,omitempty"`
}

type TimeEntryUpdatePreview added in v1.2.1

type TimeEntryUpdatePreview struct {
	Description string `json:"description"`
	ProjectID   string `json:"project_id,omitempty"`
	Start       string `json:"start,omitempty"`
	End         string `json:"end,omitempty"`
	Billable    bool   `json:"billable"`
}

TimeEntryUpdatePreview is the projected "current" shape of a time entry shown alongside a proposed-change diff during a dry-run update.

type TimesheetFillGapData added in v1.2.1

type TimesheetFillGapData struct {
	DryRun    bool               `json:"dryRun"`
	Proposed  TimeEntryDraft     `json:"proposed"`
	Entry     clockify.TimeEntry `json:"entry,omitempty"`
	Overlaps  []TimeEntryRef     `json:"overlaps,omitempty"`
	Validated bool               `json:"validated"`
}

type TimesheetIssue added in v1.2.1

type TimesheetIssue struct {
	Type            string   `json:"type"`
	Severity        string   `json:"severity"`
	Message         string   `json:"message"`
	EntryID         string   `json:"entryId,omitempty"`
	RelatedEntryIDs []string `json:"relatedEntryIds,omitempty"`
	Start           string   `json:"start,omitempty"`
	End             string   `json:"end,omitempty"`
}

type TimesheetReviewData added in v1.2.1

type TimesheetReviewData struct {
	Range            DateRange            `json:"range"`
	Totals           SummaryTotals        `json:"totals"`
	ByDay            []DaySummary         `json:"byDay"`
	ByProject        []ProjectSummary     `json:"byProject"`
	Issues           []TimesheetIssue     `json:"issues"`
	SuggestedActions []ToolSuggestion     `json:"suggestedActions"`
	Entries          []clockify.TimeEntry `json:"entries,omitempty"`
}

type ToolSuggestion added in v1.2.1

type ToolSuggestion struct {
	Tool        string         `json:"tool"`
	Reason      string         `json:"reason"`
	Arguments   map[string]any `json:"arguments,omitempty"`
	MissingArgs []string       `json:"missingArgs,omitempty"`
}

type WeeklySummaryData

type WeeklySummaryData struct {
	Range            DateRange            `json:"range"`
	Totals           SummaryTotals        `json:"totals"`
	ByDay            []DaySummary         `json:"byDay"`
	ByProject        []ProjectSummary     `json:"byProject"`
	SuggestedActions []ToolSuggestion     `json:"suggestedActions"`
	Entries          []clockify.TimeEntry `json:"entries,omitempty"`
	UnassignedKey    string               `json:"unassignedKey,omitempty"`
}

WeeklySummaryData is the structured payload for clockify_weekly_ summary: a date range, total counts, per-day and per-project rollups, suggested follow-up actions for the agent, and (optionally) the raw entries so callers can drill into specific records without a second round-trip.

type WorkspaceContext

type WorkspaceContext struct {
	WorkspaceID string `json:"workspaceId"`
}

WorkspaceContext is the lightweight envelope returned by clockify_get_workspace when the caller only needs the resolved workspace identifier (full workspace details live behind clockify_list_workspaces).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL