Skip to content

Legacy access_tokens ignore permissions.source_id; MCP reads silently return empty in non-default brains #1336

@MacGyverBot

Description

@MacGyverBot

Environment

  • v0.40.7.2, postgres engine
  • Single brain with one non-default source (e.g. source_id='brain', no sources.default set or set to that source)
  • Legacy access_tokens row (pre-OAuth, bearer token used by an MCP client)

Symptom

All MCP read ops silently return empty:

  • list_pages[]
  • get_page → not found
  • query / search → no hits

…even though the brain has hundreds of pages on disk and in DB. Writes via MCP also land in the wrong place (under a default source dir) until the routing is fixed.

Root cause

src/core/oauth-provider.ts (around line 596 on 0a03ca82) hardcodes sourceId: 'default' for the legacy bearer-token fallback, regardless of what's in access_tokens.permissions.source_id:

return {
  token,
  clientId: name,
  clientName: name,
  scopes: ['read', 'write', 'admin'],
  expiresAt: ,
  sourceId: 'default',   // ← ignores permissions.source_id
} as AuthInfo;

The CLI resolver path already honors a three-tier fallback (token perms → brain default → 'default'); the MCP/HTTP path doesn't.

Workaround (operator-side, what we did)

  1. gbrain sources default <id> to persist a brain-wide default.
  2. Hand-patch oauth-provider.ts to pull permissions from the access_tokens row and resolve sourceId = permissions?.source_id ?? brain_default ?? 'default'.
  3. UPDATE gbrain.access_tokens SET permissions = permissions || '{"source_id":"<id>"}' WHERE … for the legacy token.

After (1)+(2)+(3) all MCP reads/writes scope to the correct source.

Proposed fix

Make the legacy-token branch of oauth-provider.ts mirror the CLI resolver's three-tier semantics:

const perms = row.permissions ?? {};
const brainDefault = await this.getBrainDefaultSourceId(); // existing helper
const sourceId = perms.source_id ?? brainDefault ?? 'default';

Bonus drive-by: gbrain reindex unreachable

'reindex' is missing from CLI_ONLY in src/cli.ts (~line 30) even though case 'reindex' exists in the dispatch at ~line 1222. The command falls through and errors out. One-line add to CLI_ONLY fixes it.


Happy to send a PR if useful — let me know if you'd prefer to keep the legacy-token path explicitly 'default' and force operators onto OAuth for non-default sources instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions