dutify-mcp

Bridges an AI agent to the Dutify suite — project management, wiki (Codexum) and feature requests (Roadmarq).

От сообщества: Добавлен пользователем или импортирован; проверьте владельца перед подключениемРаботаетБез входаГлобальныйБесплатноМожет изменять данные

Что умеет

  • Whoami: Returns the calling API key’s identity — workspace it is bound to, scopes it carries, and the configured backend URLs. Resolves the bound workspace via PM `GET /v1/api-keys/current` (a fresh H
  • List Accounts: List the accounts configured for this MCP session. Returns one entry per account with `name` (the label the caller passes as the `account` tool argument) and `workspace` (the workspace
  • Find My Workspace: Self-introspect the API key: returns the bound workspace identifier+name and the scopes the key carries, in a single PM `GET /v1/api-keys/current` call (no probing). Workspace tools

Какие данные видит

Нужен ли аккаунт

Не нужен: сервер работает без входа

Bridges an AI agent to the Dutify suite — project management, wiki (Codexum) and feature requests (Roadmarq).

Tasks, spaces, lists, views, custom fields, comments and webhooks over one API key. Agents get a real seat with scoped permissions rather than a bolt-on integration, so they act on the same workspace context the team works in.

Authentication: send your Dutify PM API key (dk_live_…) as the X-API-Key header. A key is bound to one workspace; X-Dutify-Workspace optionally selects it by name or id.

Список инструментов сервера (60)

Технические названия из tools/list. Нужны только разработчикам.

whoamiReturns the calling API key’s identity — workspace it is bound to, scopes it carries, and the configured backend URLs. Resolves the bound workspace via PM `GET /v1/api-keys/current` (a fresh HTTP call on every identity check). Safe to call as a session sanity check.
list_accountsList the accounts configured for this MCP session. Returns one entry per account with `name` (the label the caller passes as the `account` tool argument) and `workspace` (the workspace identifier or name declared for that account). API keys are not returned. In single-account mode (X-API-Key with optional X-Dutify-Workspace), returns a single entry with name="default". In multi-account mode (X-Dutify-Accounts header), returns every configured account. Call this first when you do not know which account names are available.
find_my_workspaceSelf-introspect the API key: returns the bound workspace identifier+name and the scopes the key carries, in a single PM `GET /v1/api-keys/current` call (no probing). Workspace tools discover this automatically when X-Dutify-Workspace is omitted. Cached per key for an hour.
list_workspacesINFORMATIONAL ONLY — list every workspace the underlying user (the human who created this API key) is a member of. IMPORTANT: an API key is bound to EXACTLY ONE of these workspaces — only that one will accept requests. You cannot switch between workspaces within a session. To act on a different workspace, the user must provision a separate API key for it and reconfigure the MCP client. The `bound` field on each entry indicates whether it matches the API key's bound workspace (resolved via `/v1/api-keys/current`).
list_boardsList feature-request boards the caller can view in the current workspace. Each entry includes the board slug and the short-ID prefixes (featureRequestKey, bugReportKey) needed to address requests/bugs in follow-up tool calls.
list_spacesList wiki spaces the caller can view in the current workspace, each with a page count. Use the `key` field as the space identifier in follow-up wiki tool calls.
get_endpoint_examplesFetch the request/response example payloads (full JSON values) for a Dutify API resource tag. Use this when you're about to write rich content via a tool that accepts a TipTap `content` parameter (e.g. wiki_create_page) and need a concrete reference of what the doc shape looks like — banners, collapsibles, mermaid diagrams, code blocks with language, mentions, inline labels, tables, task lists, etc. Pass the resource tag (e.g. "Wiki Pages (Lite)", "Milestone Articles"). Optionally narrow with `operationId` (e.g. "createPage") and `name` (e.g. "full" or "full-tiptap") — both names appear in the per-tag detail response so an agent can pick exactly the example it needs without paying tokens for the rest. Returns the catalog JSON; the example payloads are under `operations[*].requestBodyExamples[name].value`. Tag list (lightweight) is at GET /v1/api-catalog. Per-tag detail (schemas, no example bodies) is at GET /v1/api-catalog/{tag}. This tool calls the third tier — GET /v1/api-catalog/{tag}/examples — which carries the heavy payloads.
wiki_searchFind wiki PAGES by title/keyword in the current workspace. Returns a list of matching pages (slug, title, spaceKey, spaceName, excerpt, status, updatedAt) — no UUIDs, no full body. Use this to LOCATE or LIST pages (then call wiki_get_page to read one). To ANSWER a question FROM wiki content — i.e. get back quotable passages with citations and relevance scores — use wiki_retrieve instead. Optionally scope to a single space by passing spaceKey. Defaults to hybrid (keyword + semantic) ranking; pass mode to override. Page results include webUrl: a browser link requiring normal workspace access. Use it for citations; it does not make the page public. API-key scope: `wiki:search:read`.
wiki_retrieveSearch the wiki by MEANING and get back the most relevant PASSAGES (chunks) with citations and relevance scores. Use this to GROUND or ANSWER a question from wiki content: it returns quotable chunkText plus the source page/section so you can cite it. Each result has pageSlug, pageTitle, spaceKey, spaceName, chunkIndex, headingPath (heading-path breadcrumb), chunkText, score (0..1, higher = more relevant), status and updatedAt. This is retrieval-augmented generation (RAG) over wiki content, NOT a page finder — to merely LOCATE or LIST pages by title/keyword use wiki_search. Defaults to the top 5 chunks; pass limit to widen. Fails open to keyword retrieval if the embedding provider is unavailable. Page results include webUrl: a browser link requiring normal workspace access. Use it for citations; it does not make the page public. API-key scope: `wiki:search:read`.
wiki_list_pagesList wiki pages in a space. Without `parent` returns root-level pages; pass a parent slug to list that page's children. Response items have slug, title, status, type (page|folder), parentSlug, updatedAt — no bodies. Page results include webUrl: a browser link requiring normal workspace access. Use it for citations; it does not make the page public. API-key scope: `wiki:pages:read`.
wiki_get_pageGet a wiki page by slug within a space. Default format is Markdown (the body is returned under the `markdown` field); pass format="tiptap" for raw ProseMirror JSON. Page results include webUrl: a browser link requiring normal workspace access. Use it for citations; it does not make the page public. API-key scope: `wiki:pages:read`.
wiki_create_pageCreate a wiki page under a space. Pass EITHER `markdown` (simpler, server converts to TipTap) OR `content` (TipTap/ProseMirror JSON, mutually exclusive with markdown). Use `content` when you need rich features that markdown can't express — banners, collapsibles, mermaid diagrams, action buttons, inline labels, mentions, code blocks with language, etc. For the full TipTap doc shape and a copy-friendly reference of every node and mark, call `get_endpoint_examples` with tag="Wiki Pages (Lite)" (and optionally name="full-tiptap"). Optional parent slug to nest under another page. Returns the created page DTO. Page results include webUrl: a browser link requiring normal workspace access. Use it for citations; it does not make the page public. API-key scope: `wiki:pages:write`.
wiki_update_pageUpdate an existing wiki page by slug. Any field left unset preserves the current value. Pass EITHER `markdown` OR `content` (TipTap/ProseMirror JSON) for the body — they're mutually exclusive. Use `content` for rich features (banners, collapsibles, mermaid, etc.); call get_endpoint_examples(tag="Wiki Pages (Lite)") for the full doc shape. Page results include webUrl: a browser link requiring normal workspace access. Use it for citations; it does not make the page public. API-key scope: `wiki:pages:write`.
wiki_move_pageMove a wiki page to a new parent and/or a new space. All body fields are optional and use slugs (resolved server-side in the target space) instead of UUIDs: `targetSpaceKey` for cross-space moves (omit to stay in the current space); `newParent` is the slug of the new parent page (omit/null to move to space root); `afterPage` is the slug of the sibling page to insert after (omit/null to place first). Returns the moved page DTO. Page results include webUrl: a browser link requiring normal workspace access. Use it for citations; it does not make the page public. API-key scope: `wiki:pages:write`.
wiki_delete_pageArchive (soft-delete) or permanently delete a wiki page by slug. Falls through to the non-lite Wiki Pages API since there is no lite delete endpoint — path is `DELETE /v1/workspaces/{workspaceIdentifier}/wiki/spaces/{spaceKey}/pages/{slug}` with optional `?permanent=true`. Default behavior archives the page (soft delete); pass `permanent: true` to hard-delete (requires admin access). Returns 204 on success. API-key scope: `wiki:pages:write`.
wiki_get_page_shareGet the public SHARE-LINK status for a single page (PublicShareInfoDTO): `isEnabled`, `publicToken`, `publicUrl` (the shareable link), `showAuthor`, `sharedAt`, `sharedBy`, `workspaceAllowsSharing`. A per-page share link lets anyone with the URL read just that one page — distinct from publishing a whole space (wiki_set_public_settings). Requires edit access. API-key scope: `wiki:pages:read`.
wiki_enable_page_shareEnable a public SHARE LINK for a single page, returning a PublicShareInfoDTO with the `publicUrl` to hand out. Optional `token` sets a custom URL slug (3-100 chars, lowercase letters/digits/hyphens; 409 if already taken — omit to auto-generate). Optional `showAuthor` toggles author display. ⚠️ OUTWARD-FACING: anyone with the link can read this page — confirm with the user before enabling. Requires edit access. API-key scope: `wiki:pages:write`.
wiki_disable_page_shareDisable the public share link for a single page, revoking access via its URL (returns 204). Requires edit access. API-key scope: `wiki:pages:write`.
wiki_list_spacesList every wiki space the caller can see in the current workspace. Each entry has the space's `key` (use this in subsequent calls), `name`, `description`, `effectivePermission` (view/edit/admin), and `canView`/`canEdit`/`canAdmin` booleans for quick gating. Call this first when an agent needs to figure out which space a wiki action should target. API-key scope: `wiki:spaces:read`.
wiki_get_spaceFetch a single wiki space by key. Returns the WikiSpaceDTO (id, key, name, description, icon, color, cover image, visibility flags, permissions, timestamps). For the page tree inside the space, use wiki_get_space_with_pages instead. API-key scope: `wiki:spaces:read`.
wiki_get_space_with_pagesFetch a wiki space AND its complete page tree in one call. Returns WikiSpaceWithPagesDTO — space metadata plus `pages` (a recursive tree of WikiPageTreeNodeDTO with slug, title, type=page|folder, hasChildren, children[], view count, top reactions, the caller's effectivePermission per node). Use this to render or traverse the whole space; for a single level (root or one parent's children) wiki_list_pages is lighter. API-key scope: `wiki:spaces:read`.
wiki_create_spaceCreate a new wiki space in the current workspace. `key` is the unique short identifier used in URLs and subsequent API calls — uppercase letters + digits only, 2-20 chars, must start with a letter (e.g. "DOCS", "ENG2"). `name` is the human display name. Defaults: `isPublic: true` (INTERNAL visibility — all workspace members can view), `isEditPublic: false`. NOTE: `isPublic` is internal workspace visibility ONLY; it does NOT publish the space to the public web — use wiki_set_public_settings for that. Requires workspace-level edit access. API-key scope: `wiki:spaces:write`.
wiki_update_spaceUpdate a wiki space's metadata. All fields are optional — pass only what you want to change. The space key cannot be changed. Requires edit access to the space. API-key scope: `wiki:spaces:write`.
wiki_delete_spacePERMANENTLY delete a wiki space AND every page inside it. Requires admin access to the space. This is destructive — surface a clear confirmation to the user before calling. Returns 204. API-key scope: `wiki:spaces:write`.
wiki_get_public_settingsGet a space's PUBLIC-WEB publishing settings (PublicSpaceSettingsDTO): `isEnabled` (is the space published to the public internet), `customSlug` (public URL slug), `allowedEmojis`, `showReactions`, `showPageViews`, `showLastUpdated`, `showAuthor`, `viewMode` ("space"|"helpcenter"), `heroTitle`, `heroSubtitle`. This is SEPARATE from the space's `isPublic` flag, which is internal workspace visibility only. Requires space admin. API-key scope: `wiki:spaces:read`.
wiki_check_public_slugCheck whether a public URL slug is available and validly formatted for a space, before publishing. Returns a SlugAvailabilityDTO. Call this when choosing a `customSlug` for wiki_set_public_settings. Requires space admin. API-key scope: `wiki:spaces:read`.
wiki_set_public_settingsPublish / unpublish a space to the PUBLIC INTERNET, or update its public-site config. This is the REAL publish switch — NOT the space `isPublic` flag (which is internal visibility). Pass only the fields you want to change: `isEnabled` (true = publish to the web, false = take offline), `customSlug` (public URL slug — validate first with wiki_check_public_slug), `allowedEmojis` (string[]), `showReactions`, `showPageViews`, `showLastUpdated`, `showAuthor`, `viewMode` ("space"|"helpcenter"), `heroTitle`, `heroSubtitle`. Provided fields are merged onto the current settings (read-modify-write), so unspecified fields are preserved. Minimal publish: { isEnabled: true, customSlug: "my-docs" }. ⚠️ HIGH-TRUST / OUTWARD-FACING: enabling makes the space readable by ANYONE on the internet — confirm with the user before publishing. Requires space ADMIN. API-key scope: `wiki:spaces:write`.
wiki_list_attachmentsList every attachment on a wiki page (WikiAttachmentDTO[]): id, pageId, filename, contentType, sizeBytes, status (pending|confirmed|failed), uploadedBy/At, confirmedAt. `pageId` is the page UUID (from wiki_get_space_with_pages tree node `id`, not the slug). Use to find an attachmentId to reference or delete. API-key scope: `wiki:attachments:read`.
wiki_request_attachment_uploadStep 1 of uploading an image/file to a wiki page. Returns { attachmentId, uploadUrl, storageKey }. AFTER calling this you MUST: (2) PUT the raw file bytes to `uploadUrl` with your OWN HTTP client — the MCP server cannot do this binary upload — sending the EXACT same `Content-Type` as `contentType` and a `Content-Length` equal to `sizeBytes` (both are baked into the presigned URL; a mismatch 403s); then (3) call wiki_confirm_attachment to activate it. To embed the result as an image, add a TipTap image node with no `src` — { type:"image", attrs:{ attachmentId, pageId, width, height, align } }, width <= ~660 and height proportional — via wiki_update_page (content payload). Do NOT embed base64 data: URIs; they render distorted. Max 25 MB; system-executable file types are rejected. `pageId` is the page UUID (wiki_get_space_with_pages tree node `id`). API-key scope: `wiki:attachments:write`.
wiki_confirm_attachmentStep 3 of uploading: confirm that the bytes were successfully PUT to the presigned `uploadUrl`, activating the attachment. Returns the WikiAttachmentDTO (status becomes "confirmed"). Call only after the byte PUT succeeded. API-key scope: `wiki:attachments:write`.
wiki_delete_attachmentPermanently delete an attachment and its stored file (returns 204). Useful for cleaning up unused or leftover uploads. This does not remove image nodes that still reference it in a page body — update the page content separately if needed. API-key scope: `wiki:attachments:write`.
fr_list_requestsList feature requests on a feedback board (by board slug). Filter by status / category / milestone name (lenient — trimmed + case-insensitive). Pass `q` to search request titles instead. Paginated via page/size. API-key scope: `feedback:requests:read`.
fr_get_requestGet a feature request by short ID (e.g. "FR-42"). Returns full detail: title, description, status, category, milestone, voteCount, commentCount, reactions. Internal notes and linkedTaskIds are populated only when the caller has `View Internal Data` permission. API-key scope: `feedback:requests:read`.
fr_create_requestCreate a new feature request on a board. Category is resolved by name (lenient match). No turnstile token required — API-key authentication is sufficient. Returns the new request with assigned shortId. API-key scope: `feedback:requests:write`.
fr_set_request_statusChange a feature request's status by name. The name is resolved leniently against the request's board's status set (trim + case-insensitive). Returns the updated request detail. API-key scope: `feedback:requests:write`.
fr_comment_requestAdd a comment to a feature request. Pass isInternal=true to make the comment visible only to users with `View Internal Data` permission. API-key scope: `feedback:comments:write`.
fr_vote_requestToggle a vote or emoji reaction on a feature request. Passing emoji=null or omitting the field registers a plain upvote. Calling the tool again with the same emoji removes the vote (idempotent toggle). API-key scope: `feedback:votes:write`.
fr_moderate_requestApprove, reject, or mark a feature request as spam. Action is case-insensitive. Requires `Manage Queue` permission. API-key scope: `feedback:moderation:write`.
fr_delete_requestPermanently delete a feature request. Requires `Manage Queue` permission. Returns 204 on success. This operation is irreversible — confirm with the user before calling unless the intent is unambiguous. API-key scope: `feedback:requests:write`.
fr_list_bugsList bug reports on a feedback board (by board slug). Filter by severity and/or status name (lenient match). API-key scope: `feedback:bugs:read`.
fr_get_bugGet a bug report by short ID (e.g. "BG-99"). Returns full detail: title, reproduction steps, expected/actual result, severity, status, product area, assignee, affectedCount, environment, comments count. Internal notes and linkedIssueUrl populated only for `View Internal Data` permission. API-key scope: `feedback:bugs:read`.
fr_create_bugCreate a new bug report on a board. Severity and productArea are resolved by name (lenient match). Environment is a free-form map (browser, OS, url, etc.). API-key scope: `feedback:bugs:write`.
fr_set_bug_statusChange a bug status by name (lenient match against the board's bug-status set). API-key scope: `feedback:bugs:write`.
fr_set_bug_assigneeAssign or unassign a bug. Provide `assigneeEmail` (resolved case-insensitive against workspace members) OR `assigneeId` (UUID). Exactly one; both = 400. Passing neither unassigns. API-key scope: `feedback:bugs:write`.
fr_set_bug_visibilityToggle a bug's public visibility. Security bugs stay private regardless. API-key scope: `feedback:bugs:write`.
fr_toggle_bug_affectedToggle the caller's "I'm affected" marker on a bug. Returns the updated bug detail with new affectedCount. API-key scope: `feedback:bugs:write`.
fr_comment_bugAdd a comment to a bug report. Pass isInternal=true for internal-only. API-key scope: `feedback:comments:write`.
fr_moderate_bugApprove, reject, or mark a bug as spam. Action is case-insensitive. Requires `Manage Queue` permission. API-key scope: `feedback:moderation:write`.
fr_delete_bugPermanently delete a bug report. Requires `Manage Queue` permission. Irreversible. API-key scope: `feedback:bugs:write`.
pm_get_workspace_contextSingle-call workspace orientation: members, spaces (with folders, lists, per-list statuses/priorities/taskTypes/customFields), workspace-level taskTypes, relationshipTypes, tags. The biggest agent-onboarding tool — call it first when starting in a new workspace. Pass shallow=true to skip per-list statuses/priorities for a faster tree-only response. Each per-list custom field carries an `isMandatory` flag — fields with isMandatory=true MUST be supplied in `customFields` when creating/updating a task in that list, or the write is rejected with 400 VALIDATION_ERROR. API-key scope: `workspaces:read`.
pm_get_dashboardGet aggregated counts and breakdowns (status / priority / assignee distributions, custom-field summaries) for any scope. Useful for "how is project X doing?" questions without paginating through tasks. API-key scope: `dashboards:read`.
pm_search_tasksSearch tasks across the workspace with name-based filters. status / priority / tag / taskType are repeatable (pass an array). assignee is an email or UUID. q is a free-text search over title + description. Returns a cursor-paginated page of LiteTaskResponse — pass nextCursor back as `cursor` to paginate. Present title linked to webUrl; show displayKey only when non-empty. key and identifier are API references, not display labels. API-key scope: `tasks:read`.
pm_get_taskFetch a task by ref. Ref accepts a system identifier (tsk_…) OR a task key (e.g. 'PROJ-42'). Returns LiteTaskResponse with names instead of UUIDs and emails instead of user UUIDs. Internal note: when ref is a task key the workspace query param is required — the MCP injects it automatically. Present title linked to webUrl; show displayKey only when non-empty. Do not display the raw key when displayKey is null or absent. API-key scope: `tasks:read`.
pm_get_subtasksList the direct subtasks (one level deep) of a parent task by ref. API-key scope: `tasks:read`.
pm_create_taskCreate a task. In the result, title/webUrl are for presentation; displayKey is the optional visible key. Keep key/identifier for API calls and do not expose a hidden raw key in the summary. References are name-based: status/priority/level/taskType are names; assignees are emails; tags are strings (auto-created if missing); customFields is a {name: value} map. `list` is the task-list identifier (tl_…). For subtasks, set `parent` to a task key or identifier (omit `list` and the parent's list is used). Task type is OPTIONAL: omit `taskType` to inherit the closest non-null default along the three-level chain `list → folder → space`. There's NO workspace-level fallback — if all three are null the task is created untyped (`taskType: null` in the response), which is a valid persistent state. Use `pm_list_task_types` to see what types this workspace has (9 SYSTEM rows seeded at workspace creation, plus any CUSTOM ones). MANDATORY CUSTOM FIELDS: a list can mark custom fields required (isMandatory, per field via pm_get_workspace_context). Populate them in `customFields` on create AND update — the API rejects a write that leaves one empty with HTTP 400 errorCode VALIDATION_ERROR, details.field = the field's display name; the message also names it (e.g. Mandatory custom field 'Priority' requires a value). Fix and retry; don't ask the user as a substitute. API-key scope: `tasks:write`.
pm_update_taskPartial-update a task by ref. Only fields present in the call are changed. Pass an explicit null to clear nullable fields (dueDate, parent, taskType, etc.). Names resolve leniently against the current effective set. To change just the type and nothing else, prefer this with `taskType` set; use `pm_bulk_change_task_type` when changing many tasks at once. API-key scope: `tasks:write`.
pm_delete_taskDelete a task by ref. Cascade-deletes subtasks. Requires FULL access (not just EDIT). Returns 204 on success. API-key scope: `tasks:write`.
pm_list_task_typesReturn the workspace task-type catalogue (identifier, name, singularName, pluralName, iconKind, iconValue, color, sortOrder, origin SYSTEM/CUSTOM). Use this to discover what types are available before creating/updating tasks, or to translate names to stable identifiers for the cascade-default endpoints. API-key scope: `workspaces:read`.
pm_bulk_change_task_typeChange the task type for many tasks at once (≤5000 per call). `taskIdentifiers` are stable wire identifiers (e.g. tsk_…) — task keys (PROJ-42) are NOT accepted here; use pm_search_tasks first if you only have keys. `taskType` is a name (e.g. "Bug") or null to clear the type. Returns 200 sync for ≤500 tasks; 202 with a {jobId, statusUrl} for larger batches — poll the statusUrl for completion. API-key scope: `tasks:write`.
pm_list_task_commentsList comments on a task by ref. Cursor-paginated. API-key scope: `tasks:read`.