invgate-mcp
A curated Model Context Protocol (MCP) serverthat exposes 12 read-only tools over stdio for InvGate 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 tokencache with a 60-second expiry buffer and one-shot 401 retry. - Validation: every tool input is validated with zod;invalid input returns a structured
validation_errorwithout calling the API. - Resilience: HTTP, auth, and network failures are converted to MCP textcontent with
isError: true— the server never crashes the host. - Distribution: published to npm, runnable via
npx invgate-mcp.
Install
# 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 exitswith code 1.
The OAuth2 token endpoint is derived from INVGATE_BASE_URL by stripping the/public-api/v2 segment and appending /oauth2/token/, sohttps://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):
{
"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 queryparameters. 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 thequery string (op examples: cont, eq, startswith, …).
Results & errors
- Success: the raw JSON response body, pretty-printed, as MCP
textcontent. - Errors: structured JSON
{ "error": "...", "message": "...", "status": ... }as text content withisError: true. Types:validation_error,auth_error,api_error,network_error.
Development
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