使用说明
🚀 Skills MCP GLPI v2.2
17 Production-Grade Tools (18 with the opt-in AI analysis) with 70-85% Token Efficiency and Enterprise-Grade Safety
Connect Claude Code, Gemini CLI, ChatGPT, VS Code Copilot, and Cursor to your GLPI instance
Why v2.0 • 17 Tools • Quick Start • Resources • Support
📖 About The Project
Skills MCP GLPI v2.2 is a production-ready Model Context Protocol (MCP) server for GLPI (IT Service Management) with a revolutionary token-optimization architecture. Built by Skills IT, this MCP consolidates 68 specialized tools into 17 active enterprise-grade tools (18 defined; the AI analysis tool is off by default) with Markdown responses, tool annotations, and MCP resources.
Compatible with GLPI 10.x (legacy API v1) and GLPI 11.x (current stable).
What's new in 2.2 (August 2026):
- ITIL beyond the ticket — problems, changes, projects, contracts and suppliers are now first-class, through
glpi_search_itil_recordsandglpi_manage_itil_records. - Free-criteria search —
glpi_search_records_by_criteriaqueries any itemtype, counts without paginating, and discovers which fields your instance actually exposes. - Filters people actually ask for — assigned technician, assigned group, requester and category, each accepting a name instead of forcing an id lookup first; plus urgency as its own axis,
open_only, and caller-controlled sorting. - 9 new ITIL actions on tickets — unified timeline, tasks, approvals, group assignment, ticket linking and file attachments.
- Correctness fixes for answers that looked right and were not — text search silently discarding the other filters, entity filters that never applied, and pagination reporting totals it never had. See CHANGELOG.md.
🌟 Why v2.0?
The v1.0 approach (68 tools, raw JSON responses) caused token explosion — typical GLPI queries consumed 50-100K tokens with limited reusability. v2.0 fixes this with a consolidated, Markdown-first design:
| Aspect | v1.0 | v2.2 |
|---|---|---|
| Tools | 68 fragmented | 17 consolidated ✨ |
| Response Format | Raw JSON (verbose) | Markdown (compact) ✨ |
| Token Efficiency | ~100K per operation | 15-30K per operation ✨ |
| Tool Annotations | None | Read-only & destructive hints ✨ |
| MCP Resources | 0 | 4 static resources ✨ |
| MCP Prompts | 15 templates | 15 professional prompts ✨ |
| Response Limits | default=50, max=1000 | default=10, max=50 ✨ |
| Estimated Savings | — | 70-85% token reduction ✨ |
🎯 Key Improvements
1. Consolidated Toolkit
- 17 active tools organized by domain (Tickets, ITIL, Assets, Admin, Webhooks, Knowledge, Bridge, Free-criteria search), plus the opt-in AI analysis tool
- search_ + manage_** pattern: Clear separation of read-only vs mutation operations
- Each tool handles 4-8 related operations, reducing context overhead
2. Token Efficiency (70-85% Reduction)
Markdown-formatted responses instead of JSON reduce token consumption dramatically:
- Before:
{"user":{"id":1,"name":"John","email":"john@example.com","created":"2025-01-22T10:30:00Z"}} - After:
👤 **John** (john@example.com) — Created Jan 22, 2025
3. Enterprise Safety
- Tool annotations for LLM safety (readOnlyHint, destructiveHint)
- Result limits per call (default=10, max=50), and a per-user rate limit (
RATE_LIMIT_REQUESTS_PER_MINUTE, default 60) - HTML stripping from GLPI TinyMCE fields
- Automatic internal field filtering
- Idempotent creates — repeating the same create does not create it twice
- Per-operation write policy plus a global read-only switch
4. MCP Resources & Prompts
- 4 MCP Resources: Entity list, ticket statuses, categories, priorities
- 15 MCP Prompts: 7 for IT managers, 8 for support analysts
- Enables advanced workflows without heavy tool definitions
5. Server-Side LLM Instructions
LLM receives usage guide automatically on initialization, ensuring optimal tool usage patterns.
6. Resilient Request Path
Every GLPI call goes through one point that applies timeout, retry with exponential
backoff and jitter, honours Retry-After on 429, and re-authenticates on 401.
Writes are never replayed once the server has answered. GLPI may have applied the write before failing, so a retry would create a second ticket or a duplicate followup. Only failures that provably happened before the request left the client (connection refused, connect timeout) and explicit throttling (
429, where the server refused without processing) are repeated.
7. Instance-Aware Field Resolution
Field names are resolved against your instance's own search-option catalogue and cached, so the same parameter works across installs that number fields differently. Static field maps are reconciled with the live catalogue at startup, and never block a search if the catalogue is unavailable.
🏗️ Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Claude / ChatGPT / Gemini / Copilot / Cursor │
└─────────────────────────────────────────────────────────────────┘
│
│ MCP Protocol (HTTP JSON-RPC)
▼
┌─────────────────────────────────────────────────────────────────┐
│ Skills MCP GLPI v2.2 Server │
│ localhost:8824 │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ FastAPI + Formatters │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │
│ │ │ 17 Tools │ │ 4 Resources │ │ 15 Prompts │ │ │
│ │ │ (Markdown) │ │ (Static URIs)│ │ (Parameterized) │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ │
│ │ ┌───────────────┬──────────────┬──────────────────────┐ │ │
│ │ │ HTML Stripper │ Field Filter │ Rate Limiter (10/50)│ │ │
│ │ ├───────────────┴──────────────┴──────────────────────┤ │ │
│ │ │ Write Policy · Idempotency · Retry (writes-safe) │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ GLPI REST API v1
▼
┌─────────────────────────────────────────────────────────────────┐
│ GLPI Server │
│ https://your-glpi-server.com │
└─────────────────────────────────────────────────────────────────┘
🚀 Quick Start
Prerequisites
- Python 3.11 or higher
- GLPI 10.x or 11.x with REST API enabled
- GLPI App Token and User Token (Personal Access Token)
Installation
# Clone the repository
git clone https://github.com/DevSkillsIT/Skills-MCP-GLPI.git
cd Skills-MCP-GLPI
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
GLPI Configuration
- Enable REST API: Setup > General > API — Check "Enable REST API"
- Create App Token: Setup > General > API > API Clients — Add and copy token
- Get User Token: Administration > Users > your user > Remote access keys — Generate token
Environment Setup
cp .env.example .env
nano .env
# .env
GLPI_BASE_URL=https://your-glpi-server.com
GLPI_APP_TOKEN=your_app_token_here
MCP_PORT=8824
MCP_HOST=0.0.0.0
MCP_SAFETY_GUARD=true
MCP_SAFETY_TOKEN=secure_token_min_8_chars
RATE_LIMIT_REQUESTS_PER_MINUTE=500
LOG_LEVEL=INFO
Start the Server
# Development
python -m uvicorn src.main:app --host 0.0.0.0 --port 8824 --reload
# Production (with PM2; the ecosystem file is environment-specific and not versioned here)
pm2 start ecosystem.config.cjs
Connect to Claude Code
Edit ~/.claude/settings.json:
{
"mcpServers": {
"glpi": {
"type": "streamable-http",
"url": "http://localhost:8824/mcp",
"headers": {
"X-GLPI-User-Token": "your_user_token_here"
}
}
}
}
Test Connection
curl http://localhost:8824/health
🧰 17 Tools (+1 opt-in)
🎫 Tickets (2 tools + 1 opt-in)
| Tool | Description |
|---|---|
glpi_search_helpdesk_tickets |
Search tickets/incidents/requests. Filters: status, priority, urgency, assigned_tech, assigned_group, requester, category (each by name or id), open_only, date range, sort_by/order |
glpi_manage_ticket_operations |
22 actions — get/get_by_number/create/update/delete/assign/assign_group/close/resolve/add_followup/add_task/add_document/link_tickets/request_validation/answer_validation/get_timeline/get_tasks/get_validations/get_followups/get_history/get_stats/find_similar |
glpi_manage_ticket_ai_analysis |
AI analysis: trigger/get_result/publish. Off by default — the service behind it is an in-memory stub with no GLPI-side agent, so it would report success without doing anything. Enable with ENABLE_AI_ANALYSIS=true once a real agent is wired in. |
🧩 ITIL (2 tools) — new in 2.2
| Tool | Description |
|---|---|
glpi_search_itil_records |
Search problems, changes, projects, contracts and suppliers (record_type). Filters: query, status, priority, urgency, category, entity, date range + date_field, sort, and count_only for a cheap total |
glpi_manage_itil_records |
CRUD + add_followup/get_followups/link_ticket across the same five record types |
🔍 Free-Criteria Search (1 tool) — new in 2.2
| Tool | Description |
|---|---|
glpi_search_records_by_criteria |
Query any itemtype with combined AND/OR criteria. scope=search returns rows, scope=count returns only the total (cheap probe), scope=fields discovers the filterable fields. Fields are given by name, not by id |
💻 Assets (2 tools)
| Tool | Description |
|---|---|
glpi_search_asset_inventory |
Search by scope (all, computers, monitors, software, devices, reservations, reservable, stats). Filters: assigned_user (name or id), status, location_id, manufacturer_id, plus sort_by/order |
glpi_manage_asset_operations |
CRUD + reservations: get/get_details (enriched with OS/disks/CPU/mem/net/software)/create/update/delete/get_reservations/create_reservation/update_reservation |
👥 Admin (2 tools)
| Tool | Description |
|---|---|
glpi_search_admin_resources |
Search users/groups/entities/locations by name and entity, with sort_by/order |
glpi_manage_admin_resources |
CRUD: get/create/update/delete for users, groups, entities, locations |
🔗 Webhooks (2 tools)
| Tool | Description |
|---|---|
glpi_search_webhook_integrations |
List/filter webhooks, delivery history, statistics |
glpi_manage_webhook_integrations |
CRUD + control: get/create/update/delete/test/trigger/enable/disable/retry |
📚 Knowledge (2 tools)
| Tool | Description |
|---|---|
glpi_search_knowledge_articles |
Search the native GLPI knowledge base via REST |
glpi_search_knowledge_unified |
Semantic (pgvector) + full-text search across resolved tickets, help articles and community posts, merged with RRF ranking. Each hit carries the resolution that was applied, so the caller does not have to open every result to learn what was done |
🌉 Bridge (4 tools)
| Tool | Description |
|---|---|
glpi_list_available_resources |
List 4 MCP resources with URIs |
glpi_read_resource_by_uri |
Read resource content (entities, statuses, categories, priorities) |
glpi_list_available_prompts |
List 15 professional MCP prompts |
glpi_get_prompt_template |
Execute specific prompt with arguments |
✨ What the New Capabilities Look Like
The whole ticket history in one call — followups, tasks, solutions and approvals interleaved chronologically, instead of four separate lookups:
{ "action": "get_timeline", "ticket_id": 542, "limit": 100 }
Assign to a group, by name — no id lookup, and an ambiguous name is refused with the candidate list rather than guessed:
{ "action": "assign_group", "ticket_id": 542, "group": "Infrastructure" }
Ask the questions people actually ask — filters take names, and text search combines with the other filters instead of replacing them:
{ "assigned_tech": "John", "open_only": true }
{ "query": "printer", "open_only": true, "urgency": 4 }
{ "sort_by": "date", "order": "asc" }
ITIL records beyond the ticket — contracts expiring soonest first:
{ "record_type": "contracts", "sort_by": "end_date", "order": "asc" }
Count without paginating — a cheap probe before deciding to fetch rows:
{ "record_type": "suppliers", "count_only": true }
{ "itemtype": "Computer", "scope": "count" }
Discover the fields your instance exposes — repeated labels are disambiguated by their source table, so the advertised id is the one the search will use:
{ "itemtype": "Ticket", "scope": "fields", "field_filter": "date" }
Then query anything with them:
{
"itemtype": "Ticket",
"scope": "search",
"criteria": [
{ "field": "name", "searchtype": "contains", "value": "backup" },
{ "field": "date", "searchtype": "morethan", "value": "2026-07-01", "link": "AND" }
],
"fields": ["id", "name", "status", "date"],
"sort_by": "date", "order": "desc"
}
📦 MCP Resources (4 Static URIs)
Access reference data via MCP resource protocol:
| Resource | URI | Content |
|---|---|---|
| Entities | glpi://entities |
Client/company list with IDs |
| Ticket Status | glpi://ticket-status |
Status code mapping (new, assigned, waiting, solved, closed) |
| Categories | glpi://ticket-categories |
Category tree (Hardware, Software, Network, etc.) |
| Priorities | glpi://priorities |
Priority levels (Very Low to Very High) |
Usage: Instead of searching for entity IDs, use glpi://entities resource to find correct ID.
📋 MCP Prompts (15 Templates)
IT Manager Prompts (7)
glpi_sla_performance— Monthly SLA dashboard with response times and complianceglpi_ticket_trends— Analyze ticket patterns by category over timeglpi_asset_roi— ROI analysis of assets per clientglpi_technician_productivity— Team productivity metrics and rankingsglpi_cost_per_ticket— Cost analysis and rentability reportsglpi_recurring_problems— Identify recurring issues for preventive actionglpi_client_satisfaction— NPS, CSAT, and SLA compliance scorecard
Support Analyst Prompts (8)
glpi_ticket_summary— Quick ticket summary for WhatsApp/Teamsglpi_user_ticket_history— User's complete ticket history and patternsglpi_asset_lookup— Rapid asset search by name, serial, or userglpi_onboarding_checklist— New employee IT onboarding checklistglpi_incident_investigation— RCA (Root Cause Analysis) templateglpi_change_management— Change request (RFC) workflow checklistglpi_hardware_request— Hardware request with approval workflowglpi_knowledge_base_search— Intelligent knowledge base lookup
💡 Usage Examples
# Search for tickets
GLPI, list all open tickets with high priority
# Quick asset lookup
GLPI, search equipment for user John Smith
# Get resource data
Use the glpi://entities resource to find entity IDs
# Execute prompt
GLPI, use glpi_sla_performance for last 30 days analysis
⚠️ Known Limitations & Security Notes
Read this before trusting any protection described further down. Implemented is not the same as active — two of the safeguards below are opt-in and do nothing until configured.
The confirmation guard is opt-in and OFF by default
Destructive operations (deleting tickets, assets, users, groups, locations,
webhooks and ITIL records) are wired to a confirmation guard that demands a token
and a written reason. It only runs when MCP_SAFETY_GUARD=true.
With the variable unset — the default — a delete call reaches GLPI with no confirmation at all. Verified against a live instance: a delete for a non-existent id returned "not found" from GLPI, meaning the request went through. If the id had existed, the record would be gone.
With MCP_SAFETY_GUARD=true (and a MCP_SAFETY_TOKEN of at least 8 characters) every
delete in every manage tool — tickets, assets, users, groups, locations, webhooks and
ITIL records — is refused until the call also carries confirmation_token (equal to
MCP_SAFETY_TOKEN) and reason (at least 10 characters). Both fields are declared in the
input schema of each of those tools. The camelCase spelling confirmationToken is still
accepted. A test enumerates every delete action in the tool definitions and drives it
guard-on: refused without a token, accepted with a valid one.
The write policy (GLPI_READ_ONLY, GLPI_ALLOW_<OPERATION>) is independent and
always active, and every delete operation defaults to disabled there. That is the
protection you actually get out of the box; the guard adds the human challenge on
top of it.
Knowledge base search does not derive the tenant from the token
glpi_search_knowledge_unified filters by client only when the caller passes
tenant. It is not inferred from the user token, unlike every other tool, where
the token fixes the scope.
If a single vector store holds documents ingested from more than one client, a
caller can read solutions belonging to another client. Either keep one store per
client, or always pass tenant. This is a design gap, not a bug report — it has
not been reproduced against a multi-client store.
Search options are cached per process, not per user
Field labels come from whichever session populates the cache first, and last for an hour. Two users on different languages or profiles can therefore see the same label set. Only labels are shared — never record data — but resolution by translated label may behave inconsistently across users. Resolution by canonical name and by numeric id is unaffected.
Never put a user token in the server configuration
GLPI_USER_TOKEN exists as a development fallback. Setting it in a deployment
that serves real users makes the server accept calls without any identity,
using that person's permissions and recording their name as the author of every
write. It defeats both the isolation between clients and the audit trail. Pass
the token per call, via the X-GLPI-User-Token header.
🛡️ Enterprise Features
Tool Annotations
All tools include safety hints for LLM reasoning:
{
"name": "glpi_manage_ticket_operations",
"annotations": {
"readOnlyHint": false,
"destructiveHint": true,
"idempotentHint": false,
"openWorldHint": true
}
}
Result Limits
- Default: 10 results per call
- Maximum: 50 results per call
- Prevents context overflow and token waste
- Rate limiting is separate:
RATE_LIMIT_REQUESTS_PER_MINUTE(default 60) applies per user token and client address. Calls from localhost are exempt. The counter includes every internal GLPI call, so one report prompt can consume many units
HTML Stripping
GLPI TinyMCE fields automatically converted to plain text:
Before: "<p>Issue started <b>yesterday</b> morning</p>"
After: "Issue started yesterday morning"
Field Filtering
Internal GLPI fields automatically removed:
Removed: _links, links, completename, etc.
Kept: user-facing fields only
🔄 Migration
From v2.1 to v2.2
No breaking changes. Every v2.1 call keeps working. What changed is additive:
- Three new tools (
glpi_search_itil_records,glpi_manage_itil_records,glpi_search_records_by_criteria). - New optional parameters on the existing search tools; omitting them preserves the previous behaviour.
- Nine new actions on
glpi_manage_ticket_operations.
Two behavioural corrections are worth knowing, because the previous answers were plausible and wrong:
- Text search now respects the other filters. A call combining
querywithstatus,priorityor a date range previously returned results ignoring those filters. The same call now returns fewer, correct rows. querysearches title and content. It previously matched the title only, so searching for an error message returned "none found" as if that were a fact.
From v1.0
v2.x consolidates 68 fragmented tools into 17 active tools (18 defined, one opt-in):
Key Changes:
- Use
glpi_search_*for read-only operations (searches, lists, lookups) - Use
glpi_manage_*for mutations (create, update, delete, assign) - Response format is Markdown instead of JSON
- Limits are aggressive (default=10, max=50) to prevent token waste
- Tool annotations guide LLM for optimal usage
💼 Need Help with GLPI or AI?
Skills IT - Technology Solutions specializes in IT infrastructure and has deep expertise in GLPI IT Service Management. Our team has expertise in Artificial Intelligence and Model Context Protocol (MCP), offering complete solutions for automation and system integration.
Our Services:
- ✅ GLPI consulting and implementation
- ✅ Custom MCP development for your infrastructure
- ✅ AI integration with corporate systems
- ✅ Ticket and asset management automation
- ✅ Specialized training and support
📞 WhatsApp/Phone: +55 63 3224-4925 - Brazil 🇧🇷 🌐 Website: skillsit.com.br 📧 Email: contato@skillsit.com.br
"Transforming infrastructure into intelligence"
⚙️ Configuration
Per-User Authentication
Each user configures their own X-GLPI-User-Token:
- Access GLPI with your credentials
- Go to Preferences (top right corner)
- In Personal access token, click Regenerate
- Copy the generated token
Environment Variables
Core
| Variable | Required | Description |
|---|---|---|
GLPI_BASE_URL |
Yes | GLPI server URL |
GLPI_APP_TOKEN |
Yes | GLPI App Token |
MCP_PORT |
No | Server port (default: 8824) |
MCP_HOST |
No | Server host (default: 0.0.0.0) |
MCP_SAFETY_GUARD |
No | Enable delete protection (default: false) |
MCP_SAFETY_TOKEN |
Conditional | Confirmation token if Safety Guard enabled |
RATE_LIMIT_REQUESTS_PER_MINUTE |
No | Rate limiting (default: 60) |
LOG_LEVEL |
No | Logging level (default: INFO) |
ENABLE_AI_ANALYSIS |
No | Registers glpi_manage_ticket_ai_analysis (default: false). See the Tickets section |
Request resilience
| Variable | Default | Description |
|---|---|---|
CONNECTION_TIMEOUT |
30 |
Connection timeout (seconds) |
REQUEST_TIMEOUT |
60 |
Request timeout (seconds) |
GLPI_MAX_RETRIES |
2 |
Retries only — 2 means up to 3 calls in total |
GLPI_RETRY_BACKOFF_BASE |
1.5 |
Exponential backoff base |
GLPI_RETRY_BACKOFF_CAP |
20.0 |
Backoff ceiling (seconds) |
MAX_CONNECTIONS |
20 |
Pool size |
MAX_KEEPALIVE_CONNECTIONS |
10 |
Keep-alive connections |
Write policy — reads are never affected.
| Variable | Default | Description |
|---|---|---|
GLPI_READ_ONLY |
false |
Global read-only mode: blocks every write |
GLPI_ALLOW_<OPERATION> |
see below | One switch per write operation |
The per-operation name is GLPI_ALLOW_ + the operation uppercased with . replaced by
_ (e.g. ticket.create → GLPI_ALLOW_TICKET_CREATE). Non-destructive operations
default to enabled; every delete operation defaults to disabled and must be
turned on explicitly: GLPI_ALLOW_TICKET_DELETE, GLPI_ALLOW_ASSET_DELETE,
GLPI_ALLOW_USER_DELETE, GLPI_ALLOW_GROUP_DELETE, GLPI_ALLOW_LOCATION_DELETE,
GLPI_ALLOW_WEBHOOK_DELETE, GLPI_ALLOW_PROBLEM_DELETE, GLPI_ALLOW_CHANGE_DELETE,
GLPI_ALLOW_PROJECT_DELETE, GLPI_ALLOW_CONTRACT_DELETE, GLPI_ALLOW_SUPPLIER_DELETE.
A blocked write returns an error naming the variable to set — never a silent success.
Values are read at startup; changing them needs a restart.
ITIL deletion is gated per record type: allowing a problem to be deleted is a different decision from allowing a contract to be, since contracts carry commercial data maintained outside the service desk. Creating, updating, commenting and linking ITIL records share one gate each, since the blast radius is the same across types.
The gate covers every tool whose annotations mark it destructive — tickets, assets, admin resources, webhooks and ITIL. A test asserts that mapping against the live tool catalogue, so a tool added later cannot quietly ship without a gate.
Idempotency
| Variable | Default | Description |
|---|---|---|
GLPI_IDEMPOTENCY_ENABLED |
true |
Enable the idempotency guard |
GLPI_IDEMPOTENCY_BACKEND |
sqlite |
sqlite, memory or none |
GLPI_IDEMPOTENCY_DB_PATH |
var/idempotency/store.sqlite3 |
SQLite database path |
GLPI_IDEMPOTENCY_NAMESPACE |
default |
Isolates instances sharing a database |
GLPI_IDEMPOTENCY_TTL_SECONDS |
86400 |
Record retention in the store (24 h) |
GLPI_IDEMPOTENCY_LEASE_SECONDS |
60 |
Lease held by an in-flight execution |
GLPI_IDEMPOTENCY_WAIT_TIMEOUT |
30 |
Max wait for a concurrent execution |
GLPI_IDEMPOTENCY_POLL_INTERVAL |
0.25 |
Lease polling interval |
GLPI_IDEMPOTENCY_PURGE_INTERVAL |
300 |
Expired-record cleanup interval |
Repeating the same create returns the first result flagged replayed: true without
touching GLPI. The guard window at tool dispatch is 120 seconds — deliberately
short, so a client or model retry is absorbed while a legitimately identical followup
later still goes through. If the store fails, the operation is not blocked: it runs
and the degraded mode is logged.
Knowledge base (optional)
glpi_search_knowledge_unified is the only tool backed by a vector store instead of
the GLPI REST API. Without a knowledge_base section configured it degrades
politely — the tool reports that the KB is not configured; nothing else is affected.
Two halves, sharing one knowledge_base.embedding block:
- Search (
knowledge_base.sources) — the source registry read by the MCP. Every source exposes the same fixed column contract, so adding one is a registry entry plus a relation, with no source-specific SQL in the MCP. Seesrc/services/kb_search/CONTRACT.md. - Ingestion (
knowledge_base.ingestion) — the ETL that turns a GLPI instance's own resolved tickets into that store. Seeknowledge_base/README.md.
Ingestion knobs worth knowing (full list in the knowledge_base README):
| Setting | Default | Description |
|---|---|---|
embed_strategy |
full |
full (title + category + description), form_description (only the form's free-text problem — right when titles are form names and therefore boilerplate), problem_solution (problem and resolution, so a ticket is findable by the fix and not only by the symptom) |
description_labels |
built-in list | Which form field holds the free-text problem; instances name it differently. A JSON array, not a comma-separated string |
include_followups |
true |
Fold technician follow-ups into the indexed resolution — GLPI keeps the fix in a follow-up on most tickets, so leaving this off discards it |
redact_literals |
[] |
Exact secret values to strip from indexed text, on top of the pattern-based redaction that always runs |
Credentials pasted into tickets are redacted before indexing, so they never reach
the vector, the full-text index or a rendered result. Values found anywhere in the
batch are stripped everywhere in it. This is on by default and not configurable off;
redact_literals only adds values the patterns cannot infer.
Per-source display: set solutions_expected: true on ticket sources. It is what makes
a missing resolution read as "(resolvido, sem descricao da solucao)" — the fix was
never written down — instead of the — shown by documentation and forum sources,
where having no solution field is normal.
Deployment. The ETL is incremental and meant to run on a timer.
knowledge_base/deploy/ ships a templated systemd pair, enabled once per instance:
sudo cp knowledge_base/deploy/glpi-kb-ingest@.{service,timer} /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now glpi-kb-ingest@<instance>.timer
It runs daily at 05:00 under a flock shared with the other ETLs that contend for the
same embedding endpoint. Search works against whatever is already indexed, so a missed
run degrades freshness, not availability.
🧪 Testing
# Run all tests
pytest tests/ -v
# With coverage
pytest tests/ --cov=src --cov-report=html
# Specific test file
pytest tests/test_models.py -v
Test Coverage: 1,515 automated tests passing (plus 12 skipped) at the 2026-09-28 release, covering unit, integration, contract and E2E scenarios.
Among them is a contract test on description quality: tool and prompt descriptions are the retrieval surface that MCP hubs index and match semantically, so a thin description makes a working tool unreachable — it simply never gets picked. The test fails the build on descriptions that are too short or that open with a generic verb.
Live smoke test
The suite mocks GLPI's responses, so it cannot observe GLPI's own semantics. Two real defects only surfaced against a live instance: the ordering operator on status behaving as equality (hiding assigned tickets from the "open" filter), and the plain listing endpoint silently ignoring criteria (returning every entity's groups when one entity was asked for).
# Read-only by default; the port is the first argument (default 8826)
GLPI_TOKEN=<user token> ./scripts/smoke_live.sh 8826
# Including the write cycle, against a disposable test ticket
GLPI_TOKEN=<token> SMOKE_WRITE=1 SMOKE_TICKET_ID=<id> ./scripts/smoke_live.sh 8826
⚠️ The token always comes from the environment. Never write it into the script or add it to the server's
.env: there it becomes a fallback, and the server starts accepting unauthenticated calls under that identity — breaking tenant isolation and record authorship in GLPI.
🔧 Maintenance
PM2 Commands
pm2 status mcp-glpi # Status
pm2 logs mcp-glpi # Real-time logs
pm2 restart mcp-glpi # Restart
pm2 monit # Monitoring
Update
git pull origin main
source venv/bin/activate
pip install -r requirements.txt
pm2 restart mcp-glpi
📚 Useful Links
- GLPI Project — Official GLPI website
- GLPI API Documentation — REST API docs
- MCP Specification — MCP protocol spec
- Skills IT Website — Our company website
📋 Requirements
| Component | Version |
|---|---|
| Python | 3.11+ |
| GLPI | 10.x, 11.x |
| FastAPI | 0.104+ |
| Pydantic | 2.x |
| MCP Protocol | 2024-11-05 |
🤝 Contributing
Contributions are welcome! Fork the repository, create a feature branch, and open a Pull Request with conventional commit messages.
📞 Support
Bug Reports
Open an issue with reproduction steps and environment details.
Technical support: contato@skillsit.com.br
📄 License
MIT License — see LICENSE for details.
Made with ❤️ by Skills IT - Soluções em TI - BRAZIL
We are an MSP empowering other MSPs with intelligent automation.
Version: 2.2.0 | Last Updated: August 2026
🇧🇷 Proudly Made in Brazil