Skip to main content
Glama
bayraak

Load Planner MCP

by bayraak

load-planner-mcp

CI

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

load_planner/geometry.py

Empaquetado 3D (py3dbp): ¿caben los palés en un 20GP/40GP/40HC y con qué tasa de llenado?

load_planner/solver.py

MILP de cargo fijo sobre OR-Tools CP-SAT: asignación factible más barata por patrón de modo enumerado

load_planner/risk.py

Convolución de distribución de retrasos: ETA p50/p90, probabilidad de incumplir el plazo, CVaR(alpha)

load_planner/scenarios.py

Enumera las tarjetas, las puntúa sobre un vector idéntico, las clasifica y elige una recomendación

load_planner/cli.py

Un límite JSON simple de stdin/stdout, para hosts que prefieren un proceso hijo a una importación

solver_mcp/server.py

El servidor MCP stdio: JSON-RPC 2.0, dos herramientas y verify_narration()

fixtures/cohort_urgent.json

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:

  1. explain toma 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.

  2. El registro almacenado contiene solo el resultado del solucionador. solve descarta 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.

  3. 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 pytest

O 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_mcp

El 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.cli

Conexió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/ -q

Tres 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_id de 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. solve se 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.py son 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_narration comprueba 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 tools
explainNarrate 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.

NameRequiredDescriptionDefault
result_idYesA result_id returned by solve.

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

NameRequiredDescriptionDefault
problemYesThe load-planning problem.

TDQS

A4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 2 tool updatesv0.1.0
    • First observedexplain
    • First observedsolve

TDQS

A4.2/5.0

Scored across 2 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count3/5

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.

Completeness4/5

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

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Lets AI agents pack shipping containers using the Kubova calculator, with tools for container loading and API key verification.
    4
    6 npm
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Ocean and multimodal freight intelligence suite providing cross-validated rates, total landed cost, transit reliability, customs, risk, emissions, and unified ship decisions through 47 tools.
    47
    19 npm
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables 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.
    3
    4 npm
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables 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.
    9
    253 npm
    MIT