Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/itential_mcp/runtime/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class CommandConfig:
"metavar": "<object>",
"help": "Parameters to pass to the tool",
},
"--config": {"help": CONFIG_HELP_MESSAGE},
},
add_platform_group=True,
),
Expand Down
15 changes: 15 additions & 0 deletions src/itential_mcp/runtime/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,23 @@ def parse_args(args: Sequence) -> Tuple[Callable, Tuple[Any, ...], dict]:
parser = _create_main_parser()
_create_subparsers(parser)

# Pre-capture --config from raw args before argparse parsing.
# When --config appears before the subcommand (e.g., itential-mcp --config
# file.conf call ...), the main parser captures it but the subparser
# overwrites it with its default (None). This preserves the value.
pre_config = None
args_list = list(args)
if "--config" in args_list:
idx = args_list.index("--config")
if idx + 1 < len(args_list):
pre_config = args_list[idx + 1]

parsed_args = parser.parse_args(args=args)

# Restore --config if the subparser overwrote it with None
if parsed_args.config is None and pre_config is not None:
parsed_args.config = pre_config

_process_logging_config(parsed_args)

if parsed_args.help or parsed_args.command is None:
Expand Down
75 changes: 75 additions & 0 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,81 @@ def __init__(self, tool, params):

assert result[1] == ("my_tool", '{"test": true}')

def test_call_with_config_attribute(self):
"""Test that call function works when args has config attribute"""

class MockArgs:
def __init__(self, tool, params, config):
self.tool = tool
self.params = params
self.config = config

args = MockArgs("my_tool", '{"test": true}', "/path/to/config.conf")
result = commands.call(args)

# call command should still return the same tuple structure
assert result[0] == runner.run
assert result[1] == ("my_tool", '{"test": true}')
assert result[2] is None


class TestCallCommandConfigIntegration:
"""Test cases for call command --config integration"""

def test_call_subparser_accepts_config_flag(self):
"""Test that the call subparser accepts --config flag"""
from unittest.mock import patch
from itential_mcp.runtime.parser import _create_main_parser, _create_subparsers

parser = _create_main_parser()
with patch("itential_mcp.runtime.parser.add_platform_group"), \
patch("itential_mcp.runtime.parser.add_server_group"):
_create_subparsers(parser)

# Should parse successfully with --config on call subcommand
args = parser.parse_args(["call", "get_health", "--config", "/path/to/config.conf"])

assert args.command == "call"
assert args.tool == "get_health"
assert args.config == "/path/to/config.conf"

def test_call_subparser_config_default_is_none(self):
"""Test that --config defaults to None when not provided"""
from unittest.mock import patch
from itential_mcp.runtime.parser import _create_main_parser, _create_subparsers

parser = _create_main_parser()
with patch("itential_mcp.runtime.parser.add_platform_group"), \
patch("itential_mcp.runtime.parser.add_server_group"):
_create_subparsers(parser)

args = parser.parse_args(["call", "get_health"])

assert args.command == "call"
assert args.tool == "get_health"
assert args.config is None

def test_call_subparser_config_with_params(self):
"""Test that --config works alongside --params on call subcommand"""
from unittest.mock import patch
from itential_mcp.runtime.parser import _create_main_parser, _create_subparsers

parser = _create_main_parser()
with patch("itential_mcp.runtime.parser.add_platform_group"), \
patch("itential_mcp.runtime.parser.add_server_group"):
_create_subparsers(parser)

args = parser.parse_args([
"call", "get_devices",
"--config", "/path/to/config.conf",
"--params", '{"filter": "active"}',
])

assert args.command == "call"
assert args.tool == "get_devices"
assert args.config == "/path/to/config.conf"
assert args.params == '{"filter": "active"}'


class TestModuleStructure:
"""Test cases for overall module structure and imports"""
Expand Down