[project] name = "d365fo-client" version = "0.3.7" description = "Microsoft Dynamics 365 Finance & Operations client and MCP server" readme = "README.md" license = "MIT" authors = [{ name = "Muhammad Afzaal", email = "mo@thedataguy.pro" }] requires-python = ">=3.13" dependencies = [ "aiohttp>=3.10.0", "aiofiles>=24.1.0", "azure-identity>=1.19.0", "azure-keyvault-secrets>=4.8.0", "requests>=2.32.0", "aiosqlite>=0.19.0", "cachetools>=6.1.0", "diskcache>=5.6.3", "tabulate>=0.9.0", "pyyaml>=6.0", "mcp>=1.13.0", "uvicorn>=0.32.0", "pydantic-settings>=2.6.0", "authlib>=1.6.4", "httpx>=0.28.1", "rich>=14.1.0", ] keywords = ["dynamics365", "d365", "finance", "operations", "erp", "microsoft"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.13", "Topic :: Office/Business :: Financial", "Topic :: Software Development :: Libraries :: Python Modules", ] [project.optional-dependencies] dev = [ "pytest>=8.0.0", "pytest-asyncio>=0.23.0", "pytest-cov>=4.0.0", "black>=23.0.0", "ruff>=0.1.0", ] all = [ "d365fo-client[dev]" ] [project.urls] Homepage = "https://github.com/mafzaal/d365fo-client" Repository = "https://github.com/mafzaal/d365fo-client" Documentation = "https://github.com/mafzaal/d365fo-client" Issues = "https://github.com/mafzaal/d365fo-client/issues" Changelog = "https://github.com/mafzaal/d365fo-client/blob/main/CHANGELOG.md" [project.scripts] d365fo-client = "d365fo_client.main:main" d365fo-mcp-server = "d365fo_client.mcp.fastmcp_main:main" d365fo-fastmcp-server = "d365fo_client.mcp.fastmcp_main:main" [build-system] requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] where = ["src"] [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py"] python_classes = ["Test*"] python_functions = ["test_*"] addopts = "-v --tb=short" asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" filterwarnings = [ "ignore:coroutine.*was never awaited:RuntimeWarning", ] [tool.black] line-length = 88 target-version = ["py313"] include = '\.pyi?$' extend-exclude = ''' /( # directories \.eggs | \.git | \.hg | \.mypy_cache | \.tox | \.venv | build | dist )/ ''' [tool.isort] profile = "black" line_length = 88 multi_line_output = 3 include_trailing_comma = true force_grid_wrap = 0 use_parentheses = true ensure_newline_before_comments = true [tool.mypy] python_version = "3.13" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true disallow_incomplete_defs = true check_untyped_defs = true disallow_untyped_decorators = true no_implicit_optional = true warn_redundant_casts = true warn_unused_ignores = true warn_no_return = true warn_unreachable = true strict_equality = true [dependency-groups] dev = [ "black>=25.1.0", "isort>=6.0.1", "mypy>=1.17.1", "pip-audit>=2.9.0", "pytest>=8.4.1", "pytest-asyncio>=0.25.0", "pytest-cov>=6.2.1", "ruff>=0.12.9", "types-pyyaml>=6.0.12.20250822", "types-tabulate>=0.9.0.20241207", ] integration = [ "aiohttp>=3.10.0", "pytest>=8.4.1", "pytest-asyncio>=0.25.0", "pytest-cov>=6.2.1", "httpx>=0.27.0", "responses>=0.25.0", "wiremock>=2.6.1", ]