Skip to main content
Glama
carmelocompiano

company-mcp-server

README.md
# company-mcp-server

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that connects AI assistants in Cursor (and other MCP hosts) to your company's REST API.

It handles token-based authentication, read-only lookups (account, centers, carriers), and guarded write operations (jobs, headers, packages with optional shipping-label PDFs).

This repo is a **generic template**: configure your API base URL, credentials, and path overrides via environment variables. No vendor-specific endpoints or secrets are baked in.

## Features

- **Stdio transport** — standard MCP integration for Cursor and Claude Desktop
- **Token-first auth** — login via env credentials; JWT passed to subsequent tools
- **Account vs. centers** — separate tools so agents don't mix up single-account data with location lists
- **Carrier discovery** — list carriers and services for job header payloads
- **Two job-creation flows**
  - **All-in-one** — single POST with full job body
  - **Header + packages** — create header first, then one or more packages
- **Shipping labels** — optional PDF download, local save, HTML viewer, and `file://` URL for Cursor's browser tools

## Requirements

- Node.js **16+**
- A REST API compatible with the expected request/response shapes (see [API paths](#api-paths))

## Quick start

```bash
git clone <your-repo-url>
cd company-mcp-server
npm install
cp .env.example .env
# Edit .env with your API base URL and credentials
npm run build
npm start
```

## Configuration

Copy `.env.example` to `.env` and set at least:

| Variable | Required | Description |
|----------|----------|-------------|
| `COMPANY_API_BASE_URL` | Yes | API origin, no trailing slash (e.g. `https://api.example.com`) |
| `COMPANY_API_USERNAME` | Yes | Username for the login tool |
| `COMPANY_API_PASSWORD` | Yes | Password for the login tool |
| `COMPANY_MCP_LABELS_DIR` | No | Directory for saved label PDFs (default: OS temp + `company-mcp-labels`) |

### API paths

Default relative paths (override with `COMPANY_API_PATH_*` if your backend differs):

| Env variable | Default |
|--------------|---------|
| `COMPANY_API_PATH_LOGIN` | `/auth/login` |
| `COMPANY_API_PATH_ACCOUNTS_ME` | `/accounts/me` |
| `COMPANY_API_PATH_CENTERS_ME` | `/centers/me` |
| `COMPANY_API_PATH_JOBS` | `/jobs` |
| `COMPANY_API_PATH_JOB_HEADERS` | `/jobs/headers` |
| `COMPANY_API_PATH_JOB_PACKAGES` | `/jobs/packages` |
| `COMPANY_API_PATH_WEB_CARRIERS` | `/carriers` |

Expected login response shape: `{ "data": { "token": "..." } }`.  
The token is sent in the `Authorization` header as-is (no `Bearer` prefix by default).

## Use with Cursor

Add to your MCP settings (`.cursor/mcp.json` or Cursor Settings → MCP):

```json
{
  "mcpServers": {
    "company-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/company-mcp-server/build/index.js"],
      "env": {
        "COMPANY_API_BASE_URL": "https://api.example.com",
        "COMPANY_API_USERNAME": "your-username",
        "COMPANY_API_PASSWORD": "your-password"
      }
    }
  }
}
```

Rebuild after source changes: `npm run build`.

In chat, mention `@company-mcp` to steer the agent toward these tools.

## Tools

| Tool | Type | Description |
|------|------|-------------|
| `company_auth_login` | Auth | Login; returns JWT |
| `company_accounts_me` | Read | Current account (`_id`, `uuid`, `name`) |
| `company_login_and_accounts_me` | Auth + read | Login + account in one step |
| `company_centers_me` | Read | List centers for authenticated account |
| `company_login_and_centers_me` | Auth + read | Login + centers in one step |
| `company_web_carriers` | Read | Carriers and services for job headers |
| `company_jobs_create_all_in_one` | Write | Create full job (single payload) |
| `company_jobs_headers_create` | Write | Create job header (header + packages flow) |
| `company_jobs_packages_create` | Write | Add package; optional label PDF |

Write tools are marked **destructive** in MCP annotations. The server instructions tell agents to ask for explicit user confirmation before creating or modifying data.

### Job creation flows

**All-in-one** — use `company_jobs_create_all_in_one` with a JSON `jobBody`.

**Header + packages**

1. `company_web_carriers` — resolve carrier `_id` and service `id`
2. `company_jobs_headers_create` — JSON `headerBody`
3. `company_jobs_packages_create` — one call per package; distinct `reference` per package

Do not mix both flows for the same user intent.

### Shipping labels

`company_jobs_packages_create` defaults to `requestLabel: true`. On success the server may:

1. Decode base64 `data.label` and write a PDF under `COMPANY_MCP_LABELS_DIR`
2. Generate a sibling HTML viewer
3. Attempt to open the viewer in the system browser
4. Return local paths and a `file://` URL for Cursor's Simple Browser or browser MCP

Set `requestLabel: false` only when the user explicitly does not want a label.

## Development

```bash
npm install
npm run build    # compile TypeScript → build/
npm start        # run MCP server on stdio
```

Project layout:

```
src/index.ts     # server, tools, API client helpers
build/           # compiled output (gitignored)
.env.example     # template env file (safe to commit)
```

## Security

- **Never commit** `.env` or real credentials (see `.gitignore`).
- Credentials are read only from the MCP process environment, not from tool arguments.
- Configure production vs. sandbox URLs via `COMPANY_API_BASE_URL` only — nothing is hardcoded.
- Review write-tool usage in your environment; agents should confirm before mutating data.

## License

MIT