ibm-watsonx-orchestrate-mcp-server 1.13.0b0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. .gitignore +17 -0
  2. __init__.py +0 -0
  3. ibm_watsonx_orchestrate_mcp_server/__init__.py +0 -0
  4. ibm_watsonx_orchestrate_mcp_server/server.py +46 -0
  5. ibm_watsonx_orchestrate_mcp_server/src/__init__.py +10 -0
  6. ibm_watsonx_orchestrate_mcp_server/src/agents/mcp_tools.py +162 -0
  7. ibm_watsonx_orchestrate_mcp_server/src/agents/types.py +122 -0
  8. ibm_watsonx_orchestrate_mcp_server/src/connections/helpers.py +31 -0
  9. ibm_watsonx_orchestrate_mcp_server/src/connections/mcp_tools.py +149 -0
  10. ibm_watsonx_orchestrate_mcp_server/src/connections/types.py +113 -0
  11. ibm_watsonx_orchestrate_mcp_server/src/knowledge_bases/mcp_tools.py +66 -0
  12. ibm_watsonx_orchestrate_mcp_server/src/models/mcp_tools.py +207 -0
  13. ibm_watsonx_orchestrate_mcp_server/src/models/types.py +60 -0
  14. ibm_watsonx_orchestrate_mcp_server/src/toolkits/mcp_tools.py +67 -0
  15. ibm_watsonx_orchestrate_mcp_server/src/toolkits/types.py +19 -0
  16. ibm_watsonx_orchestrate_mcp_server/src/tools/mcp_tools.py +155 -0
  17. ibm_watsonx_orchestrate_mcp_server/src/version_checker.py +7 -0
  18. ibm_watsonx_orchestrate_mcp_server/src/voice_configurations/mcp_tools.py +52 -0
  19. ibm_watsonx_orchestrate_mcp_server/utils/common.py +108 -0
  20. ibm_watsonx_orchestrate_mcp_server/utils/config/__init__.py +2 -0
  21. ibm_watsonx_orchestrate_mcp_server/utils/config/config.py +91 -0
  22. ibm_watsonx_orchestrate_mcp_server/utils/config/types.py +6 -0
  23. ibm_watsonx_orchestrate_mcp_server/utils/files/files.py +14 -0
  24. ibm_watsonx_orchestrate_mcp_server/utils/logging/__init__.py +1 -0
  25. ibm_watsonx_orchestrate_mcp_server/utils/logging/log_config.yaml +19 -0
  26. ibm_watsonx_orchestrate_mcp_server/utils/logging/logger.py +38 -0
  27. ibm_watsonx_orchestrate_mcp_server-1.13.0b0.dist-info/METADATA +12 -0
  28. ibm_watsonx_orchestrate_mcp_server-1.13.0b0.dist-info/RECORD +31 -0
  29. ibm_watsonx_orchestrate_mcp_server-1.13.0b0.dist-info/WHEEL +4 -0
  30. ibm_watsonx_orchestrate_mcp_server-1.13.0b0.dist-info/entry_points.txt +2 -0
  31. pyproject.toml +39 -0
@@ -0,0 +1,108 @@
1
+ import io
2
+ import logging
3
+ from typing import Any, Callable
4
+ from contextlib import redirect_stdout, redirect_stderr, ExitStack
5
+
6
+
7
+ # Add this at the module level to store original logger states
8
+ _original_logger_states = {}
9
+
10
+ def __save_all_logger_states():
11
+ """Save the original state of all loggers."""
12
+ global _original_logger_states
13
+ _original_logger_states = {}
14
+
15
+ # Save state for named loggers
16
+ for name, logger in logging.root.manager.loggerDict.items():
17
+ if isinstance(logger, logging.Logger):
18
+ _original_logger_states[name] = {
19
+ 'level': logger.level,
20
+ 'handlers': list(logger.handlers), # Make a copy of the handlers list
21
+ 'propagate': logger.propagate
22
+ }
23
+
24
+ # Save state for root logger
25
+ root_logger = logging.getLogger()
26
+ _original_logger_states['root'] = {
27
+ 'level': root_logger.level,
28
+ 'handlers': list(root_logger.handlers) # Root logger doesn't have propagate
29
+ }
30
+
31
+ def __reset_all_loggers():
32
+ """Reset all loggers to their original state."""
33
+ global _original_logger_states
34
+
35
+ # Reset named loggers
36
+ for name, logger in logging.root.manager.loggerDict.items():
37
+ if isinstance(logger, logging.Logger):
38
+ # Clear current handlers
39
+ logger.handlers.clear()
40
+
41
+ # Restore original state if we have it
42
+ if name in _original_logger_states:
43
+ state = _original_logger_states[name]
44
+ logger.setLevel(state['level'])
45
+ for handler in state['handlers']:
46
+ logger.addHandler(handler)
47
+ logger.propagate = state['propagate']
48
+ else:
49
+ # Default behavior if we don't have saved state
50
+ logger.propagate = True
51
+
52
+ # Reset root logger
53
+ root_logger = logging.getLogger()
54
+ root_logger.handlers.clear()
55
+
56
+ # Restore original root logger state
57
+ if 'root' in _original_logger_states:
58
+ state = _original_logger_states['root']
59
+ root_logger.setLevel(state['level'])
60
+ for handler in state['handlers']:
61
+ root_logger.addHandler(handler)
62
+
63
+
64
+
65
+ def silent_call(fn: Callable, *args, suppress_stdout: bool = True,
66
+ suppress_stderr: bool = False, suppress_logging: bool = True, **kwargs) -> Any:
67
+ """
68
+ Call a function silently, suppressing stdout and/or stderr output.
69
+
70
+ Args:
71
+ fn: The function to call
72
+ *args: Positional arguments to pass to the function
73
+ suppress_stdout: Whether to suppress stdout (default: True)
74
+ suppress_stderr: Whether to suppress stderr (default: False)
75
+ suppress_logging: Whether to suppress logging output (default: True)
76
+ **kwargs: Keyword arguments to pass to the function
77
+
78
+ Returns:
79
+ The return value of the called function
80
+ """
81
+ with ExitStack() as stack:
82
+ null_stream = io.StringIO()
83
+
84
+ if suppress_stdout:
85
+ stack.enter_context(redirect_stdout(null_stream))
86
+ if suppress_stderr:
87
+ stack.enter_context(redirect_stderr(null_stream))
88
+
89
+ if suppress_logging:
90
+ # Save original logger states before modifying
91
+ __save_all_logger_states()
92
+
93
+ stream_handler = logging.StreamHandler(null_stream)
94
+
95
+ # Patch all known loggers
96
+ for name, logger in logging.root.manager.loggerDict.items():
97
+ if isinstance(logger, logging.Logger):
98
+ logger.handlers.clear()
99
+ logger.addHandler(stream_handler)
100
+ logger.propagate = False
101
+
102
+ try:
103
+ return fn(*args, **kwargs)
104
+ except SystemExit:
105
+ raise Exception(f"{null_stream.getvalue()}")
106
+ finally:
107
+ if suppress_logging:
108
+ __reset_all_loggers()
@@ -0,0 +1,2 @@
1
+ from .config import config
2
+ from .types import MCPTransportTypes
@@ -0,0 +1,91 @@
1
+ import os
2
+ import tomllib
3
+ from typing import Any
4
+ from importlib.metadata import version
5
+
6
+ DEFAULT_SERVER_NAME: str = "WXO-MCP"
7
+ DEFAULT_VERSION: str = "Unknown"
8
+ DEFAULT_DESCRIPTION: str = "MCP Server used to interact with watsonx Orchestrate"
9
+
10
+ DEFAULT_HOST = "127.0.0.1" # Secure default - localhost only
11
+ DEFAULT_PORT = 8080
12
+ DEFAULT_TRANSPORT = "stdio" # Options: "stdio", "http", "sse" TODO: Make enum
13
+
14
+ def _find_pyproject_toml() -> str | None:
15
+ """
16
+ Locate the pyproject.toml file by traversing the directory tree upwards until found.
17
+
18
+ Returns:
19
+ The path to the pyproject.toml file if found, otherwise None.
20
+ """
21
+
22
+ current: str = os.path.abspath(os.path.dirname(__file__))
23
+ while True:
24
+ current_toml = os.path.join(current, "pyproject.toml")
25
+ if os.path.isfile(current_toml):
26
+ return current_toml
27
+ parent = os.path.dirname(current)
28
+ if parent == current:
29
+ raise FileNotFoundError("pyproject.toml not found")
30
+ current = parent
31
+
32
+ def _get_pyproject_configuration() -> dict:
33
+ """
34
+ Load configuration from the pyproject.toml file.
35
+
36
+ Returns:
37
+ A dictionary containing the configuration values from the pyproject.toml file.
38
+ If no configuration is found, an empty dictionary is returned.
39
+ """
40
+ toml_path: str | None = _find_pyproject_toml()
41
+ if not toml_path:
42
+ return {}
43
+ try:
44
+ with open(toml_path, "rb") as f:
45
+ return tomllib.load(f).get("project", {})
46
+ except FileNotFoundError:
47
+ return {}
48
+
49
+ class Config:
50
+ """Centralized configuration manager."""
51
+
52
+ def __init__(self):
53
+ pyproject_config: dict[Any, Any] = _get_pyproject_configuration()
54
+
55
+ self.server_name: str = pyproject_config.get("name", DEFAULT_SERVER_NAME)
56
+ try:
57
+ self.version: str = version("ibm-watsonx-orchestrate-mcp-server")
58
+ except:
59
+ self.version: str = DEFAULT_VERSION
60
+ self.description: str = pyproject_config.get("description", DEFAULT_DESCRIPTION)
61
+
62
+ # Network
63
+ self.host: str = os.getenv("WXO_MCP_HOST", DEFAULT_HOST)
64
+ self.port: int = int(os.getenv("WXO_MCP_PORT", str(DEFAULT_PORT)))
65
+ self.transport: str = os.getenv("WXO_MCP_TRANSPORT", DEFAULT_TRANSPORT).lower()
66
+
67
+ # Development
68
+ self.debug:bool = os.getenv("WXO_MCP_DEBUG", "false").lower() == "true"
69
+
70
+ # Application
71
+ self.working_directory = os.getenv("WXO_MCP_WORKING_DIRECTORY")
72
+
73
+ def __repr__(self) -> str:
74
+ return f"""
75
+ ========================================================
76
+ Server Name: {self.server_name}
77
+ Version: {self.version}
78
+ Description: {self.description}
79
+ ========================================================
80
+ Transport: {self.transport}
81
+ Network:
82
+ Host: {self.host}
83
+ Port: {self.port}
84
+ ========================================================
85
+ Debug: {self.debug}
86
+ ========================================================
87
+ DEFAULT_WORKING_DIRECTORY: {self.working_directory}
88
+ ========================================================
89
+ """
90
+
91
+ config: Config = Config()
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+ class MCPTransportTypes(str, Enum):
4
+ STDIO = "stdio"
5
+ HTTP_STREAMABLE = "http"
6
+ SSE = "sse"
@@ -0,0 +1,14 @@
1
+ from pathlib import Path
2
+ from ibm_watsonx_orchestrate_mcp_server.utils.config.config import config
3
+
4
+ def get_working_directory_path(path_string: str) -> str:
5
+ if config.working_directory is None:
6
+ raise Exception("No working directory defined. Access to file system is blocked. To configure working directory expose the environment variable 'WXO_MCP_WORKING_DIRECTORY'")
7
+
8
+ path: Path = Path(path_string).resolve()
9
+ working_directory: Path = Path(config.working_directory).resolve()
10
+
11
+ try:
12
+ return str(path.relative_to(working_directory))
13
+ except ValueError:
14
+ raise Exception("Attempting to access resources outside the working directory is forbidden.")
@@ -0,0 +1 @@
1
+ from .logger import setup_logging
@@ -0,0 +1,19 @@
1
+ version: 1
2
+ disable_existing_loggers: false
3
+
4
+ formatters:
5
+ standard:
6
+ format: "%(levelname)s - %(message)s"
7
+
8
+ handlers:
9
+ console:
10
+ class: logging.StreamHandler
11
+ level: DEBUG
12
+ formatter: standard
13
+ stream: ext://sys.stderr
14
+
15
+ loggers:
16
+ wxo-mcp:
17
+ level: DEBUG
18
+ handlers: [console]
19
+ propagate: false
@@ -0,0 +1,38 @@
1
+ import logging
2
+ import logging.config
3
+ import os
4
+ import yaml
5
+ from enum import Enum
6
+
7
+ class LogColors(str, Enum):
8
+ INFO = "\033[0;36m" #cyan
9
+ DEBUG = "\033[0;35m" #magenta
10
+ WARNING = "\033[0;33m" #yellow
11
+ ERROR = "\033[0;31m" #red
12
+ RESET = "\033[0;0m"
13
+
14
+
15
+ def setup_logging(debug=False):
16
+ """Setup logging configuration
17
+
18
+ Args:
19
+ debug (bool, optional): Whether to enable debug logging. Defaults to False.
20
+ """
21
+ config_path = os.path.join(os.path.dirname(__file__), "log_config.yaml")
22
+ with open(config_path, "r") as f:
23
+ config = yaml.safe_load(f)
24
+
25
+ # Adjust root logger level based on debug parameter
26
+ if not debug:
27
+ # Set console handler to INFO level if debug is False
28
+ for _, handler in config.get('handlers', {}).items():
29
+ if handler.get('class') == 'logging.StreamHandler':
30
+ handler['level'] = 'INFO'
31
+
32
+ logging.config.dictConfig(config)
33
+
34
+ # Add log colors
35
+ logging.addLevelName( logging.INFO, LogColors.INFO + f"[{logging.getLevelName(logging.INFO)}]" + LogColors.RESET)
36
+ logging.addLevelName( logging.DEBUG, LogColors.DEBUG + f"[{logging.getLevelName(logging.DEBUG)}]" + LogColors.RESET)
37
+ logging.addLevelName( logging.WARNING, LogColors.WARNING + f"[{logging.getLevelName(logging.WARNING)}]" + LogColors.RESET)
38
+ logging.addLevelName( logging.ERROR, LogColors.ERROR + f"[{logging.getLevelName(logging.ERROR)}]" + LogColors.RESET)
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: ibm-watsonx-orchestrate-mcp-server
3
+ Version: 1.13.0b0
4
+ Summary: IBM watsonx Orchestrate ADK MCP Server
5
+ Author-email: IBM <support@ibm.com>
6
+ License: MIT License
7
+ Requires-Python: <3.14,>=3.11
8
+ Requires-Dist: authlib>=1.6.3
9
+ Requires-Dist: fastmcp~=2.10
10
+ Requires-Dist: ibm-watsonx-orchestrate
11
+ Requires-Dist: pyyaml<7.0.0,>=6.0.2
12
+ Requires-Dist: typing-extensions>=4.4.0
@@ -0,0 +1,31 @@
1
+ ./.gitignore,sha256=cwcrsXHa5M1CLvBt7W3FLclADzVFBR_4wXfO9c6jRCM,146
2
+ ./__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ ./pyproject.toml,sha256=LptPuPmDSYvrg0iUsb0pIhcEwXQWzy-e__Y4iDWAakI,927
4
+ ./ibm_watsonx_orchestrate_mcp_server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ ./ibm_watsonx_orchestrate_mcp_server/server.py,sha256=cjmVZ8hUGHJUW9O8NpALzQm9eGSzrtTNK2OLzaGqsI4,1547
6
+ ./ibm_watsonx_orchestrate_mcp_server/src/__init__.py,sha256=VoM9wg6T_ggOhX7VsKJip7H-ghaXYubu43GCeCP-qak,645
7
+ ./ibm_watsonx_orchestrate_mcp_server/src/version_checker.py,sha256=XNsG5xp_Gu-JsPdWkjYMNC0Qxew0JR52hd2MBmLrRaU,216
8
+ ./ibm_watsonx_orchestrate_mcp_server/src/agents/mcp_tools.py,sha256=jBV3tkoApnffWY9d6sk96MRiHOBEnO1yyX1gU98SeAg,6862
9
+ ./ibm_watsonx_orchestrate_mcp_server/src/agents/types.py,sha256=G3c4iKM8lZ11AU-w1VKz3s8xtnjRTp6Vp7Db9Hb5noA,5269
10
+ ./ibm_watsonx_orchestrate_mcp_server/src/connections/helpers.py,sha256=3pedZYlEc3WueUBTlWqeS6qtWp19_UIZw6utcAfEhrE,1465
11
+ ./ibm_watsonx_orchestrate_mcp_server/src/connections/mcp_tools.py,sha256=CBAKq0fKHSi7ZiTgupGJLIy2IdVzo2jjkkkSjOf-xqI,5903
12
+ ./ibm_watsonx_orchestrate_mcp_server/src/connections/types.py,sha256=mjD8dNWVeK2giTi1h0cXd9V0zoJtbRUcTxd5Bd4AW7s,6727
13
+ ./ibm_watsonx_orchestrate_mcp_server/src/knowledge_bases/mcp_tools.py,sha256=TVzTPkw6Ixg-9lmEGPsxDgOq4YnK6fyGdLueIFggDPY,3362
14
+ ./ibm_watsonx_orchestrate_mcp_server/src/models/mcp_tools.py,sha256=J5fBCSyt1QpVDGkV7c8ZWX81QvwgPceRnXbX6Ia7UAY,8734
15
+ ./ibm_watsonx_orchestrate_mcp_server/src/models/types.py,sha256=Us4uiqxlWaabJu50O8I1VVOIw7fNjvsKjlYcciqE9vg,2686
16
+ ./ibm_watsonx_orchestrate_mcp_server/src/toolkits/mcp_tools.py,sha256=5mXzwkQ-SPBYlD3OpD2Vn2-BcEGqOs4YcwQs6LOLZIY,2864
17
+ ./ibm_watsonx_orchestrate_mcp_server/src/toolkits/types.py,sha256=44_W7KTGzs-8f9wjLrhkRU09NUxO8TG7IvGz5gn5XFk,2425
18
+ ./ibm_watsonx_orchestrate_mcp_server/src/tools/mcp_tools.py,sha256=YJ4a3Mfv_9FhHa9C3IRScALW_cAp0HgITT-B5l9Tz6A,6873
19
+ ./ibm_watsonx_orchestrate_mcp_server/src/voice_configurations/mcp_tools.py,sha256=gMdTHuwtjdK8HcZaGQNRwViL3uQNF6RgQ3UaJkPIFWw,2667
20
+ ./ibm_watsonx_orchestrate_mcp_server/utils/common.py,sha256=naRTpvgufoX8e5AOO7p6D43O8kaOOZLiMePEU8_Hg3E,3902
21
+ ./ibm_watsonx_orchestrate_mcp_server/utils/config/__init__.py,sha256=kPWW3exDC8gxfpExOMgnELu04Y-7rm9Zk-DIrkZqQLs,63
22
+ ./ibm_watsonx_orchestrate_mcp_server/utils/config/config.py,sha256=sATsXhzCqNyCF70YaqG-s5MhXu2Ohsdiltg_awmNrFg,3222
23
+ ./ibm_watsonx_orchestrate_mcp_server/utils/config/types.py,sha256=r9c6NGYf8rbUc4F0A9_ywEHMxGuWfiA5hzhbZ3YQXaw,123
24
+ ./ibm_watsonx_orchestrate_mcp_server/utils/files/files.py,sha256=wCjWachGS_haNw7ZtCcotjDbD56sXChG0RCml5x2lZU,692
25
+ ./ibm_watsonx_orchestrate_mcp_server/utils/logging/__init__.py,sha256=ZLPI0klEH2WFlrZ4BaPYLHRpWgOFRoVf5edR5eJIisQ,33
26
+ ./ibm_watsonx_orchestrate_mcp_server/utils/logging/log_config.yaml,sha256=nKkUdI0y-4kkoK7K7hSaiksYUdkTEj_yKT8ksNhsPLI,318
27
+ ./ibm_watsonx_orchestrate_mcp_server/utils/logging/logger.py,sha256=UWOoLCH1Acl641Z_Q2f949C2JvdKDutG8hKULniN4Iw,1450
28
+ ibm_watsonx_orchestrate_mcp_server-1.13.0b0.dist-info/METADATA,sha256=Y5YvhBiX0QEjLfTSk5Go1ppGynFpY5rcxA-3TnCyZbk,390
29
+ ibm_watsonx_orchestrate_mcp_server-1.13.0b0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
+ ibm_watsonx_orchestrate_mcp_server-1.13.0b0.dist-info/entry_points.txt,sha256=z9lzFFCOEZ9lX00T37YHJKnPfkKtaSA80iKe8LS0OPw,110
31
+ ibm_watsonx_orchestrate_mcp_server-1.13.0b0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ibm-watsonx-orchestrate-mcp-server = ibm_watsonx_orchestrate_mcp_server.server:start_server
pyproject.toml ADDED
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "ibm-watsonx-orchestrate-mcp-server"
7
+ dynamic = ["version"]
8
+ description = "IBM watsonx Orchestrate ADK MCP Server"
9
+ authors = [
10
+ { name = "IBM", email = "support@ibm.com" }
11
+ ]
12
+ #readme = { file = "README.md", content-type = 'text/markdown'}
13
+ license = {text = "MIT License"}
14
+ license-files = ["LICENSE"]
15
+ requires-python = ">=3.11, <3.14"
16
+ dependencies = [
17
+ "typing-extensions>=4.4.0",
18
+ "pyyaml>=6.0.2,<7.0.0",
19
+ "fastmcp~=2.10",
20
+ "ibm-watsonx-orchestrate",
21
+ "authlib>=1.6.3",
22
+ ]
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["."]
26
+ package-data = true
27
+
28
+ [tool.hatch.build]
29
+ include = [
30
+ "./*"
31
+ ]
32
+ directory="../../dist"
33
+
34
+ [tool.hatch.version]
35
+ path = "../../src/ibm_watsonx_orchestrate/__init__.py"
36
+ validate-bump=false
37
+
38
+ [project.scripts]
39
+ ibm-watsonx-orchestrate-mcp-server = "ibm_watsonx_orchestrate_mcp_server.server:start_server"