Skip to content

Commit e72d2f0

Browse files
Fix Tool Renaming Edge cases (#80)
* Fix Tool Filtering Edge cases Signed-off-by: rithin-pullela-aws <[email protected]> * Add Change log Signed-off-by: rithin-pullela-aws <[email protected]> --------- Signed-off-by: rithin-pullela-aws <[email protected]>
1 parent c95f1f1 commit e72d2f0

File tree

16 files changed

+665
-288
lines changed

16 files changed

+665
-288
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1313

1414
### Fixed
1515
- Handle Tool Filtering failure gracefully and define priority to the AWS Region definitions ([#74](https://github.com/opensearch-project/opensearch-mcp-server-py/pull/74))
16+
- Fix Tool Renaming Edge cases ([#80](https://github.com/opensearch-project/opensearch-mcp-server-py/pull/80))
1617

1718
### Security
1819

USER_GUIDE.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,23 @@ export OPENSEARCH_SETTINGS_ALLOW_WRITE=true
511511

512512
OpenSearch MCP server supports tool customization to modify tool display names, descriptions, and other properties. You can customize tools using either a YAML configuration file or runtime parameters.
513513

514+
**Note:** Display names must follow the pattern `^[a-zA-Z0-9_-]+$` (alphanumeric characters, underscores, and hyphens only).
515+
516+
### Supported Field Aliases
517+
518+
The following field aliases are supported for tool customization:
519+
520+
**Display Name Aliases:**
521+
- `display_name` (standard)
522+
- `name`
523+
- `displayName`
524+
- `customName`
525+
526+
**Description Aliases:**
527+
- `description` (standard)
528+
- `desc`
529+
- `customDescription`
530+
514531
### Configuration Methods
515532

516533
1. **YAML Configuration File**
@@ -519,7 +536,7 @@ Create a YAML file with your tool customization settings:
519536
```yaml
520537
tools:
521538
ListIndexTool:
522-
display_name: "Index Manager"
539+
display_name: "Index_Manager"
523540
description: "List and manage OpenSearch indices"
524541
GetShardsTool:
525542
description: "Retrieve detailed information about OpenSearch shards"
@@ -534,7 +551,7 @@ python -m mcp_server_opensearch --config path/to/config.yml
534551

535552
Customize tools directly via command line arguments:
536553
```bash
537-
python -m mcp_server_opensearch --tool.ListIndexTool.display_name="Index Manager" --tool.SearchIndexTool.description="Custom search tool"
554+
python -m mcp_server_opensearch --tool.ListIndexTool.display_name="Index_Manager" --tool.SearchIndexTool.description="Custom search tool"
538555
```
539556

540557
### Priority

example_config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ clusters:
2727
# Tool customization configurations (supported in both Single and Multi Mode)
2828
tools:
2929
ListIndexTool:
30-
display_name: "My Custom Index Lister"
30+
display_name: "My_Custom_Index_Lister"
3131
description: "This is a custom description for the tool that lists indices. It's much more descriptive now!"
3232
SearchIndexTool:
33-
display_name: "Super Searcher"
33+
display_name: "Super_Searcher"
3434
GetShardsTool:
3535
description: "A better description to get information about shards in OpenSearch."
3636

src/mcp_server_opensearch/__init__.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,21 @@
1313
def parse_unknown_args_to_dict(unknown_args: List[str]) -> Dict[str, str]:
1414
"""Parses a list of unknown arguments into a dictionary."""
1515
parser = argparse.ArgumentParser()
16-
arg_keys = {arg.split('=')[0] for arg in unknown_args if arg.startswith('--')}
16+
17+
# Extract argument keys and track duplicates with warnings
18+
seen = set()
19+
duplicates = set()
20+
arg_keys = set()
21+
22+
for arg in unknown_args:
23+
if arg.startswith('--'):
24+
key = arg.split('=')[0]
25+
arg_keys.add(key)
26+
if key in seen:
27+
duplicates.add(key)
28+
logging.warning(f"Duplicate argument '{key}' found. Using the latest value.")
29+
else:
30+
seen.add(key)
1731

1832
for key in arg_keys:
1933
parser.add_argument(key)
@@ -22,7 +36,7 @@ def parse_unknown_args_to_dict(unknown_args: List[str]) -> Dict[str, str]:
2236
parsed_args, _ = parser.parse_known_args(unknown_args)
2337
return {k: v for k, v in vars(parsed_args).items() if v is not None}
2438
except Exception as e:
25-
logging.error(f"Error parsing unknown arguments: {e}")
39+
logging.error(f'Error parsing unknown arguments: {e}')
2640
return {}
2741

2842

src/mcp_server_opensearch/stdio_server.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ async def serve(
3030
if mode == 'multi':
3131
load_clusters_from_yaml(config_file_path)
3232

33-
# Call tool generator and tool filter
33+
# Call tool generator
3434
await generate_tools_from_openapi()
35+
# Apply custom tool config (custom name and description)
3536
customized_registry = apply_custom_tool_config(
3637
TOOL_REGISTRY, config_file_path, cli_tool_overrides or {}
3738
)
39+
# Get enabled tools (tool filter)
3840
enabled_tools = get_tools(
3941
tool_registry=customized_registry, mode=mode, config_file_path=config_file_path
4042
)

src/mcp_server_opensearch/streaming_server.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ async def create_mcp_server(
3838
load_clusters_from_yaml(config_file_path)
3939

4040
server = Server('opensearch-mcp-server')
41-
# Call tool generator and tool fitler
41+
# Call tool generator
4242
await generate_tools_from_openapi()
43+
# Apply custom tool config (custom name and description)
4344
customized_registry = apply_custom_tool_config(
4445
TOOL_REGISTRY, config_file_path, cli_tool_overrides or {}
4546
)
47+
# Get enabled tools (tool filter)
4648
enabled_tools = get_tools(
4749
tool_registry=customized_registry, mode=mode, config_file_path=config_file_path
4850
)
@@ -146,9 +148,7 @@ async def serve(
146148
config_file_path: str = '',
147149
cli_tool_overrides: dict = None,
148150
) -> None:
149-
mcp_server = await create_mcp_server(
150-
mode, profile, config_file_path, cli_tool_overrides
151-
)
151+
mcp_server = await create_mcp_server(mode, profile, config_file_path, cli_tool_overrides)
152152
app_handler = MCPStarletteApp(mcp_server)
153153
app = app_handler.create_app()
154154

src/opensearch/client.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,13 @@ def initialize_client_with_cluster(cluster_info: ClusterInfo | None) -> OpenSear
160160

161161
session = boto3.Session(profile_name=profile) if profile else boto3.Session()
162162
aws_region = get_aws_region(cluster_info)
163-
print("aws_region is", aws_region)
163+
print('aws_region is', aws_region)
164164

165165
# 1. Try no authentication if explicitly enabled
166166
if os.getenv('OPENSEARCH_NO_AUTH', '').lower() == 'true':
167-
logger.info('[NO AUTH] Attempting connection without authentication (OPENSEARCH_NO_AUTH=true)')
167+
logger.info(
168+
'[NO AUTH] Attempting connection without authentication (OPENSEARCH_NO_AUTH=true)'
169+
)
168170
try:
169171
return OpenSearch(**client_kwargs)
170172
except Exception as e:
@@ -219,7 +221,7 @@ def initialize_client_with_cluster(cluster_info: ClusterInfo | None) -> OpenSear
219221
return OpenSearch(**client_kwargs)
220222
except (boto3.exceptions.Boto3Error, Exception) as e:
221223
logger.error(f'[AWS CREDS] Failed to get AWS credentials: {str(e)}')
222-
224+
223225
raise RuntimeError('No valid AWS or basic authentication provided for OpenSearch')
224226

225227

0 commit comments

Comments
 (0)