From b520d47ab33917fbc462d7a6003e8ad24ee26d34 Mon Sep 17 00:00:00 2001 From: aserrador Date: Tue, 17 Mar 2026 18:15:10 -0500 Subject: [PATCH] feat: add Docker support with uv and update taskipy start command - Add Dockerfile using uv for dependency management - Add docker-compose.yaml for container orchestration - Add .dockerignore to optimize builds - Update taskipy start task with http transport and port 3001 - Update README.md and AGENTS.md with Docker documentation --- .dockerignore | 15 +++++ AGENTS.md | 89 ++++++++++++++++++++++++---- Dockerfile | 17 ++++++ README.md | 91 ++++++++++++++++++++++++++++ docker-compose.yaml | 9 +++ pyproject.toml | 9 +++ src/tryton_mcp/config.py | 4 +- src/tryton_mcp/server.py | 2 +- src/tryton_mcp/services/base.py | 2 +- src/tryton_mcp/services/schedule.py | 2 +- tests/conftest.py | 3 +- tests/test_customer.py | 2 - tests/test_server.py | 3 - uv.lock | 92 +++++++++++++++++++++++++++++ 14 files changed, 316 insertions(+), 24 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b0dcfd1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +.git +.gitignore +__pycache__ +.pytest_cache +.env +.venv +*.pyc +*.egg-info +.eggs +dist +build +.ruff_cache +.mypy_cache +.DS_Store +*.log diff --git a/AGENTS.md b/AGENTS.md index c0229c8..d5ee74e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,8 +1,66 @@ # TrytonMCP Agent Specification +## Desarrollo + +### Configuración inicial + +```bash +# Instalar dependencias con uv +uv sync + +# Copiar configuración de ejemplo +cp .env.example .env + +# Instalar dependencias de desarrollo y test +uv pip install -e ".[test]" +``` + +### Comandos frecuentes + +```bash +# Ejecutar servidor MCP (stdio) +uv run fastmcp run src/tryton_mcp/server.py + +# Ejecutar tests +python -m pytest tests/ -v + +# Verificar código +ruff check src/ tests/ +ruff format src/ tests/ +``` + +### Docker + +```bash +# Construir imagen +docker compose build + +# Iniciar contenedor +docker compose up -d + +# Ver logs +docker compose logs -f + +# Detener +docker compose down +``` + +### Agregar nueva herramienta + +```python +from tryton_mcp.services.base import TrytonService + +class YourService(TrytonService): + name = "your.model.method" + + def execute(self, params: dict) -> List[dict]: + # Implementar lógica + pass +``` + ## Overview -TrytonMCP is an MCP (Model Context Protocol) server that enables LLMs to interact with Tryton ERP functionality through RPC calls. It wraps the `sabatron-tryton_rpc_client` library and exposes Tryton models as callable tools. +TrytonMCP es un servidor MCP (Model Context Protocol) que permite a los LLMs interactuar con Tryton ERP a través de llamadas RPC. Envuelve la librería `sabatron-tryton_rpc_client` y expone los modelos de Tryton como herramientas invocables. ## Project Structure @@ -12,10 +70,23 @@ TrytonMCP/ │ └── tryton_mcp/ │ ├── __init__.py │ ├── config.py # Settings singleton with TrytonSettings -│ └── server.py # Main MCP server with tool definitions -├── test_rpc.py # Standalone RPC test script -├── pyproject.toml # Project dependencies -└── .env.example # Environment variables template +│ ├── server.py # Main MCP server with tool definitions +│ └── services/ +│ ├── base.py # TrytonService base class +│ ├── party.py # Customer operations +│ ├── product.py # Products/Services +│ ├── schedule.py # Appointments +│ └── service_center.py # Service centers +├── tests/ # Test suite +│ ├── conftest.py +│ ├── test_customer.py +│ └── test_server.py +├── test_rpc.py # Standalone RPC test script +├── Dockerfile # Docker container definition +├── docker-compose.yaml # Docker Compose orchestration +├── .dockerignore # Docker build exclusions +├── pyproject.toml # Project dependencies +└── .env.example # Environment variables template ``` ## Architecture @@ -56,14 +127,8 @@ def your_tool_name(param1: int, param2: str) -> List[dict]: ## Running the Server ```bash -# Activate virtual environment -source .venv/bin/activate - # Run MCP server (stdio mode) -python -m tryton_mcp.server - -# Or use fastmcp CLI -fastmcp run tryton_mcp.server +uv run fastmcp run src/tryton_mcp/server.py ``` ## Configuration diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c0b9b37 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.14-trixie + +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 + +WORKDIR /app + +RUN pip install --no-cache-dir uv + +COPY pyproject.toml uv.lock ./ +COPY src/ ./src/ +RUN uv sync --frozen --no-dev +RUN uv pip install --editable . + +EXPOSE 3001 + +CMD ["uv", "run", "fastmcp", "run", "./src/tryton_mcp/server.py", "--transport", "http", "--port", "3001"] diff --git a/README.md b/README.md index e69de29..0e60b0e 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,91 @@ +# TrytonMCP + +MCP server que permite a LLMs interactuar con Tryton ERP a través de llamadas RPC. + +## Requisitos + +- Python 3.14+ +- uv (gestor de paquetes) + +## Instalación + +```bash +uv sync +cp .env.example .env +# Editar .env con las credenciales de Tryton +``` + +## Desarrollo + +### Configuración del entorno + +```bash +# Activar entorno virtual +source .venv/bin/activate + +# Instalar dependencias de desarrollo +uv pip install -e ".[test]" +``` + +### Comandos disponibles + +```bash +# Ejecutar servidor MCP +uv run fastmcp run src/tryton_mcp/server.py + +# Ejecutar tests +python -m pytest tests/ -v + +# Verificar código con ruff +ruff check src/ tests/ + +# Format código +ruff format src/ tests/ +``` + +## Estructura del proyecto + +``` +src/tryton_mcp/ +├── __init__.py +├── config.py # Configuración singleton +├── server.py # Servidor MCP principal +└── services/ + ├── base.py # TrytonService base + ├── provider.py # Provider service + ├── party.py # Customer/Party operations + ├── product.py # Products/Services + ├── schedule.py # Appointments + └── service_center.py # Service centers +``` + +## Uso con Docker + +```bash +# Construir imagen +docker compose build + +# Iniciar contenedor +docker compose up -d + +# Ver logs +docker compose logs -f + +# Detener +docker compose down +``` + +El servidor MCP estará disponible en `http://localhost:3001`. + +## Testing + +```bash +# Todos los tests +python -m pytest tests/ -v + +# Tests específicos +python -m pytest tests/test_server.py -v + +# Con coverage +python -m pytest tests/ --cov=src --cov-report=html +``` \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..c24cfc4 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,9 @@ +services: + mcp: + build: + context: . + dockerfile: Dockerfile + ports: + - "3001:3001" + env_file: + - .env diff --git a/pyproject.toml b/pyproject.toml index 3309aaf..0b817f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ dependencies = [ "sabatron-tryton-rpc-client>=7.4.0", "python-dotenv>=1.0.0", "pydantic>=2.0.0", + "pytest>=9.0.2", ] [project.optional-dependencies] @@ -21,3 +22,11 @@ test = [ [tool.setuptools.packages.find] where = ["src"] include = ["*"] + +[dependency-groups] +dev = [ + "taskipy>=1.14.1", +] + +[tool.taskipy.tasks] +start = "fastmcp run ./src/tryton_mcp/server.py --transport http --port 3001 --reload" diff --git a/src/tryton_mcp/config.py b/src/tryton_mcp/config.py index 0880605..68472ac 100644 --- a/src/tryton_mcp/config.py +++ b/src/tryton_mcp/config.py @@ -19,10 +19,10 @@ class TrytonSettings: _client: Optional[Client] = field(default=None, init=False, repr=False) hostname: str = field( - default_factory=lambda: os.environ.get("TRYTON_HOSTNAME", "localhost") + default_factory=lambda: os.environ.get("TRYTON_HOSTNAME", "localhost:10000") ) database: str = field( - default_factory=lambda: os.environ.get("TRYTON_DATABASE", "tryton") + default_factory=lambda: os.environ.get("TRYTON_DATABASE", "database") ) username: str = field( default_factory=lambda: os.environ.get("TRYTON_USERNAME", "admin") diff --git a/src/tryton_mcp/server.py b/src/tryton_mcp/server.py index d111fc6..0103c80 100644 --- a/src/tryton_mcp/server.py +++ b/src/tryton_mcp/server.py @@ -4,7 +4,7 @@ MCP Server for Naliia Module import logging from contextlib import asynccontextmanager -from datetime import datetime, timezone +from datetime import datetime from typing import Any, Dict, List, Optional from fastmcp import FastMCP diff --git a/src/tryton_mcp/services/base.py b/src/tryton_mcp/services/base.py index a14d007..acdb423 100644 --- a/src/tryton_mcp/services/base.py +++ b/src/tryton_mcp/services/base.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional +from typing import Any, List, Optional from dataclasses import dataclass diff --git a/src/tryton_mcp/services/schedule.py b/src/tryton_mcp/services/schedule.py index 7d45f42..1ee7c1d 100644 --- a/src/tryton_mcp/services/schedule.py +++ b/src/tryton_mcp/services/schedule.py @@ -1,5 +1,5 @@ from datetime import datetime, timezone -from typing import Any, Dict, List, Optional +from typing import Any, List, Optional from tryton_mcp.services.base import BaseService, TrytonResponse diff --git a/tests/conftest.py b/tests/conftest.py index 7784207..a91f320 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,4 @@ import pytest -import pytest_asyncio from unittest.mock import MagicMock, patch from fastmcp import Client @@ -19,7 +18,7 @@ def mcp_server(): return mcp -@pytest_asyncio.fixture +@pytest.fixture async def mcp_client(mcp_server): async with Client(mcp_server) as client: yield client diff --git a/tests/test_customer.py b/tests/test_customer.py index 7cb30e1..096e138 100644 --- a/tests/test_customer.py +++ b/tests/test_customer.py @@ -1,7 +1,5 @@ import pytest -import pytest_asyncio from unittest.mock import MagicMock, patch -import json import sys from pathlib import Path diff --git a/tests/test_server.py b/tests/test_server.py index b4e7263..f6fef3a 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -1,8 +1,5 @@ import pytest -import pytest_asyncio from unittest.mock import MagicMock, patch -import json -from contextlib import asynccontextmanager import sys from pathlib import Path diff --git a/uv.lock b/uv.lock index 35d30e3..f1256a0 100644 --- a/uv.lock +++ b/uv.lock @@ -623,6 +623,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" }, ] +[[package]] +name = "mslex" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/97/7022667073c99a0fe028f2e34b9bf76b49a611afd21b02527fbfd92d4cd5/mslex-1.3.0.tar.gz", hash = "sha256:641c887d1d3db610eee2af37a8e5abda3f70b3006cdfd2d0d29dc0d1ae28a85d", size = 11583, upload-time = "2024-10-16T13:16:18.523Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/f2/66bd65ca0139675a0d7b18f0bada6e12b51a984e41a76dbe44761bf1b3ee/mslex-1.3.0-py3-none-any.whl", hash = "sha256:c7074b347201b3466fc077c5692fbce9b5f62a63a51f537a53fbbd02eff2eea4", size = 7820, upload-time = "2024-10-16T13:16:17.566Z" }, +] + [[package]] name = "openapi-pydantic" version = "0.5.1" @@ -693,6 +702,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, ] +[[package]] +name = "psutil" +version = "6.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1f/5a/07871137bb752428aa4b659f910b399ba6f291156bdea939be3e96cae7cb/psutil-6.1.1.tar.gz", hash = "sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5", size = 508502, upload-time = "2024-12-19T18:21:20.568Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/99/ca79d302be46f7bdd8321089762dd4476ee725fce16fc2b2e1dbba8cac17/psutil-6.1.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8", size = 247511, upload-time = "2024-12-19T18:21:45.163Z" }, + { url = "https://files.pythonhosted.org/packages/0b/6b/73dbde0dd38f3782905d4587049b9be64d76671042fdcaf60e2430c6796d/psutil-6.1.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377", size = 248985, upload-time = "2024-12-19T18:21:49.254Z" }, + { url = "https://files.pythonhosted.org/packages/17/38/c319d31a1d3f88c5b79c68b3116c129e5133f1822157dd6da34043e32ed6/psutil-6.1.1-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003", size = 284488, upload-time = "2024-12-19T18:21:51.638Z" }, + { url = "https://files.pythonhosted.org/packages/9c/39/0f88a830a1c8a3aba27fededc642da37613c57cbff143412e3536f89784f/psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160", size = 287477, upload-time = "2024-12-19T18:21:55.306Z" }, + { url = "https://files.pythonhosted.org/packages/47/da/99f4345d4ddf2845cb5b5bd0d93d554e84542d116934fde07a0c50bd4e9f/psutil-6.1.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3", size = 289017, upload-time = "2024-12-19T18:21:57.875Z" }, + { url = "https://files.pythonhosted.org/packages/38/53/bd755c2896f4461fd4f36fa6a6dcb66a88a9e4b9fd4e5b66a77cf9d4a584/psutil-6.1.1-cp37-abi3-win32.whl", hash = "sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53", size = 250602, upload-time = "2024-12-19T18:22:08.808Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d7/7831438e6c3ebbfa6e01a927127a6cb42ad3ab844247f3c5b96bea25d73d/psutil-6.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649", size = 254444, upload-time = "2024-12-19T18:22:11.335Z" }, +] + [[package]] name = "py-key-value-aio" version = "0.4.4" @@ -875,6 +899,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, ] +[[package]] +name = "pytest-asyncio" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" }, +] + [[package]] name = "pytest-mock" version = "3.15.1" @@ -1139,12 +1175,56 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" }, ] +[[package]] +name = "taskipy" +version = "1.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, + { name = "mslex", marker = "sys_platform == 'win32'" }, + { name = "psutil" }, + { name = "tomli", marker = "python_full_version < '4'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/44/572261df3db9c6c3332f8618fafeb07a578fd18b06673c73f000f3586749/taskipy-1.14.1.tar.gz", hash = "sha256:410fbcf89692dfd4b9f39c2b49e1750b0a7b81affd0e2d7ea8c35f9d6a4774ed", size = 14475, upload-time = "2024-11-26T16:37:46.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/97/4e4cfb1391c81e926bebe3d68d5231b5dbc3bb41c6ba48349e68a881462d/taskipy-1.14.1-py3-none-any.whl", hash = "sha256:6e361520f29a0fd2159848e953599f9c75b1d0b047461e4965069caeb94908f1", size = 13052, upload-time = "2024-11-26T16:37:44.546Z" }, +] + +[[package]] +name = "tomli" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" }, + { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" }, + { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" }, + { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" }, + { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" }, + { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" }, + { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" }, + { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" }, + { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" }, + { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" }, + { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" }, + { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" }, + { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" }, +] + [[package]] name = "tryton-mcp" version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "fastmcp", extra = ["tasks"] }, + { name = "pydantic" }, + { name = "pytest" }, { name = "python-dotenv" }, { name = "sabatron-tryton-rpc-client" }, ] @@ -1152,19 +1232,31 @@ dependencies = [ [package.optional-dependencies] test = [ { name = "pytest" }, + { name = "pytest-asyncio" }, { name = "pytest-mock" }, ] +[package.dev-dependencies] +dev = [ + { name = "taskipy" }, +] + [package.metadata] requires-dist = [ { name = "fastmcp", extras = ["tasks"], specifier = ">=3.1.0" }, + { name = "pydantic", specifier = ">=2.0.0" }, + { name = "pytest", specifier = ">=9.0.2" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.0.0" }, + { name = "pytest-asyncio", marker = "extra == 'test'", specifier = ">=0.25.0" }, { name = "pytest-mock", marker = "extra == 'test'", specifier = ">=3.14.0" }, { name = "python-dotenv", specifier = ">=1.0.0" }, { name = "sabatron-tryton-rpc-client", specifier = ">=7.4.0" }, ] provides-extras = ["test"] +[package.metadata.requires-dev] +dev = [{ name = "taskipy", specifier = ">=1.14.1" }] + [[package]] name = "typer" version = "0.24.1"