Skip to content

--available-tools and --excluded-tools flags silently ignored in ACP mode (--acp) #2948

@catatafishen

Description

@catatafishen

Describe the bug

When running the CLI in ACP mode (--acp), the --available-tools and
--excluded-tools flags have no effect. The flags are parsed correctly but
never applied to the session — the model sees the full tool list regardless.

Affected version

1.0.34

Steps to reproduce the behavior

copilot --acp --stdio --excluded-tools bash edit view
The model can still call bash, edit, view etc. as if the flags were not
passed.

Expected behavior

--available-tools foo bar restricts the model to only foo and bar.
--excluded-tools bash edit hides bash and edit from the model's tool
list, matching the behaviour in interactive and non-interactive modes.

Additional context

Root cause (source-located)

In index.js, the ACP startup path branches and returns early before
availableTools/excludedTools are applied:

// Line ~4375 (main command handler)
if (t.acp) {
await startACPMode({ ..., options: t, rules: E, ... }, authManager)
return // ← early exit; ae/ce computed below never run
}
ae = normalise(t.availableTools) // only reached for interactive/non-interactive
ce = normalise(t.excludedTools)

The raw CLI options object t is forwarded as options: t, so
this.options.options.availableTools / this.options.options.excludedTools are
accessible inside the Jpt class. However, Jpt.newSession() and
Jpt.loadSession() never read them:

// Jpt.newSession — current code
let l = await this.sessionManager.createSession({ sessionId, workingDirectory, ... })
this.mcpHost && l.updateOptions({ mcpServers: ..., mcpHost: ... })
// ← availableTools / excludedTools never set

Compare to interactive mode (Mto) and non-interactive mode (Cul), both of
which correctly call:

session.updateOptions({ ..., availableTools: s, excludedTools: l, ... })

Minimal fix

In Jpt.newSession() and Jpt.loadSession(), after the existing
updateOptions call for mcpHost, add:

const _opts = this.options.options

if (_opts?.availableTools || _opts?.excludedTools)

session.updateOptions({

availableTools: _opts.availableTools,

excludedTools: _opts.excludedTools

})

Workaround

--deny-tool does work in ACP mode because it populates rules.denied, which
is passed to createSessionPermissionService and consulted before any
session/request_permission is sent to the ACP client. However, this only
controls the permission layer — the tools still appear in the model's tool list.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:non-interactiveNon-interactive mode (-p), CI/CD, ACP protocol, and headless automationarea:toolsBuilt-in tools: file editing, shell, search, LSP, git, and tool call behavior

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions