Skip to main content
Glama
willsu42
by willsu42

mcp-customer-server

A runnable MCP server (TypeScript, official @modelcontextprotocol/sdk) exposing two tools:

  • get_customer_record(customer_id: "CUST-XXXXX")

  • trigger_refund(customer_id: "CUST-XXXXX", amount: positive number, reason: string, min 10 chars)

Built to satisfy three things explicitly: strict input validation, standards-compliant JSON-RPC error mapping, and a hard guarantee that stdout carries nothing but protocol frames.

Setup

npm install
npm run build
npm start        # runs the server on stdio, waiting for JSON-RPC input

Related MCP server: customer-mcp

Design decisions

Low-level Server API, not the high-level McpServer helper. The high-level API is convenient but hides how validation failures get reported. Here, CallToolRequestSchema's handler validates arguments explicitly with Zod and throws McpError(ErrorCode.InvalidParams, ...) on failure. The SDK's protocol layer turns that into a real JSON-RPC error object (code: -32602) — not a "successful" tool result with an error message buried inside.

Protocol errors vs. tool-execution errors are kept separate on purpose:

  • Malformed input (wrong customer_id format, negative amount, short reason) → thrown as McpError → JSON-RPC error field, -32602 InvalidParams.

  • Valid input that fails for a business reason (customer not found, account suspended, refund exceeds balance) → returned as a normal tool result with isError: true. The request was well-formed; the outcome was a failure. Collapsing these two cases into one error path is a common MCP server mistake that breaks client-side retry logic.

  • Unexpected internal errors → logged in full to stderr, but the client only ever sees a generic InternalError — no stack traces or internals leak over the wire.

stdout isolation is enforced, not just followed by convention. src/logger.ts writes structured JSON logs to process.stderr exclusively, and lockdownConsole() monkey-patches console.log/.info/.debug at startup to redirect to stderr as well, so a stray debug statement (yours or a dependency's) can't silently corrupt the JSON-RPC stream on stdout.

Zod is the single source of truth for validation. zod-to-json-schema generates the inputSchema advertised in tools/list directly from the same Zod schemas used to validate incoming calls, so the two can't drift apart.

Verifying stdio isolation and protocol compliance

npm run test:stdio

This spawns the compiled server, drives it through a real initialize → tools/list → tools/call handshake over raw stdio, and asserts:

  • every line on stdout parses as JSON (fails loudly on the first non-JSON line)

  • an out-of-format customer_id and an invalid amount/reason all come back as error.code === -32602

  • valid calls succeed with no error field

  • log output was actually observed on stderr (proving separation, not just absence of failure)

Manual exploration with MCP Inspector

npx @modelcontextprotocol/inspector node build/server.js

Try:

  • get_customer_record with customer_id: "CUST-00001" → succeeds

  • get_customer_record with customer_id: "12345" → JSON-RPC error, -32602

  • trigger_refund with amount: -10 → JSON-RPC error, -32602

  • trigger_refund with reason: "no" → JSON-RPC error, -32602 (under 10 chars)

  • trigger_refund against CUST-00003 (seeded as suspended) → tool result with isError: true, not a protocol error

Mock data

Three customers are seeded in src/data.ts for demo purposes: CUST-00001 and CUST-00002 are active with balances; CUST-00003 is suspended, to exercise the business-logic error path.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for regulated enterprises, providing per-tool RBAC, redacted audit logging, and structured error handling. Exposes bank tools for customer lookup, statement search, and dispute resolution over stdio and HTTPS transports.
    MIT
  • F
    license
    B
    quality
    C
    maintenance
    Enables retrieval of customer records and triggering refunds via MCP tools, supporting both stdio and streamable HTTP transports.
    2
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP clients to discover and invoke tools for fictional customer lookup and simulated USD refunds, with strict argument validation, business-rule checks, and SQLite-backed audit persistence.
    -