Skip to main content
Glama
Rahul-Saini11

Haulistic MCP Server

README.md
# Haulistic MCP Server

Standalone proof-of-concept MCP server exposing read-only product resources for
one Haulistic organization. The organization is selected at startup with
`MCP_ORGANIZATION_SLUG`; clients cannot select or change it.

This POC intentionally has no user authentication. Anyone who can reach the MCP
endpoint can read the public catalog for the configured organization.

## Requirements

- Node.js 20+
- PostgreSQL connectivity to the Haulistic database
- A PostgreSQL login with read-only access

## Setup

```bash
cp .env.example .env
npm install
npm run dev
```

The server fails to start if `MCP_ORGANIZATION_SLUG` is missing, deleted,
deactivated, or does not exist.

## Endpoints

- `POST /mcp` — stateless MCP Streamable HTTP endpoint
- `GET /health` — database and configured-organization readiness check
- Other methods on `/mcp` return `405 Method Not Allowed`

The MCP server exposes these resource templates:

- `haulistic://products/catalog/{offset}/{limit}`
- `haulistic://products/by-name/{productName}`
- `haulistic://products/by-route/{productRoute}`

Only products that are active, listed, and not deleted are returned. Catalog
limits must be between 1 and 100. Name searches are case-insensitive partial
matches and return at most 20 products.

The MCP server also exposes these reusable prompts:

- `browse-product-catalog` — browse and summarize a catalog page
- `find-products-by-name` — find and present products matching a name
- `compare-products` — compare two products using their storefront routes

## Read-only database role

Use a separate database role for this service. The exact administration flow
depends on the deployment platform, but the privileges should be equivalent to:

```sql
CREATE ROLE mcp_reader LOGIN PASSWORD 'replace-with-a-secret';
GRANT CONNECT ON DATABASE haulistic TO mcp_reader;
GRANT USAGE ON SCHEMA public TO mcp_reader;
GRANT SELECT ON TABLE
  "Organization",
  "Products",
  "ProductRoutes",
  "ProductOption",
  "ProductOptionValue"
TO mcp_reader;
ALTER ROLE mcp_reader SET default_transaction_read_only = on;
```

The application also requests `default_transaction_read_only=on` for every
database connection and applies a configurable statement timeout. Database
permissions remain the primary security boundary.

## Build and run

```bash
npm run build
npm start
```

Or build the container:

```bash
docker build -t haulistic-mcp-server .
docker run --rm -p 8080:8080 --env-file .env haulistic-mcp-server
```

Deploy the service behind HTTPS, then configure the Claude custom connector with
the externally reachable endpoint, for example:
`https://mcp-poc.example.com/mcp`. A `PUBLIC_MCP_URL` environment variable is
not needed for this unauthenticated, stateless POC.

## POC boundaries

- No OAuth or other client authentication
- One organization per deployment
- Product resources only; no mutating tools
- Public product DTOs intentionally omit creator data, internal notes, draft and
  deleted products, integration configuration, and internal timestamps

Maintenance

ActivitySlowing
ResponsivenessNo issues