tools

package
v1.3.0-rc.4 Latest Latest
Warning

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

Go to latest
Published: May 13, 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 added in v0.6.0

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 ApprovalAuditTrail

type ApprovalAuditTrail struct {
	State         string         `json:"state,omitempty"`
	UpdatedBy     string         `json:"updated_by,omitempty"`
	UpdatedByName string         `json:"updated_by_name,omitempty"`
	UpdatedAt     string         `json:"updated_at,omitempty"`
	Note          string         `json:"note,omitempty"`
	Creator       map[string]any `json:"creator,omitempty"`
	Source        string         `json:"source,omitempty"`
	Raw           map[string]any `json:"raw,omitempty"`
}

type ApprovalDurationTotals

type ApprovalDurationTotals struct {
	Approved *EntryDurationView `json:"approved,omitempty"`
	Pending  *EntryDurationView `json:"pending,omitempty"`
	Tracked  *EntryDurationView `json:"tracked,omitempty"`
	Billable *EntryDurationView `json:"billable,omitempty"`
	Break    *EntryDurationView `json:"break,omitempty"`
}

type ApprovalExpenseSummary

type ApprovalExpenseSummary struct {
	Count         int        `json:"count"`
	BillableCount int        `json:"billable_count,omitempty"`
	Amount        *MoneyView `json:"amount,omitempty"`
	Source        string     `json:"source"`
	Reason        string     `json:"reason,omitempty"`
}

type ApprovalMoneyTotals

type ApprovalMoneyTotals struct {
	Earned   *MoneyView `json:"earned,omitempty"`
	Cost     *MoneyView `json:"cost,omitempty"`
	Expenses *MoneyView `json:"expenses,omitempty"`
	Profit   *MoneyView `json:"profit,omitempty"`
	Source   string     `json:"source"`
	Reason   string     `json:"reason,omitempty"`
}

type ApprovalView

type ApprovalView struct {
	ID               string                          `json:"id,omitempty"`
	Request          map[string]any                  `json:"request,omitempty"`
	Owner            map[string]any                  `json:"owner,omitempty"`
	Creator          map[string]any                  `json:"creator,omitempty"`
	Status           map[string]any                  `json:"status,omitempty"`
	AuditTrail       *ApprovalAuditTrail             `json:"audit_trail,omitempty"`
	DateRange        any                             `json:"date_range,omitempty"`
	Totals           map[string]any                  `json:"totals,omitempty"`
	DurationTotals   ApprovalDurationTotals          `json:"duration_totals"`
	MoneyTotals      ApprovalMoneyTotals             `json:"money_totals"`
	Financials       EntryFinancials                 `json:"financials"`
	EntrySummary     ReportEntrySummary              `json:"entry_summary"`
	ExpenseSummary   ApprovalExpenseSummary          `json:"expense_summary"`
	ClientSummary    []ReportClientSummary           `json:"client_summary,omitempty"`
	Rollups          map[string][]ReportEntityRollup `json:"rollups,omitempty"`
	Entries          []ReportEntryView               `json:"entries,omitempty"`
	Expenses         []map[string]any                `json:"expenses,omitempty"`
	Actions          []string                        `json:"actions,omitempty"`
	SuggestedActions []ToolSuggestion                `json:"suggestedActions,omitempty"`
	Raw              map[string]any                  `json:"raw,omitempty"`
}

type AssignmentDurationView

type AssignmentDurationView struct {
	Seconds int64   `json:"seconds"`
	Hours   float64 `json:"hours"`
	Display string  `json:"display,omitempty"`
}

type AssignmentReportData

type AssignmentReportData struct {
	Range  FinancialRangeView     `json:"range"`
	Groups []string               `json:"groups"`
	Rows   []AssignmentReportRow  `json:"rows"`
	Totals AssignmentReportTotals `json:"totals"`
	Raw    map[string]any         `json:"raw,omitempty"`
}

type AssignmentReportMoney

type AssignmentReportMoney struct {
	Earned *MoneyView `json:"earned,omitempty"`
	Cost   *MoneyView `json:"cost,omitempty"`
	Profit *MoneyView `json:"profit,omitempty"`
	Source string     `json:"source"`
	Reason string     `json:"reason,omitempty"`
}

type AssignmentReportRow

type AssignmentReportRow struct {
	Title            string                 `json:"title"`
	GroupKey         map[string]string      `json:"group_key"`
	Entities         map[string]any         `json:"entities,omitempty"`
	Scheduled        AssignmentDurationView `json:"scheduled"`
	Available        AssignmentDurationView `json:"available"`
	AmountScheduled  *MoneyView             `json:"amount_scheduled,omitempty"`
	CostScheduled    *MoneyView             `json:"cost_scheduled,omitempty"`
	ExpectedProfit   *MoneyView             `json:"expected_profit,omitempty"`
	Tracked          AssignmentDurationView `json:"tracked"`
	AmountTracked    *MoneyView             `json:"amount_tracked,omitempty"`
	CostTracked      *MoneyView             `json:"cost_tracked,omitempty"`
	Difference       AssignmentDurationView `json:"difference"`
	AmountDifference *MoneyView             `json:"amount_difference,omitempty"`
	CostDifference   *MoneyView             `json:"cost_difference,omitempty"`
	RealizedProfit   *MoneyView             `json:"realized_profit,omitempty"`
	Status           string                 `json:"status,omitempty"`
	Financials       AssignmentReportMoney  `json:"financials"`
	Source           string                 `json:"source"`
	Warnings         []string               `json:"warnings,omitempty"`
	Raw              map[string]any         `json:"raw,omitempty"`
}

type AssignmentReportTotals

type AssignmentReportTotals struct {
	Scheduled        AssignmentDurationView `json:"scheduled"`
	Available        AssignmentDurationView `json:"available"`
	Tracked          AssignmentDurationView `json:"tracked"`
	Difference       AssignmentDurationView `json:"difference"`
	AmountScheduled  *MoneyView             `json:"amount_scheduled,omitempty"`
	CostScheduled    *MoneyView             `json:"cost_scheduled,omitempty"`
	ExpectedProfit   *MoneyView             `json:"expected_profit,omitempty"`
	AmountTracked    *MoneyView             `json:"amount_tracked,omitempty"`
	CostTracked      *MoneyView             `json:"cost_tracked,omitempty"`
	AmountDifference *MoneyView             `json:"amount_difference,omitempty"`
	CostDifference   *MoneyView             `json:"cost_difference,omitempty"`
	RealizedProfit   *MoneyView             `json:"realized_profit,omitempty"`
}

type AssignmentView

type AssignmentView map[string]any

type ClientApprovalSummary

type ClientApprovalSummary struct {
	Source                 string                       `json:"source"`
	Reason                 string                       `json:"reason,omitempty"`
	WithApprovalRequest    int                          `json:"with_approval_request,omitempty"`
	WithoutApprovalRequest int                          `json:"without_approval_request,omitempty"`
	RequestIDs             []string                     `json:"request_ids,omitempty"`
	States                 map[string]int               `json:"states,omitempty"`
	DurationsByState       map[string]EntryDurationView `json:"durations_by_state,omitempty"`
}

type ClientContactView

type ClientContactView struct {
	Email    string `json:"email,omitempty"`
	Address  string `json:"address,omitempty"`
	Note     string `json:"note,omitempty"`
	CCEmails any    `json:"ccEmails,omitempty"`
}

type ClientCurrencyView

type ClientCurrencyView struct {
	Code string `json:"code,omitempty"`
	ID   string `json:"id,omitempty"`
}

type ClientEntryHealth

type ClientEntryHealth struct {
	EntriesCount            int `json:"entries_count"`
	LockedCount             int `json:"locked_count,omitempty"`
	MissingDescriptionCount int `json:"missing_description_count,omitempty"`
	MissingProjectCount     int `json:"missing_project_count,omitempty"`
	MissingTaskCount        int `json:"missing_task_count,omitempty"`
}

type ClientInvoiceSummary

type ClientInvoiceSummary struct {
	TotalCount    int            `json:"total_count,omitempty"`
	ReturnedCount int            `json:"returned_count,omitempty"`
	Amount        *MoneyView     `json:"amount,omitempty"`
	Balance       *MoneyView     `json:"balance,omitempty"`
	Paid          *MoneyView     `json:"paid,omitempty"`
	OverdueCount  int            `json:"overdue_count,omitempty"`
	ByStatus      map[string]int `json:"by_status,omitempty"`
	Source        string         `json:"source"`
	Reason        string         `json:"reason,omitempty"`
}

type ClientProjectSummary

type ClientProjectSummary struct {
	Count         int  `json:"count"`
	ActiveCount   int  `json:"active_count,omitempty"`
	ArchivedCount int  `json:"archived_count,omitempty"`
	BillableCount int  `json:"billable_count,omitempty"`
	TasksCount    int  `json:"tasks_count,omitempty"`
	Truncated     bool `json:"truncated,omitempty"`
}

type ClientReportView

type ClientReportView struct {
	Client           ClientView         `json:"client"`
	Range            FinancialRangeView `json:"range"`
	Projects         []ProjectView      `json:"projects,omitempty"`
	Entries          []ReportEntryView  `json:"entries,omitempty"`
	EntryHealth      ClientEntryHealth  `json:"entry_health"`
	SuggestedActions []ToolSuggestion   `json:"suggestedActions,omitempty"`
	Warnings         []string           `json:"warnings,omitempty"`
}

type ClientTimeSummary

type ClientTimeSummary struct {
	TrackedDurationSeconds int64   `json:"tracked_duration_seconds,omitempty"`
	TrackedHours           float64 `json:"tracked_hours,omitempty"`
	TrackedDisplay         string  `json:"tracked_display,omitempty"`
	EntriesCount           int     `json:"entries_count,omitempty"`
	Source                 string  `json:"source"`
	Reason                 string  `json:"reason,omitempty"`
}

type ClientView

type ClientView struct {
	ID           string `json:"id"`
	Name         string `json:"name"`
	Address      string `json:"address,omitempty"`
	Archived     bool   `json:"archived,omitempty"`
	CCEmails     any    `json:"ccEmails,omitempty"`
	CurrencyCode string `json:"currencyCode,omitempty"`
	CurrencyID   string `json:"currencyId,omitempty"`
	Email        string `json:"email,omitempty"`
	Note         string `json:"note,omitempty"`
	WorkspaceID  string `json:"workspaceId,omitempty"`

	Currency        ClientCurrencyView    `json:"currency"`
	Contact         ClientContactView     `json:"contact"`
	ProjectSummary  ClientProjectSummary  `json:"project_summary"`
	Financials      ProjectFinancials     `json:"financials"`
	TimeSummary     ClientTimeSummary     `json:"time_summary"`
	InvoiceSummary  ClientInvoiceSummary  `json:"invoice_summary"`
	ApprovalSummary ClientApprovalSummary `json:"approval_summary"`
	Warnings        []string              `json:"warnings,omitempty"`
	Raw             map[string]any        `json:"raw,omitempty"`
}

type CustomFieldDefinitionView

type CustomFieldDefinitionView struct {
	ID         string         `json:"id,omitempty"`
	Name       string         `json:"name,omitempty"`
	Type       string         `json:"type,omitempty"`
	Status     string         `json:"status,omitempty"`
	EntityType string         `json:"entity_type,omitempty"`
	Source     string         `json:"source,omitempty"`
	Raw        map[string]any `json:"raw,omitempty"`
}

type CustomFieldValueView

type CustomFieldValueView struct {
	ID            string                     `json:"id,omitempty"`
	CustomFieldID string                     `json:"custom_field_id,omitempty"`
	Name          string                     `json:"name,omitempty"`
	Type          string                     `json:"type,omitempty"`
	Status        string                     `json:"status,omitempty"`
	EntityType    string                     `json:"entity_type,omitempty"`
	Value         any                        `json:"value,omitempty"`
	Source        string                     `json:"source"`
	Definition    *CustomFieldDefinitionView `json:"definition,omitempty"`
	Raw           map[string]any             `json:"raw,omitempty"`
}

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 DonutChartSegmentView

type DonutChartSegmentView struct {
	ID              string                `json:"id,omitempty"`
	Name            string                `json:"name,omitempty"`
	Percent         *float64              `json:"percent,omitempty"`
	Duration        *EntryDurationView    `json:"duration,omitempty"`
	Financials      EntryFinancials       `json:"financials"`
	MoneyByCurrency []MoneyByCurrencyView `json:"money_by_currency,omitempty"`
	Raw             map[string]any        `json:"raw,omitempty"`
}

type EffectiveRate

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

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 EntityChangeView

type EntityChangeView map[string]any

type EntityChangesData

type EntityChangesData struct {
	Kind    string             `json:"kind"`
	Types   []string           `json:"types,omitempty"`
	Changes []EntityChangeView `json:"changes"`
	Raw     []map[string]any   `json:"raw,omitempty"`
}

type EntryApprovalView

type EntryApprovalView struct {
	RequestID string         `json:"request_id,omitempty"`
	State     string         `json:"state,omitempty"`
	Source    string         `json:"source,omitempty"`
	Raw       map[string]any `json:"raw,omitempty"`
}

type EntryAuditView

type EntryAuditView struct {
	Locked             *bool          `json:"locked,omitempty"`
	MissingDescription *bool          `json:"missing_description,omitempty"`
	MissingProject     *bool          `json:"missing_project,omitempty"`
	MissingTask        *bool          `json:"missing_task,omitempty"`
	Source             string         `json:"source,omitempty"`
	Raw                map[string]any `json:"raw,omitempty"`
}

type EntryDurationView

type EntryDurationView struct {
	Seconds int64   `json:"seconds"`
	Hours   float64 `json:"hours"`
	Display string  `json:"display"`
	Source  string  `json:"source,omitempty"`
}

EntryDurationView is the normalized duration block used by report-derived entry views and summaries.

type EntryEntitiesView

type EntryEntitiesView struct {
	User    *EntryEntityRef  `json:"user,omitempty"`
	Client  *EntryEntityRef  `json:"client,omitempty"`
	Project *EntryEntityRef  `json:"project,omitempty"`
	Task    *EntryEntityRef  `json:"task,omitempty"`
	Tags    []EntryEntityRef `json:"tags,omitempty"`
}

type EntryEntityRef

type EntryEntityRef struct {
	ID    string         `json:"id,omitempty"`
	Name  string         `json:"name,omitempty"`
	Email string         `json:"email,omitempty"`
	Color string         `json:"color,omitempty"`
	Raw   map[string]any `json:"raw,omitempty"`
}

EntryEntityRef keeps entity IDs and names close to the entry that produced them without forcing callers to understand Clockify's varying row shapes.

type EntryFinancials

type EntryFinancials struct {
	Earned *MoneyView     `json:"earned,omitempty"`
	Cost   *MoneyView     `json:"cost,omitempty"`
	Profit *MoneyView     `json:"profit,omitempty"`
	Source string         `json:"source"`
	Reason string         `json:"reason,omitempty"`
	Rate   *EntryRateView `json:"rate,omitempty"`
}

type EntryInvoicingView

type EntryInvoicingView struct {
	Invoiced      *bool          `json:"invoiced,omitempty"`
	State         string         `json:"state,omitempty"`
	InvoiceID     string         `json:"invoice_id,omitempty"`
	InvoiceNumber string         `json:"invoice_number,omitempty"`
	Source        string         `json:"source,omitempty"`
	Raw           map[string]any `json:"raw,omitempty"`
}

type EntryRateView

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

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 EntryView

type EntryView struct {
	ID                string                 `json:"id"`
	Description       string                 `json:"description"`
	ProjectID         string                 `json:"projectId"`
	ProjectName       string                 `json:"projectName,omitempty"`
	TaskID            string                 `json:"taskId,omitempty"`
	TagIDs            []string               `json:"tagIds,omitempty"`
	Billable          bool                   `json:"billable,omitempty"`
	CostRate          *clockify.Rate         `json:"costRate,omitempty"`
	CustomFieldValues any                    `json:"customFieldValues,omitempty"`
	CustomFields      []CustomFieldValueView `json:"custom_fields_normalized,omitempty"`
	HourlyRate        *clockify.Rate         `json:"hourlyRate,omitempty"`
	IsLocked          bool                   `json:"isLocked,omitempty"`
	KioskID           string                 `json:"kioskId,omitempty"`
	Type              string                 `json:"type,omitempty"`
	UserID            string                 `json:"userId,omitempty"`
	WorkspaceID       string                 `json:"workspaceId,omitempty"`
	TimeInterval      clockify.TimeInterval  `json:"timeInterval"`
	Financials        EntryFinancials        `json:"financials"`
	Approval          *EntryApprovalView     `json:"approval,omitempty"`
	Invoicing         *EntryInvoicingView    `json:"invoicing,omitempty"`
	Entities          *EntryEntitiesView     `json:"entities,omitempty"`
	Audit             *EntryAuditView        `json:"audit,omitempty"`
}

EntryView is the model-facing time-entry envelope used by every tool that returns entries. It intentionally keeps the original clockify.TimeEntry JSON fields at the top level and appends a financials block so old clients keep working while agents can answer money questions without a second tool call.

type EstimateProgressView

type EstimateProgressView struct {
	TrackedDurationSeconds int64    `json:"tracked_duration_seconds"`
	EstimateSeconds        *int64   `json:"estimate_seconds,omitempty"`
	RemainingSeconds       *int64   `json:"remaining_seconds,omitempty"`
	PercentUsed            *float64 `json:"percent_used,omitempty"`
	OverEstimate           *bool    `json:"over_estimate,omitempty"`
	Source                 string   `json:"source"`
	Reason                 string   `json:"reason,omitempty"`
}

type ExpenseReportView

type ExpenseReportView struct {
	Expenses         []ExpenseView        `json:"expenses"`
	TotalsSummary    ExpenseTotalsSummary `json:"totals_summary"`
	ExpenseSummary   ExpenseSummary       `json:"expense_summary"`
	SuggestedActions []ToolSuggestion     `json:"suggestedActions,omitempty"`
	Raw              map[string]any       `json:"raw,omitempty"`
}

type ExpenseSummary

type ExpenseSummary struct {
	Count         int            `json:"count"`
	BillableCount int            `json:"billable_count,omitempty"`
	ByStatus      map[string]int `json:"by_status,omitempty"`
	ByCategory    map[string]int `json:"by_category,omitempty"`
	Amount        *MoneyView     `json:"amount,omitempty"`
	Source        string         `json:"source"`
	Reason        string         `json:"reason,omitempty"`
}

type ExpenseTotalsSummary

type ExpenseTotalsSummary struct {
	Rows   int        `json:"rows"`
	Amount *MoneyView `json:"amount,omitempty"`
	Raw    any        `json:"raw,omitempty"`
	Source string     `json:"source"`
}

type ExpenseView

type ExpenseView map[string]any

type FinancialRangeView

type FinancialRangeView struct {
	Start         string `json:"start,omitempty"`
	End           string `json:"end,omitempty"`
	DateRangeType string `json:"date_range_type,omitempty"`
	Timezone      string `json:"timezone,omitempty"`
}

type FindAndUpdateEntryData

type FindAndUpdateEntryData struct {
	Entry          EntryView               `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 added in v0.6.0

type IdentityData struct {
	User        clockify.User `json:"user"`
	UserView    *UserView     `json:"user_view,omitempty"`
	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 InvoiceItemView

type InvoiceItemView map[string]any

type InvoicePaymentView

type InvoicePaymentView map[string]any

type InvoiceReportView

type InvoiceReportView struct {
	Invoices         []InvoiceView  `json:"invoices"`
	AggregationScope string         `json:"aggregationScope"`
	PageTotalAmount  *MoneyView     `json:"pageTotalAmount,omitempty"`
	PageStatusCounts map[string]int `json:"pageStatusCounts,omitempty"`
	TotalAmount      *MoneyView     `json:"totalAmount,omitempty"`
	StatusCounts     map[string]int `json:"statusCounts,omitempty"`
	Summary          InvoiceSummary `json:"summary"`
	Raw              map[string]any `json:"raw,omitempty"`
}

type InvoiceSettingsView

type InvoiceSettingsView map[string]any

type InvoiceSummary

type InvoiceSummary struct {
	Count                 int            `json:"count"`
	ByStatus              map[string]int `json:"by_status,omitempty"`
	OverdueCount          int            `json:"overdue_count,omitempty"`
	ImportedTimeCount     int            `json:"imported_time_count,omitempty"`
	ImportedExpenseCount  int            `json:"imported_expense_count,omitempty"`
	Amount                *MoneyView     `json:"amount,omitempty"`
	Paid                  *MoneyView     `json:"paid,omitempty"`
	Balance               *MoneyView     `json:"balance,omitempty"`
	Currencies            []string       `json:"currencies,omitempty"`
	Source                string         `json:"source"`
	Reason                string         `json:"reason,omitempty"`
	SuggestedActionsCount int            `json:"suggested_actions_count,omitempty"`
}

type InvoiceView

type InvoiceView map[string]any

type LogTimeData added in v0.6.0

type LogTimeData struct {
	Entry           EntryView `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 MoneyByCurrencyView

type MoneyByCurrencyView struct {
	Type     string         `json:"type,omitempty"`
	Currency string         `json:"currency,omitempty"`
	Money    MoneyView      `json:"money"`
	Raw      map[string]any `json:"raw,omitempty"`
}

type MoneyView

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

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

func MoneyFromCents(cents int64, currency string) MoneyView

MoneyFromCents wraps an int64 cents value into a MoneyView.

func MoneyFromRate

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

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

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 ProjectEstimateView

type ProjectEstimateView struct {
	EstimateRaw         any        `json:"estimate_raw,omitempty"`
	BudgetEstimateRaw   any        `json:"budget_estimate_raw,omitempty"`
	TimeEstimateRaw     any        `json:"time_estimate_raw,omitempty"`
	EstimateResetRaw    any        `json:"estimate_reset_raw,omitempty"`
	DurationRaw         string     `json:"duration_raw,omitempty"`
	DurationSeconds     *int64     `json:"duration_seconds,omitempty"`
	EstimateSeconds     *int64     `json:"estimate_seconds,omitempty"`
	TimeEstimateSeconds *int64     `json:"time_estimate_seconds,omitempty"`
	BudgetEstimate      *MoneyView `json:"budget_estimate,omitempty"`
}

type ProjectFinancials

type ProjectFinancials struct {
	Earned *MoneyView          `json:"earned,omitempty"`
	Cost   *MoneyView          `json:"cost,omitempty"`
	Profit *MoneyView          `json:"profit,omitempty"`
	Source string              `json:"source"`
	Reason string              `json:"reason,omitempty"`
	Range  *FinancialRangeView `json:"range,omitempty"`
}

type ProjectMemberRateView

type ProjectMemberRateView struct {
	UserID           string         `json:"user_id"`
	TargetID         string         `json:"target_id,omitempty"`
	MembershipType   string         `json:"membership_type,omitempty"`
	MembershipStatus string         `json:"membership_status,omitempty"`
	HourlyRate       *clockify.Rate `json:"hourly_rate,omitempty"`
	CostRate         *clockify.Rate `json:"cost_rate,omitempty"`
	HourlyMoney      *MoneyView     `json:"hourly_money,omitempty"`
	CostMoney        *MoneyView     `json:"cost_money,omitempty"`
}

type ProjectRatesView

type ProjectRatesView struct {
	ProjectHourly      *clockify.Rate          `json:"project_hourly,omitempty"`
	ProjectCost        *clockify.Rate          `json:"project_cost,omitempty"`
	ProjectHourlyMoney *MoneyView              `json:"project_hourly_money,omitempty"`
	ProjectCostMoney   *MoneyView              `json:"project_cost_money,omitempty"`
	Members            []ProjectMemberRateView `json:"members,omitempty"`
	Tasks              []TaskRateView          `json:"tasks,omitempty"`
}

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 ProjectView

type ProjectView struct {
	ID                     string                       `json:"id"`
	Name                   string                       `json:"name"`
	ClientID               string                       `json:"clientId,omitempty"`
	ClientName             string                       `json:"clientName,omitempty"`
	Client                 any                          `json:"client,omitempty"`
	Color                  string                       `json:"color,omitempty"`
	Archived               bool                         `json:"archived"`
	Billable               bool                         `json:"billable,omitempty"`
	BudgetEstimate         any                          `json:"budgetEstimate,omitempty"`
	CostRate               *clockify.Rate               `json:"costRate,omitempty"`
	Currency               any                          `json:"currency,omitempty"`
	CustomFields           any                          `json:"customFields,omitempty"`
	CustomFieldsNormalized []CustomFieldValueView       `json:"custom_fields_normalized,omitempty"`
	Duration               string                       `json:"duration,omitempty"`
	Estimate               any                          `json:"estimate,omitempty"`
	EstimateReset          any                          `json:"estimateReset,omitempty"`
	Expenses               any                          `json:"expenses,omitempty"`
	Favorite               bool                         `json:"favorite,omitempty"`
	HourlyRate             *clockify.Rate               `json:"hourlyRate,omitempty"`
	Memberships            []clockify.ProjectMembership `json:"memberships,omitempty"`
	Note                   string                       `json:"note,omitempty"`
	Public                 bool                         `json:"public,omitempty"`
	Template               bool                         `json:"template,omitempty"`
	TimeEstimate           any                          `json:"timeEstimate,omitempty"`
	WorkspaceID            string                       `json:"workspaceId,omitempty"`

	Rates            ProjectRatesView     `json:"rates"`
	Financials       ProjectFinancials    `json:"financials"`
	Estimates        ProjectEstimateView  `json:"estimates"`
	EstimateProgress EstimateProgressView `json:"estimate_progress"`
	Tasks            []TaskView           `json:"tasks,omitempty"`
	ExpensesSummary  map[string]any       `json:"expenses_summary,omitempty"`
	RawHydrated      map[string]any       `json:"raw_hydrated,omitempty"`
}

type QuickReportData

type QuickReportData struct {
	Range               DateRange        `json:"range"`
	Totals              SummaryTotals    `json:"totals"`
	TopProject          *ProjectSummary  `json:"topProject,omitempty"`
	RunningEntries      []EntryView      `json:"runningEntries,omitempty"`
	EntriesSample       []EntryView      `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

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 ReportApprovalSummary

type ReportApprovalSummary struct {
	WithApprovalRequest    int                          `json:"with_approval_request,omitempty"`
	WithoutApprovalRequest int                          `json:"without_approval_request,omitempty"`
	RequestIDs             []string                     `json:"request_ids,omitempty"`
	States                 map[string]int               `json:"states,omitempty"`
	DurationsByState       map[string]EntryDurationView `json:"durations_by_state,omitempty"`
}

type ReportClientSummary

type ReportClientSummary struct {
	Client          EntryEntityRef        `json:"client"`
	EntrySummary    ReportEntrySummary    `json:"entry_summary"`
	Financials      EntryFinancials       `json:"financials"`
	ApprovalSummary ReportApprovalSummary `json:"approval_summary"`
}

type ReportDefaults

type ReportDefaults struct {
	Timezone              string `json:"timezone,omitempty"`
	WeekStart             string `json:"week_start,omitempty"`
	DateFormat            string `json:"date_format,omitempty"`
	TimeFormat            string `json:"time_format,omitempty"`
	SummaryReportSettings any    `json:"summary_report_settings,omitempty"`
	Source                string `json:"source,omitempty"`
}

type ReportEntityRollup

type ReportEntityRollup struct {
	ID       string            `json:"id,omitempty"`
	Name     string            `json:"name,omitempty"`
	Email    string            `json:"email,omitempty"`
	Color    string            `json:"color,omitempty"`
	Count    int               `json:"count"`
	Duration EntryDurationView `json:"duration"`
}

type ReportEntitySummary

type ReportEntitySummary struct {
	Users    []ReportEntityRollup `json:"users,omitempty"`
	Clients  []ReportEntityRollup `json:"clients,omitempty"`
	Projects []ReportEntityRollup `json:"projects,omitempty"`
	Tasks    []ReportEntityRollup `json:"tasks,omitempty"`
	Tags     []ReportEntityRollup `json:"tags,omitempty"`
}

type ReportEntrySummary

type ReportEntrySummary struct {
	Count                   int               `json:"count"`
	Duration                EntryDurationView `json:"duration"`
	BillableCount           int               `json:"billable_count,omitempty"`
	UnbillableCount         int               `json:"unbillable_count,omitempty"`
	LockedCount             int               `json:"locked_count,omitempty"`
	MissingDescriptionCount int               `json:"missing_description_count,omitempty"`
	MissingProjectCount     int               `json:"missing_project_count,omitempty"`
	MissingTaskCount        int               `json:"missing_task_count,omitempty"`
	ByType                  map[string]int    `json:"by_type,omitempty"`
}

type ReportEntryView

type ReportEntryView struct {
	ID                string                   `json:"id,omitempty"`
	Description       string                   `json:"description,omitempty"`
	Type              string                   `json:"type,omitempty"`
	Billable          *bool                    `json:"billable,omitempty"`
	Locked            *bool                    `json:"locked,omitempty"`
	Duration          *EntryDurationView       `json:"duration,omitempty"`
	TimeInterval      map[string]any           `json:"time_interval,omitempty"`
	Entities          *EntryEntitiesView       `json:"entities,omitempty"`
	CustomFieldValues any                      `json:"customFieldValues,omitempty"`
	CustomFields      []CustomFieldValueView   `json:"custom_fields_normalized,omitempty"`
	Approval          *EntryApprovalView       `json:"approval,omitempty"`
	Invoicing         *EntryInvoicingView      `json:"invoicing,omitempty"`
	Audit             *EntryAuditView          `json:"audit,omitempty"`
	Financials        EntryFinancials          `json:"financials"`
	RateBreakdown     *ReportRateBreakdownView `json:"rate_breakdown,omitempty"`
	MoneyByCurrency   []MoneyByCurrencyView    `json:"money_by_currency,omitempty"`
	Raw               map[string]any           `json:"raw,omitempty"`
}

type ReportGroupTotalsSummary

type ReportGroupTotalsSummary struct {
	Count       int               `json:"count"`
	Duration    EntryDurationView `json:"duration"`
	Financials  EntryFinancials   `json:"financials"`
	ByGroupType map[string]int    `json:"by_group_type,omitempty"`
}

type ReportRateBreakdownView

type ReportRateBreakdownView struct {
	Rate         *MoneyView     `json:"rate,omitempty"`
	Amount       *MoneyView     `json:"amount,omitempty"`
	EarnedAmount *MoneyView     `json:"earnedAmount,omitempty"`
	EarnedRate   *MoneyView     `json:"earnedRate,omitempty"`
	CostAmount   *MoneyView     `json:"costAmount,omitempty"`
	CostRate     *MoneyView     `json:"costRate,omitempty"`
	Currency     string         `json:"currency,omitempty"`
	Raw          map[string]any `json:"raw,omitempty"`
}

type ReportRollupView

type ReportRollupView struct {
	Group              string                `json:"group,omitempty"`
	Level              int                   `json:"level,omitempty"`
	ID                 string                `json:"id,omitempty"`
	Name               string                `json:"name,omitempty"`
	Duration           EntryDurationView     `json:"duration"`
	Entries            int                   `json:"entries,omitempty"`
	Financials         EntryFinancials       `json:"financials"`
	MoneyByCurrency    []MoneyByCurrencyView `json:"money_by_currency,omitempty"`
	WeeklyDayBreakdown []WeeklyDayTotalView  `json:"weekly_day_breakdown,omitempty"`
	Children           []ReportRollupView    `json:"children,omitempty"`
	Raw                map[string]any        `json:"raw,omitempty"`
}

type ReportTotalsSummary

type ReportTotalsSummary struct {
	Rows              int                   `json:"rows"`
	EntriesCount      int                   `json:"entries_count,omitempty"`
	TotalTime         *EntryDurationView    `json:"total_time,omitempty"`
	TotalBillableTime *EntryDurationView    `json:"total_billable_time,omitempty"`
	Financials        EntryFinancials       `json:"financials"`
	MoneyByCurrency   []MoneyByCurrencyView `json:"money_by_currency,omitempty"`
	Raw               any                   `json:"raw,omitempty"`
}

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
	// DocumentedAPIWrites enables generic probe_lab_api write/delete calls.
	// Runtime defaults this off for hosted profiles and on for local profiles.
	DocumentedAPIWrites bool
	// EntryFinancialReports forces entry financial enrichment to call the
	// reports host even when the client is pointed at a non-canonical base URL.
	// Production Clockify calls auto-enable this path; tests and local proxies
	// opt in explicitly so unrelated fake handlers do not receive surprise
	// reports-api requests.
	EntryFinancialReports bool
	// 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 added in v0.6.0

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

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

func (*Service) AssignmentReport

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

func (*Service) AttendanceReport

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) ClientReport

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

func (*Service) CreateClient added in v0.6.0

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 added in v0.6.0

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

func (*Service) CreateProjectFromTemplate

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 added in v0.6.0

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

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

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

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

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) GetClientWithArgs

func (s *Service) GetClientWithArgs(ctx context.Context, args map[string]any) (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

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, args map[string]any) (ResultEnvelope, error)

func (*Service) GetProjectTemplate

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

func (*Service) GetTag

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

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 added in v0.6.0

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) ListHolidaysInPeriod

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

func (*Service) ListInProgressTimeEntries

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

ListInProgressTimeEntries returns workspace-wide running timers.

func (*Service) ListProjectTemplates

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

func (*Service) ListProjects added in v0.6.0

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 added in v0.6.0

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) ListUserManagers

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

ListUserManagers returns managers assigned to a workspace user.

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) ListWebhookLogs

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

ListWebhookLogs returns delivery attempts for a webhook via the documented POST logs search route.

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 added in v0.6.0

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

func (*Service) LogTime added in v0.6.0

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

func (*Service) PolicyInfo added in v0.6.0

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 added in v0.6.0

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 added in v0.6.0

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

func (*Service) ResolveName

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 added in v0.6.0

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

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 added in v0.6.0

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 104 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

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

func (*Service) TodayEntries added in v0.6.0

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

TodayEntries returns time entries for the current day.

func (*Service) UpdateClient

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

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

UpdateMemberProfile updates live-supported workspace member profile fields.

func (*Service) UpdateProject

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

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

func (*Service) UpdateProjectTemplate

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

func (*Service) UpdateProjectUserRate

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

func (*Service) UpdateTag

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

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

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) UploadImage

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

func (*Service) WeeklySummary

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

func (*Service) WhoAmI added in v0.6.0

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

type SummaryData added in v0.6.0

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 TaskRateView

type TaskRateView struct {
	TaskID      string         `json:"task_id,omitempty"`
	TaskName    string         `json:"task_name,omitempty"`
	HourlyRate  *clockify.Rate `json:"hourly_rate,omitempty"`
	CostRate    *clockify.Rate `json:"cost_rate,omitempty"`
	HourlyMoney *MoneyView     `json:"hourly_money,omitempty"`
	CostMoney   *MoneyView     `json:"cost_money,omitempty"`
}

type TaskView

type TaskView struct {
	ID                     string                 `json:"id"`
	Name                   string                 `json:"name"`
	ProjectID              string                 `json:"projectId"`
	AssigneeID             string                 `json:"assigneeId,omitempty"`
	AssigneeIDs            []string               `json:"assigneeIds,omitempty"`
	Billable               bool                   `json:"billable"`
	BudgetEstimate         int64                  `json:"budgetEstimate,omitempty"`
	CostRate               *clockify.Rate         `json:"costRate,omitempty"`
	Duration               string                 `json:"duration,omitempty"`
	Estimate               string                 `json:"estimate,omitempty"`
	HourlyRate             *clockify.Rate         `json:"hourlyRate,omitempty"`
	Status                 string                 `json:"status,omitempty"`
	UserGroupIDs           []string               `json:"userGroupIds,omitempty"`
	CustomFieldsNormalized []CustomFieldValueView `json:"custom_fields_normalized,omitempty"`

	Rates            TaskRateView         `json:"rates"`
	Financials       ProjectFinancials    `json:"financials"`
	Estimates        ProjectEstimateView  `json:"estimates"`
	EstimateProgress EstimateProgressView `json:"estimate_progress"`
}

type Tier2Group added in v0.6.0

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

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

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 TimeOffBalanceView

type TimeOffBalanceView map[string]any

type TimeOffPolicyView

type TimeOffPolicyView map[string]any

type TimeOffRequestView

type TimeOffRequestView map[string]any

type TimerStatusData

type TimerStatusData struct {
	Running bool       `json:"running"`
	Entry   *EntryView `json:"entry,omitempty"`
	Elapsed string     `json:"elapsed,omitempty"`
}

type TimesheetFillGapData added in v1.2.1

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

type TimesheetIssue

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

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          []EntryView      `json:"entries,omitempty"`
}

type ToolSuggestion

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

type UserFeatureFlags

type UserFeatureFlags struct {
	Scheduling bool `json:"scheduling,omitempty"`
	Approval   bool `json:"approval,omitempty"`
	PTO        bool `json:"pto,omitempty"`
}

type UserView

type UserView struct {
	ID                     string                 `json:"id"`
	Name                   string                 `json:"name"`
	Email                  string                 `json:"email"`
	ActiveWorkspace        string                 `json:"activeWorkspace,omitempty"`
	CustomFields           any                    `json:"customFields,omitempty"`
	CustomFieldsNormalized []CustomFieldValueView `json:"custom_fields_normalized,omitempty"`
	DefaultWorkspace       string                 `json:"defaultWorkspace,omitempty"`
	Memberships            any                    `json:"memberships,omitempty"`
	ProfilePicture         string                 `json:"profilePicture,omitempty"`
	Settings               any                    `json:"settings,omitempty"`
	Status                 string                 `json:"status,omitempty"`
	ReportDefaults         ReportDefaults         `json:"report_defaults"`
	FeatureFlags           UserFeatureFlags       `json:"feature_flags"`
	Raw                    map[string]any         `json:"raw,omitempty"`
}

UserView preserves the upstream user fields while adding compact settings blocks that agents can use for report defaults and feature-aware wording.

type WebhookLogView

type WebhookLogView map[string]any

type WeeklyDayTotalView

type WeeklyDayTotalView struct {
	Date            string                `json:"date,omitempty"`
	Duration        EntryDurationView     `json:"duration"`
	Financials      EntryFinancials       `json:"financials"`
	MoneyByCurrency []MoneyByCurrencyView `json:"money_by_currency,omitempty"`
	Raw             map[string]any        `json:"raw,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 added in v0.6.0

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).

type WorkspaceSettings

type WorkspaceSettings struct {
	Currencies                any      `json:"currencies,omitempty"`
	Features                  []string `json:"features,omitempty"`
	FeaturePlan               string   `json:"feature_plan,omitempty"`
	DurationFormat            string   `json:"duration_format,omitempty"`
	CurrencyFormat            any      `json:"currency_format,omitempty"`
	NumberFormat              any      `json:"number_format,omitempty"`
	ProjectLabel              string   `json:"project_label,omitempty"`
	TaskLabel                 string   `json:"task_label,omitempty"`
	WorkingDays               any      `json:"working_days,omitempty"`
	LockPolicy                any      `json:"lock_policy,omitempty"`
	Rounding                  any      `json:"rounding,omitempty"`
	EntityCreationPermissions any      `json:"entity_creation_permissions,omitempty"`
	HasHourlyRate             bool     `json:"has_hourly_rate,omitempty"`
	HasCostRate               bool     `json:"has_cost_rate,omitempty"`
	MembershipsCount          int      `json:"memberships_count,omitempty"`
	Source                    string   `json:"source,omitempty"`
}

type WorkspaceView

type WorkspaceView struct {
	ID                      string            `json:"id"`
	Name                    string            `json:"name"`
	CakeOrganizationID      string            `json:"cakeOrganizationId,omitempty"`
	CostRate                *clockify.Rate    `json:"costRate,omitempty"`
	Currencies              any               `json:"currencies,omitempty"`
	FeatureSubscriptionType string            `json:"featureSubscriptionType,omitempty"`
	Features                []string          `json:"features,omitempty"`
	HourlyRate              *clockify.Rate    `json:"hourlyRate,omitempty"`
	ImageURL                string            `json:"imageUrl,omitempty"`
	Memberships             any               `json:"memberships,omitempty"`
	Subdomain               any               `json:"subdomain,omitempty"`
	WorkspaceSettings       any               `json:"workspaceSettings,omitempty"`
	SettingsSummary         WorkspaceSettings `json:"settings_summary"`
	Raw                     map[string]any    `json:"raw,omitempty"`
}

Jump to

Keyboard shortcuts

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