Load Planner MCP
load-planner-mcp
Детерминированный решатель задач планирования загрузки, а также MCP-сервер stdio, который предоставляет его в виде двух инструментов. Решатель определяет вид транспорта для группы заказов — полностью авиа, консолидированный морской LCL или полный контейнер, — рассчитывает стоимость каждого варианта и прилагает оценку риска (процентили ETA, вероятность срыва срока, CVaR хвоста задержки).
Что здесь находится
Путь | Содержимое |
| 3D-упаковка в контейнеры (py3dbp): помещаются ли паллеты в 20GP/40GP/40HC и с каким коэффициентом заполнения |
| MILP с фиксированными затратами на основе OR-Tools CP-SAT: самое дешёвое допустимое назначение для каждого перечисленного шаблона режима |
| Свёртка распределения задержек: p50/p90 ETA, вероятность срыва срока, CVaR(alpha) |
| Перечисляет карточки, оценивает их по одному общему вектору, ранжирует и выбирает рекомендацию |
| Простая JSON-граница stdin/stdout для хостов, предпочитающих дочерний процесс импорту |
| MCP-сервер stdio: JSON-RPC 2.0, два инструмента и |
| Синтетическая группа из 20 паллет с синтетическим тарифным листом, используемая в тестах |
Две подзадачи выстроены слоями, а не объединены. Решение настоящего 3D-размещения внутри MILP комбинаторно взрывается, поэтому упаковщик запускается первым и передаёт CP-SAT коэффициент заполнения и флаг допустимости.
Related MCP server: freight-pulse
Контракт двух инструментов
solve(problem) запускает решатель и возвращает его вывод дословно — без переформатирования, округления или обобщения — вместе с result_id и SHA-256 content_hash результата. Результат хранится во внутрипроцессном хранилище.
explain(result_id) возвращает повествование, построенное по фиксированному шаблону, слоты которого заполняются из сохранённого результата.
Такое разделение — это и есть замысел. Языковая модель, вызывающая этот сервер, выбирает, что решать, и облекает ответ в слова; она не порождает ни одной цифры. Три свойства делают это структурным, а не декларативным:
explainпринимает один непрозрачный идентификатор и ничего больше. Его входная схема имеет единственное свойство. Ему нельзя передать тариф, вес или срок, поэтому он не может их пересказать.Сохранённая запись содержит только результат решателя.
solveотбрасывает полезную нагрузку задачи после того, как решатель отработал. В сохранённой записи нет поля, которое могло бы нести входное значение.На пути
explainнет никакой арифметики. Значения извлекаются по ключу и отображаются как строки. Выбор рекомендуемой карточки читает флаг, который уже установил решатель; он не сравнивает и не вычисляет.
verify_narration(narration, stored) превращает утверждение в проверку. Он сканирует текст на наличие последовательностей цифр и отклоняет любой токен, отсутствующий в сохранённом результате, так что повествование, округляющее 11480.0 до «11500», преобразующее 0.1246 в «12.46%» или складывающее две сохранённые стоимости, не проходит — каждая из этих цифр не была порождена решателем. Хост может применить его к любому повествованию перед отображением, включая то, которое модель написала своими словами, а не то, что вернул explain. explain запускает его на собственном выводе перед возвратом.
Что защита намеренно допускает, чтобы её не приняли за более сильное утверждение: цифры внутри сохранённых строк и ключей словарей считаются присутствующими, поскольку повествование может дословно цитировать эти строки. "ortools-cpsat+py3dbp" допускает 3, а имя поля eta_p90_days допускает 90. Это лексическая проверка числовых токенов, а не доказательство семантической корректности: повествование, приписывающее правильное число неправильной метке, всё равно проходит.
Установка
Python 3.10 или новее.
python -m venv .venv
./.venv/bin/pip install ortools py3dbp pytestИли установите сам пакет, который подтянет две зависимости времени выполнения:
pip install -e .ortools — это движок CP-SAT; py3dbp — 3D-упаковщик, лицензия MIT. MCP-сервер не добавляет ничего сверх стандартной библиотеки — поверхность протокола stdio достаточно мала, чтобы реализовать её напрямую, что делает список зависимостей проверяемым.
Запуск
Сервер общается через построчно разделённый JSON-RPC 2.0 на stdin/stdout:
python -m solver_mcpРешатель также можно использовать без MCP — как библиотеку или как дочерний процесс:
from load_planner import generate_scenarios
result = generate_scenarios(problem)cat fixtures/cohort_urgent.json | python -m load_planner.cliПодключение к MCP-клиенту
Любой клиент, запускающий stdio-серверы, принимает команду и аргументы. Для клиента, использующего распространённую форму конфигурации mcpServers:
{
"mcpServers": {
"load-planner": {
"command": "/absolute/path/to/.venv/bin/python",
"args": ["-m", "solver_mcp"],
"env": { "PYTHONPATH": "/absolute/path/to/load-planner-mcp" }
}
}
}PYTHONPATH нужен только в том случае, если пакет не установлен в окружение интерпретатора; после pip install -e . блок env можно убрать.
Рукопожатие стандартное: initialize, затем уведомление notifications/initialized, затем tools/list. Сервер сообщает версию протокола 2025-06-18 и принимает 2025-03-26 и 2024-11-05, возвращая ту, которую запросил клиент, если она одна из этих.
Тесты
python -m pytest tests/ -qТри набора: собственные тесты решателя на фикстуре; рукопожатие MCP и оба инструмента, проверенные как в процессе, так и через реальный дочерний процесс stdio; и набор проверок на подделку, который утверждает, что повествование, содержащее значение, отсутствующее в сохранённом результате, отклоняется.
Ограничения
Одна машина, один процесс. Хранилище результатов находится в памяти и живёт столько же, сколько процесс сервера.
result_idиз одного процесса разрешается в другом только потому, что идентификаторы адресуются по содержимому, а решатель детерминирован — повторное решение той же задачи воспроизводит идентификатор. Нет общего хранилища, нет вытеснения и нет ограничения на количество сохраняемых результатов.Время работы решателя. CP-SAT вызывается один раз на каждый перечисленный шаблон режима, максимум три раза за
solve, на модели с одной целочисленной переменной и двумя ограничениями; он возвращается за миллисекунды. Затраты, которые масштабируются, — это 3D-упаковщик, размещающий один предмет на паллет — несколько сотен паллет — это нормально, десятки тысяч — нет.solveвыполняется синхронно и не имеет внутреннего тайм-аута, поэтому хост должен установить свой собственный.Только назначение всего заказа. Разделение одного заказа на два режима (политика «база плюс пик») не моделируется; каждый заказ назначается целиком одному режиму.
Заданные входные данные риска. Распределения задержек в
risk.py— это опубликованные показатели надёжности перевозчиков, а не измерения из вашей собственной истории маршрутов. Они имеют правильную форму и неправильную точность, пока вызывающий код не заменит их.Защита лексическая. См. примечание выше:
verify_narrationпроверяет, что каждое число в повествовании присутствует в результате. Он не проверяет, что число использовано для обозначения правильной вещи.
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.41 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.475 npmMIT
- AlicenseNot gradedqualityCmaintenancePlan optimal container & truck loads: 3D layouts, right-size the container mix, and check utilization, centre of gravity, crush protection and securing across 200+ equipment types.9 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.37 npmMIT