BSN Inventory 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., "@BSN Inventory MCPcheck inventory for BSN-12345"
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.
BSN Inventory MCP
Streamable HTTP MCP server for BSN SKU/material identification and inventory availability.
Setup
npm install
cp .env.example .envEdit .env before running. Keep secrets in .env or the parent shell, not in source files.
Required to start: set at least one inbound MCP bearer key:
BSN_MCP_API_KEY=
BSN_MCP_API_KEY_1=
BSN_MCP_API_KEY_2=Clients must send:
Authorization: Bearer <local_mcp_api_key>When the server is hosted behind Amazon Bedrock AgentCore Runtime with AWS_IAM,
SigV4 uses the Authorization header. In that case, configure a custom key
header and allowlist that header in the AgentCore runtime:
BSN_MCP_API_KEY_HEADER=X-Api-KeyBSN_MCP_API_KEY is kept as a legacy slot-1 alias. For key rotation, prefer numbered slots. The server accepts any configured value from BSN_MCP_API_KEY, BSN_MCP_API_KEY_1, or BSN_MCP_API_KEY_2.
Inventory lookup defaults to PROD. These values are required only when calling getInventoryAvailability:
BSN_INVENTORY_API_ENV=prod
BSN_API_BASE_URL_QA=https://api-qa.bsnsports.com:443
BSN_API_BASE_URL_PROD=https://api.bsnsports.com:443
BSN_INVENTORY_API_KEY_QA=
BSN_INVENTORY_API_KEY_PROD=
BSN_INVENTORY_API_KEY=
BSN_INVENTORY_RESPONSE_PAYLOAD_FORMAT=prettyBSN_INVENTORY_RESPONSE_PAYLOAD_FORMAT supports pretty and json. Use pretty by default because the server normalizes that payload into a complete color/size inventory matrix.
SKU/material identification uses local brand SKU catalogs in resources/skus/*.jsonl first. OpenAI file search is the fallback path when the local catalog has weak, ambiguous, or unavailable results. Set at least one OpenAI key before calling getVectorStoreFiles or before relying on vector fallback from identifySkuMaterial:
OPENAI_API_KEY=
OPENAI_API_KEY_1=
OPENAI_API_KEY_2=
OPENAI_SKU_VECTOR_STORE_IDS=
OPENAI_SKU_BRAND_VECTOR_STORE_IDS=
OPENAI_SKU_SEARCH_MODEL=gpt-5.5
OPENAI_SKU_SEARCH_MAX_OUTPUT_TOKENS=900OPENAI_SKU_SEARCH_MODEL is optional and defaults to gpt-5.5. Set it in .env to use a different model.
OPENAI_API_KEY is kept as a legacy slot-1 alias. For rotation, prefer OPENAI_API_KEY_1 and OPENAI_API_KEY_2. The server tries configured OpenAI keys in order and only falls back to the next configured key when OpenAI rejects the current key for authentication or authorization.
OPENAI_SKU_VECTOR_STORE_IDS is optional. When set, it scopes broad fallback SKU search and getVectorStoreFiles to those comma-separated vector stores. When unset, vector fallback from identifySkuMaterial discovers accessible completed OpenAI vector stores at runtime, and getVectorStoreFiles lists accessible stores from OpenAI. identifySkuMaterial also accepts per-call vectorStoreIds when a client needs to search a specific store such as SanMar.
OPENAI_SKU_BRAND_VECTOR_STORE_IDS is optional. When set, vector fallback from identifySkuMaterial routes a provided brand to that brand's vector store before broad env or discovery search. Use comma-separated brand=vectorStoreId entries, such as nike=vs_...,adidas=vs_...; use | inside one entry if a brand needs multiple stores. Fallback vector-store precedence is explicit vectorStoreIds, then brand route, then OPENAI_SKU_VECTOR_STORE_IDS, then OpenAI discovery.
The local SanMar JSONL catalog is searched as the distributor/multi-brand fallback. Include the SanMar sanmar_skus vector store as the OpenAI fallback for SanMar-sourced and SM* catalog families before using BSN Shop or web search as a last resort; pass its current vector store ID through identifySkuMaterial.vectorStoreIds when it was not already searched.
Related MCP server: Product MCP Server
Key Rotation
Use numbered key slots to rotate without interrupting users:
Put the current key in
BSN_MCP_API_KEY_1orOPENAI_API_KEY_1.Put the new key in
BSN_MCP_API_KEY_2orOPENAI_API_KEY_2.Update clients or the OpenAI project/provider side to use the new key.
Remove the old key after traffic has moved.
Optionally move the new key back to slot 1 before the next rotation.
The unnumbered BSN_MCP_API_KEY and OPENAI_API_KEY variables continue to work for existing installs. Avoid keeping different values in both legacy and numbered slot 1 longer than needed; leave only the active numbered slots after rotation.
Run
npm run devOr run compiled output:
npm run build
npm run startDefault MCP endpoint:
http://127.0.0.1:3100/mcpFor client-specific connection examples and hosted-client notes, see MCP_CLIENT_CONNECTIONS.md.
Source Layout
src/main.tsis the process entrypoint and owns startup validation pluslisten().src/http/app.tsowns the Streamable HTTP endpoint, bearer auth boundary, and per-request transport lifecycle.src/mcp/server.tscreates theMcpServerand registers resources, prompts, and config metadata.src/tools/registerInventoryTools.tsregisters the public MCP tools.src/inventory/,src/openai/,src/resources/, andsrc/prompts/contain the domain-specific helpers used by those tools.src/index.tsis import-safe and only re-exports modules for tests or local consumers.
Architecture
flowchart TB
Client["MCP Client"] -->|"POST /mcp<br/>Authorization: Bearer key"| App
subgraph Http["HTTP/Auth Boundary"]
App["Express MCP App<br/>src/http/app.ts"]
Auth["Bearer Auth<br/>src/auth/mcpAuth.ts"]
Reject["Unauthorized response<br/>no transport allocated"]
App --> Auth
Auth -->|"authorized"| Transport["Stateless Streamable HTTP Transport<br/>per request"]
Auth -.->|"missing/invalid bearer key"| Reject
end
subgraph Runtime["Per-request MCP Runtime"]
Server["McpServer<br/>src/mcp/server.ts"]
Tools["Public Tool Registration<br/>src/tools/registerInventoryTools.ts"]
Resources["Context Resources<br/>resources/ via BSN_RESOURCES_DIR"]
Prompts["Local Prompts<br/>prompts/"]
ApiConfig["api-config Resource<br/>runtime metadata"]
Server --> Tools
Server --> Resources
Server --> Prompts
Server --> ApiConfig
end
Transport --> Server
Config["Environment Config<br/>src/config/env.ts"] --> Auth
Config --> Resources
Config --> ApiConfig
Tools --> ReturnShape["MCP Tool Return<br/>concise text + structuredContent"]Tool Workflow
flowchart TB
Need["User needs SKU/material or inventory"] --> Known{"Exact material ID known?"}
Known -->|"yes"| InventoryTool["getInventoryAvailability"]
Known -->|"no"| IdentifyTool["identifySkuMaterial"]
IdentifyTool --> LocalSku["Local resources/skus JSONL lookup<br/>brand file first, SanMar fallback"]
LocalSku --> LocalCandidate{"Confident local candidate?"}
LocalCandidate -->|"yes"| Candidate
LocalCandidate -->|"no"| SearchScope["Resolve fallback vector scope<br/>explicit vectorStoreIds, brand route,<br/>OPENAI_SKU_VECTOR_STORE_IDS, or discovery"]
SanMar["SanMar sanmar_skus vector store<br/>distributor/multi-brand fallback where available"] -.-> SearchScope
SearchScope --> Responses["OpenAI Responses API<br/>file_search"]
Responses --> Candidate{"Usable SKU/material candidate?"}
Candidate -->|"yes"| InventoryTool
Candidate -->|"no"| LastResort["searchBsnShopLastResort<br/>returns host-agent instructions only"]
LastResort -.-> HostSearch["Host agent searches BSN Shop<br/>outside this MCP server"]
HostSearch --> ExactFound{"Exact material ID found?"}
ExactFound -->|"yes"| InventoryTool
ExactFound -->|"no"| AskUser["Ask user for SKU, material ID,<br/>product link, or clearer details"]
InventoryTool --> BsnApi["BSN Inventory API<br/>/v1/private/inventory-inquiry/{material_id}"]
BsnApi --> Normalize["Inventory Normalization<br/>src/inventory/normalize.ts"]
Normalize --> InventoryReturn["Inventory result<br/>structuredContent source of truth"]
VectorFiles["getVectorStoreFiles"] --> StoreScope["Explicit vectorStoreIds,<br/>OPENAI_SKU_VECTOR_STORE_IDS,<br/>or OpenAI discovery"]
StoreScope --> StoresApi["OpenAI Vector Stores API<br/>metadata only"]
StoresApi --> StoreReturn["Vector store/file metadata<br/>no file contents"]Dashed edges describe guidance or host-agent activity outside this MCP server process.
Tools
identifySkuMaterialgetVectorStoreFilessearchBsnShopLastResortgetInventoryAvailability
Use identifySkuMaterial when a user provides a natural-language product description, partial SKU, or uncertain style/color/size wording. It searches local brand JSONL catalogs in resources/skus first and returns immediately when the local candidate is confident. If local candidates are weak, ambiguous, or unavailable, it searches explicit vectorStoreIds, brand-routed vector stores, configured OpenAI vector stores, or discovered OpenAI vector stores and returns closest SKU/material candidates with evidence. It does not check live inventory.
Use getVectorStoreFiles to inspect accessible OpenAI vector stores and their attached vector store file metadata. It does not fetch file contents. It uses explicit vectorStoreIds input first, then OPENAI_SKU_VECTOR_STORE_IDS, then OpenAI vector store discovery.
Use searchBsnShopLastResort only when local SKU lookup and explicit, configured, or discovered vector-store search, including the SanMar distributor/multi-brand fallback where relevant, return no usable SKU/material candidates. It does not scrape or browse from the MCP server. It returns instructions for the host agent to search https://www.bsnsports.com/shop/, preserve exact product identifiers from matching products, resolve styles/SKUs to a material ID when needed, and then call getInventoryAvailability only after an exact material ID is found.
Use getInventoryAvailability only after the exact material ID is known. Pass optional color and size when the user asks for a specific variant quantity. It calls:
/v1/private/inventory-inquiry/{material_id}The text response contains a compact inventory summary and, when color, size, or a full material ID can identify a variant, the matched inventory cell. Matched cells include the split stock levels and combined total when available, for example Matched availability: available 1778, IP 1528, DS 250, total 1778. Agents should report IP and DS separately in addition to the combined total for inventory questions. If the upstream pretty payload only exposes segment-coded IP and DS rows, the normalizer maps them to ip and ds; when explicit available and total fields are absent and both values are numeric, it computes available and total as IP + DS. If the requested text does not match the inventory matrix labels, the matcher also tries color and size codes embedded in full material IDs such as NKCJ1611657LRG. structuredContent.data is the source of truth for normalized product, size, color, inventory-cell fields, and matchedAvailability.
Resources
Inventory-only context resources are exposed under:
context://bsn-inventory-mcp/resources/<relative-path>Use resources/instructions.md as the entry resource and resources/tool-map.md for the tool workflow. BSN_RESOURCES_DIR controls local context resources and the server-side resources/skus/*.jsonl SKU catalogs. Those SKU catalogs are searched before OpenAI vector stores; large JSONL files are intended for server-side lookup, not whole-file model context.
Secret-free runtime metadata is exposed under:
config://bsn-inventory-mcpThe config resource includes registered operations, prompt metadata, environment variable names, selected inventory environment, logging settings, local SKU catalog metadata, brand vector-store routing metadata, and vector-store discovery settings. It does not include credential values.
Prompts
Only inventory/SKU prompt templates belong in prompts/. check-inventory is the default prompt for inventory lookup.
Checks
npm run checkThe combined check runs:
npm run typecheck
npm run typecheck:test
npm test
npm run buildGitHub Actions runs npm ci and npm run check on pushes to main and pull requests.
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/aapatil67/inventory-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server