Load Planner MCP
load-planner-mcp
Un solucionador determinista de planificación de carga, más un servidor MCP stdio que lo expone como dos herramientas. El solucionador decide el modo de transporte para un conjunto de pedidos — todo por aire, mar consolidado (LCL) o contenedor completo —, calcula el precio de cada opción y adjunta una lectura de riesgo (percentiles de ETA, probabilidad de incumplir el plazo, CVaR de la cola de retraso).
Qué contiene
Ruta | Contenido |
| Empaquetado 3D (py3dbp): ¿caben los palés en un 20GP/40GP/40HC y con qué tasa de llenado? |
| MILP de cargo fijo sobre OR-Tools CP-SAT: asignación factible más barata por patrón de modo enumerado |
| Convolución de distribución de retrasos: ETA p50/p90, probabilidad de incumplir el plazo, CVaR(alpha) |
| Enumera las tarjetas, las puntúa sobre un vector idéntico, las clasifica y elige una recomendación |
| Un límite JSON simple de stdin/stdout, para hosts que prefieren un proceso hijo a una importación |
| El servidor MCP stdio: JSON-RPC 2.0, dos herramientas y |
| Una cohorte sintética de 20 palés con una tarjeta de tarifas sintética, utilizada por las pruebas |
Los dos subproblemas están en capas en lugar de fusionados. Resolver la colocación 3D real dentro del MILP explota combinatoriamente, por lo que el empaquetador se ejecuta primero y entrega a CP-SAT una tasa de llenado y un indicador de viabilidad.
Related MCP server: freight-pulse
El contrato de dos herramientas
solve(problem) ejecuta el solucionador y devuelve su salida tal cual — sin
reformatear, sin redondear, sin resumir — junto con un result_id y un
content_hash SHA-256 del resultado. El resultado se guarda en un almacén dentro del proceso.
explain(result_id) devuelve una narración construida a partir de una plantilla fija cuyos espacios
se rellenan con ese resultado almacenado.
La división es el diseño. Un modelo de lenguaje que llama a este servidor elige qué resolver y pone la respuesta en palabras; no origina ninguna cifra. Tres propiedades hacen que esto sea estructural en lugar de aspiracional:
explaintoma un único id opaco y nada más. Su esquema de entrada tiene una única propiedad. No se le puede pasar una tarifa, un peso o un plazo, por lo que no puede repetir uno.El registro almacenado contiene solo el resultado del solucionador.
solvedescarta la carga del problema una vez que el solucionador ha terminado. No hay ningún campo en el registro almacenado que pueda contener un valor de entrada.No hay aritmética en la ruta de
explain. Los valores se buscan por clave y se representan como cadenas. Seleccionar la tarjeta recomendada lee un indicador que el solucionador ya estableció; no compara ni calcula.
verify_narration(narration, stored) convierte la afirmación en una comprobación. Escanea el
texto en busca de secuencias de dígitos y rechaza cualquier token que no esté en el resultado almacenado, por lo que una
narración que redondea 11480.0 a "11500", convierte 0.1246 a "12.46%" o suma
dos costes almacenados falla — cada uno de esos es un número que el solucionador nunca
produjo. Un host puede aplicarlo a cualquier narración antes de mostrarla, incluida una que el
modelo escribió con sus propias palabras en lugar de una que explain devolvió. explain lo ejecuta
sobre su propia salida antes de devolverla.
Lo que la protección permite deliberadamente, para que no se confunda con una afirmación más fuerte:
los dígitos dentro de cadenas almacenadas y claves de diccionario cuentan como presentes, porque una narración
puede citar esas cadenas textualmente. "ortools-cpsat+py3dbp" admite 3, y el
nombre de campo eta_p90_days admite 90. Es una comprobación léxica de tokens numéricos,
no una prueba de corrección semántica: una narración que asocia el número correcto
a la etiqueta incorrecta sigue pasando.
Instalación
Python 3.10 o superior.
python -m venv .venv
./.venv/bin/pip install ortools py3dbp pytestO instala el paquete en sí, que trae las dos dependencias de ejecución:
pip install -e .ortools es el motor CP-SAT; py3dbp es el empaquetador 3D, con licencia MIT. El servidor MCP
no añade nada más allá de la biblioteca estándar — la superficie del protocolo stdio es
lo suficientemente pequeña como para implementarla directamente, lo que mantiene la lista de dependencias auditable.
Ejecución
El servidor habla JSON-RPC 2.0 delimitado por nuevas líneas en stdin/stdout:
python -m solver_mcpEl solucionador también se puede usar sin MCP, como biblioteca o como proceso hijo:
from load_planner import generate_scenarios
result = generate_scenarios(problem)cat fixtures/cohort_urgent.json | python -m load_planner.cliConexión con un cliente MCP
Cualquier cliente que lance servidores stdio toma un comando y argumentos. Para un
cliente que use la forma de configuración común mcpServers:
{
"mcpServers": {
"load-planner": {
"command": "/absolute/path/to/.venv/bin/python",
"args": ["-m", "solver_mcp"],
"env": { "PYTHONPATH": "/absolute/path/to/load-planner-mcp" }
}
}
}PYTHONPATH solo es necesario cuando el paquete no se ha instalado en el
entorno del intérprete; después de pip install -e . el bloque env se puede eliminar.
El protocolo de inicio es el estándar: initialize, luego la
notificación notifications/initialized, y después tools/list. El servidor informa
la versión de protocolo 2025-06-18 y acepta 2025-03-26 y 2024-11-05,
devolviendo la que el cliente haya solicitado si es una de esas.
Pruebas
python -m pytest tests/ -qTres suites: las pruebas propias del solucionador contra el fixture; el protocolo de inicio de MCP y ambas herramientas, ejercitadas en proceso y sobre un subproceso stdio real; y la suite de manipulación, que verifica que una narración que contenga un valor ausente del resultado almacenado sea rechazada.
Limitaciones
Una sola máquina, un solo proceso. El almacén de resultados está en memoria y vive durante la vida del proceso del servidor. Un
result_idde un proceso se resuelve en otro solo porque los ids están direccionados por contenido y el solucionador es determinista — volver a resolver el mismo problema reproduce el id. No hay almacén compartido, ni desalojo, ni límite en el número de resultados retenidos.Tiempos de ejecución del solucionador. CP-SAT se llama una vez por patrón de modo enumerado, como máximo tres veces por
solve, en un modelo con una variable entera y dos restricciones; devuelve en milisegundos. El coste que escala es el empaquetador 3D, que coloca un artículo por palé — unos cientos de palés está bien, decenas de miles no.solvese ejecuta de forma síncrona y no tiene tiempo de espera interno, por lo que un host debería imponer el suyo propio.Solo asignación de pedido completo. Dividir un pedido entre dos modos (una política de base más suplemento) no está modelado; cada pedido se asigna por completo a un modo.
Entradas de riesgo con semilla. Las distribuciones de retraso en
risk.pyson semillas publicadas de fiabilidad de transportistas, no mediciones de tu propio historial de rutas. Tienen la forma correcta y la precisión incorrecta hasta que un llamador las reemplace.La protección es léxica. Véase la nota anterior:
verify_narrationcomprueba que cada número en una narración aparece en el resultado. No comprueba que el número se haya utilizado para significar lo correcto.
Available Tools
2 toolsexplainNarrate a stored solver resultA
Return a narration template populated only from a stored solver result. Takes a result_id and nothing else: it has no access to the problem inputs and performs no arithmetic, so it cannot state a number the solver did not produce.
| Name | Required | Description | Default |
|---|---|---|---|
| result_id | Yes | A result_id returned by solve. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It explicitly discloses key behavioral constraints: no access to problem inputs, no arithmetic, and inability to state numbers the solver did not produce. It does not cover failure modes or detailed return structure, but the core limitation is clearly communicated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the primary action and followed by a concise constraint. Every sentence earns its place, and there is no repetition of schema fields or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with no output schema, the description explains the input source, what the tool returns, and its limitations. It could specify the narration template's structure, but the tool's simplicity and clear boundaries make it adequately complete for selection and invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter is already described as 'A result_id returned by solve.' The description adds value by emphasizing that it takes 'a result_id and nothing else' and by clarifying the tool's isolation from problem inputs, reinforcing the parameter's purpose beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Return a narration template populated only from a stored solver result,' which is a specific verb and object. It clearly distinguishes this tool from the sibling solve by emphasizing that it consumes a stored result rather than producing one.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use after solve by stating it takes a result_id and nothing else, and the schema's parameter description says the result_id is 'returned by solve.' It also provides a clear exclusion: it has no access to problem inputs and performs no arithmetic, so it should not be used to derive or verify numbers.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solveSolve a load planA
Run the CP-SAT load-planning solver on a problem and return its numeric result verbatim, with a result_id and a content hash. This is the only tool that produces numbers.
| Name | Required | Description | Default |
|---|---|---|---|
| problem | Yes | The load-planning problem. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that it runs a solver and returns the numeric result verbatim with result_id and content hash, which is useful. However, it does not mention side effects, performance implications, error behavior, or prerequisites, leaving a moderate gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the action, and contains no redundant or irrelevant information. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich schema for the input and no output schema, the description adequately describes the output format (numeric result, result_id, content hash) and provides context (only numeric tool). However, it omits details like failure handling or solver constraints, which could be important. Overall it is fairly complete for a simple tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema itself defines the problem structure thoroughly. The tool description adds no specific parameter guidance beyond 'run on a problem', so it meets the baseline of 3 but does not elevate it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (run the CP-SAT load-planning solver) and resource (a problem), and specifically notes 'This is the only tool that produces numbers', which differentiates it from the sibling 'explain'. This meets the standard of a specific verb+resource that distinguishes from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear guidance on when to use this tool (when numeric results are needed) by stating it is the only tool that produces numbers. However, it does not explicitly mention when not to use it or alternative usage scenarios beyond that differentiation, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.1.0- First observed
explain - First observed
solve
TDQS
Scored across 2 tools
solve and explain have clearly separated responsibilities: solve is the only numeric-producing tool, while explain only consumes a stored result_id and never touches inputs or arithmetic. There is no overlap or plausible misselection.
Both tool names are bare imperative verbs following the same style: solve and explain. Although the pattern is not verb_noun, it is entirely consistent across the server.
With only two tools, the server is minimal and borderline thin. Each tool has a distinct role, but the surface feels light for a load-planning MCP.
The core solve-then-explain workflow is covered, and solve returns a result_id for later explanation. Gaps appear around stored result management, such as listing or retrieving prior results independently.
Maintenance
Related MCP Connectors
Plan optimal container & truck loads: 3D layouts, utilization, centre of gravity, crush checks.
Pack cargo into containers & onto pallets; a verifiable 3D loading plan. Free tier + REST API.
Load planning for containers, trucks & pallets in Claude & ChatGPT, with a 3D load plan in the chat.
Calculate required trucks or containers, verify shipment fit, and manage Haulista loading plans.
Related MCP Servers
AlicenseAqualityDmaintenanceLets AI agents pack shipping containers using the Kubova calculator, with tools for container loading and API key verification.46 npmMIT- AlicenseAqualityDmaintenanceOcean and multimodal freight intelligence suite providing cross-validated rates, total landed cost, transit reliability, customs, risk, emissions, and unified ship decisions through 47 tools.4719 npmMIT
- AlicenseAqualityDmaintenanceEnables AI agents to pack trucks and shipping containers by generating validated 3D load plans with metrics like LDM, linear feet, and pallet positions through the Hansatic packing API.34 npmMIT
- AlicenseAqualityBmaintenanceEnables AI assistants to query and manage logistics shipment data, supporting operations like tracking, quoting, and performance analysis via nine tools backed by a demo dataset or a REST API.9253 npmMIT