Korral StoreLink MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Korral StoreLink MCP ServerCheck inventory and sales for store 47, SKU 8847291"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 |
| One call returns on-hand inventory and trailing-24h POS sales, plus a pre-computed |
| Fires a mock |
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 stdioDuring development you can run the TypeScript source directly without building:
npm run dev # tsx src/index.tsWiring 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 toolscreate_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).
| Name | Required | Description | Default |
|---|---|---|---|
| sku | Yes | SKU to replenish. | |
| quantity | Yes | Number of units to order. Must be a positive integer. | |
| store_id | Yes | Store that needs replenishment. |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| sku | Yes | Product SKU to look up, e.g. "8847291" (Madeta butter 250g). | |
| store_id | Yes | Korral store identifier, e.g. "47" or "102". |
TDQS
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.
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.
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.
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.
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.
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.
2 tool updates
v1.0.0- First observed
create_replenishment_order - First observed
get_store_inventory_and_sales
TDQS
Scored across 2 tools
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.
Both tools follow a consistent verb_noun pattern in snake_case: get_store_inventory_and_sales and create_replenishment_order.
Only 2 tools is minimal, but acceptable for a narrowly scoped replenishment server. However, typical integrations might benefit from a few more tools.
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
Related MCP Connectors
- mcp-serverOAuthcom.make
Give your AI agents the tools to build, manage, and run automation workflows.
Manage your NanoCart store from any AI agent: products, orders, coupons, subscribers, reports.
Connect AI agents to 1000+ apps with managed authentication and tool-calling.
Manage your Savanto store from your AI: catalog, content, prompts, and analytics, by chat.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceEnables 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.-
- FlicenseAqualityDmaintenanceEnables store operations including inventory and sales queries and automated replenishment ordering through natural language.3-
- FlicenseNot gradedqualityBmaintenanceMCP 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.-
- FlicenseAqualityCmaintenanceEnables 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-