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,189 @@
|
|
1
|
+
"""Label 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 LabelTools:
|
17
|
+
"""Label and localization tools for the MCP server."""
|
18
|
+
|
19
|
+
def __init__(self, client_manager: D365FOClientManager):
|
20
|
+
"""Initialize label 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 label tools.
|
29
|
+
|
30
|
+
Returns:
|
31
|
+
List of Tool definitions
|
32
|
+
"""
|
33
|
+
return [self._get_label_tool(), self._get_labels_batch_tool()]
|
34
|
+
|
35
|
+
def _get_label_tool(self) -> Tool:
|
36
|
+
"""Get label tool definition."""
|
37
|
+
return Tool(
|
38
|
+
name="d365fo_get_label",
|
39
|
+
description="Get label text by label ID",
|
40
|
+
inputSchema={
|
41
|
+
"type": "object",
|
42
|
+
"properties": {
|
43
|
+
"labelId": {
|
44
|
+
"type": "string",
|
45
|
+
"description": "Label ID (e.g., @SYS1234)",
|
46
|
+
},
|
47
|
+
"language": {
|
48
|
+
"type": "string",
|
49
|
+
"default": "en-US",
|
50
|
+
"description": "Language code for label text",
|
51
|
+
},
|
52
|
+
"fallbackToEnglish": {
|
53
|
+
"type": "boolean",
|
54
|
+
"default": True,
|
55
|
+
"description": "Fallback to English if translation not found",
|
56
|
+
},
|
57
|
+
"profile": {
|
58
|
+
"type": "string",
|
59
|
+
"description": "Configuration profile to use (optional - uses default profile if not specified)",
|
60
|
+
},
|
61
|
+
},
|
62
|
+
"required": ["labelId"],
|
63
|
+
},
|
64
|
+
)
|
65
|
+
|
66
|
+
def _get_labels_batch_tool(self) -> Tool:
|
67
|
+
"""Get labels batch tool definition."""
|
68
|
+
return Tool(
|
69
|
+
name="d365fo_get_labels_batch",
|
70
|
+
description="Get multiple labels in a single request",
|
71
|
+
inputSchema={
|
72
|
+
"type": "object",
|
73
|
+
"properties": {
|
74
|
+
"labelIds": {
|
75
|
+
"type": "array",
|
76
|
+
"items": {"type": "string"},
|
77
|
+
"description": "List of label IDs to retrieve",
|
78
|
+
},
|
79
|
+
"language": {
|
80
|
+
"type": "string",
|
81
|
+
"default": "en-US",
|
82
|
+
"description": "Language code for label texts",
|
83
|
+
},
|
84
|
+
"fallbackToEnglish": {
|
85
|
+
"type": "boolean",
|
86
|
+
"default": True,
|
87
|
+
"description": "Fallback to English if translation not found",
|
88
|
+
},
|
89
|
+
"profile": {
|
90
|
+
"type": "string",
|
91
|
+
"description": "Configuration profile to use (optional - uses default profile if not specified)",
|
92
|
+
},
|
93
|
+
},
|
94
|
+
"required": ["labelIds"],
|
95
|
+
},
|
96
|
+
)
|
97
|
+
|
98
|
+
async def execute_get_label(self, arguments: dict) -> List[TextContent]:
|
99
|
+
"""Execute get label tool.
|
100
|
+
|
101
|
+
Args:
|
102
|
+
arguments: Tool arguments
|
103
|
+
|
104
|
+
Returns:
|
105
|
+
List of TextContent responses
|
106
|
+
"""
|
107
|
+
try:
|
108
|
+
profile = arguments.get("profile", "default")
|
109
|
+
client = await self.client_manager.get_client(profile)
|
110
|
+
|
111
|
+
label_id = arguments["labelId"]
|
112
|
+
language = arguments.get("language", "en-US")
|
113
|
+
|
114
|
+
# Get label text
|
115
|
+
label_text = await client.get_label_text(label_id, language=language)
|
116
|
+
|
117
|
+
response = {
|
118
|
+
"labelId": label_id,
|
119
|
+
"text": label_text or f"[{label_id}]",
|
120
|
+
"language": language,
|
121
|
+
"found": label_text is not None,
|
122
|
+
}
|
123
|
+
|
124
|
+
return [TextContent(type="text", text=json.dumps(response, indent=2))]
|
125
|
+
|
126
|
+
except Exception as e:
|
127
|
+
logger.error(f"Get label failed: {e}")
|
128
|
+
error_response = {
|
129
|
+
"error": str(e),
|
130
|
+
"tool": "d365fo_get_label",
|
131
|
+
"arguments": arguments,
|
132
|
+
}
|
133
|
+
return [TextContent(type="text", text=json.dumps(error_response, indent=2))]
|
134
|
+
|
135
|
+
async def execute_get_labels_batch(self, arguments: dict) -> List[TextContent]:
|
136
|
+
"""Execute get labels batch tool.
|
137
|
+
|
138
|
+
Args:
|
139
|
+
arguments: Tool arguments
|
140
|
+
|
141
|
+
Returns:
|
142
|
+
List of TextContent responses
|
143
|
+
"""
|
144
|
+
try:
|
145
|
+
profile = arguments.get("profile", "default")
|
146
|
+
client = await self.client_manager.get_client(profile)
|
147
|
+
|
148
|
+
label_ids = arguments["labelIds"]
|
149
|
+
language = arguments.get("language", "en-US")
|
150
|
+
|
151
|
+
start_time = time.time()
|
152
|
+
|
153
|
+
# Get labels in batch
|
154
|
+
labels = {}
|
155
|
+
missing_labels = []
|
156
|
+
|
157
|
+
for label_id in label_ids:
|
158
|
+
try:
|
159
|
+
label_text = await client.get_label_text(
|
160
|
+
label_id, language=language
|
161
|
+
)
|
162
|
+
if label_text:
|
163
|
+
labels[label_id] = label_text
|
164
|
+
else:
|
165
|
+
missing_labels.append(label_id)
|
166
|
+
except Exception:
|
167
|
+
missing_labels.append(label_id)
|
168
|
+
|
169
|
+
retrieval_time = time.time() - start_time
|
170
|
+
|
171
|
+
response = {
|
172
|
+
"labels": labels,
|
173
|
+
"missingLabels": missing_labels,
|
174
|
+
"retrievalTime": round(retrieval_time, 3),
|
175
|
+
"language": language,
|
176
|
+
"totalRequested": len(label_ids),
|
177
|
+
"foundCount": len(labels),
|
178
|
+
}
|
179
|
+
|
180
|
+
return [TextContent(type="text", text=json.dumps(response, indent=2))]
|
181
|
+
|
182
|
+
except Exception as e:
|
183
|
+
logger.error(f"Get labels batch failed: {e}")
|
184
|
+
error_response = {
|
185
|
+
"error": str(e),
|
186
|
+
"tool": "d365fo_get_labels_batch",
|
187
|
+
"arguments": arguments,
|
188
|
+
}
|
189
|
+
return [TextContent(type="text", text=json.dumps(error_response, indent=2))]
|