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.
- d365fo_client/__init__.py +305 -0
- d365fo_client/auth.py +93 -0
- d365fo_client/cli.py +700 -0
- d365fo_client/client.py +1454 -0
- d365fo_client/config.py +304 -0
- d365fo_client/crud.py +200 -0
- d365fo_client/exceptions.py +49 -0
- d365fo_client/labels.py +528 -0
- d365fo_client/main.py +502 -0
- d365fo_client/mcp/__init__.py +16 -0
- d365fo_client/mcp/client_manager.py +276 -0
- d365fo_client/mcp/main.py +98 -0
- d365fo_client/mcp/models.py +371 -0
- d365fo_client/mcp/prompts/__init__.py +43 -0
- d365fo_client/mcp/prompts/action_execution.py +480 -0
- d365fo_client/mcp/prompts/sequence_analysis.py +349 -0
- d365fo_client/mcp/resources/__init__.py +15 -0
- d365fo_client/mcp/resources/database_handler.py +555 -0
- d365fo_client/mcp/resources/entity_handler.py +176 -0
- d365fo_client/mcp/resources/environment_handler.py +132 -0
- d365fo_client/mcp/resources/metadata_handler.py +283 -0
- d365fo_client/mcp/resources/query_handler.py +135 -0
- d365fo_client/mcp/server.py +432 -0
- d365fo_client/mcp/tools/__init__.py +17 -0
- d365fo_client/mcp/tools/connection_tools.py +175 -0
- d365fo_client/mcp/tools/crud_tools.py +579 -0
- d365fo_client/mcp/tools/database_tools.py +813 -0
- d365fo_client/mcp/tools/label_tools.py +189 -0
- d365fo_client/mcp/tools/metadata_tools.py +766 -0
- d365fo_client/mcp/tools/profile_tools.py +706 -0
- d365fo_client/metadata_api.py +793 -0
- d365fo_client/metadata_v2/__init__.py +59 -0
- d365fo_client/metadata_v2/cache_v2.py +1372 -0
- d365fo_client/metadata_v2/database_v2.py +585 -0
- d365fo_client/metadata_v2/global_version_manager.py +573 -0
- d365fo_client/metadata_v2/search_engine_v2.py +423 -0
- d365fo_client/metadata_v2/sync_manager_v2.py +819 -0
- d365fo_client/metadata_v2/version_detector.py +439 -0
- d365fo_client/models.py +862 -0
- d365fo_client/output.py +181 -0
- d365fo_client/profile_manager.py +342 -0
- d365fo_client/profiles.py +178 -0
- d365fo_client/query.py +162 -0
- d365fo_client/session.py +60 -0
- d365fo_client/utils.py +196 -0
- d365fo_client-0.1.0.dist-info/METADATA +1084 -0
- d365fo_client-0.1.0.dist-info/RECORD +51 -0
- d365fo_client-0.1.0.dist-info/WHEEL +5 -0
- d365fo_client-0.1.0.dist-info/entry_points.txt +3 -0
- d365fo_client-0.1.0.dist-info/licenses/LICENSE +21 -0
- 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))]
|