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,371 @@
1
+ """MCP-specific models and data structures."""
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from enum import Enum
6
+ from typing import Any, Dict, List, Optional, Union
7
+
8
+ # Resource Models
9
+
10
+
11
+ @dataclass
12
+ class EntityProperty:
13
+ name: str
14
+ type: str
15
+ is_key: bool
16
+ is_required: bool
17
+ max_length: Optional[int] = None
18
+ label: Optional[str] = None
19
+ description: Optional[str] = None
20
+
21
+
22
+ @dataclass
23
+ class EntityMetadata:
24
+ name: str
25
+ entity_set_name: str
26
+ keys: List[str]
27
+ properties: List[EntityProperty]
28
+ is_read_only: bool
29
+ label_text: Optional[str] = None
30
+
31
+
32
+ @dataclass
33
+ class EntityResourceContent:
34
+ metadata: Optional[EntityMetadata]
35
+ sample_data: Optional[List[Dict[str, Any]]] = None
36
+ record_count: Optional[int] = None
37
+ last_updated: Optional[str] = None
38
+
39
+
40
+ class MetadataType(Enum):
41
+ ENTITIES = "entities"
42
+ ACTIONS = "actions"
43
+ ENUMERATIONS = "enumerations"
44
+ LABELS = "labels"
45
+
46
+
47
+ @dataclass
48
+ class MetadataStatistics:
49
+ categories: Dict[str, int]
50
+ capabilities: Dict[str, int]
51
+
52
+
53
+ @dataclass
54
+ class MetadataResourceContent:
55
+ type: MetadataType
56
+ count: int
57
+ last_updated: str
58
+ items: List[Dict[str, Any]]
59
+ statistics: Optional[MetadataStatistics] = None
60
+
61
+
62
+ @dataclass
63
+ class VersionInfo:
64
+ application: str
65
+ platform: str
66
+ build: str
67
+
68
+
69
+ @dataclass
70
+ class ConnectivityStatus:
71
+ data_endpoint: bool
72
+ metadata_endpoint: bool
73
+ last_tested: str
74
+
75
+
76
+ @dataclass
77
+ class CacheInfo:
78
+ size: int
79
+ last_updated: str
80
+ hit_rate: float
81
+
82
+
83
+ @dataclass
84
+ class CacheStatus:
85
+ metadata: CacheInfo
86
+ labels: CacheInfo
87
+
88
+
89
+ @dataclass
90
+ class EnvironmentResourceContent:
91
+ base_url: str
92
+ version: VersionInfo
93
+ connectivity: ConnectivityStatus
94
+ cache: CacheStatus
95
+
96
+
97
+ @dataclass
98
+ class QueryParameter:
99
+ name: str
100
+ type: str
101
+ required: bool
102
+ description: str
103
+ default_value: Optional[Any] = None
104
+
105
+
106
+ @dataclass
107
+ class QueryResourceContent:
108
+ entity_name: str
109
+ select: Optional[List[str]] = None
110
+ filter: Optional[str] = None
111
+ expand: Optional[List[str]] = None
112
+ order_by: Optional[List[str]] = None
113
+ top: Optional[int] = None
114
+ skip: Optional[int] = None
115
+ template: bool = False
116
+ parameters: Optional[List[QueryParameter]] = None
117
+
118
+
119
+ # Tool Input/Output Models
120
+
121
+
122
+ @dataclass
123
+ class TestConnectionInput:
124
+ base_url: Optional[str] = None
125
+ timeout: Optional[int] = None
126
+
127
+
128
+ @dataclass
129
+ class EndpointStatus:
130
+ data: bool
131
+ metadata: bool
132
+
133
+
134
+ @dataclass
135
+ class TestConnectionOutput:
136
+ success: bool
137
+ endpoints: EndpointStatus
138
+ response_time: float
139
+ error: Optional[str] = None
140
+
141
+
142
+ @dataclass
143
+ class EnvironmentInfoOutput:
144
+ base_url: str
145
+ versions: VersionInfo
146
+ connectivity: bool
147
+ cache_status: CacheStatus
148
+ statistics: Optional[Dict[str, int]] = None
149
+
150
+
151
+ @dataclass
152
+ class SyncMetadataInput:
153
+ force_refresh: bool = False
154
+ include_labels: bool = True
155
+ include_actions: bool = True
156
+
157
+
158
+ @dataclass
159
+ class SyncStatistics:
160
+ entities_downloaded: int
161
+ actions_downloaded: int
162
+ labels_downloaded: int
163
+
164
+
165
+ @dataclass
166
+ class SyncMetadataOutput:
167
+ success: bool
168
+ sync_time: float
169
+ statistics: SyncStatistics
170
+ cache_location: str
171
+
172
+
173
+ @dataclass
174
+ class SearchEntitiesInput:
175
+ pattern: str
176
+ entity_category: Optional[str] = None
177
+ data_service_enabled: Optional[bool] = None
178
+ data_management_enabled: Optional[bool] = None
179
+ is_read_only: Optional[bool] = None
180
+ limit: int = 100
181
+
182
+
183
+ @dataclass
184
+ class SearchEntitiesOutput:
185
+ entities: List[Dict[str, Any]]
186
+ total_count: int
187
+ search_time: float
188
+
189
+
190
+ @dataclass
191
+ class QueryEntitiesInput:
192
+ entity_name: str
193
+ select: Optional[List[str]] = None
194
+ filter: Optional[str] = None
195
+ expand: Optional[List[str]] = None
196
+ order_by: Optional[List[str]] = None
197
+ top: Optional[int] = None
198
+ skip: Optional[int] = None
199
+ count: bool = False
200
+ search: Optional[str] = None
201
+
202
+
203
+ @dataclass
204
+ class QueryEntitiesOutput:
205
+ data: List[Dict[str, Any]]
206
+ count: Optional[int] = None
207
+ next_link: Optional[str] = None
208
+ query_time: float = 0.0
209
+ total_records: Optional[int] = None
210
+
211
+
212
+ @dataclass
213
+ class GetEntityRecordInput:
214
+ entity_name: str
215
+ key: Union[str, Dict[str, Any]]
216
+ select: Optional[List[str]] = None
217
+ expand: Optional[List[str]] = None
218
+
219
+
220
+ @dataclass
221
+ class GetEntityRecordOutput:
222
+ record: Optional[Dict[str, Any]]
223
+ found: bool
224
+ retrieval_time: float
225
+
226
+
227
+ @dataclass
228
+ class CreateEntityRecordInput:
229
+ entity_name: str
230
+ data: Dict[str, Any]
231
+ return_record: bool = False
232
+
233
+
234
+ @dataclass
235
+ class CreateEntityRecordOutput:
236
+ success: bool
237
+ record_id: Optional[str] = None
238
+ created_record: Optional[Dict[str, Any]] = None
239
+ validation_errors: Optional[List[str]] = None
240
+
241
+
242
+ @dataclass
243
+ class UpdateEntityRecordInput:
244
+ entity_name: str
245
+ key: Union[str, Dict[str, Any]]
246
+ data: Dict[str, Any]
247
+ return_record: bool = False
248
+ if_match: Optional[str] = None
249
+
250
+
251
+ @dataclass
252
+ class UpdateEntityRecordOutput:
253
+ success: bool
254
+ updated_record: Optional[Dict[str, Any]] = None
255
+ validation_errors: Optional[List[str]] = None
256
+ conflict_detected: bool = False
257
+
258
+
259
+ @dataclass
260
+ class DeleteEntityRecordInput:
261
+ entity_name: str
262
+ key: Union[str, Dict[str, Any]]
263
+ if_match: Optional[str] = None
264
+
265
+
266
+ @dataclass
267
+ class DeleteEntityRecordOutput:
268
+ success: bool
269
+ conflict_detected: bool = False
270
+ error: Optional[str] = None
271
+
272
+
273
+ @dataclass
274
+ class GetLabelInput:
275
+ label_id: str
276
+ language: str = "en-US"
277
+ fallback_to_english: bool = True
278
+
279
+
280
+ @dataclass
281
+ class GetLabelOutput:
282
+ label_id: str
283
+ text: str
284
+ language: str
285
+ found: bool
286
+
287
+
288
+ @dataclass
289
+ class GetLabelsBatchInput:
290
+ label_ids: List[str]
291
+ language: str = "en-US"
292
+ fallback_to_english: bool = True
293
+
294
+
295
+ @dataclass
296
+ class GetLabelsBatchOutput:
297
+ labels: Dict[str, str]
298
+ missing_labels: List[str]
299
+ retrieval_time: float
300
+
301
+
302
+ # Error Models
303
+
304
+
305
+ @dataclass
306
+ class D365FOErrorDetails:
307
+ http_status: int
308
+ error_code: str
309
+ error_message: str
310
+ correlation_id: Optional[str] = None
311
+
312
+
313
+ @dataclass
314
+ class MCPErrorDetails:
315
+ d365fo_error: Optional[D365FOErrorDetails] = None
316
+ validation_errors: Optional[List[str]] = None
317
+ context: Optional[Dict[str, Any]] = None
318
+
319
+
320
+ @dataclass
321
+ class MCPError:
322
+ code: str
323
+ message: str
324
+ timestamp: str
325
+ details: Optional[MCPErrorDetails] = None
326
+ tool: Optional[str] = None
327
+ retryable: bool = False
328
+
329
+
330
+ # Configuration Models
331
+
332
+
333
+ @dataclass
334
+ class PerformanceConfig:
335
+ max_concurrent_requests: int = 10
336
+ connection_pool_size: int = 5
337
+ request_timeout: int = 30
338
+ batch_size: int = 100
339
+
340
+
341
+ @dataclass
342
+ class CacheConfig:
343
+ metadata_cache_dir: str
344
+ label_cache_expiry_minutes: int = 120
345
+ use_label_cache: bool = True
346
+ cache_size_limit_mb: int = 100
347
+
348
+
349
+ @dataclass
350
+ class SecurityConfig:
351
+ encrypt_cached_tokens: bool = True
352
+ token_expiry_buffer_minutes: int = 5
353
+ max_retry_attempts: int = 3
354
+
355
+
356
+ @dataclass
357
+ class MCPServerConfig:
358
+ name: str = "d365fo-mcp-server"
359
+ version: str = "1.0.0"
360
+ description: str = "MCP Server for Microsoft Dynamics 365 Finance & Operations"
361
+ performance: PerformanceConfig = None
362
+ cache: CacheConfig = None
363
+ security: SecurityConfig = None
364
+
365
+ def __post_init__(self):
366
+ if self.performance is None:
367
+ self.performance = PerformanceConfig()
368
+ if self.cache is None:
369
+ self.cache = CacheConfig(metadata_cache_dir="~/.d365fo-mcp/cache")
370
+ if self.security is None:
371
+ self.security = SecurityConfig()
@@ -0,0 +1,43 @@
1
+ """Prompts package for MCP server."""
2
+
3
+ from .action_execution import (
4
+ ACTION_EXECUTION_PROMPT,
5
+ ActionBindingKind,
6
+ ActionExecutionPrompt,
7
+ ActionExecutionPromptArgs,
8
+ ActionExecutionType,
9
+ )
10
+ from .sequence_analysis import (
11
+ SEQUENCE_ANALYSIS_PROMPT,
12
+ SequenceAnalysisPrompt,
13
+ SequenceAnalysisPromptArgs,
14
+ SequenceAnalysisType,
15
+ SequenceScope,
16
+ )
17
+
18
+ # Available prompts for MCP server
19
+ AVAILABLE_PROMPTS = {
20
+ "d365fo_sequence_analysis": SEQUENCE_ANALYSIS_PROMPT,
21
+ "d365fo_action_execution": ACTION_EXECUTION_PROMPT,
22
+ }
23
+
24
+ # Future: Additional prompt handlers will be implemented here
25
+ # Following the specification patterns for:
26
+ # - Entity analysis prompts
27
+ # - Query builder prompts
28
+ # - Integration planning prompts
29
+ # - Troubleshooting prompts
30
+
31
+ __all__ = [
32
+ "SEQUENCE_ANALYSIS_PROMPT",
33
+ "SequenceAnalysisPrompt",
34
+ "SequenceAnalysisPromptArgs",
35
+ "SequenceAnalysisType",
36
+ "SequenceScope",
37
+ "ACTION_EXECUTION_PROMPT",
38
+ "ActionExecutionPrompt",
39
+ "ActionExecutionPromptArgs",
40
+ "ActionExecutionType",
41
+ "ActionBindingKind",
42
+ "AVAILABLE_PROMPTS",
43
+ ]