Skip to content

execute allowlist omits the space-scoped /tasks paths when toolsets are narrowed #110

Open

Description

@martinmdrive

Describe the bug

When --toolsets narrows the active set, the execute path allowlist rejects the space-scoped forms of /tasks even though the tasks toolset is enabled. /api/tasks resolves, but /api/{spaceId}/tasks and /api/spaces/{spaceIdentifier}/tasks are both rejected as pathNotAllowed.

The rejection uses the message reserved for a path that belongs to no toolset, rather than the one for a path whose toolset is disabled — so the server is reporting that these paths are absent from the allowlist table entirely, which matches what the table contains.

This is the difference between a reachable endpoint and a useful one. /api/tasks is the unscoped listing; the space-scoped forms are the ones documented to accept project, states, fromCompletedDate and toCompletedDate. With them blocked there is no way to ask what happened to a given project's tasks over a date range.

Steps to reproduce

Start the server with toolsets narrowed, including tasks:

npx -y @octopusdeploy/mcp-server --toolsets projects,deployments,releases,tasks --read-only

Call execute:

{ "method": "GET", "path": "/api/Spaces-1/tasks" }

Actual:

{
  "success": false,
  "reason": "pathNotAllowed",
  "message": "Path '/api/Spaces-1/tasks' is not on the execute allowlist for any toolset. If this is a legitimate Octopus endpoint not yet covered, file an issue against the MCP server."
}

/api/spaces/Spaces-1/tasks behaves identically. /api/tasks is accepted.

With --toolsets all (the default) the allowlist is skipped altogether, so this only appears when toolsets are narrowed.

Expected behavior

With the tasks toolset enabled, all three documented prefixes resolve.

The server's own catalog documents both space prefixes. grep_llms_txt for GET /tasks returns:

- `GET /tasks` - List all of the tasks in the supplied Octopus Deploy Space. The results will be
  sorted from newest to oldest. | Prefixes (pick one): `/{spaceId}`, `/spaces/{spaceIdentifier}`
  | ?active, batch, description, environment, fromCompletedDate, fromQueueDate, fromStartDate,
  ..., project, ..., states, take, tenant, tenantTag, toCompletedDate, ...
  → TaskResourceCollection

Since the execute tool description instructs callers to "Discover endpoints with grep_llms_txt", the documented discovery path currently leads to a path the allowlist rejects.

Root cause

src/helpers/pathAllowlist.ts:91:

tasks: ["/api/tasks", "/api/tasks/**"],

Every other toolset that covers a space-scoped resource builds its patterns from the spaceScoped() helper (23 call sites in that table), which emits all four forms:

function spaceScoped(suffix: string): readonly string[] {
  return [
    `/api/*/${suffix}`,
    `/api/*/${suffix}/**`,
    `/api/spaces/*/${suffix}`,
    `/api/spaces/*/${suffix}/**`,
  ];
}

tasks is the only entry in TOOLSET_PATH_PATTERNS that does not use it, and the only one written as a single-line literal.

Suggested fix

The events toolset already handles exactly this shape — a resource with both space-scoped and unscoped endpoints:

events: [
  // Space-scoped audit log endpoints.
  ...spaceScoped("events"),
  // Unscoped metadata endpoints (categories, groups, agents, documenttypes).
  "/api/events",
  "/api/events/**",
],

So tasks becomes:

tasks: [
  ...spaceScoped("tasks"),
  "/api/tasks",
  "/api/tasks/**",
],

Environment and versions

  • MCP Client: Claude Code
  • Octopus MCP Server Version: 2.3.2
  • Octopus Server Version: 2026.4.1480
  • Started with --toolsets projects,deployments,releases,tasks

Related

#108. The two compound: /api/tasks is the one accepted form, but with query dropped it cannot be filtered either. Until both are fixed, task history is unreachable by project or date window through execute by any route — which is what sent me looking at the allowlist in the first place.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions