A community-driven Microsoft Dynamics 365 Finance & Operations MCP server
io.github.mafzaal/d365fo-client โ D365FO MCP Server
A community-driven Model Context Protocol (MCP) server for Microsoft Dynamics 365 Finance & Operations (D365 F&O). It exposes D365 F&O capabilities to AI assistants and other MCP-compatible tools, enabling Dynamics 365 integration workflows through standardized protocol interactions.
๐ ๏ธ Key Features
Production-ready MCP server
Exposes the full capabilities of Microsoft Dynamics 365 Finance & Operations (D365 F&O)
Integration workflows via MCP-compatible interactions
๐ Use Cases
Standardized AI-assisted integration with D365 F&O
Building Dynamics 365 integration workflows for MCP-compatible tools
โก Developer Benefits
Communicates with AI assistants and other MCP-compatible tools using a standardized protocol
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.
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)
bash
# 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"# ORexport D365FO_MCP_API_KEY_VALUE="your-secret-key"# Deploy
./deploy-aca.sh
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 a production-ready Model Context Protocol (MCP) server (d365fo-fastmcp-server) built on the FastMCP framework that exposes the full capabilities of D365 Finance & Operations to AI assistants and other MCP-compatible tools.
The server provides multi-transport support (stdio, HTTP, SSE) with enhanced performance and deployment flexibility.
Key Features
49 comprehensive tools covering all major D365 F&O operations across 9 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
Option 2: Explicit Credentials
For environments requiring service principal authentication:
json
{"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:
json
{"servers":{"d365fo-fastmcp-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:
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:
python
from mcp import Client
asyncwith Client("d365fo-fastmcp-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:
bash
# 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:
bash
# 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
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
bash
# Test connectivity
d365fo-client version app --base-url https://your-environment.dynamics.com
# Check logstail -f ~/.d365fo-mcp/logs/mcp-server.log
Authentication Issues
bash
# Verify Azure CLI authentication
az account show
# Test with explicit credentialsexport D365FO_CLIENT_ID="your-client-id"# ... set other variables
d365fo-fastmcp-server
๐ค For AI agents and assistants, see the AI Agent Guide for structured workflows, best practices, and automation patterns.
MCP Resources
The server exposes four types of resources for discovery and access:
Entity Resources
Access entity metadata and sample data:
code
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:
code
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:
code
d365fo://environment/status # Environment health and connectivity
d365fo://environment/version # Version information (app, platform, build)
d365fo://environment/cache # Cache status and statistics V2
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:
bash
# === 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, CRITICALexport 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-httpexport 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 modeexport D365FO_MCP_HTTP_JSON="true"# Enable JSON response mode# === Cache and Performance Settings ===export D365FO_CACHE_DIR="/custom/cache/path"# General cache directoryexport D365FO_META_CACHE_DIR="/custom/metadata/cache"# Metadata cache directoryexport 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 secondsexport D365FO_MCP_MAX_CONCURRENT_REQUESTS="10"# Max concurrent requestsexport D365FO_MCP_REQUEST_TIMEOUT="30"# Request timeout in secondsexport 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
๏ฟฝ๏ธ JSON Services: Generic access to D365 F&O JSON service endpoints (/api/services pattern)
๏ฟฝ๐ 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 49 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
bash
# 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-fastmcp-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.
# 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
python
# 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 labelsfor prop in entity_info.enhanced_properties[:5]:
ifhasattr(prop, 'label_text') and prop.label_text:
print(f"{prop.name}: {prop.label_text}")
Error Handling
python
from d365fo_client import D365FOClientError, AuthenticationError, ConnectionError
try:
asyncwith 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
bash
# 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
You can override this by explicitly setting metadata_cache_dir:
python
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 programmaticallyfrom 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:
bash
# 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
bash
# 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
Mock Server Tests - Fast, isolated tests against a simulated D365 F&O API
No external dependencies
Complete API simulation
Ideal for CI/CD pipelines
Sandbox Tests โญ (Default) - Tests against real D365 F&O test environments
Validates authentication
Tests real API behavior
Requires test environment access
Live Tests - Optional tests against production environments
Final validation
Performance benchmarking
Use with caution
Configuration
Set up integration testing with environment variables:
bash
# Copy the template and configurecp 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
bash
# 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