{
  "markdown": "# mcp-itglue\n\n[![npm version](https://img.shields.io/npm/v/mcp-itglue)](https://www.npmjs.com/package/mcp-itglue)\n[![license: MIT](https://img.shields.io/npm/l/mcp-itglue)](LICENSE)\n\nAn MCP ([Model Context Protocol](https://modelcontextprotocol.io)) server for the [IT Glue](https://www.itglue.com/) API, built for MSPs that want AI assistants to read — and safely write — their documentation.\n\n- **Documents & sections** — list, read, create, update, publish, delete\n- **Flexible assets** — browse asset types and their fields, list/read/create/update/delete assets\n- **Attachments & images** — attach an image/file to any record from base64, a URL, or a local path; list and delete attachments\n- **Semantic vector search** — \"how do I remove a backup agent\" finds the Veeam decommissioning runbook, even when the words don't match (OpenAI or Azure OpenAI embeddings, local JSON index)\n- **Role-based access control** — viewer / editor / admin bearer tokens decide which tools each session can even see\n- **Bring your own key** — clients may supply their own IT Glue API key per session, so IT Glue's own permissions apply\n- **Index freshness** — IT Glue webhook, post-write self-refresh, and a manual refresh endpoint\n- **Transports** — stdio for local use, streamable HTTP for shared deployments; Docker image included\n\n## Installation\n\nYou need an IT Glue API key (IT Glue → Account → Settings → API Keys). Non-US accounts set `ITGLUE_REGION` to `eu` or `au`.\n\n### npx (recommended)\n\nClaude Desktop (`claude_desktop_config.json`) or Claude Code (`.mcp.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"itglue\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-itglue\"],\n      \"env\": { \"ITGLUE_API_KEY\": \"ITG.xxxx\" }\n    }\n  }\n}\n```\n\nClaude Code one-liner:\n\n```bash\nclaude mcp add itglue --env ITGLUE_API_KEY=ITG.xxxx -- npx -y mcp-itglue\n```\n\nClaude Desktop users can instead grab `mcp-itglue.mcpb` from the [latest release](https://github.com/mspstack/mcp-itglue/releases/latest) — open it with Claude Desktop and fill in the API key when prompted.\n\nstdio always runs with the full tool surface — it is a local, single-user transport using your own key.\n\n### Docker\n\nThe container image defaults to the HTTP transport (for [shared deployments](#http-deployment)):\n\n```bash\ndocker run --rm -p 3000:3000 \\\n  -e ITGLUE_API_KEY=ITG.xxxx \\\n  ghcr.io/mspstack/mcp-itglue\n```\n\nFor local stdio use under Docker:\n\n```json\n{\n  \"mcpServers\": {\n    \"itglue\": {\n      \"command\": \"docker\",\n      \"args\": [\"run\", \"-i\", \"--rm\", \"-e\", \"ITGLUE_API_KEY\", \"ghcr.io/mspstack/mcp-itglue\", \"--transport\", \"stdio\"],\n      \"env\": { \"ITGLUE_API_KEY\": \"ITG.xxxx\" }\n    }\n  }\n}\n```\n\n### From source\n\n```bash\ngit clone https://github.com/mspstack/mcp-itglue.git && cd mcp-itglue\nnpm install && npm run build\nITGLUE_API_KEY=ITG.xxxx node dist/index.js\n```\n\n## HTTP deployment\n\n```bash\nITGLUE_API_KEY=ITG.xxxx \\\nMCP_TOKENS_VIEWER=\"alice:$(openssl rand -hex 32)\" \\\nMCP_TOKENS_EDITOR=\"automation:$(openssl rand -hex 32)\" \\\nMCP_TOKENS_ADMIN=\"ops:$(openssl rand -hex 32)\" \\\nnpx -y mcp-itglue --transport http --port 3000\n```\n\nOr with Docker:\n\n```bash\ndocker run --rm -p 3000:3000 \\\n  -e ITGLUE_API_KEY -e MCP_TOKENS_VIEWER -e MCP_TOKENS_EDITOR -e MCP_TOKENS_ADMIN \\\n  ghcr.io/mspstack/mcp-itglue\n```\n\nEndpoints:\n\n| Route | Purpose |\n|---|---|\n| `POST/GET/DELETE /mcp` | MCP streamable-http endpoint |\n| `GET /health` | Liveness probe |\n| `POST /webhook/itglue` | IT Glue webhook → incremental index update |\n| `POST /index/refresh` | Manual index refresh (shared secret or admin token) |\n\n> Sessions are held in memory — run a single instance (or add sticky sessions) behind your load balancer.\n\n## Access control\n\n### Role tokens\n\nThree env vars hold comma-separated `label:token` lists:\n\n```bash\nMCP_TOKENS_VIEWER=\"alice:tokA,bob:tokB\"   # read-only tools\nMCP_TOKENS_EDITOR=\"hatz:tokC\"             # + create/update/publish, delete section\nMCP_TOKENS_ADMIN=\"ops:tokD\"               # + delete documents / flexible assets\n```\n\nClients authenticate with `Authorization: Bearer <token>`. The label appears in the audit log (`[rbac] session … for alice (viewer)`) and lets you revoke one person's token without rotating everyone's.\n\nTools a role cannot use are **not registered** for that session — a viewer doesn't even see `itglue_create_document` in `tools/list` — and a runtime guard re-checks the role on every call as defense in depth. Session ids never carry privilege: every request re-authenticates, and presenting a different principal against an existing session returns 403.\n\nIf **no** tokens are configured, the server runs in dev mode: all requests get admin access and a loud startup warning. Don't do this in production.\n\n### Bring your own IT Glue key (BYOK)\n\nClients may send their own IT Glue API key in the `x-itglue-api-key` header on the initialize request. The session then talks to IT Glue with **that** key and gets the full tool surface — IT Glue's own key permissions are the effective access control. `CLIENT_ITGLUE_KEYS` controls the policy:\n\n| Value | Behavior |\n|---|---|\n| `with-token` (default) | BYOK allowed, but a valid bearer token is still required — protects your server from being an open proxy |\n| `open` | An IT Glue key alone authenticates (trusted networks / local use) |\n| `disabled` | The header is rejected; only the server-wide key is used |\n\nWith BYOK enabled the server-wide `ITGLUE_API_KEY` becomes optional: sessions without a client key are rejected with a clear error. Client keys are never logged; sessions are bound to a SHA-256 hash of the key and audit-labeled `byok:<hash-prefix>`.\n\n## Tools\n\n| Tool | Tier |\n|---|---|\n| `itglue_list_organizations`, `itglue_get_organization` | read |\n| `itglue_list_documents`, `itglue_get_document` | read |\n| `itglue_list_document_folders` | read |\n| `itglue_list_document_sections`, `itglue_get_document_section` | read |\n| `itglue_list_flexible_asset_types`, `itglue_get_flexible_asset_type` | read |\n| `itglue_list_flexible_assets`, `itglue_get_flexible_asset` | read |\n| `itglue_list_attachments` | read |\n| `itglue_vector_search`, `itglue_vector_index_status` | read |\n| `itglue_create_document`, `itglue_update_document`, `itglue_publish_document` | write |\n| `itglue_create_document_section`, `itglue_update_document_section` | write |\n| `itglue_delete_document_section` † | write |\n| `itglue_create_flexible_asset`, `itglue_update_flexible_asset` | write |\n| `itglue_create_attachment` | write |\n| `itglue_build_vector_index` | write |\n| `itglue_delete_documents` | destructive |\n| `itglue_delete_flexible_asset` | destructive |\n| `itglue_delete_attachment` | destructive |\n| `itglue_find_endpoint`, `itglue_get` ‡ | read |\n\nViewer = read. Editor = read + write. Admin = everything.\n† Permanent, but editor-tier: editors need it to restructure documents and can already blank section content via update.\n‡ Advanced toolset (opt-in, off by default): `itglue_get` is a read-only GET passthrough for any API path the curated tools don't wrap, and `itglue_find_endpoint` searches a curated endpoint catalog. Enable with `ITGLUE_ADVANCED_TOOLSET=true` or `--advanced`. Password resources (`/passwords`) are hard-blocked — credential values never reach the model.\n\nVector tools appear only when an embedding provider is configured.\n\n## Vector search\n\nSet `OPENAI_API_KEY` (or `AZURE_OPENAI_API_KEY` + `AZURE_OPENAI_ENDPOINT`, where `EMBEDDING_MODEL` is your deployment name), then run `itglue_build_vector_index` per organization. The index is a JSON file at `VECTOR_INDEX_PATH` (default `./vector-index.json`) — on ephemeral hosts, point it at a persistent volume.\n\nThe index stays fresh three ways:\n\n1. **IT Glue webhook** — in IT Glue, webhooks are sent by **Workflows** (Admin → Workflows): add a *Document* trigger (created/updated) with a *Webhook* action. Workflow actions cannot send custom headers, so put the shared secret in the URL:\n\n   ```\n   https://<host>/webhook/itglue?secret=<ITGLUE_WEBHOOK_SECRET>\n   ```\n\n   and use a JSON payload template like:\n\n   | Key | Value |\n   |---|---|\n   | `event` | `[trigger_name]` |\n   | `resource_url` | `[resource_url]` |\n   | `resource_name` | `[resource_name]` |\n   | `organization_name` | `[organization_name]` |\n\n   The document id is parsed from `resource_url`; the trigger name maps to created/updated/deleted by keyword. Classic JSON:API-style payloads with an `x-itglue-webhook-signature` HMAC-SHA256 header are also accepted.\n2. **Self-refresh** — documents created/updated/published/deleted through this server's tools are re-indexed automatically in the background.\n3. **Manual refresh** — `POST /index/refresh` with `Authorization: Bearer <ITGLUE_WEBHOOK_SECRET>` (or an `x-refresh-secret` header, or an admin token). Body `{\"document_id\": \"123\"}` refreshes one document; an empty body re-crawls every indexed organization. Returns `202` and processes in the background.\n\n## Configuration reference\n\n| Variable | Default | Purpose |\n|---|---|---|\n| `ITGLUE_API_KEY` | — | Server-wide IT Glue API key |\n| `ITGLUE_REGION` | `us` | `us`, `eu`, or `au` |\n| `ITGLUE_BASE_URL` | per region | Override the API base URL |\n| `TRANSPORT` | `stdio` | `stdio` or `http` |\n| `PORT` | `3000` | HTTP port |\n| `MCP_TOKENS_VIEWER/EDITOR/ADMIN` | — | `label:token,label:token` per role |\n| `CLIENT_ITGLUE_KEYS` | `with-token` | BYOK policy: `disabled`, `with-token`, `open` |\n| `ALLOWED_ORIGINS` | — | Extra browser origins allowed on `/mcp` (comma-separated). Requests without an `Origin` header and localhost origins always pass; other browser origins are rejected with 403 |\n| `ITGLUE_ADVANCED_TOOLSET` | `false` | `true`/`1` registers the advanced toolset (`itglue_get`, `itglue_find_endpoint`) |\n| `ITGLUE_WEBHOOK_SECRET` | — | Webhook signature + `/index/refresh` secret |\n| `VECTOR_INDEX_PATH` | `./vector-index.json` | Vector index file |\n| `OPENAI_API_KEY` | — | Enables vector search (OpenAI) |\n| `AZURE_OPENAI_API_KEY` / `AZURE_OPENAI_ENDPOINT` / `AZURE_OPENAI_API_VERSION` | — | Enables vector search (Azure OpenAI) |\n| `EMBEDDING_MODEL` | `text-embedding-3-small` | Embedding model / Azure deployment |\n\nCLI flags `--transport`, `--port`, `--region`, `--base-url`, `--advanced` override the environment. Run `mcp-itglue --help` for details.\n\n## Notes & limits\n\n- IT Glue rate limit: 3000 requests / 5 minutes per key.\n- The IT Glue documents API is only partially documented; document/section endpoints follow observed API behavior.\n- Flexible-asset trait updates replace the whole traits object — the update tool's description warns the model to send all traits back.\n- List tools return summary fields per item (in both text and `structuredContent`) so default page sizes stay within client token limits; the `itglue_get_*` tools return the complete record.\n- IT Glue has no user impersonation: a given API key always acts as itself. RBAC here controls what *tool calls* a session may make; BYOK delegates to IT Glue's own key permissions.\n\n## Development\n\n```bash\nnpm install\nnpm run dev          # stdio via tsx\nnpm run dev:http     # http via tsx\nnpm test             # vitest\nnpm run build        # tsc → dist/\n```\n\n## Author\n\nBuilt by **Eugene Samotija** ([@selic](https://github.com/selic)) — [defency.net](https://defency.net).\nMore projects: [github.com/selic](https://github.com/selic) · [LinkedIn](https://www.linkedin.com/in/evghenii-samotiia)\n\n## License\n\n[MIT](LICENSE)\n",
  "bytes": 11404,
  "sha": "68c76a82b68324e4278029c19de507b06c73a03e0adf7e6727e1bad0e66c9103",
  "repo_slug": "mspstack/mcp-itglue",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_mspstack_mcp_itglue_3870afec/readme"
}