E-Commerce Support Agent MCP Server
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., "@E-Commerce Support Agent MCP ServerWhat's the status of my order #4521?"
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.
E-Commerce Support Agent
A harness-controlled, tool-connected, RAG-grounded customer support agent for a mock e-commerce company. It answers order-status, delivery, account, and policy questions by calling real (mock) tools and a real retriever — never by inventing an answer — and a Python harness, not the model, decides which tool call is actually allowed to run.
Prerequisites
Python 3.12
uv for dependency management — if it's not installed yet:
pip install uv(or see the link above for other install methods)An Anthropic API key
Related MCP server: Commerce Operations MCP Server
Setup
git clone <repo-url>
cd <the-folder-git-just-created>
uv sync
cp .env.example .envuv sync creates a .venv in the project folder and installs everything into it
automatically. Every command elsewhere in this README is prefixed with uv run,
which runs inside that .venv without needing it activated — but if you'd rather
activate it directly (e.g. to run python/streamlit without the uv run prefix):
# macOS/Linux
source .venv/bin/activate
# Windows (PowerShell)
.venv\Scripts\Activate.ps1
# Windows (cmd.exe)
.venv\Scripts\activate.batEdit .env:
ANTHROPIC_API_KEY=sk-ant-...
CLAUDE_MODEL=claude-sonnet-5 # any model your account can accessThe first run downloads the
sentence-transformers/multi-qa-MiniLM-L6-cos-v1 embedding model used
for policy retrieval — a few seconds, then cached locally — and creates
data/chroma_db/, the persisted vector index (gitignored; safe to
delete if you want to force a full re-index).
How to run it
Chat with the agent (start here):
uv run streamlit run app.pyPick one of the sample customers from the dropdown — their account status is shown, since a couple are deliberately flagged/suspended so you can demo how the agent handles that — and start chatting.
Or run one scenario at a time, no UI:
uv run python -m scripts.test_order_authorizationSee Verifying it works for the full list.
Run the MCP server standalone (for an MCP-compatible client, e.g. Claude Desktop):
uv run python -m src.mcp_serverProject structure
app.py Streamlit chat UI — login + chat, no business logic of its own
src/
agent.py CustomerSupportAgent — the harness loop + system prompt
auth_context.py AuthContext — the authenticated customer_id for a session
conversation_memory.py Short-term, in-process message history (last N turns)
llm.py Thin wrapper around the Anthropic Messages API
tools.py Data-access functions: orders, accounts, products
action_guard.py request_order_cancellation — ownership/state/confirmation checks
tool_registry.py Tool schemas (Claude tool-use format) + execute_tool() — the harness gate
policy_retriever.py Loads/chunks policies/*.md; hybrid retrieval — Chroma (dense/cosine) + BM25 (sparse), fused via Reciprocal Rank Fusion
policy_qa.py search_policies (tool-facing) + the grounding filter/thresholds
mcp_server.py FastMCP server exposing the same tools over stdio
support_session.py create_session / SupportSession — the boundary external callers use
logging_config.py Console + rotating-file logging setup
audit_logger.py Per-turn and per-tool-call log records
data/ Mock orders, accounts, products (JSON); chroma_db/ — persisted vector index, generated on first run, gitignored
policies/ 9 Markdown policy documents (chunked by "## " heading)
scripts/ Runnable scenarios and boundary checks (see Verifying it works)
logs/ Generated at runtime, gitignored
project_docs/ Deeper detail: architecture, security model, testing mapWhy I built the harness this way
The harness decides, not the model. Claude can only propose a
tool call (a name and arguments). tool_registry.execute_tool is the
only code path that actually runs one, and it always injects
authenticated_customer_id from the session's AuthContext — a value
Claude never sees as something it can set. An authorization bypass
here isn't a prompting problem to patch; there is no code path where
the model supplies whose data it's asking for.
Ticket-type scoping. The four ticket categories this project
scopes to (order status, delivery issues, refunds, subscription/account
questions) map directly onto the existing tool/retrieval surface,
rather than needing a separate classification step: order status and
delivery both resolve through lookup_order / list_customer_orders;
refund questions resolve through search_policies (actual refund
issuance — issue_refund — is explicitly out of scope for this
project); account questions resolve through check_account_status
for current state and search_policies for anything about why a
status exists or how to change it. I didn't add an explicit
classify-then-route stage because the four categories already have a
clean mapping onto tools Claude selects directly — an extra routing
layer would be one more place to misclassify without adding real
routing power at this scale.
One MCP permission-boundary decision. The in-process agent surface
and the MCP surface enforce ownership through the same underlying
checks (action_guard.py, tools.py), but they differ in where the
customer ID comes from. On the agent surface, AuthContext is set
once at session creation and every tool call gets
authenticated_customer_id injected by trusted code. On the MCP
surface, an external client has no AuthContext to inject from, so
customer_id is a plain tool argument instead — and the server logs
every call in full but does not itself verify that argument. I kept
this trust boundary explicit and visible (see
project_docs/02_security_and_authorization.md)
rather than either quietly inheriting the same gap on the trusted
surface, or building a fake auth layer for a single-process demo with
no real identity provider behind it.
Policy retrieval lives behind MCP, for governance and standardization,
not just convenience. search_policies is exposed as an ordinary tool
— identically from the in-process agent and from mcp_server.py —
rather than a Python-internal pre-fetch step. That means any
MCP-compatible client, not just this agent, can call the same governed
retrieval capability the same way, instead of every consumer
re-implementing the embedding/retrieval pipeline itself. The tradeoff
this creates — grounding is no longer a forced step — is real, and it's
what the next paragraph addresses.
Grounding is a checked guarantee, not just an instruction.
search_policies is a tool Claude decides to call — the system prompt
requires it before any policy answer, but a model can still skip it.
After the tool-use loop produces an answer with no further tool calls,
the harness re-runs the same local retriever directly against the raw
customer message before returning that answer; if it finds a strong
match and search_policies was never called that turn, the harness
forces one more loop iteration with a corrective instruction instead
of returning the ungrounded answer. This closes the main gap in
"the system prompt tells it to call the tool" — grounding no longer
depends entirely on the model remembering to.
Hybrid retrieval (Chroma + BM25), not a single similarity signal.
Policy chunks are embedded once and indexed in a persistent Chroma
collection (data/chroma_db/, cosine space) instead of an in-memory
array rebuilt on every start, and that dense ranking is fused with a
BM25 lexical ranking (rank_bm25) via Reciprocal Rank Fusion — dense
catches paraphrases with no shared words, BM25 catches exact terms dense
retrieval can blur past. The two rankings are fused by rank position, not
raw score, since cosine similarity and BM25 scores live on incompatible
scales. One consequence worth knowing: RRF's fused score reflects rank,
not calibrated relevance, so policy_retriever.retrieve() returns both
relevance_score (RRF, used for relative filtering) and
dense_similarity (raw cosine, used as the absolute floor that decides
whether to ground at all) — see policy_qa._filter_relevant_chunks. A
single RRF-based threshold can't reject an out-of-scope question, since
the top result always passes relative to itself; the absolute floor is
what actually enforces the honest-gap requirement.
Tools
Tool | Purpose | Auth model |
| Semantic search over policy documents | Not customer-scoped; Claude calls it on its own judgment before any policy answer |
| Status + delivery info for one order | Denies access if the order belongs to another customer |
| All orders for the authenticated customer | Same |
| Active / flagged / suspended / | Same |
| Stock quantity + availability | Not customer-scoped |
| Two-step guarded cancellation | Ownership + cancellable-state + explicit confirmation, all checked before anything is written to disk |
Every tool returns {"success": bool, ...}; failures carry an
error_code (ORDER_NOT_FOUND, ORDER_ACCESS_DENIED,
ORDER_NOT_CANCELLABLE, AUTHENTICATION_REQUIRED, etc.) so the agent
reacts to a stable code, not free-text error parsing.
Logging & observability
There's no logs/ folder in the repo — it's gitignored, and nothing
under it ships. It's created automatically the first time the app
runs: configure_logging() (src/logging_config.py) runs on first
import of audit_logger or policy_retriever, creates logs/ if it
doesn't already exist, and attaches handlers for two files, created
the same way:
logs/application.log— human-readable, one line per event (event=name key=value ...): startup, per-query retrieval performance, one line per conversation turn.logs/observability.log— full-detail JSON records, one per tool call and one per conversation turn, linked bysession_id. This is what makes RAG grounding traceable: everysearch_policiescall is logged with the exact chunk(s) retrieved (source, section, content, RRF relevance score, and dense-similarity score), not just a claim that retrieval happened.
Both files rotate at 5 MB (5 backups kept) so they don't grow
unbounded across a long session. Read observability.log with
uv run python -m scripts.view_logs (filters: --customer, --tool,
--failures, --type, --summary) rather than opening the raw file.
Verifying it works
Script | What it exercises | Needs |
| Full agent loop: cross-customer order access is denied | Yes |
| Full agent loop: | Yes |
| Full agent loop: guarded cancellation, with confirmation | Yes |
| Full agent loop: multi-turn follow-ups resolved from short-term memory | Yes |
|
| Yes |
| Claude calls | Yes |
|
| No |
|
| No |
| Policy retrieval/grounding in isolation, no LLM | No |
| MCP schema validation rejecting malformed/unexpected arguments, live | No |
| Lists the tools/schemas the MCP server registers | No |
| MCP | No |
| MCP's | No |
| Terminal viewer for | No |
Run any of them with:
uv run python -m scripts.test_order_authorizationNote: test_guarded_cancellation.py, test_agent_cancellation.py,
and test_mcp_cancellation.py all cancel a real order in
data/orders.json (ORD-1004). Re-running one after the first hits
ORDER_ALREADY_CANCELLED instead of the full confirm flow. Reset with
git checkout -- data/orders.json.
See project_docs/ for a deeper look at the architecture, the full security/authorization model, and a requirement-by-requirement testing map.
Known limitations
Long-term memory is not implemented. Short-term, in-conversation memory (
ConversationMemory) exists; a prior-ticket-history lookup keyed by customer ID does not. This is a known gap against the project's requirements, not a design choice — noted here rather than left silent.Conversation memory is in-process only — no persistence across runs.
The MCP surface trusts the calling client's
customer_idoutright. Every MCP call is logged in full, but logging isn't authentication.Policy grounding depends on two thresholds — an absolute dense-similarity floor and a relative RRF-score cutoff — both tuned against a handful of measured queries, not a systematic eval set (the absolute floor has been re-verified against the current hybrid scores; the relative cutoff is carried over from the pre-hybrid design and not yet re-measured). Accurate for the cases checked against; a differently-phrased edge case could still land on the wrong side of a cutoff.
No concurrency handling on the JSON data files — fine for a single local demo, not for concurrent writers.
Available Tools
6 toolscancel_orderA
Cancel an order belonging to a specific customer.
This is a state-changing operation, gated the same way as the in-process agent: the order must exist, must belong to customer_id, and must be in a cancellable state (Pending or Processing). Call with confirmed=False first to preview the result without cancelling anything; call again with confirmed=True only after the customer has explicitly confirmed that specific order.
The calling client remains responsible for authenticating the customer before invoking this tool.
| Name | Required | Description | Default |
|---|---|---|---|
| order_id | Yes | ||
| confirmed | Yes | ||
| customer_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the burden of disclosing behavior. It clearly states this is a state-changing operation, explains the confirmation flow prevents accidental cancellation, and explicitly notes the authentication responsibility. It also indirectly signals irreversibility by contrasting 'preview' with 'without cancelling anything.'
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 well-structured: a concise opening statement, then a logical flow covering preconditions, the two-step confirmation process, and the client's responsibility. Each sentence earns its place, and the formatting (paragraph breaks) aids readability without unnecessary verbosity.
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 tool's complexity (destructive state change, conditional gating, confirmation flow), the description covers all critical aspects: preconditions, cancellation states, preview/confirm workflow, and security responsibility. The presence of an output schema means return values need not be described, so the description is complete for safe and correct usage.
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?
Even though the input schema has no parameter descriptions (0% coverage), the description explains the semantics of all three parameters: order_id must exist and be cancellable, customer_id must own the order, and confirmed controls preview vs. actual cancellation. This adds substantial meaning beyond the bare 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 starts with a clear verb+resource: 'Cancel an order belonging to a specific customer.' It immediately distinguishes from sibling tools like lookup_order and list_customer_orders by emphasizing the cancellation action and the ownership constraint, leaving no ambiguity about the tool's purpose.
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?
Provides explicit when-to-use guidance: the order must exist, belong to customer_id, and be in a cancellable state (Pending or Processing). It also prescribes the two-step workflow (preview with confirmed=False, then confirm with confirmed=True) and clarifies that the client must handle customer authentication. This is strong, actionable usage direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_account_statusA
Retrieve the current status of a customer account.
This MCP-facing tool accepts a customer ID because an external MCP client does not share the local agent's AuthContext.
The calling client remains responsible for authenticating and authorizing the customer before invoking this tool.
| Name | Required | Description | Default |
|---|---|---|---|
| customer_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It adds the important fact that the tool does not share local AuthContext and that the client is responsible for authentication/authorization. However, it omits details like whether the operation is read-only, error behavior, or rate limits, so transparency is only partial.
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 concise and front-loaded with the purpose. The additional two sentences about AuthContext are relevant and add necessary context without being overly verbose. Structure is clean and readable.
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?
For a simple one-parameter tool with an output schema present, the description provides adequate context: it explains the purpose, the parameter's role, and the auth responsibility. It does not describe return values, but that is covered by the output schema. Some details like error conditions or example usage are missing, but overall it is sufficiently 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 0%, so the description must compensate. It effectively explains the meaning of customer_id by noting that external MCP clients must pass it because AuthContext is not shared. This adds rationale beyond the schema's bare type definition, though it doesn't specify format or constraints.
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 opens with a specific verb and resource: 'Retrieve the current status of a customer account.' This clearly distinguishes it from sibling tools (orders, product availability, policies) and leaves no ambiguity about its function.
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 when to use the tool by explaining that it accepts a customer ID because an external MCP client doesn't share AuthContext. However, it does not explicitly mention alternatives or conditions for when to prefer this tool over siblings, leaving usage guidance somewhat implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_product_availabilityA
Check whether a product is currently available and return its available stock quantity.
Use this when a customer asks whether a particular product is in stock.
The product ID is required.
| Name | Required | Description | Default |
|---|---|---|---|
| product_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of behavioral disclosure. It explains that it checks availability and returns stock quantity, which implies a read operation, but it does not disclose error handling, behavior when product is not found, or any side effects. This is minimal but not misleading.
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?
Three short sentences: the first states the core function, the second gives usage context, and the third states the required parameter. No fluff or repeated information.
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?
For a single-parameter tool with an output schema present, the description covers the purpose and when to use it. It lacks mention of edge cases or fallback behavior, but the simplicity and output schema lower the burden. It is nearly complete for its scope.
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?
The schema coverage is 0%, so the description must compensate. It only repeats that 'The product ID is required', adding no meaning about what the product ID represents, its format, or how to obtain it. This is redundant with the schema's required field.
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 states a clear verb ('check'), a specific resource ('product'), and the result ('available stock quantity'). It is easily distinguishable from sibling tools like check_account_status or list_customer_orders.
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 explicitly says 'Use this when a customer asks whether a particular product is in stock', which provides clear context. It does not mention alternatives or exclusions, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_customer_ordersA
List orders associated with a specific customer.
Use this when the customer wants to view their orders but has not provided one specific order ID.
The customer ID is required.
| Name | Required | Description | Default |
|---|---|---|---|
| customer_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
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 describes the operation as 'List' which implies read-only, but does not explicitly confirm no side effects, error behavior, or data safety. For a simple list operation, this is minimally adequate but lacks explicit transparency.
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?
Three concise sentences: first delivers the core purpose, second provides usage context, third emphasizes a requirement. No redundant words and information is front-loaded.
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?
For a simple one-parameter list operation with an output schema, the description covers the main use case and gives usage context. It could mention what happens when no orders exist or the customer is not found, but overall it is sufficiently complete given the tool's simplicity.
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?
Input schema has 0% description coverage, and the description only repeats that customer_id is required, which is already in the schema. It does not explain the format, domain, or source of the customer ID, adding minimal semantic value beyond the 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?
Description clearly states the tool lists orders associated with a specific customer, using a specific verb ('List') and resource ('orders'). It also distinguishes from sibling tools like lookup_order by noting it's for when no specific order ID is provided.
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 this when the customer wants to view their orders but has not provided one specific order ID.' This provides a clear use case and implicitly excludes lookup_order, offering strong guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lookup_orderA
Look up an order belonging to an authenticated customer.
Args: order_id: The order identifier, for example ORD-1002.
customer_id:
The authenticated customer identifier, for example CUS-002.Returns: Customer-safe order status and delivery information when the customer is authorized to access the order.
| Name | Required | Description | Default |
|---|---|---|---|
| order_id | Yes | ||
| customer_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of disclosing behavior. It adds an authorization constraint ('when the customer is authorized') and mentions 'customer-safe' output, which is useful. However, it does not describe what happens for unauthorized access, nonexistent orders, or confirm explicitly that the operation is read-only.
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 concise and well-structured with Args and Returns sections. Every sentence adds value, and there is no redundancy or filler.
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?
For a simple two-parameter lookup with an existing output schema, the description covers the essential context: what is returned (customer-safe order status and delivery info), the authorization requirement, and parameter examples. It omits failure modes, but the output schema likely handles return details, and the tool is straightforward.
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 0%, so the description must compensate. It provides example formats (ORD-1002, CUS-002) and clarifies that customer_id is the 'authenticated customer identifier,' adding meaning beyond the bare schema. It could be more explicit about the relationship between the two parameters but is adequate.
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 function with the verb 'Look up' and the resource 'an order belonging to an authenticated customer.' It distinguishes itself from siblings like list_customer_orders (which lists multiple orders) and cancel_order (which modifies state) by focusing on a single order lookup.
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?
No explicit guidance is given for when to use this tool versus alternatives. The description does not mention that this is for retrieving a specific order by ID when the customer is known, nor does it reference sibling tools such as list_customer_orders for batch scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_policiesA
Search company policy documents for text relevant to a question.
Args: query: A self-contained search query. Conversation history is not available on this surface, so include whatever context the search needs directly in the query text.
Returns: Matching policy chunks (source, section, content, relevance score) when found; grounded=False when nothing relevant enough was retrieved.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It explicitly describes the return value ('matching policy chunks') and the fallback behavior ('grounded=False when nothing relevant enough was retrieved'). This adds useful transparency beyond what a search tool would infer.
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 concise and well-organized into Args and Returns sections. Every sentence adds value, and there is no redundant or vague phrasing. It is a model of efficient documentation.
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 single parameter and existing output schema, the description is complete. It explains the purpose, the query construction, and the return behavior, including the grounded flag. No critical context is missing.
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?
The input schema only defines 'query' as a string, but the description compensates with detailed guidance: 'A self-contained search query. Conversation history is not available on this surface, so include whatever context the search needs directly in the query text.' This adds significant semantic meaning beyond the schema, so the parameter is fully explained.
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: 'Search company policy documents for text relevant to a question.' It uses a specific verb (search) and resource (policy documents) and distinguishes from sibling tools that handle customer orders and accounts.
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 provides clear usage context: it tells the agent to craft a self-contained query because conversation history is unavailable. While it doesn't explicitly name alternatives, the purpose and sibling list imply this is for policy searches only, so this counts as clear context without exclusions.
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. Dates show when Glama detected each change.
6 tool updates
v0.1.0- First observed
cancel_order - First observed
check_account_status - First observed
check_product_availability - First observed
list_customer_orders - First observed
lookup_order - First observed
search_policies
TDQS
Each tool targets a distinct resource and action: account status, list orders, product availability, specific order lookup, policy search, and order cancellation. There is no overlap or ambiguity between them.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., check_account_status, list_customer_orders, lookup_order). The style is uniform and predictable.
With 6 tools, the server is well-scoped for an e-commerce support agent, covering essential operations without unnecessary bloat or a thin surface.
The server covers the core support workflows: account status, order lookup and cancellation, product availability, and policy search. A minor gap is the lack of an order update or return tool, but these are often handled through separate processes.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Agentic commerce gateway: discovery, search, checkout across Shopify/Woo/Odoo/PrestaShop.
AI-powered commerce API for luxury skincare shopping. Enables AI agents to search products, browse collections, manage shopping carts, and generate checkout URLs for the Regenique Elegance Shopify store.
Agentic commerce with 58 MCP tools for product search, checkout, A2A negotiation, C-Suite analytics.
Hosted MCP for e-commerce: live product catalog, stock, and pricing for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables customer support across e-commerce platforms by providing order management, product guidance, and account assistance tools through natural language queries.5MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to independently investigate and resolve e-commerce order issues, particularly refund processing, with tools for order search, refund eligibility checks, and safe refund execution.-
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to check order statuses, retrieve FAQ policy answers via RAG, and create/manage support tickets, all based on the e-commerce support workflow in the repository.-
- FlicenseNot gradedqualityBmaintenanceEnables e-commerce customer service agents to retrieve product catalog and return/delivery policy documents through multi-source RAG with RRF fusion, exposing product_search and policy_qa tools for grounded, cited responses.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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/CuriousMonkey414/ecommerce-customer-support-agent'
If you have feedback or need assistance with the MCP directory API, please join our Discord server