mcpField
D
D365FO MCP Server

D365FO MCP Server

本地服务
github.com/mafzaal商业与营销403 天前更新

关于 D365FO MCP Server

D365FO MCP Server 是 Microsoft Dynamics 365 Finance & Operations 的社区 MCP 服务,基于 FastMCP 框架构建,并附带 Python 客户端库。它面向需要让 AI 助手访问 D365 F&O 环境的开发者与企业用户。项目支持 stdio、HTTP 和 SSE 传输方式,并提供 Azure AD 认证选项。

主要功能

  1. 0149 个覆盖 D365 F&O 操作的工具
  2. 0212 类资源及元数据发现
  3. 03支持 stdio、HTTP 与 SSE 传输
  4. 04多环境配置与凭据管理
  5. 05基于 Azure AD 的认证

适用场景

  1. 01让 AI 助手查询 D365 F&O 环境信息
  2. 02通过 HTTP 端点为 Web 应用提供远程访问
  3. 03在 VS Code 中通过 Copilot 连接 D365 F&O
  4. 04以 Docker 容器方式部署 MCP 服务

MCP 相关

该项目是一个 MCP 服务,向 MCP 客户端暴露 49 个工具、12 类资源以及 2 个提示词模板。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"mafzaal-d365fo-client": {
"command": "uvx",
"args": [
"d365fo-client"
],
"env": {
"D365FO_CLIENT_ID": "<D365FO_CLIENT_ID>",
"D365FO_CLIENT_SECRET": "<D365FO_CLIENT_SECRET>",
"D365FO_TENANT_ID": "<D365FO_TENANT_ID>",
"D365FO_BASE_URL": "<D365FO_BASE_URL>"
}
}
}
}
启动命令uvx d365fo-client
需要配置的环境变量
D365FO_CLIENT_IDYour D365FO Client ID
D365FO_CLIENT_SECRET密钥Your D365FO Client Secret
D365FO_TENANT_IDYour D365FO Tenant ID
D365FO_BASE_URLYour D365FO Base URL

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypid365fo-client0.3.6
ocighcr.io/mafzaal/d365fo-client:0.3.6

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Dynamics 365 Finance & Operations MCP 服务

D365FO MCP 服务 Logo

可用于生产环境的 Model Context Protocol(MCP)服务,可向 AI 助手和其他兼容 MCP 的工具开放 Microsoft Dynamics 365 Finance & Operations(D365 F&O)的全部功能。通过标准化的协议交互,可实现复杂的 Dynamics 365 集成工作流。

GitHub 关注者 GitHub 分支 GitHub 星标

🚀 一键安装到 VS Code:

在 VS Code 中使用 UVX 安装 在 VS Code Insiders 中使用 UVX 安装

🐳 在 VS Code 中使用 Docker 安装: 在 VS Code 中使用 Docker 安装 在 VS Code Insiders 中使用 Docker 安装

☁️ 部署到 Azure Container Apps:

将 MCP 服务部署为安全、可通过互联网访问的 HTTP 端点,并使用 OAuth 或 API Key 进行身份验证。非常适合 Web 集成和远程 AI 助手访问。

选项 1:使用 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"
# OR
export D365FO_MCP_API_KEY_VALUE="your-secret-key"

# Deploy
./deploy-aca.sh

选项 2:使用 ARM 模板

  1. 下载 azure-deploy.json
  2. 前往 Azure 门户 → 部署自定义模板
  3. 点击“在编辑器中生成自己的模板”
  4. 粘贴 azure-deploy.json 的内容
  5. 填写参数并部署

PyPI - 下载量

还包含一个功能全面的 Python 客户端库,用于 Microsoft Dynamics 365 Finance & Operations,支持 OData 端点、元数据操作、标签管理和 CLI 工具。

MCP 服务概述

d365fo-client 包含一个基于 FastMCP 框架构建的可用于生产环境的 Model Context Protocol (MCP) 服务(d365fo-fastmcp-server),可向 AI 助手和其他兼容 MCP 的工具开放 D365 Finance & Operations 的全部功能。

该服务支持多种传输方式(stdio、HTTP、SSE),性能更出色,部署也更灵活。

主要功能
  • 49 个全面的工具,涵盖 9 个功能类别中的所有主要 D365 F&O 操作
  • 12 种资源类型,具备全面的元数据开放与发现能力
  • 2 个提示词模板,用于提供高级工作流辅助
  • 多种传输方式(FastMCP):stdio、HTTP、Server-Sent Events (SSE)
  • 可用于生产环境,具备完善的错误处理、身份验证和安全验证
  • 性能增强(FastMCP):启动速度提升 40%,内存使用量降低 15%
  • 高级配置文件管理,支持多个环境和安全的凭据存储
  • 数据库分析功能,支持安全的 SQL 查询和元数据洞察
  • 基于会话的同步,提供详细的进度跟踪和多种同步策略
  • 多语言支持,具备标签解析和本地化能力
  • 企业级安全性,集成 Azure AD、支持 Key Vault 并提供审计日志
v0.3.0 中的新功能
  • 🔧 Pydantic 设置模型:类型安全的环境变量管理,并为 35 多个配置选项提供验证
  • 📂 自定义日志文件支持:通过 D365FO_LOG_FILE 环境变量灵活设置日志文件路径
  • 🔄 旧版配置迁移:自动检测并迁移旧版配置文件
  • 🌐 环境变量标准化:所有 MCP HTTP 变量现在统一使用 D365FO_ 前缀
  • ⚡ 增强的 FastMCP 服务:改进启动配置、错误处理和优雅关闭
  • 🔀 MCP 返回类型标准化:所有 MCP 工具现在都返回字典,而非 JSON 字符串,以提升类型安全性
  • 🛠️ 增强的配置:支持 .env 文件,并提供全面的环境变量文档
快速开始
安装与设置
# 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 服务(推荐)

现代化的 FastMCP 实现性能更出色,并提供多种传输方式:

# 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

主要优势:

  • 优化的性能,基于 FastMCP 框架
  • 高效的资源使用,得益于优化的架构
  • 支持多种传输方式:stdio、HTTP、Server-Sent Events (SSE)
  • 增强的错误处理,提供更完善的 async/await 支持
  • 可用于生产环境,提供用于 API 集成的 Web 传输方式
与 AI 助手集成
VS Code 集成(推荐)

使用默认凭据的 FastMCP 服务: 将以下内容添加到 VS Code mcp.json,以便通过 MCP 使用 GitHub Copilot:

{
  "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"
      }
    }
  }
}

选项 2:显式指定凭据 适用于需要使用服务主体进行身份验证的环境:

{
  "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
    }
  ]
}

选项 3:Docker 集成 适用于容器化环境并提供更强的隔离性:

{
  "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
    }
  ]
}

使用 Docker 方案的优势:

  • 完全隔离环境并确保可复现性
  • 无需在本地安装 Python
  • 在不同系统间提供一致的运行环境
  • 通过预构建镜像自动管理依赖项
  • 通过容器化增强安全性
  • 通过 Docker 卷(d365fo-mcp)持久化存储数据

先决条件:

  • 已安装并运行 Docker
  • 可访问 Docker Hub 或 GitHub Container Registry
  • 具备拉取容器镜像所需的网络访问权限
Claude Desktop 集成

FastMCP 服务: 将以下内容添加到 Claude Desktop 配置中:

{
  "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"
      }
    }
  }
}

传统 MCP 服务(替代方案):

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

使用 uvx 方案的优势:

  • 始终使用仓库中的最新版本
  • 无需本地安装
  • 自动管理依赖项
  • 可在不同环境中运行
使用 FastMCP 进行 Web 集成

FastMCP 服务提供 HTTP 和 SSE 传输方式,用于集成 Web 应用程序:

用于 Web API 的 HTTP 传输
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 传输
// 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)
    });
}
替代方案:以编程方式使用
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()
自定义 MCP 客户端

使用任意兼容 MCP 的客户端库进行连接:

from mcp import Client

async with 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 部署

适用于容器化环境和生产部署:

拉取 Docker 镜像:

# 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

独立 Docker 用法:

# 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 示例:

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 优势:

  • 完整的环境隔离和可复现性
  • 无需在本地安装 Python
  • 不同系统之间拥有一致的运行时环境
  • 内置依赖管理
  • 通过容器化增强安全性
  • 通过 Docker 卷实现持久化数据存储
  • 轻松集成到编排平台(Kubernetes、Docker Swarm)
架构优势
对 AI 助手而言
  • 标准化接口:通过一致的 MCP 协议访问 D365 F&O
  • 丰富的元数据:具有自我描述能力的实体和操作
  • 类型安全:对所有操作进行架构验证
  • 错误上下文:提供详细的错误信息以便排查问题
对开发者而言
  • 最简集成:使用标准 MCP 客户端库
  • 全面覆盖:提供完整的 D365 F&O 功能
  • 性能优化:采用高效的连接和缓存策略
  • 文档完善:提供完整的 API 文档和示例
对组织而言
  • 安全访问:企业级身份验证(Azure AD、Managed Identity)
  • 审计日志:完整的操作跟踪和监控
  • 可扩展设计:连接池和会话管理
  • 便于维护:架构清晰,测试覆盖全面
故障排除
常见问题

连接失败

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

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

身份验证问题

# Verify Azure CLI authentication
az account show

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

性能问题

# Enable debug logging
export D365FO_LOG_LEVEL="DEBUG"

# Adjust connection settings
export D365FO_CONNECTION_TIMEOUT="120"
export D365FO_MAX_CONCURRENT_REQUESTS="5"
获取帮助
  • 日志:查看 ~/.d365fo-mcp/logs/mcp-server.log 获取详细的错误信息
  • 环境:使用 d365fo_get_environment_info 工具检查系统状态
  • 文档:查看 MCP 实现摘要 了解技术详情
  • 问题反馈:在 GitHub Issues 报告问题
MCP 工具

此服务提供 49 个全面的工具,按功能类别组织:

连接和环境工具(2 个工具)
  • d365fo_test_connection - 测试连接和身份验证,并提供性能指标和错误诊断信息
  • d365fo_get_environment_info - 获取全面的环境详情,包括版本、配置和功能
CRUD 操作工具(7 个工具)
  • d365fo_query_entities - 简化的 OData 查询,支持“eq”筛选、通配符模式、字段选择和分页
  • d365fo_get_entity_record - 按键检索特定记录,支持展开选项和 ETag
  • d365fo_create_entity_record - 创建新的实体记录,并执行验证和业务逻辑
  • d365fo_update_entity_record - 更新现有记录,支持部分更新和乐观并发控制
  • d365fo_delete_entity_record - 删除实体记录,并检查引用完整性和级联规则
  • d365fo_call_action - 执行 OData 操作和函数,以完成复杂的业务操作
  • d365fo_call_json_service - 调用通用 JSON 服务端点,支持参数和响应处理
元数据发现工具(6 个)
  • d365fo_search_entities - 按模式搜索实体,支持类别筛选和全文搜索
  • d365fo_get_entity_schema - 获取详细的实体架构,包括属性、关系和标签解析
  • d365fo_search_actions - 搜索可用的 OData 操作,并获取绑定类型和参数信息
  • d365fo_search_enumerations - 按关键词筛选并搜索系统枚举
  • d365fo_get_enumeration_fields - 获取详细的枚举成员信息,支持多语言
  • d365fo_get_installed_modules - 获取已安装模块及其配置的信息
标签管理工具(2 个)
  • d365fo_get_label - 按 ID 获取单个标签文本,支持多语言和回退选项
  • d365fo_get_labels_batch - 通过批处理和性能优化高效获取多个标签
配置文件管理工具(14 个)
  • d365fo_list_profiles - 列出所有已配置的 D365FO 环境配置文件及其状态信息
  • d365fo_get_profile - 获取特定配置文件的详细配置信息
  • d365fo_create_profile - 创建新的环境配置文件,支持全面的身份验证选项
  • d365fo_update_profile - 修改现有配置文件,支持部分更新
  • d365fo_delete_profile - 删除环境配置文件,并执行适当的清理和验证
  • d365fo_set_default_profile - 指定一个配置文件作为操作的默认配置文件
  • d365fo_get_default_profile - 获取当前已配置的默认配置文件信息
  • d365fo_validate_profile - 验证配置文件是否完整并符合安全要求
  • d365fo_test_profile_connection - 测试特定配置文件的连接和身份验证
  • d365fo_clone_profile - 克隆现有配置文件,并提供用于新环境的自定义选项
  • d365fo_search_profiles - 按模式搜索配置文件,支持筛选和排序
  • d365fo_get_profile_names - 获取可用配置文件名称的简化列表,以便快速查阅
  • d365fo_import_profiles - 从外部来源或备份导入配置文件
  • d365fo_export_profiles - 导出配置文件,以用于备份或部署
数据库分析工具(4 个)
  • d365fo_execute_sql_query - 在元数据库上执行 SELECT 查询,并进行安全验证
  • d365fo_get_database_schema - 获取全面的数据库架构信息,包括关系
  • d365fo_get_table_info - 获取特定数据库表的详细信息及示例数据
  • d365fo_get_database_statistics - 生成数据库统计信息和分析数据,用于性能监控
同步工具(5 个)
  • d365fo_start_sync - 使用多种策略启动元数据同步,并跟踪会话
  • d365fo_get_sync_progress - 监控同步会话的详细进度和时间预估
  • d365fo_cancel_sync - 取消正在运行的同步会话,并执行平稳清理
  • d365fo_list_sync_sessions - 列出所有活动同步会话及其状态和进度信息
  • d365fo_get_sync_history - 获取已完成同步会话的历史记录,包括成功或失败状态及统计信息
SRS 报表工具(6 个工具)
  • d365fo_download_srs_report - 下载支持参数的 SQL Server Reporting Services(SRS)报表
  • d365fo_download_sales_confirmation - 以多种格式下载销售确认报表
  • d365fo_download_purchase_order - 下载支持格式选项的采购订单文档
  • d365fo_download_customer_invoice - 下载支持自定义的客户发票报表
  • d365fo_download_free_text_invoice - 下载自由文本发票文档
  • d365fo_download_debit_credit_note - 下载借项通知单和贷项通知单报表
性能监控工具(3 个工具)
  • d365fo_get_server_performance - 获取服务器性能指标和统计信息
  • d365fo_get_server_config - 获取服务器配置信息和系统设置
  • d365fo_reset_performance_stats - 重置性能统计数据和计数器,以便重新开始监控

📖 有关所有 MCP 工具的详细信息,包括用法示例和最佳实践,请参阅《MCP 工具综合介绍》。

🤖 AI Agent 和助手请参阅 AI Agent 指南,了解结构化工作流、最佳实践和自动化模式。

MCP 资源

服务提供四种类型的资源,供发现和访问:

实体资源

访问实体元数据和示例数据:

d365fo://entities/CustomersV3     # Customer entity with metadata and sample data
d365fo://entities/SalesOrders     # Sales order entity information
d365fo://entities/Products        # Product entity details
元数据资源

访问系统范围的元数据:

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
环境资源

访问环境状态和信息:

d365fo://environment/status       # Environment health and connectivity
d365fo://environment/version      # Version information (app, platform, build)
d365fo://environment/cache        # Cache status and statistics V2
查询资源

访问预定义查询和模板化查询:

d365fo://queries/customers_recent # Recent customers query template
d365fo://queries/sales_summary    # Sales summary query with parameters
数据库资源(V2 新增)

访问元数据数据库查询:

d365fo://database/entities        # SQL-based entity searches with FTS5
d365fo://database/actions         # Action discovery with metadata
d365fo://database/statistics      # Cache and performance statistics
用法示例
基本工具执行
{
  "tool": "d365fo_query_entities",
  "arguments": {
    "entityName": "CustomersV3",
    "select": ["CustomerAccount", "Name", "Email"],
    "filter": "CustomerGroup eq 'VIP'",
    "top": 10
  }
}
实体架构发现
{
  "tool": "d365fo_get_entity_schema", 
  "arguments": {
    "entityName": "CustomersV3",
    "includeProperties": true,
    "resolveLabels": true,
    "language": "en-US"
  }
}
环境信息
{
  "tool": "d365fo_get_environment_info",
  "arguments": {}
}
身份验证与配置
默认凭据(推荐)

使用 Azure 默认凭据链(托管标识、Azure CLI 等):

export D365FO_BASE_URL="https://your-environment.dynamics.com"
# No additional auth environment variables needed
d365fo-fastmcp-server
显式凭据

用于服务主体身份验证:

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-fastmcp-server
Azure Key Vault 集成(v0.2.3 新增)

使用 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-fastmcp-server
高级配置

v0.3.0 新增:使用 Pydantic 设置进行全面的环境变量管理,并提供类型安全和验证功能。

创建配置文件或设置其他环境变量:

# === 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

环境文件支持:也可以在项目目录中创建 .env 文件并添加这些变量,以方便开发。

Python 客户端库

功能
  • 🔗 OData 客户端:对 D365 F&O 数据实体执行完整的 CRUD 操作,支持复合键
  • 📊 元数据管理 V2:增强型缓存系统,支持智能同步和 FTS5 搜索
  • 🏷️ 标签操作 V2:多语言标签缓存,性能有所提升,并支持异步操作
  • 🔍 高级查询:支持所有 OData 查询参数($select、$filter、$expand 等)
  • ⚡ 操作执行:执行绑定和非绑定 OData 操作,并全面处理参数
  • 🗂️ JSON 服务:通用访问 D365 F&O JSON 服务端点(/api/services 模式)
  • 🔒 身份验证:集成 Azure AD,支持默认凭据、服务主体和 Azure Key Vault
  • 💾 智能缓存:跨环境共享缓存,并基于模块检测版本
  • 🌐 Async/Await:采用现代 async/await 模式,并优化会话管理
  • 📝 类型提示:全面支持类型注解,并增强数据模型
  • 🤖 MCP 服务:可用于生产环境的 Model Context Protocol 服务,包含 49 个工具和 4 种资源类型
  • 🖥️ 全面的 CLI:适用于所有 D365 F&O 操作的分层命令行界面
  • 🧪 多层测试:模拟、沙盒和实时集成测试框架(17/17 项测试通过)
  • 📋 元数据脚本:用于发现实体、枚举和操作的 PowerShell 和 Python 实用工具
  • 🔐 增强型凭据管理:支持 Azure Key Vault 和多种凭据来源
  • 📊 高级同步管理:基于会话的同步,并详细跟踪进度
  • 🔧 新增 v0.3.0:Pydantic 设置模型,支持类型安全的环境变量验证
  • 📂 新增 v0.3.0:支持自定义日志文件路径和灵活的日志记录配置
  • 🔄 新增 v0.3.0:自动迁移旧版配置,并提供兼容层
安装
# 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

注意:默认情况下,软件包包含 MCP(Model Context Protocol)依赖项,可支持 AI 助手集成。安装后即可使用 d365fo-client CLI 和 d365fo-fastmcp-server 命令。

v0.2.3 中的重大变更:为保持一致性,已更新环境变量名称:

  • AZURE_CLIENT_ID → D365FO_CLIENT_ID
  • AZURE_CLIENT_SECRET → D365FO_CLIENT_SECRET
  • AZURE_TENANT_ID → D365FO_TENANT_ID

升级时请相应地更新环境变量。

Python 客户端快速入门

命令行界面(CLI)

d365fo-client 提供全面的 CLI,包含用于与 Dynamics 365 Finance & Operations API 和元数据交互的分层命令。CLI 支持所有主要操作,包括实体管理、元数据发现和系统管理。

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

# Alternative: Module execution
python -m d365fo_client.main [OPTIONS] COMMAND [ARGS]
命令类别
实体操作
# 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
元数据操作
# 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
版本信息
# Get application versions
d365fo-client version app
d365fo-client version platform  
d365fo-client version build
标签操作
# Resolve single label
d365fo-client labels resolve "@SYS13342"

# Search labels by pattern
d365fo-client labels search "customer" --language "en-US"
JSON 服务操作
# Call SQL diagnostic services  
d365fo-client service sql-diagnostic GetAxSqlExecuting
d365fo-client service sql-diagnostic GetAxSqlResourceStats --since-minutes 5
d365fo-client service sql-diagnostic GetAxSqlBlocking --output json

# Generic JSON service calls
d365fo-client service call SysSqlDiagnosticService SysSqlDiagnosticServiceOperations GetAxSqlExecuting
d365fo-client service call YourServiceGroup YourServiceName YourOperation --parameters '{"param1":"value1"}'
全局选项
  • --base-url URL — 指定 D365 F&O 环境 URL
  • --profile NAME — 使用命名配置文件
  • --output FORMAT — 输出格式:json、table、csv、yaml(默认:table)
  • --verbose — 启用详细输出以进行调试
  • --timeout SECONDS — 请求超时(默认:30)
配置文件

在 ~/.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"
示例
# 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

完整命令参考:

d365fo-client --help
d365fo-client entities --help
d365fo-client metadata --help
基本用法
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())
使用便捷函数
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)

配置

环境变量管理(v0.3.0 新增)

d365fo-client 现已包含完整的 Pydantic 设置模型,可实现类型安全的环境变量管理:

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()

主要优势:

  • 类型安全:自动验证并转换 35 个以上环境变量的类型
  • IDE 支持:为配置选项提供完整的 IntelliSense 和自动补全
  • 环境文件:支持在开发过程中使用 .env 文件
  • 全面的默认值:为所有配置选项提供合理的默认值
  • 验证:内置对 URL、端口、超时和其他设置的验证
身份验证选项
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
)
旧版配置迁移(v0.3.0 新增)

d365fo-client 会自动检测并迁移旧版配置文件:

  • 自动检测:识别旧版配置模式(缺少 verify_ssl、字段名称过时)
  • 字段迁移:将 cache_dir 更新为 metadata_cache_dir,将 auth_mode 更新为 use_default_credentials
  • 创建备份:迁移前备份原始配置
  • 无缝升级:无需手动干预,即可从旧版本平稳过渡
# Legacy configurations are automatically migrated when FastMCP server starts
# No manual intervention required - migration happens transparently

核心操作

CRUD 操作
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}")
高级查询
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')}")
操作执行
# 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"
})
JSON 服务操作
# Basic JSON service call (no parameters)
response = await client.post_json_service(
    service_group="SysSqlDiagnosticService",
    service_name="SysSqlDiagnosticServiceOperations",
    operation_name="GetAxSqlExecuting"
)

if response.success:
    print(f"Found {len(response.data)} executing SQL statements")
    print(f"Status: HTTP {response.status_code}")
else:
    print(f"Error: {response.error_message}")

# JSON service call with parameters
from datetime import datetime, timezone, timedelta

end_time = datetime.now(timezone.utc)
start_time = end_time - timedelta(minutes=10)

response = await client.post_json_service(
    service_group="SysSqlDiagnosticService",
    service_name="SysSqlDiagnosticServiceOperations",
    operation_name="GetAxSqlResourceStats",
    parameters={
        "start": start_time.isoformat(),
        "end": end_time.isoformat()
    }
)

# Using JsonServiceRequest object for better structure
from d365fo_client.models import JsonServiceRequest

request = JsonServiceRequest(
    service_group="SysSqlDiagnosticService",
    service_name="SysSqlDiagnosticServiceOperations",
    operation_name="GetAxSqlBlocking"
)

response = await client.call_json_service(request)
print(f"Service endpoint: {request.get_endpoint_path()}")

# Multiple SQL diagnostic operations
operations = ["GetAxSqlExecuting", "GetAxSqlBlocking", "GetAxSqlLockInfo"]
for operation in operations:
    response = await client.post_json_service(
        service_group="SysSqlDiagnosticService",
        service_name="SysSqlDiagnosticServiceOperations",
        operation_name=operation
    )
    
    if response.success:
        count = len(response.data) if isinstance(response.data, list) else 1
        print(f"{operation}: {count} records")

# Custom service call template
response = await client.post_json_service(
    service_group="YourServiceGroup",
    service_name="YourServiceName",
    operation_name="YourOperation",
    parameters={
        "parameter1": "value1",
        "parameter2": 123,
        "parameter3": True
    }
)
元数据操作
# 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}")
标签操作
# 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}")

错误处理

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}")

开发

设置开发环境
# 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
项目结构
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
│           ├── mixins/          # FastMCP tool mixins (49 tools)
│           ├── tools/           # Legacy MCP tools (deprecated)
│           │   ├── 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

配置选项

选项类型默认值描述
base_urlstr必填D365 F&O 基础 URL
client_idstrNoneAzure AD 客户端 ID
client_secretstrNoneAzure AD 客户端密钥
tenant_idstrNoneAzure AD 租户 ID
use_default_credentialsboolTrue使用 Azure 默认凭据
credential_sourcestr"environment"凭据来源:"environment"、"keyvault"
keyvault_urlstrNone用于存储凭据的 Azure Key Vault URL
verify_sslboolFalse验证 SSL 证书
timeoutint30请求超时时间(秒)
metadata_cache_dirstr平台特定的用户缓存目录元数据缓存目录
use_label_cacheboolTrue启用标签缓存 V2
label_cache_expiry_minutesint60标签缓存过期时间
use_cache_firstboolFalse启用缓存优先模式并在后台同步
缓存目录行为

默认情况下,客户端使用适用于各平台的用户缓存目录:

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

你可以通过显式设置 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)
)

测试

本项目包含多个层级的全面测试,以确保可靠性和质量。

单元测试

运行核心功能的标准单元测试:

# 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
集成测试

本项目包含一个完善的多层级集成测试框架:

快速开始
# 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
测试级别
  1. 模拟服务测试 - 针对模拟 D365 F&O API 进行快速、隔离的测试

    • 无需外部依赖
    • 完整模拟 API
    • 非常适合 CI/CD 管道
  2. 沙盒测试 ⭐ (默认) - 针对真实 D365 F&O 测试环境进行测试

    • 验证身份验证
    • 测试真实 API 行为
    • 需要访问测试环境
  3. 实时测试 - 可选的生产环境测试

    • 最终验证
    • 性能基准测试
    • 请谨慎使用
配置

使用环境变量设置集成测试:

# 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
可用命令
# 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
测试覆盖率

集成测试涵盖:

  • ✅ 连接与身份验证 - Azure AD 集成、SSL/TLS 验证
  • ✅ 版本方法 - 获取应用程序、平台和构建版本
  • ✅ 元数据操作 - 实体发现、元数据 API 验证
  • ✅ 数据操作 - CRUD 操作、OData 查询验证
  • ✅ 错误处理 - 网络故障、身份验证错误、无效请求
  • ✅ 性能 - 响应时间验证、并发操作

详细信息请参阅集成测试文档。

测试结果

近期沙盒集成测试结果:

✅ 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

贡献

  1. Fork 此仓库
  2. 创建功能分支(git checkout -b feature/amazing-feature)
  3. 进行更改
  4. 运行测试(uv run pytest)
  5. 运行集成测试(.\tests\integration\integration-test-simple.ps1 test-sandbox)
  6. 格式化代码(uv run black . && uv run isort .)
  7. 提交更改(git commit -m 'Add amazing feature')
  8. 推送到分支(git push origin feature/amazing-feature)
  9. 发起 Pull Request

许可证

本项目采用 MIT 许可证,详情请参阅 LICENSE 文件。

更新日志

更改和版本历史记录请参阅 CHANGELOG.md。

支持

相关项目

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。