Skip to content

feat: expose Settings / ProviderAccount / ToolProvider CRUD via CLI + MCP #92

Description

@Flare576

Context

Came up while confirming a suspicion Flare had: today, ei create/update/remove (CLI) and ei_create/ei_update/ei_remove (MCP) cannot touch a Provider, ToolProvider, or any other field in human.settings. Verified by reading the actual dispatch code, not inferred:

  • src/cli.ts gates create/update/remove type args through resolveCorrectableType/resolveUpdatableType, which only resolve against CORRECTABLE_TYPES = ["fact","topic","person"] / UPDATABLE_TYPES = [...that, "quote"] (+ "persona" bolted on at the CLI layer).
  • src/cli/mcp.ts hardcodes the same set as Zod enums on ei_create/ei_update/ei_remove.
  • src/cli/corrections-endpoints.ts:108SCHEMAS = { fact, topic, person } is the entirety of the generic dispatch; quote/persona get their own hand-written paths. None of the three schemas, and no fourth path, has any notion of ProviderAccount, ToolProvider, or HumanSettings.
  • The only mutators that exist for those types are Processor.updateHuman() (writes human.settings, which nests accounts: ProviderAccount[] — this is where api_key lives for LLM/storage providers) and Processor.addToolProvider/updateToolProvider/removeToolProvider (ToolProvider.config — where Tavily's key and Spotify's OAuth refresh token live, plus the enabled on/off flag). Both are called only from the TUI's /settings and /provider//tools $EDITOR flows and the Web SettingsModal/ToolkitEditor/PersonaCreatorModal — never from a corrections-backed path.

So: nothing in the Ei corrections queue (corrections.jsonCorrectionRecord) can carry a settings/provider payload. It's not a permission check that's missing — the schema/type has no branch for it.

The ask

Give CLI/MCP callers (agents working alongside Flare, and non-vim humans like Jess) a first-class, validated way to:

  • list/view provider accounts (LLM + storage) — secrets masked by default
  • create/update/remove a ProviderAccount, including setting api_key
  • enable/disable and configure a ToolProvider (Tavily key, Spotify refresh token, on/off)
  • read/update the rest of HumanSettings that doesn't carry secrets (model defaults, queue_paused, ceremony/backup tuning, message rolloff thresholds, name_display, theme)

Goal per Flare: CLI should be a first-class citizen, not a subset of what Web/TUI can do — anyone comfortable with the CLI (or an agent driving it) should be able to do everything a human clicking through Settings can do.

Why this needs actual design, not just "widen the enum"

  • ProviderAccount/ToolProvider/HumanSettings aren't DataItemBase entities — no id in the same sense, no sources, no embedding, no natural slot in the existing CorrectableType union.
  • Secrets make the existing "full-record round-trip" pattern (ei --id X → edit → ei update X --json '<whole record>') actively unsafe: reading a provider back to change one field would print the plaintext api_key/password to stdout, and resubmitting pushes it through --json on argv (shell history) — see Add non-argv JSON input mode for ei create / ei update #82, which is close to a prerequisite here if secrets ever flow through this surface.
  • Need a redaction convention on read (mask api_key/password/refresh tokens unless explicitly asked to reveal) and probably a distinct "rotate secret" verb instead of full-record replace, so changing a key doesn't require re-handling the old one.
  • ProviderAccount (LLM/storage) and ToolProvider (built-in tool integrations) solve overlapping-but-distinct problems — worth deciding up front whether they get one CLI surface or two, and whether HumanSettings' non-secret fields (theme, ceremony tuning, etc.) ride along or get their own ei settings verb.

Non-goal (confirmed, not part of this issue)

This is net new functionality, not a bug fix — confirmed the current absence is intentional-by-omission, not a broken guard. The corrections pipeline is currently, correctly, incapable of this; this issue is the design+build to add it deliberately, with the redaction/rotation story handled up front instead of discovered after the fact.

Scope

Design first — decide the redaction/rotation UX and whether ProviderAccount/ToolProvider share one verb before implementing create/update/remove. This issue tracks the ask, not a finished spec.

— Sisyphus

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions