Skip to content

Profiles: Add profile commands, routes and MCP tools - #954

Closed
tobocop2 wants to merge 3 commits into
feat/profile-operationsfrom
feat/profile-surfaces
Closed

tobocop2 wants to merge 3 commits into
feat/profile-operationsfrom
feat/profile-surfaces

Conversation

@tobocop2

@tobocop2 tobocop2 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Problem

Profiles had a library API but no way to use it from the command line, from an agent, or over HTTP.

Solution

CLI. lilbee profile shows the active profile and lists, shows, diffs and applies profiles (apply --reindex). It also covers new, save, update, discard, duplicate, rename, delete, export, import and validate. Every write takes --target global or --target project. Every command supports --json.

HTTP. /api/profiles routes cover the same operations, with GET /api/profiles/active for the applied profile. A profile name in a URL is matched against the library and never used as a file path.

MCP. Four tools: lilbee_profile_list, lilbee_profile_show, lilbee_profile_apply, and lilbee_profile_manage, which takes an action. They are off by default behind the mcp_profiles_enabled setting, like session tools, because the default tool list is at its size budget.

A profile's authors and tested_on line show wherever it is listed or shown, and every surface reports the same error text. A name that clashes with an existing profile answers 409; bad input answers 400.

Names of the fixed routes (active, new, discard, import, validate) and Windows device names are reserved. Imports are capped at 256 KB before anything is written. The MCP tools take file content, not paths on the host.

Notes

This stacks on #951.

@tobocop2
tobocop2 added this pull request to stack #942 September 27, 2026 12:01
@tobocop2
tobocop2 force-pushed the feat/profile-surfaces branch from 12cb520 to 7636607 Compare September 27, 2026 14:12
@tobocop2 tobocop2 changed the title Add profile commands, routes and MCP tools Profiles: Add profile commands, routes and MCP tools Sep 27, 2026
@tobocop2
tobocop2 force-pushed the feat/profile-surfaces branch from 7636607 to 1ac9fd9 Compare September 27, 2026 23:51
Every profile operation now has a CLI, HTTP and MCP surface over the
profile use cases. `lilbee profile` covers show, list, diff, apply
(with --reindex), new, save, update, discard, duplicate, rename,
delete, export, import and validate; every write takes --target
global|project, global by default. The /api/profiles routes cover the
same operations, with GET /api/profiles/active for the applied
profile. The MCP profile tools are list, show, apply and one manage
tool with an action enum.

A profile name from a URL only reaches the profile lookup, never a
file path. A missing profile answers 404 and a refused operation 400.
Every surface prints the message the profile use cases raise, and a
failed file write gets one shared message. HTTP runs each operation
on a thread. Every listed or shown profile carries its authors as a
credit line and its tested_on text.

The default MCP tool schema had 4 bytes left under its cap, so the
four profile tools are gated on a new setting, mcp_profiles_enabled,
off by default, in the same way as mcp_sessions_enabled.

The use cases gain what the surfaces need: a not-found error, the
active profile's entry, an update that checks a given name, export
and import as text, and validation of text.
A profile named active, new, discard, import or validate was shadowed
by the fixed route of that name under /api/profiles/, so its own URL
answered another route or 405. The name check now refuses every name
whose lookup key is one of those segments, or a Windows device name
(CON, PRN, AUX, NUL, COM0-9, LPT0-9), since a write would create
con.toml. The one list lives in the core name check, so every surface
refuses the name and a file on disk with it is listed as broken. A
test reads the fixed segments from the app's routes and fails when one
is missing from the list.

The 256 KB profile cap now applies to profile text as well as to files,
so HTTP import and validate refuse an oversized upload before anything
is written. Both routes also carry a body limit of six times the cap,
the largest a capped file can become in JSON, so Litestar answers 413
instead of reading a larger body.

The URL path-safety test now creates both profile folders, so a
handler that joins the name into a path deletes the planted file and
fails the test. New tests pin the target folder on HTTP new, duplicate
and import, CLI duplicate and MCP duplicate, and the credit lines of
lilbee profile show for the active profile.
Export now returns the canonical name and folder on the CLI and MCP,
matching every other profile write.

A failed reindex after profile apply --reindex now reports the
apply's own result and the reindex failure in one JSON object, and
exits non-zero.

A name clash on a profile write answers 409; every other refusal
stays 400.

The MCP manage tool takes a profile's content and file name instead
of a host path for export, import and validate, so it can no longer
read or write arbitrary files on the machine running lilbee.

One test now drives every profile route handler and asserts each
runs its operation off the event loop, not only list.

Reflow a doc line and add the AGENTS.md annotation to the isinstance
guard moved in the last round.
@tobocop2

tobocop2 commented Oct 3, 2026

Copy link
Copy Markdown
Owner Author

This change is now part of #1003, which collects every Profiles pull request on one branch. Review and merge happen there. The branch stays in place.

@tobocop2 tobocop2 closed this Oct 3, 2026
@tobocop2
tobocop2 deleted the feat/profile-surfaces branch November 1, 2026 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant