Skip to main content
Glama
wdelcant

invgate-mcp

by wdelcant
README.md
# invgate-mcp

A curated [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server
that exposes **12 read-only tools** over stdio for [InvGate Asset Management](https://www.invgate.com/asset-management).
Any MCP-compatible client (Claude Desktop, etc.) can query assets, people,
computers, servers, software, and API health through natural language.

- **Transport**: stdio only (the universal default for local agents).
- **Auth**: OAuth2 client-credentials flow (`scope=read`), in-memory token
  cache with a 60-second expiry buffer and one-shot 401 retry.
- **Validation**: every tool input is validated with [zod](https://zod.dev);
  invalid input returns a structured `validation_error` without calling the API.
- **Resilience**: HTTP, auth, and network failures are converted to MCP text
  content with `isError: true` — the server never crashes the host.
- **Distribution**: published to npm, runnable via `npx invgate-mcp`.

## Install

```bash
# Run without installing
npx invgate-mcp

# Or install globally
npm install -g invgate-mcp
invgate-mcp
```

## Configuration

The server reads three required environment variables at startup:

| Env var | Description | Example |
|---|---|---|
| `INVGATE_BASE_URL` | InvGate public API base URL (ends with `/public-api/v2`) | `https://acme.invgate.net/public-api/v2` |
| `INVGATE_CLIENT_ID` | OAuth2 client ID | `my-client-id` |
| `INVGATE_CLIENT_SECRET` | OAuth2 client secret | `my-client-secret` |

If any are missing the server prints a descriptive error to stderr and exits
with code 1.

The OAuth2 token endpoint is derived from `INVGATE_BASE_URL` by stripping the
`/public-api/v2` segment and appending `/oauth2/token/`, so
`https://acme.invgate.net/public-api/v2` → `https://acme.invgate.net/oauth2/token/`.

## Claude Desktop config

Add `invgate-mcp` to your `mcpServers` block
(`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "invgate": {
      "command": "npx",
      "args": ["-y", "invgate-mcp"],
      "env": {
        "INVGATE_BASE_URL": "https://acme.invgate.net/public-api/v2",
        "INVGATE_CLIENT_ID": "your-client-id",
        "INVGATE_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}
```

## Tools

| Tool | Input | Behavior |
|---|---|---|
| `invgate_list_asset_types` | _none_ | Returns all asset types |
| `invgate_list_assets` | `page`, `per_page`, `asset_type_id`, `criteria` | Paginated asset list with optional filters |
| `invgate_get_asset` | `asset_id` (required) | Single asset by ID |
| `invgate_list_people` | `page`, `per_page`, `criteria` | Paginated people list |
| `invgate_get_person` | `person_id` (required) | Single person by ID |
| `invgate_get_person_assets` | `person_id` (required), `page`, `per_page` | Assets assigned to a person |
| `invgate_list_computers` | `page`, `per_page`, `criteria` | Assets of type "computer" |
| `invgate_get_computer` | `asset_id` (required) | Single computer asset |
| `invgate_list_servers` | `page`, `per_page`, `criteria` | Assets of type "server" |
| `invgate_get_server` | `asset_id` (required) | Single server asset |
| `invgate_get_health` | _none_ | API connectivity status |
| `invgate_list_software` | `page`, `per_page`, `criteria` | Paginated installed-software catalog |

### Parameter mapping

Tool inputs use `snake_case`; the server maps them to the InvGate API query
parameters. `per_page` → `page_size`, `asset_type_id` → `asset_types`.
The `criteria` object maps to InvGate's nested syntax:
`{ "name": "cont:MacBook" }` becomes `criteria[name]=cont:MacBook` on the
query string (`op` examples: `cont`, `eq`, `startswith`, …).

### Results & errors

- **Success**: the raw JSON response body, pretty-printed, as MCP `text` content.
- **Errors**: structured JSON `{ "error": "...", "message": "...", "status": ... }`
  as text content with `isError: true`. Types:
  `validation_error`, `auth_error`, `api_error`, `network_error`.

## Development

```bash
npm install
npm run build       # tsup → dist/index.js (single ESM bundle)
npm run typecheck   # tsc --noEmit
npm test            # vitest run (59 tests, MSW for HTTP interception)
npm run test:coverage # vitest run --coverage (80% gate on src/**)
npm run dev         # tsx src/index.ts
```

Requires Node.js 20+ (uses native `fetch`).

## License

MIT

TDQS

A3.5/5.0

Scored across 12 tools

Disambiguation5/5

Each tool targets a distinct resource and action: get/list for assets, computers, servers, people, and specialized tools for asset types, software, and health. No overlapping purposes.

Naming Consistency5/5

All tools follow the consistent pattern 'invgate_<verb>_<noun>' with snake_case. Verbs are either 'get', 'list', or 'check', and nouns clearly identify the resource.

Tool Count5/5

12 tools is well-scoped for an asset management interface, covering the main entities and common operations without being excessive or sparse.

Completeness2/5

The tool set only provides read operations (get, list) and lacks any create, update, or delete capabilities. For a full asset management lifecycle, this is a significant gap, potentially causing agent failures when write operations are needed.

Maintenance

ActivityInactive
ResponsivenessNo issues