Talk to Snipe-IT from Claude. Ask "show me all overdue audits", "check out laptop A-42 to manuel", "which licenses expire in the next 90 days" — and the LLM picks the right API call out of 183 tools. Read-and-write, with a safety gate for destructive operations and an envelope-aware client that never mistakes a Snipe-IT error for success.
A Model Context Protocol (MCP) server that exposes the entire Snipe-IT REST API to Claude (Desktop, Code, Agent SDK) over stdio. Built for IT asset managers who'd rather describe what they want than navigate a dashboard.
Three tool layers:
- 38 hand-wrappers (
snipeit_*) — friendlier UX for common workflows (checkout/checkin, audits, by-tag/by-serial lookup, bulk checkout) - ~145 auto-generated tools (
snipeit_gen_*) — full coverage of every operation in the OpenAPI 3.1 spec snipeit_raw_request— escape hatch for any method/path
Plus 3 resources (current user, settings, asset summary) and 3 prompts (inventory audit, user onboarding, license health).
Prerequisites: Node ≥ 20, a Snipe-IT instance you can reach (self-hosted or cloud), and an API token from User menu → Manage API Keys (docs).
npm install -g the-real-snipeit-mcpgit clone https://github.com/mguttmann/the-real-snipeit-mcp.git
cd the-real-snipeit-mcp
npm install
cp .env.example .env
# edit .env: set SNIPEIT_API_TOKEN and SNIPEIT_API_BASE for your instance
npm run build
npm start # ← stdio: this blocks; that's normal — your MCP client speaks JSON-RPC over stdin/stdoutVerify with the MCP Inspector (separate terminal):
npm run inspector
⚠️ TheSNIPEIT_API_BASEdefaulthttps://snipe-it.example.com/api/v1is an RFC 2606 reserved placeholder — it does not resolve. Set your own URL before running.
| Variable | Default | Description |
|---|---|---|
SNIPEIT_API_TOKEN |
(required) | Snipe-IT Personal API Token (JWT) |
SNIPEIT_API_BASE |
https://snipe-it.example.com/api/v1 |
API base URL |
SNIPEIT_CONFIRM_WRITES |
false |
If true, destructive tools require confirm: "YES" |
SNIPEIT_TIMEOUT_MS |
30000 |
Per-request timeout |
SNIPEIT_LOG_LEVEL |
info |
debug | info | warn | error |
{
"mcpServers": {
"snipeit": {
"command": "node",
"args": [
"--env-file=/absolute/path/to/the-real-snipeit-mcp/.env",
"/absolute/path/to/the-real-snipeit-mcp/dist/index.js"
]
}
}
}| Tool | Endpoint | Annotations |
|---|---|---|
snipeit_me |
GET /users/me |
readOnly |
| Tool | Endpoint | Annotations |
|---|---|---|
snipeit_list_hardware |
GET /hardware (paginated, common filters) |
readOnly |
snipeit_search_hardware |
GET /hardware?search={query} (convenience) |
readOnly |
snipeit_get_hardware_by_id |
GET /hardware/{id} |
readOnly |
snipeit_get_hardware_by_tag |
GET /hardware/bytag/{tag} |
readOnly |
snipeit_get_hardware_by_serial |
GET /hardware/byserial/{serial} |
readOnly |
snipeit_create_hardware |
POST /hardware |
writeOnce |
snipeit_update_hardware |
PATCH /hardware/{id} |
writeIdempotent |
snipeit_delete_hardware |
DELETE /hardware/{id} |
writeIdempotent |
snipeit_checkout_hardware |
POST /hardware/{id}/checkout (user/location/asset) |
writeOnce |
snipeit_checkin_hardware |
POST /hardware/{id}/checkin |
writeOnce |
snipeit_audit_hardware |
POST /hardware/audit |
writeOnce |
snipeit_list_audit_due |
GET /hardware/audit/due |
readOnly |
snipeit_list_audit_overdue |
GET /hardware/audit/overdue |
readOnly |
| Tool | Endpoint | Annotations |
|---|---|---|
snipeit_list_users |
GET /users |
readOnly |
snipeit_get_user |
GET /users/{id} |
readOnly |
snipeit_get_user_assets |
GET /users/{id}/assets |
readOnly |
snipeit_get_user_accessories |
GET /users/{id}/accessories |
readOnly |
snipeit_get_user_licenses |
GET /users/{id}/licenses |
readOnly |
| Tool | Endpoint | Annotations |
|---|---|---|
snipeit_list_licenses |
GET /licenses |
readOnly |
snipeit_get_license_seats |
GET /licenses/{id}/seats |
readOnly |
snipeit_checkout_license_seat |
PUT /licenses/{license_id}/seats/{seat_id} |
writeIdempotent |
| Tool | Endpoint | Annotations |
|---|---|---|
snipeit_list_accessories |
GET /accessories |
readOnly |
snipeit_checkout_accessory |
POST /accessories/{id}/checkout |
writeOnce |
snipeit_checkin_accessory |
POST /accessories/{id}/checkin (pivot-id) |
writeOnce |
snipeit_list_consumables |
GET /consumables |
readOnly |
snipeit_checkout_consumable |
POST /consumables/{id}/checkout |
writeOnce |
snipeit_list_components |
GET /components |
readOnly |
snipeit_checkout_component |
POST /components/{id}/checkout (to asset) |
writeOnce |
snipeit_checkin_component |
POST /components/{id}/checkin (pivot-id) |
writeOnce |
| Tool | Endpoint | Annotations |
|---|---|---|
snipeit_list_locations |
GET /locations |
readOnly |
snipeit_get_location |
GET /locations/{id} |
readOnly |
snipeit_list_statuslabels |
GET /statuslabels |
readOnly |
snipeit_get_statuslabel_assets |
GET /statuslabels/{id}/assetlist |
readOnly |
snipeit_list_maintenances |
GET /maintenances |
readOnly |
snipeit_create_maintenance |
POST /maintenances |
writeOnce |
| Tool | Behavior | Annotations |
|---|---|---|
snipeit_bulk_checkout |
Serially checks out N assets, returns per-item success/error summary | writeOnce |
snipeit_raw_request |
Any method/path against SNIPEIT_API_BASE — escape hatch |
writeOnce (writeIdempotent for GET) |
List tools (snipeit_list_*) accept limit?, offset?, and all?: boolean. With all: true, the tool auto-paginates up to 10 000 rows.
All 77 paths × every method in the Snipe-IT OpenAPI 3.1 spec are exposed as snipeit_gen_<snake_operation_id> — roughly 145 tools. Use these when the hand-wrapper layer doesn't cover what you need. Read tools have readOnlyHint: true; writes have destructiveHint: true. Regenerate with npm run codegen after npm run refresh-spec.
Escape hatch for anything else:
{ method: "PATCH", path: "/locations/4", body: { name: "HQ" } }GET requests bypass the destructive-write guard; other methods honor SNIPEIT_CONFIRM_WRITES.
| URI | Description |
|---|---|
snipeit://me |
Current authenticated user (GET /users/me) |
snipeit://settings |
Server settings (GET /settings) |
snipeit://hardware/summary |
{total, by_status_label, by_category} — aggregated counts |
| Prompt | Args | Purpose |
|---|---|---|
snipeit-inventory-audit |
– | Lists overdue/due audits + unassigned assets, then summarizes |
snipeit-user-onboarding |
user_id, optional kit |
Suggests a checkout sequence for a new user |
snipeit-license-health |
– | Seat usage + licenses expiring within 90 days |
- Confirm the user:
snipeit_get_user(id: 42) - Find an available laptop:
snipeit_list_hardware(category_id: 3, status_id: 5)(ready-to-deploy) - Checkout:
snipeit_checkout_hardware(id: 100, checkout_to_type: "user", assigned_user: 42, note: "Onboarding 2026-05-25")
{
"items": [
{ "asset_id": 100, "checkout_to_type": "user", "assigned_user": 42 },
{ "asset_id": 101, "checkout_to_type": "user", "assigned_user": 42 },
{ "asset_id": 102, "checkout_to_type": "user", "assigned_user": 42 }
]
}Continues on per-item errors. Returns {summary: {total, ok, errors}, results: [...]}.
snipeit_list_audit_overdue(all: true)— full list, auto-paginated- For each:
snipeit_audit_hardware(asset_tag: "...", location_id: 1, next_audit_date: "2027-05-25")
- By asset tag:
snipeit_get_hardware_by_tag(tag: "A-42")(handles URL encoding) - By serial:
snipeit_get_hardware_by_serial(serial: "SN12345")
Browse the MCP Inspector:
npm run build && npm run inspectorBy default, destructive tools execute directly. Set SNIPEIT_CONFIRM_WRITES=true and any write tool returns a redacted preview instead — re-invoke with confirm: "YES" to actually execute. Preview includes the full URL (apiBase + path) and a redacted body (password/secret/token/api_key fields replaced with (redacted)).
Snipe-IT often returns HTTP 200 with {"status":"error","messages":…} for validation errors. This server detects that envelope and surfaces the messages as a tool error (with isError: true), so callers never accidentally treat a Snipe-IT error as success. Successful envelopes ({"status":"success","payload":…}) are unwrapped automatically so tool data is the inner payload, not the outer wrapper.
npm run dev # tsx watch
npm test # unit + integration if env present
npm run test:unit # unit only (CI-safe)
npm run test:integration # live; requires SNIPEIT_API_TOKEN in .env
npm run lint
npm run typecheck
npm run codegen # regenerate src/tools/generated from vendor/snipe-it-rest-api.json
npm run refresh-spec # pull latest OpenAPI spec from snipe-it.readme.io
npm run inspector # MCP Inspector- API token is read from
SNIPEIT_API_TOKENenv only. Never hard-coded..envis git-ignored. - The logger redacts known secret patterns (Bearer tokens, JWTs,
api_tokenfields,Authorizationheader) before any output. - All MCP stdio output goes to
stderronly —stdoutis reserved for the protocol. - If your token has ever been pasted into a chat or commit, rotate it.
MIT.