v1.28
v1.28 - 2026-05-04
OAuth 2.1 release. Three issues land together (#36, #38, #39) plus a full audit-trail of UI polish and security hardening discovered along the way. The headline change is the embedded OAuth 2.1 authorization server: ChatGPT custom apps, Claude Desktop remote connectors, MCP Inspector, and any MCP 2025-11-25 compliant client can now negotiate auth against a Zabbix MCP deployment without an external IdP, without a hardcoded bearer, and without operators learning OAuth library internals.
Added
- Active-only problem filter (issue #39, original concept by @fenbays). Two doors into the same data:
problem_get(monitored=True)- new boolean parameter on the existing tool, matches the semantic ofhost_get/item_get'smonitoredflag. When set, problems whose trigger hasstatus != 0or whose host hasstatus != 0are dropped client-side after the API fetch (Zabbix has no nativemonitoredflag onproblem.get). Defaultfalsekeeps backwards-compat: an unfiltered call still returns every problem on file.problem_active_get- new extension tool that pre-bakes the right defaults for an LLM that just wants "what is wrong right now":severities=[2,3,4,5](Warning and above), themonitoredfilter from above, and per-row enrichment withhost,hostid,time(UTC, human-readable like"2026-04-28 17:30 UTC"), andseverity_label. Returns{"problems": [...], "count": N, "filtered_out": M}so callers can tell how much got dropped vs. how much got kept. Tighter prompt budget thanproblem_getbecause the LLM does not have to know about disabled-trigger noise or numeric severity codes.
- The
monitoredflag onproblem_getand theproblem_active_getenrichment share a single helper (_filter_active_problems) so the filter logic stays in one place. - Per-token tools/list filtering (issue #38, original concept by @fenbays). Until now,
[tokens.X].scopesonly gated tool invocation - the catalog returned bytools/listwas always the full 232-tool surface, regardless of which token connected. That cost two real things: an LLM's initial handshake had to pay schemas for every admin / users / extensions tool it could not call (3 KB vs. 25 KB token cost on Claude Desktop / ChatGPT custom GPTs reported in #13), and the model would happily tryhost_createon a monitoring-only token, eating a round-trip to a 403. v1.28 wraps the FastMCPtools/listhandler with_filter_tools_by_token: it reads the calling token's scopes from the existingcurrent_token_infocontextvar (no new auth surface), expands group names via_expand_tool_groups, and prunes the response to what the token may actually call. Tokens withscopes = ["*"](or unset) keep the full list, so single-token / no-auth setups behave exactly as before. Read-only tokens additionally lose every*_create / *_update / *_delete / *_mass*tool plusaction_prepare,action_confirm, andzabbix_raw_api_callfrom the catalog - the auto-detected write set is built once at server boot fromMethodDef.read_onlyplus a small hand-rolled extension list. Field test on production: a monitoring-only read-only token'stools/listshrinks from 232 entries to 25. problem_active_getregistered in theextensionstool group AND themonitoringgroup, so monitoring-only tokens still see it after the per-token filter applies.- Embedded OAuth 2.1 authorization server (issue #36). New
[oauth] enabled = trueboots an in-process AS that ChatGPT custom apps, Claude Desktop remote connectors, and any MCP 2025-11-25 client can negotiate against - no external IdP, no shared OAuth provider needed. Implements the full discovery surface (RFC 8414/.well-known/oauth-authorization-server, RFC 9728/.well-known/oauth-protected-resource,WWW-Authenticate: Bearer ... resource_metadata="..."on 401), dynamic client registration (RFC 7591/register), authorization code + PKCE S256, refresh-token rotation, and revocation (RFC 7009). Audience binding (RFC 8707) ties every issued token to[server].public_urlso a leaked token cannot be replayed against a different MCP deployment.- Login UI reuses the existing admin-portal users (
[admin.users.*], scrypt-hashed). Operators do not maintain a second identity store; if the admin portal already letstomasin, that is the username they type into ChatGPT's "Advanced OAuth settings" sign-in dialog. The login + consent screen mirrors the admin portal's login surface (logo, theme switcher, light/dark variables, footer) so the flow does not feel like a third-party page bolted on top. - Authorization codes / access tokens / refresh tokens are in-memory (10-min / 1-h / 30-day TTLs). Registered clients persist in
[oauth_clients.<client_id>]config sections so they survive restart; codes and tokens vanish on restart so any in-flight session re-authorizes via the client's auto-refresh logic. - Legacy bearer-token mode keeps working alongside OAuth. A client that already authenticates via
[tokens.X]does not need to migrate; the OAuth provider'sload_access_tokenfalls back to the existingTokenStorewhen the bearer is not an OAuth-issued credential. - Full setup, security checklist, and ChatGPT / Claude Desktop integration walkthrough in
docs/OAUTH.md.
- Login UI reuses the existing admin-portal users (