d365fo-client 0.3.0__py3-none-any.whl → 0.3.2__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/query.py CHANGED
@@ -1,9 +1,13 @@
1
1
  """OData query utilities for D365 F&O client."""
2
2
 
3
- from typing import Any, Dict, Optional, Union
3
+ from typing import Any, Dict, Optional, Union, TYPE_CHECKING
4
4
  from urllib.parse import quote, urlencode
5
5
 
6
6
  from .models import QueryOptions
7
+ from .odata_serializer import ODataSerializer
8
+
9
+ if TYPE_CHECKING:
10
+ from .models import PublicEntityInfo
7
11
 
8
12
 
9
13
  class QueryBuilder:
@@ -70,47 +74,51 @@ class QueryBuilder:
70
74
  return params
71
75
 
72
76
  @staticmethod
73
- def encode_key(key: Union[str, Dict[str, Any]]) -> str:
74
- """Encode entity key for URL
77
+ def encode_key(
78
+ key: Union[str, Dict[str, Any]],
79
+ entity_schema: Optional["PublicEntityInfo"] = None
80
+ ) -> str:
81
+ """Encode entity key for URL with optional schema-aware serialization.
75
82
 
76
83
  Args:
77
84
  key: Entity key value (string for simple keys, dict for composite keys)
85
+ entity_schema: Optional entity schema for type-aware serialization
78
86
 
79
87
  Returns:
80
- URL-encoded key
88
+ URL-encoded key with proper data type handling
81
89
  """
82
90
  if isinstance(key, dict):
83
- # Format composite key: key1=value1,key2=value2
84
- key_parts = []
85
- for key_name, key_value in key.items():
86
- encoded_value = quote(str(key_value), safe="")
87
- key_parts.append(f"{key_name}='{encoded_value}'")
88
- return ",".join(key_parts)
91
+ # Serialize values according to their data types
92
+ serialized_dict = ODataSerializer.serialize_key_dict(key, entity_schema)
93
+ # Format as composite key with proper quoting
94
+ return ODataSerializer.format_composite_key(serialized_dict, entity_schema)
89
95
  else:
90
- # Simple string key
91
- return quote(str(key), safe="")
96
+ # Simple key - serialize as string type
97
+ return ODataSerializer.serialize_value(str(key), "String", "Edm.String")
92
98
 
93
99
  @staticmethod
94
100
  def build_entity_url(
95
101
  base_url: str,
96
102
  entity_name: str,
97
103
  key: Optional[Union[str, Dict[str, Any]]] = None,
104
+ entity_schema: Optional["PublicEntityInfo"] = None,
98
105
  ) -> str:
99
- """Build entity URL
106
+ """Build entity URL with optional schema-aware key encoding.
100
107
 
101
108
  Args:
102
109
  base_url: Base F&O URL
103
110
  entity_name: Entity set name
104
111
  key: Optional entity key (string for simple keys, dict for composite keys)
112
+ entity_schema: Optional entity schema for type-aware key encoding
105
113
 
106
114
  Returns:
107
- Complete entity URL
115
+ Complete entity URL with properly encoded keys
108
116
  """
109
117
  base = f"{base_url.rstrip('/')}/data/{entity_name}"
110
118
  if key:
111
- encoded_key = QueryBuilder.encode_key(key)
119
+ encoded_key = QueryBuilder.encode_key(key, entity_schema)
112
120
  if isinstance(key, dict):
113
- # For composite keys, don't wrap in additional quotes
121
+ # For composite keys, formatting is handled by ODataSerializer
114
122
  return f"{base}({encoded_key})"
115
123
  else:
116
124
  # For simple string keys, wrap in quotes
@@ -123,17 +131,19 @@ class QueryBuilder:
123
131
  action_name: str,
124
132
  entity_name: Optional[str] = None,
125
133
  entity_key: Optional[Union[str, Dict[str, Any]]] = None,
134
+ entity_schema: Optional["PublicEntityInfo"] = None,
126
135
  ) -> str:
127
- """Build action URL
136
+ """Build action URL with optional schema-aware key encoding.
128
137
 
129
138
  Args:
130
139
  base_url: Base F&O URL
131
140
  action_name: Action name
132
141
  entity_name: Optional entity name for bound actions
133
142
  entity_key: Optional entity key for bound actions (string for simple keys, dict for composite keys)
143
+ entity_schema: Optional entity schema for type-aware key encoding
134
144
 
135
145
  Returns:
136
- Complete action URL
146
+ Complete action URL with properly encoded keys
137
147
  """
138
148
  base = base_url.rstrip("/")
139
149
 
@@ -147,9 +157,9 @@ class QueryBuilder:
147
157
 
148
158
  if entity_name and entity_key:
149
159
  # Bound action on specific entity
150
- encoded_key = QueryBuilder.encode_key(entity_key)
160
+ encoded_key = QueryBuilder.encode_key(entity_key, entity_schema)
151
161
  if isinstance(entity_key, dict):
152
- # For composite keys, don't wrap in additional quotes
162
+ # For composite keys, formatting is handled by ODataSerializer
153
163
  return f"{base}/data/{entity_name}({encoded_key}){action_path}"
154
164
  else:
155
165
  # For simple string keys, wrap in quotes
d365fo_client/settings.py CHANGED
@@ -5,7 +5,7 @@ from enum import Enum
5
5
  from pathlib import Path
6
6
  from typing import Literal, Optional
7
7
 
8
- from pydantic import Field, field_validator
8
+ from pydantic import Field, SecretStr, field_validator
9
9
  from pydantic_settings import BaseSettings, SettingsConfigDict
10
10
 
11
11
  from .utils import get_default_cache_directory
@@ -104,7 +104,15 @@ class D365FOSettings(BaseSettings):
104
104
  description="MCP authentication required scopes (comma-separated)",
105
105
  alias="D365FO_MCP_AUTH_REQUIRED_SCOPES"
106
106
  )
107
-
107
+
108
+ # === MCP API Key Authentication Settings ===
109
+
110
+ mcp_api_key_value: Optional[SecretStr] = Field(
111
+ default=None,
112
+ description="API key value for authentication (send as Authorization: Bearer <key>)",
113
+ alias="D365FO_MCP_API_KEY_VALUE"
114
+ )
115
+
108
116
  # === MCP Server Transport Settings ===
109
117
 
110
118
  mcp_transport: TransportProtocol = Field(
@@ -285,6 +293,10 @@ class D365FOSettings(BaseSettings):
285
293
  def has_mcp_auth_credentials(self) -> bool:
286
294
  """Check if MCP authentication credentials are configured."""
287
295
  return all([self.mcp_auth_client_id, self.mcp_auth_client_secret, self.mcp_auth_tenant_id])
296
+
297
+ def has_mcp_api_key_auth(self) -> bool:
298
+ """Check if API key authentication is configured."""
299
+ return self.mcp_api_key_value is not None
288
300
 
289
301
  def get_startup_mode(self) -> Literal["profile_only", "default_auth", "client_credentials"]:
290
302
  """Determine startup mode based on configuration."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: d365fo-client
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Microsoft Dynamics 365 Finance & Operations client
5
5
  Author-email: Muhammad Afzaal <mo@thedataguy.pro>
6
6
  License-Expression: MIT
@@ -30,7 +30,7 @@ Requires-Dist: diskcache>=5.6.3
30
30
  Requires-Dist: tabulate>=0.9.0
31
31
  Requires-Dist: pyyaml>=6.0
32
32
  Requires-Dist: mcp>=1.13.0
33
- Requires-Dist: uvicorn[standard]>=0.32.0
33
+ Requires-Dist: uvicorn>=0.32.0
34
34
  Requires-Dist: pydantic-settings>=2.6.0
35
35
  Requires-Dist: authlib>=1.6.4
36
36
  Requires-Dist: httpx>=0.28.1
@@ -59,6 +59,34 @@ Dynamic: license-file
59
59
  [![Install with Docker in VS Code](https://img.shields.io/badge/VS_Code-Install_D365_FO_MCP_Server_(Docker)-2496ED?style=flat-square&logo=docker&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=d365fo-docker&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22docker%22%2C%22args%22%3A%5B%22run%22%2C%22--rm%22%2C%22-i%22%2C%22-v%22%2C%22d365fo-mcp%3A%2Fhome%2Fmcp_user%2F%22%2C%22-e%22%2C%22D365FO_CLIENT_ID%3D%24%7Binput%3Aclient_id%7D%22%2C%22-e%22%2C%22D365FO_CLIENT_SECRET%3D%24%7Binput%3Aclient_secret%7D%22%2C%22-e%22%2C%22D365FO_TENANT_ID%3D%24%7Binput%3Atenant_id%7D%22%2C%22ghcr.io%2Fmafzaal%2Fd365fo-client%3Alatest%22%5D%2C%22env%22%3A%7B%22D365FO_LOG_LEVEL%22%3A%22DEBUG%22%2C%22D365FO_CLIENT_ID%22%3A%22%24%7Binput%3Aclient_id%7D%22%2C%22D365FO_CLIENT_SECRET%22%3A%22%24%7Binput%3Aclient_secret%7D%22%2C%22D365FO_TENANT_ID%22%3A%22%24%7Binput%3Atenant_id%7D%22%7D%7D&inputs=%5B%7B%22id%22%3A%22tenant_id%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Azure%20AD%20Tenant%20ID%20for%20D365%20F%26O%20authentication%22%2C%22password%22%3Atrue%7D%2C%7B%22id%22%3A%22client_id%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Azure%20AD%20Client%20ID%20for%20D365%20F%26O%20authentication%22%2C%22password%22%3Atrue%7D%2C%7B%22id%22%3A%22client_secret%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Azure%20AD%20Client%20Secret%20for%20D365%20F%26O%20authentication%22%2C%22password%22%3Atrue%7D%5D)
60
60
  [![Install with Docker in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_D365_FO_MCP_Server_(Docker)-2496ED?style=flat-square&logo=docker&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=d365fo-docker&quality=insiders&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22docker%22%2C%22args%22%3A%5B%22run%22%2C%22--rm%22%2C%22-i%22%2C%22-v%22%2C%22d365fo-mcp%3A%2Fhome%2Fmcp_user%2F%22%2C%22-e%22%2C%22D365FO_CLIENT_ID%3D%24%7Binput%3Aclient_id%7D%22%2C%22-e%22%2C%22D365FO_CLIENT_SECRET%3D%24%7Binput%3Aclient_secret%7D%22%2C%22-e%22%2C%22D365FO_TENANT_ID%3D%24%7Binput%3Atenant_id%7D%22%2C%22ghcr.io%2Fmafzaal%2Fd365fo-client%3Alatest%22%5D%2C%22env%22%3A%7B%22D365FO_LOG_LEVEL%22%3A%22DEBUG%22%2C%22D365FO_CLIENT_ID%22%3A%22%24%7Binput%3Aclient_id%7D%22%2C%22D365FO_CLIENT_SECRET%22%3A%22%24%7Binput%3Aclient_secret%7D%22%2C%22D365FO_TENANT_ID%22%3A%22%24%7Binput%3Atenant_id%7D%22%7D%7D&inputs=%5B%7B%22id%22%3A%22tenant_id%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Azure%20AD%20Tenant%20ID%20for%20D365%20F%26O%20authentication%22%2C%22password%22%3Atrue%7D%2C%7B%22id%22%3A%22client_id%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Azure%20AD%20Client%20ID%20for%20D365%20F%26O%20authentication%22%2C%22password%22%3Atrue%7D%2C%7B%22id%22%3A%22client_secret%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Azure%20AD%20Client%20Secret%20for%20D365%20F%26O%20authentication%22%2C%22password%22%3Atrue%7D%5D)
61
61
 
62
+ **☁️ Deploy to Azure Container Apps:**
63
+
64
+ Deploy the MCP server as a secure, internet-accessible HTTP endpoint with OAuth or API Key authentication. Perfect for web integrations and remote AI assistant access.
65
+
66
+ **Option 1: Using Bash Script (Recommended)**
67
+ ```bash
68
+ # Download and run the deployment script
69
+ curl -O https://raw.githubusercontent.com/mafzaal/d365fo-client/main/deploy-aca.sh
70
+ chmod +x deploy-aca.sh
71
+
72
+ # Set authentication (choose OAuth or API Key)
73
+ export D365FO_MCP_AUTH_CLIENT_ID="your-client-id"
74
+ export D365FO_MCP_AUTH_CLIENT_SECRET="your-client-secret"
75
+ export D365FO_MCP_AUTH_TENANT_ID="your-tenant-id"
76
+ # OR
77
+ export D365FO_MCP_API_KEY_VALUE="your-secret-key"
78
+
79
+ # Deploy
80
+ ./deploy-aca.sh
81
+ ```
82
+
83
+ **Option 2: Using ARM Template**
84
+ 1. Download [azure-deploy.json](https://raw.githubusercontent.com/mafzaal/d365fo-client/main/azure-deploy.json)
85
+ 2. Go to [Azure Portal → Deploy a custom template](https://portal.azure.com/#create/Microsoft.Template)
86
+ 3. Click "Build your own template in the editor"
87
+ 4. Paste the contents of `azure-deploy.json`
88
+ 5. Fill in the parameters and deploy
89
+
62
90
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/d365fo-client?label=Downloads)](https://pypi.org/project/d365fo-client/)
63
91
 
64
92
  **Also includes a comprehensive Python client library** for Microsoft Dynamics 365 Finance & Operations with OData endpoints, metadata operations, label management, and CLI tools.
@@ -822,7 +850,8 @@ export DEBUG="true" # Enable debug mode
822
850
  - 🏷️ **Label Operations V2**: Multilingual label caching with performance improvements and async support
823
851
  - 🔍 **Advanced Querying**: Support for all OData query parameters ($select, $filter, $expand, etc.)
824
852
  - ⚡ **Action Execution**: Execute bound and unbound OData actions with comprehensive parameter handling
825
- - 🔒 **Authentication**: Azure AD integration with default credentials, service principal, and Azure Key Vault support
853
+ - �️ **JSON Services**: Generic access to D365 F&O JSON service endpoints (/api/services pattern)
854
+ - �🔒 **Authentication**: Azure AD integration with default credentials, service principal, and Azure Key Vault support
826
855
  - 💾 **Intelligent Caching**: Cross-environment cache sharing with module-based version detection
827
856
  - 🌐 **Async/Await**: Modern async/await patterns with optimized session management
828
857
  - 📝 **Type Hints**: Full type annotation support with enhanced data models
@@ -933,6 +962,18 @@ d365fo-client labels resolve "@SYS13342"
933
962
  d365fo-client labels search "customer" --language "en-US"
934
963
  ```
935
964
 
965
+ #### JSON Service Operations
966
+ ```bash
967
+ # Call SQL diagnostic services
968
+ d365fo-client service sql-diagnostic GetAxSqlExecuting
969
+ d365fo-client service sql-diagnostic GetAxSqlResourceStats --since-minutes 5
970
+ d365fo-client service sql-diagnostic GetAxSqlBlocking --output json
971
+
972
+ # Generic JSON service calls
973
+ d365fo-client service call SysSqlDiagnosticService SysSqlDiagnosticServiceOperations GetAxSqlExecuting
974
+ d365fo-client service call YourServiceGroup YourServiceName YourOperation --parameters '{"param1":"value1"}'
975
+ ```
976
+
936
977
  ### Global Options
937
978
 
938
979
  - `--base-url URL` — Specify D365 F&O environment URL
@@ -1189,6 +1230,76 @@ result = await client.post_data("/data/CustomersV3('US-001')/calculateBalance",
1189
1230
  })
1190
1231
  ```
1191
1232
 
1233
+ ### JSON Service Operations
1234
+
1235
+ ```python
1236
+ # Basic JSON service call (no parameters)
1237
+ response = await client.post_json_service(
1238
+ service_group="SysSqlDiagnosticService",
1239
+ service_name="SysSqlDiagnosticServiceOperations",
1240
+ operation_name="GetAxSqlExecuting"
1241
+ )
1242
+
1243
+ if response.success:
1244
+ print(f"Found {len(response.data)} executing SQL statements")
1245
+ print(f"Status: HTTP {response.status_code}")
1246
+ else:
1247
+ print(f"Error: {response.error_message}")
1248
+
1249
+ # JSON service call with parameters
1250
+ from datetime import datetime, timezone, timedelta
1251
+
1252
+ end_time = datetime.now(timezone.utc)
1253
+ start_time = end_time - timedelta(minutes=10)
1254
+
1255
+ response = await client.post_json_service(
1256
+ service_group="SysSqlDiagnosticService",
1257
+ service_name="SysSqlDiagnosticServiceOperations",
1258
+ operation_name="GetAxSqlResourceStats",
1259
+ parameters={
1260
+ "start": start_time.isoformat(),
1261
+ "end": end_time.isoformat()
1262
+ }
1263
+ )
1264
+
1265
+ # Using JsonServiceRequest object for better structure
1266
+ from d365fo_client.models import JsonServiceRequest
1267
+
1268
+ request = JsonServiceRequest(
1269
+ service_group="SysSqlDiagnosticService",
1270
+ service_name="SysSqlDiagnosticServiceOperations",
1271
+ operation_name="GetAxSqlBlocking"
1272
+ )
1273
+
1274
+ response = await client.call_json_service(request)
1275
+ print(f"Service endpoint: {request.get_endpoint_path()}")
1276
+
1277
+ # Multiple SQL diagnostic operations
1278
+ operations = ["GetAxSqlExecuting", "GetAxSqlBlocking", "GetAxSqlLockInfo"]
1279
+ for operation in operations:
1280
+ response = await client.post_json_service(
1281
+ service_group="SysSqlDiagnosticService",
1282
+ service_name="SysSqlDiagnosticServiceOperations",
1283
+ operation_name=operation
1284
+ )
1285
+
1286
+ if response.success:
1287
+ count = len(response.data) if isinstance(response.data, list) else 1
1288
+ print(f"{operation}: {count} records")
1289
+
1290
+ # Custom service call template
1291
+ response = await client.post_json_service(
1292
+ service_group="YourServiceGroup",
1293
+ service_name="YourServiceName",
1294
+ operation_name="YourOperation",
1295
+ parameters={
1296
+ "parameter1": "value1",
1297
+ "parameter2": 123,
1298
+ "parameter3": True
1299
+ }
1300
+ )
1301
+ ```
1302
+
1192
1303
  ### Metadata Operations
1193
1304
 
1194
1305
  ```python
@@ -1,31 +1,32 @@
1
1
  d365fo_client/__init__.py,sha256=uJ8QB_7tc5oHKt6kJt8hDjpL4IWG50JAbHOP3ZwyJsc,7947
2
2
  d365fo_client/auth.py,sha256=CgO2KctDvqftWWJMFIQA22KL8na9ISlrcOMd7NPNJlk,4152
3
- d365fo_client/cli.py,sha256=NBYzxQ4upvSgibj-5Dg2Gz5-CMqv4KT7It7uVXee3j0,26784
4
- d365fo_client/client.py,sha256=BM-XtUwzt5ehWIsT6FneNWW63fgfI6NO68RANw0rtEI,55447
3
+ d365fo_client/cli.py,sha256=O8grQ0OIVqa3gVvDv8Sz6vbYuYuYVyBhqoRu7qmmT-Q,32255
4
+ d365fo_client/client.py,sha256=3lbLDclu0em_VpOQBj7Q9pQT-mTsMpMk8d4AnCEnUr0,70554
5
5
  d365fo_client/config.py,sha256=p4bF_WemoLyR70-CZvL7tmTR2L-vAo-9-uY0uFpZv5Q,11569
6
6
  d365fo_client/credential_sources.py,sha256=19nnkjbPjubq84BgTLay2U1eqQP6caUc4R-ZeegIsAM,17560
7
- d365fo_client/crud.py,sha256=YBjYIKqgyWYsLB8uRtI_sjRa2G7d9qtgm5mLGCB2CfA,6701
7
+ d365fo_client/crud.py,sha256=b5eSzospp_ahuH-DfwjA-EfbUUMio0iDOkfmV7h3Ai8,7963
8
8
  d365fo_client/exceptions.py,sha256=k8tVb5K6C_F4sCY5NVoE5RYpKPjCgPLd3JtcLIuXzTw,733
9
9
  d365fo_client/labels.py,sha256=a7b_YYWDWaXANirDAr-CoodEpBvfaZvRGy76kNg4Z44,18412
10
- d365fo_client/main.py,sha256=VrQ3eTkc2BRJtmGqn0NJLPDHKoaj-pYcmVnVEeRxzKo,19008
10
+ d365fo_client/main.py,sha256=E0xcDGwvcvTyhdzHvR2cR9h0geTXQ8hl-uQOEw8DXU8,20932
11
11
  d365fo_client/metadata_api.py,sha256=1tDkPLxvR3F4St8GjHssn9EAoNa-ZDEP0-pbGa84DLI,41624
12
- d365fo_client/models.py,sha256=2OA9zd10ac2vOxR5BHmHhAqR_UeBqwsLSczd0WakjXU,28550
12
+ d365fo_client/models.py,sha256=GG2MLnHT_PoZ2bW3BA9OpawLmzkOHsA4nXyws0NDnKc,29828
13
+ d365fo_client/odata_serializer.py,sha256=wcqufwWkT8PhCUm8ahctSbTTJqzjZ-eJXzd1s42DixY,11496
13
14
  d365fo_client/output.py,sha256=0hfyPQ_JvC8lf4s-D8lcrFiokqV_SLB06hVDb0AeE28,5981
14
15
  d365fo_client/profile_manager.py,sha256=43_V82r0gugEgn5o2EbGN-JDleJaEFMPH9Ak4KmJVdk,13710
15
16
  d365fo_client/profiles.py,sha256=3EwD9zYfyjdiuPPaul-_qvL8GUPiky_m6kyZqoYN20I,8106
16
- d365fo_client/query.py,sha256=wOZjXEtGzPcd5mRfdkpMZTHZdSId44gLSboJs4LeSaw,5028
17
+ d365fo_client/query.py,sha256=oWDlb2aDaLCaYNBM29pXBfvPpwFiLlqvqBf5F1cg8kI,5882
17
18
  d365fo_client/session.py,sha256=4OIR61eYQHALPmbXZ446Ko4j5ttvozDxDRnMikogBys,1841
18
- d365fo_client/settings.py,sha256=Pq5GnJA6B15RDKCbaIR8XQQ2Leys3RvqI1sfm3f2qcA,10854
19
+ d365fo_client/settings.py,sha256=kkoB1UUo2Hwkz42hlpj35g_ih-BaP6vHCLPRea6N_10,11284
19
20
  d365fo_client/sync_models.py,sha256=BOYR3zCaqPwrvAQq2pM3cBb6Pt9SU7pxKKTAJLsoVZA,9247
20
21
  d365fo_client/utils.py,sha256=JywzDfgEI4Ei3l6xnAA0aw15RThWAT8mY-C4tpTrToU,6846
21
22
  d365fo_client/mcp/__init__.py,sha256=IT55UrOYT3kC7DS5zlALPilVu_KEIlVgIm3WR7QmEcQ,673
22
23
  d365fo_client/mcp/client_manager.py,sha256=LoCpRl_WeURXVjv8ugBFFlWqQ3bUO-HpP94CwC5c010,9705
23
- d365fo_client/mcp/fastmcp_main.py,sha256=0kzxugFnqRyiiWaEmeX2_ZSmnn5TzJKwB_jeRiXafC8,13934
24
+ d365fo_client/mcp/fastmcp_main.py,sha256=a8K2agZtGkKzb2bNAJrqqDvDRQJvjKBBHXccYrZXy4M,15801
24
25
  d365fo_client/mcp/fastmcp_server.py,sha256=xm1gugM8TX0n613n9MqRFDlBL9pK2-5jsM2kpbsCt9o,23873
25
- d365fo_client/mcp/fastmcp_utils.py,sha256=uBg4iziIEVN-MiMxtMwSg8a4RPseW6ltC-HKdGq-dWw,18250
26
+ d365fo_client/mcp/fastmcp_utils.py,sha256=QMcc57p-H1B_l9R1CMyD7CtNtHkcb7qeI0tFQOpr_iQ,18496
26
27
  d365fo_client/mcp/main.py,sha256=sNG6IIs3SvzumUhfzRH6aNzN2T7OZrPNl7_Yx-Fkt8I,5333
27
28
  d365fo_client/mcp/models.py,sha256=Tq48Xvh6aXkGAHZ805r1OwPIzftUGXSYE-rt0pY4wI8,7493
28
- d365fo_client/mcp/server.py,sha256=n4BlgfJkMuRZbHD8jshZOS-oPH-Pi2uKBExE4oxeo3U,24964
29
+ d365fo_client/mcp/server.py,sha256=SWIfDEM2ieVCT_naUgI-eW2TqHH5wv0SVL7HgSLhdxA,25540
29
30
  d365fo_client/mcp/auth_server/__init__.py,sha256=PaB9lYYwpfPRXgd05RgZVQfnabKfCufzKr3Zqcclal8,128
30
31
  d365fo_client/mcp/auth_server/dependencies.py,sha256=CE0olD7ugJIbmfBrA3Y-w2gVWQBbExnRQxu1i2DuV40,3915
31
32
  d365fo_client/mcp/auth_server/auth/__init__.py,sha256=GwoyosVxuWCPzFHaCnj6iFp9fulnp124G2gQfsnzcgc,695
@@ -33,13 +34,14 @@ d365fo_client/mcp/auth_server/auth/auth.py,sha256=YLM04cwXHURaI1o3liPhAw-37YAnDO
33
34
  d365fo_client/mcp/auth_server/auth/oauth_proxy.py,sha256=EOveccoyF6wkRuf1ccQ-3QHH1n8JGzinKzbrbyodQHs,42253
34
35
  d365fo_client/mcp/auth_server/auth/redirect_validation.py,sha256=Jlhela9xpTbw4aWnQ04A5Z-TW0HYOC3f9BMsq3NXx1Q,2000
35
36
  d365fo_client/mcp/auth_server/auth/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- d365fo_client/mcp/auth_server/auth/providers/azure.py,sha256=MyOkyz_c19MB9RrcaM-mXuTbIlRK-Z5Z-o2AnT7N-jk,12824
37
+ d365fo_client/mcp/auth_server/auth/providers/apikey.py,sha256=g9ZvzE40fjRFrth-0FhFiBLFSfCFV2uV5jIBlDr0F2Y,2960
38
+ d365fo_client/mcp/auth_server/auth/providers/azure.py,sha256=3oyVz6AAoHNQP7UKnSmNA9jDOQY9kNbgawgE181vF_4,16032
37
39
  d365fo_client/mcp/auth_server/auth/providers/bearer.py,sha256=uz7sbxXQobem3YV6HUSf-QUOnkhhnmjyXoUEu5AIIkc,891
38
40
  d365fo_client/mcp/auth_server/auth/providers/jwt.py,sha256=Xj9W8WsENjeT8U3Ncic69gxQREkPp1P6LxQodE3UI5A,19542
39
41
  d365fo_client/mcp/mixins/__init__.py,sha256=b7sJ77m-7EmT5PKEuMkIIBAI6ISTG2-ZnNNQQBVYbTc,778
40
- d365fo_client/mcp/mixins/base_tools_mixin.py,sha256=pk13sckDjKQqqwS8VQyRIqXRa-M0xiB4IdwTBP1sY3k,1694
42
+ d365fo_client/mcp/mixins/base_tools_mixin.py,sha256=Pk3qli8A1DzD1-uypjMFa6YSXBqVK_gfkq2HLiGfjY0,1642
41
43
  d365fo_client/mcp/mixins/connection_tools_mixin.py,sha256=RUynwtbdTGgGRmPyTdyF_H8WK5nDrnr9CdIIKInk23k,1713
42
- d365fo_client/mcp/mixins/crud_tools_mixin.py,sha256=zV3UqpSiUb8EJZOWnJIhIytLFmjOb7Zty27sh6UKCkA,12670
44
+ d365fo_client/mcp/mixins/crud_tools_mixin.py,sha256=sxfDbO2vfT2k2SO3zwZMn7kHpVGmoF5DrEybv0JbVS0,18670
43
45
  d365fo_client/mcp/mixins/database_tools_mixin.py,sha256=6FeT-IVl5diikNE3IV-7kujo8TLfmcz48sK2DsO7gXw,29335
44
46
  d365fo_client/mcp/mixins/label_tools_mixin.py,sha256=TYwdMVnkmJzbPWAn3bnj8AtGUZYoGzzEo7gnBCktw3o,2692
45
47
  d365fo_client/mcp/mixins/metadata_tools_mixin.py,sha256=lyFqnree5J2o-0hb_uBWQ2cD1TARBxZvQbzcVe_0Unw,26037
@@ -55,10 +57,11 @@ d365fo_client/mcp/resources/entity_handler.py,sha256=wFYMPp_Rny-HZams5NtIFF8vrYU
55
57
  d365fo_client/mcp/resources/environment_handler.py,sha256=iblut_E_0q9Z4gfOeEG5bfodTPOzFcvfiYQFzH3WggE,4469
56
58
  d365fo_client/mcp/resources/metadata_handler.py,sha256=ZPH4yAylASpbAPptWMHazACKS3dhDQKr88o22KBqRsM,11618
57
59
  d365fo_client/mcp/resources/query_handler.py,sha256=NMJ07SolMO_rjdY9l7m53_EV2j0KHQSrckTySnTw1oU,4635
58
- d365fo_client/mcp/tools/__init__.py,sha256=kfPPcs2r6biL_KLn-1MqSN2tU2eD5QahocMIun7yfuU,463
60
+ d365fo_client/mcp/tools/__init__.py,sha256=CDMug55Nm6NAYDqzh9_rZKs2M-z59VK4QkKag_BXZjo,536
59
61
  d365fo_client/mcp/tools/connection_tools.py,sha256=TT4eDF0Bb8gS36nTj5K-AIuuAYCZMB-UjW66w5HLi3I,6872
60
62
  d365fo_client/mcp/tools/crud_tools.py,sha256=Ed6qKPekGvDMwOLahPbtGl-xAyFhC96qzmxpKa2wL2Y,31682
61
63
  d365fo_client/mcp/tools/database_tools.py,sha256=Kh9g-e0RCTKPbmsuZ99MDK8-ZYaBB2czbElHDaJXPGU,33286
64
+ d365fo_client/mcp/tools/json_service_tools.py,sha256=m3G235YrIIc4UP_GEvAwtZ5syQzDUvRyW3tf4xe1T4g,12334
62
65
  d365fo_client/mcp/tools/label_tools.py,sha256=BpUI55MgDjhokN44JhZLh1J46JgiPL0Fh0pfhZrD5I0,6376
63
66
  d365fo_client/mcp/tools/metadata_tools.py,sha256=NHFrQbpL0403EA2mxLqqRE0q7MDPLroZ79JRb3gqxeQ,32260
64
67
  d365fo_client/mcp/tools/profile_tools.py,sha256=n8-uGbA-K4kFVBZ--yfk-9znyPydiwCoWNEm9EpULwg,42337
@@ -76,9 +79,9 @@ d365fo_client/metadata_v2/search_engine_v2.py,sha256=s_XVqP3LLog19IAv8DpxVUS7TFR
76
79
  d365fo_client/metadata_v2/sync_manager_v2.py,sha256=JM8ThiXyXKYlnGaH3iwbBlPd9RFkDr0-ivkuHLAIo40,34090
77
80
  d365fo_client/metadata_v2/sync_session_manager.py,sha256=XWxjFGwgnm6S4lzeYqyPqZgvpcqzK3tBaxnQ-srgYrg,44365
78
81
  d365fo_client/metadata_v2/version_detector.py,sha256=t9mKaeT4SKb13LmIq5fB6PTLOZn5Jp7ZUqQobntNEUg,15791
79
- d365fo_client-0.3.0.dist-info/licenses/LICENSE,sha256=idD7NJAZD7ognzZVyKjDxVYDCmngEIt0WxA_uB1v0iI,1071
80
- d365fo_client-0.3.0.dist-info/METADATA,sha256=AbDB8_EoFT_MaATG9HDXXPvIQ16sJ3dAw78HrLICB2s,59480
81
- d365fo_client-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
82
- d365fo_client-0.3.0.dist-info/entry_points.txt,sha256=jCw6TT6lLRKzAWTSzxMhdYbTT-m5v0LDcZ9Zun4JM-0,174
83
- d365fo_client-0.3.0.dist-info/top_level.txt,sha256=ZbvqO90RjhOW0cjFCAEeP8OFyITbhrij2vC3k4bWERQ,14
84
- d365fo_client-0.3.0.dist-info/RECORD,,
82
+ d365fo_client-0.3.2.dist-info/licenses/LICENSE,sha256=idD7NJAZD7ognzZVyKjDxVYDCmngEIt0WxA_uB1v0iI,1071
83
+ d365fo_client-0.3.2.dist-info/METADATA,sha256=AgOQLu9KsyxcGuD5C92qiLQK__xreaCsMrQJGbsCFsg,63275
84
+ d365fo_client-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
85
+ d365fo_client-0.3.2.dist-info/entry_points.txt,sha256=jCw6TT6lLRKzAWTSzxMhdYbTT-m5v0LDcZ9Zun4JM-0,174
86
+ d365fo_client-0.3.2.dist-info/top_level.txt,sha256=ZbvqO90RjhOW0cjFCAEeP8OFyITbhrij2vC3k4bWERQ,14
87
+ d365fo_client-0.3.2.dist-info/RECORD,,