MCP App Store
by KeenEthics

Overview

Connect your Duckhunt account to review incoming work, organize entries into tasks, and resume work with its notes and linked repositories. Uses Duckhunt's OAuth-protected MCP server and respects your workspace and agent preferences.

Tools

duckhunt-agent-config

ChatGPT
Reads what duckhunt agents may do for this user, and where. Inside an agent run, self is the run's own effective policy: tier, effective profile and its stored ceiling, the lock that forces read and the layer that set it, kit (shell, aws, file writes, memory, web, mcp tools), timeout, whether another turn would be accepted and whether the daily turn cap is reached. launch previews a new conversation from this workspace (or workspaceId) and repo: whether it can be launched and why not, default profile and its lock, timeout, daily caps with usage (max null = no cap set; ruleRuns = investigations launched by the user's automation rules against the daily limit the user sets, or the instance cap when it is stricter), and the machines that would run it. Also the instance limits for this user, the user's MCP behaviour settings, their machines (name, online, paused, accepts, capabilities, slots in use) and the repo keys they can use (provider, mode, default profile, mapped machines with health, linked workspaces). Each policy value carries the layer that decided it (instance, person, workspace, repo, runner, run). Use it before proposing or launching agent work. Read-only: the user changes agent policy in duckhunt settings, never over MCP.

duckhunt-agent-investigate

ChatGPT
Enqueues an investigation agent run on any entry (alert, ticket, PR, email…; the prompt adapts to its category): the duckhunt-runner daemon of the user, on their machine, claims it and launches claude code as a read-only conversation in an isolated worktree of the repo (read-only shell; read-only aws cli only for the entry account the machine maps; no web) with the duckhunt mcp; the verdict is stored in the run conversation and can be sent via push. Optional repo (ws/slug) and branch; without repo it is resolved from the entry (pr → its repo; attached target → target_repo; nightwatch app → its repo). Returns the reference of the enqueued run (r#N, to follow it with duckhunt-agent-run-get) or the skip reason (active_run: another copy of the same item is already being investigated, e.g. the same alert in another workspace; cooldown; daily_cap; daily_turn_cap). The user gets a launch alert on their devices for every run enqueued here.

duckhunt-agent-run-get

ChatGPT
Reads a whole agent run by its r#N reference: status, investigated entry, cost, and the full thread (the conversation between the agent and the user, the questions with their answer and the chain of continuations) and the similar earlier runs it was shown when it was launched (similarRuns). Use it when the user mentions a run in the conversation ("what happened with r#87?"): it is what is shown in /agents.

duckhunt-agent-run-list

ChatGPT
Agent runs of the user in the workspace of the token, most recent first: r#N reference, status, investigated entry, the target it was launched from and verdict in one sentence. Optional filters by status (several), source, provider of the entry and target (runs launched from it or on its attached entries, in any workspace). allWorkspaces=true lists the runs of ALL workspaces of the user. To read the whole conversation of one, duckhunt-agent-run-get.

duckhunt-attachment-add

ChatGPT
Uploads base64 content (dataBase64, also accepts a data-url data:...;base64,...) as an attachment of a task. ONLY for small content that you generate right here (a few KB: a note, a short diff). If the file is already on disk or weighs more than ~64 KB use duckhunt-attachment-upload-ticket: base64 goes through the conversation and costs ~1.4 characters per byte (a 100 KB png is ~137,000 characters, and they are paid twice if you also generate it with base64 in the terminal). 10 MB limit per file and subject to the storage quota of the task owner. Requires write permission on the task. contentType is optional: if omitted it is inferred from the filename extension (it matters so attachment-read later renders it as image/text). Attachments appear in duckhunt-attachment-list and in attachments of duckhunt-target-get. Returns the created metadata {id, filename, contentType, sizeBytes, url}.

duckhunt-attachment-delete

ChatGPT
Deletes an attachment by its id (the one from duckhunt-attachment-list): the metadata row + the blob. Requires write permission on the owning task. Idempotent on retries. Returns {ok, targetId}; error if it does not exist or without permission.

duckhunt-attachment-list

ChatGPT
Lists the attachments of a task: [{id, filename, contentType, sizeBytes, createdAt, url}]. It is the cheap way to find the id that duckhunt-attachment-read/delete need, instead of requesting the whole detail with duckhunt-target-get. [] if the task has no attachments. Does not return content.

duckhunt-attachment-read

ChatGPT
Reads the content of an attachment by its id (the one from duckhunt-attachment-list, or from attachments in duckhunt-target-get). Images are returned as an image block (directly visible); text files as plain text; everything else as a base64 binary resource. Use it to inspect a bug screenshot, a log or a file the user attached to the task. Requires read access to the owning task.

duckhunt-attachment-upload-ticket

ChatGPT
THIS is the way to attach a file that ALREADY EXISTS ON DISK (a screenshot, a log, a pdf, a binary): returns a single-use upload url and you upload the file with curl, without its bytes going through the conversation. Do NOT read the file or convert it to base64; with the url you only copy the command. Returns {uploadUrl, expiresInS, maxBytes, curl}: run curl (the field contains the ready command, just replace the path) and the 201 response gives you the metadata of the created attachment. The url expires in 5 minutes, works for ONE upload and is not valid for another file or another task: request one ticket per file. 10 MB limit and subject to the owner quota; requires write permission on the task (checked already when issuing the ticket). contentType is optional: if omitted it is inferred from the filename extension.

duckhunt-automation-create-archive-tasks

ChatGPT
Creates one automation rule to archive tasks. Archives the subject tasks. Available on target transitions or schedules with scan=targets. This call saves the rule; it does not execute the action immediately.

duckhunt-automation-create-attach-entry

ChatGPT
Creates one automation rule to attach entries. Attaches the matching entry to an owned task. Supply exactly one of targetId or match=jira_key. This call saves the rule; it does not execute the action immediately.

duckhunt-automation-create-create-task

ChatGPT
Creates one automation rule to create tasks. Creates a task when the entry or schedule trigger fires. attachTrigger also links the triggering entry. This call saves the rule; it does not execute the action immediately.

duckhunt-automation-create-investigate

ChatGPT
Creates one automation rule to investigate entries. Queues a read-only investigation of the triggering entry on the user runner using its type template. Saved disabled; the user enables it in Duckhunt. Posting the result to Jira is not supported by this tool. This call saves the rule; it does not execute the action immediately.

duckhunt-automation-create-notify

ChatGPT
Creates one automation rule to send notifications. Sends an in-app/push notification to the rule owner about the triggering entry. Requires an entry trigger. This call saves the rule; it does not execute the action immediately.

duckhunt-automation-create-run-prompt

ChatGPT
Creates one automation rule to run prompts. Queues the supplied prompt on the user runner with the read repository profile. The agent may change Duckhunt data through its allowed tools but cannot edit repository code. Anchored to the triggering entry/task, each scanned task, or no item on a schedule without scan. Saved disabled; the user enables it in Duckhunt. This call saves the rule; it does not execute the action immediately.

duckhunt-automation-create-suppress-event

ChatGPT
Creates one automation rule to suppress inbox events. Discards the matching inbox event and prevents its notification. Requires trigger=entry and triggerConfig.on=notified. This call saves the rule; it does not execute the action immediately.

duckhunt-automation-create-update-tasks

ChatGPT
Creates one automation rule to update tasks. Changes status, type, priority or labels of the subject tasks. Supply at least one change. A schedule requires scan=targets. This call saves the rule; it does not execute the action immediately.

duckhunt-automation-delete

ChatGPT
Deletes an automation rule you own (and its run log).

duckhunt-automation-list

ChatGPT
Reads saved automation rules owned by the user in the active workspace, including global rules. Returns their configuration and enabled/expired state. Does not execute, create, modify or enable rules. Each supported automation action has separate create/update tools with its full schema in tools/list. Use duckhunt-automation-runs to read execution history.

duckhunt-automation-runs

ChatGPT
Reads the latest 50 persisted execution records of one owned automation rule, newest first. Does not run or retry the rule.

duckhunt-automation-update-archive-tasks

ChatGPT
Updates one owned automation rule whose only action is to archive tasks. Archives the subject tasks. Available on target transitions or schedules with scan=targets. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.

duckhunt-automation-update-attach-entry

ChatGPT
Updates one owned automation rule whose only action is to attach entries. Attaches the matching entry to an owned task. Supply exactly one of targetId or match=jira_key. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.

duckhunt-automation-update-create-task

ChatGPT
Updates one owned automation rule whose only action is to create tasks. Creates a task when the entry or schedule trigger fires. attachTrigger also links the triggering entry. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.

duckhunt-automation-update-investigate

ChatGPT
Updates one owned automation rule whose only action is to investigate entries. Queues a read-only investigation of the triggering entry on the user runner using its type template. Saved disabled; the user enables it in Duckhunt. Posting the result to Jira is not supported by this tool. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.

duckhunt-automation-update-notify

ChatGPT
Updates one owned automation rule whose only action is to send notifications. Sends an in-app/push notification to the rule owner about the triggering entry. Requires an entry trigger. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.

duckhunt-automation-update-run-prompt

ChatGPT
Updates one owned automation rule whose only action is to run prompts. Queues the supplied prompt on the user runner with the read repository profile. The agent may change Duckhunt data through its allowed tools but cannot edit repository code. Anchored to the triggering entry/task, each scanned task, or no item on a schedule without scan. Saved disabled; the user enables it in Duckhunt. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.

duckhunt-automation-update-suppress-event

ChatGPT
Updates one owned automation rule whose only action is to suppress inbox events. Discards the matching inbox event and prevents its notification. Requires trigger=entry and triggerConfig.on=notified. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.

duckhunt-automation-update-update-tasks

ChatGPT
Updates one owned automation rule whose only action is to update tasks. Changes status, type, priority or labels of the subject tasks. Supply at least one change. A schedule requires scan=targets. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.

duckhunt-bitbucket-pr-comments

ChatGPT
Comments of the pr (lazy fetch from bitbucket). Paginated, sort=-created_on.

duckhunt-bitbucket-pr-tasks

ChatGPT
Tasks of the pr (checklist items with state UNRESOLVED|RESOLVED). A single page.

duckhunt-bitbucket-task-resolve

ChatGPT
Resolves (or reopens with resolved=false) a checklist task of a bitbucket pr. taskId comes from duckhunt-bitbucket-pr-tasks. Closes the loop of addressing review feedback.

duckhunt-brief

ChatGPT
Single-call orientation: in_progress tasks with their latest work note (handoff from the previous session) and blocked flag, what is due in the next 7 days, the number of unseen items in the inbox, and concurrentTasks (tasks that your OTHER agent connections are working RIGHT NOW: once you work a task, only the same task or tasks sharing one of its repos; before that, the ones in this workspace that declare repos, each with its repos — coordinate only if one is the repo you work in). Start here before target-list/inbox.

duckhunt-calendar-upcoming

ChatGPT
Upcoming agenda: calendar events (google calendar) of the workspace + targets with a due date, from today up to days days ahead (default 7, max 30).

duckhunt-code-commits

ChatGPT
Lists the commits of a code review entry (pr/mr): hash, message, author and date, newest first. Generic (bitbucket today). Useful to understand the scope of a pr before reviewing or commenting on it.

duckhunt-code-diff

ChatGPT
Unified diff (raw text) of a code review entry (pr/mr), capped at 200KB. Generic (bitbucket today). The basis for reviewing the changes and leaving comments with duckhunt-entry-comment.

duckhunt-daily-generate

ChatGPT
Generates (or regenerates) the daily note for a date (YYYY-MM-DD, default: today) from the kanban transitions, according to the config of the active workspace (in per-workspace scope there is one note per workspace). Stored as a duckhunt note (read or edit it with duckhunt-user-note-get/update using the returned noteId). Preserves user edits below the marker.

duckhunt-daily-list

ChatGPT
Lists the user's daily notes (stored as duckhunt notes, one per day, or per workspace and day in per-workspace scope), newest first

duckhunt-daily-preview

ChatGPT
Returns the markdown the daily note would generate for a date (YYYY-MM-DD, default: today) without writing anything. Respects the config of the active workspace (global vs per-workspace scope, filters, sections).

duckhunt-entry-claim

ChatGPT
Creates a new task with this entry attached. Returns the targetId.

duckhunt-entry-comment

ChatGPT
Comments on the entry (jira, bitbucket). Polymorphic by source. Email is read-only (does not support comments). To mention someone use the canonical syntax @[Name](accountid:ID) (resolve ids with duckhunt-mention-suggest); each provider translates it to its own format.

duckhunt-entry-comments

ChatGPT
Persisted comments of the entry (jira/bitbucket), in chronological order, with mentionsMe. Backfills live if needed.

duckhunt-entry-delete

ChatGPT
Deletes an entry you own: detaches it from its targets and removes its local data (extensions, comments, events, custom fields). Its agent conversations are kept (they move to a deleted-entry placeholder and stay in /agents). Hard delete WITHOUT tombstone: if the entry is still alive in its source (a jira issue still assigned, an email, a notion page still shared), the poller may re-ingest it later. Use it to clean up stale or orphaned entries, not to archive work in progress (for that, move/archive the target).

duckhunt-entry-field-options

ChatGPT
Selectable options for a field in its source. Without transitionId: editable field of the entry (assignable users, open sprints, project versions, labels, priorities, components; duedate has no options, use YYYY-MM-DD in set-field). With transitionId: field on the screen of THAT transition (field = the id returned by duckhunt-entry-list-transitions, e.g. resolution or customfield_10034), useful when its catalog does not fit entirely in the response (user directories). q filters. Supported according to the provider capabilities (jira today).

duckhunt-entry-file-list

ChatGPT
Lists the files hanging from the SOURCE of an entry: attachments of an email (including the images pasted in the body, inline: true), attachments of a jira ticket or files of a slack message. They are not stored in duckhunt: they live in the source and are read on-demand. Returns [{ref, filename, contentType, sizeBytes, inline, from}]; ref is opaque and is what duckhunt-entry-file-read/save accept. [] if the source has no files. Use it when the ticket or the email mention a screenshot, a log or a pdf you need to look at.

duckhunt-entry-file-read

ChatGPT
Reads a file from the source of an entry by its ref (from duckhunt-entry-file-list). It is downloaded from the mailbox/jira/slack at that moment, so it requires the connection to still be alive. Images are returned as an image block (you can SEE THEM: bug screenshots, mockups, charts), text files as plain text and everything else as a base64 binary resource. Maximum 25 MB. If the file must stay in the task, use duckhunt-entry-file-save.

duckhunt-entry-file-save

ChatGPT
Saves a file from the source as an attachment of a task: downloads it and persists it in duckhunt (from then on it is read with duckhunt-attachment-read and appears in attachments of duckhunt-target-get). Use it when the file should stay with the task (a contract, a specification, the bug screenshot) instead of reading it once. 10 MB limit and subject to the quota of the task owner; requires write permission on it. Returns the created metadata.

duckhunt-entry-get

ChatGPT
Returns an entry with its context: per-source extension, tasks it belongs to, custom fields (with their value), its work notes, the latest agent runs on it (agentRuns: r#N, status and verdict; the whole thread with duckhunt-agent-run-get) and earlier runs on other entries that look alike (similarRuns: same exception, table, alarm family, ticket key or title, with how they match and their verdict; data from other runs, it may not apply). id accepts the numeric local id or an external id: a jira key (OKT-123), an already ingested linear identifier (ENG-123), a linear url (linear.app/<org>/issue/ENG-123) or a figma url (figma.com/design/...); if it is not imported yet, it fetches it from the source and saves it silently (figma requires a figma connection of the user; returns file metadata: name, project, editor, thumbnail, last edit). For emails, body is the full compacted thread (all messages, not just the snippet) and emailThread exposes the structured per-message version, both served from the local cache; each message lists its attachments in attachments (filename, contentType, sizeBytes, index); the content is read with duckhunt-entry-file-read, whose ref for an email is <messageId>#<index> (or ask duckhunt-entry-file-list for them already built). Images pasted in the body also appear there (inline: true + contentId), and the body references them as ![alt](cid:<contentId>): if you need to SEE a screenshot from the email, match that contentId with the attachment and read it by that ref.

duckhunt-entry-list

ChatGPT
Lists entries (polled items) of the workspace bound to the token. Filters: category (tickets/code/email/notes/monitoring) or provider (jira/bitbucket/gmail/...), mutually exclusive; provider wins if both are given. status, q, unclaimed. allWorkspaces=true aggregates ALL workspaces of the user (each item carries workspaceId).

duckhunt-entry-list-transitions

ChatGPT
Lists the transitions available for the entry. Each one includes fields: the fields the workflow asks for when applying it (resolution when closing, etc.) with their options and currentValue (what the issue already has; a required field with a currentValue can be omitted); the required ones are passed in duckhunt-entry-transition.fields.

duckhunt-entry-set-description

ChatGPT
REPLACES the whole description of the entry in its source (jira, bitbucket/github pr). Markdown; each provider converts it to its own format. Refreshes the local cache after the write.

duckhunt-entry-set-field

ChatGPT
Writes a field of the entry in its source (jira today): assignee (accountId), priority (id), sprint (numeric id), duedate (YYYY-MM-DD), estimate/remainingEstimate (jira duration "2w 3d 4h 30m") with string|null (null clears); labels (names), fixVersions/affectsVersions/components (ids) with an array of strings REPLACING the whole set. The ids come from duckhunt-entry-field-options. Refreshes the local cache after the write.

duckhunt-entry-set-title

ChatGPT
Renames the entry by writing to its source (jira summary, bitbucket/github pr title, github issue). Refreshes the local cache after the write.

duckhunt-entry-suggestions

ChatGPT
Suggests entries related to this one (same external_id, or ticket keys mentioned in its title or note content)

duckhunt-entry-transition

ChatGPT
Applies a transition to the entry; transitionId comes from duckhunt-entry-list-transitions. If that transition declares required fields (e.g. resolution when closing), pass them in fields as {fieldId: value} with the ids of their options; if you omit them, they are filled with the default value of the source (or its first option) ONLY if the issue has them empty.

duckhunt-inbox

ChatGPT
Lists unread inbox events of the workspace bound to the token, with the task(s) associated with each entry. Filters: category or provider (mutually exclusive; provider wins). allWorkspaces=true aggregates all workspaces of the user.

duckhunt-inbox-seen

ChatGPT
Marks an event as seen

duckhunt-inbox-snooze

ChatGPT
Hides an event until a future date (iso8601)

duckhunt-insights

ChatGPT
The INSIGHTS views of the user for a period, the same data their /insights tabs show. view: summary (done, created, tracked time by signal and day, agent cost, inbox volume and triage, open board now, each with the previous comparable span and a series), findings (deterministic flags of what deserves action: review_merged, review_queue, stale_wip, unattributed_code, noisy_source, agent_rule_cost; without the dismissed ones), time (per local day totals and, with blocks=true, its de-overlapped blocks hour by hour; time per task and per repo with what reached no task, meetings, tempo per day; a quarter has no blocks), flow (cycle time p50/p85 over 90 days, started work with its age, where finished work waited by status, reopened tasks), agents (runs and cost per day and origin, models, usefulness per automation rule, the most expensive conversations, questions and permission waits, machine occupancy) or sources (where inbox notices ended up per provider, triage, the mute rule that would help backtested on 30 days, the most repeated items). Everything follows scope: with workspace, time and meetings are only what belongs to its tasks, issues, repos and calendars; with all, the whole user. Optional period (day|week|month|quarter, default week), anchor (yyyy-mm-dd inside the period; default today for day and yesterday otherwise) and scope (workspace = the active one, all = every own workspace).

duckhunt-jira-create

ChatGPT
Creates a new jira issue and ingests it as a local entry. Optional targetId attaches it to that task in the same step (useful for derived work: "this needs a follow-up ticket"). Valid projectKey/issueType via duckhunt-jira-projects. Returns {entryId, key}.

duckhunt-jira-projects

ChatGPT
Lists the jira projects where you can create issues, with their issue types. Use it to discover valid projectKey/issueType before duckhunt-jira-create. A project with empty issueTypes is one whose metadata could not be read: do not use it to create. Slow (1-3s); cache the result in your context.

duckhunt-label-list

ChatGPT
Lists the labels of the user with their color and the number of labeled targets (usageCount)

duckhunt-label-set

ChatGPT
Replaces the label set of a task BY NAME. Names that do not exist are created inline (auto color from the palette). Empty list = remove all. Returns the resulting labels.

duckhunt-list-monitors

ChatGPT
Lists monitors of the workspace bound to the token (aws cloudwatch alarms + open nightwatch issues + uptime kuma monitors) with derived severity. All of them live in category=monitoring; filter by provider (aws|nightwatch|uptime_kuma) or severity. Resolved nightwatch issues are omitted. allWorkspaces=true aggregates the monitors of ALL the workspaces of the user.

duckhunt-mention-suggest

ChatGPT
Suggests users to mention in the entry (jira: user search; bitbucket: workspace members). Returns canonical tokens ready for duckhunt-entry-comment.

duckhunt-note-add

ChatGPT
Adds a work note to a task (targetId) or to an entry (entryId), exactly one of them. It is YOUR channel to leave state visible to the user and context for future agent sessions: kind=progress (progress of the ongoing work), blocker (what blocks you), result (summary/handoff when finishing), note (free context, default). body in markdown. summary: ONE sentence in plain text (max. 200 chars) with the verdict; it is the only thing the user reads in the mobile notification WITHOUT expanding it, so write it to be understood on its own. Depending on notification preferences, adding the note can send a push through the user's configured push service. data optional: free json object for structured state (branch, pr url, checklist...). Use data.context (conversationId, host, repoPath, memoryDir...) so that a future invocation resumes in its environment. author: identify yourself (e.g. "claude-code"). Notes appear embedded in duckhunt-target-get and duckhunt-entry-get. Inside an agent run your answer goes through duckhunt-run-reply, never here: a note holds the state of the task you are working on when your prompt asks you to track it, or what the user asks for. Related: duckhunt-note-update (keep the same note alive), duckhunt-note-list, duckhunt-note-delete.

duckhunt-note-delete

ChatGPT
Deletes one of your own work notes

duckhunt-note-list

ChatGPT
Lists the work notes of a task (targetId) or entry (entryId), in chronological order. Usually not needed: duckhunt-target-get and duckhunt-entry-get already embed them. Useful to filter by kind (e.g. only blockers).

duckhunt-note-update

ChatGPT
Updates one of your own work notes (body, kind and/or data). Useful to keep a single progress note alive instead of piling up one per step. data is MERGED over the existing state (shallow): the keys you pass are updated and the rest are kept, so you can change a single key (e.g. status) without resending everything. A null value on a key deletes it; data:null (top-level) deletes all the structured state; omitting data leaves it untouched. The noteId comes from duckhunt-note-add or from the notes embedded in duckhunt-target-get / duckhunt-entry-get. Related: duckhunt-note-list, duckhunt-note-delete.

duckhunt-pipeline-logs

ChatGPT
Log tail (~64KB) of a step of the pr pipeline. Without stepUuid it resolves the first failed step of the run; pipelineUuid is optional (default: the last persisted run). Use it after a ci_failed event to read the build error and fix it.

duckhunt-pipeline-status

ChatGPT
CI status (bitbucket pipelines) of the pr: last run of the source branch persisted by the poller (state PENDING|IN_PROGRESS|COMPLETED, result SUCCESSFUL|FAILED|ERROR|STOPPED). fresh=true queries bitbucket live and adds the recent runs of the branch.

duckhunt-pr-merge

ChatGPT
Merges a pr/mr into its destination in the source (bitbucket/github). strategy is the raw provider name (bitbucket: merge_commit|squash|fast_forward); if omitted, the repo default is used. closeSourceBranch closes the source branch after merging. Before merging, review the doneChecklist of the target (open review tasks). Refreshes the local cache after the merge.

duckhunt-pr-open

ChatGPT
Opens the pull request of a repo linked to the target (see duckhunt-target-branch-set) against bitbucket/github and ingests it as an entry attached to the target in the same step. repoId can be omitted only if the target has ONE linked repo. title defaults to the target title; description is only sent if passed explicitly. Returns {entryId, url, prNumber}.

duckhunt-pr-update-branch

ChatGPT
Updates the pr branch with its destination (merges base into head, in the source). github supports it; bitbucket cloud has no public sync api. Useful when the pr fell behind its base before merging. Refreshes the local cache afterwards.

duckhunt-set-custom-field

ChatGPT
Sets (or clears with an empty/null value) the value of a custom field on a target or an entry. Pass EXACTLY one of targetId/entryId. fieldId is the definition id (visible in customFields of duckhunt-target-get/entry-get). value is text: number→numeric, date→yyyy-mm-dd, checkbox→0/1, select→one option, multi_select→json array of options. Returns the resolved fields.

duckhunt-share-grant

ChatGPT
Shares a target of YOURS (targetId, contract 36) or a whole workspace of YOURS (workspaceId, contract 43) with another duckhunt user by email. Exactly one of targetId/workspaceId. role=viewer (read-only) or editor (moves targets, leaves work notes; in a workspace it also creates targets). Idempotent: re-granting updates the role and can downgrade an existing editor to viewer. The recipient must have an account. Returns the grant {granteeUserId, email, role}.

duckhunt-share-list

ChatGPT
Lists who a target of YOURS (targetId) or a workspace of YOURS (workspaceId) is shared with: active grants (email + role). Exactly one of the two. Owner only.

duckhunt-share-revoke

ChatGPT
Revokes the access of a user to a target of YOURS (targetId) or to a workspace of YOURS (workspaceId). Exactly one of the two. Owner only. Idempotent.

duckhunt-shared-list

ChatGPT
Lists what OTHER users have shared with you: items = individual targets (contract 36: validation / handoff; id, title, status, owner email and your role) and workspaces = whole workspaces (contract 43: id, name, owner and role). viewer=read-only, editor=you can write. Open a target with duckhunt-target-get (you will see the collaborative layer + your own per-source entries); a shared workspace is worked on with an mcp token bound to it (activate it in the ui and re-authorize) or by passing it as workspaceId when creating.

duckhunt-status-list

ChatGPT
Lists the kanban statuses of the user (built-in + custom) with their key, label and color. Use the key (e.g. "in_progress" or "c1") as the status value in target-create / target-update. locked lists the columns locked in the active workspace: no task can be created in, moved into or out of, reordered, archived or deleted from them until the user unlocks them on the board.

duckhunt-target-add-time

ChatGPT
Adjusts the agent session time of a target WITH SIGN (the session signal of duckhunt-target-time). Corrects undercounted time: implicit tracking splits your session when you go >60min without touching duckhunt (long stretches of editing/compiling/running without tool calls), so your real time may exceed the recorded one. POSITIVE minutes adds the missing ones; NEGATIVE corrects downwards if you overshot. To set an absolute total use duckhunt-target-set-time. NOT idempotent: each call adjusts again, do not retry blindly. Requires mcp time tracking enabled in settings. Returns the updated total.

duckhunt-target-attach

ChatGPT
Attaches an entry to a task

duckhunt-target-branch-delete

ChatGPT
Unlinks a repo from the target (row of repos from duckhunt-target-get). It does not touch the already opened pr or its entry.

duckhunt-target-branch-set

ChatGPT
Links a repo and its branches to a target so its pull request can be opened with duckhunt-pr-open. Adding NEVER overwrites previous rows: a target can accumulate several prs, even from the same repo (another source branch, or the same one against dev and master); only repeating the exact coordinates is idempotent (returns the existing row). repo = workspace/slug (bitbucket) or owner/repo (github); omitted destBranch = main branch of the repo when opening. Configured repos come in repos of duckhunt-target-get (stale branches are removed with duckhunt-target-branch-delete). Do it when creating the working branch: it leaves the coordinates ready to open the pr when done.

duckhunt-target-create

ChatGPT
Creates a task, optionally with initial attached entries. Optional parentId to be born as a subtask of another target. isEpic=true creates an epic (organizational container: groups subtasks, with no work or status of its own). Optional priority (1=urgent..4=low). Optional taskType classifies the task (catalog key, built-in feature|bug|chore|improvement|research or custom; list them with duckhunt-task-type-list). Optional status to start directly in a column (e.g. in_progress when claiming and starting). Optional note leaves an initial work note kind=progress (attributed to author); it collapses the claim+start flow into a single call. Optional workspaceId creates it in another workspace of the user (default: the active one). Returns {id, workspaceId, url, created}; created=false if a recent target with the same title already existed (idempotent on retries).

duckhunt-target-detach

ChatGPT
Removes an entry from a task

duckhunt-target-follow-up

ChatGPT
Creates a new version ("v2"/follow-up) of a target: a CLEAN task linked to the original (copies the title with suffix (vN), description and labels; its own board and timeline), without touching or cluttering the original. Use it when a closed task has to be reopened or redone instead of reviving its history. Different from a subtask/epic: it is not hierarchy. Returns the id of the new version. The version chain appears in versions of duckhunt-target-get.

duckhunt-target-get

ChatGPT
Returns a task with all its attached entries, subtasks, labels, custom fields (with their value), its work notes (state/memory left by agents and the user; read them before resuming work), the latest agent runs launched from it or on its entries (agentRuns: r#N, status and verdict; the whole thread with duckhunt-agent-run-get), earlier runs on other items that look alike (similarRuns: same exception, table, alarm family, ticket key or title, with how they match and their verdict; data from other runs, it may not apply) and its associated repos, each with the already ingested commits of its branch (repos[].commits, most recent first: the code that was written even if nobody noted it).

duckhunt-target-list

ChatGPT
Lists the tasks (targets) in the workspace of the token with entry counts per source and their labels. Optional status: a catalog key (built-in backlog|todo|in_progress|in_review|done|canceled or custom; list them with duckhunt-status-list). Optional parent: "root" = roots only, number = only direct children of that id. Optional labels: label names of the user, filters with OR semantics. allWorkspaces=true aggregates tasks from ALL workspaces of the user.

duckhunt-target-merge

ChatGPT
Merges (reconciles) the task sourceId INTO destId and DELETES the source: entries, notes, labels, attachments, custom fields, time, subtasks and shares move to the destination (the scalar fields of the destination win; gaps are filled with those of the source). Entries that the destination owner has no copy of in their workspace are detached (not deleted). Supports shared tasks: you need write permission (owner or editor) on BOTH; when absorbing a task from another owner, that owner receives an editor grant on the destination.

duckhunt-target-move

ChatGPT
Moves a task (and its whole subtree of subtasks) to another workspace of the user. Reconciles what is per-workspace: a status/type that does not exist in the destination is adjusted (status→todo), the kanban order is recalculated and the custom fields of the source are discarded. Entries that do not live in the destination are DETACHED from the task (not deleted). Owner only; get the destination workspaceId from duckhunt-workspace-list (id + name of each workspace).

duckhunt-target-set-time

ChatGPT
Sets the agent session time of a target to an ABSOLUTE total in minutes (the session signal of duckhunt-target-time), correcting the difference with what has been recorded so far. Use it when you know the real total time and want the signal to reflect it exactly, instead of adding/subtracting blindly with add-time. minutes >= 0. It is idempotent with respect to the total (setting it twice to the same value leaves the same total). Requires mcp time tracking enabled in settings. Returns the updated total.

duckhunt-target-stats

ChatGPT
Returns task counts by status + orphan entries for the dashboard

duckhunt-target-suggestions

ChatGPT
Suggests unattached entries related to the ones already attached to the task

duckhunt-target-time

ChatGPT
Tracked time of a task. timeline is the authoritative total: the wall-clock union of every signal (manual clock, coding time from wakatime, mcp agent sessions, work in the duckhunt ui) with overlaps counted once. bySignal sums to totalSeconds (an overlapping minute goes to the most reliable signal: manual > code > agent > app), byDay is per local day and codeVia says how coding time reached this task: assigned (the user assigned those coding blocks to the task by hand), branch (jira key in the branch), repo (a work branch linked only to this task, never a trunk such as main or a branch other tasks merge into), anchor (coding in a compatible repo while a session of this task was running) or commit (jira keys in the day's own commit messages); codeByBranch = its coding time by (project, branch, issue). The other fields are raw per-signal detail and must NOT be added up: session = agent sessions, app = ui work, worklog = tracked-vs-logged state in tempo per key, provenance = which signal the ALREADY logged time came from.

duckhunt-target-update

ChatGPT
Updates fields of a task (status, title, description, etc.). status accepts any key from the catalog (built-in or custom; list them with duckhunt-status-list). descriptionEntryId links an attached entry (any source) as a live description; mainEntryId marks an attached entry as the main one of the target. null in either of them unlinks. parentId re-parents the target (null = make it a root); rejects cycles.

duckhunt-task-type-list

ChatGPT
Lists the task types of the user (built-in feature|bug|chore|improvement|research + custom) with their key, label, color and icon, plus the keys hidden in the active workspace. Use the key (e.g. "bug" or "tt1") as the taskType value in target-create / target-update.

duckhunt-tempo-list-worklogs

ChatGPT
LOCAL read-back of the worklog ledger that duckhunt pushed to tempo (does NOT call tempo: lists what duckhunt logged, with the source signal). Each row: source (code/agent/manual/app/explicit), jiraKey, day, seconds, tempoWorklogId (null = tracked but not pushed yet). For reconciling what was synced and why. Does NOT see worklogs created outside duckhunt. Optional from/to/jiraKey filters.

duckhunt-tempo-log-worklog

ChatGPT
Creates one new worklog in Tempo Cloud for the Jira issue of an owned entry, using the connected Tempo account. This writes time to an external service; call only when the user requests time logging. seconds is a whole number of at least 60. date and startTime use the user timezone. If startTime is omitted, use the live agent session start, or a block ending now when there is no live session. If date is omitted, use the date of that resolved block start. Each successful call creates a new worklog; do not retry an uncertain result without checking duckhunt-tempo-list-worklogs. Requires connected Tempo and Jira accounts. Does not update or delete existing worklogs.

duckhunt-tempo-manage-day

ChatGPT
Marks (managed=true, default) or releases (false) a (jira issue, day) as MANUALLY MANAGED: tempo auto-sync stops adding time on top of it; the manual correction wins. Use it after balancing a day by hand in tempo so duckhunt does not stack slivers on it on the next tick. The auto-sync also sets these locks by itself when it reads tempo back and finds a worklog on that issue and day created, edited or deleted outside duckhunt. Explicit logging (duckhunt-tempo-log-worklog) is NOT affected: it is a deliberate action. Returns the final state and the full list of locks of the user.

duckhunt-unattributed-time

ChatGPT
UNATTRIBUTED coding time: the part of your coding wall-clock (wakatime, overlaps counted once) that reached no task and no jira issue by any route (branch key, task branch, a session of a task in the same repo, or keys in that day's own commit messages). Makes the zero honest: a low code time on a task does not mean no work was done, check this. codeSeconds = all coding time in the range, unattributedSeconds = the remainder, attributedByVia = how the rest was attributed, plus the remainder by day and by (project, branch). Optional from/to (yyyy-mm-dd, inclusive).

duckhunt-user-note-create

ChatGPT
Creates a note of the user (standalone markdown document, visible and editable in /notes). To report progress on a task use duckhunt-note-add (work notes), not this.

duckhunt-user-note-delete

ChatGPT
Deletes a note of the user (standalone document). Its agent conversations are kept in /agents.

duckhunt-user-note-get

ChatGPT
Reads a note of the user (standalone markdown document) with its full content.

duckhunt-user-note-list

ChatGPT
Lists the notes of the user (standalone markdown documents in duckhunt, NOT the work notes of targets/entries). Ordered by last edit. q filters by title.

duckhunt-user-note-update

ChatGPT
Updates the title and/or content of a note of the user.

duckhunt-workspace-list

ChatGPT
Lists the workspaces of the user with their id, name, whether it is the default and which one is active for the token. Translates a workspace name ("personal", "okticket") into the workspaceId required by duckhunt-target-create and duckhunt-target-move. The rest of the tools operate only on the active workspace unless they accept allWorkspaces=true.

Capabilities

Writes

Example Prompts

Click any prompt to copy it.

Similar Apps