Skip to main content
Glama

query_memory_graph

Read-onlyIdempotent

Run a graph query, in a Cypher subset, over the caller's own memory graph.

Use this when the user wants a structured traversal — shared-entity counts,
paths between events, tag membership — that a text query cannot express. Do
not use it for relational table facts; use `query_memories_with_sql` for that.
Do not use it when the starting point is a sentence and no pattern is stated;
use `find_memory_connections` for that.

Read-only.

The subset: a query opens with `START a = events(text: "..." | entity: "name
or id" | ids: [...], k: n)`, so the anchor set is always events. `k` defaults
to 5 and by default goes up to 20, or 200 with `entity:` alone. Events reach
events through `SHARES` (shared entities), `SIMILAR` and `FAR` (vector),
`NEXT`, and `RESOLVED_BY`, which runs `(plan)-[:RESOLVED_BY]->(evidence)`
from a plan or expectation to the memory that realized it and carries
`r.relation` and `r.asserted_at`; revoked links never appear. Events reach
entities through `PARTICIPATED_IN` and tags through `MEMBER_OF`; entities
reach entities through `CONNECTED` (stored co-occurrence) and `SAME_AS`
(stored alias). There is no `WITH` — conditions go in relation parameters
such as `{min: 3}`. The rest is ordinary Cypher: `MATCH`, `WHERE`,
`RETURN [DISTINCT]`, `ORDER BY`, `LIMIT`, aggregates in `RETURN`, `$name`
parameters, and `cos(a, b)`. Without `LIMIT`, rows stop at 20; `LIMIT` goes
up to 200.

Name match: `WHERE e.name CONTAINS $part` keeps the rows whose `Entity.name`
or `Tag.name` holds that piece, ignoring letter case and full-width forms. A
piece that is all ASCII needs two characters; one Hangul or Han character is
enough. It runs on the rows the walk already returned, so when
`truncated` is non-empty an empty result means the piece was not seen in what
was reached, not that no such name exists.

Scoped start: `events(entity: $name, text: $q, k: n)` ranks, by closeness to
`$q`, just the events that entity takes part in; `tag: $t, text: $q` does the
same inside a tag, and `tag:` alone gives its newest events. A list,
`entity: ["A", "B"]`, keeps events with any of the names; `entity_all:` or
`tag_all:` keeps events with all of them; `entity:` with `tag:` keeps events
matching both. Every part must hold and any name holds a part; there are no
brackets, no negation and no entity-or-tag choice. Up to 10 names in all;
`start.unresolved` lists the `{kind, name}` not found, and a part with no
name found gives no rows. The combined starts take `k` up to 20 and `tag:`
alone up to 200 by default; a server can set other caps, and `budget.caps`
in the response shows the ones in force. Names match exactly, up to 20
entities or tags; `start.entities_truncated` or `tags_truncated` says more
matched. `a.score` is the start event's cosine to
the start text, null when there is no text and on events reached by a hop;
nulls sort last, so use `ORDER BY a.score DESC, a.id` for a stable order.
`start.scoped_mode` is `exact` or `filtered_ann` (a large scope searched
through the vector index). `exact` measures every candidate's distance but
returns only the top `k`; `start.has_more: true` says the scope holds more
candidates than came back. A scope not fully covered (`filled: false` or a
names cap) adds a `stage: start` entry to `truncated` and sets `partial`
whatever the row count; 0 rows then means not confirmed, not absent.
`MATCH` can be left out when the start itself is the answer: `START a =
events(entity: $name, text: $q, k: 20) RETURN a, a.score ORDER BY a.score
DESC, a.id`. An arrow left off a directed relation is filled in, with a
line in `notes`, when the end labels allow one way only, as
`(a)-[:MEMBER_OF]-(t)` from an event reads `->`; `NEXT` and `RESOLVED_BY`
join two events and still need their arrow.

Example: `START a = events(text: $q, k: 3) MATCH (a)-[:PARTICIPATED_IN]-(e)
-[:PARTICIPATED_IN]-(b) RETURN b, count(DISTINCT e) AS shared ORDER BY shared
DESC LIMIT 20`

Args:
    query: The graph query text.
    params: Values for `$name` references (strings, numbers, lists).

Returns:
    `{columns, rows, row_count, start, partial, truncated, plan, budget,
    notes}`. Rows are projected: an Event to `{id, summary, timestamp,
    order_index}`, an Entity to `{id, name, type}`, a Tag to `{id, name}`.
    Budget caps, including a START cut short (`stage: start`), are
    reported in `truncated`, never applied silently.
    Rejections come back as `{error, blocked_by: syntax|grammar|params,
    hint?, allowed_*}`.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesThe graph query text.
paramsNoValues for `$name` references (strings, numbers, lists).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, and the description's 'Read-only.' merely restates that. It does add real behavioral context elsewhere — budget caps surfaced in `truncated` and never applied silently, revoked RESOLVED_BY links never appearing, arrow inference logged in `notes`, null-sorting order, and the `{error, blocked_by, hint?, allowed_*}` rejection shape. That is meaningful, but it is largely specification of the query language rather than disclosure of operational traits (auth, latency, side effects), so a 3 is the honest ceiling against rich annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose, exclusions, and example are front-loaded, and there is light sectioning ('The subset:', 'Name match:', 'Scoped start:', 'Returns:'). But the body is a dense multi-paragraph reference manual covering edge cases (full-width matching, Hangul/Han thresholds, arrow inference) that would be better placed in external docs, and it runs well past what a selection-time description needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a high-complexity query tool the description is complete: it documents the grammar subset, defaults and caps, partial-result semantics (`partial`, `truncated`, `stage: start`), scoping modes, an inline example, and the error envelope. An output schema exists, so return values need not be re-explained, and it still summarizes row projection and budget reporting adequately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the schema only says 'The graph query text.' and 'Values for `$name` references.' The description supplies the entire semantics of `query` — the START grammar, relation set, defaults for `k`, limits, scoping modes — and clarifies `params` as `$name` bindings accepting strings, numbers, and lists. It adds far more meaning than the structured fields carry.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a precise verb, resource, and scope: 'Run a graph query, in a Cypher subset, over the caller's own memory graph.' It immediately distinguishes itself from siblings by naming query_memories_with_sql and find_memory_connections and stating the conditions that route to each.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use ('structured traversal — shared-entity counts, paths between events, tag membership — that a text query cannot express') plus two explicit when-not-to-use clauses naming the correct alternative tools. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.