@erickwendel/ew-customers-mcp
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., "@@erickwendel/ew-customers-mcpFind the customer named Ana"
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.
@erickwendel/ew-customers-mcp
An MCP (Model Context Protocol) server that exposes a legacy customer CRUD REST API as tools, a resource, and a prompt β all runnable directly inside VS Code Copilot Chat.
This server is a thin adapter: it wraps the legacy nodejs-fastify-mongodb-crud API (Node/Fastify + MongoDB) over HTTP and does not modify it. The legacy API stays exactly as it is; only the MCP wrapper was ported from TypeScript to Python.
What it does
Capability | Name | Description |
π§ Tool |
| Lists all customers |
π§ Tool |
| Finds a customer by id, name, or phone |
π§ Tool |
| Creates a customer |
π§ Tool |
| Updates a customer's name and/or phone by id |
π§ Tool |
| Deletes a customer by id |
π Resource |
| Describes the legacy REST API this server wraps |
π¬ Prompt |
| Pre-built prompt that asks the agent to search a customer |
Related MCP server: sap-mcp-server
Architecture
src/customers_mcp/
domain/
customer.py # Pydantic models mirroring the legacy API's wire format
infrastructure/
customer_http_client.py # HTTP client for the legacy REST API
application/
customer_service.py # Business rules (find-by-any-field, delegates CRUD)
mcp/
server.py # Wires tools/resource/prompt onto a FastMCP instance
tools/ # One module per tool (SRP)
resources/
prompts/
__main__.py # Entry point β connects the server to stdio transport
tests/
conftest.py # Shared MCP client helper (async context manager)
test_customer_service.py # Unit tests (fake HTTP client, no network)
test_customer_tools.py # Integration tests via a real MCP stdio client
test_api_info_resource.py
test_find_customer_prompt.pyCustomerService receives its CustomerHttpClient via constructor injection (composed in mcp/server.py), so it can be tested in isolation with a fake client β no legacy API or network needed for test_customer_service.py.
Prerequisites
Python 3.12+
uv (recommended) or
pipThe legacy
nodejs-fastify-mongodb-crudAPI running athttp://localhost:9999(only needed to actually call the tools or run the integration tests β see that project'sdocker-compose.yml:npm run docker:infra:up)
Installation
uv syncUsing in VS Code
1. Add the MCP server configuration
Create (or open) .vscode/mcp.json in your workspace:
{
"servers": {
"customers-mcp": {
"command": "uv",
"args": ["run", "python", "-m", "customers_mcp"]
}
}
}2. Reload VS Code
Command Palette (Cmd+Shift+P) β Developer: Reload Window.
3. Use it in Copilot Chat
List all customersCreate a customer named "Ana" with phone "999-000-111"Find the customer named JohnRunning tests
uv run pytesttest_customer_service.py runs standalone (no dependencies). The other test files spawn the real MCP server and call the legacy API, so they require it running at http://localhost:9999 first.
Available commands
Command | Description |
| Start the server (used by MCP clients) |
| Run all tests |
| Lint |
| Format |
Available Tools
5 toolscreate_customerB
Create a customer
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Full name of the customer | |
| phone | Yes | Phone number of the customer |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | MongoDB ObjectId of the customer |
| isError | No | Indicates if an error occurred |
| message | No | Confirmation message |
| customer | No | The found customer |
| customers | No | List of customers |
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 only states the action and provides zero information about side effects, required permissions, error cases, or success behavior. There is no mention of what happens on duplicate names or how the response is structured (though output schema exists). This is a significant gap.
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 a single sentence with no filler or redundant information. It is front-loaded with the core action. However, it is so minimal that it could be considered under-specified rather than concise, so it earns a 4 rather than a 5.
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 create operation with an output schema, the description is minimally sufficient for an agent to know the core purpose. However, it lacks usage context and behavioral details that would help the agent decide when to use it and what to expect. An agent might call it without knowing potential failure modes or preconditions.
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 has 100% description coverage with clear parameter descriptions ('Full name of the customer' and 'Phone number of the customer'). The description does not add any meaning beyond the schema, but the baseline is 3 because schema already documents both parameters adequately.
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 'Create a customer' states a specific verb and resource. It distinguishes itself from sibling tools (list_customers, get_customer, delete_customer, update_customer) by indicating the create operation. However, it adds no nuance beyond the tool name, which slightly limits its clarity.
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?
Usage is implied by the verb 'create' β it is for adding a new customer. But there is no explicit guidance on when to use it vs alternatives, no prerequisites, and no mention of conditions like uniqueness checks. The agent must infer the intended use case from the tool name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_customerB
Delete a customer by their id
| Name | Required | Description | Default |
|---|---|---|---|
| customer_id | Yes | MongoDB ObjectId of the customer to delete |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | MongoDB ObjectId of the customer |
| isError | No | Indicates if an error occurred |
| message | No | Confirmation message |
| customer | No | The found customer |
| customers | No | List of customers |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must disclose behavioral traits. It only says 'Delete a customer' without indicating whether this is a hard delete, whether it's irreversible, what happens on missing id, or any side effects. The lack of such disclosure is a significant gap for a destructive operation.
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 a single, front-loaded sentence with no filler. It is concise and to the point, though it could benefit from additional context without becoming verbose.
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 presence of an output schema (not shown), the return value might be covered there, but the description does not explain error behavior, permanence, or prerequisites. For a delete operation, this is incompleteβespecially without annotations to carry the safety profile.
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 fully describes customer_id with 100% coverage. The description adds no extra meaning beyond 'by their id', which is redundant. Since schema coverage is high, the baseline of 3 applies, but the description contributes nothing beyond that.
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 the verb 'Delete', the resource 'customer', and the method 'by their id'. It clearly distinguishes from sibling tools (list, get, create, update) by specifying the destructive action.
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 usage is implied by the verb 'Delete' but there is no explicit guidance on when to use it versus alternatives, nor any mention of prerequisites or consequences. For example, it doesn't say 'use this to permanently remove a customer' or 'this cannot be undone'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_customerA
Find a customer by id, name, or phone number
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Full name of the customer | |
| phone | No | Phone number of the customer | |
| customer_id | No | MongoDB ObjectId of the customer |
Output Schema
| Name | Required | Description |
|---|---|---|
| customer | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description carries the burden of behavioral disclosure. 'Find' reasonably implies a read-only operation with no modification side effects, which is helpful. However, it does not clarify behavior when no parameters are passed, when multiple parameters are passed, or when no matching customer exists.
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 entire guidance is one efficient sentence with no filler. The action and the target identification method are immediately evident, making it easy to scan and parse.
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 lookup tool, the description conveys the essence, and the output schema covers return structure. Yet all three input parameters are optional, and the description never states that at least one should be provided or how multiple identifiers interact, leaving an important call-time gap.
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 baseline is 3. The description adds marginal value by framing the three properties as alternative search identifiers, but it does not explain whether they are mutually exclusive, combinable, or required, so it does not substantially improve on 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?
The description uses the specific verb 'find' and identifies the resource 'customer' plus the three lookup keys (id, name, phone). This clearly separates it from siblings like list_customers, create_customer, update_customer, and delete_customer.
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 phrase 'by id, name, or phone number' implies when it should be used: when you have a customer identifier and need that customer's record. It gives clear context but stops short of explicitly contrasting with list_customers or noting exclusions, so it does not reach the top tier.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_customersA
List all customers
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| customers | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It states only the basic action and provides no information about pagination, ordering, response structure, or potential performance implications. While it clearly implies a read operation, it does not add any behavioral context beyond what the name suggests.
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 a single, concise sentence with no redundant words. It is appropriately sized for a tool with no parameters and a straightforward purpose, making it easy for an agent to parse quickly.
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 simplicity of the tool (no parameters, clear purpose, and an output schema exists), the description is nearly complete. It states the core function, and the output schema covers return values. However, it could mention that it returns a list of all customers without pagination or any limits, but this is largely implicit. It is adequate but not exhaustive.
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 tool has zero parameters, and the schema is trivially 100% covered. Per the calibration baseline, a 0-parameter tool merits a 4. The description does not need to explain any parameters, and it does not add anything that conflicts with 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?
The description 'List all customers' uses a specific verb (list) and resource (customers), clearly distinguishing it from sibling tools that get, delete, create, or update a customer. It leaves no ambiguity about what action is performed.
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 tool's usage is implied by the name and description: it lists all customers, while siblings handle individual customer operations. However, there is no explicit guidance on when to choose this over get_customer or when a filter would be needed. The context is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_customerA
Update an existing customer's name and/or phone number by their id
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Full name of the customer | |
| phone | No | Phone number of the customer | |
| customer_id | Yes | MongoDB ObjectId of the customer |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | MongoDB ObjectId of the customer |
| isError | No | Indicates if an error occurred |
| message | No | Confirmation message |
| customer | No | The found customer |
| customers | No | List of customers |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral burden. 'Update' signals mutation and 'and/or' hints at partial updates, but the description does not disclose what happens when only customer_id is provided, whether omitted fields preserve their values or are set to null, or how missing IDs are handled. These are significant behavioral gaps for an update operation.
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?
A single, front-loaded sentence conveys the operation, target, and affected fields with no filler. Every word earns its place.
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?
The schema fully documents parameters and an output schema exists, so return-value details are not the description's job. However, the description leaves omitted-parameter semantics ambiguous and gives no guidance on edge cases, making it minimally adequate rather than 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 description coverage is 100%, so the schema already documents customer_id, name, and phone meaningfully. The description adds only that the named fields are the update targets and that the ID identifies the customer, which is a slight reinforcement but not substantial added 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?
The description uses a specific verb ('Update'), a clear resource ('existing customer'), and the exact fields affected ('name and/or phone number') plus the identifying mechanism ('by their id'). This fully distinguishes it from the create, delete, list, and get siblings.
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?
'Existing customer' clearly implies this tool is for customers that already exist, not for creation, and 'by their id' indicates the caller must know the target ID. It does not explicitly name alternatives or exclusions, but the context is strong enough for an agent to recognize when it applies.
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.
5 tool updates
v0.0.1- First observed
create_customer - First observed
delete_customer - First observed
get_customer - First observed
list_customers - First observed
update_customer
TDQS
Scored across 5 tools
Each tool has a clear, distinct purpose: list, get, create, update, and delete customers. No overlap or ambiguity between them.
All tools follow the consistent verb_noun pattern: list_customers, get_customer, delete_customer, create_customer, update_customer. Perfectly consistent.
With 5 tools, the set is well-scoped for a customers CRUD server. Each tool is necessary and none are redundant.
The tool set covers full CRUD operations (list, get, create, update, delete) for customers, missing only a bulk operation or search by multiple criteria, but agents can achieve most workflows.
Maintenance
Related MCP Connectors
List, read, edit, and deploy your GenMB AI-generated apps from any MCP client.
An MCP server that provides an API to LLMs to manage their JumpCloud resources.
API-first CRM for LLMs - contacts, companies, deals and activities over a native MCP server.
Remote MCP for 1,500+ APIs. Vault-managed credentials; OAuth or API key. Search, load, and execute.
Related MCP Servers
- FlicenseBqualityDmaintenanceMCP server for IBM Watson Orchestrate (WXO). Manage tools, agents, connections, flows, and execute tools from Cursor, VS Code Copilot, Claude Desktop, Antigravity, Windsurf, or the WxO Builder extension.35-
- FlicenseNot gradedqualityCmaintenanceEnables natural language querying of SAP business partner data by exposing OData APIs as MCP tools for LLM agents.-
- FlicenseNot gradedqualityCmaintenanceEnables natural language queries against uploaded OpenAPI/Swagger documentation via a hybrid RAG pipeline, providing grounded answers through MCP-compatible clients like VS Code Copilot.-
- AlicenseNot gradedqualityCmaintenanceEnables interaction with a REST API of customers through MCP tools, resources, and prompts, allowing listing, creating, retrieving, updating, and deleting customer records from MCP-compatible clients.5 npmISC