recordari
Server Details
Persistent knowledge graph for AI-augmented teams. Store decisions, findings, and standing rules across agent sessions with semantic search and typed connections. Includes cross-session memory, audit trail, workspace isolation, and secret detection. Built for teams running agents that need to remember. Free until launch with team tier as default, anon trial available.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP
- URL
Available Tools
16 toolsauditARead-onlyInspect
Inspect the health of the knowledge graph. mode=stale: surface drift candidates (contradictions, superseded labels, duplicates, stale open questions, old transient memories, and shadow rows — memories stored under an alternate domain name rather than the canonical domain, making them unreachable by domain-scoped reads). mode=orphans: return memories with no connections. mode=archived: list archived memories — only call forget(restore=true) on any listed memory after explicit unambiguous user confirmation; never on implication or casual mention. mode=conflicts: domain-wide sweep for semantically close memory pairs, ranked by authority severity (STORY-135) — candidate-surfacing only, same aboutness-not-agreement caveat as remember()'s possible_contradicts: the server never asserts these pairs actually conflict, only that they are worth your review. Connecting a flagged pair with any relationship (in either direction) suppresses it from future conflicts sweeps; a later substantive revision to either memory lifts the suppression and the pair resurfaces. Returns lean results only — id, label, and a truncated why_matters excerpt; call recall(id) for full content. When a list or section has 2 or more results, each is rendered as a single compact text line — "[id] label — excerpt (domain, node_kind)" — instead of a JSON object; exactly one result is returned as a full object.stale digest lines also carry reason= and conflicts_with= when present, and state= when set. Optional domain, limit, tags, node_kind, and state filters. tags (space-separated) filters results to memories carrying any of those tags — applies to stale, orphans, and archived modes. node_kind (space-separated union) filters results to matching kinds — applies to all modes. Negation and wildcards are not supported. state (space-separated union) post-filters results to memories with any of the given lifecycle states: none | resolved | superseded | contested — applies to stale, orphans, and archived modes. memory_id (stale mode only) restricts drift results to the depth-2 neighbourhood of that memory; silently ignored in other modes.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | ||
| tags | No | ||
| limit | No | ||
| state | No | ||
| domain | No | ||
| memory_id | No | ||
| node_kind | No | Optional filter: space-separated node kinds (union match, same convention as tags). E.g. 'option standing' returns memories whose node_kind is option OR standing. Negation and wildcards are not supported. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool readOnly and non-destructive, and the description adds substantial behavioral context beyond that: lean result shape, compact text-line rendering vs full object, suppression of conflict pairs, memory_id being silently ignored in other modes, and which filters apply to which modes. This gives the agent a realistic model of how the tool behaves at call time.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but information-dense, with the core purpose front-loaded and each mode and filter earning its place. Some parenthetical asides, such as the shadow-rows explanation, add necessary context. It is structured effectively, though it could be tightened without losing key details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given seven optional parameters, no output schema, and multiple modes, the description covers most of what an agent needs: mode semantics, filter behavior, output format variations, suppression behavior, and cross-tool safety guidance. Minor gaps remain, such as domain/limit semantics and definitive mode enum values, but overall it is nearly complete for a tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 14%, so the description carries most of the burden, and it largely succeeds: tags, node_kind, state, and memory_id all receive semantic explanations. However, domain and limit are named but not given semantics such as allowed domain values or default/maximum limits, so compensation is strong but not complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Inspect the health of the knowledge graph,' then enumerates four distinct modes (stale, orphans, archived, conflicts) that make the tool's scope concrete. This clearly separates audit from sibling retrieval tools like recall and search, even without naming them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Each mode is tied to a specific use case, e.g., stale surfaces drift candidates, orphans returns memories with no connections, and conflicts surfaces semantically close pairs. It also gives an explicit safety rule for archived mode ('only call forget(restore=true) ... after explicit unambiguous user confirmation') and points to recall(id) for full content. However, it does not explicitly say when to prefer a sibling tool over audit, so it stops short of full when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
connectAInspect
Create one or more typed connections between memories. relationship: connects_to (default) | depends_on | led_to | blocked_by | contradicts | resolved | caused_by | unblocks | is_example_of — or any custom type. relationship=resolved adjudicates a contradiction between the exact from_memory/to_memory ids you pass: it is pure-additive and does NOT remove any existing contradicts connection between the pair — both remain on the record, preserving the full contradicts-then-resolved timeline. "Works on any pair" means you do not need to have called connect(relationship=contradicts) first — it does NOT mean any topically-similar pair will do. If you are resolving a hit from audit(mode=stale) or a possible_contradicts suggestion, verify the exact two ids first with why_connected rather than inferring them from labels alone — a newer or related memory with a similar label has a different id from the one actually holding the contradicts connection, and resolving the wrong pair leaves the real contradiction unadjudicated with no error to warn you. Optionally pass verdict (false_positive | reconciled | superseded) to classify the outcome; stored on the connection and returned by recall. Once resolved, the pair stops surfacing in audit(mode=stale) and its contradicts penalty in significance(mode=trust) is lifted. When relationship=resolved and either endpoint is human-owned by another workspace member, override_reason (required) and override_confirm=true (required) are needed — Editor or Owner role only; agent-owned or your own human-owned endpoints need no override. override_reason/override_confirm apply to the single-memory form only — batch connect has no override path for such resolutions; call connect individually instead. Single: pass fields directly. Batch: {items:[{from_memory,to_memory,relationship,narrative},...]} — returns {edges_created:N} and, when present, rejections:[{from_memory,to_memory,error_class,message}] for items that could not be applied.
| Name | Required | Description | Default |
|---|---|---|---|
| items | No | ||
| verdict | No | ||
| narrative | No | ||
| to_memory | No | ||
| from_memory | No | ||
| relationship | No | ||
| override_reason | No | ||
| override_confirm | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description reveals important behaviors beyond the sparse annotations: relationship=resolved is pure-additive and does not remove existing contradicts connections, wrong-pair resolutions fail silently, override requires Editor/Owner role, and resolved pairs stop appearing in audit and significance. This is exactly the kind of behavioral context annotations do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and long, but nearly every sentence carries essential caveats or constraints. It front-loads the core purpose and relationship list before diving into edge cases, though the run-on style and heavy use of quotes make it harder to scan quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, lack of output schema, and conditional authorization requirements, the description covers the critical ground: single vs batch, return shape, rejection reporting, cross-owner overrides, and integration with audit and significance. An agent has enough to call this tool correctly in most scenarios.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero schema description coverage, the description compensates by explaining relationship values/default, verdict options, override_reason/override_confirm conditions, and batch structure. However, narrative is only mentioned in the batch shape without any semantic explanation, and from_memory/to_memory are described indirectly as ids rather than explicitly defined.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Create one or more typed connections between memories.' It enumerates the supported relationship types, including a default, so an agent knows exactly what the tool does and can distinguish it from sibling tools like disconnect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance, including verifying ids with why_connected before resolving audit suggestions, using the single form when override is needed, and avoiding batch connect for resolved cross-owner conflicts. It also clarifies the intended scope of 'works on any pair,' preventing misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
disconnectADestructiveInspect
Remove one or more connections. Single: {id}. Batch: {ids:[id,...]} — returns {results:[{id,success,error}]}.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | ||
| ids | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The destructiveHint=true annotation already signals mutation, and 'Remove' is consistent with it. The description adds genuinely useful behavior: it explains single versus batch processing and the per-item success/error result envelope, which are not derivable from annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences carry the entire necessary payload: action, scope, parameter syntax, and return shape. There is no wasted wording, and the primary action is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity destructive tool with no output schema, the description covers input, output, and semantics efficiently. It stops short of advising when to choose single versus batch mode, but the semantics are simple enough that this is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by documenting both parameters explicitly: 'id' for single removal and 'ids' for batch removal. It also gives concrete payload shapes and the result format, so an agent understands how to invoke the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a precise verb ('Remove') and resource ('connections') and immediately clarifies both invocation modes. It is clearly scoped relative to siblings like 'connect' (the opposite action) and 'remember'/'forget' (which manage memories rather than connections).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no explicit when-to-use or when-not-to-use guidance, and it does not mention alternative tools. Usage context must be inferred entirely from the tool name and sibling list, so an agent gets no direct routing help.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
domainsAInspect
Domain administration and discovery. Default (action=list or omit action): return all domains with at least one live memory and all registered aliases ({domains:[...], aliases:[{alias,canonical_domain},...]}). action=alias: register a new alias ({alias,domain} required) — rejected if the alias name already has live memories (move or archive them first). Synonyms: add, create. action=unalias: delete a registered alias ({alias} required). Synonyms: remove. action=resolve: return the canonical domain for a name ({name} required). action=rename: rename a domain in place — all memories move from old_domain to new_domain, and an alias from old_domain is registered automatically ({old_domain,new_domain} required). Precondition for rename: new_domain must not already have memories — if it does, use merge_domains instead.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| alias | No | ||
| action | No | ||
| domain | No | ||
| new_domain | No | ||
| old_domain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description provides rich behavioral detail, including memory movement on rename, automatic alias registration, and the rejection of aliases with live memories. However, it directly contradicts the annotations: destructiveHint=false while action=unalias explicitly deletes a registered alias and rename mutates domain state in place. This makes the safety signal unreliable and earns a score of 1 under the contradiction rule.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but densely structured, with no filler. Each sentence adds a distinct behavior, precondition, or synonym, and the default/list behavior is front-loaded before the action-specific cases. This is efficient for a six-parameter multi-action tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex multi-action tool with no output schema, the description covers the default return shape, the resolve return shape, preconditions, and the merge_domains alternative. The main gaps are that return values for alias, unalias, and rename are not specified, and no auth/permission context is given, but these are minor given the overall detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the full burden for all six parameters. It maps every parameter to a concrete action and condition: {alias,domain} for alias registration, {alias} for unalias, {name} for resolve, {old_domain,new_domain} for rename, and action values/synonyms are listed explicitly. This fully compensates for the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource pair, 'Domain administration and discovery,' and then details every action (list, alias, unalias, resolve, rename) with its specific effect and required parameters. The default behavior is explicitly defined, so an agent can distinguish this tool from the memory- and search-focused siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states exactly when to omit action (default list), enumerates action choices and synonyms, and gives a concrete exclusion: if the new_domain already has memories, use merge_domains instead. It also tells the agent to move or archive live memories before registering an alias, making the routing guidance explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
forgetADestructiveInspect
Archive (soft-delete), un-archive, or permanently purge one or more memories. ARCHIVE (default): Only call after explicit unambiguous user confirmation — never on implication or casual mention. If archiving multiple memories, prefer the items array — the same confirmation protocol applies. Single archive: {id, reason}. Batch archive — use this when you have 2 or more confirmed memories to archive at once; more efficient than multiple single calls: {items:[{id,reason},...]} — returns {results:[{id,success,error}]}. RESTORE: Pass restore=true to un-archive an archived memory — obtain the ID from audit(mode=archived). Same explicit confirmation gate as archive. Single restore: {id, restore:true}. Batch restore: {items:[{id},...], restore:true}. PURGE (hard delete): Pass purge=true to permanently delete an already-archived memory and all its connections. Purge only operates on archived memories — archive the memory first if it is still live. A workspace key can only purge memories with no live inbound connections; connected memories return a structured warning listing live_inbound_connections rather than an error, and are not purged. Pass force=true (org_admin or platform key only) to override the connection guard and purge regardless. A workspace key passing force=true is rejected with error_class=forbidden. Single purge: {id, purge:true} or {id, purge:true, force:true}. Batch purge: {items:[{id},...], purge:true} — returns {results:[{id,purged,warning,error}]}. On failure, content[0].text is JSON: {"error_class": "not_found|retryable|forbidden|validation|internal", "message": "..."}. Switch on error_class: retry on retryable.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | ||
| force | No | ||
| items | No | ||
| purge | No | ||
| reason | No | ||
| restore | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite destructiveHint=true already signaling danger, the description adds crucial behavioral detail: archive is soft-delete, purge is hard delete, connected memories return structured warnings rather than errors, force can override the guard but is forbidden for workspace keys. It also discloses the JSON error format and retry guidance, which annotations alone would never convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but the complexity justifies it. Information is grouped by mode (ARCHIVE, RESTORE, PURGE), with examples inline and error handling at the end. A few patterns repeat, but each sentence adds operational value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive multi-mode tool with no output schema and minimal annotations, the description is remarkably complete. It covers preconditions, confirmation gates, permission restrictions, edge cases like live inbound connections, response shapes, and error handling. An agent has everything needed to call any variant correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full parameter semantics. It explains the role of id, reason, items, restore, purge, and force, maps them to each mode, and gives concrete request shapes for single and batch calls. This far exceeds what the bare schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the tool's exact operations: archive (soft-delete), un-archive, and permanently purge memories. It clearly distinguishes three modes with distinct intents and parameter shapes, so an agent knows precisely what resource and action are being invoked.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong operational guidance: explicit confirmation is required for archive/restore, batch use is recommended for multiple items, restore IDs must come from audit(mode=archived), purge only works on archived memories, and force is restricted to org_admin or platform keys. It also explains when to switch between single and batch calls, and how to handle failures via error_class.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
historyARead-onlyInspect
Return memories ordered chronologically. Default (important_only=false) includes all memories ordered by COALESCE(occurred_at, created_at) ASC. Set important_only=true to return only memories with occurred_at set (the curated decision timeline). Pass memory_id instead of domain to scope the timeline to a single memory's neighbourhood (depth 2 by default, domain-clipped) — useful for understanding how a specific workstream evolved. memory_id takes precedence if both domain and memory_id are supplied. Optional from/to date filters apply to the effective date. Optional tags filter uses whole-word matching. Optional node_kind filter (space-separated union) restricts timeline entries to matching kinds. For importance analysis beyond the timeline, use significance. Returns lean results only — id, label, and a truncated why_matters excerpt; call recall(id) for full content. When a list or section has 2 or more results, each is rendered as a single compact text line — "[id] label — excerpt (domain, node_kind)" — instead of a JSON object; exactly one result is returned as a full object. Each line also carries the memory's effective date.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | ||
| from | No | ||
| tags | No | ||
| depth | No | ||
| domain | No | ||
| memory_id | No | ||
| node_kind | No | Optional filter: space-separated node kinds (union match, same convention as tags). E.g. 'option standing' returns memories whose node_kind is option OR standing. Negation and wildcards are not supported. | |
| important_only | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark read-only and non-destructive, and the description adds substantial operational detail: precedence of memory_id over domain, depth default, effective-date filtering, whole-word tags matching, node_kind union semantics, lean result shape, and multi-result line rendering. This goes well beyond structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence adds operational information, with the core behavior front-loaded. While a bulleted structure could improve scannability, there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given eight optional parameters, no output schema, and no required fields, the description explains result formatting, single vs multi-result rendering, effective dates, and filter interactions. There is no obvious gap an agent would need to make a correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 13% with just node_kind described, so the description carries the weight for all eight parameters. It explains from/to date filtering, tags whole-word matching, important_only semantics, depth, memory_id precedence over domain, and node_kind union behavior—fully compensating for the sparse schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Return') plus resource ('memories') and specifies chronological ordering. It also distinguishes itself from siblings by describing scope and explicitly routing importance analysis to significance and full content to recall.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent to use recall(id) for full content and significance for importance analysis beyond the timeline. It also clarifies when memory_id is useful for understanding a specific workstream's evolution, giving clear selection context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
orientARead-onlyInspect
Get a bounded orientation snapshot. If stale_count > 0, call audit(mode=stale) before filing new memories. If conflicts_count > 0, call audit(mode=conflicts) to review semantically close memory pairs — candidate-surfacing only, not confirmed contradictions. conflicts_count is a density signal, not a monotonically-decreasing queue: connecting a flagged pair suppresses it, but a later substantive revision to either memory lifts the suppression, so the count can rise again without indicating new drift. pass topic when the session has a known purpose — orient will run a semantic search for the topic within the resolved domain and return a relevant section instead of significant. Omit domain (or pass no domain) to get a cross-domain bootstrap snapshot listing all active domains with their per-domain counts (total_nodes, owned_contradiction_count, owned_superseded_count, others_change_count, other_member_count, stale_count) — use this at session start when you do not yet know which domain to work in; call audit(mode=conflicts) for full contradiction pairs. The owned_* fields (owned_contradiction_count, owned_superseded_count, others_change_count, other_member_count) are computed only for authenticated callers with a personal identity (scope=mine or scope=user:); they are always 0 for plain workspace-key sessions (scope=all). stale_count is always populated regardless of scope. Pass a domain to get the full orient response for that domain: rules — up to 20 standing constraints and durable decisions (node_kind='standing') ordered by inbound connection count DESC; always present (empty array when none); rules_count gives the true total — when rules_count > len(rules), call search(node_kind='standing', domain=X) to retrieve the full set. declared_spine — memories with occurred_at set, sorted chronologically (up to 20); these are the curated significant decisions that shaped the domain. significant (when topic is absent) — up to 10 structurally load-bearing memories ranked by recency-weighted importance; these are the memories the domain currently depends on most. relevant (when topic is supplied) — up to 10 memories semantically matched to the topic; replaces significant. recent — the most recently updated memories by the caller (owner-scoped by default; domain-wide when scope=all); shows where your active work is happening. digest (present when scope is personalised) — since-you-were-last-here summary: others_change_count, other_member_count, members list, owned_contradiction_count and owned_contradictions (conflict pairs where the caller owns at least one memory), owned_superseded_count and owned_superseded (archived memories you owned that another member superseded — read from supersedes relationships, not audit_log). summary_hint — a prompt you can pass to an LLM to synthesise the orient data into a narrative paragraph. Overlap between sections is intentional and meaningful: a memory appearing in both significant and declared_spine is both historically important and structurally central. Returns lean results only — id, label, and a truncated why_matters excerpt; call recall(id) for full content. When a list or section has 2 or more results, each is rendered as a single compact text line — "[id] label — excerpt (domain, node_kind)" — instead of a JSON object; exactly one result is returned as a full object.Multi-entry sections (rules, declared_spine, significant/relevant, recent) render as single-line digest strings at 2+ entries. The response always includes server_version — a stable string identifying the current tool surface. If server_version differs from a previously cached value, call tools/list again before issuing any tool calls — the tool surface has changed and your cached schema is stale. Do not call orient again to find more memories — the sections are bounded by design. If you need to find something specific, use search with a targeted query instead.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | Controls whose memories appear in the `recent` section and which contradictions are flagged. 'mine' (default when authenticated) — recent and contradictions scoped to the caller; 'all' — domain-wide, no personalisation (previous default, still the default for plain workspace-key sessions); 'user:<ref>' — view as another member, where ref is a user_id UUID or email address. | |
| topic | No | Optional topic for the session. When supplied, replaces the significant section with a relevant section of semantically matched memories (up to 10). | |
| domain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false, so the description does not need to restate safety. It goes beyond annotations with rich behavioral detail: conflicts_count is a density signal, not a monotonically-decreasing queue; suppression mechanics; owned_* fields are zero for plain workspace-key sessions; lean results render as single-line digest strings at 2+ entries; overlap between sections is intentional; server_version staleness handling. This is exactly the kind of non-obvious behavior an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and information-rich, and it front-loads the core purpose well. However, it is very long and covers a lot of output-section detail that is arguably output-schema territory; an agent must parse several hundred words before reaching the action items. Every sentence does earn its place functionally, but the lack of structural formatting (headers, bullets, separation of summary vs edge cases) makes it harder to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only orientation tool with no output schema, the description fully compensates: it explains return sections, their counts, when they appear, how to handle truncation (rules_count > len(rules) → search), how to get full content (recall), rendering format, scope-dependent fields, and server_version handling. There is no output schema, so this level of descriptive detail is necessary, and it is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67%, and for the documented parameters (scope, topic) the schema already provides solid semantics. The description compensates for the undocumented domain parameter with extensive details about passing a domain vs omitting it, and it adds critical behavioral semantics for scope (which fields are computed per scope) and topic (replaces significant with relevant). A slight deduction because the domain parameter itself has no schema description, but the description more than covers its meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: "Get a bounded orientation snapshot." It then enumerates the exact sections returned (rules, declared_spine, significant/relevant, recent, digest) and how they differ, which clearly distinguishes this tool from siblings like search, recall, and audit. The purpose is unambiguous and grounded in named outputs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: omit domain at session start for a cross-domain bootstrap; pass topic for a purpose-driven session; call audit(mode=stale) if stale_count > 0; call audit(mode=conflicts) for full contradiction pairs; use search instead of orient for finding specific memories; and call tools/list again if server_version changed. It also tells the agent when not to call orient again because sections are bounded. This is exemplary routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recallARead-onlyInspect
Retrieve a memory by ID along with its connections. On failure, content[0].text is JSON: {"error_class": "not_found|retryable|forbidden|internal", "message": "..."}. Switch on error_class: retry on retryable, prompt user to check the ID on not_found.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description does not contradict them. It adds significant behavioral detail beyond annotations: on failure, content[0].text is a JSON error envelope with a specific error_class discriminator and a suggested recovery action per error type.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with the primary action front-loaded and error-handling instructions compactly integrated. No filler, redundancy, or repetition of annotation information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with no output schema, the description covers the failure response format and recovery steps well. The successful return structure is only summarized as 'memory along with its connections', which is sufficient for high-level invocation but leaves parsing details implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies that 'id' refers to the memory ID, which adds some meaning, but it does not describe ID format, validity, or optionality. Compensation is partial for a single-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description uses a specific verb ('Retrieve'), a resource ('a memory by ID'), and an additional output ('along with its connections'). This clearly distinguishes it from siblings like remember, forget, and search, which create, delete, or query memories differently.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies clear usage context: call when you have a memory ID and need that memory plus its connections. It also gives explicit guidance on failure handling—retry on retryable errors and prompt the user to verify the ID on not_found—though it does not name alternative tools or exclusion cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recentARead-onlyInspect
Return recently modified memories, optionally grouped by domain. Pass tags (space-separated) to filter to memories tagged with any of those tags (union match). Pass node_kind (space-separated) to filter to specific kinds (union match, same convention as tags). Pass memory_id to restrict results to memories directly connected to that memory, ordered by updated_at DESC. When both are supplied the intersection is returned (tags AND connected to memory_id). When neither is supplied the existing behaviour is unchanged. Returns lean results only — id, label, and a truncated why_matters excerpt; call recall(id) for full content. When a list or section has 2 or more results, each is rendered as a single compact text line — "[id] label — excerpt (domain, node_kind)" — instead of a JSON object; exactly one result is returned as a full object. In group_by_domain mode each line omits domain (already the group key).
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| limit | No | ||
| domain | No | ||
| memory_id | No | ||
| node_kind | No | Optional filter: space-separated node kinds (union match, same convention as tags). E.g. 'option standing' returns memories whose node_kind is option OR standing. Negation and wildcards are not supported. | |
| group_by_domain | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the readOnlyHint/destructiveHint annotations, disclosing union matching, intersection behavior, updated_at ordering, lean result format, and compact text-line rendering rules. These behavioral details materially change how an agent should interpret results and are not available elsewhere.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and mostly front-loaded with the core behavior. It contains several necessary output-format details, though the phrase 'the existing behaviour is unchanged' is vague and the rendering rules could have been tightened. No sentence is purely filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description appropriately explains the return format and directs the agent to recall for full content. It is complete enough for the main use case, but unexplained limit and domain parameters leave moderate ambiguity in a six-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 17%, so the description must compensate. It does explain tags, node_kind, memory_id, and group_by_domain semantics thoroughly, but it leaves limit and domain without explicit meaning. This is a real gap, but the description still adds substantial value for most parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Return recently modified memories', and adds an optional grouping dimension. It clearly differentiates itself from recall by stating 'call recall(id) for full content', so an agent can distinguish listing recent memories from retrieving a full memory.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear conditional guidance for tags, node_kind, memory_id, and their interaction, and explicitly routes to recall for full content. It does not explicitly contrast with search or history, but the tool's purpose and alternatives are clear enough for correct selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rememberAInspect
Store one or more new memories (concepts, decisions, findings). Before filing, search for related content first — use the search results to infer the domain: if related memories exist in a domain, file there. Prefer existing domains over creating new ones; only propose a new domain if no related content is found anywhere. Single: pass fields directly — returns {memory, suggested_connections}. Batch: pass {items:[{label,domain,...},...]} — returns {memories:[{memory,suggested_connections},...]}. After filing, review suggested_connections for agreement or contradiction with what you just filed — not only for connect opportunities. Semantic similarity reflects aboutness, not agreement; the server surfaces candidates that may warrant your review but never asserts they conflict. When a filed memory is close enough to an existing memory that they may be worth comparing, the response also includes possible_contradicts=true and possible_contradicts_candidates (id, node_kind, semantic_distance, authority_severity) — same aboutness-not-agreement caveat: the server flags these as worth your attention, never as confirmed contradictions. Review them and call connect(relationship=contradicts) if you judge they actually conflict. ALWAYS call connect for any suggested_connections you accept before ending your session (batch: connect each accepted candidate). On failure, content[0].text is JSON: {"error_class": "conflict|retryable|forbidden|validation|internal", "message": "..."}. Switch on error_class: retry on retryable, surface message on validation, treat conflict as duplicate.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Optional caller-supplied id instead of an auto-generated one. For idempotent external imports: if a memory with this id already exists, remember fails with error_class=conflict rather than overwriting it — call recall(id) to check first, or treat a conflict response as already-imported. | |
| tags | No | ||
| items | No | ||
| label | No | ||
| domain | No | ||
| node_kind | No | Classification of this memory. One of: 'transient' (temporary, will expire), 'decision' (a specific decision made, default), 'standing' (a durable rule or principle), 'reference' (a person, system, or org — referential rather than propositional knowledge), 'issue' (an open question or problem), 'option' (a considered alternative), 'assumption' (an unverified premise), 'finding' (an observed fact or result), or 'goal' (a desired outcome). Absent defaults to 'decision'. Takes precedence over the transient bool field when both are supplied. | |
| transient | No | ||
| related_to | No | ||
| description | No | ||
| occurred_at | No | When this event actually happened (not when it is being filed). Format: YYYY-MM-DD or RFC3339. Two cases: (a) Events you directly witnessed during the current session (e.g. a decision made in the live conversation) — set occurred_at without asking; if the user did not specify a date, use today. (b) Inferred or back-dated historical events you did not directly observe — propose+confirm: state the date and your reasoning, ask the user to confirm, and only set occurred_at once confirmed. Never guess a historical date and never infer it silently from context. Turn-boundary rule: when proposing to file something as significant, the proposal must be the only action in that turn — do not include occurred_at in any remember or revise call in the same message as the proposal. Only set occurred_at in a subsequent call, after the user has replied. Always set why_matters when using occurred_at. | |
| why_matters | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses many non-obvious behaviors beyond the sparse annotations: suggested_connections reflect aboutness not agreement, possible_contradicts are flagged as candidates rather than confirmed conflicts, and failures return a structured error_class with explicit handling rules ('retry on retryable, surface message on validation, treat conflict as duplicate'). These details substantially exceed what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but logically ordered: purpose, pre-filing search, invocation shapes, post-filing review, contradiction handling, connect mandate, and error handling. Each sentence adds a distinct piece of guidance with minimal redundancy, though the continuous prose format could be more scannable with paragraph breaks or bullet lists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex write tool without an output schema, the description thoroughly covers return values ({memory, suggested_connections}, {memories:[...]}), the error JSON structure, domain inference, and the mandatory connect step. It does not explicitly explain every parameter, but many are self-explanatory or covered by the schema, making the description complete enough for correct invocation in most cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema coverage at only 27%, the description compensates partially by clarifying the two invocation shapes ('Single: pass fields directly' and 'Batch: pass {items:[{label,domain,...},...]}') and their return formats. However, several parameters (tags, transient, why_matters, related_to) are not explained beyond the sparse schema, leaving their meanings to inference. The compensation is partial, not complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Store one or more new memories (concepts, decisions, findings)', naming a specific verb (store), resource (memories), and scope (new). It clearly differentiates from siblings such as recall (read), revise (update), forget (delete), and search (query) by focusing on creation, and it distinguishes the singular and batch invocation forms.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit workflow guidance: 'Before filing, search for related content first — use the search results to infer the domain' and 'Prefer existing domains over creating new ones'. It also mandates post-action behavior with 'ALWAYS call connect for any suggested_connections you accept before ending your session', naming complementary tools (search, connect) and making the conditions for use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reviseAInspect
IMPORTANT — bulk domain migration: domain moves via revise are for individual corrections only. If the user needs to move many memories between domains, inform the user that bulk migration must be performed via the admin interface (merge_domains) — do not attempt to replicate a merge by looping revise calls. Update one or more existing memories. Omitted fields are unchanged. Single: pass fields directly — returns {updated, connections, suggested_connections} and, when the filing-time threshold is crossed, possible_contradicts + possible_contradicts_candidates (same shapes as remember()). Batch: {items:[{id,...},...]} — returns {items:[{id, updated, connections, suggested_connections, ...}]} with a per-item envelope on each success, not only an updated count. After every successful revise — plain update, override, claim, or supersede — review connections, suggested_connections, and possible_contradicts in the same turn; do not defer to a separate recall or suggest_connections call. Semantic similarity reflects aboutness, not agreement; the server surfaces candidates that may warrant your review but never asserts they conflict. Every memory has an owner (whoever created it) — revising a memory you don't own is rejected with error_class=forbidden unless you are an Editor or Owner and supply override_reason (required) plus override_confirm=true (required only when the memory is human-owned; not required for agent-owned or ownerless memories). The override path requires a session with a workspace role (a human JWT session, or a personal key linked to an Editor/Owner user); sessions on plain workspace keys cannot override regardless of arguments. An override changes content in-place, not ownership — substantive changes (label, description, why_matters, node_kind) on a foreign-owned memory are rejected; use supersede=true instead, which creates your successor memory, archives the original intact, and wires a supersedes relationship. supersede=true (single-memory form only) returns {superseded, archived_id, archived_connections} plus the revise envelope on the successor; foreign supersede uses the same override_reason/override_confirm ceremony. Correction-class overrides (tags, occurred_at, transient) may still use in-place override. override_reason/override_confirm/supersede apply to the single-memory form only — batch revise has no override or supersede path: if any item in the batch targets a memory you don't own, the whole batch is rejected and none of it applies; revise that item individually instead. claim=true (single-memory form only) makes an ownerless memory (owner_id IS NULL — either it predates ownership tracking, or was orphaned by a member offboard) yours: requires Editor or Owner role, is rejected with error_class=validation if the memory already has an owner (use override or supersede instead), and error_class=conflict if someone else claimed it first (race). claim never moves a memory from one owner to another — only from no owner to you — and may be combined with other field updates in the same call. domain (single-memory form only) moves the memory to a different domain; domain_move_reason is required when domain is present — the call is rejected with error_class=validation if domain_move_reason is absent; domain equal to the memory's current domain is also rejected. On failure, content[0].text is JSON: {"error_class": "not_found|conflict|retryable|forbidden|validation|internal", "message": "..."}. Switch on error_class: retry on retryable, surface message on validation, re-fetch on not_found.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | ||
| tags | No | ||
| claim | No | ||
| items | No | ||
| label | No | ||
| domain | No | ||
| node_kind | No | Classification of this memory. One of: 'transient' (temporary, will expire), 'decision' (a specific decision made, default), 'standing' (a durable rule or principle), 'reference' (a person, system, or org — referential rather than propositional knowledge), 'issue' (an open question or problem), 'option' (a considered alternative), 'assumption' (an unverified premise), 'finding' (an observed fact or result), or 'goal' (a desired outcome). Absent defaults to 'decision'. Takes precedence over the transient bool field when both are supplied. | |
| supersede | No | ||
| transient | No | ||
| description | No | ||
| occurred_at | No | When this event actually happened (not when it is being filed). Format: YYYY-MM-DD or RFC3339. Two cases: (a) Events you directly witnessed during the current session (e.g. a decision made in the live conversation) — set occurred_at without asking; if the user did not specify a date, use today. (b) Inferred or back-dated historical events you did not directly observe — propose+confirm: state the date and your reasoning, ask the user to confirm, and only set occurred_at once confirmed. Never guess a historical date and never infer it silently from context. Turn-boundary rule: when proposing to file something as significant, the proposal must be the only action in that turn — do not include occurred_at in any remember or revise call in the same message as the proposal. Only set occurred_at in a subsequent call, after the user has replied. Always set why_matters when using occurred_at. | |
| why_matters | No | ||
| override_reason | No | ||
| override_confirm | No | ||
| domain_move_reason | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses far more than the annotations provide: ownership rejection with error_class=forbidden, override requirements, in-place vs. supersede semantics, claim ownership race behavior, domain-move validation, batch all-or-nothing rejection, and exact return shapes. It also reveals the post-success review convention for connections and possible_contradicts, which is behavior an agent could not infer from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely long, but nearly every sentence encodes a distinct behavioral rule, and the most urgent warning (bulk migration) is front-loaded. It loses a point for dense, wall-of-text structure that would be more scannable with bullets or clearer separation between the single, batch, override, supersede, claim, and domain cases.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and a high-complexity mutation tool, the description is exceptionally complete. It specifies both single and batch return envelopes, error handling via content[0].text JSON with error_class switching guidance, ownership/override paths, and the review obligation after success. An agent has enough information to invoke the tool correctly across all documented scenarios.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 13% schema description coverage, the description carries nearly the full semantic burden and succeeds. It explains the meaning and constraints of override_reason, override_confirm, supersede, claim, domain, domain_move_reason, and items, and clarifies that omitted fields are unchanged. This adds substantial meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise action ('Update one or more existing memories') and explicitly distinguishes revise from bulk migration via merge_domains and from remember() by scoping it to existing memories. It also clarifies the single vs. batch forms immediately, leaving no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: individual corrections only, never to emulate bulk merge by looping revise calls. It also provides conditional alternatives for override vs. supersede, claim vs. override, and single vs. batch, including when batch revise cannot be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchARead-onlyInspect
Search memories by keyword. The query must use vocabulary that appears in stored labels, descriptions, or tags — not intent summaries or paraphrases. Pass node_kind (space-separated) to list or search within specific kinds — unrelated kinds that happen to match query text are excluded. Omit query with node_kind set to list matching kinds ordered by most-recently-updated. Default limit: 10. Use exact=true for identifiers (ticket numbers, short codes with hyphens) — FTS tokenises hyphens away so 'PROJ-042' is not found by default. If search returns zero or truncated results, use orient (with domain) to browse all memories, then recall by ID, then follow connections from a known memory. Returns lean results only — id, label, and a truncated why_matters excerpt; call recall(id) for full content. When a list or section has 2 or more results, each is rendered as a single compact text line — "[id] label — excerpt (domain, node_kind)" — instead of a JSON object; exactly one result is returned as a full object. exact=true is exempt — it always returns full objects, regardless of result count. state (space-separated union) post-filters results to memories with any of the given lifecycle states: none | resolved | superseded | contested. On failure, content[0].text is JSON: {"error_class": "retryable|forbidden|internal", "message": "..."}. Switch on error_class: retry on retryable.
| Name | Required | Description | Default |
|---|---|---|---|
| exact | No | When true, use label substring (ILIKE) matching instead of FTS. Results are ordered by updated_at DESC with no semantic_distance. Use for identifiers like ticket numbers or short codes where FTS tokenisation loses the match. | |
| limit | No | Maximum results to return. Default: 10. If truncated is true in the response, raise the limit or narrow the query. | |
| query | No | Words to match against stored labels, descriptions, and tags. Use vocabulary from the stored content — if zero results, try words that are likely in the stored text rather than intent or paraphrase. | |
| state | No | ||
| domain | No | ||
| memory_id | No | Restrict search to nodes directly connected to this memory ID. Useful for searching within a workstream. Applied before FTS/exact scoring, not as a post-filter. When omitted, all nodes in the workspace (or domain) are searched. | |
| node_kind | No | Optional filter: space-separated node kinds (union match, same convention as tags). E.g. 'option standing' returns memories whose node_kind is option OR standing. Negation and wildcards are not supported. | |
| max_distance | No | When set (e.g. 0.35), only vector-search results whose semantic_distance is at or below this value are returned. Absent (or 0) means no distance filtering — all ranked results up to limit are returned. Use this from hooks to suppress low-relevance injections (STORY-315). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even with readOnlyHint=true and destructiveHint=false annotations, the description adds substantial behavioral detail: exact=true returns full objects regardless of count, multi-result lists render as compact text lines, state is a post-filter, FTS tokenisation drops hyphens, and failures return a structured error_class JSON. These details go well beyond the safety profile captured by annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every clause earns its place, covering query semantics, listing behavior, exact-match nuance, result rendering, fallback guidance, state filtering, and error handling. It is front-loaded with the core purpose and then layers edge cases in a logical order. It is arguably long, but for a tool with eight parameters and no output schema, the length is justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of explaining return behavior, and it does so thoroughly: lean result fields, compact text-line rendering versus full objects, exact=true exemption, and error JSON with retry semantics. It also covers failure fallbacks and sibling routing, leaving an agent well-equipped to invoke the tool correctly and interpret its results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, and the description adds meaning beyond the schema for key parameters: query must echo stored vocabulary, node_kind excludes unrelated matching kinds, exact=true bypasses FTS hyphen issues, and state values are enumerated. The main gap is that the domain parameter is never directly explained in the description, and max_distance is left entirely to the schema, so the description doesn't fully carry the parameter-semantics burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Search memories by keyword,' giving a clear verb and resource, and is further sharpened by the title 'Search memories.' It distinguishes itself from siblings by explicitly routing full-content retrieval to recall(id) and browsing to orient, so an agent can tell this tool apart even though the tool name is the generic 'search.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance on when to use keyword vocabulary, when to set exact=true for identifiers, and how to use node_kind for listing. It also provides a fallback escalation path—'use orient (with domain) to browse all memories, then recall by ID, then follow connections'—and names the alternatives directly. This is exceptional contextual routing beyond what schemas or annotations provide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
significanceARead-onlyInspect
Dual-signal importance analysis. Returns four sections, each capped at limit (default 10) and paired with a boolean *_results_truncated signal (declared_results_truncated, structural_results_truncated, uncurated_results_truncated, potentially_stale_results_truncated) — true when that section's count equals limit and more may exist. Call again with a higher limit to get more of the same ranked/ordered list, not a different one:
declared: memories explicitly marked significant (occurred_at set), most-recent-limit, chronological ascending.
structural: memories ranked by weighted inbound degree — SUM(1/(1+days_since_linker_updated)), top-limit. High score means many recently-active memories depend on this memory right now. Linkers updated more than recency_window days ago contribute zero weight.
uncurated: memories in structural top-N with no occurred_at — significance candidates not yet on the timeline. Its results_truncated mirrors structural's, since it is a filter over that same section.
potentially_stale: memories with occurred_at that do not appear in structural top-N — declared important but nothing current depends on them. Its results_truncated mirrors declared's, since it is a filter over that same section.
Pass memory_id to scope significance to a single memory's neighbourhood (depth 2, domain-clipped) — useful for workstream health checks when you already know the anchor. Pass domain for a full domain scan. memory_id takes precedence if both are supplied. Optional node_kind (space-separated union) filters all sections to matching kinds.
The gap between uncurated and potentially_stale is the most actionable output: use it to promote missed decisions onto the timeline and archive claims that no longer hold.
Do not use this tool to list all memories chronologically — use history for that. For age-based staleness, use audit(mode=stale). significance and audit are complementary: significance catches importance-based staleness; audit catches age-based staleness.
Pass mode=trust for epistemic trust ranking instead of dual-signal analysis. Trust mode returns memories ranked by trust_score [0,1] with trust_basis per memory — derived from node_kind intrinsic weight plus inbound neighbour contributions (contradicts connections subtract). When node_kind is omitted, reference and transient memories are excluded from trust output; when node_kind is set, only matching kinds are returned. nodes_results_truncated is true when more ranked memories exist beyond limit.
Returns lean results only — id, label, and a truncated why_matters excerpt; call recall(id) for full content. When a list or section has 2 or more results, each is rendered as a single compact text line — "[id] label — excerpt (domain, node_kind)" — instead of a JSON object; exactly one result is returned as a full object. structural/uncurated digest lines also carry the importance_score; trust mode digest lines carry trust_score and trust_basis.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | ||
| tags | No | ||
| limit | No | ||
| domain | No | ||
| memory_id | No | ||
| node_kind | No | Optional filter: space-separated node kinds (union match, same convention as tags). E.g. 'option standing' returns memories whose node_kind is option OR standing. Negation and wildcards are not supported. | |
| recency_window | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only and non-destructive, and the description adds substantial behavioral context beyond that: truncation semantics with *_results_truncated flags, the exact structural ranking formula, recency_window zero-weight behavior, memory_id precedence, trust-mode scoring, and lean-result rendering rules. No statement contradicts the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description is densely informative and well-structured with bullet sections, bolded section names, and clear mode/usage/format subsections. Every sentence contributes operational meaning, and the most decision-relevant facts (alternative tools, truncation, and scope precedence) are stated directly rather than buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity — two modes, four result sections, truncation flags, filtering, output formatting, and no output schema — the description covers all necessary invocation and interpretation details. It even explains the actionable gap between uncurated and potentially_stale and tells the agent to call recall(id) for full content, leaving no critical gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 14%, so the description carries the parameter burden, and it does so thoroughly for limit, mode, memory_id, domain, node_kind, and recency_window. It explains default limit, the trust-mode switch, scoping precedence, filtering behavior, and how recency_window affects weighting. The tags parameter is not explained in the description, which prevents a perfect score, but the overall compensation is strong.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Dual-signal importance analysis' and immediately enumerates the four result sections, tying the tool to a specific analytic resource. It explicitly differentiates from siblings by naming history and audit as the correct tools for chronological listing and age-based staleness, so the agent can tell significance apart without opening other definitions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage guidance is explicit and actionable: 'Do not use this tool to list all memories chronologically — use history for that' and 'For age-based staleness, use audit(mode=stale)'. It also clarifies when to pass memory_id vs domain, how to paginate with limit, and that memory_id takes precedence when both are supplied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suggest_connectionsARead-onlyInspect
Given a memory ID, return up to limit semantically similar candidates (default 5) from anywhere in the workspace ranked by semantic_distance — not limited to the source memory's domain. Review results for agreement or contradiction with the source memory, not only for connect opportunities. Semantic similarity reflects aboutness, not agreement; the server surfaces candidates that may warrant your review but never asserts they conflict. Each suggestion includes the candidate's domain and semantic_distance. Read-only — never creates connections.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | ||
| limit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and non-destructive behavior, and the description reinforces this while adding important nuance: semantic similarity reflects aboutness, not agreement, and the server never asserts conflicts. This helps prevent misinterpretation of returned candidates.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-structured, front-loading the core behavior and then adding interpretative guidance. A small amount of redundancy exists in restating read-only behavior already covered by annotations, but every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with no output schema, the description adequately covers input semantics, ranking behavior, and result contents (domain and semantic_distance). It does not specify the ordering direction of semantic_distance, which is a minor gap, but overall an agent has enough to invoke and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description compensates by explaining that 'id' is a memory ID and 'limit' controls the maximum number of candidates (default 5). It could specify constraints or types more precisely, but the core meaning of both parameters is clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns semantically similar candidates for a given memory ID, ranked by semantic_distance, and explicitly contrasts with connection creation via 'Read-only — never creates connections.' This distinguishes it from sibling tools like 'connect' and 'why_connected.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: use it to surface candidates for review of agreement or contradiction, not just for connect opportunities. It does not explicitly name alternative tools or when not to use them, but the context is strong enough for an agent to decide appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
visualiseARead-onlyInspect
Generate a Mermaid.js flowchart for human visual inspection only. NOT for orphan detection or programmatic analysis — use audit(mode=orphans) to find isolated memories. Output may be truncated for large domains; never infer graph properties (e.g. orphans) from a truncated result. Pass memory_id (memory ID) to see a single memory and all its direct connections. Pass domain to see the full domain graph (most-connected memories first, capped at limit, default 40 max 100). Returns JSON with mermaid, node_count, edge_count, nodes_shown, nodes_total, edges_shown, edges_total, truncated, memories([{id,label}]) and connections([{from,to,relationship}]). If client supports HTML widgets, prefer passing memories and connections to an interactive renderer rather than outputting raw mermaid. If not, output mermaid inside a ```mermaid code block. If truncated is true, note only most-connected memories are shown and nodes_total/edges_total reveal what was dropped.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| domain | No | ||
| memory_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=false, and destructiveHint=false, and the description adds meaningful behavioral context beyond that: truncation can occur for large domains, properties must not be inferred from truncated results, and ordered output is 'most-connected memories first.' It also fully discloses the JSON return fields, including truncated counts, which helps the agent understand and safely interpret results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place: purpose and exclusions, parameter behavior, return shape, rendering guidance, and truncation caveat. The description is longer than usual but densely packed with necessary information and well-ordered from high-level purpose to concrete invocation details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description enumerates the full JSON response shape (mermaid, node_count, edge_count, nodes_shown, nodes_total, edges_shown, edges_total, truncated, memories, connections). It also covers invocation modes, limits, truncation semantics, and client-specific rendering instructions. Nothing an agent needs to correctly select and invoke this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full responsibility for parameter meaning. It clearly explains all three parameters: memory_id views a single memory and its direct connections, domain views the full domain graph, and limit is capped at 100 with a default of 40. This adds substantive meaning beyond the bare schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Generate a Mermaid.js flowchart for human visual inspection only.' It also explicitly distinguishes itself from audit(mode=orphans), making it clear this tool is for visualization rather than orphan detection or programmatic analysis. The title 'Visualise domain graph' reinforces the purpose without creating ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use and when-not-to-use guidance, including a direct alternative: 'NOT for orphan detection or programmatic analysis — use audit(mode=orphans) to find isolated memories.' It also explains when to pass memory_id vs domain, the limit default and cap, and how to render output depending on client support for HTML widgets. This is unusually actionable usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
why_connectedARead-onlyInspect
Find direct connections between two memories, in either direction. Prefer from_id/to_id when you already have exact ids — resolution is exact-match and errors if a given id has no matching live memory, rather than silently falling back to label search. This is the recommended way to verify an exact pair (e.g. before connect(relationship=resolved)). Use from_label/to_label when you only have a concept in mind, not an id — resolution is a fuzzy substring match against the most recently created candidate. Each side resolves independently, so from_id may be combined with to_label.
| Name | Required | Description | Default |
|---|---|---|---|
| to_id | No | ||
| domain | No | ||
| from_id | No | ||
| to_label | No | ||
| from_label | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds meaningful behavioral detail: id resolution errors when no live memory matches, label resolution falls back to fuzzy substring matching against the most recently created candidate, and there is no silent fallback from id to label. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence adds distinct value: core purpose, exact-id guidance with error behavior, recommended use case, label fallback semantics, and independent resolution. The description is front-loaded with the action and uses clear contrasts without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with no output schema, the description covers the main resolution modes and error behavior well. The missing explanation of the domain parameter is the main gap, and the description does not state what happens if neither ids nor labels are supplied. Otherwise, an agent has enough to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden. It thoroughly explains from_id, to_id, from_label, and to_label, including resolution modes and combinability. The domain parameter, however, is never mentioned, leaving a five-parameter tool with one parameter unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with a specific verb and resource: 'Find direct connections between two memories, in either direction.' It clearly distinguishes this tool from siblings like connect, recall, and suggest_connections by framing it as a verification/query tool for exact pairs, even naming connect as a follow-up use case.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly specifies when to use from_id/to_id versus from_label/to_label, explains the exact-match versus fuzzy-match behavior, and gives a concrete recommended scenario: 'before connect(relationship=resolved)'. It also states that sides resolve independently, so mixed id/label combinations are allowed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
1 tool update
- Changed
search1 field changed- added
Input schema / properties / max_distanceAdded value: +{ + "description": "When set (e.g. 0.35), only vector-search results whose semantic_distance is at or below this value are returned. Absent (or 0) means no distance filtering — all ranked results up to limit are returned. Use this from hooks to suppress low-relevance injections (STORY-315).", + "type": "number" +}
16 tool updates
- First observed
audit - First observed
connect - First observed
disconnect - First observed
domains - First observed
forget - First observed
history - First observed
orient - First observed
recall - First observed
recent - First observed
remember - First observed
revise - First observed
search - First observed
significance - First observed
suggest_connections - First observed
visualise - First observed
why_connected
Frequently Asked Questions
Claiming proves that you control a remote MCP connector. It does not move, proxy, or interrupt the server.
Open the connector listing, choose Claim ownership, and sign in to Glama.
Complete one verification method:
GitHub identity — fastest for official registry listings. For a namespace such as
io.github.alice/server, link the matching GitHub user, then choose Claim with GitHub. An organization namespace such asio.github.acme/serveralso needs that organization to have installed the Glama AI GitHub App and approved its permissions, because GitHub discloses organization membership only to apps it has installed. Use HTTP or DNS when it has not.HTTP challenge — works when you can deploy a public file. Generate a token, publish the exact JSON Glama shows at
/.well-known/glama.jsonon the same origin as the connector, then choose Check HTTP challenge.DNS challenge — works when you control DNS but cannot change the server. Generate a token, create the exact TXT record Glama shows, wait for it to propagate, then choose Check DNS challenge.
After verification, Glama sends a confirmation email and gives you access to listing details, thumbnails, health checks, and analytics. Keep the HTTP file or DNS record in place: Glama periodically checks it and ownership remains verified while the token is discoverable.
The HTTP ownership file has this structure:
{
"$schema": "https://glama.ai/mcp/schemas/connector.json",
"claim": "glama_claim_..."
}Claim tokens are opaque, stable, and bound to the signed-in Glama account. They contain no email address or other personal information. If Glama can no longer discover a verified HTTP or DNS token, it starts a seven-day grace period before removing claim-based access. Restore the same token during that period to keep ownership verified. Never publish an email address, Glama session token, GitHub token, or connector credential as ownership proof.
If verification fails, confirm that you copied the current token exactly. The HTTP file must be public, return valid JSON with a successful HTTP response, and stay on the connector's origin. DNS changes may need more time to propagate. A claim cannot transfer to a different origin or hostname: if the connector target changes, Glama starts the grace period and the new target must be claimed separately after the previous claim is released.
For a connector linked to the official MCP Registry, registry updates continue to replace its name, description, and URL by default. After claiming, open Manage connector and enable Use Glama listing details as the source of truth if edits made on Glama should be preserved. Categories and thumbnails are always managed on Glama; registry linkage and technical connection settings continue to sync.
Control your server's listing on Glama, including description and metadata
Access analytics and receive server usage reports
Get monitoring and health status updates for your server
Feature your server to boost visibility and reach more users
To improve your MCP server's ranking:
Claim ownership of the server listing
Complete the server profile with an accurate description and thumbnail
Provide a test profile so Glama can connect to and evaluate the server
Keep tool definitions clear and complete to earn a high Tool Definition Quality Score (TDQS)
Route real usage through the Glama Gateway; more recorded successful server uses also improve the ranking
For users:
Full audit trail – every tool call is logged with inputs and outputs for compliance and debugging
Granular tool control – enable or disable individual tools per connector to limit what your AI agents can do
Centralized credential management – store and rotate API keys and OAuth tokens in one place
Change alerts – get notified when a connector changes its schema, adds or removes tools, or updates tool definitions, so nothing breaks silently
For server owners:
Proven adoption – public usage metrics on your listing show real-world traction and build trust with prospective users
Tool-level analytics – see which tools are being used most, helping you prioritize development and documentation
Direct user feedback – users can report issues and suggest improvements through the listing, giving you a channel you would not have otherwise
The connector status is unhealthy when Glama is unable to successfully connect to the server. This can happen for several reasons:
The server is experiencing an outage
The URL of the server is wrong
Credentials required to access the server are missing or invalid
If you are the owner of this MCP connector and would like to make modifications to the listing, including providing test credentials for accessing the server, please contact support@glama.ai.
Discussions
No comments yet. Be the first to start the discussion!
Related MCP Connectors
Persistent memory and knowledge graphs for AI agents. Hybrid search, context checkpoints, and more.
Shared long-term memory for AI agents: save and recall context as a searchable knowledge graph.
Persistent memory for AI agents. EU-hosted, privacy-first, hybrid recall, contradiction detection.
Intelligent context infrastructure for AI teams: knowledge graph, sessions, tasks, documents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides persistent knowledge graph memory for AI agents, enabling them to store, recall, and query facts about people, projects, and relationships across sessions.MIT
- AlicenseNot gradedqualityBmaintenanceEnables persistent, graph-based memory for AI agents, allowing them to store, traverse, and recall relationships between facts, decisions, and context across sessions for efficient reasoning and reduced token usage.MIT
- AlicenseAqualityDmaintenanceProvides versioned, structured memory for AI agents, allowing them to store facts, detect conflicts, and track knowledge history via a hosted SaaS platform. It enables efficient hierarchical information retrieval and semantic search while keeping token usage constant as memory scales.7248Apache 2.0

Memsolus MCP Serverofficial
AlicenseAqualityDmaintenanceProvides persistent long-term memory for AI agents through semantic search and automated knowledge graph extraction. It enables agents to store, recall, and reason over facts, preferences, and relationships across multiple conversations and sessions.1419MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.
TDQS
Each tool targets a distinct operation—lifecycle (remember/revise/forget), graph edges (connect/disconnect/why_connected), retrieval (recall/search/recent/history/orient/significance)—and the descriptions carefully disambiguate overlaps. However, the read/analysis cluster (recent, history, orient.recent, significance) could still cause initial misselection before reading the detailed descriptions.
Names are readable and consistently lowercase, but they do not follow a single convention: most are bare verbs (connect, remember, revise, search, visualise) while others are nouns (domains, history, recent, significance) and two are multiword phrases (suggest_connections, why_connected). This mix is still predictable enough to navigate, but less coherent than a uniform verb_noun surface.
16 tools is slightly above the typical 3–15 band, but the scope of a knowledge-graph memory server justifies the breadth: CRUD, connections, domain admin, and multiple query/analysis tools are all represented. No tool feels redundant enough to cut, though the set is at the heavy end.
Core lifecycle is well covered: create/read/update/archive/purge, connection creation/removal, domain admin, and multiple query/analysis modes. The main gap is that bulk domain merge (merge_domains) is referenced in tool descriptions but not exposed as an MCP tool, so agents must direct users to an external admin interface for that operation.