d365fo-client 0.1.0__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 (51) hide show
  1. d365fo_client/__init__.py +305 -0
  2. d365fo_client/auth.py +93 -0
  3. d365fo_client/cli.py +700 -0
  4. d365fo_client/client.py +1454 -0
  5. d365fo_client/config.py +304 -0
  6. d365fo_client/crud.py +200 -0
  7. d365fo_client/exceptions.py +49 -0
  8. d365fo_client/labels.py +528 -0
  9. d365fo_client/main.py +502 -0
  10. d365fo_client/mcp/__init__.py +16 -0
  11. d365fo_client/mcp/client_manager.py +276 -0
  12. d365fo_client/mcp/main.py +98 -0
  13. d365fo_client/mcp/models.py +371 -0
  14. d365fo_client/mcp/prompts/__init__.py +43 -0
  15. d365fo_client/mcp/prompts/action_execution.py +480 -0
  16. d365fo_client/mcp/prompts/sequence_analysis.py +349 -0
  17. d365fo_client/mcp/resources/__init__.py +15 -0
  18. d365fo_client/mcp/resources/database_handler.py +555 -0
  19. d365fo_client/mcp/resources/entity_handler.py +176 -0
  20. d365fo_client/mcp/resources/environment_handler.py +132 -0
  21. d365fo_client/mcp/resources/metadata_handler.py +283 -0
  22. d365fo_client/mcp/resources/query_handler.py +135 -0
  23. d365fo_client/mcp/server.py +432 -0
  24. d365fo_client/mcp/tools/__init__.py +17 -0
  25. d365fo_client/mcp/tools/connection_tools.py +175 -0
  26. d365fo_client/mcp/tools/crud_tools.py +579 -0
  27. d365fo_client/mcp/tools/database_tools.py +813 -0
  28. d365fo_client/mcp/tools/label_tools.py +189 -0
  29. d365fo_client/mcp/tools/metadata_tools.py +766 -0
  30. d365fo_client/mcp/tools/profile_tools.py +706 -0
  31. d365fo_client/metadata_api.py +793 -0
  32. d365fo_client/metadata_v2/__init__.py +59 -0
  33. d365fo_client/metadata_v2/cache_v2.py +1372 -0
  34. d365fo_client/metadata_v2/database_v2.py +585 -0
  35. d365fo_client/metadata_v2/global_version_manager.py +573 -0
  36. d365fo_client/metadata_v2/search_engine_v2.py +423 -0
  37. d365fo_client/metadata_v2/sync_manager_v2.py +819 -0
  38. d365fo_client/metadata_v2/version_detector.py +439 -0
  39. d365fo_client/models.py +862 -0
  40. d365fo_client/output.py +181 -0
  41. d365fo_client/profile_manager.py +342 -0
  42. d365fo_client/profiles.py +178 -0
  43. d365fo_client/query.py +162 -0
  44. d365fo_client/session.py +60 -0
  45. d365fo_client/utils.py +196 -0
  46. d365fo_client-0.1.0.dist-info/METADATA +1084 -0
  47. d365fo_client-0.1.0.dist-info/RECORD +51 -0
  48. d365fo_client-0.1.0.dist-info/WHEEL +5 -0
  49. d365fo_client-0.1.0.dist-info/entry_points.txt +3 -0
  50. d365fo_client-0.1.0.dist-info/licenses/LICENSE +21 -0
  51. d365fo_client-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,175 @@
1
+ """Connection tools for MCP server."""
2
+
3
+ import json
4
+ import logging
5
+ import time
6
+ from typing import List
7
+
8
+ from mcp import Tool
9
+ from mcp.types import TextContent
10
+
11
+ from ..client_manager import D365FOClientManager
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class ConnectionTools:
17
+ """Connection and testing tools for the MCP server."""
18
+
19
+ def __init__(self, client_manager: D365FOClientManager):
20
+ """Initialize connection tools.
21
+
22
+ Args:
23
+ client_manager: D365FO client manager instance
24
+ """
25
+ self.client_manager = client_manager
26
+
27
+ def get_tools(self) -> List[Tool]:
28
+ """Get list of connection tools.
29
+
30
+ Returns:
31
+ List of Tool definitions
32
+ """
33
+ return [self._get_test_connection_tool(), self._get_environment_info_tool()]
34
+
35
+ def _get_test_connection_tool(self) -> Tool:
36
+ """Get test connection tool definition."""
37
+ return Tool(
38
+ name="d365fo_test_connection",
39
+ description="Test connectivity to D365FO environment. If no profile is specified, uses the default profile. If no default profile is set, provides guidance on setting up profiles.",
40
+ inputSchema={
41
+ "type": "object",
42
+ "properties": {
43
+ "profile": {
44
+ "type": "string",
45
+ "description": "Configuration profile to use (optional - uses default profile if not specified)",
46
+ },
47
+ "baseUrl": {
48
+ "type": "string",
49
+ "description": "Override default base URL",
50
+ },
51
+ "timeout": {
52
+ "type": "integer",
53
+ "description": "Connection timeout in seconds",
54
+ "minimum": 1,
55
+ "maximum": 300,
56
+ },
57
+ },
58
+ },
59
+ )
60
+
61
+ def _get_environment_info_tool(self) -> Tool:
62
+ """Get environment info tool definition."""
63
+ return Tool(
64
+ name="d365fo_get_environment_info",
65
+ description="Get comprehensive environment information. If no profile is specified, uses the default profile.",
66
+ inputSchema={
67
+ "type": "object",
68
+ "properties": {
69
+ "profile": {
70
+ "type": "string",
71
+ "description": "Configuration profile to use (optional - uses default profile if not specified)",
72
+ }
73
+ },
74
+ },
75
+ )
76
+
77
+ async def execute_test_connection(self, arguments: dict) -> List[TextContent]:
78
+ """Execute test connection tool.
79
+
80
+ Args:
81
+ arguments: Tool arguments
82
+
83
+ Returns:
84
+ List of TextContent responses
85
+ """
86
+ try:
87
+ start_time = time.time()
88
+ profile = arguments.get("profile", "default")
89
+
90
+ # Test connection
91
+ success = await self.client_manager.test_connection(profile)
92
+ response_time = time.time() - start_time
93
+
94
+ # Build response
95
+ response = {
96
+ "success": success,
97
+ "profile": profile,
98
+ "endpoints": {
99
+ "data": success,
100
+ "metadata": success, # Simplification for now
101
+ },
102
+ "responseTime": round(response_time, 3),
103
+ "error": None if success else "Connection failed",
104
+ }
105
+
106
+ return [TextContent(type="text", text=json.dumps(response, indent=2))]
107
+
108
+ except ValueError as e:
109
+ # Handle configuration errors with helpful messages
110
+ logger.error(
111
+ f"Configuration error for profile {arguments.get('profile', 'default')}: {e}"
112
+ )
113
+ error_response = {
114
+ "success": False,
115
+ "profile": arguments.get("profile", "default"),
116
+ "endpoints": {"data": False, "metadata": False},
117
+ "responseTime": 0.0,
118
+ "error": str(e),
119
+ "suggestion": "Please create a profile or set a default profile using the profile management tools.",
120
+ }
121
+ return [TextContent(type="text", text=json.dumps(error_response, indent=2))]
122
+ except Exception as e:
123
+ logger.error(f"Test connection failed: {e}")
124
+ error_response = {
125
+ "success": False,
126
+ "profile": arguments.get("profile", "default"),
127
+ "endpoints": {"data": False, "metadata": False},
128
+ "responseTime": 0.0,
129
+ "error": str(e),
130
+ }
131
+ return [TextContent(type="text", text=json.dumps(error_response, indent=2))]
132
+
133
+ async def execute_get_environment_info(self, arguments: dict) -> List[TextContent]:
134
+ """Execute get environment info tool.
135
+
136
+ Args:
137
+ arguments: Tool arguments
138
+
139
+ Returns:
140
+ List of TextContent responses
141
+ """
142
+ try:
143
+ profile = arguments.get("profile", "default")
144
+ env_info = await self.client_manager.get_environment_info(profile)
145
+
146
+ # Format response according to specification with enhanced metadata info
147
+ response = {
148
+ "baseUrl": env_info["base_url"],
149
+ "versions": env_info["versions"],
150
+ "connectivity": env_info["connectivity"],
151
+ "metadataInfo": env_info["metadata_info"],
152
+ }
153
+
154
+ return [TextContent(type="text", text=json.dumps(response, indent=2))]
155
+
156
+ except ValueError as e:
157
+ # Handle configuration errors with helpful messages
158
+ logger.error(
159
+ f"Configuration error for profile {arguments.get('profile', 'default')}: {e}"
160
+ )
161
+ error_response = {
162
+ "error": str(e),
163
+ "tool": "d365fo_get_environment_info",
164
+ "arguments": arguments,
165
+ "suggestion": "Please create a profile or set a default profile using the profile management tools.",
166
+ }
167
+ return [TextContent(type="text", text=json.dumps(error_response, indent=2))]
168
+ except Exception as e:
169
+ logger.error(f"Get environment info failed: {e}")
170
+ error_response = {
171
+ "error": str(e),
172
+ "tool": "d365fo_get_environment_info",
173
+ "arguments": arguments,
174
+ }
175
+ return [TextContent(type="text", text=json.dumps(error_response, indent=2))]