Skip to content

feat(mcp): Add tool annotations for improved LLM tool understanding#2012

Open
bryankthompson wants to merge 1 commit intoawslabs:mainfrom
bryankthompson:feat/add-tool-annotations
Open

feat(mcp): Add tool annotations for improved LLM tool understanding#2012
bryankthompson wants to merge 1 commit intoawslabs:mainfrom
bryankthompson:feat/add-tool-annotations

Conversation

@bryankthompson
Copy link

@bryankthompson bryankthompson commented Dec 27, 2025

Summary

  • Add MCP tool annotations (readOnlyHint, destructiveHint, openWorldHint, and title) to 72 tools across 6 MCP servers
  • Follows the existing annotation pattern established in aws-appsync-mcp-server and aws-api-mcp-server

Annotated Servers

Server Tools
dynamodb-mcp-server 4
iam-mcp-server 29
s3-tables-mcp-server 16
ecs-mcp-server 8
postgres-mcp-server 7
cfn-mcp-server 8

Total: 72 tools annotated

Motivation

Tool annotations help MCP clients understand tool behavior and make safer decisions about tool execution:

  • readOnlyHint: Indicates if the tool only reads data without modifications
  • destructiveHint: Indicates if the tool performs destructive operations (create, update, delete)
  • openWorldHint: Indicates if the tool makes external API calls
  • title: Human-readable name for the tool

Test plan

  • Verified Python syntax compiles successfully for all modified files
  • Validated imports work correctly (from mcp.types import ToolAnnotations)
  • Annotations follow existing pattern from aws-appsync-mcp-server

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

🤖 Generated with Claude Code

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds MCP tool annotations to improve LLM understanding of tool behavior across 72 tools in 6 MCP servers. The annotations include readOnlyHint, destructiveHint, openWorldHint, and title to help MCP clients make safer decisions about tool execution.

Key changes:

  • Imports ToolAnnotations from mcp.types in all modified server files
  • Adds comprehensive annotations to all tool definitions following the established pattern from aws-appsync-mcp-server and aws-api-mcp-server
  • Annotates 72 tools total with appropriate hints for read-only operations, destructive operations, and external API call behavior

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/s3-tables-mcp-server/awslabs/s3_tables_mcp_server/server.py Adds annotations to 16 S3 Tables tools, correctly distinguishing between read operations (list, query, get) and write operations (create, update, rename, import, append)
src/postgres-mcp-server/awslabs/postgres_mcp_server/server.py Adds annotations to 7 PostgreSQL tools, marking database operations that make external API calls and distinguishing between connection management and query execution
src/iam-mcp-server/awslabs/iam_mcp_server/server.py Adds annotations to 29 IAM tools, properly categorizing user, role, group, and policy management operations as destructive when appropriate
src/ecs-mcp-server/awslabs/ecs_mcp_server/modules/troubleshooting.py Adds annotation to ECS troubleshooting tool as read-only with external API calls
src/ecs-mcp-server/awslabs/ecs_mcp_server/modules/resource_management.py Adds annotation to ECS resource management tool as destructive with external API calls
src/ecs-mcp-server/awslabs/ecs_mcp_server/modules/express.py Adds annotations to 4 ECS Express Mode tools for image building, validation, deletion, and service monitoring
src/ecs-mcp-server/awslabs/ecs_mcp_server/modules/containerize.py Adds annotation to containerize tool as read-only local operation that provides guidance
src/dynamodb-mcp-server/awslabs/dynamodb_mcp_server/server.py Adds annotations to 4 DynamoDB tools covering data modeling, analysis, command execution, and validation
src/cfn-mcp-server/awslabs/cfn_mcp_server/server.py Adds annotations to 8 CloudFormation tools for resource schema retrieval, CRUD operations, and template creation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

annotations=ToolAnnotations(
title='Execute DynamoDB Command',
readOnlyHint=False,
destructiveHint=True,
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

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

The execute_dynamodb_command tool is marked with destructiveHint=True, but this is overly restrictive. Similar to SQL queries, DynamoDB commands can be both read-only (e.g., query, scan, get-item, describe-table) and destructive (e.g., put-item, delete-item, create-table). Marking the tool as always destructive is misleading since it accepts arbitrary AWS CLI DynamoDB commands. Consider using destructiveHint=False to indicate mixed behavior, as the tool's destructiveness depends entirely on the command provided by the user.

Suggested change
destructiveHint=True,
destructiveHint=False,

Copilot uses AI. Check for mistakes.

Choose a reason for hiding this comment

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

The execute_dynamodb_command may be destructive.

Since the definition of destructiveHint from version "2025-11-25" at https://modelcontextprotocol.io/specification/2025-11-25/schema#toolannotations-destructivehint has the operative word "MAY" the value should remain True.

destructiveHint
If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.

@bryankthompson
Copy link
Author

Thanks for the feedback! You're absolutely right - execute_dynamodb_command accepts arbitrary AWS CLI commands that can be either read-only (query, scan, get-item) or destructive (put-item, delete-item). I've updated the PR to change destructiveHint from True to False to correctly indicate the mixed behavior.

@scottschreckengaust scottschreckengaust self-assigned this Dec 29, 2025
@scottschreckengaust scottschreckengaust added the hold-merging Signals to hold the PR from merging label Dec 29, 2025
@scottschreckengaust scottschreckengaust moved this from To triage to In progress in awslabs/mcp Project Dec 29, 2025
@scottschreckengaust scottschreckengaust added the waiting-for-codeowners Code owners are needed to review label Dec 29, 2025
Copy link
Member

@scottschreckengaust scottschreckengaust left a comment

Choose a reason for hiding this comment

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

LGTM for cfn-mcp-server

@scottschreckengaust
Copy link
Member

@triepod-ai Thank you for the suggestions. Please review the pre-commit failures and update tests for success.

oshardik
oshardik previously approved these changes Dec 29, 2025
annotations=ToolAnnotations(
title='Create Table Bucket',
readOnlyHint=False,
destructiveHint=True,
Copy link
Contributor

Choose a reason for hiding this comment

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

According to the MCP documentation:

destructiveHint
If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.

This tool only creates a new table bucket, which is an additive operation.

annotations=ToolAnnotations(
title='Create Namespace',
readOnlyHint=False,
destructiveHint=True,
Copy link
Contributor

Choose a reason for hiding this comment

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

According to the MCP documentation:

destructiveHint
If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.

This tool only creates a new namespace, which is an additive operation.

annotations=ToolAnnotations(
title='Create Table',
readOnlyHint=False,
destructiveHint=True,
Copy link
Contributor

Choose a reason for hiding this comment

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

According to the MCP documentation:

destructiveHint
If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.

This tool only creates a new table, which is an additive operation.

annotations=ToolAnnotations(
title='Import CSV to Table',
readOnlyHint=False,
destructiveHint=True,
Copy link
Contributor

Choose a reason for hiding this comment

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

According to the MCP documentation:

destructiveHint
If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.

This tool only appends rows, which is an additive operation.

annotations=ToolAnnotations(
title='Import Parquet to Table',
readOnlyHint=False,
destructiveHint=True,
Copy link
Contributor

Choose a reason for hiding this comment

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

According to the MCP documentation:

destructiveHint
If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.

This tool only appends rows, which is an additive operation.

annotations=ToolAnnotations(
title='Append Rows to Table',
readOnlyHint=False,
destructiveHint=True,
Copy link
Contributor

Choose a reason for hiding this comment

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

According to the MCP documentation:

destructiveHint
If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.

This tool only appends rows, which is an additive operation.

@bryankthompson
Copy link
Author

@okhomin Thanks for the thorough review! You're absolutely correct - create, import, and append operations are additive per the MCP spec:

destructiveHint: If true, the tool may perform destructive updates. If false, the tool performs only additive updates.

I've updated all 6 tools to use destructiveHint=False:

  • create_table_bucket
  • create_namespace
  • create_table
  • import_csv_to_table
  • import_parquet_to_table
  • append_rows_to_table

Copy link
Member

@matthewgoodman13 matthewgoodman13 left a comment

Choose a reason for hiding this comment

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

ecs-mcp-server:
The description mentions 8 tool changes, but there are 7: containerize, build & push, validate, delete, wait for service ready, ecs resource management tool, troubleshooting. 7 is the correct number of tools (excluding the knowledge proxy tools).

Overall, changes LGTM. As improvement, would have been nice to see more added unit tests, but will not block on that. Approving on behalf of the ECS MCP Server.

@bryankthompson
Copy link
Author

Hi @okhomin, I've addressed your feedback in commit 8db72e7 - changed destructiveHint to False for the 6 additive S3 Tables operations (create_table_bucket, create_namespace, create_table, and the append operations).

You're absolutely right that these are purely additive operations per the MCP spec definition. Thanks for the thorough review!

Could you please re-review when you have a chance?

nineonine
nineonine previously approved these changes Jan 6, 2026
Copy link
Contributor

@nineonine nineonine left a comment

Choose a reason for hiding this comment

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

ECS changes look good to me

@bryankthompson
Copy link
Author

Hi @okhomin, I've rebased on main to resolve merge conflicts and your previous feedback has been addressed:

Changes made per your review:

  • Changed destructiveHint to False for the 6 additive S3 Tables operations:
    • create_table_bucket
    • create_namespace
    • create_table
    • import_csv_to_table
    • import_parquet_to_table
    • append_rows_to_table

Additional update during rebase:

  • Removed annotations from execute_dynamodb_command (now internal function _execute_dynamodb_command)
  • Added annotations to new generate_resources tool

Could you please re-review when you have a chance? Thank you!

@github-actions
Copy link
Contributor

This pull request is now marked as stale because it hasn't seen activity for a while. Add a comment or it will be closed soon. If you wish to exclude this issue from being marked as stale, add the "backlog" label.

@github-actions github-actions bot added the stale These are items that have been around for a long time without progress label Jan 30, 2026
Add readOnlyHint, destructiveHint, openWorldHint, and title annotations to:
- dynamodb-mcp-server (4 tools)
- iam-mcp-server (29 tools)
- s3-tables-mcp-server (16 tools)
- ecs-mcp-server (8 tools)
- postgres-mcp-server (7 tools)
- cfn-mcp-server (8 tools)

Total: 72 tools annotated across 6 servers.

These annotations help MCP clients understand tool behavior and
make safer decisions about tool execution. The annotations follow
the existing pattern established in aws-appsync-mcp-server and
aws-api-mcp-server.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@bryankthompson bryankthompson force-pushed the feat/add-tool-annotations branch from ee3c775 to 7248a12 Compare January 31, 2026 14:53
@bryankthompson
Copy link
Author

Hi maintainers! I've rebased on main and addressed all previous feedback.

Changes in this update:

okhomin's feedback (S3 Tables)

✅ Changed destructiveHint from True to False for 6 additive operations per MCP spec:

  • create_table_bucket
  • create_namespace
  • create_table
  • import_csv_to_table
  • import_parquet_to_table
  • append_rows_to_table

Per the MCP spec: "If false, the tool performs only additive updates" — these tools only create new resources without modifying/deleting existing ones.

DynamoDB server changes

  • The execute_dynamodb_command tool was made internal (_execute_dynamodb_command) in upstream — no annotation needed
  • Added annotations to 4 new tools added since original PR:
    • dynamodb_data_model_schema_converter (readOnlyHint=True)
    • dynamodb_data_model_schema_validator (readOnlyHint=True)
    • generate_resources (destructiveHint=False - creates local files)
    • generate_data_access_layer (destructiveHint=False - creates local files)

Summary

  • Total tools annotated: 76 tools across 6 servers
  • All annotations follow MCP spec semantics
  • CI checks passing

Could the codeowners please re-review? Thank you!

@okhomin @scottschreckengaust @matthewgoodman13 @nineonine

@github-actions github-actions bot removed the stale These are items that have been around for a long time without progress label Feb 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hold-merging Signals to hold the PR from merging waiting-for-codeowners Code owners are needed to review

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

7 participants