Skip to main content
Glama
cfollette18

mcp-epicor

by cfollette18
README.md
# Epicor MCP

Production [FastMCP](https://gofastmcp.com) server for **Epicor Kinetic**. **Read-only.** There are no write tools and the HTTP client rejects any method other than `GET`.

Auth follows the same split used by Azure MCP and Atlassian Rovo:

1. **Inbound** — the MCP client authenticates to this server (HTTP only).
2. **Outbound** — this server authenticates to Kinetic (`X-API-Key` plus Basic or Bearer).

HTTP is fail-closed without `MCP_JWKS_URI` or `MCP_JWT_SECRET`.

Author: **Clinton Follette**.

## Tools

| Tool | Access | Notes |
|---|---|---|
| `get_sales_order` | read | Header, `OrderDtls`, and `OrderRels`. Short-ship = `OurReqQty` vs shipped qty. |
| `get_customer` | read | By `CustNum` or `CustID`. |
| `get_part` | read | By `PartNum`. |
| `get_shipments` | read | `CustShipSvc/ShipDtls` pack lines. Never writes a pack. |

`$select` is always applied. The Kinetic Company id is configuration, not a tool argument.

## Install (local STDIO)

```json
{
  "mcpServers": {
    "epicor": {
      "command": "mcp-epicor",
      "env": {
        "EPICOR_BASE_URL": "https://your-server/kinetic",
        "EPICOR_COMPANY": "YOURCO",
        "EPICOR_API_KEY": "<key>",
        "EPICOR_USERNAME": "<user>",
        "EPICOR_PASSWORD": "<password>"
      }
    }
  }
}
```

```bash
pip install .
mcp-epicor
```

## Remote HTTP

```bash
export MCP_TRANSPORT=http
export MCP_HOST=127.0.0.1
export MCP_PORT=8002
export MCP_JWKS_URI=https://login.example.com/.well-known/jwks.json
export MCP_JWT_ISSUER=https://login.example.com
export MCP_JWT_AUDIENCE=mcp-epicor
mcp-epicor
```

Endpoint: `http://127.0.0.1:8002/mcp`. Health: `GET /health`.

## Outbound Kinetic configuration

| Variable | Required | Purpose |
|---|---|---|
| `EPICOR_BASE_URL` | yes | Kinetic origin |
| `EPICOR_COMPANY` | yes | Path segment in `/api/v2/odata/{Company}/...` |
| `EPICOR_API_KEY` | typical | `X-API-Key` |
| `EPICOR_USERNAME` / `EPICOR_PASSWORD` | or bearer | Basic auth |
| `EPICOR_BEARER_TOKEN` | optional | Alternative to Basic |

## Security

- No POST/PATCH/DELETE helpers exist on the client.
- HTTP without inbound JWT configuration refuses to boot.
- Vendor 401s do not echo credentials.

See [SECURITY.md](SECURITY.md).

## License

MIT. Copyright (c) 2026 Clinton Follette.

TDQS

B3.4/5.0

Scored across 4 tools

Disambiguation4/5

Each tool targets a distinct entity (sales order, customer, part, shipments), and descriptions clarify their purposes. get_shipments could be confused with get_sales_order since it retrieves order-related data, but the description explicitly distinguishes it as shipment pack lines.

Naming Consistency5/5

All tools follow a consistent get_ + noun snake_case pattern, making them predictable and easy to distinguish.

Tool Count3/5

Four tools is borderline thin for an ERP integration like Epicor Kinetic. While each tool is well-scoped, the set covers only a small fraction of typical ERP operations, suggesting under-scoping.

Completeness2/5

The surface is read-only with no create, update, delete, or list operations for any entity. This creates significant gaps for an agent that needs to perform common ERP tasks beyond fetching individual records.

Maintenance

ActivityMaintained
ResponsivenessNo issues