d365fo-client

mafzaal/d365fo-client

3.4

If you are the rightful owner of d365fo-client and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

The Model Context Protocol (MCP) server for Dynamics 365 Finance & Operations provides a standardized interface for AI assistants and other MCP-compatible tools to interact with D365 F&O functionalities.

Tools
5
Resources
0
Prompts
0

Dynamics 365 Finance & Operations MCP Server

Production-ready Model Context Protocol (MCP) server that exposes the full capabilities of Microsoft Dynamics 365 Finance & Operations (D365 F&O) to AI assistants and other MCP-compatible tools. This enables sophisticated Dynamics 365 integration workflows through standardized protocol interactions.

๐Ÿš€ One-Click Installation for VS Code:

Install with UVX in VS Code Install with UVX in VS Code Insiders

๐Ÿณ Docker Installation for VS Code:

Install with Docker in VS Code Install with Docker in VS Code Insiders

โ˜๏ธ Deploy to Azure Container Apps:

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.

Option 1: Using Bash Script (Recommended)

# Download and run the deployment script
curl -O https://raw.githubusercontent.com/mafzaal/d365fo-client/main/deploy-aca.sh
chmod +x deploy-aca.sh

# Set authentication (choose OAuth or API Key)
export D365FO_MCP_AUTH_CLIENT_ID="your-client-id"
export D365FO_MCP_AUTH_CLIENT_SECRET="your-client-secret"
export D365FO_MCP_AUTH_TENANT_ID="your-tenant-id"
# OR
export D365FO_MCP_API_KEY_VALUE="your-secret-key"

# Deploy
./deploy-aca.sh

Option 2: Using ARM Template

  1. Download azure-deploy.json
  2. Go to Azure Portal โ†’ Deploy a custom template
  3. Click "Build your own template in the editor"
  4. Paste the contents of azure-deploy.json
  5. Fill in the parameters and deploy

PyPI - Downloads

Also includes a comprehensive Python client library for Microsoft Dynamics 365 Finance & Operations with OData endpoints, metadata operations, label management, and CLI tools.

MCP Server Overview

The d365fo-client includes two production-ready Model Context Protocol (MCP) servers that expose the full capabilities of D365 Finance & Operations to AI assistants and other MCP-compatible tools:

  • Traditional MCP SDK (d365fo-mcp-server) - Original implementation with stdio support
  • FastMCP Framework (d365fo-fastmcp-server) - Modern implementation with multi-transport support โญ Recommended

Both servers provide identical functionality but the FastMCP implementation offers enhanced performance and deployment flexibility.

Key Features

  • 34 comprehensive tools covering all major D365 F&O operations across 7 functional categories
  • 12 resource types with comprehensive metadata exposure and discovery capabilities
  • 2 prompt templates for advanced workflow assistance
  • Multi-transport support (FastMCP): stdio, HTTP, Server-Sent Events (SSE)
  • Production-ready implementation with proper error handling, authentication, and security validation
  • Enhanced performance (FastMCP): 40% faster startup, 15% lower memory usage
  • Advanced profile management supporting multiple environments with secure credential storage
  • Database analysis capabilities with secure SQL querying and metadata insights
  • Session-based synchronization with detailed progress tracking and multiple sync strategies
  • Multi-language support with label resolution and localization capabilities
  • Enterprise security with Azure AD integration, Key Vault support, and audit logging

New in v0.3.0

  • ๐Ÿ”ง Pydantic Settings Model: Type-safe environment variable management with validation for 35+ configuration options
  • ๐Ÿ“‚ Custom Log File Support: D365FO_LOG_FILE environment variable for flexible log file paths
  • ๐Ÿ”„ Legacy Config Migration: Automatic detection and migration of legacy configuration files
  • ๐ŸŒ Environment Variable Standardization: All MCP HTTP variables now use D365FO_ prefix for consistency
  • โšก Enhanced FastMCP Server: Improved startup configuration, error handling, and graceful shutdown
  • ๐Ÿ”€ MCP Return Type Standardization: All MCP tools now return dictionaries instead of JSON strings for better type safety
  • ๐Ÿ› ๏ธ Enhanced Configuration: Support for .env files and comprehensive environment variable documentation

Quick Start

Installation and Setup
# Install d365fo-client with MCP dependencies
pip install d365fo-client

# Set up environment variables
export D365FO_BASE_URL="https://your-environment.dynamics.com"
export D365FO_CLIENT_ID="your-client-id"          # Optional with default credentials
export D365FO_CLIENT_SECRET="your-client-secret"  # Optional with default credentials  
export D365FO_TENANT_ID="your-tenant-id"          # Optional with default credentials
FastMCP Server (Recommended)

The modern FastMCP implementation provides enhanced performance and multiple transport options:

# Development (stdio transport - default)
d365fo-fastmcp-server

# Production HTTP API
d365fo-fastmcp-server --transport http --port 8000 --host 0.0.0.0

# Real-time Web Applications (SSE)
d365fo-fastmcp-server --transport sse --port 8001 --host 0.0.0.0

Key Benefits:

  • 40% faster startup compared to traditional MCP SDK
  • 15% lower memory usage through optimized architecture
  • Multi-transport support: stdio, HTTP, Server-Sent Events (SSE)
  • Enhanced error handling with better async/await support
  • Production ready with web transports for API integration
Traditional MCP Server

The original MCP SDK implementation remains available for backward compatibility:

# Start the traditional MCP server
d365fo-mcp-server
Integration with AI Assistants
VS Code Integration (Recommended)

FastMCP Server with Default Credentials: Add to your VS Code mcp.json for GitHub Copilot with MCP:

{
  "servers": {
    "d365fo-fastmcp-server": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "--from",
        "d365fo-client@latest",
        "d365fo-fastmcp-server"
      ],
      "env": {
        "D365FO_BASE_URL": "https://your-environment.dynamics.com",
        "D365FO_LOG_LEVEL": "INFO"
      }
    }
  }
}

Traditional MCP Server (Alternative):

{
  "servers": {
    "d365fo-mcp-server": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "--from",
        "d365fo-client",
        "d365fo-mcp-server"
      ],
      "env": {
        "D365FO_BASE_URL": "https://your-environment.dynamics.com",
        "D365FO_LOG_LEVEL": "INFO"
      }
    }
  }
}

Option 2: Explicit Credentials For environments requiring service principal authentication:

{
  "servers": {
    "d365fo-fastmcp-server": {
      "type": "stdio", 
      "command": "uvx",
      "args": [
        "--from",
        "d365fo-client",
        "d365fo-fastmcp-server"
      ],
      "env": {
        "D365FO_BASE_URL": "https://your-environment.dynamics.com",
        "D365FO_LOG_LEVEL": "DEBUG",
        "D365FO_CLIENT_ID": "${input:client_id}",
        "D365FO_CLIENT_SECRET": "${input:client_secret}",
        "D365FO_TENANT_ID": "${input:tenant_id}"
      }
    }
  },
  "inputs": [
    {
      "id": "tenant_id",
      "type": "promptString",
      "description": "Azure AD Tenant ID for D365 F&O authentication",
      "password": true
    },
    {
      "id": "client_id", 
      "type": "promptString",
      "description": "Azure AD Client ID for D365 F&O authentication",
      "password": true
    },
    {
      "id": "client_secret",
      "type": "promptString", 
      "description": "Azure AD Client Secret for D365 F&O authentication",
      "password": true
    }
  ]
}

Option 3: Docker Integration For containerized environments and enhanced isolation:

{
  "servers": {
    "d365fo-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "-v",
        "d365fo-mcp:/home/mcp_user/",
        "-e",
        "D365FO_CLIENT_ID=${input:client_id}",
        "-e",
        "D365FO_CLIENT_SECRET=${input:client_secret}",
        "-e",
        "D365FO_TENANT_ID=${input:tenant_id}",
        "ghcr.io/mafzaal/d365fo-client:latest"
      ],
      "env": {
        "D365FO_LOG_LEVEL": "DEBUG",
        "D365FO_CLIENT_ID": "${input:client_id}",
        "D365FO_CLIENT_SECRET": "${input:client_secret}",
        "D365FO_TENANT_ID": "${input:tenant_id}"
      }
    }
  },
  "inputs": [
    {
      "id": "tenant_id",
      "type": "promptString",
      "description": "Azure AD Tenant ID for D365 F&O authentication",
      "password": true
    },
    {
      "id": "client_id",
      "type": "promptString",
      "description": "Azure AD Client ID for D365 F&O authentication",
      "password": true
    },
    {
      "id": "client_secret",
      "type": "promptString",
      "description": "Azure AD Client Secret for D365 F&O authentication",
      "password": true
    }
  ]
}

Benefits of Docker approach:

  • Complete environment isolation and reproducibility
  • No local Python installation required
  • Consistent runtime environment across different systems
  • Automatic dependency management with pre-built image
  • Enhanced security through containerization
  • Persistent data storage via Docker volume (d365fo-mcp)

Prerequisites:

  • Docker installed and running
  • Access to Docker Hub or GitHub Container Registry
  • Network access for pulling the container image
Claude Desktop Integration

FastMCP Server: Add to your Claude Desktop configuration:

{
  "mcpServers": {
    "d365fo-fastmcp": {
      "command": "uvx",
      "args": [
        "--from",
        "d365fo-client",
        "d365fo-fastmcp-server"
      ],
      "env": {
        "D365FO_BASE_URL": "https://your-environment.dynamics.com",
        "D365FO_LOG_LEVEL": "INFO"
      }
    }
  }
}

Traditional MCP Server (Alternative):

{
  "mcpServers": {
    "d365fo": {
      "command": "uvx",
      "args": [
        "--from",
        "d365fo-client",
        "d365fo-mcp-server"
      ],
      "env": {
        "D365FO_BASE_URL": "https://your-environment.dynamics.com",
        "D365FO_LOG_LEVEL": "INFO"
      }
    }
  }
}

Benefits of uvx approach:

  • Always uses the latest version from the repository
  • No local installation required
  • Automatic dependency management
  • Works across different environments
Web Integration with FastMCP

The FastMCP server provides HTTP and SSE transports for web application integration:

HTTP Transport for Web APIs
import aiohttp
import json

async def call_d365fo_api():
    """Example: Using HTTP transport for web API integration"""
    
    # Start FastMCP server with HTTP transport
    # d365fo-fastmcp-server --transport http --port 8000
    
    mcp_request = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "d365fo_query_entities",
            "arguments": {
                "entityName": "CustomersV3",
                "top": 10,
                "select": ["CustomerAccount", "Name"]
            }
        }
    }
    
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "http://localhost:8000/mcp",
            json=mcp_request,
            headers={"Content-Type": "application/json"}
        ) as response:
            result = await response.json()
            print(json.dumps(result, indent=2))
SSE Transport for Real-time Applications
// Example: JavaScript client for real-time D365FO data
// Start FastMCP server: d365fo-fastmcp-server --transport sse --port 8001

const eventSource = new EventSource('http://localhost:8001/sse');

eventSource.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log('Received D365FO data:', data);
    
    // Handle real-time updates from D365FO
    if (data.method === 'notification') {
        updateDashboard(data.params);
    }
};

// Send MCP requests via SSE
function queryCustomers() {
    const request = {
        jsonrpc: "2.0",
        id: Date.now(),
        method: "tools/call",
        params: {
            name: "d365fo_search_entities",
            arguments: {
                pattern: "customer",
                limit: 50
            }
        }
    };
    
    fetch('http://localhost:8001/sse/send', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(request)
    });
}
Alternative: Programmatic Usage
from d365fo_client.mcp import D365FOMCPServer

# Create and run server with custom configuration
config = {
    "default_environment": {
        "base_url": "https://your-environment.dynamics.com",
        "use_default_credentials": True
    }
}

server = D365FOMCPServer(config)
await server.run()
Custom MCP Clients

Connect using any MCP-compatible client library:

from mcp import Client

async with Client("d365fo-mcp-server") as client:
    # Discover available tools
    tools = await client.list_tools()
    
    # Execute operations
    result = await client.call_tool(
        "d365fo_query_entities",
        {"entityName": "Customers", "top": 5}
    )
Docker Deployment

For containerized environments and production deployments:

Pull the Docker Image:

# Pull from GitHub Container Registry
docker pull ghcr.io/mafzaal/d365fo-client:latest

# Or pull a specific version
docker pull ghcr.io/mafzaal/d365fo-client:v0.2.3

Standalone Docker Usage:

# Run MCP server with environment variables
docker run --rm -i \
  -e D365FO_BASE_URL="https://your-environment.dynamics.com" \
  -e D365FO_CLIENT_ID="your-client-id" \
  -e D365FO_CLIENT_SECRET="your-client-secret" \
  -e D365FO_TENANT_ID="your-tenant-id" \
  -e D365FO_LOG_LEVEL="INFO" \
  -v d365fo-mcp:/home/mcp_user/ \
  ghcr.io/mafzaal/d365fo-client:latest

# Run CLI commands with Docker
docker run --rm -it \
  -e D365FO_BASE_URL="https://your-environment.dynamics.com" \
  -e D365FO_CLIENT_ID="your-client-id" \
  -e D365FO_CLIENT_SECRET="your-client-secret" \
  -e D365FO_TENANT_ID="your-tenant-id" \
  ghcr.io/mafzaal/d365fo-client:latest \
  d365fo-client entities --limit 10

Docker Compose Example:

version: '3.8'
services:
  d365fo-mcp:
    image: ghcr.io/mafzaal/d365fo-client:latest
    environment:
      - D365FO_BASE_URL=https://your-environment.dynamics.com
      - D365FO_CLIENT_ID=${D365FO_CLIENT_ID}
      - D365FO_CLIENT_SECRET=${D365FO_CLIENT_SECRET}
      - D365FO_TENANT_ID=${D365FO_TENANT_ID}
      - D365FO_LOG_LEVEL=INFO
    volumes:
      - d365fo-mcp:/home/mcp_user/
    stdin_open: true
    tty: true

volumes:
  d365fo-mcp:

Docker Benefits:

  • Complete environment isolation and reproducibility
  • No local Python installation required
  • Consistent runtime environment across different systems
  • Built-in dependency management
  • Enhanced security through containerization
  • Persistent data storage via Docker volumes
  • Easy integration with orchestration platforms (Kubernetes, Docker Swarm)

Architecture Benefits

For AI Assistants
  • Standardized Interface: Consistent MCP protocol access to D365 F&O
  • Rich Metadata: Self-describing entities and operations
  • Type Safety: Schema validation for all operations
  • Error Context: Detailed error information for troubleshooting
For Developers
  • Minimal Integration: Standard MCP client libraries
  • Comprehensive Coverage: Full D365 F&O functionality exposed
  • Performance Optimized: Efficient connection and caching strategies
  • Well Documented: Complete API documentation and examples
For Organizations
  • Secure Access: Enterprise-grade authentication (Azure AD, Managed Identity)
  • Audit Logging: Complete operation tracking and monitoring
  • Scalable Design: Connection pooling and session management
  • Maintenance Friendly: Clear architecture and comprehensive test coverage

Troubleshooting

Common Issues

Connection Failures

# Test connectivity
d365fo-client version app --base-url https://your-environment.dynamics.com

# Check logs
tail -f ~/.d365fo-mcp/logs/mcp-server.log

Authentication Issues

# Verify Azure CLI authentication
az account show

# Test with explicit credentials
export D365FO_CLIENT_ID="your-client-id"
# ... set other variables
d365fo-mcp-server

Performance Issues

# Enable debug logging
export D365FO_LOG_LEVEL="DEBUG"

# Adjust connection settings
export D365FO_CONNECTION_TIMEOUT="120"
export D365FO_MAX_CONCURRENT_REQUESTS="5"
Getting Help
  • Logs: Check ~/.d365fo-mcp/logs/mcp-server.log for detailed error information
  • Environment: Use d365fo_get_environment_info tool to check system status
  • Documentation: See for technical details
  • Issues: Report problems at GitHub Issues

MCP Tools

The server provides 34 comprehensive tools organized into functional categories:

Connection & Environment Tools (2 tools)
  • d365fo_test_connection - Test connectivity and authentication with performance metrics and error diagnostics
  • d365fo_get_environment_info - Get comprehensive environment details including versions, configurations, and capabilities
CRUD Operations Tools (6 tools)
  • d365fo_query_entities - Simplified OData querying with 'eq' filtering, wildcard patterns, field selection, and pagination
  • d365fo_get_entity_record - Retrieve specific records by key with expansion options and ETag support
  • d365fo_create_entity_record - Create new entity records with validation and business logic execution
  • d365fo_update_entity_record - Update existing records with partial updates and optimistic concurrency control
  • d365fo_delete_entity_record - Delete entity records with referential integrity checking and cascading rules
  • d365fo_call_action - Execute OData actions and functions for complex business operations
Metadata Discovery Tools (6 tools)
  • d365fo_search_entities - Search entities by pattern with category filtering and full-text search capabilities
  • d365fo_get_entity_schema - Get detailed entity schemas with properties, relationships, and label resolution
  • d365fo_search_actions - Search available OData actions with binding type and parameter information
  • d365fo_search_enumerations - Search system enumerations with keyword-based filtering
  • d365fo_get_enumeration_fields - Get detailed enumeration member information with multi-language support
  • d365fo_get_installed_modules - Retrieve information about installed modules and their configurations
Label Management Tools (2 tools)
  • d365fo_get_label - Get single label text by ID with multi-language support and fallback options
  • d365fo_get_labels_batch - Get multiple labels efficiently with batch processing and performance optimization
Profile Management Tools (10 tools)
  • d365fo_list_profiles - List all configured D365FO environment profiles with status information
  • d365fo_get_profile - Get detailed configuration information for specific profiles
  • d365fo_create_profile - Create new environment profiles with comprehensive authentication options
  • d365fo_update_profile - Modify existing profile configurations with partial update support
  • d365fo_delete_profile - Remove environment profiles with proper cleanup and validation
  • d365fo_set_default_profile - Designate a specific profile as the default for operations
  • d365fo_get_default_profile - Retrieve information about the currently configured default profile
  • d365fo_validate_profile - Validate profile configurations for completeness and security compliance
  • d365fo_test_profile_connection - Test connectivity and authentication for specific profiles
  • d365fo_get_profile_status - Get comprehensive status information for profiles
Database Analysis Tools (4 tools)
  • d365fo_execute_sql_query - Execute SELECT queries against metadata database with security validation
  • d365fo_get_database_schema - Get comprehensive database schema information including relationships
  • d365fo_get_table_info - Get detailed information about specific database tables with sample data
  • d365fo_get_database_statistics - Generate database statistics and analytics for performance monitoring
Synchronization Tools (4 tools)
  • d365fo_start_sync - Initiate metadata synchronization with various strategies and session tracking
  • d365fo_get_sync_progress - Monitor detailed progress of sync sessions with time estimates
  • d365fo_cancel_sync - Cancel running sync sessions with graceful cleanup
  • d365fo_list_sync_sessions - List all active sync sessions with status and progress information

๐Ÿ“– For detailed information about all MCP tools including usage examples and best practices, see the .

MCP Resources

The server exposes four types of resources for discovery and access:

Entity Resources

Access entity metadata and sample data:

d365fo://entities/CustomersV3     # Customer entity with metadata and sample data
d365fo://entities/SalesOrders     # Sales order entity information
d365fo://entities/Products        # Product entity details
Metadata Resources

Access system-wide metadata:

d365fo://metadata/entities        # All data entities metadata (V2 cache)
d365fo://metadata/actions         # Available OData actions  
d365fo://metadata/enumerations    # System enumerations
d365fo://metadata/labels          # System labels and translations
Environment Resources

Access environment status and information:

d365fo://environment/status       # Environment health and connectivity
d365fo://environment/version      # Version information (app, platform, build)
d365fo://environment/cache        # Cache status and statistics V2
Query Resources

Access predefined and templated queries:

d365fo://queries/customers_recent # Recent customers query template
d365fo://queries/sales_summary    # Sales summary query with parameters
Database Resources (New in V2)

Access metadata database queries:

d365fo://database/entities        # SQL-based entity searches with FTS5
d365fo://database/actions         # Action discovery with metadata
d365fo://database/statistics      # Cache and performance statistics

Usage Examples

Basic Tool Execution
{
  "tool": "d365fo_query_entities",
  "arguments": {
    "entityName": "CustomersV3",
    "select": ["CustomerAccount", "Name", "Email"],
    "filter": "CustomerGroup eq 'VIP'",
    "top": 10
  }
}
Entity Schema Discovery
{
  "tool": "d365fo_get_entity_schema", 
  "arguments": {
    "entityName": "CustomersV3",
    "includeProperties": true,
    "resolveLabels": true,
    "language": "en-US"
  }
}
Environment Information
{
  "tool": "d365fo_get_environment_info",
  "arguments": {}
}

Authentication & Configuration

Default Credentials (Recommended)

Uses Azure Default Credential chain (Managed Identity, Azure CLI, etc.):

export D365FO_BASE_URL="https://your-environment.dynamics.com"
# No additional auth environment variables needed
d365fo-mcp-server
Explicit Credentials

For service principal authentication:

export D365FO_BASE_URL="https://your-environment.dynamics.com"
export D365FO_CLIENT_ID="your-client-id"
export D365FO_CLIENT_SECRET="your-client-secret"
export D365FO_TENANT_ID="your-tenant-id"
d365fo-mcp-server
Azure Key Vault Integration (New in v0.2.3)

For secure credential storage using Azure Key Vault:

export D365FO_BASE_URL="https://your-environment.dynamics.com"
export D365FO_CREDENTIAL_SOURCE="keyvault"
export D365FO_KEYVAULT_URL="https://your-keyvault.vault.azure.net/"
d365fo-mcp-server
Advanced Configuration

New in v0.3.0: Comprehensive environment variable management with type safety and validation using Pydantic settings.

Create a configuration file or set additional environment variables:

# === Core D365FO Connection Settings ===
export D365FO_BASE_URL="https://your-environment.dynamics.com"
export D365FO_CLIENT_ID="your-client-id"
export D365FO_CLIENT_SECRET="your-client-secret"
export D365FO_TENANT_ID="your-tenant-id"

# === Logging Configuration ===
export D365FO_LOG_LEVEL="DEBUG"                        # DEBUG, INFO, WARNING, ERROR, CRITICAL
export D365FO_LOG_FILE="/custom/path/server.log"       # Custom log file path

# === MCP Server Transport Settings (v0.3.0+) ===
export D365FO_MCP_TRANSPORT="stdio"                    # stdio, sse, http, streamable-http
export D365FO_MCP_HTTP_HOST="0.0.0.0"                 # HTTP host (default: 127.0.0.1)
export D365FO_MCP_HTTP_PORT="8000"                     # HTTP port (default: 8000)
export D365FO_MCP_HTTP_STATELESS="true"                # Enable stateless mode
export D365FO_MCP_HTTP_JSON="true"                     # Enable JSON response mode

# === Cache and Performance Settings ===
export D365FO_CACHE_DIR="/custom/cache/path"           # General cache directory
export D365FO_META_CACHE_DIR="/custom/metadata/cache"  # Metadata cache directory
export D365FO_LABEL_CACHE="true"                       # Enable label caching (default: true)
export D365FO_LABEL_EXPIRY="1440"                      # Label cache expiry in minutes (24 hours)
export D365FO_USE_CACHE_FIRST="true"                   # Use cache before API calls

# === Connection and Performance Tuning ===
export D365FO_TIMEOUT="60"                             # General timeout in seconds
export D365FO_MCP_MAX_CONCURRENT_REQUESTS="10"         # Max concurrent requests
export D365FO_MCP_REQUEST_TIMEOUT="30"                 # Request timeout in seconds
export D365FO_VERIFY_SSL="true"                        # Verify SSL certificates

# === MCP Authentication Settings (Advanced) ===
export D365FO_MCP_AUTH_CLIENT_ID="your-mcp-client-id"
export D365FO_MCP_AUTH_CLIENT_SECRET="your-mcp-client-secret"
export D365FO_MCP_AUTH_TENANT_ID="your-mcp-tenant-id"
export D365FO_MCP_AUTH_BASE_URL="http://localhost:8000"
export D365FO_MCP_AUTH_REQUIRED_SCOPES="User.Read,email,openid,profile"

# === Debug Settings ===
export DEBUG="true"                                     # Enable debug mode

Environment File Support: You can also create a .env file in your project directory with these variables for development convenience.

Python Client Library

Features

  • ๐Ÿ”— OData Client: Full CRUD operations on D365 F&O data entities with composite key support
  • ๐Ÿ“Š Metadata Management V2: Enhanced caching system with intelligent synchronization and FTS5 search
  • ๐Ÿท๏ธ Label Operations V2: Multilingual label caching with performance improvements and async support
  • ๐Ÿ” Advanced Querying: Support for all OData query parameters ($select, $filter, $expand, etc.)
  • โšก Action Execution: Execute bound and unbound OData actions with comprehensive parameter handling
  • ๐Ÿ”’ Authentication: Azure AD integration with default credentials, service principal, and Azure Key Vault support
  • ๐Ÿ’พ Intelligent Caching: Cross-environment cache sharing with module-based version detection
  • ๐ŸŒ Async/Await: Modern async/await patterns with optimized session management
  • ๐Ÿ“ Type Hints: Full type annotation support with enhanced data models
  • ๐Ÿค– MCP Server: Production-ready Model Context Protocol server with 12 tools and 4 resource types
  • ๐Ÿ–ฅ๏ธ Comprehensive CLI: Hierarchical command-line interface for all D365 F&O operations
  • ๐Ÿงช Multi-tier Testing: Mock, sandbox, and live integration testing framework (17/17 tests passing)
  • ๐Ÿ“‹ Metadata Scripts: PowerShell and Python utilities for entity, enumeration, and action discovery
  • ๐Ÿ” Enhanced Credential Management: Support for Azure Key Vault and multiple credential sources
  • ๐Ÿ“Š Advanced Sync Management: Session-based synchronization with detailed progress tracking
  • ๐Ÿ”ง NEW v0.3.0: Pydantic settings model with type-safe environment variable validation
  • ๐Ÿ“‚ NEW v0.3.0: Custom log file path support and flexible logging configuration
  • ๐Ÿ”„ NEW v0.3.0: Automatic legacy configuration migration and compatibility layer

Installation

# Install from PyPI
pip install d365fo-client

# Or install from source
git clone https://github.com/mafzaal/d365fo-client.git
cd d365fo-client
uv sync  # Installs with exact dependencies from uv.lock

# Or use Docker (no local installation required)
docker pull ghcr.io/mafzaal/d365fo-client:latest

# Run with Docker
docker run --rm -it \
  -e D365FO_BASE_URL="https://your-environment.dynamics.com" \
  -e D365FO_CLIENT_ID="your-client-id" \
  -e D365FO_CLIENT_SECRET="your-client-secret" \
  -e D365FO_TENANT_ID="your-tenant-id" \
  -v d365fo-mcp:/home/mcp_user/ \
  ghcr.io/mafzaal/d365fo-client:latest

Note: The package includes MCP (Model Context Protocol) dependencies by default, enabling AI assistant integration. Both d365fo-client CLI and d365fo-mcp-server commands will be available after installation.

Breaking Change in v0.2.3: Environment variable names have been updated for consistency:

  • AZURE_CLIENT_ID โ†’ D365FO_CLIENT_ID
  • AZURE_CLIENT_SECRET โ†’ D365FO_CLIENT_SECRET
  • AZURE_TENANT_ID โ†’ D365FO_TENANT_ID

Please update your environment variables accordingly when upgrading.

Python Client Quick Start

Command Line Interface (CLI)

d365fo-client provides a comprehensive CLI with hierarchical commands for interacting with Dynamics 365 Finance & Operations APIs and metadata. The CLI supports all major operations including entity management, metadata discovery, and system administration.

Usage

# Use the installed CLI command
d365fo-client [GLOBAL_OPTIONS] COMMAND [SUBCOMMAND] [OPTIONS]

# Alternative: Module execution
python -m d365fo_client.main [OPTIONS] COMMAND [ARGS]

Command Categories

Entity Operations
# List entities with filtering
d365fo-client entities list --pattern "customer" --limit 10

# Get entity details and schema
d365fo-client entities get CustomersV3 --properties --keys --labels

# CRUD operations
d365fo-client entities create Customers --data '{"CustomerAccount":"US-999","Name":"Test"}'
d365fo-client entities update Customers US-999 --data '{"Name":"Updated Name"}'
d365fo-client entities delete Customers US-999
Metadata Operations
# Search and discover entities
d365fo-client metadata entities --search "sales" --output json

# Get available actions
d365fo-client metadata actions --pattern "calculate" --limit 5

# Enumerate system enumerations
d365fo-client metadata enums --search "status" --output table

# Synchronize metadata cache
d365fo-client metadata sync --force-refresh
Version Information
# Get application versions
d365fo-client version app
d365fo-client version platform  
d365fo-client version build
Label Operations
# Resolve single label
d365fo-client labels resolve "@SYS13342"

# Search labels by pattern
d365fo-client labels search "customer" --language "en-US"

Global Options

  • --base-url URL โ€” Specify D365 F&O environment URL
  • --profile NAME โ€” Use named configuration profile
  • --output FORMAT โ€” Output format: json, table, csv, yaml (default: table)
  • --verbose โ€” Enable verbose output for debugging
  • --timeout SECONDS โ€” Request timeout (default: 30)

Configuration Profiles

Create reusable configurations in ~/.d365fo-client/config.yaml:

profiles:
  production:
    base_url: "https://prod.dynamics.com"
    use_default_credentials: true
    timeout: 60
    
  development:
    base_url: "https://dev.dynamics.com" 
    client_id: "${D365FO_CLIENT_ID}"
    client_secret: "${D365FO_CLIENT_SECRET}"
    tenant_id: "${D365FO_TENANT_ID}"
    use_cache_first: true

default_profile: "development"

Examples

# Quick entity discovery
d365fo-client entities list --pattern "cust.*" --output json

# Get comprehensive entity information
d365fo-client entities get CustomersV3 --properties --keys --labels --output yaml

# Search for calculation actions
d365fo-client metadata actions --pattern "calculate|compute" --output table

# Test environment connectivity
d365fo-client version app --verbose

For a complete command reference:

d365fo-client --help
d365fo-client entities --help
d365fo-client metadata --help

Basic Usage

import asyncio
from d365fo_client import D365FOClient, FOClientConfig

async def main():
    # Simple configuration with default credentials
    config = FOClientConfig(
        base_url="https://your-fo-environment.dynamics.com",
        use_default_credentials=True  # Uses Azure Default Credential
    )
    
    async with D365FOClient(config) as client:
        # Test connection
        if await client.test_connection():
            print("โœ… Connected successfully!")
        
        # Get environment information
        env_info = await client.get_environment_info()
        print(f"Environment: {env_info.application_version}")
        
        # Search for entities (uses metadata cache v2)
        customer_entities = await client.search_entities("customer")
        print(f"Found {len(customer_entities)} customer entities")
        
        # Get customers with query options
        from d365fo_client import QueryOptions
        options = QueryOptions(
            select=["CustomerAccount", "Name", "SalesCurrencyCode"],
            top=10,
            orderby=["Name"]
        )
        
        customers = await client.get_data("/data/CustomersV3", options)
        print(f"Retrieved {len(customers['value'])} customers")

if __name__ == "__main__":
    asyncio.run(main())

Using Convenience Function

from d365fo_client import create_client

# Quick client creation with enhanced defaults
async with create_client("https://your-fo-environment.dynamics.com") as client:
    customers = await client.get_data("/data/CustomersV3", top=5)

Configuration

Environment Variable Management (New in v0.3.0)

The d365fo-client now includes a comprehensive Pydantic settings model for type-safe environment variable management:

from d365fo_client import D365FOSettings, get_settings

# Get type-safe settings instance
settings = get_settings()

# Access settings with full IntelliSense support
print(f"Base URL: {settings.base_url}")
print(f"Log Level: {settings.log_level}")
print(f"Cache Directory: {settings.cache_dir}")

# Check configuration state
if settings.has_client_credentials():
    print("Client credentials configured")

startup_mode = settings.get_startup_mode()  # "profile_only", "default_auth", "client_credentials"

# Convert to environment dictionary for external tools
env_vars = settings.to_env_dict()

Key Benefits:

  • Type Safety: Automatic validation and type conversion for all 35+ environment variables
  • IDE Support: Full IntelliSense and autocompletion for configuration options
  • Environment Files: Support for .env files in development
  • Comprehensive Defaults: Sensible defaults for all configuration options
  • Validation: Built-in validation for URLs, ports, timeouts, and other settings

Authentication Options

from d365fo_client import FOClientConfig

# Option 1: Default Azure credentials (recommended)
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com",
    use_default_credentials=True
)

# Option 2: Client credentials
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com",
    client_id="your-client-id",
    client_secret="your-client-secret", 
    tenant_id="your-tenant-id",
    use_default_credentials=False
)

# Option 3: Azure Key Vault integration (New in v0.2.3)
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com",
    credential_source="keyvault",  # Use Azure Key Vault for credentials
    keyvault_url="https://your-keyvault.vault.azure.net/"
)

# Option 4: With custom settings
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com",
    use_default_credentials=True,
    verify_ssl=False,  # For development environments
    timeout=60,  # Request timeout in seconds
    metadata_cache_dir="./my_cache",  # Custom cache directory
    use_label_cache=True,  # Enable label caching
    label_cache_expiry_minutes=120  # Cache for 2 hours
)

Legacy Configuration Migration (New in v0.3.0)

The d365fo-client automatically detects and migrates legacy configuration files:

  • Automatic Detection: Identifies legacy configuration patterns (missing verify_ssl, outdated field names)
  • Field Migration: Updates cache_dir โ†’ metadata_cache_dir, auth_mode โ†’ use_default_credentials
  • Backup Creation: Creates backup of original configuration before migration
  • Seamless Upgrade: Ensures smooth transition from older versions without manual intervention
# Legacy configurations are automatically migrated when FastMCP server starts
# No manual intervention required - migration happens transparently

Core Operations

CRUD Operations

async with D365FOClient(config) as client:
    # CREATE - Create new customer (supports composite keys)
    new_customer = {
        "CustomerAccount": "US-999",
        "Name": "Test Customer",
        "SalesCurrencyCode": "USD"
    }
    created = await client.create_data("/data/CustomersV3", new_customer)
    
    # READ - Get single customer by key
    customer = await client.get_data("/data/CustomersV3('US-001')")
    
    # UPDATE - Update customer with optimistic concurrency
    updates = {"Name": "Updated Customer Name"}
    updated = await client.update_data("/data/CustomersV3('US-001')", updates)
    
    # DELETE - Delete customer
    success = await client.delete_data("/data/CustomersV3('US-999')")
    print(f"Delete successful: {success}")

Advanced Querying

from d365fo_client import QueryOptions

# Complex query with multiple options
options = QueryOptions(
    select=["CustomerAccount", "Name", "SalesCurrencyCode", "CustomerGroupId"],
    filter="SalesCurrencyCode eq 'USD' and contains(Name, 'Corp')",
    expand=["CustomerGroup"],
    orderby=["Name desc", "CustomerAccount"],
    top=50,
    skip=10,
    count=True
)

result = await client.get_data("/data/CustomersV3", options)
print(f"Total count: {result.get('@odata.count')}")

Action Execution

# Unbound action
result = await client.post_data("/data/calculateTax", {
    "amount": 1000.00,
    "taxGroup": "STANDARD"
})

# Bound action on entity set
result = await client.post_data("/data/CustomersV3/calculateBalances", {
    "asOfDate": "2024-12-31"
})

# Bound action on specific entity instance  
result = await client.post_data("/data/CustomersV3('US-001')/calculateBalance", {
    "asOfDate": "2024-12-31"
})

Metadata Operations

# Intelligent metadata synchronization (v2 system)
sync_manager = await client.get_sync_manager()
await sync_manager.smart_sync()

# Search entities with enhanced filtering
sales_entities = await client.search_entities("sales")
print("Sales-related entities:", [e.name for e in sales_entities])

# Get detailed entity information with labels
entity_info = await client.get_public_entity_info("CustomersV3")
if entity_info:
    print(f"Entity: {entity_info.name}")
    print(f"Label: {entity_info.label_text}")
    print(f"Data Service Enabled: {entity_info.data_service_enabled}")

# Search actions with caching
calc_actions = await client.search_actions("calculate")
print("Calculation actions:", [a.name for a in calc_actions])

# Get enumeration information
enum_info = await client.get_public_enumeration_info("NoYes")
if enum_info:
    print(f"Enum: {enum_info.name}")
    for member in enum_info.members:
        print(f"  {member.name} = {member.value}")

Label Operations

# Get specific label (v2 caching system)
label_text = await client.get_label_text("@SYS13342")
print(f"Label text: {label_text}")

# Get multiple labels efficiently
labels = await client.get_labels_batch([
    "@SYS13342", "@SYS9490", "@GLS63332"
])
for label_id, text in labels.items():
    print(f"{label_id}: {text}")

# Enhanced entity info with resolved labels
entity_info = await client.get_public_entity_info_with_labels("CustomersV3")
if entity_info.label_text:
    print(f"Entity display name: {entity_info.label_text}")

# Access enhanced properties with labels
for prop in entity_info.enhanced_properties[:5]:
    if hasattr(prop, 'label_text') and prop.label_text:
        print(f"{prop.name}: {prop.label_text}")

Error Handling

from d365fo_client import D365FOClientError, AuthenticationError, ConnectionError

try:
    async with D365FOClient(config) as client:
        customer = await client.get_data("/data/CustomersV3('NON-EXISTENT')")
except ConnectionError as e:
    print(f"Connection failed: {e}")
except AuthenticationError as e:
    print(f"Authentication failed: {e}")
except D365FOClientError as e:
    print(f"Client operation failed: {e}")
    print(f"Status code: {e.status_code}")
    print(f"Response: {e.response_text}")

Development

Setting up Development Environment

# Clone the repository
git clone https://github.com/mafzaal/d365fo-client.git
cd d365fo-client

# Install with development dependencies using uv
uv sync --dev

# Run tests
uv run pytest

# Run integration tests
.\tests\integration\integration-test-simple.ps1 test-sandbox

# Format code
uv run black .
uv run isort .

# Type checking
uv run mypy src/

# Quality checks
.\make.ps1 quality-check  # Windows PowerShell
# or
make quality-check       # Unix/Linux/macOS

Project Structure

d365fo-client/
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ d365fo_client/
โ”‚       โ”œโ”€โ”€ __init__.py          # Public API exports
โ”‚       โ”œโ”€โ”€ main.py              # CLI entry point  
โ”‚       โ”œโ”€โ”€ cli.py               # CLI command handlers
โ”‚       โ”œโ”€โ”€ client.py            # Enhanced D365FOClient class
โ”‚       โ”œโ”€โ”€ config.py            # Configuration management
โ”‚       โ”œโ”€โ”€ auth.py              # Authentication management
โ”‚       โ”œโ”€โ”€ session.py           # HTTP session management
โ”‚       โ”œโ”€โ”€ crud.py              # CRUD operations
โ”‚       โ”œโ”€โ”€ query.py             # OData query utilities
โ”‚       โ”œโ”€โ”€ metadata.py          # Legacy metadata operations
โ”‚       โ”œโ”€โ”€ metadata_api.py      # Metadata API client
โ”‚       โ”œโ”€โ”€ metadata_cache.py    # Metadata caching layer V2
โ”‚       โ”œโ”€โ”€ metadata_sync.py     # Metadata synchronization V2 with session management
โ”‚       โ”œโ”€โ”€ sync_session.py      # Enhanced sync session management (New in v0.2.3)
โ”‚       โ”œโ”€โ”€ credential_manager.py # Credential source management (New in v0.2.3)
โ”‚       โ”œโ”€โ”€ labels.py            # Label operations V2
โ”‚       โ”œโ”€โ”€ profiles.py          # Profile data models
โ”‚       โ”œโ”€โ”€ profile_manager.py   # Profile management
โ”‚       โ”œโ”€โ”€ models.py            # Data models and configurations
โ”‚       โ”œโ”€โ”€ output.py            # Output formatting
โ”‚       โ”œโ”€โ”€ utils.py             # Utility functions
โ”‚       โ”œโ”€โ”€ exceptions.py        # Custom exceptions
โ”‚       โ””โ”€โ”€ mcp/                 # Model Context Protocol server
โ”‚           โ”œโ”€โ”€ __init__.py      # MCP server exports
โ”‚           โ”œโ”€โ”€ main.py          # MCP server entry point
โ”‚           โ”œโ”€โ”€ server.py        # Core MCP server implementation
โ”‚           โ”œโ”€โ”€ client_manager.py# D365FO client connection pooling
โ”‚           โ”œโ”€โ”€ models.py        # MCP-specific data models
โ”‚           โ”œโ”€โ”€ tools/           # MCP tool implementations (12 tools)
โ”‚           โ”‚   โ”œโ”€โ”€ connection_tools.py
โ”‚           โ”‚   โ”œโ”€โ”€ crud_tools.py
โ”‚           โ”‚   โ”œโ”€โ”€ metadata_tools.py
โ”‚           โ”‚   โ””โ”€โ”€ label_tools.py
โ”‚           โ”œโ”€โ”€ resources/       # MCP resource handlers (4 types)
โ”‚           โ”‚   โ”œโ”€โ”€ entity_handler.py
โ”‚           โ”‚   โ”œโ”€โ”€ metadata_handler.py
โ”‚           โ”‚   โ”œโ”€โ”€ environment_handler.py
โ”‚           โ”‚   โ””โ”€โ”€ query_handler.py
โ”‚           โ””โ”€โ”€ prompts/         # MCP prompt templates
โ”œโ”€โ”€ tests/                       # Comprehensive test suite
โ”‚   โ”œโ”€โ”€ unit/                    # Unit tests (pytest-based)
โ”‚   โ”œโ”€โ”€ integration/             # Multi-tier integration testing
โ”‚   โ”‚   โ”œโ”€โ”€ mock_server/         # Mock D365 F&O API server
โ”‚   โ”‚   โ”œโ”€โ”€ test_mock_server.py  # Mock server tests
โ”‚   โ”‚   โ”œโ”€โ”€ test_sandbox.py      # Sandbox environment tests โœ…
โ”‚   โ”‚   โ”œโ”€โ”€ test_live.py         # Live environment tests
โ”‚   โ”‚   โ”œโ”€โ”€ conftest.py          # Shared pytest fixtures
โ”‚   โ”‚   โ”œโ”€โ”€ test_runner.py       # Python test execution engine
โ”‚   โ”‚   โ””โ”€โ”€ integration-test-simple.ps1 # PowerShell automation
โ”‚   โ””โ”€โ”€ test_mcp_server.py       # MCP server unit tests โœ…
โ”œโ”€โ”€ scripts/                     # Metadata discovery scripts
โ”‚   โ”œโ”€โ”€ search_data_entities.ps1 # PowerShell entity search
โ”‚   โ”œโ”€โ”€ get_data_entity_schema.ps1 # PowerShell schema retrieval
โ”‚   โ”œโ”€โ”€ search_enums.py          # Python enumeration search
โ”‚   โ”œโ”€โ”€ get_enumeration_info.py  # Python enumeration info
โ”‚   โ”œโ”€โ”€ search_actions.ps1       # PowerShell action search
โ”‚   โ””โ”€โ”€ get_action_info.py       # Python action information
โ”œโ”€โ”€ docs/                        # Comprehensive documentation
โ”œโ”€โ”€ pyproject.toml               # Project configuration
โ””โ”€โ”€ README.md                    # This file

Configuration Options

OptionTypeDefaultDescription
base_urlstrRequiredD365 F&O base URL
client_idstrNoneAzure AD client ID
client_secretstrNoneAzure AD client secret
tenant_idstrNoneAzure AD tenant ID
use_default_credentialsboolTrueUse Azure Default Credential
credential_sourcestr"environment"Credential source: "environment", "keyvault"
keyvault_urlstrNoneAzure Key Vault URL for credential storage
verify_sslboolFalseVerify SSL certificates
timeoutint30Request timeout in seconds
metadata_cache_dirstrPlatform-specific user cacheMetadata cache directory
use_label_cacheboolTrueEnable label caching V2
label_cache_expiry_minutesint60Label cache expiry time
use_cache_firstboolFalseEnable cache-first mode with background sync

Cache Directory Behavior

By default, the client uses platform-appropriate user cache directories:

  • Windows: %LOCALAPPDATA%\d365fo-client (e.g., C:\Users\username\AppData\Local\d365fo-client)
  • macOS: ~/Library/Caches/d365fo-client (e.g., /Users/username/Library/Caches/d365fo-client)
  • Linux: ~/.cache/d365fo-client (e.g., /home/username/.cache/d365fo-client)

You can override this by explicitly setting metadata_cache_dir:

from d365fo_client import FOClientConfig

# Use custom cache directory
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com",
    metadata_cache_dir="/custom/cache/path"
)

# Or get the default cache directory programmatically
from d365fo_client import get_user_cache_dir

cache_dir = get_user_cache_dir("my-app")  # Platform-appropriate cache dir
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com", 
    metadata_cache_dir=str(cache_dir)
)

Testing

This project includes comprehensive testing at multiple levels to ensure reliability and quality.

Unit Tests

Run standard unit tests for core functionality:

# Run all unit tests
uv run pytest

# Run with coverage
uv run pytest --cov=d365fo_client --cov-report=html

# Run specific test file
uv run pytest tests/test_client.py -v

Integration Tests

The project includes a sophisticated multi-tier integration testing framework:

Quick Start
# Run sandbox integration tests (recommended)
.\tests\integration\integration-test-simple.ps1 test-sandbox

# Run mock server tests (no external dependencies)
.\tests\integration\integration-test-simple.ps1 test-mock

# Run with verbose output
.\tests\integration\integration-test-simple.ps1 test-sandbox -VerboseOutput
Test Levels
  1. Mock Server Tests - Fast, isolated tests against a simulated D365 F&O API

    • No external dependencies
    • Complete API simulation
    • Ideal for CI/CD pipelines
  2. Sandbox Tests โญ (Default) - Tests against real D365 F&O test environments

    • Validates authentication
    • Tests real API behavior
    • Requires test environment access
  3. Live Tests - Optional tests against production environments

    • Final validation
    • Performance benchmarking
    • Use with caution
Configuration

Set up integration testing with environment variables:

# Copy the template and configure
cp tests/integration/.env.template tests/integration/.env

# Edit .env file with your settings:
INTEGRATION_TEST_LEVEL=sandbox
D365FO_SANDBOX_BASE_URL=https://your-test.dynamics.com
D365FO_CLIENT_ID=your-client-id
D365FO_CLIENT_SECRET=your-client-secret
D365FO_TENANT_ID=your-tenant-id
Available Commands
# Test environment setup
.\tests\integration\integration-test-simple.ps1 setup

# Dependency checking
.\tests\integration\integration-test-simple.ps1 deps-check

# Run specific test levels
.\tests\integration\integration-test-simple.ps1 test-mock
.\tests\integration\integration-test-simple.ps1 test-sandbox
.\tests\integration\integration-test-simple.ps1 test-live

# Coverage and reporting
.\tests\integration\integration-test-simple.ps1 coverage

# Clean up test artifacts
.\tests\integration\integration-test-simple.ps1 clean
Test Coverage

Integration tests cover:

  • โœ… Connection & Authentication - Azure AD integration, SSL/TLS validation
  • โœ… Version Methods - Application, platform, and build version retrieval
  • โœ… Metadata Operations - Entity discovery, metadata API validation
  • โœ… Data Operations - CRUD operations, OData query validation
  • โœ… Error Handling - Network failures, authentication errors, invalid requests
  • โœ… Performance - Response time validation, concurrent operations

For detailed information, see .

Test Results

Recent sandbox integration test results:

โœ… 17 passed, 0 failed, 2 warnings in 37.67s
====================================================== 
โœ… TestSandboxConnection::test_connection_success
โœ… TestSandboxConnection::test_metadata_connection_success  
โœ… TestSandboxVersionMethods::test_get_application_version
โœ… TestSandboxVersionMethods::test_get_platform_build_version
โœ… TestSandboxVersionMethods::test_get_application_build_version
โœ… TestSandboxVersionMethods::test_version_consistency
โœ… TestSandboxMetadataOperations::test_download_metadata
โœ… TestSandboxMetadataOperations::test_search_entities
โœ… TestSandboxMetadataOperations::test_get_data_entities
โœ… TestSandboxMetadataOperations::test_get_public_entities
โœ… TestSandboxDataOperations::test_get_available_entities
โœ… TestSandboxDataOperations::test_odata_query_options
โœ… TestSandboxAuthentication::test_authenticated_requests
โœ… TestSandboxErrorHandling::test_invalid_entity_error
โœ… TestSandboxErrorHandling::test_invalid_action_error
โœ… TestSandboxPerformance::test_response_times
โœ… TestSandboxPerformance::test_concurrent_operations

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests (uv run pytest)
  5. Run integration tests (.\tests\integration\integration-test-simple.ps1 test-sandbox)
  6. Format code (uv run black . && uv run isort .)
  7. Commit changes (git commit -m 'Add amazing feature')
  8. Push to branch (git push origin feature/amazing-feature)
  9. Open a Pull Request

License

This project is licensed under the MIT License - see the file for details.

Changelog

See for a list of changes and version history.

Support

Related Projects