korral-mcp
Click on "Install 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-mcpcheck stock status for store 42 and SKU ABC123"
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-mcp
MCP server that lets a Duvo agent talk to Korral's StoreLink store-ordering/stock-tracking API, so category buyers can offload the daily "check on-hand vs. POS, decide if a store will go empty, raise a replenishment order" detective work described in CLAUDE.md.
Files
server.py— the MCP server (FastMCP). Exposes 3 tools to the agent.storelink.py— mock StoreLink API (FastAPI), standing in for the real Korral system during local dev.key_manager.py— loads per-storeX-Korral-Store-Keyvalues fromkeys.jsonand resolves store_id ↔ key.keys.json— store_id → key map (git-ignored; seeded with test keys for local dev)..env/.env.example—STORELINK_API_URLandSTORELINK_KEYS_FILEconfig.requirements.txt—mcp,fastapi,uvicorn,httpx,python-dotenv,pydantic.
Related MCP server: Tendem MCP
Running locally
pip install -r requirements.txt
# terminal 1: mock StoreLink API
uvicorn storelink:app --reload --port 8000
# terminal 2: MCP server (reads STORELINK_API_URL=http://localhost:8000/v1 from .env)
python server.pyTools exposed
check_stock_status(store_id, sku, fields=None)— on-hand units and/or recent sales for a SKU (fields: subset of["on_hand", "hours_of_stock_left"], defaults to both; field names match the result keys, and an unknown field is rejected with a clear error rather than silently ignored). Requestinghours_of_stock_leftreturnsunits_sold_last_24h,hourly_sales_rate, andhours_of_stock_left(all derived from trailing-24h POS).units_sold_last_24his returned explicitly so the "gap between on-hand and last 24h of sales" comparison a buyer makes is a direct subtraction, not something the agent has to reconstruct from the rate.hours_of_stock_leftisNonewhen there are no recent sales to project from.raise_replenishment(store_id, sku, quantity)— raises a replenishment order, returnsorder_idand status.get_replenishment_status(store_id, order_id)— looks up the status of a previously raised order.
StoreLink endpoints not exposed as tools
The mock implements the full StoreLink surface these tools need, but several endpoints from the spec are deliberately not wrapped as MCP tools at all:
Endpoint | Why it's not a tool |
| The agent operates on a |
| Same reasoning — store metadata (name, address, etc.) isn't needed to check stock or raise a reorder. |
| Only used internally to resolve a SKU's |
| Same as above — was only reachable via the SKU lookup, and had no other use. |
These aren't gaps — they're the API's general-browsing/reference endpoints, and the tool surface is intentionally narrowed to the three actions a buyer's agent actually needs: check status, reorder, track the order. If a future workflow needs store or supplier metadata, adding it back is a deliberate decision, not something we forgot.
Key decisions and tradeoffs
Only 3 tools, not a 1:1 wrapper of the StoreLink API. StoreLink exposes 8 endpoints (stores list, store detail, inventory, POS, replenishment create/status, SKU detail, supplier detail). We deliberately don't expose store list/detail, raw SKU lookup, or raw supplier lookup as tools — the agent's job is narrowly "is this SKU about to run out at this store, and if so, reorder it," not general StoreLink browsing. Fewer tools means a smaller, easier-to-reason-about surface for the agent and less risk of it wandering into unrelated data. Tradeoff: if a future workflow needs store metadata or supplier browsing, those tools don't exist yet and would need to be added deliberately (a feature, not a gap we forgot).
check_stock_status takes an optional fields list instead of being two separate tools. On-hand and hours-left both start from the same inventory lookup, and a caller sometimes only wants on-hand (cheap) without paying for the POS call (more expensive, more data). One tool with optional fields avoids duplicating the store/key/HTTP plumbing across near-identical tools, while still letting the caller avoid unnecessary calls.
Tradeoff: the tool's contract is slightly more complex than a plain single-purpose tool (caller needs to know the fields values), but this is a small, well-documented list.
Supplier lead-time enrichment (time_to_replenish) was scoped out. An earlier draft had check_stock_status also return the SKU's supplier lead time, so the agent could compare "hours left" vs. "time to replenish" and judge urgency in one call. We pulled it back out: the comparison logic (small gap between hours-left and lead-time ⇒ trigger reorder) is exactly the kind of decision that should stay explicit and reviewable rather than buried in a tool's return value, and until that policy is defined, a lead-time field would just be unused surface area on the tool.
Tradeoff: the agent (or buyer) currently has to know or separately determine supplier lead time to judge urgency — there's no shortcut for that yet. Revisit once the reorder-trigger policy is actually decided.
storelink.py is a real HTTP mock (FastAPI + uvicorn), not an in-process fake. server.py talks to it over httpx exactly as it would talk to the real StoreLink API, including the X-Korral-Store-Key auth header and per-store key validation (a mismatched key/store_id pair gets a 401). This exercises the real integration path (auth, HTTP errors, JSON shapes) rather than a shortcut that would need to be re-validated when pointed at the real API.
Tradeoff: more moving parts locally (two processes) than a pure in-memory fake.
Keys are per-store, loaded from keys.json, not baked into server.py. StoreLink keys are scoped to a single store and rotated weekly by Korral IT. key_manager.py centralizes key lookup so a key rotation only means updating keys.json, not code, and one MCP server instance can serve a buyer who covers multiple stores.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ilyadurov97/korral-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server