Scope Resolution
Every MCP tool call that reads or writes memory must resolve a scope before it can proceed. Understanding scope resolution prevents blocked_scope write failures and confusing empty retrieval results.
ScopeState values
| State | Meaning | Read? | Write? |
|---|---|---|---|
resolved | Project exists in graph; focus (if given) exists as a FocusArea node | Yes (full) | Yes |
uncertain | project_id provided but no matching Project node exists yet | Yes (project scope only, no focus) | No |
unresolved | No project_id provided | No | No |
Resolution state machine
stateDiagram-v2
[*] --> unresolved : no project_id
[*] --> uncertain : project_id given, project not in graph
[*] --> resolved : project_id given, project exists
uncertain --> resolved : save_session creates Project node
resolved --> resolved : focus provided and FocusArea exists
resolved --> uncertain : project deleted from graph Practical flow
New project (first session)
# 1. Check state — project doesn't exist yet
get_scope_state(project_id="my-new-project")
# Returns: { scope_state: "uncertain", project_exists: false }
# 2. Save a session — this creates the Project node
save_session(session={...}, project_id="my-new-project")
# Returns: { status: "saved" }
# 3. Now scope is resolved
get_scope_state(project_id="my-new-project")
# Returns: { scope_state: "resolved", project_exists: true }
Using focus areas
# 1. Check scope with a focus area
get_scope_state(project_id="my-project", focus="auth-refactor")
# Returns: { scope_state: "uncertain" } ← FocusArea node doesn't exist yet
# 2. Save something with focus — this creates the FocusArea node
save_context(
context={"content": "...", "topic": "auth", "scope": "focus", "relevance_score": 1.0},
project_id="my-project",
focus="auth-refactor"
)
# 3. Focus is now resolved
get_scope_state(project_id="my-project", focus="auth-refactor")
# Returns: { scope_state: "resolved", project_exists: true }
Why writes block on uncertain scope
Writing to a project that doesn't exist would silently create orphaned nodes without a proper [:BELONGS_TO] relationship. The scope gate prevents this by requiring an explicit Project node before any non-session writes are allowed.
The exception is save_session — it is the bootstrapping tool that creates the Project node on first use. All other write tools (save_decision, save_pattern, etc.) require a pre-existing Project node and return blocked_scope if one doesn't exist.
Scope gate summary
| Tool | Allowed when uncertain? | Creates Project node? |
|---|---|---|
get_scope_state | Yes (read-only) | No |
retrieve_context | Partial (project scope only) | No |
save_session | Yes | Yes |
save_decision | No → blocked_scope | No |
save_pattern | No → blocked_scope | No |
save_context | No → blocked_scope | No |
upsert_entity_with_deps | No → blocked_scope | No |