Skip to main content
Glama
yashgoel1331

Warehouse Triage MCP

by yashgoel1331

Warehouse Triage MCP

A remotely hosted TypeScript MCP server that helps warehouse operations investigate delayed inventory stages and create safe, deduplicated human-review escalations.

All records are synthetic. The hosted demo requires no local setup.

Safety patterns follow the same spirit as fulfillment-triage-mcp: read-only investigation, signed continuation tokens, and an additive escalation write path that re-locks and rechecks evidence before committing.

Try the hosted workflow

Connect any Streamable HTTP-compatible MCP client to:

https://warehouse-triage-mcp-production.up.railway.app/mcp

For Claude, add this URL under Settings → Connectors → Add custom connector, enable Warehouse Triage in a new chat, and try:

Investigate PO-847291 in the demo workspace. Explain the current stage, timing, threshold, source-reported signals, and supported next action. Do not create an escalation.

Then explicitly approve the only business mutation:

Create the human-review escalation using the investigation you just completed. Do not change receiving, putaway, or inventory state yourself.

Finally verify persistence and a refusal:

Re-investigate PO-847291 in the demo workspace.

Investigate CASE-WITHIN-THRESHOLD in the demo workspace and try to create an escalation.

Expected results:

  • Receiving is overdue after strictly exceeding its eight-hour threshold.

  • The operator must explicitly request escalation.

  • Creation writes an immutable escalation, audit event, and idempotency result only.

  • Re-investigation returns ALREADY_ESCALATED.

  • The within-threshold request is rejected with FULFILLMENT_NOT_OVERDUE.

Product boundary

The selected user is a warehouse operations specialist investigating inventory that appears stuck in:

Stage

Escalation threshold

Receiving

More than 8 hours after ASN arrival

Putaway

More than 4 additional hours after receiving completion

Discrepancy resolution

More than 12 hours after the earliest unresolved discrepancy flag

The MCP gathers synthetic purchase-order, receiving, putaway, discrepancy, and existing-escalation evidence. It derives the active stage, calculates elapsed time, distinguishes source observations from proven causes, and recommends a supported next action.

It can create one human-review escalation. It cannot confirm receiving, complete putaway, resolve discrepancies, adjust quantities, cancel a purchase order, or mutate source inventory state.

MCP surface

Capability

Type

Purpose

investigate_inventory_issue

Read-only tool

Evaluate one purchase-order or ASN reference in a workspace and return evidence, timing, decision, signals, and a signed continuation token

create_inventory_escalation

Additive tool

Revalidate the signed investigation and create or safely refuse a deduplicated escalation

warehouse-triage://demo/scenarios

Resource

Describe the synthetic scenarios available in the demo workspace

Tool inputs:

  • Investigate: workspace_slug, reference, optional as_of (RFC3339)

  • Escalate: continuation_token, episode_key, idempotency_key, optional operator_note

Some AI clients do not expose MCP resources or structuredContent to the model. For compatibility, the investigation’s plain-text content includes the essential decision, detailed source-attributed signals, and exact signed continuation token.

Why MCP is central

The model does not receive a generic database or HTTP wrapper. The MCP defines the product workflow and safety boundary:

flowchart LR
    O["Operations specialist"] --> C["MCP-compatible AI client"]
    C --> I["investigate_inventory_issue"]
    I --> E["PostgreSQL evidence"]
    I --> D["Derived delay decision"]
    D -->|"Explicit operator approval"| X["create_inventory_escalation"]
    X --> R["Lock and revalidate evidence"]
    R --> A["Escalation + audit + idempotency"]

The model cannot supply a stage, threshold, elapsed duration, evidence version, or evidence snapshot. Those values are calculated or recovered from trusted server state.

Safety and correctness

  • Source purchase-order, receiving, putaway, and discrepancy records are read-only to MCP tools.

  • Threshold equality is not overdue; the stage must strictly exceed its limit.

  • Missing or contradictory evidence produces a refusal instead of a guess.

  • Source messages are labeled as untrusted observations, not instructions or proven root causes.

  • A short-lived HMAC-signed investigation token preserves the exact evidence across clients that open a new MCP session for each tool call.

  • Escalation creation locks and reloads evidence, recalculates eligibility, and rejects stale versions.

  • Idempotency prevents repeated identical commands; a separate stable episode key prevents duplicates submitted with different keys.

  • Escalation, audit event, and idempotency result commit atomically.

  • Synthetic workspaces are isolated by workspace_id.

  • Request body size limits are enforced on /mcp.

Demo scenarios

Seeded under workspace slug demo (npm run db:seed):

Reference

Expected investigation

PO-847291

Receiving overdue; escalation supported

CASE-PUTAWAY-OVERDUE

Putaway overdue; escalation supported

CASE-DISCREPANCY-OVERDUE

Discrepancy resolution overdue; escalation supported

CASE-WITHIN-THRESHOLD

Not overdue; escalation refused

CASE-ALREADY-ESCALATED

Existing escalation returned

CASE-MISSING-EVIDENCE

Insufficient evidence; no guess

CASE-CONTRADICTORY-RECEIVING

Contradictory receiving evidence; refused

Architecture

  • Node.js 22 and strict TypeScript

  • Official MCP TypeScript SDK with Streamable HTTP at /mcp

  • PostgreSQL on Supabase via pg (hand-written SQL; no ORM / PostgREST)

  • Executable SQL migrations with checksum tracking

  • Zod input schemas

  • Domain policy separated from repositories, service orchestration, MCP handlers, and HTTP transport

  • Railway-hosted Node service; Supabase-hosted PostgreSQL

The schema models demo workspaces, purchase orders, receiving/putaway/discrepancy evidence, escalations, idempotency, and audit events. See docs/database-schema.md for relationships, statuses, indexes, and repository methods.

Local setup

Prerequisites:

  • Node.js 22+

  • A PostgreSQL database (Supabase session pooler recommended; IPv4)

Copy .env.example to .env and set at least:

DATABASE_URL='postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres?sslmode=require'
INVESTIGATION_TOKEN_SECRET='local-development-secret-at-least-32-characters'

URL-encode special characters in the password. Prefer the session pooler for SELECT … FOR UPDATE safety.

Install, migrate, seed, and run:

npm ci
npm run db:migrate
npm run db:seed
npm run dev

Verify:

curl http://127.0.0.1:3000/health

Use MCP Inspector:

npx @modelcontextprotocol/inspector

Select Streamable HTTP and connect to http://127.0.0.1:3000/mcp.

Verification

Run typecheck, unit tests, and build:

npm run check

Run the DB-backed integration suite (uses TEST_DATABASE_URL or DATABASE_URL):

npm run test:integration

Or both:

npm run test:all

The current suite contains 44 tests covering:

  • Exact SLA boundaries and invalid/contradictory evidence

  • Investigation decisions and refusal codes

  • Read-only investigation behavior

  • Atomic escalation, audit, and idempotency writes

  • Stale evidence, duplicate keys, concurrent episode races, and transaction rollback

  • Signed-token tampering and expiry

  • MCP discovery, schemas, text compatibility, resources, and annotations

  • HTTP method, body-size, health, and MCP initialize behavior

The hosted endpoint was also exercised with Streamable HTTP initialize and manually through Claude as an independent AI consumer.

Decisions, assumptions, and exclusions

Key decisions:

  • Prefer one coherent warehouse-inventory workflow over broad OMS/WMS coverage.

  • Escalate to a human instead of automating operational recovery.

  • Keep the mutation additive and make source-system state unreachable from MCP writes.

  • Use realistic PostgreSQL-backed synthetic systems rather than hard-coded tool responses.

  • Preserve workflow continuity with a signed capability instead of assuming every MCP client retains a transport session.

  • Host Postgres on Supabase and the Node process on Railway.

Assumptions:

  • Stage clocks run continuously; calendars and paused SLA windows are out of scope.

  • Only the current active stage is eligible.

  • Source timestamps and status fields are the available evidence.

  • Human review is represented by PostgreSQL escalation/audit rows, not an external ticketing system.

Explicit exclusions:

  • Real warehouse, purchase-order, or customer data

  • Confirming receiving, completing putaway, resolving discrepancies, quantity adjustments, cancellations, or inventory mutations

  • Escalation assignment, acknowledgement, closure, or downstream queue processing

  • Authentication, production tenant identity, and a frontend

  • Background monitoring or automatic escalation

Known production limitations:

  • Authentication is intentionally omitted because the public demo uses isolated synthetic data.

  • MCP transport is stateless JSON mode; signed workflow tokens still reference database-backed evidence across fresh sessions.

  • /health is a process liveness check, not a database-readiness probe.

  • Rotating the investigation-token secret invalidates outstanding short-lived tokens.

Environment and scripts

Variable

Purpose

DATABASE_URL

Postgres connection string (required)

TEST_DATABASE_URL

Optional override for integration tests

INVESTIGATION_TOKEN_SECRET

HMAC secret (≥32 chars)

INVESTIGATION_TOKEN_TTL_MS

Token TTL (default 900000)

HOST / PORT

Bind address (default 0.0.0.0:3000)

MCP_MAX_BODY_BYTES

Request body limit (default 262144)

NODE_ENV

development | test | production

Script

Action

npm run dev

Watch mode server

npm start

Migrate then run compiled server

npm run build / typecheck

Compile / typecheck

npm test

Unit tests

npm run test:integration

Integration tests against Postgres

npm run test:all

Unit + integration

npm run db:migrate

Apply pending SQL migrations

npm run db:seed

Replace the demo workspace with catalog cases

npm run check

typecheck + unit + build

Supporting documents