Skip to content

v0.6.0

Latest

Choose a tag to compare

@ScottRBK ScottRBK released this 19 Oct 23:39
· 18 commits to main since this release
7d9547e

v0.6.0

Breaking change: scoped JWT and introspection tokens

This release fixes MCP permission widening when tokens contain mixed scopes, list-valued scopes,
or the scp claim. A token such as "scope": "openid read" now stays read-only.

A nonempty scope claim containing no recognised Forgetful permission now denies all MCP tools.
For example, a token containing only api:read api:write may still authenticate, but discovery
returns no tools and tool calls are denied.

Before upgrading an affected deployment:

  1. Keep the IdP scopes required by FASTMCP_SERVER_AUTH_*_REQUIRED_SCOPES.
  2. Configure the issuer or introspection response to include the intended Forgetful permissions:
    • Read-only tools: "scope": "api:read api:write read".
    • Read/write tools: "scope": "api:read api:write read write".
    • Narrower permissions can use category labels such as write:memories.
  3. Obtain replacement tokens after changing issued claims, then check discovery and an allowed
    operation. Changing REQUIRED_SCOPES alone does not change an existing token.

REQUIRED_SCOPES controls admission. FORGETFUL_SCOPES sets the server's tool limit, and
recognised scopes in the token narrow its MCP access. Use * only when it should receive all tools
allowed by the server. Scope settings use commas; token scope strings use spaces. There is no new
forgetful_scopes field.

Absent or empty scope claims retain the existing server-permission fallback after authentication.
Normal built-in GitHub/Google OAuth logins and local no-auth usage do not need the token change
above. See the configuration guide for provider differences and examples.

Security fixes

  • Scope PostgreSQL activity listing, history, counts and expired-event cleanup to the requesting
    user, without relying on database row-level security (#105).
  • Check ownership of both memories before creating links on SQLite and PostgreSQL
    (#103).
  • Validate project ownership before attaching documents, code artifacts, files, skills or plans.
    Reject missing and foreign project references consistently. Check SQLite source-memory ownership
    before using its embedding for similarity searches (#113).
  • Preserve recognised token restrictions alongside unrelated IdP scopes, and support list-valued
    scope and scp claims (#107).
  • Update PyJWT 2.13.0 to 2.15.1, urllib3 2.7.0 to 2.8.0, and fsspec 2026.2.0 to 2026.9.0
    (#102). Require those versions in published package metadata too, so normal pip
    upgrades cannot silently retain the older versions (#165).

The ownership fixes prevent new invalid relationships. They do not remove cross-user links or
project references that an earlier version may already have stored.

Memory Plugin

Add an optional administrator-configured MemoryPlugin registration with handlers for create,
update, obsolete and restore operations (#97, #164):

  • Before-save handlers can allow, warn or reject. Enforce mode blocks rejected writes; warn mode
    continues with warnings.
  • After-save handlers can return advisory warnings. Create handlers receive existing similarity
    results and resulting links; no extra similarity searches are added to other operations.
  • MCP, REST and CLI responses expose warnings while preserving successful response shapes.
    After-save failures cannot veto or roll back a completed write.

The plugin is disabled by default and runs trusted administrator Python with server privileges.
Configure MEMORY_WRITE_PLUGIN to reference a module:object containing a MemoryPlugin.
See the plugin contract and examples.

This is the first published version of the plugin. Users who tested the earlier unreleased
single-function contract on main must update their registration; ordinary 0.5.5 installations
have no plugin contract to migrate. Timeouts remain cooperative, and handlers have no durable
retry or delivery guarantee. After a cancelled request or lost response, check stored state
before retrying a write.

Other changes

  • Add unobsolete_memory to restore a memory mistakenly marked obsolete (#88).
  • Run FastEmbed work off the event loop with a bounded worker pool. The new
    EMBEDDING_MAX_CONCURRENCY setting defaults to 1; increasing it is optional. DirectML requires
    1. This limits active work per process, not the waiting queue (#101).
  • Add public GET /.well-known capability discovery for planning, skills, files and activity
    streaming. It reports enabled features without creating a user (#99).
  • Treat explicit null fields in memory updates as unchanged; empty relationship lists still
    clear associations (#100).
  • Fix Windows OAuth token-cache paths (#93) and recovery after failed embedding rebuilds
    (6d0199e).
  • Improve MCP project-ID validation, project name-lookup guidance and concurrent user-creation
    recovery.
  • Add architecture-boundary checks and broader backup, recovery, plugin and Windows test coverage.

Upgrade and known limitations

  • No new database migration or embedding rebuild is required when upgrading from 0.5.5.
  • Python remains 3.12 or newer. PyJWT, urllib3 and fsspec now have explicit fixed-version
    requirements; other existing runtime requirements are unchanged. Two development-only
    architecture-check packages were also added.
  • Upgrade PyPI installations with python -m pip install --upgrade forgetful-ai==0.6.0 in the
    intended environment, then run python -m pip check. Normal dependency resolution upgrades
    these three dependencies or reports a conflict. Do not use --no-deps to bypass the requirements.
    Locked source installations can use uv sync --locked; Docker users can select the 0.6.0 image.
  • The MCP scope changes do not enforce scope restrictions on REST endpoints. REST authorization is
    tracked separately in #155; do not rely on MCP tool restrictions to protect REST.
  • The separate empty-instance-permission-set fallback is unchanged. Do not use an empty resolved
    tool set as a deny-all configuration; see the configuration guide.

Contributors

Thanks to @bertheto, @leninworld and @giovannimanzoni for contributions included in this release.

Full changelog