Skip to main content
Glama
AI-Product-Allen-Yu

Korral StoreLink MCP Server

Korral StoreLink MCP Server

A standalone Model Context Protocol server, written in TypeScript with the official @modelcontextprotocol/sdk, that exposes the StoreLink backend of the Korral grocery chain to an AI agent.

It ships two collapsed, semantic tools designed for a stock-out / replenishment workflow:

Tool

Purpose

get_store_inventory_and_sales(store_id, sku)

One call returns on-hand inventory and trailing-24h POS sales, plus a pre-computed demand_gap and stockout_risk.

create_replenishment_order(store_id, sku, quantity)

Fires a mock POST to raise a replenishment (restock) order and returns the confirmation.

The transport is Stdio — the server reads JSON-RPC from stdin and writes to stdout, which is how MCP hosts (Claude Desktop, IDEs, agent runtimes) launch local servers.

Quick start

npm install
npm test        # vitest — unit tests for the tool logic
npm run build   # esbuild — bundles a single production file to dist/index.js
npm start       # runs dist/index.js over stdio

During development you can run the TypeScript source directly without building:

npm run dev     # tsx src/index.ts

Wiring it into an MCP host

{
  "mcpServers": {
    "korral-storelink": {
      "command": "node",
      "args": ["E:/temp/duvo-mcp-assignment/dist/index.js"]
    }
  }
}

Related MCP server: store-ops-mcp

Mock data

The mock backend (src/mockData.ts) tracks one SKU — 8847291, Madeta butter 250g — across two stores, deliberately seeded to show contrasting demand gaps:

Store

On-hand

POS (last 24h)

Demand gap

Risk

47

2

10

8

high

102

12

14

2

moderate

demand_gap = units_sold_last_24h - on_hand. Store 47 sold far more than it has on the shelf — a clear restock candidate; Store 102 is keeping pace.

Architectural choices & tradeoffs

1. Collapsed, semantic tools over a 1:1 API mirror

In the real StoreLink API, inventory and POS sales live behind two separate endpoints. A naïve MCP server would expose them as two tools, forcing the agent to make two round-trips, hold both payloads in context, and do the subtraction itself.

Instead, get_store_inventory_and_sales collapses both endpoints into one payload and pre-computes demand_gap and stockout_risk. The benefits for an agent:

  • Fewer tokens / less context churn — one tool result instead of two, with only the fields that matter for the decision.

  • Fewer round-trips — one tool call to assess a store/SKU instead of two-then-reason.

  • Less room for error — the server, not the model, does the arithmetic and risk bucketing.

Tradeoff: the tool is opinionated and less general-purpose than raw endpoints. A different consumer that wanted only inventory now over-fetches POS data, and the stockout_risk thresholds (gap >= 5 → high, >= 1 → moderate) are baked into the server rather than chosen by the caller. For an agent-first tool surface this is the right trade — we optimize for the agent's context window and decision quality, not for maximal API flexibility.

2. Action tool returns a confirmation, not a raw HTTP echo

create_replenishment_order models a side-effecting POST. It returns a small, structured confirmation (order_id, status: "submitted", echoed inputs) rather than a verbose HTTP response, so the agent gets just enough to confirm success and report back.

3. Schema validation with Zod

Tool inputs are validated with Zod schemas registered through the SDK. Each field carries a .describe() string that the SDK surfaces in the JSON Schema sent to the model — so the agent learns what store_id, sku, and quantity mean. quantity is constrained to a positive integer both in the schema and defensively in the handler.

4. Pure functions + thin server wiring (testability)

The tool logic (getStoreInventoryAndSales, createReplenishmentOrder) is implemented as pure, exported functions; buildServer() only wires them to the MCP transport. This keeps the Vitest suite fast and transport-free — it tests behavior directly, with no stdio mocking.

5. esbuild → single bundled file

npm run build (see build.mjs) bundles everything — including the SDK and Zod — into one self-contained, minified dist/index.js with a #!/usr/bin/env node shebang. An MCP host can run it with a single node dist/index.js command, no node_modules required at the deploy target. Node built-ins are left external since the runtime provides them.

Tradeoff: bundling dependencies makes the output larger (~330 KB) and pins them at build time, but removes any runtime install step — the right call for a server meant to be dropped into a host config.

Project layout

.
├── build.mjs            # esbuild bundle script -> dist/index.js
├── package.json
├── tsconfig.json
├── vitest.config.ts
├── src
│   ├── index.ts         # MCP server: schemas, tools, stdio wiring
│   ├── index.test.ts    # Vitest unit tests
│   └── mockData.ts      # Mock StoreLink inventory + POS data
└── dist
    └── index.js         # Bundled production server (generated)

Available Tools

2 tools
create_replenishment_orderCreate replenishment orderA

Raise a replenishment (restock) order for a store/SKU via StoreLink. Use after get_store_inventory_and_sales shows a meaningful demand gap. quantity is the number of units to order (positive integer).

ParametersJSON Schema
NameRequiredDescriptionDefault
skuYesSKU to replenish.
quantityYesNumber of units to order. Must be a positive integer.
store_idYesStore that needs replenishment.

TDQS

A3.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It only notes that quantity must be positive, but fails to disclose behavioral traits like whether the action is irreversible, required permissions, or rate limits. The word 'create' implies mutation, but more transparency is needed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose. Efficient and no wasted words. Could potentially be slightly more concise, but it's well-structured.

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 simple tool with three required parameters and no output schema, the description provides adequate context: purpose, usage trigger, and parameter note. Could mention response or constraints (e.g., max quantity) but overall complete.

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 coverage is 100%, so the schema describes all parameters. The description adds the note that quantity is 'number of units to order (positive integer)', but this largely repeats schema info. No meaningful new semantic context beyond 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 clearly states the tool's purpose: 'Raise a replenishment (restock) order for a store/SKU via StoreLink.' The verb 'raise' and resource 'replenishment order' are specific, and it distinguishes from the sibling tool by implying this is the action after inventory check.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: 'Use after get_store_inventory_and_sales shows a meaningful demand gap.' This provides clear context and prevents misuse.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_store_inventory_and_salesGet store inventory and salesA

Fetch on-hand inventory AND trailing-24h POS sales for a single store/SKU in one call. Returns a pre-computed demand_gap and stockout_risk so you can decide whether to replenish without making two separate requests.

ParametersJSON Schema
NameRequiredDescriptionDefault
skuYesProduct SKU to look up, e.g. "8847291" (Madeta butter 250g).
store_idYesKorral store identifier, e.g. "47" or "102".

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions returning pre-computed fields but omits details like read-only nature, error handling, rate limits, or authentication requirements. Some transparency is present but incomplete.

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 extraneous information. It efficiently communicates the tool's purpose and key return values.

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?

Despite lacking an output schema, the description mentions the key return fields (demand_gap, stockout_risk) which are critical for its usage. For a simple tool with two parameters, the description covers the main points, though it could include more behavioral context.

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%, so the input schema already documents both parameters adequately. The description adds no additional parameter semantics beyond what the schema provides, meeting the baseline.

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 verb (fetch) and resource (store/SKU inventory and sales). It explicitly distinguishes itself from the sibling tool 'create_replenishment_order' by highlighting that it combines two data points and provides pre-computed metrics for replenishment decisions.

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 usage context: when you need both inventory and sales for replenishment, avoiding two calls. However, it does not explicitly state when not to use it or list alternative tools beyond the sibling.

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 updatesv1.0.0
    • First observedcreate_replenishment_order
    • First observedget_store_inventory_and_sales

TDQS

A3.9/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: one retrieves inventory and sales data, the other creates a replenishment order. There is no overlap or ambiguity.

Naming Consistency5/5

Both tools follow a consistent verb_noun pattern in snake_case: get_store_inventory_and_sales and create_replenishment_order.

Tool Count3/5

Only 2 tools is minimal, but acceptable for a narrowly scoped replenishment server. However, typical integrations might benefit from a few more tools.

Completeness2/5

The server covers the core check-and-create cycle but lacks essential operations like listing, updating, or canceling replenishment orders, which agents may need.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables AI agents to interact with Skulabs inventory management system through comprehensive tools for managing products, orders, customers, and analytics. Supports voice agents like Retell AI and desktop applications like Claude for natural language inventory operations.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    MCP server that lets a Duvo agent talk to Korral's StoreLink API, enabling category buyers to offload daily stock checking, replenishment ordering, and order tracking tasks.
    -
  • F
    license
    A
    quality
    C
    maintenance
    Enables an AI grocery replenishment agent to interface with Korral's StoreLink stock API, providing tools to look up SKUs, get stock positions and gaps across stores, create replenishment orders (with buyer approval), and track order status.
    4
    -