Back to MCP directory
publicPublicdnsLocal runtime

d365fo-client

这是一个用于Microsoft Dynamics 365 Finance & Operations的Python客户端库和MCP服务器,提供完整的OData操作、元数据管理、标签缓存和AI助手集成功能。

article

README

🚀 Dynamics 365 Finance & Operations MCP Server

这是一个生产就绪的模型上下文协议(MCP)服务器,它将 Microsoft Dynamics 365 Finance & Operations(D365 F&O)的全部功能开放给 AI 助手和其他 MCP 兼容工具。通过标准化的协议交互,它能够实现复杂的 Dynamics 365 集成工作流。

GitHub watchers GitHub forks GitHub stars

🚀 快速开始

安装与设置

# 安装带有 MCP 依赖的 d365fo-client
pip install d365fo-client

# 设置环境变量
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"          # 使用默认凭证时可选

FastMCP 服务器(推荐)

现代的 FastMCP 实现提供了增强的性能和多种传输选项:

# 开发环境(stdio 传输 - 默认)
d365fo-fastmcp-server

# 生产环境 HTTP API
d365fo-fastmcp-server --transport http --port 8000 --host 0.0.0.0

# 实时 Web 应用程序(SSE)
d365fo-fastmcp-server --transport sse --port 8001 --host 0.0.0.0

主要优势

  • 使用 FastMCP 框架优化性能。
  • 通过优化架构实现高效的资源利用。
  • 支持多传输方式:stdio、HTTP、服务器发送事件(SSE)。
  • 增强的错误处理,提供更好的异步/等待支持。
  • 具备用于 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": "用于 D365 F&O 认证的 Azure AD 租户 ID",
      "password": true
    },
    {
      "id": "client_id", 
      "type": "promptString",
      "description": "用于 D365 F&O 认证的 Azure AD 客户端 ID",
      "password": true
    },
    {
      "id": "client_secret",
      "type": "promptString", 
      "description": "用于 D365 F&O 认证的 Azure AD 客户端密钥",
      "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": "用于 D365 F&O 认证的 Azure AD 租户 ID",
      "password": true
    },
    {
      "id": "client_id",
      "type": "promptString",
      "description": "用于 D365 F&O 认证的 Azure AD 客户端 ID",
      "password": true
    },
    {
      "id": "client_secret",
      "type": "promptString",
      "description": "用于 D365 F&O 认证的 Azure AD 客户端密钥",
      "password": true
    }
  ]
}

Docker 方式的优势

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

前提条件

  • 已安装并运行 Docker。
  • 可以访问 Docker Hub 或 GitHub 容器注册表。
  • 具备拉取容器镜像的网络访问权限。
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 服务器为 Web 应用程序集成提供了 HTTP 和 SSE 传输方式:

用于 Web API 的 HTTP 传输
import aiohttp
import json

async def call_d365fo_api():
    """示例:使用 HTTP 传输进行 Web API 集成"""
    
    # 启动带有 HTTP 传输的 FastMCP 服务器
    # 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 传输
// 示例:用于实时 D365FO 数据的 JavaScript 客户端
// 启动 FastMCP 服务器: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);
    
    // 处理来自 D365FO 的实时更新
    if (data.method === 'notification') {
        updateDashboard(data.params);
    }
};

// 通过 SSE 发送 MCP 请求
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

# 使用自定义配置创建并运行服务器
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:
    # 发现可用工具
    tools = await client.list_tools()
    
    # 执行操作
    result = await client.call_tool(
        "d365fo_query_entities",
        {"entityName": "Customers", "top": 5}
    )

Docker 部署

对于容器化环境和生产部署: 拉取 Docker 镜像

# 从 GitHub 容器注册表拉取
docker pull ghcr.io/mafzaal/d365fo-client:latest

# 或者拉取特定版本
docker pull ghcr.io/mafzaal/d365fo-client:v0.2.3

独立 Docker 使用

# 使用环境变量运行 MCP 服务器
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

# 使用 Docker 运行 CLI 命令
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)集成。

✨ 主要特性

  • 49 个综合工具:涵盖 9 个功能类别中的所有主要 D365 F&O 操作。
  • 12 种资源类型:具备全面的元数据暴露和发现功能。
  • 2 个提示模板:用于高级工作流辅助。
  • 多传输支持(FastMCP):stdio、HTTP、服务器发送事件(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 文件,并提供全面的环境变量文档。

📦 安装指南

一键安装到 VS Code

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

使用 Docker 安装到 VS Code

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

部署到 Azure 容器应用

将 MCP 服务器部署为一个安全的、可通过互联网访问的 HTTP 端点,并使用 OAuth 或 API 密钥进行身份验证。非常适合 Web 集成和远程 AI 助手访问。 选项 1:使用 Bash 脚本(推荐)

# 下载并运行部署脚本
curl -O https://raw.githubusercontent.com/mafzaal/d365fo-client/main/deploy-aca.sh
chmod +x deploy-aca.sh

# 设置认证(选择 OAuth 或 API 密钥)
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"
# 或者
export D365FO_MCP_API_KEY_VALUE="your-secret-key"

# 部署
./deploy-aca.sh

选项 2:使用 ARM 模板

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

💻 使用示例

基本工具执行

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

📚 详细文档

MCP 服务器概述

d365fo-client 包含一个基于 FastMCP 框架构建的生产就绪的模型上下文协议(MCP)服务器 (d365fo-fastmcp-server),它将 D365 Finance & Operations 的全部功能开放给 AI 助手和其他 MCP 兼容工具。 该服务器提供多传输支持(stdio、HTTP、SSE),具有增强的性能和部署灵活性。

架构优势

对于 AI 助手
  • 标准化接口:通过一致的 MCP 协议访问 D365 F&O。
  • 丰富的元数据:自描述的实体和操作。
  • 类型安全:对所有操作进行模式验证。
  • 错误上下文:提供详细的错误信息,便于故障排除。
对于开发人员
  • 最小化集成:使用标准的 MCP 客户端库。
  • 全面覆盖:暴露 D365 F&O 的全部功能。
  • 性能优化:采用高效的连接和缓存策略。
  • 文档完善:提供完整的 API 文档和示例。
对于组织
  • 安全访问:企业级身份验证(Azure AD、托管标识)。
  • 审计日志:完整的操作跟踪和监控。
  • 可扩展设计:连接池和会话管理。
  • 易于维护:清晰的架构和全面的测试覆盖。

故障排除

常见问题

连接失败

# 测试连接性
d365fo-client version app --base-url https://your-environment.dynamics.com

# 查看日志
tail -f ~/.d365fo-mcp/logs/mcp-server.log

身份验证问题

# 验证 Azure CLI 身份验证
az account show

# 使用显式凭证进行测试
export D365FO_CLIENT_ID="your-client-id"
# ... 设置其他变量
d365fo-fastmcp-server

性能问题

# 启用调试日志
export D365FO_LOG_LEVEL="DEBUG"

# 调整连接设置
export D365FO_CONNECTION_TIMEOUT="120"
export D365FO_MAX_CONCURRENT_REQUESTS="5"
获取帮助
  • 日志:查看 ~/.d365fo-mcp/logs/mcp-server.log 以获取详细的错误信息。
  • 环境:使用 d365fo_get_environment_info 工具检查系统状态。
  • 文档:查看 MCP 实现总结 以获取技术细节。
  • 问题反馈:在 GitHub 问题 中报告问题。

MCP 工具

服务器提供49 个综合工具,按功能类别组织:

连接与环境工具(2 个)
  • d365fo_test_connection:使用性能指标和错误诊断测试连接性和身份验证。
  • d365fo_get_environment_info:获取包括版本、配置和功能在内的全面环境详细信息。
CRUD 操作工具(7 个)
  • d365fo_query_entities:使用 'eq' 过滤、通配符模式、字段选择和分页进行简化的 OData 查询。
  • 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 报告服务(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 代理和助手,请参阅 AI 代理指南,以获取结构化工作流、最佳实践和自动化模式。

MCP 资源

服务器公开了四种类型的资源,用于发现和访问:

实体资源

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

d365fo://entities/CustomersV3     # 带有元数据和示例数据的客户实体
d365fo://entities/SalesOrders     # 销售订单实体信息
d365fo://entities/Products        # 产品实体详细信息
元数据资源

访问系统级元数据:

d365fo://metadata/entities        # 所有数据实体元数据(V2 缓存)
d365fo://metadata/actions         # 可用的 OData 操作
d365fo://metadata/enumerations    # 系统枚举
d365fo://metadata/labels          # 系统标签和翻译
环境资源

访问环境状态和信息:

d365fo://environment/status       # 环境健康和连接性
d365fo://environment/version      # 版本信息(应用程序、平台、构建)
d365fo://environment/cache        # 缓存状态和统计信息 V2
查询资源

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

d365fo://queries/customers_recent # 近期客户查询模板
d365fo://queries/sales_summary    # 带有参数的销售摘要查询
数据库资源(V2 新增)

访问元数据数据库查询:

d365fo://database/entities        # 基于 SQL 的实体搜索,使用 FTS5
d365fo://database/actions         # 带有元数据的操作发现
d365fo://database/statistics      # 缓存和性能统计信息

🔧 技术细节

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。
  • 💾 智能缓存:跨环境缓存共享,支持基于模块的版本检测。
  • 🌐 异步/等待:采用现代的异步/等待模式,优化会话管理。
  • 📝 类型提示:全面支持类型注解,增强数据模型。
  • 🤖 MCP 服务器:生产就绪的模型上下文协议服务器,提供 49 个工具和 4 种资源类型。
  • 🖥️ 综合 CLI:为所有 D365 F&O 操作提供分层命令行界面。
  • 🧪 多层测试:模拟、沙盒和实时集成测试框架(17/17 测试通过)。
  • 📋 元数据脚本:用于实体、枚举和操作发现的 PowerShell 和 Python 实用程序。
  • 🔐 增强的凭证管理:支持 Azure Key Vault 和多个凭证源。
  • 📊 高级同步管理:基于会话的同步,提供详细的进度跟踪。
  • 🔧 NEW v0.3.0:Pydantic 设置模型,对环境变量进行类型安全的验证。
  • 📂 NEW v0.3.0:支持自定义日志文件路径和灵活的日志配置。
  • 🔄 NEW v0.3.0:自动迁移旧配置并提供兼容性层。
安装
# 从 PyPI 安装
pip install d365fo-client

# 或者从源代码安装
git clone https://github.com/mafzaal/d365fo-client.git
cd d365fo-client
uv sync  # 使用 uv.lock 中的精确依赖项进行安装

# 或者使用 Docker(无需本地安装)
docker pull ghcr.io/mafzaal/d365fo-client:latest

# 使用 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(模型上下文协议)依赖项,可实现 AI 助手集成。安装后,d365fo-client CLI 和 d365fo-fastmcp-server 命令将可用。

v0.2.3 版本的重大变更:环境变量名称已更新以保持一致性:

  • AZURE_CLIENT_IDD365FO_CLIENT_ID
  • AZURE_CLIENT_SECRETD365FO_CLIENT_SECRET
  • AZURE_TENANT_IDD365FO_TENANT_ID 升级时请相应更新你的环境变量。

Python 客户端快速入门

命令行界面(CLI)

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

使用方法
# 使用已安装的 CLI 命令
d365fo-client [全局选项] 命令 [子命令] [选项]

# 替代方法:模块执行
python -m d365fo_client.main [选项] 命令 [参数]
命令类别
实体操作
# 列出实体并进行过滤
d365fo-client entities list --pattern "customer" --limit 10

# 获取实体详细信息和架构
d365fo-client entities get CustomersV3 --properties --keys --labels

# CRUD 操作
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
元数据操作
# 搜索和发现实体
d365fo-client metadata entities --search "sales" --output json

# 获取可用操作
d365fo-client metadata actions --pattern "calculate" --limit 5

# 枚举系统枚举
d365fo-client metadata enums --search "status" --output table

# 同步元数据缓存
d365fo-client metadata sync --force-refresh
版本信息
# 获取应用程序版本
d365fo-client version app
d365fo-client version platform
d365fo-client version build
标签操作
# 解析单个标签
d365fo-client labels resolve "@SYS13342"

# 按模式搜索标签
d365fo-client labels search "customer" --language "en-US"
JSON 服务操作
# 调用 SQL 诊断服务
d365fo-client service sql-diagnostic GetAxSqlExecuting
d365fo-client service sql-diagnostic GetAxSqlResourceStats --since-minutes 5
d365fo-client service sql-diagnostic GetAxSqlBlocking --output json

# 通用 JSON 服务调用
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"
示例
# 快速实体发现
d365fo-client entities list --pattern "cust.*" --output json

# 获取全面的实体信息
d365fo-client entities get CustomersV3 --properties --keys --labels --output yaml

# 搜索计算操作
d365fo-client metadata actions --pattern "calculate|compute" --output table

# 测试环境连接性
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():
    # 简单配置,使用默认凭证
    config = FOClientConfig(
        base_url="https://your-fo-environment.dynamics.com",
        use_default_credentials=True  # 使用 Azure 默认凭证
    )

    async with D365FOClient(config) as client:
        # 测试连接
        if await client.test_connection():
            print("✅ 连接成功!")

        # 获取环境信息
        env_info = await client.get_environment_info()
        print(f"环境:{env_info.application_version}")

        # 搜索实体(使用元数据缓存 v2)
        customer_entities = await client.search_entities("customer")
        print(f"找到 {len(customer_entities)} 个客户实体")

        # 使用查询选项获取客户
        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"检索到 {len(customers['value'])} 个客户")

if __name__ == "__main__":
    asyncio.run(main())
使用便捷函数
from d365fo_client import create_client

# 快速创建客户端,使用增强的默认设置
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

# 获取类型安全的设置实例
settings = get_settings()

# 使用完整的智能感知功能访问设置
print(f"基础 URL:{settings.base_url}")
print(f"日志级别:{settings.log_level}")
print(f"缓存目录:{settings.cache_dir}")

# 检查配置状态
if settings.has_client_credentials():
    print("已配置客户端凭证")

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

# 转换为环境字典,供外部工具使用
env_vars = settings.to_env_dict()

主要优势

  • 类型安全:对所有 35 多个环境变量进行自动验证和类型转换。
  • IDE 支持:为配置选项提供完整的智能感知和自动完成功能。
  • 环境文件:在开发环境中支持 .env 文件。
  • 全面的默认值:为所有配置选项提供合理的默认值。
  • 验证:对 URL、端口、超时时间和其他设置进行内置验证。
身份验证选项
from d365fo_client import FOClientConfig

# 选项 1:默认 Azure 凭证(推荐)
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com",
    use_default_credentials=True
)

# 选项 2:客户端凭证
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
)

# 选项 3:Azure Key Vault 集成(v0.2.3 新增)
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com",
    credential_source="keyvault",  # 使用 Azure Key Vault 存储凭证
    keyvault_url="https://your-keyvault.vault.azure.net/"
)

# 选项 4:自定义设置
config = FOClientConfig(
    base_url="https://your-fo-environment.dynamics.com",
    use_default_credentials=True,
    verify_ssl=False,  # 用于开发环境
    timeout=60,  # 请求超时时间(秒)
    metadata_cache_dir="./my_cache",  # 自定义缓存目录
    use_label_cache=True,  # 启用标签缓存
    label_cache_expiry_minutes=120  # 缓存 2 小时
)
旧配置迁移(v0.3.0 新增)

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

  • 自动检测:识别旧的配置模式(缺少 verify_ssl、过时的字段名称)。
  • 字段迁移:将 cache_dir 更新为 metadata_cache_dir,将 auth_mode 更新为 use_default_credentials
  • 备份创建:在迁移前创建原始配置的备份。
  • 无缝升级:确保从旧版本顺利过渡,无需手动干预。
# 启动 FastMCP 服务器时,旧配置会自动迁移
# 无需手动干预 - 迁移过程透明进行

核心操作

CRUD 操作
async with D365FOClient(config) as client:
    # 创建 - 创建新客户(支持复合键)
    new_customer = {
        "CustomerAccount": "US-999",
        "Name": "Test Customer",
        "SalesCurrencyCode": "USD"
    }
    created = await client.create_data("/data/CustomersV3", new_customer)

    # 读取 - 通过键获取单个客户
    customer = await client.get_data("/data/CustomersV3('US-001')")

    # 更新 - 使用乐观并发更新客户
    updates = {"Name": "Updated Customer Name"}
    updated = await client.update_data("/data/CustomersV3('US-001')", updates)

    # 删除 - 删除客户
    success = await client.delete_data("/data/CustomersV3('US-999')")
    print(f"删除成功:{success}")
高级查询
from d365fo_client import QueryOptions

# 具有多个选项的复杂查询
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"总计数:{result.get('@odata.count')}")
操作执行
# 未绑定操作
result = await client.post_data("/data/calculateTax", {
    "amount": 1000.00,
    "taxGroup": "STANDARD"
})

# 实体集上的绑定操作
result = await client.post_data("/data/CustomersV3/calculateBalances", {
    "asOfDate": "2024-12-31"
})

# 特定实体实例上的绑定操作
result = await client.post_data("/data/CustomersV3('US-001')/calculateBalance", {
    "asOfDate": "2024-12-31"
})
JSON 服务操作
# 基本 JSON 服务调用(无参数)
response = await client.post_json_service(
    service_group="SysSqlDiagnosticService",
    service_name="SysSqlDiagnosticServiceOperations",
    operation_name="GetAxSqlExecuting"
)

if response.success:
    print(f"找到 {len(response.data)} 条正在执行的 SQL 语句")
    print(f"状态:HTTP {response.status_code}")
else:
    print(f"错误:{response.error_message}")

# 带有参数的 JSON 服务调用
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()
    }
)

# 使用 JsonServiceRequest 对象以获得更好的结构
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"服务端点:{request.get_endpoint_path()}")

# 多个 SQL 诊断操作
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} 条记录")

# 自定义服务调用模板
response = await client.post_json_service(
    service_group="YourServiceGroup",
    service_name="YourServiceName",
    operation_name="YourOperation",
    parameters={
        "parameter1": "value1",
        "parameter2": 123,
        "parameter3": True
    }
)
元数据操作
# 智能元数据同步(v2 系统)
sync_manager = await client.get_sync_manager()
await sync_manager.smart_sync()

# 带有增强过滤的实体搜索
sales_entities = await client.search_entities("sales")
print("与销售相关的实体:", [e.name for e in sales_entities])

# 获取带有标签的详细实体信息
entity_info = await client.get_public_entity_info("CustomersV3")
if entity_info:
    print(f"实体:{entity_info.name}")
    print(f"标签:{entity_info.label_text}")
    print(f"数据服务启用:{entity_info.data_service_enabled}")

# 带有缓存的操作搜索
calc_actions = await client.search_actions("calculate")
print("计算操作:", [a.name for a in calc_actions])

# 获取枚举信息
enum_info = await client.get_public_enumeration_info("NoYes")
if enum_info:
    print(f"枚举:{enum_info.name}")
    for member in enum_info.members:
        print(f"  {member.name} = {member.value}")
标签操作
# 获取特定标签(v2 缓存系统)
label_text = await client.get_label_text("@SYS13342")
print(f"标签文本:{label_text}")

# 高效获取多个标签
labels = await client.get_labels_batch([
    "@SYS13342", "@SYS9490", "@GLS63332"
])
for label_id, text in labels.items():
    print(f"{label_id}{text}")

# 带有解析标签的增强实体信息
entity_info = await client.get_public_entity_info_with_labels("CustomersV3")
if entity_info.label_text:
    print(f"实体显示名称:{entity_info.label_text}")

# 访问带有标签的增强属性
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"连接失败:{e}")
except AuthenticationError as e:
    print(f"身份验证失败:{e}")
except D365FOClientError as e:
    print(f"客户端操作失败:{e}")
    print(f"状态码:{e.status_code}")
    print(f"响应:{e.response_text}")

开发

设置开发环境
# 克隆仓库
git clone https://github.com/mafzaal/d365fo-client.git
cd d365fo-client

# 使用 uv 安装开发依赖项
uv sync --dev

# 运行测试
uv run pytest

# 运行集成测试
.\tests\integration\integration-test-simple.ps1 test-sandbox

# 格式化代码
uv run black .
uv run isort .

# 类型检查
uv run mypy src/

# 质量检查
.\make.ps1 quality-check  # Windows PowerShell
# 或者
make quality-check       # Unix/Linux/macOS
项目结构
d365fo-client/
├── src/
│   └── d365fo_client/
│       ├── __init__.py          # 公共 API 导出
│       ├── main.py              # CLI 入口点
│       ├── cli.py               # CLI 命令处理程序
│       ├── client.py            # 增强的 D365FOClient 类
│       ├── config.py            # 配置管理
│       ├── auth.py              # 身份验证管理
│       ├── session.py           # HTTP 会话管理
│       ├── crud.py              # CRUD 操作
│       ├── query.py             # OData 查询实用程序
│       ├── metadata.py          # 旧的元数据操作
│       ├── metadata_api.py      # 元数据 API 客户端
│       ├── metadata_cache.py    # 元数据缓存层 V2
│       ├── metadata_sync.py     # 元数据同步 V2,带有会话管理
│       ├── sync_session.py      # 增强的同步会话管理(v0.2.3 新增)
│       ├── credential_manager.py # 凭证源管理(v0.2.3 新增)
│       ├── labels.py            # 标签操作 V2
│       ├── profiles.py          # 配置文件数据模型
│       ├── profile_manager.py   # 配置文件管理
│       ├── models.py            # 数据模型和配置
│       ├── output.py            # 输出格式化
│       ├── utils.py             # 实用函数
│       ├── exceptions.py        # 自定义异常
│       └── mcp/                 # 模型上下文协议服务器
│           ├── __init__.py      # MCP 服务器导出
│           ├── main.py          # MCP 服务器入口点
│           ├── server.py        # 核心 MCP 服务器实现
│           ├── client_manager.py# D365FO 客户端连接池
│           ├── models.py        # MCP 特定的数据模型
│           ├── mixins/          # FastMCP 工具混合类(49 个工具)
│           ├── tools/           # 旧的 MCP 工具(已弃用)
│           │   ├── connection_tools.py
│           │   ├── crud_tools.py
│           │   ├── metadata_tools.py
│           │   └── label_tools.py
│           ├── resources/       # MCP 资源处理程序(4 种类型)
│           │   ├── entity_handler.py
│           │   ├── metadata_handler.py
│           │   ├── environment_handler.py
│           │   └── query_handler.py
│           └── prompts/         # MCP 提示模板
├── tests/                       # 全面的测试套件
│   ├── unit/                    # 单元测试(基于 pytest)
│   ├── integration/             # 多层集成测试
│   │   ├── mock_server/         # 模拟 D365 F&O API 服务器
│   │   ├── test_mock_server.py  # 模拟服务器测试
│   │   ├── test_s
help

Runtime guide

cloud

Hosted runtime

Hosted servers run from a provider-managed environment. You usually connect the MCP client to the hosted endpoint or follow the provider's authorization flow, without keeping a local process alive

  1. Open provider connection page
  2. Authorize or copy endpoint
  3. Connect from your MCP client
terminal

Local runtime / other methods

Local servers run on your own machine or infrastructure. You normally copy the server_config into your MCP client, install the required package, and provide env variables from env_schema when needed

  1. Copy server_config
  2. Install required package
  3. Fill env variables and restart client