Skip to content

Conversation

@nirajchowdhary
Copy link
Contributor

Issue #, if available: None

Overview

This change consolidates tool permission checking logic to ensure consistent behavior between the /tools display and actual tool execution in Q CLI.

Background

The CLI had two separate implementations for checking tool permissions:

Display path: Used for showing trust status in /tools command

Execution path: Used when actually running tools

These implementations had different wildcard pattern support, leading to inconsistent user experience.

Documentation Reference

https://github.com/aws/amazon-q-developer-cli/blob/main/docs/agent-format.md#allowedtools-field

According to the allowedTools specification:

Pattern Types:

  • Native tools: "fs_read", "fs_*"

  • MCP tools: "@server", "@server/tool", "@quip"

Key Rules:

  • Patterns starting with @ apply to MCP tools

  • Patterns without @ apply to native tools

Both support wildcard patterns (*, ?)

Solution

Created a centralized tool_permission_checker utility that:

  • Provides single source of truth for permission logic

  • Properly separates native vs MCP pattern matching

  • Ensures consistent wildcard support across all code paths

  • Stays consistent with Q cli documentation on allowedTools instructions

Testing

  • Ran cargo tests and all test succeeded
  • Check comment for detailed testing

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@nirajchowdhary
Copy link
Contributor Author

nirajchowdhary commented Sep 23, 2025

Before change Behavior:

Example Scenario

Configuration: in Agent mcp config file

{
 {
    "name": "amazon_q_default",
    "description": "Default agent configuration",
    "mcpServers": {

        "quip-mcp-server": {
            "command": "/home/Workspace/src/quip-mcp-server/dist/index.js",
            "transportType": "stdio",
            "timeout": 300000
        }
    },
    "tools": [
        "*"
    ],
    "allowedTools": [
        "fsRead",
        "*quip*"
    ],

    ...
    ...
    ..rest of config
} 
}

On running /tools displays MCP tools from quip-server showed as "not trusted"

🤖 You are chatting with claude-sonnet-4

[amazon_q_default] > /tools
Built-in:
- execute_bash                        * trust read-only commands
- fs_read                             * trust working directory
- fs_write                            * not trusted
- introspect                          * trusted
- knowledge                           * not trusted
- report_issue                        * trusted
- use_aws                             * trust read-only commands
- 
quip-mcp-server (MCP):
- get_quip_documents                  * not trusted
- search_quip_documents               * not trusted

On running q to read a quip document

Execution: it runs get_quip_documents tool as trusted without asking user for permission as seen shown above it being not trusted

[amazon_q_default] > read quip doc using quip mcp <<url to quip>>

> I'll read the Quip document for you. I notice there's a typo in the URL (.coam instead of .com), so I'll use the correct domain.


🛠️  Using tool: get_quip_documents (trusted) from mcp server quip-mcp-server
 ⋮ 
 ● Running get_quip_documents with the param:
 ⋮  {
 ⋮    "urls": [
 ⋮      "<url to quip>"
 ⋮    ]
 ⋮  }
^C

@nirajchowdhary
Copy link
Contributor Author

After fix Behavior:

Example Scenario

Configuration: in Agent mcp config file

{
 {
    "name": "amazon_q_default",
    "description": "Default agent configuration",
    "mcpServers": {

        "quip-mcp-server": {
            "command": "/home/Workspace/src/quip-mcp-server/dist/index.js",
            "transportType": "stdio",
            "timeout": 300000
        }
    },
    "tools": [
        "*"
    ],
    "allowedTools": [
        "fsRead",
        "*quip*"
    ],

    ...
    ...
    ..rest of config
} 
}

On running /tools displays MCP tools from quip-server showed as "not trusted"

🤖 You are chatting with claude-sonnet-4

[amazon_q_default] > /tools
Built-in:
- execute_bash                        * trust read-only commands
- fs_read                             * trust working directory
- fs_write                            * not trusted
- introspect                          * trusted
- knowledge                           * not trusted
- report_issue                        * trusted
- use_aws                             * trust read-only commands
- 
quip-mcp-server (MCP):
- get_quip_documents                  * not trusted
- search_quip_documents               * not trusted

On running q to read a quip document

Execution: it runs get_quip_documents tool and asks for permission as it is not trusted

[amazon_q_default] > read a quip doc using quip mcp <url to quip>

> I'll read the Quip document for you using the MCP tool.


🛠️  Using tool: get_quip_documents from mcp server quip-mcp-server
 ⋮ 
 ● Running get_quip_documents with the param:
 ⋮  {
 ⋮    "urls": [
 ⋮      "<url to quip>"
 ⋮    ]
 ⋮  }

Allow this action? Use 't' to trust (always allow) this tool for the session. [y/n/t]:

[amazon_q_default] > 

@nirajchowdhary
Copy link
Contributor Author

Another After fix Behavior:

Example Scenario

Configuration: in Agent mcp config file

{
 {
    "name": "amazon_q_default",
    "description": "Default agent configuration",
    "mcpServers": {

        "quip-mcp-server": {
            "command": "/home/Workspace/src/quip-mcp-server/dist/index.js",
            "transportType": "stdio",
            "timeout": 300000
        }
    },
    "tools": [
        "*"
    ],
    "allowedTools": [
        "fsRead",
        "@*quip*"
    ],

    ...
    ...
    ..rest of config
} 
}

On running /tools displays MCP tools from quip-server showed as "not trusted"

🤖 You are chatting with claude-sonnet-4

[amazon_q_default] > /tools
Built-in:
- execute_bash                        * trust read-only commands
- fs_read                             * trust working directory
- fs_write                            * not trusted
- introspect                          * trusted
- knowledge                           * not trusted
- report_issue                        * trusted
- use_aws                             * trust read-only commands
- 
quip-mcp-server (MCP):
- get_quip_documents                  * trusted
- search_quip_documents               * trusted

On running q to read a quip document

Execution: this time since tool is trusted it reads directly without asking for permission

[amazon_q_default] > read a quip doc using quip mcp <url to quip>

> I'll read the Quip document for you using the MCP tool.


🛠️  Using tool: get_quip_documents (trusted) from mcp server santos-quip-mcp-server
 ⋮ 
 ● Running get_quip_documents with the param:
 ⋮  {
 ⋮    "urls": [
 ⋮      "<url to quip>"
 ⋮    ]
 ⋮  }
^C

Copy link
Contributor

@kkashilk kkashilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you confirm that you've run -

cargo clippy --locked --workspace --color always -- -D warnings

cargo +nightly fmt --check -- --color always

cargo +nightly fmt

// Native tool
None => {
let patterns = filter_patterns(|p| !p.starts_with('@'));
info!("Native patterns: {:?}", patterns);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: change info! to debug! unless necessary.

You can run Q_LOG_LEVEL=debug cargo run... to get these logs if necessary.


/// Checks if a tool is allowed based on the agent's allowed_tools configuration.
/// This function handles both native tools and MCP tools with wildcard pattern support.
pub fn is_tool_allowed(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can replace the call to matches_any_pattern in native tool validation as well

For example -

let is_in_allowlist = matches_any_pattern(&agent.allowed_tools, "fs_read");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good callout

ToolOrigin::Native => None,
_ => Some(<ToolOrigin as Borrow<str>>::borrow(origin)),
};
is_tool_allowed(&a.allowed_tools, tool_name, server_name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: change method name to is_tool_in_allowlist.

Whether a tool is allowed or not is a bit more complicated depending on the tool

@kkashilk kkashilk merged commit 5acd7e3 into aws:main Sep 25, 2025
xianwwu pushed a commit to xianwwu/amazon-q-developer-cli that referenced this pull request Oct 6, 2025
aws#2975)

* fix: consolidate tool permission logic for consistent display and execution

* fix: centralize tool permission checking logic

---------

Co-authored-by: Niraj Chowdhary <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants