Skip to main content
Glama
Pappa

mcp-oidc-proxy

by Pappa

save_config

Save current configuration to users.yaml and settings.yaml, refusing if another writer changed them; then reload the running proxy.

Instructions

Save current configuration to YAML files (persists changes made via create/update tools without persist=True support). Writes users.yaml and settings.yaml as one coordinated, conflict-checked save (#229) and then refreshes the running configuration from what was just written. To refuse the save if another writer (the web UI, another agent, a second nanoidp process on the same directory) changed a file since you read it, pass the expected_users_revision / expected_settings_revision a read tool handed back (list_users and get_user carry users_revision; list_clients, get_client and get_settings carry settings_revision; reload_config and a successful save_config carry both). save_config always writes both files, so there are exactly two modes: omitting both revisions keeps today's unconditional last-write-wins, and supplying either makes the WHOLE save conflict-checked - the omitted revision defaults to the one this runtime was loaded from, so a save guarded on users.yaml cannot silently overwrite a settings.yaml another writer changed, or vice versa. A failure response's 'kind' distinguishes four outcomes: 'conflict' (nothing was written - a supplied revision was stale; call reload_config, reapply your change on the fresh state and save with the revisions from its response), 'lock_timeout' or 'lock_unsupported' (nothing was written either - the write never started; lock_timeout is worth retrying, lock_unsupported means this config directory's filesystem does not support advisory locks and will not succeed on retry), a hook's own 'kind' under hooks.strict (both files ARE written; only the mirror push failed), or 'reload_after_save' (both files ARE written but the runtime could not adopt them - do not retry expecting a different result, the file on disk is authoritative).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
expected_users_revisionNousers.yaml revision from a read tool; the save is refused with kind 'conflict' if the file no longer matches it. Supplying either revision makes the whole two-file save conflict-checked (the omitted one defaults to this runtime's loaded revision); omit both for unconditional last-write-wins.
expected_settings_revisionNosettings.yaml revision from a read tool; same contract as expected_users_revision.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully carries the behavioral burden. It discloses that the tool writes both files, coordinates the save, refreshes the runtime config, refuses the save on stale revisions, and defines four distinct failure kinds with their consequences (nothing written vs. files written but mirror/reload failed). This is exceptionally transparent about side effects and edge cases.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and long, but every sentence carries necessary information for a complex tool. It is front-loaded with the primary purpose and then logically progresses through modes and failure outcomes. It loses one point because a structured list or clearer paragraph breaks for the four failure kinds would improve scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema and no annotations, the description is complete enough for an agent to invoke the tool correctly and handle all outcomes. It explains return semantics via the failure 'kind' field, gives recovery steps for conflicts, warns about non-retryable lock_unsupported conditions, and clarifies when files are actually written. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds substantial semantics beyond the schema. It explains the interaction between the two revisions, the defaulting of an omitted revision to the runtime's loaded revision, and the fact that supplying either revision makes the entire two-file save conflict-checked. This deeper meaning is critical for correct invocation and is not fully derivable from the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Save current configuration to YAML files', and immediately names the exact outputs (users.yaml, settings.yaml). It distinguishes itself from siblings by stating it persists changes made via create/update tools that lack persist=True, while related tools like reload_config focus on runtime state. This leaves no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool (to persist changes from create/update tools without persist=True support) and gives conditional guidance for the two modes: omit revisions for last-write-wins, or supply them to enable conflict checking. It also names alternatives in context, such as calling reload_config after a conflict and using read tools to obtain revisions. This is clear, actionable usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.