Skip to main content
Glama
Javiervalladares1

compu-ai-mcp

README.md
# compu-ai-mcp

MCP server for a **computer and electronics store**. It exposes the store's
commercial truth — catalogue, real stock, prices, promotions, instalment plans,
quotes, reservations and orders — as MCP tools backed by PostgreSQL.

The Model Context Protocol is implemented **directly over JSON-RPC 2.0**: no
MCP SDK is used, only the message exchange defined by the specification.

Built for **CC3067 Redes**, Universidad del Valle de Guatemala. Free to reuse.

## Why it is not a trivial server

- Every answer is a real SQL query against PostgreSQL; nothing is hard-coded.
- Prices are computed by applying the best **active** promotion at query time.
- Instalments are computed in integer cents, with the last payment absorbing the
  rounding remainder so the payments always add up exactly to the total.
- Reservations run inside a transaction with `SELECT ... FOR UPDATE`, so two
  concurrent callers cannot both take the last unit, and they are **idempotent**:
  repeating the same key returns the existing reservation instead of double booking.
- Turning a reservation into an order moves stock in both counters atomically.

## Requirements

- Node.js 20.6+
- Docker (for the bundled PostgreSQL) or any reachable PostgreSQL 14+

## Installation

```bash
git clone https://github.com/<user>/compu-ai-mcp
cd compu-ai-mcp
npm install
cp .env.example .env

npm run db:up      # PostgreSQL 17 in Docker, host port 5434
npm run db:setup   # creates the schema and loads the demo catalogue
npm run build
```

Verify it works, end to end, without any host or LLM:

```bash
npm run selftest
```

The self test walks the three business use cases (recommend, offer an
alternative when out of stock, quote → reserve → order) and checks the guard
rails. It prints `ALL CHECKS PASSED` when everything is fine.

Check that the server obeys the protocol:

```bash
npm run conformance
```

This one drives `dist/index.js` over real stdio pipes with a throwaway client —
deliberately not the project's own MCP client, so a bug present on both sides of
the connection cannot hide. It covers 28 checks: the handshake, version
negotiation and fallback, notifications going unanswered, correlation of
concurrent requests by `id`, string ids, the JSON-RPC error codes (`-32700`,
`-32601`, `-32602`), recovery from malformed input, business failures reported
as `isError` instead of protocol errors, and stdout carrying nothing but
protocol frames.

## Using it from an MCP host

The server speaks **stdio**: one JSON-RPC message per line on stdin/stdout.

### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "compu-ai": {
      "command": "node",
      "args": ["/absolute/path/to/compu-ai-mcp/dist/index.js"],
      "env": {
        "DATABASE_URL": "postgres://compu_ai:compu_ai_local_only@localhost:5434/compu_ai"
      }
    }
  }
}
```

### Any other host

```json
{
  "name": "compu-ai",
  "command": "node",
  "args": ["dist/index.js"],
  "cwd": "/absolute/path/to/compu-ai-mcp"
}
```

### By hand, to see the protocol

```bash
printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"demo","version":"1.0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
  '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"check_availability","arguments":{"sku":"LAP-ACR-A515"}}}' \
  | node dist/index.js
```

## Tools

| Tool | Reads / writes | Purpose |
|------|----------------|---------|
| `search_products` | read | Search the catalogue by text, category, brand, budget and stock |
| `get_product_details` | read | Specs, price, promotion, warranty and stock of one SKU |
| `check_availability` | read | Units really available (on hand − reserved) |
| `get_current_price` | read | List price, active promotion, final cash price, card price |
| `compare_products` | read | Compare 2–4 SKUs side by side |
| `recommend_alternatives` | read | Available substitutes in the same category and price range |
| `list_installment_plans` | read | Instalment plans that apply to an amount |
| `calculate_installments` | read | Exact monthly payment for a SKU under a plan |
| `create_quote` | **write** | Persist a quote and return its code |
| `reserve_item` | **write** | Hold units for a customer (idempotent, concurrency safe) |
| `release_reservation` | **write** | Return held units to stock |
| `create_order` | **write** | Turn a reservation into a confirmed order |
| `get_order_status` | read | Look up an order by code |
| `get_store_policies` | read | Hours, location, warranty, returns, shipping |

Full parameter-by-parameter specification with examples:
[`docs/specification.md`](docs/specification.md).

## Demo data

14 products across laptops, desktops, monitors, components and peripherals, with
prices in Guatemalan quetzales. Two products are deliberately **out of stock**
(`LAP-ASU-VB15`, `PER-HP-LJ107`) so a host can be shown offering alternatives,
and two carry an active promotion (`LAP-ACR-A515`, `MON-SAM-24F`).

Re-running `npm run db:setup` always rebuilds the same dataset.

## Configuration

| Variable | Default | Meaning |
|----------|---------|---------|
| `DATABASE_URL` | `postgres://compu_ai:compu_ai_local_only@localhost:5434/compu_ai` | PostgreSQL connection |
| `CURRENCY_SYMBOL` | `Q` | Symbol used when formatting money |

## Layout

```
db/schema.sql     tables (money stored in integer cents)
db/seed.sql       reproducible demo catalogue
src/index.ts      stdio loop: one JSON-RPC message per line
src/protocol.ts   initialize / tools/list / tools/call dispatch
src/tools.ts      the 14 tools and their SQL
src/money.ts      instalment maths in integer cents
src/db.ts         connection pool and transaction helper
src/selftest.ts   end-to-end check through the JSON-RPC layer
```

## Licence

MIT.

TDQS

A4.4/5.0

Scored across 14 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: searching, retrieving details, checking availability, getting price, comparing, recommending, listing plans, calculating installments, reserving, releasing, creating order, checking order status, getting policies, and creating quotes. No overlapping functionality is evident.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (e.g., search_products, get_product_details, reserve_item, create_order). The naming style is uniform and predictable.

Tool Count5/5

With 14 tools, the set is well-scoped for a store operation domain. It covers a broad range of customer and sales workflows without being excessive or sparse.

Completeness5/5

The tool surface covers the full lifecycle from product discovery (search, details, compare) to transactional actions (reserve, order, quote) and support (policies, installment plans). No critical gaps are apparent.

Maintenance

ActivityMaintained
ResponsivenessNo issues