MCP Server - edmozley/freeitsm GitHub Wiki
FreeITSM speaks the Model Context Protocol (MCP), so an AI assistant - Claude Code, Claude Desktop, or any MCP client - can read it directly: "Which projects are off track, and why?", "What changed this morning?", "Is the VPN down?"
It is read-only, and it sees exactly what the analyst behind its API key may see.
- System → API → create a key with the MCP server permission. The key acts as the analyst you choose, so pick the analyst whose view the assistant should have. Limit it to companies if you need to.
- Give the assistant the address shown on that page:
https://your-server/api/mcp/
Claude Code:
claude mcp add --transport http freeitsm https://your-server/api/mcp/ --header "Authorization: Bearer fitsm_…"Any other client that supports MCP over HTTP ("Streamable HTTP") with a bearer token works the same way: the address, and the header Authorization: Bearer <key>.
Note
Connectors that only sign in with OAuth (rather than a key in a header) cannot connect yet: FreeITSM uses its API keys.
| Tool | Answers | Needs |
|---|---|---|
list_projects |
Projects with health, status, progress, target, project manager and why they are the colour they are | Projects |
project_overview |
One project in full: goal, health and why, stages and gates, milestones (reached, missed or due), open risks and issues, budget against actual, linked changes not yet approved, recent history | Projects |
project_raid |
A project's RAID log, with risk scores and plans | Projects |
project_budget |
Planned against actual, every line, labour - never one person's rate | Projects |
project_tasks |
A project's tasks, overdue first | Projects |
project_dates |
Project dates coming up across every project - stage ends, milestones, target finishes - and missed milestones (3.3.0) | Projects |
open_incidents |
Open tickets at a priority | Tickets |
ticket_spike |
Whether tickets are arriving faster than usual | Tickets |
related_tickets |
Tickets linked to one ticket | Tickets |
on_call |
Who is on call | Tickets |
service_status |
Services and open service incidents | Service Status |
recent_changes |
Changes in the last few days | Changes |
asset_lookup |
An asset by name, tag or serial | Assets |
impact_of |
What depends on a configuration item | CMDB |
known_errors |
Problems with a known workaround | Problems |
supplier_contact |
Who to call at a supplier | Contracts |
morning_checks |
Today's morning checks | Morning Checks |
search_knowledge |
Knowledge article titles | Knowledge |
Tickets are referred to by number and projects by code (PRJ-0042); project_* tools also accept a project's id or a unique part of its name. Ticket answers carry operational facts - numbers, states, subjects (a confidential ticket by number only) - not ticket bodies or requester details.
- Read-only. No tool changes anything. An assistant reading a ticket can be fed instructions by whoever wrote it; read-only makes that harmless.
- As the key's analyst. A tool is offered only if that analyst can open its module (the Needs column above) and has any permission it needs. A tool they cannot use is not listed at all.
- Never wider than the analyst. A key's companies are narrowed to the companies its analyst may see: a key left on all companies for an analyst limited to one company sees that one company, and a key naming a company the analyst cannot reach sees nothing there.
- Within those companies. The Projects and Knowledge tools are limited to them. On an install with more than one company, the tools that read one company's tickets, changes, assets, CMDB or problems are offered only when the key and its analyst both cover every company - they do not narrow themselves by company yet, so they are withheld rather than allowed to show another company's data.
- No chat. War-room search is not offered: it includes the analyst's direct messages and private channels, and a key can act as any analyst, so it would let a key holder read somebody's private conversations.
- History that names another module (a linked contract, a raised ticket, a Knowledge article) is left out of a project overview when the analyst cannot open that module.
- The same key rules as the REST API: expiry, rate limit, a disabled key or an inactive analyst, and last used on System → API.
- What comes back is text people wrote. Tool answers include titles, workarounds, plans, notes and comments that analysts (and sometimes customers, quoted in a known error or a service comment) wrote. The assistant reads them; because every tool is read-only, text that tries to give the assistant instructions cannot make FreeITSM do anything.
- Reviewed. An independent security review of the MCP layer (October 2026) found the gaps above - a key reaching beyond its analyst's companies, chat including direct messages, Knowledge ignoring the key's companies, database error text reaching the client - all fixed before release.
| File | What it is |
|---|---|
api/mcp/index.php |
The protocol: MCP Streamable HTTP, stateless JSON responses (no event stream, no session). initialize, notifications/* (202), ping, tools/list, tools/call. Speaks 2025-06-18, 2025-03-26 and 2024-11-05. JSON-RPC errors: -32700 parse, -32600 invalid (batches are refused - 2025-06-18 removed them), -32601 unknown method, -32602 unknown or forbidden tool. GET/DELETE are 405. A request whose Origin is not the request's own Host is refused - a second fence only: the real protection from browsers is that the endpoint takes nothing but a bearer key (no cookies, no CORS). |
includes/mcp/tools.php |
The tools and the gate. mcpEffectiveScope() narrows the key's companies to its analyst's, once, straight after authentication. Warbot handlers are called directly (not through warbotRunTool(), which returns exception text). MCP has its own search_knowledge through KnowledgeViewer::forApiKey(). A thin adapter over the Warbot registry (includes/warbot/tools.php): each Warbot tool is mapped to its module and marked company-safe or not in mcpWarbotToolMap(); the Projects tools are MCP-only and company-scoped by the key. mcpToolAllowed() = module access + capability + (company-safe, or single-company install, or a key covering every company). |
api/v1/lib/auth.php |
Reused as is: apiAuthenticate(), the mcp permission (api/v1/lib/permissions.php). |
api/mcp/.htaccess |
Passes the Authorization header through on FastCGI / PHP-FPM (#115). |
Adding a tool: a Warbot tool appears once it has a row in mcpWarbotToolMap() - module and whether it is company-safe. Do not mark a tool company-safe unless its handler genuinely scopes by company or reads install-wide data. An MCP-only tool is a mcpTools() entry with module, company_safe, capability and a handler (PDO, args, analystId, apiKey) returning text; throw ServiceError for a problem the assistant should see as a tool error.
Not built yet: write tools; OAuth sign-in for connectors that need it; company scoping inside the Warbot tools (so they can be offered to a single-company key); a log of which tools an assistant called.