{"id":50339950,"url":"https://github.com/mguttmann/the-real-snipeit-mcp","last_synced_at":"2026-05-29T16:01:28.281Z","repository":{"id":360314839,"uuid":"1249542441","full_name":"mguttmann/the-real-snipeit-mcp","owner":"mguttmann","description":"MCP server for Snipe-IT REST API (100% coverage, hand-wrappers + codegen)","archived":false,"fork":false,"pushed_at":"2026-05-25T21:56:09.000Z","size":176,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T23:27:37.551Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mguttmann.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-25T20:14:17.000Z","updated_at":"2026-05-25T21:56:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mguttmann/the-real-snipeit-mcp","commit_stats":null,"previous_names":["mguttmann/the-real-snipeit-mcp"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mguttmann/the-real-snipeit-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mguttmann%2Fthe-real-snipeit-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mguttmann%2Fthe-real-snipeit-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mguttmann%2Fthe-real-snipeit-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mguttmann%2Fthe-real-snipeit-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mguttmann","download_url":"https://codeload.github.com/mguttmann/the-real-snipeit-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mguttmann%2Fthe-real-snipeit-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33659872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-29T16:01:27.236Z","updated_at":"2026-05-29T16:01:28.268Z","avatar_url":"https://github.com/mguttmann.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# the-real-snipeit-mcp\n\nMCP server for the [Snipe-IT](https://snipeitapp.com) REST API. 100 % endpoint coverage (read + write), hand-written wrappers for common workflows, codegen from the official OpenAPI 3.1 spec, stdio transport.\n\n**Three tool layers:**\n- **39 hand-wrappers** (`snipeit_*`) — friendlier UX for common workflows\n- **~145 auto-generated tools** (`snipeit_gen_*`) — 100 % endpoint coverage\n- **`snipeit_raw_request`** — escape hatch for any method/path\n\nPlus **3 resources**, **3 prompts**, and an MCPB bundle for one-click Claude Desktop install.\n\n---\n\n## Quick start\n\n```bash\nnpm install\ncp .env.example .env\n# edit .env: set SNIPEIT_API_TOKEN\nnpm run build\nnpm start\n```\n\nVerify the connection with the MCP Inspector:\n```bash\nnpm run inspector\n```\n\n## Configuration\n\n| Variable | Default | Description |\n|---|---|---|\n| `SNIPEIT_API_TOKEN` | (required) | Snipe-IT Personal API Token (JWT) |\n| `SNIPEIT_API_BASE` | `https://snipe-it.example.com/api/v1` | API base URL |\n| `SNIPEIT_CONFIRM_WRITES` | `false` | If true, destructive tools require `confirm: \"YES\"` |\n| `SNIPEIT_TIMEOUT_MS` | `30000` | Per-request timeout |\n| `SNIPEIT_LOG_LEVEL` | `info` | `debug` \\| `info` \\| `warn` \\| `error` |\n\n## Claude Desktop config\n\n```json\n{\n  \"mcpServers\": {\n    \"snipeit\": {\n      \"command\": \"node\",\n      \"args\": [\n        \"--env-file=/absolute/path/to/the-real-snipeit-mcp/.env\",\n        \"/absolute/path/to/the-real-snipeit-mcp/dist/index.js\"\n      ]\n    }\n  }\n}\n```\n\nOr install via the MCPB bundle: `npm run build:mcpb` → install the `.mcpb` file in Claude Desktop.\n\n---\n\n## Tool reference\n\n### Hand-wrappers (39 tools)\n\n#### Identity (1)\n\n| Tool | Endpoint | Annotations |\n|---|---|---|\n| `snipeit_me` | `GET /users/me` | readOnly |\n\n#### Hardware / Assets (13)\n\n| Tool | Endpoint | Annotations |\n|---|---|---|\n| `snipeit_list_hardware` | `GET /hardware` (paginated, common filters) | readOnly |\n| `snipeit_search_hardware` | `GET /hardware?search={query}` (convenience) | readOnly |\n| `snipeit_get_hardware_by_id` | `GET /hardware/{id}` | readOnly |\n| `snipeit_get_hardware_by_tag` | `GET /hardware/bytag/{tag}` | readOnly |\n| `snipeit_get_hardware_by_serial` | `GET /hardware/byserial/{serial}` | readOnly |\n| `snipeit_create_hardware` | `POST /hardware` | writeOnce |\n| `snipeit_update_hardware` | `PATCH /hardware/{id}` | writeIdempotent |\n| `snipeit_delete_hardware` | `DELETE /hardware/{id}` | writeIdempotent |\n| `snipeit_checkout_hardware` | `POST /hardware/{id}/checkout` (user/location/asset) | writeOnce |\n| `snipeit_checkin_hardware` | `POST /hardware/{id}/checkin` | writeOnce |\n| `snipeit_audit_hardware` | `POST /hardware/audit` | writeOnce |\n| `snipeit_list_audit_due` | `GET /hardware/audit/due` | readOnly |\n| `snipeit_list_audit_overdue` | `GET /hardware/audit/overdue` | readOnly |\n\n#### Users (5)\n\n| Tool | Endpoint | Annotations |\n|---|---|---|\n| `snipeit_list_users` | `GET /users` | readOnly |\n| `snipeit_get_user` | `GET /users/{id}` | readOnly |\n| `snipeit_get_user_assets` | `GET /users/{id}/assets` | readOnly |\n| `snipeit_get_user_accessories` | `GET /users/{id}/accessories` | readOnly |\n| `snipeit_get_user_licenses` | `GET /users/{id}/licenses` | readOnly |\n\n#### Licenses (3)\n\n| Tool | Endpoint | Annotations |\n|---|---|---|\n| `snipeit_list_licenses` | `GET /licenses` | readOnly |\n| `snipeit_get_license_seats` | `GET /licenses/{id}/seats` | readOnly |\n| `snipeit_checkout_license_seat` | `PUT /licenses/{license_id}/seats/{seat_id}` | writeIdempotent |\n\n#### Accessories / Consumables / Components (8)\n\n| Tool | Endpoint | Annotations |\n|---|---|---|\n| `snipeit_list_accessories` | `GET /accessories` | readOnly |\n| `snipeit_checkout_accessory` | `POST /accessories/{id}/checkout` | writeOnce |\n| `snipeit_checkin_accessory` | `POST /accessories/{id}/checkin` (pivot-id) | writeOnce |\n| `snipeit_list_consumables` | `GET /consumables` | readOnly |\n| `snipeit_checkout_consumable` | `POST /consumables/{id}/checkout` | writeOnce |\n| `snipeit_list_components` | `GET /components` | readOnly |\n| `snipeit_checkout_component` | `POST /components/{id}/checkout` (to asset) | writeOnce |\n| `snipeit_checkin_component` | `POST /components/{id}/checkin` (pivot-id) | writeOnce |\n\n#### Locations / Status-Labels / Maintenances (6)\n\n| Tool | Endpoint | Annotations |\n|---|---|---|\n| `snipeit_list_locations` | `GET /locations` | readOnly |\n| `snipeit_get_location` | `GET /locations/{id}` | readOnly |\n| `snipeit_list_statuslabels` | `GET /statuslabels` | readOnly |\n| `snipeit_get_statuslabel_assets` | `GET /statuslabels/{id}/assetlist` | readOnly |\n| `snipeit_list_maintenances` | `GET /maintenances` | readOnly |\n| `snipeit_create_maintenance` | `POST /maintenances` | writeOnce |\n\n#### Bulk \u0026 Escape (2)\n\n| Tool | Behavior | Annotations |\n|---|---|---|\n| `snipeit_bulk_checkout` | Serially checks out N assets, returns per-item success/error summary | writeOnce |\n| `snipeit_raw_request` | Any method/path against `SNIPEIT_API_BASE` — escape hatch | writeOnce (writeIdempotent for GET) |\n\n**List tools** (`snipeit_list_*`) accept `limit?`, `offset?`, and `all?: boolean`. With `all: true`, the tool auto-paginates up to 10 000 rows.\n\n### Auto-generated tools (`snipeit_gen_*`)\n\nAll 77 paths × every method in the Snipe-IT OpenAPI 3.1 spec are exposed as `snipeit_gen_\u003csnake_operation_id\u003e` — 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`.\n\n### `snipeit_raw_request`\n\nEscape hatch for anything else:\n```ts\n{ method: \"PATCH\", path: \"/locations/4\", body: { name: \"HQ\" } }\n```\nGET requests bypass the destructive-write guard; other methods honor `SNIPEIT_CONFIRM_WRITES`.\n\n---\n\n## Resources\n\n| URI | Description |\n|---|---|\n| `snipeit://me` | Current authenticated user (`GET /users/me`) |\n| `snipeit://settings` | Server settings (`GET /settings`) |\n| `snipeit://hardware/summary` | `{total, by_status_label, by_category}` — aggregated counts |\n\n## Prompts\n\n| Prompt | Args | Purpose |\n|---|---|---|\n| `snipeit-inventory-audit` | – | Lists overdue/due audits + unassigned assets, then summarizes |\n| `snipeit-user-onboarding` | `user_id`, optional `kit` | Suggests a checkout sequence for a new user |\n| `snipeit-license-health` | – | Seat usage + licenses expiring within 90 days |\n\n---\n\n## Workflows / Recipes\n\n### Onboard a new user with a laptop\n\n1. Confirm the user: `snipeit_get_user(id: 42)`\n2. Find an available laptop: `snipeit_list_hardware(category_id: 3, status_id: 5)` (ready-to-deploy)\n3. Checkout: `snipeit_checkout_hardware(id: 100, checkout_to_type: \"user\", assigned_user: 42, note: \"Onboarding 2026-05-25\")`\n\n### Bulk-checkout a kit to one user\n\n```json\n{\n  \"items\": [\n    { \"asset_id\": 100, \"checkout_to_type\": \"user\", \"assigned_user\": 42 },\n    { \"asset_id\": 101, \"checkout_to_type\": \"user\", \"assigned_user\": 42 },\n    { \"asset_id\": 102, \"checkout_to_type\": \"user\", \"assigned_user\": 42 }\n  ]\n}\n```\nContinues on per-item errors. Returns `{summary: {total, ok, errors}, results: [...]}`.\n\n### Audit overdue cleanup\n\n1. `snipeit_list_audit_overdue(all: true)` — full list, auto-paginated\n2. For each: `snipeit_audit_hardware(asset_tag: \"...\", location_id: 1, next_audit_date: \"2027-05-25\")`\n\n### Find an asset by tag or serial\n\n- By asset tag: `snipeit_get_hardware_by_tag(tag: \"A-42\")` (handles URL encoding)\n- By serial: `snipeit_get_hardware_by_serial(serial: \"SN12345\")`\n\n### Discover what an LLM can do\n\nBrowse the MCP Inspector:\n```bash\nnpm run build \u0026\u0026 npm run inspector\n```\n\n---\n\n## Write safety\n\nBy 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)`).\n\n## Snipe-IT API quirk\n\nSnipe-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.\n\n---\n\n## Develop\n\n```bash\nnpm run dev               # tsx watch\nnpm test                  # unit + integration if env present\nnpm run test:unit         # unit only (CI-safe)\nnpm run test:integration  # live; requires SNIPEIT_API_TOKEN in .env\nnpm run lint\nnpm run typecheck\nnpm run codegen           # regenerate src/tools/generated from vendor/snipe-it-rest-api.json\nnpm run refresh-spec      # pull latest OpenAPI spec from snipe-it.readme.io\nnpm run inspector         # MCP Inspector\nnpm run build:mcpb        # build .mcpb installable bundle\n```\n\nSee [`ARCHITECTURE.md`](./ARCHITECTURE.md) for the layer diagram and data flow. See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for adding hand-wrappers, regenerating the codegen layer, and debugging.\n\n## Security\n\n- API token is read from `SNIPEIT_API_TOKEN` env only. Never hard-coded. `.env` is git-ignored.\n- The logger redacts known secret patterns (Bearer tokens, JWTs, `api_token` fields, `Authorization` header) before any output.\n- All MCP stdio output goes to `stderr` only — `stdout` is reserved for the protocol.\n- **If your token has ever been pasted into a chat or commit, rotate it.**\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmguttmann%2Fthe-real-snipeit-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmguttmann%2Fthe-real-snipeit-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmguttmann%2Fthe-real-snipeit-mcp/lists"}