Public log

@next-lane/mcp

Model Context Protocol (MCP) server for Next Lane — read & write a project's workflows/SDLC and core entities from external agents (Claude Desktop, Claude Code, etc.).

npm · fingerprint 76d6c391eafce5d0a2939935 · repository · RSS

132tools
2recorded versions
45dtracked
unchanged 11d

What changed

Changed between 3 September 2026 and 6 October 2026 (first seen 2026-10-06 13:35 UTC)

6 descriptions rewritten, 126 schema or annotation changes with the description left byte-identical.

--- pinned/add_checklist_item
+++ observed/add_checklist_item
  {
    "description": "Add a checklist item to an issue. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "text": {
--- pinned/add_comment
+++ observed/add_comment
  {
    "description": "Add a comment to an issue (markdown supported). Requires MEMBER+. Pass `idempotencyKey` (any string you generate once, e.g. a UUID) when RETRYING a call after a network error/timeout so the retry replays the original comment instead of posting a duplicate; omit it for a normal call. Mid-session corrections don't need to accumulate as new comments — see update_comment/delete_comment.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "body": {
          "description": "Comment body (markdown).",
-         "description": "Issue to comment on.",
+         "description": "Issue id or key (e.g. \"NL-5\") to comment on.",
          "type": "string"
        }
      },
--- pinned/add_issue_label
+++ observed/add_issue_label
  {
    "description": "Attach an existing label to an issue. Find the labelId with list_labels (or create_label first). Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue to label.",
+         "description": "Issue id or key (e.g. \"NL-5\") to label.",
          "type": "string"
        },
        "labelId": {
--- pinned/add_workflow_transition
+++ observed/add_workflow_transition
  {
    "description": "Add a transition to a named workflow. fromStatusId null means “from any status” (wildcard). Optionally scope to an issueType and attach gates. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "fromStatusId": {
          "description": "Source status id, or null/omit for “from any status”.",
-           "additionalProperties": false,
            "description": "A single transition gate rule.",
            "properties": {
              "field": {
--- pinned/add_worklog
+++ observed/add_worklog
  {
    "description": "Log time spent on an issue. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "minutes": {
--- pinned/assign_board_workflow
+++ observed/assign_board_workflow
  {
    "description": "Assign a named workflow to a board (or pass workflowId null to detach). When the board’s workflow is enforced, issue moves on that board respect its transitions. Requires board ADMIN/MEMBER.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "boardId": {
          "description": "Board id.",
--- pinned/bulk_update_issues
+++ observed/bulk_update_issues
  {
    "description": "Apply the same change to up to 100 issues at once: status, assignee, priority, sprint, type, parentId (re-parent — e.g. attach 30 tickets to an epic in one call), and/or attach a label. Foreign-project references (a parentId/statusId/sprintId from a different project) are rejected per-item with the same precise message as update_issue. Set `atomic: true` to make the whole batch all-or-nothing: every issue is validated first, and the writes only happen if EVERY issue passes — one bad id rolls back nothing being written at all, instead of the default independent-per-issue partial-success behavior. Set `dryRun: true` to preview per-item verdicts (which ids would update vs. why one would fail) with zero writes, with or without atomic. Returns a compact { updated, failed, atomic?, dryRun?, wouldUpdate? } — `failed` lists any ids that could not be changed and why (not found, insufficient permissions, cross-project reference, etc). At least one change field must be set.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "addLabelIds": {
          "description": "Label ids to attach to every matching issue (idempotent).",
--- pinned/create_automation
+++ observed/create_automation
  {
    "description": "Create an automation rule (trigger → optional NLQL condition → actions). Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "actions": {
          "description": "Ordered actions to run.",
-           "additionalProperties": false,
            "description": "A single automation action.",
            "properties": {
              "params": {
--- pinned/create_board
+++ observed/create_board
  {
    "description": "Create a board in a project. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Board name.",
--- pinned/create_component
+++ observed/create_component
  {
    "description": "Create a project component. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "defaultAssigneeId": {
          "description": "Default assignee user id, or null.",
--- pinned/create_custom_field
+++ observed/create_custom_field
  {
    "description": "Create a project custom field definition. type is immutable. SELECT / MULTI_SELECT need options. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "appliesToTypes": {
          "description": "Restrict to these issue types (omit = all).",
--- pinned/create_dashboard
+++ observed/create_dashboard
  {
    "description": "Create a dashboard in a project (a per-project view holding NLQL-native gadgets). Requires project MEMBER+. A brand-new project's very first dashboard is pre-populated with 3 starter gadgets (open issues, by status, my open issues) — every dashboard after that starts empty. Capped at 20 dashboards per project; a 400 at the cap names the limit.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Dashboard name.",
--- pinned/create_dashboard_gadget
+++ observed/create_dashboard_gadget
  {
    "description": "Add a gadget to a dashboard: an NLQL `query` (empty string matches every issue in the project) rendered as `visualization`. BREAKDOWN gadgets require `config.field`. VELOCITY_TREND ignores `query` — it's project-wide (config.sprints, default 6). Requires project MEMBER+. Capped at 30 gadgets per dashboard; a 400 at the cap names the limit.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "config": {
-         "additionalProperties": false,
          "description": "Visualization + grid-layout settings for a gadget.",
          "properties": {
            "columns": {
--- pinned/create_issue
+++ observed/create_issue
  {
-   "description": "Create an issue in a project. Only projectId and title are required; the rest are optional. CONFIRM THE TARGET PROJECT before calling — pasting/dictating a projectId from a stale context is the single easiest way to file an issue into the wrong project, and there is no undo. YOU MUST PASS `expectedProjectKey` (the project key you believe projectId resolves to, e.g. \"NL\") on every call — a field report confirmed an agent without this habit filed into the wrong project with no way to detect it after the fact. A mismatch fails BEFORE anything is created, with a clear error; the response also always echoes the resolved `project: {id, key, name}` as a second, after-the-fact check. If the environment variable NEXT_LANE_MCP_STRICT_PROJECT_KEY is set on this MCP server, omitting expectedProjectKey is itself a hard error (no issue created) rather than a soft recommendation. Pass `idempotencyKey` (any string you generate once, e.g. a UUID) when RETRYING a call after a network error/timeout/ambiguous response — a retry with the SAME key replays the original created issue instead of filing a duplicate; omit it for a normal, non-retried call.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
+   "description": "Create an issue in a project. Only projectId and title are required; the rest are optional. CONFIRM THE TARGET PROJECT before calling — pasting/dictating a projectId from a stale context is the single easiest way to file an issue into the wrong project, and there is no undo. YOU MUST PASS `expectedProjectKey` (the project key you believe projectId resolves to, e.g. \"NL\") on every call — a field report confirmed an agent without this habit filed into the wrong project with no way to detect it after the fact. A mismatch fails BEFORE anything is created, with a clear error; the response also always echoes the resolved `project: {id, key, name}` as a second, after-the-fact check. If the environment variable NEXT_LANE_MCP_STRICT_PROJECT_KEY is set on this MCP server, omitting expectedProjectKey is itself a hard error (no issue created) rather than a soft recommendation. Pass `idempotencyKey` (any string you generate once, e.g. a UUID) when RETRYING a call after a network error/timeout/ambiguous response — a retry with the SAME key replays the original created issue instead of filing a duplicate; omit it for a normal, non-retried call. Returns a compact ack by default — `{id, key, title, status, assignee, priority, type, project}` — not the full issue object; pass `verbose: true` for that (rank, description, labels, custom fields, etc).",
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "assigneeId": {
          "type": "string"
+       },
+       "verbose": {
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
+         "type": "boolean"
        }
      },
      "required": [
--- pinned/create_issue_from_template
+++ observed/create_issue_from_template
  {
    "description": "Create an issue from an issue template (list_issue_templates for the id). Any field passed here overrides that template’s default; the resolved title must end up non-empty (from the override or the template’s titleTemplate) or the API rejects the request.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "assigneeId": {
          "description": "Overrides the template default, or null to force unassigned.",
--- pinned/create_label
+++ observed/create_label
  {
    "description": "Create a label in a project (name + optional hex color). Returns the new label including its id, which add_issue_label needs. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "color": {
          "description": "Optional 6-digit hex color, e.g. #ef4444.",
--- pinned/create_page
+++ observed/create_page
  {
    "description": "Create a knowledge-base page in a project. Reference other pages with `[[Page Title]]` (or `[[Page Title|display text]]`) anywhere in `content` — resolved automatically into the link graph on save (case-insensitive exact title match, WORKSPACE-WIDE: this project first, then any other project or the workspace-docs space in the same workspace; never another workspace; self-links excluded). A title with no matching page just renders as-is until a page with that exact title exists AND this page is saved again (see get_page_links). Mentioning an issue key (e.g. NL-123) from THIS project links the page to that issue. Omit `parentId` (or pass null) for a top-level page; pass an existing page's id to nest it as that page's child (appended at the end of its children). For a doc that is not about one project (handbook, runbook, ADR, policy), use create_workspace_page instead. Requires `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "content": {
          "description": "Markdown body (default empty string). Capped at 256 KB (UTF-8 bytes).",
--- pinned/create_page_from_template
+++ observed/create_page_from_template
  {
    "description": "Create a page from a doc template (list_page_templates for the id). The template supplies the markdown body; `{{date}}`, `{{title}}`, `{{author}}` and friends are substituted server-side at creation. DESTINATION: a workspace-scoped template can create the page either in the workspace-docs space (omit `projectId`) or inside a project (pass it); a project-scoped template always creates in its OWN project, and passing a different `projectId` is rejected rather than silently redirected. The resolved title must end up non-empty (from `title` or the template’s default) or the API rejects the request. Requires `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "parentId": {
          "description": "Parent page id, or null/omit for a top-level page.",
--- pinned/create_page_template
+++ observed/create_page_template
  {
    "description": "Create a doc (page) template — a reusable markdown skeleton that create_page_from_template stamps out into new pages. SCOPE: pass `workspaceId` for a workspace-wide template (offered when creating ANY page in that workspace, including inside a project) or `projectId` for one only that project sees. Exactly one is required. Prefer the workspace scope for house style — a project template that reuses a workspace template’s name reads as a deliberate override and sorts above it in the picker. TOKENS: `{{title}} {{date}} {{time}} {{datetime}} {{year}} {{month}} {{day}} {{author}}` in `content` (and in `titleTemplate`) are substituted when a page is created, not now. An UNKNOWN token is left verbatim rather than blanked, so a fill-me-in marker survives into the page — that is deliberate, but it also means a typo like `{{data}}` will ship to readers as literal text. Names must be unique within the scope. Requires workspace ADMIN, and `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "content": {
          "description": "The markdown body, with any `{{token}}` placeholders unrendered.",
--- pinned/create_personal_card
+++ observed/create_personal_card
  {
    "description": "Add a card to a column on the caller’s personal (non-project) board. Use get_personal_board to find a columnId.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "color": {
          "description": "Hex accent color, or null/omit for none.",
--- pinned/create_project
+++ observed/create_project
  {
    "description": "Create a new project inside a workspace — get workspaceId from list_workspaces (or create_workspace). Seeds the standard three statuses (To Do / In Progress / Done) and a default Kanban board so the board view works immediately. `key` (e.g. \"NL\") becomes the issue-key prefix (NL-1, NL-2, ...) and must be unique within the workspace — this is the value every create_issue call's `expectedProjectKey` should match going forward. Requires workspace MEMBER+. The response echoes `id` and `key` prominently since downstream calls need both.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "description": {
          "maxLength": 2000,
--- pinned/create_quick_link
+++ observed/create_quick_link
  {
    "description": "Add a personal shortcut link (shown in the caller’s sidebar quick-links menu).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "color": {
          "description": "Hex accent color (#rrggbb), or null/omit for none.",
--- pinned/create_saved_filter
+++ observed/create_saved_filter
  {
    "description": "Save a reusable NLQL filter on a project (optionally shared with the team). Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Filter name.",
--- pinned/create_sprint
+++ observed/create_sprint
  {
    "description": "Create a sprint in a project. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "endDate": {
          "description": "ISO-8601 date.",
--- pinned/create_status
+++ observed/create_status
  {
    "description": "Create a workflow status (column) in a project. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "category": {
          "description": "Lifecycle category a status belongs to.",
--- pinned/create_version
+++ observed/create_version
  {
    "description": "Create a project version/release. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "description": {
          "type": [
--- pinned/create_workflow
+++ observed/create_workflow
  {
    "description": "Create a new (empty) named workflow in a project. Add transitions afterwards with add_workflow_transition. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "description": {
          "description": "Optional description.",
--- pinned/create_workflow_from_template
+++ observed/create_workflow_from_template
  {
    "description": "Create a named workflow pre-populated with transitions from a template ('simple' | 'kanban' | 'scrum' | 'bug-triage'). Fastest way to stand up an SDLC. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Optional workflow name.",
--- pinned/create_workspace
+++ observed/create_workspace
  {
    "description": "Create a new workspace — the top-level tenant that holds projects and members. The caller becomes its first ADMIN. Use list_workspaces first to check whether a suitable workspace already exists; a fresh workspace is usually only needed for a genuinely new organization/team, not a new project (use create_project for that — it belongs INSIDE an existing workspace). The response echoes `id` and `slug` prominently since downstream calls (create_project, list_projects) need the workspace id.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Workspace display name.",
--- pinned/create_workspace_page
+++ observed/create_workspace_page
  {
    "description": "Create a page in the WORKSPACE docs space — org-level knowledge that outlives any single project (handbook, runbooks, ADRs, conventions, postmortems). Identical to create_page except the page belongs to the workspace, not a project, and shows up in list_workspace_pages. `[[Page Title]]` links resolve workspace-wide (other workspace pages first, then any project in the workspace), so a workspace page can link straight into project docs and will appear in their get_page_backlinks. Issue keys are NOT auto-linked here — a workspace page has no project to resolve keys against; link the project page instead. `parentId` must be another WORKSPACE page (400 otherwise); omit/null for top-level. Everything after creation uses the same by-id tools as project pages (get_page, update_page, move_page, delete_page, versions, backlinks). Requires `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "content": {
          "description": "Markdown body (default empty string). Capped at 256 KB (UTF-8 bytes).",
--- pinned/delete_comment
+++ observed/delete_comment
  {
    "description": "Delete a comment permanently. Author-or-project-ADMIN gated (same rule as the API's work-log edit/delete). Irreversible.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "commentId": {
          "description": "Comment id (from list_comments).",
--- pinned/delete_dashboard
+++ observed/delete_dashboard
  {
    "description": "Delete a dashboard. Its gadgets cascade. Requires project MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Dashboard id.",
--- pinned/delete_dashboard_gadget
+++ observed/delete_dashboard_gadget
  {
    "description": "Delete a gadget from a dashboard. Requires project MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Gadget id.",
--- pinned/delete_issue
+++ observed/delete_issue
  {
    "description": "Delete an issue permanently. Requires MEMBER+. Irreversible.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id to delete.",
+         "description": "Issue id or key (e.g. \"NL-5\") to delete.",
          "type": "string"
        }
      },
--- pinned/delete_page
+++ observed/delete_page
  {
    "description": "Delete a page. Rejected with a 400 if it still has child pages — move them elsewhere (update_page with a new parentId) or delete them first; this keeps a whole subtree from disappearing as a side effect of deleting one parent page. Irreversible — there is no undo and no cascade-delete-subtree option in this API. CHECK get_page_backlinks FIRST: deleting a page other pages link to leaves their [[links]] dangling as unresolved references (the graph stays consistent but readers hit dead ends) — re-point or update the linking pages first, or archive instead. The response reports `orphanedBacklinks` (how many inbound links the delete just orphaned); a non-zero value you did not expect means you skipped that check. Requires `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Page id.",
--- pinned/delete_page_template
+++ observed/delete_page_template
  {
    "description": "Delete a doc (page) template. Pages already created from it are unaffected — they are ordinary pages and keep their content. Irreversible, and that includes the six built-in starters: a deleted starter is NOT re-seeded on the next API restart (seeding is keyed on a per-workspace marker, not on \"this workspace has no templates\"), so deleting one is permanent unless you re-create it by hand. Requires workspace ADMIN, and `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Doc template id.",
--- pinned/delete_quick_link
+++ observed/delete_quick_link
  {
    "description": "Remove a personal quick link.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Quick link id.",
--- pinned/delete_workflow
+++ observed/delete_workflow
  {
    "description": "Delete a named workflow. Its transitions cascade and any boards using it have their workflow cleared. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Workflow id.",
--- pinned/delete_workflow_transition
+++ observed/delete_workflow_transition
  {
    "description": "Delete a workflow-scoped transition. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Transition id.",
--- pinned/get_burndown_report
+++ observed/get_burndown_report
  {
    "description": "Burndown report: daily ideal vs remaining story points for one sprint.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/get_cfd_report
+++ observed/get_cfd_report
  {
    "description": "Cumulative Flow Diagram: per-day count of issues in each status category (TODO / IN_PROGRESS / DONE) over a window. Defaults to 30 days.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "days": {
          "description": "Window size in days (default 30).",
--- pinned/get_dashboard
+++ observed/get_dashboard
  {
    "description": "Get a dashboard with all of its gadgets (id, title, NLQL query, visualization, config), ordered by grid position.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "dashboardId": {
          "description": "Dashboard id.",
--- pinned/get_dashboard_data
+++ observed/get_dashboard_data
  {
    "description": "Evaluate every gadget on a dashboard server-side (filters the project’s issues through each gadget’s NLQL query, then shapes the result per visualization). A gadget with an invalid query or unresolvable config gets a per-gadget `error` field instead of data.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "dashboardId": {
          "description": "Dashboard id.",
--- pinned/get_epic_overview
+++ observed/get_epic_overview
  {
    "description": "One tool call for \"what's in this epic and where does it stand\": the epic itself (key, title, status, type), its children in compact form (id, key, title, type, status), a per-status breakdown of the children, and a done/total progress figure (done = children whose status category is DONE). Composed from the same parent→children relation the issue drawer uses (a plain get_issue already returns children, but only status/type — not assignee/priority/startDate; call get_issue on a specific child for its full detail). `epicId` can be any issue id with children, not only EPIC-typed ones — a story with sub-tasks works identically. `limit`/`offset`/`verbose` apply to the children list (default compact, same as list_issues).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "epicId": {
-         "description": "Epic (or any parent) issue id.",
+         "description": "Epic (or any parent) issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "limit": {
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/get_github_automation_config
+++ observed/get_github_automation_config
  {
    "description": "Read a project’s GitHub auto-transition-on-merge automation config: whether it’s enabled and the target status id a merged PR moves its linked issue(s) to. Off by default. Returns null when GitHub isn’t configured for the project. NEVER returns the webhook secret or PAT — this tool is a narrower surface than the REST GET on purpose, so even an admin-scoped token never sees a secret over MCP (configuring the repo/token itself stays unexposed — see \"Not exposed over MCP\"). Requires the `github:read` PAT scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/get_gitlab_automation_config
+++ observed/get_gitlab_automation_config
  {
    "description": "Read a project’s GitLab auto-transition-on-merge automation config. Mirrors `get_github_automation_config` exactly, including never returning the webhook secret/PAT. Requires the `gitlab:read` PAT scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/get_issue
+++ observed/get_issue
  {
    "description": "Get a single issue by id with its full detail.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        }
      },
--- pinned/get_issue_github_live_status
+++ observed/get_issue_github_live_status
  {
    "description": "Live PR/CI status for an issue’s linked GitHub pull requests — a real-time GitHub API call (state, merged, combined checks rollup), not the last webhook-delivered snapshot `list_issue_github_links` returns. Returns `[]` when GitHub isn’t configured or there are no linked PRs. Each entry carries `error` (and null fields) instead of failing the whole call when the live lookup for that one PR fails (rate limit, deleted PR, network). Requires the `github:read` PAT scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        }
      },
--- pinned/get_issue_gitlab_live_status
+++ observed/get_issue_gitlab_live_status
  {
    "description": "Live MR/pipeline status for an issue’s linked GitLab merge requests — a real-time GitLab API call (state, merged, latest pipeline status), not the last webhook-delivered snapshot `list_issue_gitlab_links` returns. Mirrors `get_issue_github_live_status` exactly, including per-link graceful degradation on a failed lookup. Requires the `gitlab:read` PAT scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        }
      },
--- pinned/get_issue_pages
+++ observed/get_issue_pages
  {
    "description": "The knowledge-base PAGES that reference this issue — \"what docs mention this work\". Powers the issue drawer's \"Linked pages\" section. Returns compact page refs (`{id, title}`); follow `id` into get_page to read the doc. Reverse of get_page_issues. Use this to find the spec/runbook/ADR behind an issue before starting it, or to see what documentation an issue change might invalidate. `truncated: true` means more pages reference the issue than the response cap.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id (not the key — the id).",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        }
      },
--- pinned/get_my_analytics
+++ observed/get_my_analytics
  {
    "description": "Personal analytics for the caller (their own throughput/cycle time) over a rolling day window. Defaults to 30 days.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "days": {
          "description": "Rolling window size in days (default 30).",
--- pinned/get_page
+++ observed/get_page
  {
    "description": "Get a knowledge-base page by id: title, full markdown content, hierarchy (`parentId`), author/last-editor, and timestamps. Defaults to ALSO orienting you in the knowledge graph in this same call — pass `includeLinks: false` to skip that and save two extra API calls when you only need the raw content. When included, `links.outgoing` is this page's own [[wiki-links]] split into `resolved` (pages that exist — follow `pageId` with another get_page/get_page_links to keep traversing) and `unresolvedTitles` (referenced but not yet written — candidates for create_page), and `links.backlinkCount` is how many OTHER pages link here (call get_page_backlinks for the full \"what links here\" list).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Page id.",
--- pinned/get_page_backlinks
+++ observed/get_page_backlinks
  {
    "description": "Walk backlinks to find everything referencing this page — \"what links here\", the INCOMING edge of the knowledge graph. Each item is the linking page as a compact ref (`sourcePageId`/`sourcePageTitle`) plus `sourceProjectId`/`sourceProjectKey`/`sourceWorkspaceId` and when the link was created. Already WORKSPACE-WIDE: a source can be in another project or in the workspace-docs space (`sourceProjectId: null`), never another workspace. Check this before editing or archiving a page to see what would be left dangling, or to find the pages most central to a topic (many backlinks = load-bearing doc — keep walking backlinks from those to map a whole subject area). Pairs with get_page_links (the reverse direction — this page's own outgoing links), get_page_graph (one project at once) and get_workspace_page_graph (the whole workspace at once).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
--- pinned/get_page_graph
+++ observed/get_page_graph
  {
    "description": "CROWN-JEWEL traversal call: load a project's ENTIRE knowledge graph in one shot — every page as a node (`{id, title, projectId, projectKey, updatedAt}`) and every resolved `[[wiki-link]]` as a directed edge (`{sourceId, targetId}`). Nodes carry `updatedAt`, so this one call also answers \"which docs are stale / what changed recently\". Load the graph to understand how the project's knowledge connects: spot hub pages (many edges — the docs everything depends on), orphaned pages (no edges either way — candidates to link up or archive), and navigable paths between two docs, all before drilling into any single page. Capped at 1000 nodes; `truncated: true` means the project has more pages than that and BOTH the node and edge sets were cut off (an edge touching a dropped node is dropped too, so the graph returned is always internally consistent) — treat it as a large sample, not the full picture, and fall back to get_page_links/get_page_backlinks for a specific page's exact neighbors. This view is narrowed to ONE project's own pages; because wiki-links resolve workspace-wide, a link crossing into another project (or into the workspace-docs space) is not in it — use get_workspace_page_graph for the whole workspace at once.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/get_page_issues
+++ observed/get_page_issues
  {
    "description": "The tracked ISSUES this page links to — the tracker↔docs bridge. A page auto-links an issue when its markdown mentions that issue key (e.g. \"NL-123\") in the SAME project; the link is (re)computed every time the page is saved. Returns compact issue refs (`{id, key, title, type, status}`) so you can jump from a design doc to the work it describes. Reverse of get_issue_pages (which pages document a given issue). `truncated: true` means the page mentions more issues than the response cap.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "pageId": {
          "description": "Page id.",
--- pinned/get_page_links
+++ observed/get_page_links
  {
    "description": "This page's own OUTGOING [[wiki-links]] — the links it makes, split into `resolved` (target pages that already exist, `{pageId, title}` — follow `pageId` into another get_page/get_page_links call to keep traversing the graph outward) and `unresolvedTitles` (titles referenced in the text with no matching page yet — the classic \"link first, write later\" flow; creating a page with that exact title does NOT retroactively resolve this edge — it only resolves the next time THIS page itself is saved). Pairs with get_page_backlinks (the reverse direction: who links TO this page) and get_page_graph (the whole project's graph in one call, for a wider traversal than walking page-by-page).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "pageId": {
          "description": "Page id.",
--- pinned/get_page_template
+++ observed/get_page_template
  {
    "description": "Get one doc (page) template in full, including its markdown body — which list_page_templates omits by default. Read this before update_page_template: the update is a partial patch, so you need the current `content` in hand to edit it rather than replace it wholesale. Requires `pages:read` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Doc template id (from list_page_templates).",
--- pinned/get_page_version
+++ observed/get_page_version
  {
    "description": "Get one historical version of a page: its title + content exactly as of that snapshot (`pageId`, `versionNumber` — from list_page_versions). Compare against the current get_page result to see what changed, or hand the content to restore_page_version to roll back.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "pageId": {
          "description": "Page id.",
--- pinned/get_personal_board
+++ observed/get_personal_board
  {
    "description": "Get the caller’s personal (non-project) board: columns in order, each with its cards in rank order. Three default columns (\"To Do\", \"Doing\", \"Done\") are created automatically on first access. Use this to find columnId/card ids for create_personal_card / update_personal_card.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
      "properties": {},
      "type": "object"
    },
--- pinned/get_project_analytics
+++ observed/get_project_analytics
  {
    "description": "Team analytics for a project over a rolling day window (throughput, cycle time, workload by assignee). Defaults to 30 days.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "days": {
          "description": "Rolling window size in days (default 30).",
--- pinned/get_project_context
+++ observed/get_project_context
  {
    "description": "Call this FIRST when starting work on a Next Lane project — it is the persistent handoff document previous agent runs (or humans) left for you: current goal/state, decisions made, in-flight work, next steps, gotchas. Returns `content` (markdown, empty string if nothing has been written yet — this never 404s), `updatedAt`/`updatedBy`, and a `staleness` object: `changesSinceUpdate` counts project activity (issue changes + project-scoped audit events) newer than the document, and `lastProjectActivityAt` is the most recent one. A non-zero `changesSinceUpdate` means real work has happened since this was written — treat the handoff as a starting point to verify against recent activity (e.g. list_issues, get_epic_overview), not gospel. Pairs with update_project_context, which you should call before ending your own session.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/get_project_csv
+++ observed/get_project_csv
  {
    "description": "Export a project’s issues as CSV text (same data as the web app’s \"Export CSV\" button). Optional NLQL `q` filter narrows the rows. The result is returned as raw CSV text, not JSON. Very large exports may be truncated by the API.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id to export.",
--- pinned/get_roadmap
+++ observed/get_roadmap
  {
    "description": "Project roadmap: every epic with its scheduled window, how far its children overrun that window, plus dated sprints, release milestones and BLOCKS dependencies between epics. Built for the questions an agent is actually asked — \"what is slipping?\" is `overrunDays > 0`, and \"is the plan even possible?\" is a dependency with `violated: true` (a blocker scheduled to finish after the epic it blocks is due to start). Compact by default: epics are `{id, key, title, start, end, progress, overrunDays, childrenOutside}` — pass `verbose: true` for the full payload including rollup dates.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/get_unread_notification_count
+++ observed/get_unread_notification_count
  {
    "description": "Get the caller’s unread notification count.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
      "properties": {},
      "type": "object"
    },
--- pinned/get_velocity_report
+++ observed/get_velocity_report
  {
    "description": "Velocity report: committed vs completed story points per completed/active sprint.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/get_velocity_trend_report
+++ observed/get_velocity_trend_report
  {
    "description": "Cross-sprint velocity trend: the same committed/completed points as get_velocity_report, bounded to the project's most recent N sprints (default 6, max 24) — \"are we speeding up or slowing down\" without paging through the full velocity report. Also powers the dashboard VELOCITY_TREND gadget.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/get_workflow
+++ observed/get_workflow
  {
    "description": "Get a single named workflow by id, including its full list of transitions (from/to status, issue type, gates).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "workflowId": {
          "description": "Workflow id.",
--- pinned/get_workspace_page_graph
+++ observed/get_workspace_page_graph
  {
    "description": "The whole WORKSPACE's knowledge graph in one call — every page in every project of the workspace PLUS the workspace-level docs space, as one connected graph. Same payload as get_page_graph (nodes `{id, title, projectId, projectKey, updatedAt}` — `projectId: null` marks a workspace-level page — edges `{sourceId, targetId}`, `truncated`, 1000-node cap). Use this over get_page_graph when the question spans projects: \"what is connected to this handbook page anywhere in the org\", which projects depend on a shared runbook, or where the cross-project hubs are. Wiki-links resolve workspace-wide, so cross-project edges are real and only appear here. Requires `pages:read` scope when the token is scoped; scoped to workspaces you are a member of.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "workspaceId": {
          "description": "Workspace id.",
--- pinned/link_issues
+++ observed/link_issues
  {
    "description": "Create a typed dependency/relation from a source issue to a target issue — e.g. type BLOCKS to mark that the source blocks the target, or BLOCKED_BY for the reverse. The target may be an issue key (e.g. \"NL-5\") or an id; both issues must be in the same project. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Source issue id (the link is from this issue).",
+         "description": "Source issue id or key (the link is from this issue).",
          "type": "string"
        },
        "target": {
--- pinned/list_automations
+++ observed/list_automations
  {
    "description": "List a project’s automation rules (trigger, condition, actions). Compact `{id, name, trigger, enabled}` per rule by default — pass `verbose: true` for the full object (condition, actions, order, timestamps).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_boards
+++ observed/list_boards
  {
    "description": "List all boards for a project (kanban/scrum boards). Compact `{id, name, type, isDefault}` per board by default — pass `verbose: true` for the full board (filterQuery, colorRules, workflowId, defaultGroupBy, timestamps).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_checklist
+++ observed/list_checklist
  {
    "description": "List an issue’s checklist items (with done state + ids). Already a minimal shape — no verbose mode; `limit`/`offset` page a long checklist.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "limit": {
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        }
--- pinned/list_comments
+++ observed/list_comments
  {
    "description": "List the comments on an issue (newest-relevant order). Full comment (including body) is already the minimal useful shape — no verbose mode; `limit`/`offset` page a long comment thread.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "limit": {
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        }
--- pinned/list_components
+++ observed/list_components
  {
    "description": "List a project’s components with their ids. Compact `{id, name, defaultAssignee}` per component by default — pass `verbose: true` for the full object (description, timestamps).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_custom_fields
+++ observed/list_custom_fields
  {
    "description": "List a project’s custom field definitions (key, name, type, options). Needed to set customFields on issues. Compact `{id, key, name, type, required}` per field by default — pass `verbose: true` for the full object (options, appliesToTypes, showOnCard, order).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_dashboards
+++ observed/list_dashboards
  {
    "description": "List a project’s configurable dashboards. Already a minimal summary shape (`{id, name, order, gadgetCount}`, plus timestamps in `verbose: true`); `limit`/`offset` cap a project with many dashboards.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_epic_children
+++ observed/list_epic_children
  {
    "description": "The child issues of one roadmap epic with their scheduled windows. `fromSprint: true` means the window is inherited from the sprint the issue sits in rather than set on the issue itself — those dates cannot be changed by scheduling the issue directly.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "epicId": {
-         "description": "Epic issue id.",
+         "description": "Epic issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "projectId": {
--- pinned/list_issue_gitea_links
+++ observed/list_issue_gitea_links
  {
    "description": "List an issue’s linked Gitea pull requests / commits / branches (populated by the push/PR webhook integration, if configured). Requires the `gitea:read` PAT scope when the token is scoped. Does not include the project’s webhook secret — configuring the integration itself is not exposed over MCP (admin-only, secret-bearing), mirroring the GitHub/GitLab integrations. v1 has no live-status/automation counterpart (no `get_issue_gitea_live_status` / `get_gitea_automation_config` tools — Gitea integration v1 is links-only). Already a minimal shape; `limit`/`offset` cap an issue with many linked PRs/commits.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "limit": {
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        }
--- pinned/list_issue_github_links
+++ observed/list_issue_github_links
  {
    "description": "List an issue’s linked GitHub pull requests / commits (populated by the push/PR webhook integration, if configured). Requires the `github:read` PAT scope when the token is scoped. Does not include the project’s webhook secret — configuring the integration itself is not exposed over MCP (admin-only, secret-bearing). Already a minimal shape; `limit`/`offset` cap an issue with many linked PRs/commits.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "limit": {
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        }
--- pinned/list_issue_gitlab_links
+++ observed/list_issue_gitlab_links
  {
    "description": "List an issue’s linked GitLab merge requests / commits / branches (populated by the push/MR webhook integration, if configured). Requires the `gitlab:read` PAT scope when the token is scoped. Does not include the project’s webhook secret — configuring the integration itself is not exposed over MCP (admin-only, secret-bearing), mirroring the GitHub integration. Already a minimal shape; `limit`/`offset` cap an issue with many linked MRs/commits.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "limit": {
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        }
--- pinned/list_issue_links
+++ observed/list_issue_links
  {
    "description": "List the typed links (dependencies / relations) for an issue, resolved from that issue's perspective — e.g. an issue it blocks, or is blocked by. Each entry includes the link id (needed for unlink_issues). Already a minimal shape; `limit`/`offset` cap a very heavily-linked issue.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id to list links for.",
+         "description": "Issue id or key (e.g. \"NL-5\") to list links for.",
          "type": "string"
        },
        "limit": {
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        }
--- pinned/list_issue_templates
+++ observed/list_issue_templates
  {
    "description": "List a project’s issue templates (name, target issue type, default title/description/priority/assignee/component/labels). Use with create_issue_from_template. Compact `{id, name, issueType}` per template by default — pass `verbose: true` for the full object (default title/description/priority/assignee/component/labels).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_issues
+++ observed/list_issues
  {
    "description": "List issues. Two modes: (1) default — filter by project/sprint/assignee/type/status and/or a short free-text `q`, cursor-paginated via `cursor` + `limit`; (2) `query` set — a full NLQL expression (the same language as the board search bar / saved filters / get_project_csv, e.g. `status = \"In Progress\" AND assignee = me()`), validated and evaluated server-side against the whole project so you never have to pull every issue to find one. Requires projectId; the structural filters and `q`/`cursor` are ignored in this mode — express them inside the NLQL string instead. An invalid query fails with the API parser's own message (not a generic error) — this includes an unresolvable `assignee`/`reporter`/`sprint` value (e.g. a misspelled name): it 400s naming the value rather than silently returning zero issues, so a \"0 results\" answer for those fields always means the name was found and genuinely has nothing matching. Returns a compact `{key, title, status, assignee, priority, type}` per issue by default — pass `verbose: true` for the full issue object (id, description, labels, custom fields, etc). Response shape: `{ items, limit, hasMore, total?, offset?, nextCursor? }` — `total`/`offset` are only present in `query` mode (default mode is cursor-paginated and does not compute a full count).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "assigneeId": {
          "description": "Filter by assignee user id (ignored when `query` is set).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_labels
+++ observed/list_labels
  {
    "description": "List the labels defined in a project, with their ids and colors. Use this to find a labelId for add_issue_label / remove_issue_label. Already a minimal shape; `limit`/`offset` cap a project with many labels.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
--- pinned/list_notifications
+++ observed/list_notifications
  {
    "description": "List the caller’s notifications, newest first. Compact `{id, type, issueKey, message, read}` per notification by default — pass `verbose: true` for the full object (actor, issueId, projectId, createdAt). Response always includes `unreadCount`.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_page_templates
+++ observed/list_page_templates
  {
    "description": "List the doc (page) templates available for a scope — reusable markdown skeletons for new pages. Pass `projectId` for a project (returns the project’s own templates FIRST, then the workspace-wide ones it inherits) or `workspaceId` for the workspace-docs space (workspace templates only). Exactly one of the two is required. Use the returned id with create_page_from_template. Compact `{id, name, description, scope}` per template by default — pass `verbose: true` for the full object including the markdown body. Requires `pages:read` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        },
        "workspaceId": {
--- pinned/list_page_versions
+++ observed/list_page_versions
  {
    "description": "A page's version history, newest first, cursor-paginated via `cursor` + `limit`. Each item is a compact summary (no content — call get_page_version for a specific version's full title+content). Use restore_page_version to roll a page back to an earlier version (writes a NEW version with the old content — history is never rewritten or truncated).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "cursor": {
          "description": "Pagination cursor from a prior call's nextCursor.",
--- pinned/list_pages
+++ observed/list_pages
  {
    "description": "List a project's knowledge-base pages, flattened from its page tree into sidebar (rank) order. Use this to discover pageId values and see the doc hierarchy before drilling into a specific page. Compact refs by default: `{id, title, parentId, archived}` — `parentId: null` means a top-level page. The underlying tree call carries no timestamps/content, so compact refs omit `updatedAt`; pass `verbose: true` to hydrate every page in the RETURNED SLICE with its full object (content, author, lastEditedBy, timestamps) — this issues one extra API call per item, fetched concurrently and capped at 25 hydrated pages per call (page through the rest with `offset`), or use get_page directly for a single page. For the wiki-link graph instead of the folder hierarchy, use get_page_graph.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_project_activity
+++ observed/list_project_activity
  {
-   "description": "Unified \"what changed\" feed for a project: issue field changes (status/assignee/priority/etc.), comments, and work logs across every issue, chronologically merged into one cursor-paginated stream. This is the cheap alternative to polling list_issues/get_issue blind — answer \"what changed since I last looked\" or \"did someone update NL-42\" in one call. Pass `since` (ISO-8601 timestamp) to start from a known point in time, or `cursor` (from a prior call's `nextCursor`) to continue where you left off; omitting both starts from the beginning of the project's history. Results are OLDEST-of-the-page-first (ascending), so paging forward with `nextCursor` walks events in the order they happened. Each item has a `kind` (ISSUE_FIELD | COMMENT | WORK_LOG), the issue it belongs to (`issueId`/`issueKey`), who did it, and a one-line `summary` cheap to skim without interpreting field/from/to yourself.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
+   "description": "Unified \"what changed\" feed for a project: issue field changes (status/assignee/priority/etc.), comments, and work logs across every issue, chronologically merged into one cursor-paginated stream. This is the cheap alternative to polling list_issues/get_issue blind — answer \"what changed since I last looked\" or \"did someone update NL-42\" in one call. Pass `since` (ISO-8601 timestamp) to start from a known point in time, or `cursor` (from a prior call's `nextCursor`) to continue where you left off; omitting both starts from the beginning of the project's history. Results are OLDEST-of-the-page-first (ascending), so paging forward with `nextCursor` walks events in the order they happened. Each item is `{kind, issueKey, actor, summary, field?, from?, to?, at}` — `kind` is ISSUE_FIELD | COMMENT | WORK_LOG, `actor` is a display name (or null for a system change), and `summary` is a one-line, already-human-readable line cheap to skim: status/assignee/sprint/component/label changes are resolved to names (never a raw id) both in `summary` and in `field`/`from`/`to`, so \"what changed\" never requires a follow-up list_statuses/list_users call. `field`/`from`/`to` are omitted for COMMENT/WORK_LOG items and for a plain \"created the issue\" event (summary already says so).",
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "cursor": {
          "description": "Pagination cursor from a prior call's nextCursor.",
--- pinned/list_project_role_overrides
+++ observed/list_project_role_overrides
  {
    "description": "List a project’s EFFECTIVE members: every workspace member, each with their workspace role, their effective role on this project, and whether that role comes from a per-project override (`isOverride`). Use to find a userId for set_project_role_override / remove_project_role_override. Compact `{userId, name, effectiveRole, isOverride}` per member by default — pass `verbose: true` for the full object (full user, workspaceRole).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_projects
+++ observed/list_projects
  {
    "description": "List projects in a workspace. Provide workspaceId to scope the list. Use this first to discover projectId values for other tools. Compact `{id, key, name}` per project by default — pass `verbose: true` for the full project object.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        },
        "workspaceId": {
--- pinned/list_quick_links
+++ observed/list_quick_links
  {
    "description": "List the caller’s personal shortcut links (sidebar quick links), ordered. Compact `{id, label, url, group}` per link by default — pass `verbose: true` for the full object (color, order, timestamps).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_saved_filters
+++ observed/list_saved_filters
  {
    "description": "List a project’s saved NLQL filters (own + shared). Compact `{id, name, query, shared, projectId}` per filter by default — pass `verbose: true` for the full object (ownerId, timestamps).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_sprints
+++ observed/list_sprints
  {
    "description": "List a project’s sprints (with state, dates, goal). Compact `{id, name, state}` per sprint by default — pass `verbose: true` for the full object (goal, startDate, endDate).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_statuses
+++ observed/list_statuses
  {
    "description": "List the workflow statuses (columns) defined for a project. Status ids are needed to build workflow transitions and move issues. Compact `{id, name, category}` per status by default — pass `verbose: true` for the full object (order, wipLimit).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_users
+++ observed/list_users
  {
    "description": "List users the caller can see (workspace members). Use to find an assigneeId / default-assignee id for create_issue, update_issue, etc. Optional `q` filters server-side by a case-insensitive name/email substring match (e.g. `q: \"dana\"`) so resolving \"who is Dana\" does not require paging through every member. Compact `{id, name, email}` per user by default — pass `verbose: true` for the full object (avatarColor, emailNotifications, createdAt).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_versions
+++ observed/list_versions
  {
    "description": "List a project’s versions/releases with their ids and state. Compact `{id, name, state, releaseDate, issueCount}` per version by default — pass `verbose: true` for the full object (description, timestamps).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_workflows
+++ observed/list_workflows
  {
    "description": "List named workflows for a project, each with its transition and board counts. A workflow defines the allowed status transitions (the SDLC). Compact `{id, name, enforced, transitionCount, boardCount}` per workflow by default — pass `verbose: true` for the full object.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/list_worklogs
+++ observed/list_worklogs
  {
    "description": "List the time-tracking work logs on an issue. Already a minimal shape — no verbose mode; `limit`/`offset` page an issue with many log entries.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "limit": {
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        }
--- pinned/list_workspace_pages
+++ observed/list_workspace_pages
  {
    "description": "The WORKSPACE docs space — pages that belong to the org rather than to any one project (handbook, runbooks, ADRs, policies). Flattened from the workspace page tree into sidebar (rank) order, same compact refs as list_pages (`{id, title, parentId, archived}`) and the same `verbose: true` hydration (capped at 25 pages per call). This lists ONLY workspace-level pages — project pages are not included; use list_pages per project for those, or get_workspace_page_graph for both at once as a graph. Read from here before assuming a convention isn't written down: cross-project knowledge lives here. Requires `pages:read` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        },
        "workspaceId": {
--- pinned/list_workspaces
+++ observed/list_workspaces
  {
    "description": "List all workspaces the authenticated token can access. Use to find a workspaceId for list_projects. Compact `{id, name, slug}` per workspace by default — pass `verbose: true` for the full object.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max items to return (default 50, max 200).",
-         "description": "Number of items to skip, for paging through a long list (default 0).",
+         "description": "Items to skip, for paging (default 0).",
          "minimum": 0,
          "type": "integer"
        },
-         "description": "Return the full API object for each item instead of the compact default fields below. Only set this when you actually need the extra fields — it multiplies the response size.",
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
          "type": "boolean"
        }
      },
--- pinned/mark_all_notifications_read
+++ observed/mark_all_notifications_read
  {
    "description": "Mark all of the caller’s notifications as read.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
      "properties": {},
      "type": "object"
    },
--- pinned/mark_notification_read
+++ observed/mark_notification_read
  {
    "description": "Mark one of the caller’s notifications as read.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Notification id.",
--- pinned/move_issue
+++ observed/move_issue
  {
-   "description": "Move an issue to a different status. Pass boardId to apply that board’s enforced workflow rules; omit it for a plain status change.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
+   "description": "Move an issue to a different status. Pass boardId to apply that board’s enforced workflow rules; omit it for a plain status change. Returns a compact ack by default — `{id, key, status}` — not the full issue object (a status change does not touch title/assignee/priority/type, so echoing them back is pure overhead); pass `verbose: true` for the full object.",
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "boardId": {
          "description": "Board context for workflow-enforced moves.",
-         "description": "Issue id to move.",
+         "description": "Issue id or key (e.g. \"NL-5\") to move.",
          "type": "string"
        },
        "statusId": {
+       },
+       "verbose": {
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
+         "type": "boolean"
        }
      },
      "required": [
--- pinned/move_page
+++ observed/move_page
  {
    "description": "Reorder and/or reparent a page among siblings — the drag-and-drop move, computing a fractional-index rank server-side so you never need to know the rank encoding. Pass `beforeId`/`afterId` (an existing SIBLING of the destination parent) to place it precisely; omit both to append to the end of the destination sibling list. `parentId` omitted = keep the current parent (pure reorder); `parentId: null` = move to top-level; `parentId: <id>` = reparent under that page. Rejected with a 400 if the move would make the page its own ancestor (a cycle). For just changing a page's parent without caring about sibling position, update_page's `parentId` is simpler. Requires `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "afterId": {
          "description": "Place immediately after this sibling id (in the destination parent).",
--- pinned/remove_issue_label
+++ observed/remove_issue_label
  {
    "description": "Remove a label from an issue (issueId + labelId). Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue to unlabel.",
+         "description": "Issue id or key (e.g. \"NL-5\") to unlabel.",
          "type": "string"
        },
        "labelId": {
--- pinned/remove_project_role_override
+++ observed/remove_project_role_override
  {
    "description": "Clear a project role override, reverting the user back to inheriting their workspace role on this project. Requires EFFECTIVE project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/restore_page_version
+++ observed/restore_page_version
  {
    "description": "Roll a page back to an earlier version's title/content. This does NOT rewrite or delete history — it writes a brand-new version whose content equals the target version's (e.g. restoring version 3 on a page currently at version 8 creates version 9; versions 1-8 stay untouched). Re-syncs the page's outgoing [[wiki-links]] to match the restored content. Requires `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "pageId": {
          "description": "Page id.",
--- pinned/search_comments
+++ observed/search_comments
  {
    "description": "Full-text search issue COMMENTS — the place decisions actually get written down (\"Decision: we are going with Stripe\", \"reverted this, here is why\"). Use it for questions about WHY something is the way it is, or what was agreed, when you do not already know which issue holds the answer; list_comments only works if you do. Each hit is `{id, issueId, issueKey, issueTitle, projectId, projectKey, authorName, createdAt, snippet}` — the highlighted excerpt plus enough issue identity to cite the decision without a follow-up get_issue. Matched terms are wrapped in U+E000/U+E001 sentinels (not HTML). Server-side paged in the standard `{items, total, limit, offset, hasMore}` envelope. Requires the same access as issues (comments are issue data).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max hits per group (default 10, max 50). Applied server-side; each hit includes a snippet, so keep it small.",
--- pinned/search_issues
+++ observed/search_issues
  {
-   "description": "Full-text search issues by title/key/description. Scope to one project with projectId, or omit it to search everything the caller can access. Every hit carries a `snippet`: a relevance-ranked, highlighted excerpt of the matching DESCRIPTION text, so you can judge which issues are actually relevant from this one call — do NOT fetch each hit with get_issue just to find out. Matched terms are wrapped in U+E000/U+E001 (invisible Private Use Area sentinels, not HTML); ignore them or strip them, they are only markers. `limit`/`offset` are real SERVER-SIDE paging: `total`/`hasMore` describe the `issues` array and `total` is the true match count, not the page length — page with `offset` while `hasMore`. Returns the minimal `SearchIssueDto` shape (no verbose mode) plus a `projects` array of matched project names/keys (paged by the same window; its count is `projectsTotal`, normally tiny). Looking for a DECISION rather than an issue? Use search_comments.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
+   "description": "Full-text search issues by title/key/description. Scope to one project with projectId, or omit it to search everything the caller can access. Every hit carries a `snippet`: a relevance-ranked, highlighted excerpt of the matching DESCRIPTION text, so you can judge which issues are actually relevant from this one call — do NOT fetch each hit with get_issue just to find out. Matched terms are wrapped in U+E000/U+E001 (invisible Private Use Area sentinels, not HTML); ignore them or strip them, they are only markers. `limit`/`offset` are real SERVER-SIDE paging: `total`/`hasMore` describe the `items` array and `total` is the true match count, not the page length — page with `offset` while `hasMore`. Returns the minimal `SearchIssueDto` shape (no verbose mode) plus a `projects` array of matched project names/keys (paged by the same window; its count is `projectsTotal`, normally tiny). Looking for a DECISION rather than an issue? Use search_comments.",
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max hits per group (default 10, max 50). Applied server-side; each hit includes a snippet, so keep it small.",
--- pinned/search_pages
+++ observed/search_pages
  {
    "description": "Full-text search the knowledge base: relevance-ranked matches over page TITLES AND BODY CONTENT (Postgres FTS), scoped to what the caller can access. The cheapest way to find the right doc — prefer this over listing/reading pages one by one when you know words that would appear in it (\"deploy runbook\", an error message, a feature name). Scope to one project with projectId or omit it to search all accessible projects. Each hit is `{id, title, projectId, projectKey, archived, snippet}`, where `snippet` is a relevance-ranked, highlighted excerpt of the matching BODY text — enough to answer \"what do we know about X?\" from this call alone. Only follow `id` into get_page when you need the full document (it can be up to 256 KB); reading every hit to find out which one mattered is the mistake this snippet exists to prevent. Matched terms are wrapped in U+E000/U+E001 (invisible Private Use Area sentinels, not HTML); ignore or strip them. `limit`/`offset` are real SERVER-SIDE paging in the standard `{items, total, limit, offset, hasMore}` envelope — `total` is the true match count, not the page length. From a hit, get_page_links/get_page_backlinks traverse outward; pairs with get_page_graph (structure-first discovery) the way search pairs with browsing.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "limit": {
          "description": "Max hits per group (default 10, max 50). Applied server-side; each hit includes a snippet, so keep it small.",
--- pinned/set_github_automation_config
+++ observed/set_github_automation_config
  {
    "description": "Turn a project’s auto-transition-on-merge automation on/off and/or set its target status: a `merged` PR webhook event then moves every linked issue to that status, reusing the same workflow-transition enforcement + automation-bypass path the automation engine’s TRANSITION action uses. Requires the integration to already be connected (`get_github_automation_config` returns non-null) — this tool does NOT connect a repo/token (that stays admin-only/web-UI-only, secret-bearing). Enabling for the first time requires `statusId` (a project status id from `list_statuses`); omit it to keep the currently-stored target while just flipping `enabled`. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "enabled": {
          "description": "Turn auto-transition-on-merge on or off.",
--- pinned/set_gitlab_automation_config
+++ observed/set_gitlab_automation_config
  {
    "description": "Turn a project’s GitLab auto-transition-on-merge automation on/off and/or set its target status. Mirrors `set_github_automation_config` exactly. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "enabled": {
          "description": "Turn auto-transition-on-merge on or off.",
--- pinned/set_issue_parent
+++ observed/set_issue_parent
  {
-   "description": "Set or clear an issue’s parent — a focused shortcut for the most common re-parenting case (e.g. nest a subtask under a story, or a story under an epic). Pass parentId to attach, or parentId:null to detach. Both issues must be in the same project. (update_issue can do this too, alongside other fields.)",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
+   "description": "Set or clear an issue’s parent — a focused shortcut for the most common re-parenting case (e.g. nest a subtask under a story, or a story under an epic). Pass parentId to attach, or parentId:null to detach. Both issues must be in the same project. (update_issue can do this too, alongside other fields.) Returns a compact ack by default — `{id, key, title, status, assignee, priority, type}` — not the full issue object; pass `verbose: true` for that.",
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "The child issue id to re-parent.",
+         "description": "The child issue id or key (e.g. \"NL-5\") to re-parent.",
          "type": "string"
        },
        "parentId": {
+       },
+       "verbose": {
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
+         "type": "boolean"
        }
      },
      "required": [
--- pinned/set_issue_versions
+++ observed/set_issue_versions
  {
    "description": "Set the full list of versions (fix-versions) on an issue, replacing any existing. Pass an empty array to clear. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "issueId": {
-         "description": "Issue id.",
+         "description": "Issue id or key (e.g. \"NL-5\").",
          "type": "string"
        },
        "versionIds": {
--- pinned/set_project_role_override
+++ observed/set_project_role_override
  {
    "description": "Set (create or replace) a per-project role override for a workspace member — e.g. elevate a MEMBER to project ADMIN, or restrict them to project VIEWER, scoped to this project only. Requires EFFECTIVE project ADMIN (a project override can itself grant this, not just workspace ADMIN). Refuses to override a workspace ADMIN (they always have full access).",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "projectId": {
          "description": "Project id.",
--- pinned/unlink_issues
+++ observed/unlink_issues
  {
    "description": "Delete an issue link by its link id (get it from list_issue_links). The reverse link is removed automatically. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "linkId": {
          "description": "Issue-link id to delete.",
--- pinned/update_board
+++ observed/update_board
  {
    "description": "Update a board — rename, change type, set its default NLQL filter (filterQuery; null clears so the board shows everything), or set its default swimlane grouping (defaultGroupBy; applied when a link to the board doesn't include its own ?group= override — one of \"assignee\" | \"priority\" | \"type\" | \"epic\" | \"component\" | \"sprint\" | \"label\", or \"cf:<customFieldId>\" for a project SELECT custom field; null clears it). Requires MEMBER+. (Use assign_board_workflow for the workflow.)",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "boardId": {
          "description": "Board id.",
--- pinned/update_checklist_item
+++ observed/update_checklist_item
  {
    "description": "Update a checklist item — rename and/or toggle done. Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "done": {
          "description": "Mark complete/incomplete.",
--- pinned/update_comment
+++ observed/update_comment
  {
    "description": "Edit a comment's body. Author-or-project-ADMIN gated (same rule as the API's work-log edit/delete): the original author or a project admin can edit; anyone else gets a 403. Use this for mid-session corrections instead of piling on new comments.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "body": {
          "description": "New comment body (markdown).",
--- pinned/update_dashboard
+++ observed/update_dashboard
  {
    "description": "Rename a dashboard and/or change its display order. Requires project MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "id": {
          "description": "Dashboard id.",
--- pinned/update_dashboard_gadget
+++ observed/update_dashboard_gadget
  {
    "description": "Update a gadget’s title, NLQL query, visualization, and/or config (config is merged with the existing value, not replaced). Requires project MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "config": {
-         "additionalProperties": false,
          "description": "Visualization + grid-layout settings for a gadget.",
          "properties": {
            "columns": {
--- pinned/update_issue
+++ observed/update_issue
  {
-   "description": "Update fields on an existing issue. Only the fields you pass are changed (partial update). Use parentId to re-parent an issue (e.g. attach a subtask to an epic/story) or pass parentId:null to unparent it; the same null-to-clear rule applies to assigneeId, sprintId, componentId, storyPoints, startDate, dueDate, and originalEstimateMinutes. When both startDate and dueDate end up set, startDate must be <= dueDate. To change status use move_issue (it can apply workflow rules); to link issues use link_issues.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
+   "description": "Update fields on an existing issue. Only the fields you pass are changed (partial update). Use parentId to re-parent an issue (e.g. attach a subtask to an epic/story) or pass parentId:null to unparent it; the same null-to-clear rule applies to assigneeId, sprintId, componentId, storyPoints, startDate, dueDate, and originalEstimateMinutes. When both startDate and dueDate end up set, startDate must be <= dueDate. To change status use move_issue (it can apply workflow rules); to link issues use link_issues. Returns a compact ack by default — `{id, key, title, status, assignee, priority, type}` — not the full issue object; pass `verbose: true` for that.",
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "assigneeId": {
          "description": "Assignee user id, or null to unassign.",
-         "description": "Issue id to update.",
+         "description": "Issue id or key (e.g. \"NL-5\") to update.",
          "type": "string"
        },
        "originalEstimateMinutes": {
+       },
+       "verbose": {
+         "description": "Return the full API object per item instead of the compact default fields. Only set when needed — it multiplies response size.",
+         "type": "boolean"
        }
      },
      "required": [
--- pinned/update_page
+++ observed/update_page
  {
    "description": "Update a page. Only the fields you pass are changed (partial update). Changing `title` and/or `content` writes a new version snapshot (list_page_versions/restore_page_version) and re-syncs this page's outgoing [[wiki-links]] to match the new content (resolved workspace-wide). Works on project AND workspace-docs pages alike. `parentId` re-parents the page within its own tree (null = move to top-level; omit to leave unchanged) — rejected with a 400 if it would create a cycle or the new parent is in a different scope (another project, or the workspace-docs space); use move_page instead if you also care about sibling position. `archived: true` hides it from the default sidebar view without deleting it (`archived: false` unhides it). Requires `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "archived": {
          "description": "Archive (true) or unarchive (false) the page.",
--- pinned/update_page_template
+++ observed/update_page_template
  {
    "description": "Update a doc (page) template. PARTIAL — only the fields you pass change, but any field you DO pass replaces its value outright, so get_page_template first when editing `content` rather than replacing it. Editing a template never touches pages already created from it; a template is a stamp, not a live layout. A built-in starter is edited exactly like a user-authored one — `builtIn` is informational. A template cannot be moved between scopes; create a new one and delete this one. Requires workspace ADMIN, and `pages:write` scope when the token is scoped.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "content": {
          "description": "New markdown body — REPLACES the old one.",
--- pinned/update_personal_card
+++ observed/update_personal_card
  {
    "description": "Edit and/or move a personal board card. To move it, pass columnId (the destination column) plus beforeId/afterId — the neighbor cards in that column used to compute the card’s new rank (omit both to place it at the end). Other fields (title, notes, color, dueDate) are a partial update.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "afterId": {
          "description": "Neighbor card that should come immediately after this one after the move.",
--- pinned/update_project_context
+++ observed/update_project_context
  {
    "description": "Before ending a work session on a Next Lane project — and after significant milestones or direction changes — replace the project's agent handoff document with a concise summary for the next run (which may be you, in a future session, with no memory of this one): current goal/state, decisions made, in-flight work, next steps, and gotchas. This is a FULL-CONTENT REPLACE, not an append or merge — call get_project_context first if you want to preserve any part of the existing document. Keep it current: replace stale content rather than growing it forever. Capped at 64 KB measured in UTF-8 bytes (the API returns a 400 with the exact limit if you exceed it); requires project MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "content": {
          "description": "Full markdown handoff document — replaces whatever is currently stored. Suggested structure: Current goal / State & decisions / In-flight work / Next steps / Gotchas.",
--- pinned/update_quick_link
+++ observed/update_quick_link
  {
    "description": "Rename, re-point, recolor, regroup, or reorder a personal quick link.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "color": {
          "description": "Hex accent color, or null to clear.",
--- pinned/update_sprint
+++ observed/update_sprint
  {
    "description": "Update a sprint — rename, change dates/goal, or set state (PLANNED → ACTIVE to start, ACTIVE → COMPLETED to close). Requires MEMBER+.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "endDate": {
          "type": "string"
--- pinned/update_status
+++ observed/update_status
  {
    "description": "Update a status — name, category, order, or WIP limit (null clears). Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "category": {
          "description": "Lifecycle category a status belongs to.",
--- pinned/update_workflow
+++ observed/update_workflow
  {
    "description": "Update a named workflow’s name, description, and/or enforced flag. Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "description": {
          "maxLength": 500,
--- pinned/update_workflow_transition
+++ observed/update_workflow_transition
  {
    "description": "Update a workflow-scoped transition (from/to status, issue type, name, gates). Requires project ADMIN.",
-   "execution": {
-     "taskSupport": "forbidden"
-   },
    "inputSchema": {
-     "$schema": "http://json-schema.org/draft-07/schema#",
-     "additionalProperties": false,
      "properties": {
        "fromStatusId": {
          "type": [
-           "additionalProperties": false,
            "description": "A single transition gate rule.",
            "properties": {
              "field": {

Current tools

Show all 132 tool fingerprints
add_checklist_item
ea36d5cd0a490790
add_comment
15b5617da13b4687
add_issue_label
58d74237feda2410
add_workflow_transition
7817f87182c2a351
add_worklog
f49e9d8d5241606d
assign_board_workflow
4e30802f5e17237a
bulk_update_issues
f81818aba125a221
create_automation
2e9f29d95d6a2656
create_board
1bf83e0be2844bd6
create_component
62ab93ba8067f447
create_custom_field
0968558605d681d0
create_dashboard
36015191a7a4eb4e
create_dashboard_gadget
2470408bea5f8093
create_issue
2cdcc59e3b140102
create_issue_from_template
ab13aeb5a3e13ee1
create_label
9e3d969a936c4702
create_page
a27a203c56005bfc
create_page_from_template
5fb63a578f2679a7
create_page_template
09d01449cb68c7da
create_personal_card
14d72243604ab6f1
create_project
9714a198a172f954
create_quick_link
a0296a7218cc2f6f
create_saved_filter
261e14e84c626bc7
create_sprint
219ea062e90951d1
create_status
11a078ed5f9be63b
create_version
40ba61cf37d894ab
create_workflow
fd4cfa82baa2949c
create_workflow_from_template
7cc74afdedec0271
create_workspace
f0805c9fc9a601ff
create_workspace_page
758f9c1495df3cfe
delete_comment
6315f41e7c2a4336
delete_dashboard
919279fe767c6b35
delete_dashboard_gadget
3b07f1900f398a97
delete_issue
36ac7f9b8c0add13
delete_page
dba392f6bd5f9673
delete_page_template
bde2d5c8b4662605
delete_quick_link
8fabb58cb1019331
delete_workflow
e8f038b7d1ca6bca
delete_workflow_transition
ccd34a7df38a35df
get_burndown_report
fadad8fc18fe8134
get_cfd_report
cab2a40c88cec87a
get_dashboard
00164e1c73d30ec2
get_dashboard_data
6a09198e7d448fb6
get_epic_overview
917f48330cd9b112
get_github_automation_config
4d7fc5621e474c5b
get_gitlab_automation_config
446ac929281c3c97
get_issue
f7f5e4dc1a89501c
get_issue_github_live_status
c662625de3774326
get_issue_gitlab_live_status
609724e7bef89d4f
get_issue_pages
01d99a827aaf1958
get_my_analytics
8da4beb8de3f59c0
get_page
b6b499a0b23e6008
get_page_backlinks
98bfb93870df726b
get_page_graph
239d79976a590e15
get_page_issues
29b2dcfe2f2a6288
get_page_links
22559ca1768bfc7e
get_page_template
9319493e606a6e18
get_page_version
268e0d10f128f200
get_personal_board
dc11cd3ee0e23fb0
get_project_analytics
dfe9d78d3571b1f7
get_project_context
dac3647d59599e00
get_project_csv
082ec95827ce83b2
get_roadmap
c53f9022fbf35592
get_unread_notification_count
e5bcdd3463cf204c
get_velocity_report
79989a34b69cef65
get_velocity_trend_report
05e0f4a81e64a44b
get_workflow
9c65d963c9fa7910
get_workspace_page_graph
0474b85feea3d07a
link_issues
2fc9db8ffb7fed11
list_automations
bd3ecb8a40f7b902
list_boards
c608d975b8fd5d11
list_checklist
dedee4bc9e720490
list_comments
6e1c97447ab6c99c
list_components
d8c1c77b34e3b95a
list_custom_fields
da5b313e8de981c9
list_dashboards
4b67c49a45cfecdc
list_epic_children
b2d8dbdc19296780
list_issue_gitea_links
b0740c646f8562c7
list_issue_github_links
0e40f3646088ffa7
list_issue_gitlab_links
bc596d1e4fe12f61
list_issue_links
61ddde59abd2b053
list_issue_templates
2c970aa12ff2a1cc
list_issues
cce0f2e5c3df669c
list_labels
38748f32a2c814ba
list_notifications
99f5bddbed2ac115
list_page_templates
dbf2494e7b99b233
list_page_versions
1aab9b7dda240a44
list_pages
9f8c4cca84a7a99f
list_project_activity
be4aa7b12f165e61
list_project_role_overrides
c0804e596c37fb00
list_projects
212390ef2b3f08db
list_quick_links
c3f4fd49fe7856b1
list_saved_filters
84a94341a11eed79
list_sprints
4cfe87b985d985b5
list_statuses
8a1153df463aefdd
list_users
381dc8870ca64156
list_versions
945ba30b5bd9fb10
list_workflows
8de0d7fc485adc80
list_worklogs
4ba141e187f7cab8
list_workspace_pages
1ad8740b1b650903
list_workspaces
37128b091311e1d8
mark_all_notifications_read
28c04550fe86b888
mark_notification_read
f281fdd72907e354
move_issue
301eabb2f52c1455
move_page
5fabed4714ac6d90
remove_issue_label
ee99e7b347cac945
remove_project_role_override
91d738faf1d431c8
restore_page_version
2340d68647d147cb
search_comments
569a9838ff70d705
search_issues
426c9889dae0a35d
search_pages
030ffef7a5b56130
set_github_automation_config
73ea3ee8c31ef22d
set_gitlab_automation_config
21047c1d42cffac0
set_issue_parent
9eb2bb58c7d73f83
set_issue_versions
6dbca458f9cabe39
set_project_role_override
ccd0e51753904871
unlink_issues
102332d260daef08
update_board
32a6307b94940e4f
update_checklist_item
233f89244ef0b56d
update_comment
3a62e8f3ef061032
update_dashboard
2aff4a3d97e73eab
update_dashboard_gadget
70998fc8f8155678
update_issue
be6978baeac39d71
update_page
18c250165fdba60e
update_page_template
e8cc390ec550d376
update_personal_card
a7b872098f9ff9d1
update_project_context
92d8016f3a901a43
update_quick_link
8a4db6c8b6906f33
update_sprint
dc96ad51eaefa40c
update_status
761420c21e8c7e0f
update_workflow
f591d20870427bd4
update_workflow_transition
3c64e1d64fb2d4dc

Watch this server yourself

If you run this server, put the proxy in front of it. It pins these exact fingerprints on first connect and stops the session if they move.

npx -y mcp-pin@0.2.3 -- <your @next-lane/mcp command>

Or subscribe to this page's RSS feed to be told when it changes.

Badge

mcp-pin status badge for @next-lane/mcp

The badge states one fact about time and nothing else. It never claims a server is safe.

[![mcp-pin](https://mcp-pin.gautamkhosla.com/badge/15d72bc5bf123b0b.svg)](https://mcp-pin.gautamkhosla.com/servers/15d72bc5bf123b0b.html)