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,349 @@
1
+ """
2
+ D365 Finance & Operations Sequence Analysis Prompt for MCP.
3
+
4
+ This module provides a comprehensive prompt for analyzing D365FO number sequences
5
+ with validated entity schemas and query limitations.
6
+ """
7
+
8
+ from enum import Enum
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ from pydantic import BaseModel, Field
12
+
13
+
14
+ class SequenceAnalysisType(str, Enum):
15
+ """Types of sequence analysis."""
16
+
17
+ COMPREHENSIVE = "comprehensive"
18
+ BASIC = "basic"
19
+ SPECIFIC_SEQUENCES = "specific_sequences"
20
+ PERFORMANCE_FOCUS = "performance_focus"
21
+
22
+
23
+ class SequenceScope(str, Enum):
24
+ """Sequence scope types."""
25
+
26
+ DATA_AREA = "DataArea"
27
+ DATA_AREA_FISCAL = "DataAreaFiscalCalender"
28
+ LEGAL_ENTITY = "LegalEntity"
29
+ OPERATING_UNIT = "OperatingUnit"
30
+
31
+
32
+ class SequenceAnalysisPromptArgs(BaseModel):
33
+ """Arguments for sequence analysis prompt."""
34
+
35
+ analysis_scope: SequenceAnalysisType = Field(
36
+ default=SequenceAnalysisType.COMPREHENSIVE,
37
+ description="Scope of analysis: comprehensive, basic, specific_sequences, performance_focus",
38
+ )
39
+ company_filter: Optional[str] = Field(
40
+ default=None,
41
+ description="Filter analysis to specific company code (e.g., 'USMF')",
42
+ )
43
+ sequence_codes: Optional[List[str]] = Field(
44
+ default=None,
45
+ description="Specific sequence codes to analyze (e.g., ['Addr_1', 'Cust_1'])",
46
+ )
47
+ focus_areas: List[str] = Field(
48
+ default=["configuration", "performance", "security", "maintenance"],
49
+ description="Areas to focus analysis on",
50
+ )
51
+
52
+
53
+ # Validated entity field mappings from live D365FO environment
54
+ SEQUENCE_ENTITY_FIELDS = {
55
+ "SequenceV2Tables": [
56
+ "NumberSequenceCode",
57
+ "ScopeType",
58
+ "ScopeValue",
59
+ "Name",
60
+ "Next", # Changed from NextRec
61
+ "Format",
62
+ "Preallocation",
63
+ "Manual",
64
+ "ToALowerNumber", # Additional field found
65
+ "Cyclical",
66
+ "Continuous",
67
+ "Stopped",
68
+ "InUse",
69
+ ],
70
+ "NumberSequencesV2References": [
71
+ "DataTypeName",
72
+ "NumberSequenceCode",
73
+ "ReuseNumbers",
74
+ "ScopeType",
75
+ "ScopeValue",
76
+ ],
77
+ }
78
+
79
+
80
+ class SequenceAnalysisPrompt:
81
+ """Sequence number analysis prompt handler."""
82
+
83
+ @staticmethod
84
+ def get_prompt_template() -> str:
85
+ """Get the prompt template for sequence analysis."""
86
+ return """
87
+ # D365 Finance & Operations Number Sequence Analysis
88
+
89
+ You are an expert D365 Finance & Operations consultant specializing in number sequence analysis. You have access to D365FO MCP tools to analyze number sequences directly from the system.
90
+
91
+ ## Your Mission
92
+ Analyze D365 Finance & Operations number sequences to identify configuration issues, optimization opportunities, and provide actionable recommendations. Use the MCP tools to gather real-time data from the system.
93
+
94
+ ## Available MCP Tools
95
+
96
+ **Entity Query Tools:**
97
+ - `d365fo_query_entities` - Query D365FO entities (limited OData support)
98
+ - `d365fo_get_entity_by_key` - Get specific entity record by key
99
+ - `d365fo_search_entities` - Search for entities by name pattern
100
+ - `d365fo_get_entity_schema` - Get entity metadata and schema information
101
+
102
+ **Version & System Tools:**
103
+ - `d365fo_get_environment_info` - Get D365FO application version and environment info
104
+ - `d365fo_test_connection` - Test connection to D365FO environment
105
+
106
+ ## Key Entities for Sequence Analysis
107
+
108
+ ### Primary Entities (Validated and Working)
109
+ - **SequenceV2Tables** - Main number sequence definitions ✅
110
+ - Key fields: NumberSequenceCode, Name, Manual, Stopped, InUse, Cyclical, Continuous, ScopeType, ScopeValue, Next, Format, Preallocation
111
+ - **NumberSequencesV2References** - Number sequence references and assignments ✅
112
+ - Key fields: NumberSequenceCode, DataTypeName, ReuseNumbers, ScopeType, ScopeValue
113
+
114
+ ### Field Values (Validated from Live System)
115
+ All boolean/enum fields use string values:
116
+ - **Manual**: 'Yes', 'No'
117
+ - **Stopped**: 'No' (mostly 'No' in system)
118
+ - **InUse**: 'Yes', 'No'
119
+ - **Cyclical**: 'No' (mostly 'No' in system)
120
+ - **Continuous**: 'Yes', 'No'
121
+ - **ScopeType**: 'DataArea', 'DataAreaFiscalCalender', 'LegalEntity', 'OperatingUnit'
122
+
123
+ ### Query Limitations (Important!)
124
+ This D365FO environment has limited OData capabilities:
125
+ - ✅ **Works**: Basic entity retrieval, simple key-based filters
126
+ - ❌ **Fails**: Field filtering on Manual/Stopped/InUse, $select, $orderby, complex filters
127
+
128
+ **Working Filter Examples:**
129
+ ```
130
+ NumberSequenceCode eq 'Addr_1' ✅ Works
131
+ ```
132
+
133
+ **Non-Working Filters (Return 400 errors):**
134
+ ```
135
+ Manual eq 'Yes' ❌ Fails
136
+ InUse eq 'Yes' ❌ Fails
137
+ ScopeType eq 'DataArea' ❌ Fails
138
+ Manual eq Microsoft.Dynamics.DataEntities.NoYes'Yes' ❌ Fails
139
+ ```
140
+
141
+ ## Analysis Framework
142
+
143
+ ### 1. System Overview
144
+ Start every analysis by gathering system information:
145
+ ```
146
+ Use d365fo_get_environment_info to identify D365FO version and environment
147
+ Use d365fo_query_entities with entity_name="SequenceV2Tables" (NO FILTERS) to get all data
148
+ ```
149
+
150
+ ### 2. Data Collection Strategy
151
+ Due to query limitations, collect all data first then analyze in memory:
152
+ ```
153
+ 1. Get ALL SequenceV2Tables data (no filters)
154
+ 2. Get ALL NumberSequencesV2References data (no filters)
155
+ 3. Filter and analyze the results programmatically
156
+ ```
157
+
158
+ ### 3. Manual Analysis Approach
159
+ Since field filtering doesn't work, analyze data manually:
160
+ - Load all sequence records into memory
161
+ - Filter records by checking field values programmatically
162
+ - Count sequences by categories (Manual='Yes', InUse='Yes', etc.)
163
+ - Identify patterns and issues through data analysis
164
+
165
+ ### 4. Configuration Analysis
166
+ For each sequence category, analyze:
167
+ - **Scope Distribution**: Count by ScopeType values
168
+ - **Usage Patterns**: Manual vs automatic sequences
169
+ - **Status Analysis**: Active, stopped, unused sequences
170
+ - **Format Analysis**: Number format patterns
171
+ - **Performance Considerations**: Preallocation settings
172
+
173
+ ### 5. Reference Analysis
174
+ Understand sequence usage:
175
+ ```
176
+ Use d365fo_query_entities with entity_name="NumberSequencesV2References" (no filters)
177
+ Cross-reference NumberSequenceCode with sequence definitions
178
+ Analyze DataTypeName to understand business context
179
+ ```
180
+
181
+ ## Step-by-Step Analysis Process
182
+
183
+ ### Step 1: Environment Assessment
184
+ ```
185
+ 1. Use d365fo_get_environment_info to identify environment
186
+ 2. Use d365fo_query_entities(entity_name="SequenceV2Tables") - get ALL records (10,000+ expected)
187
+ 3. Count and categorize sequences programmatically:
188
+ - Total sequences
189
+ - Manual sequences (Manual='Yes')
190
+ - Active sequences (InUse='Yes')
191
+ - Stopped sequences (Stopped='Yes')
192
+ - Scope distribution
193
+ ```
194
+
195
+ ### Step 2: Active Sequence Analysis
196
+ From the collected data, programmatically filter for:
197
+ ```
198
+ 1. Active sequences: InUse='Yes'
199
+ 2. Manual sequences: Manual='Yes' AND InUse='Yes'
200
+ 3. Problem sequences: Stopped='Yes' AND InUse='Yes'
201
+ 4. Scope analysis: Group by ScopeType values
202
+ ```
203
+
204
+ ### Step 3: Reference Analysis
205
+ ```
206
+ 1. Use d365fo_query_entities(entity_name="NumberSequencesV2References") - get ALL references
207
+ 2. Cross-reference with sequence definitions
208
+ 3. Identify unused sequences (in SequenceV2Tables but not in References)
209
+ 4. Analyze DataTypeName patterns for business context
210
+ ```
211
+
212
+ ### Step 4: Configuration Deep Dive
213
+ For specific sequences of interest:
214
+ ```
215
+ 1. Use d365fo_get_entity_by_key to get detailed sequence information
216
+ 2. Analyze Format patterns for readability
217
+ 3. Check Preallocation settings for performance
218
+ 4. Review ScopeValue configurations
219
+ ```
220
+
221
+ ### Step 5: Recommendations
222
+ Provide specific recommendations based on analysis:
223
+ - Manual to automatic conversion opportunities
224
+ - Format optimization suggestions
225
+ - Scope configuration improvements
226
+ - Performance tuning recommendations
227
+ - Risk mitigation strategies
228
+
229
+ ## Data Analysis Examples
230
+
231
+ ### Collect All Sequence Data
232
+ ```
233
+ # Get all sequences (no filtering possible)
234
+ all_sequences = d365fo_query_entities(entity_name="SequenceV2Tables")
235
+
236
+ # Programmatically analyze
237
+ manual_sequences = [s for s in all_sequences['value'] if s.get('Manual') == 'Yes']
238
+ active_sequences = [s for s in all_sequences['value'] if s.get('InUse') == 'Yes']
239
+ stopped_sequences = [s for s in all_sequences['value'] if s.get('Stopped') == 'Yes']
240
+ ```
241
+
242
+ ### Scope Analysis
243
+ ```
244
+ # Count by scope type
245
+ scope_counts = {}
246
+ for seq in all_sequences['value']:
247
+ scope = seq.get('ScopeType', 'Unknown')
248
+ scope_counts[scope] = scope_counts.get(scope, 0) + 1
249
+ ```
250
+
251
+ ### Find Problematic Sequences
252
+ ```
253
+ # Manual sequences that should be automatic
254
+ manual_active = [s for s in all_sequences['value']
255
+ if s.get('Manual') == 'Yes' and s.get('InUse') == 'Yes']
256
+
257
+ # Stopped sequences still marked as in use
258
+ stopped_in_use = [s for s in all_sequences['value']
259
+ if s.get('Stopped') == 'Yes' and s.get('InUse') == 'Yes']
260
+ ```
261
+
262
+ ## Output Format
263
+
264
+ Structure your analysis as:
265
+
266
+ 1. **Executive Summary** - Key findings and critical issues
267
+ 2. **Environment Overview** - Version, total sequences, basic statistics
268
+ 3. **Sequence Categories** - Breakdown by Manual/Auto, Active/Stopped, Scope
269
+ 4. **Configuration Analysis** - Detailed findings from data analysis
270
+ 5. **Reference Analysis** - Usage patterns and orphaned sequences
271
+ 6. **Recommendations** - Prioritized action items with implementation guidance
272
+ 7. **Risk Assessment** - Potential impacts of identified issues
273
+
274
+ ## Important Constraints
275
+
276
+ - **No Field Filtering**: Cannot filter by Manual, InUse, Stopped, or other fields
277
+ - **No $select Operations**: Must retrieve full records
278
+ - **No $orderby**: Data comes in system order
279
+ - **Large Dataset**: Expect 10,000+ sequence records
280
+ - **Manual Analysis Required**: Filter and analyze data programmatically after retrieval
281
+
282
+ ## Best Practices
283
+
284
+ 1. **Collect First, Filter Later**: Get all data with simple d365fo_query_entities calls
285
+ 2. **Programmatic Analysis**: Use code logic to filter and categorize
286
+ 3. **Key-Based Lookups**: Use d365fo_get_entity_by_key for specific sequence details
287
+ 4. **Reference Cross-Checking**: Compare sequences with their references
288
+ 5. **Pattern Recognition**: Look for naming patterns, scope patterns, format patterns
289
+
290
+ Begin your analysis by using d365fo_get_environment_info and d365fo_query_entities(entity_name="SequenceV2Tables") to gather the foundation data, then build your insights through programmatic analysis of the retrieved records.
291
+ """
292
+
293
+ @staticmethod
294
+ def get_data_retrieval_queries() -> dict:
295
+ """Get standard data retrieval queries for sequence analysis."""
296
+ return {
297
+ "all_sequences": {
298
+ "entity_name": "SequenceV2Tables",
299
+ "description": "Get all number sequences (no filtering due to OData limitations)",
300
+ },
301
+ "sequence_references": {
302
+ "entity_name": "NumberSequencesV2References",
303
+ "description": "Get all sequence references (no filtering due to OData limitations)",
304
+ },
305
+ "specific_sequence": {
306
+ "entity_name": "SequenceV2Tables",
307
+ "key_field": "NumberSequenceCode",
308
+ "description": "Get specific sequence by code using get_entity_by_key",
309
+ },
310
+ }
311
+
312
+ @staticmethod
313
+ def get_analysis_metadata() -> dict:
314
+ """Get metadata for sequence analysis."""
315
+ return {
316
+ "version": "2.0",
317
+ "validated_entities": ["SequenceV2Tables", "NumberSequencesV2References"],
318
+ "known_limitations": [
319
+ "No field filtering on enum/boolean fields",
320
+ "No $select operations",
321
+ "No $orderby operations",
322
+ "Manual data analysis required",
323
+ ],
324
+ "field_values": {
325
+ "Manual": ["Yes", "No"],
326
+ "Stopped": ["Yes", "No"],
327
+ "InUse": ["Yes", "No"],
328
+ "Cyclical": ["Yes", "No"],
329
+ "Continuous": ["Yes", "No"],
330
+ "ScopeType": [
331
+ "DataArea",
332
+ "DataAreaFiscalCalender",
333
+ "LegalEntity",
334
+ "OperatingUnit",
335
+ ],
336
+ },
337
+ "expected_record_count": "10000+",
338
+ "analysis_approach": "collect_all_then_filter",
339
+ }
340
+
341
+
342
+ # Export the complete prompt configuration
343
+ SEQUENCE_ANALYSIS_PROMPT = {
344
+ "name": "sequence_analysis",
345
+ "description": "Comprehensive D365 Finance & Operations number sequence analysis with validated entity schemas and query limitations",
346
+ "template": SequenceAnalysisPrompt.get_prompt_template(),
347
+ "data_queries": SequenceAnalysisPrompt.get_data_retrieval_queries(),
348
+ "metadata": SequenceAnalysisPrompt.get_analysis_metadata(),
349
+ }
@@ -0,0 +1,15 @@
1
+ """Resource handlers package."""
2
+
3
+ from .database_handler import DatabaseResourceHandler
4
+ from .entity_handler import EntityResourceHandler
5
+ from .environment_handler import EnvironmentResourceHandler
6
+ from .metadata_handler import MetadataResourceHandler
7
+ from .query_handler import QueryResourceHandler
8
+
9
+ __all__ = [
10
+ "EntityResourceHandler",
11
+ "MetadataResourceHandler",
12
+ "EnvironmentResourceHandler",
13
+ "QueryResourceHandler",
14
+ "DatabaseResourceHandler",
15
+ ]