Skip to content

feat(mcp): build timestamps, mcp server start fixes, and resolveIdentity adaptation - #665

Merged
vscheuber merged 10 commits into
rockcarver:mainfrom
vscheuber:main
Aug 18, 2026
Merged

feat(mcp): build timestamps, mcp server start fixes, and resolveIdentity adaptation#665
vscheuber merged 10 commits into
rockcarver:mainfrom
vscheuber:main

Conversation

@vscheuber

Copy link
Copy Markdown
Contributor

Summary

Follow-on work after #664 on the polaris/mcp-claude-channel-capability line that continued to accumulate on main before this PR was opened. Highlights:

  • Report special-kind skill counts in mcp server info
  • Surface build timestamps via frodo -v and the MCP server manifest
  • mcp server start: disable token cache, drop unused realm positional, hide --no-cache/--flush-cache from help, reformat build-timestamp display
  • Document username-only password auto-resolution in --username help
  • Adapt variables ops to frodo-lib's resolveIdentity replacing resolvePerpetratorUuid

Depends on

This PR's resolveIdentity adaptation depends on rockcarver/frodo-lib#628, which is not yet merged or published to npm. Opening as a draft until that lands and @rockcarver/frodo-lib is bumped past the currently-pinned 4.2.1; CI on this PR may fail until then.

Test plan

vscheuber and others added 10 commits August 15, 2026 08:22
…ility

feat(mcp): MCP server visibility improvements for Claude CLI
The includeSpecial/allowOperationTypes gap fixed upstream in frodo-lib
(applyCapabilityPolicy) was easy to get wrong silently — a preset could
claim includeSpecial: true while a leftover allow-list quietly vetoed
every special-kind capability anyway. `frodo mcp server info` now
reports how many special-kind skills are available vs. active under the
resolved policy/profile, with an active-by-risk-class breakdown, so that
kind of gap is visible from the CLI instead of requiring a source read.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ePerpetratorUuid

frodo-lib renamed and restructured resolvePerpetratorUuid into
resolveIdentity, which returns a structured object instead of an
opaque formatted string. Add formatResolvedIdentity to rebuild an
equivalent display label for the variable list/describe commands'
"Modifier" column, matching the previous per-kind formatting
(admin/service/realm-user) plus a new label for the "admin-unconfirmed"
case that resolveIdentity can now return.
…ame help

Follow-up to frodo-lib's new getTokens() behavior (roadmap item 2):
passing --username alone, with a matching connection profile for the
target host, now resolves that profile's stored password instead of
requiring it on the command line. Updates the global --username
argument's help text so this is discoverable from `--help` on any
command, including `frodo mcp server start`.
`new FrodoCommand('frodo mcp server start', [])` kept every default
positional argument, giving this command the signature
`<host> [realm] [username] [password]` — but nothing in this command
ever reads state.getRealm() afterward; it's stored and never used.

That's a real footgun, and it just caused a live misconfiguration:
running `frodo mcp server start <host> <username>` (the natural
pattern, matching `frodo info`, which explicitly omits realm the same
way) put the username in the realm positional slot instead. Username
ended up unset, so getTokens() fell back to loading the default stored
connection profile rather than the intended one, and the stray value
sitting in state as a "realm" broke session.getSessionInfo's URL
construction downstream.

Fixed by adding 'realm' to this command's omits, matching `info`'s
existing precedent, and updating the action handler's parameter
destructuring to match. Added a help example showing the
username-only, password-auto-resolved invocation this footgun was
tripping people up on. Verified live: `frodo mcp server start <host>
<username> --dry-run --json` now reports authMode "admin-account" with
full discovery hydration succeeding, using only host + username.
…er manifest

Companion to frodo-lib's getLibBuildTimestamp() (see that commit for
the full motivation): after a source fix, tsup's app.cjs bundle can
look correct in every static check — file mtimes fresh, grepped
strings present — while the actually-running process still exhibits
old behavior, because a downstream packaging step (or something less
obvious) silently produced a stale artifact. There was no way to ask
a running frodo-cli process "what did you actually get built from"
without shell access to grep a binary, which itself turned out
unreliable (comments don't survive bundling; -C Gzip means the packed
executable isn't even readable plaintext).

Added __CLI_BUILD_TIMESTAMP__, injected the same way as frodo-lib's
build timestamp: a real ISO 8601 literal substituted by tsup's `define`
at bundle time, not a generated source file. Exposed three ways:

- `frodo -v` now prints cli-build/lib-build timestamp lines alongside
  the existing cli/lib version lines.
- MCP_SERVER_VERSION (reported to every MCP client at protocol
  handshake, and by `frodo mcp server info`) now carries both build
  timestamps as semver build metadata
  (4.5.2+cli.<compact-ts>.lib.<compact-ts>) — queryable via standard
  MCP protocol introspection, no shell access needed.
- `frodo mcp server info` also prints/returns both as plain ISO 8601
  timestamps for readability.

Verified live: spawned the actual packed binary as a real MCP server
via the SDK client and confirmed the handshake reports real, current
timestamps matching the actual build time.

Updated the one test this broke — a hardcoded exact-match on the old
unversioned "Frodo MCP Server v4.5.2" info line — to check the stable
version prefix plus real assertions on the new build-timestamp lines,
rather than loosening it to ignore the new output.
…timestamp display

Two changes, both from live debugging today.

1. Root-caused a real, reproducible "403 No session for request"
   failure on `frodo mcp server start`'s login, which appeared out of
   nowhere mid-session while frodo-lib's own getTokens() kept
   succeeding with identical credentials against the same host. The
   token cache (~/.frodo/TokenCache.json) is shared, on-disk, and
   written by every frodo process — including the four concurrent
   `mcp server start` processes (one per policy preset) this session
   normally runs, plus whatever ad-hoc test processes were spawned
   during today's investigation. That's exactly the kind of concurrent
   reader/writer pressure an unsynchronized shared cache file breaks
   under. Confirmed live: forcing state.setUseTokenCache(false)
   immediately fixed the login failure.

   Hard-coded off for this command specifically rather than exposed as
   a configurable default — the token cache exists to let successive
   short-lived CLI invocations skip re-authenticating, which doesn't
   apply to a long-running server that logs in once and relies on
   frodo-lib's own auto-refresh afterward. Root cause (making the
   on-disk cache safe for concurrent writers) is a separate, bigger
   piece of work, tracked for later rather than attempted here.

2. Reformatted build-timestamp display, consistently, across `frodo -v`,
   `frodo mcp server info`, and the MCP server manifest (the
   {name, version} pair every MCP client sees at protocol handshake):
   version number followed by the build timestamp in parentheses, e.g.
   `cli: v4.5.2 (2026-08-17T03:17:15.421Z)`, replacing the earlier
   separate "cli-build:"/"CLI build:" lines and the compacted semver
   build-metadata string. `mcp server info` now also shows the lib
   version number alongside its build timestamp, matching `frodo -v`'s
   existing cli/lib pairing exactly rather than showing build info without
   the version it belongs to.

Verified live via the actual MCP protocol (a real SDK client spawning
the built binary, not a hand-rolled harness): login now succeeds
consistently; the handshake reports version "4.5.2 (2026-08-17T03:32:...)"
in the new format; and — closing the loop on today's earlier ranking
investigation — with a real request finally getting through, mutating
skills (create/delete/relationship-write) no longer crowd the top of
"authenticated identity info" results at all, confirming that fix does
work in the real bundled binary. session.getSessionInfo now ranks
21st of 51 real candidates for that query — a genuine improvement from
being unfindable, even though it still loses to the ten idm.managed.*
read skills that legitimately earn the identity bonus for a query
that generic. Further ranking tuning, if wanted, is a separate
follow-up.
Follow-up to hard-coding the token cache off for this command: the
flags were still registered and shown in --help, implying a choice
that no longer exists — --no-cache would silently be a no-op since the
cache is already off, and --flush-cache would flush a cache this
command never reads from or writes to in the first place. Omitted
both, matching the existing pattern already used for 'realm'.
@vscheuber
vscheuber marked this pull request as ready for review August 18, 2026 04:41
@vscheuber
vscheuber merged commit 9e70161 into rockcarver:main Aug 18, 2026
1 of 4 checks passed
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