Skip to main content
Glama

Neotoma

Your agents forget. Neotoma makes them remember.

Versioned records — contacts, tasks, decisions, finances — that persist across Claude, Cursor, ChatGPT, OpenClaw, and every agent you run. Open-source. Local-first. Deterministic. MIT licensed.

neotoma.io · Evaluate · Install · Documentation

Why this exists

You run AI agents across tools and sessions. Without a state layer, you become the human sync layer:

  • Every session starts from zero — nothing your agent learns carries over

  • Facts conflict across tools — two agents store different versions of the same person

  • Decisions execute without a reproducible trail — you can't trace why your agent acted

  • Corrections don't stick — you fix something in Claude and it's wrong again in Cursor

These are not hypothetical. They happen every day in production agent systems. You compensate by re-prompting context, patching state gaps, and maintaining manual workarounds. Neotoma removes that tax.

Related MCP server: Mneme Memory MCP

What Neotoma does

Neotoma is a deterministic state layer for AI agents. It stores structured records — contacts, tasks, transactions, decisions, events, contracts — with versioned history and full provenance. Every change creates a new version. Nothing is overwritten. Every state can be replayed from the observation log.

Not retrieval memory (RAG, vector search, semantic lookup). Neotoma enforces deterministic state evolution: same observations always produce the same entity state, regardless of when or in what order they are processed.

Architecture

graph LR
  Sources["Sources (files, messages, APIs)"] --> Obs[Observations]
  Obs --> Entities[Entity Resolution]
  Entities --> Snapshots["Entity Snapshots (versioned)"]
  Snapshots --> Graph[Memory Graph]
  Graph <--> MCP[MCP Protocol]
  MCP --> Claude
  MCP --> ChatGPT
  MCP --> Cursor
  MCP --> OpenClaw
  • Deterministic. Same observations always produce the same versioned entity snapshots. No ordering sensitivity.

  • Immutable. Append-only observations. Corrections add new data, never erase.

  • Replayable. Inspect any entity at any point in time. Diff versions. Reconstruct history from the observation log.

  • Structure-first. Schema-first extraction with deterministic retrieval. Optional similarity search when embeddings are configured.

Three foundations

Foundation

What it means

Privacy-first

Your data stays local. Never used for training. User-controlled storage, optional encryption at rest. Full export and deletion control.

Deterministic

Same input always produces same output. Schema-first extraction, hash-based entity IDs, full provenance. No silent mutation.

Cross-platform

One memory graph across Claude, ChatGPT, Cursor, OpenClaw, Codex, and CLI. MCP-based access. No platform lock-in. Works alongside native memory.

State guarantees

Most AI memory systems optimize storage or retrieval. Neotoma enforces state integrity. Full comparison with explanations →

Property

Platform

Retrieval / RAG

Files

Database

Neotoma

Deterministic state evolution

✗

✗

✗

✗

✓

Versioned history

✗

✗

⚠ manual

✗

✓

Replayable timeline

✗

✗

✗

✗

✓

Auditable change log

✗

✗

⚠ partial

✗

✓

Schema constraints

✗

✗

✗

⚠ partial

✓

Silent mutation risk

⚠ common

⚠ common

⚠ common

⚠ common

prevented

Conflicting facts risk

⚠ common

⚠ common

⚠ possible

⚠ common

prevented

Reproducible state reconstruction

✗

✗

✗

✗

✓

Human inspectability (diffs/lineage)

⚠ partial

⚠ partial

⚠ partial

⚠ partial

✓

Zero-setup onboarding

✓

✗

✗

✗

✗

Semantic similarity search

✗

✓

✗

✗

✓

Direct human editability

✗

✗

✓

✗

✗

Platform: Claude, ChatGPT, Gemini, Copilot. Retrieval: Mem0, Zep, LangChain Memory. Files: Markdown files, JSON stores, CRDT docs. Database: SQLite, Postgres, MySQL. Neotoma: Deterministic state layer (reference implementation).

Quick start

Ask your AI agent whether Neotoma fits your workflow. Paste this into Claude, Cursor, ChatGPT, or any MCP-capable tool:

Read https://neotoma.io/evaluate. Before you answer, inspect any broader tool, workspace, and configuration context you can access so you assess my real workflow rather than just this chat. Then tell me whether Neotoma is a real fit for my workflow, what data would be highest value to persist first, and what I should do next.

The agent reads the evaluation page, checks your context, and gives you an honest assessment. If it's a fit, the agent carries you through install and activation.

Agent-driven install

Agents install Neotoma themselves. Paste this prompt into Claude, Cursor, ChatGPT, or Codex:

Read https://neotoma.io/install and carry me through the install-first Neotoma flow. Install, activate it with my data, and configure my current tool for robust ongoing use.

The agent handles npm install, initialization, and MCP configuration. Manual install:

npm install -g neotoma
neotoma init
neotoma mcp config

More options: Docker | CLI reference | Getting started

Example

neotoma store --json='[{"entity_type":"task","title":"Submit expense report","status":"open"}]'
neotoma entities list --type task
neotoma upload ./invoice.pdf

Results reflect versioned entity state with full provenance. Agents perform the same operations through MCP tool calls (store, retrieve_entities, retrieve_entity_by_identifier).

Interfaces

Three interfaces. One state invariant. Every interface provides the same deterministic behavior regardless of how you access the state layer.

Interface

Description

REST API

Full HTTP interface for application integration. Entities, relationships, observations, schema, timeline, and version history.

MCP Server

Model Context Protocol for Claude, ChatGPT, Cursor, OpenClaw, Codex, and more. Agents store and retrieve state through structured tool calls.

CLI

Command-line for scripting and direct access. Inspect entities, replay timelines, and manage state from the terminal.

All three map to the same OpenAPI-backed operations. MCP tool calls log the equivalent CLI invocation.

Who this is for

People building a personal operating system with AI agents across their life — wiring together tools like Claude, Cursor, ChatGPT, OpenClaw, and custom scripts to manage contacts, tasks, finances, code, content, and other domains. The same person operates their agents, builds new pipelines, and debugs state drift. These are three operational modes, not separate personas:

Mode

What you're doing

The tax you pay without Neotoma

What you get back

Operating

Running AI tools across sessions and contexts

Re-prompting, context re-establishment, manual cross-tool sync

Attention, continuity, trust in your tools

Building

Shipping agents and pipelines

Prompt workarounds, dedup hacks, memory regression fixes

Product velocity, shipping confidence

Debugging

Tracing state drift and reproducing failures

Writing glue (checkpoint logic, custom diffing, state serialization)

Debugging speed, platform design time

Not for: Casual note-taking. PKM/Obsidian-style users. Thought-partner usage where the human drives every turn. Platform builders who build state management as their core product. Users who need zero-install onboarding (Neotoma requires npm and CLI today).

Record types

Neotoma stores typed entities with versioned history and provenance. Each type has a dedicated guide on neotoma.io:

Type

What it stores

Examples

Contacts

People, companies, roles, relationships

contact, company, account

Tasks

Obligations, deadlines, habits, goals

task, habit, goal

Transactions

Payments, receipts, invoices, ledger entries

transaction, invoice, receipt

Contracts

Agreements, clauses, amendments

contract, clause, amendment

Decisions

Choices, rationale, audit trails

decision, assessment, review

Events

Meetings, milestones, outcomes

event, meeting, milestone

Schema is flexible — store any entity type with whatever fields the message implies. The system infers and evolves schemas automatically.

Current status

Version: v0.4.2 · Releases: 13 · License: MIT

What is guaranteed (even in preview)

  • No silent data loss. Operations either succeed and are recorded or fail with explicit errors.

  • Explicit, inspectable state mutations. Every change is a named operation with visible inputs. State is reconstructable from the audit trail.

  • Auditable operations. Full provenance. CLI and MCP map to the same underlying contract.

  • Same contract for CLI and MCP. Both use the same OpenAPI-backed operations.

What is not guaranteed yet

  • Stable schemas

  • Deterministic extraction across versions

  • Long-term replay compatibility

  • Backward compatibility

Breaking changes should be expected. Storage: Local-only (SQLite + local file storage). See Developer preview storage.

Security defaults

Neotoma stores user data and requires secure configuration.

  • Authentication: Local auth (dev stub or key-based when encryption is enabled).

  • Authorization: Local data isolation and explicit operation-level access controls.

  • Data protection: User-controlled data with full export and deletion control. Never used for training. Optional encryption at rest.

  • Verify your setup: Run npm run doctor for environment, database, and security checks. See Auth, Privacy, Compliance.

Development

Servers:

npm run dev          # MCP server (stdio)
npm run dev:ui       # Frontend
npm run dev:server   # API only (MCP at /mcp)
npm run dev:full     # API + UI + build watch

CLI:

npm run cli        # Run via npm (no global install)
npm run cli:dev    # Dev mode (tsx; picks up source changes)
npm run setup:cli  # Build and link so `neotoma` is available globally

Testing: npm test | npm run test:integration | npm run test:e2e | npm run test:agent-mcp | npm run type-check | npm run lint · Source checkout:

git clone https://github.com/markmhendrickson/neotoma.git
cd neotoma
npm install
npm test

Prerequisites: Node.js v18.x or v20.x (LTS), npm v9+. No .env required for local storage. See Getting started.

Using with AI tools (MCP)

Neotoma exposes state via MCP. Local storage only in preview. Local built-in auth.

Setup guides: Cursor · Claude Code · Claude · ChatGPT · Codex · OpenClaw

Agent behavior contract: Store first, retrieve before storing, extract entities from user input, create tasks for commitments. Full instructions: MCP instructions and CLI agent instructions.

Representative actions: store, retrieve_entities, retrieve_entity_snapshot, merge_entities, list_observations, create_relationship, list_relationships, list_timeline_events, retrieve_graph_neighborhood. Full list: MCP spec.

OpenClaw native plugin

Neotoma ships as a native OpenClaw plugin with kind: "memory", so it can fill the dedicated memory slot. All 30+ MCP tools are registered as agent tools.

openclaw plugins install neotoma

Then assign it to the memory slot in your OpenClaw config:

{
  plugins: {
    slots: { memory: "neotoma" },
    entries: {
      neotoma: {
        enabled: true,
        config: {
          dataDir: "~/.local/share/neotoma",
          environment: "production"
        }
      }
    }
  }
}

Verify installation: openclaw plugins inspect neotoma shows Format: native, Kind: memory, and all registered tool contracts.

Common questions

Platform memory (Claude, ChatGPT) is good enough — why add another tool? Platform memory stores what one vendor decides to remember, in a format you can't inspect or export. It doesn't version, doesn't detect conflicts, and vanishes if you switch tools. Neotoma gives you structured, cross-tool state you control.

Can't I just build this with SQLite or a JSON file? You can start there — many teams do. But you'll eventually need versioning, conflict detection, schema evolution, and cross-tool sync. That's months of infrastructure work. Neotoma ships those guarantees on day one.

What's the difference between RAG memory and deterministic memory? RAG stores text chunks and retrieves them by similarity. Neotoma stores structured observations and composes entity state with reducers; the same observations always yield the same snapshot. RAG optimizes relevance; deterministic memory optimizes integrity, versioning, and auditability.

Is this production-ready? Neotoma is in developer preview — used daily by real agent workflows. The core guarantees (deterministic state, versioned history, append-only log) are stable. Install in 5 minutes and let your agent evaluate the fit.

More questions: FAQ

Documentation

Full documentation is organized at neotoma.io/docs and in the docs/ directory.

Getting started: Evaluate, Install, Walkthrough

Reference: REST API, MCP server, CLI, Memory guarantees, Architecture, Terminology

Foundational: Core identity, Philosophy, Problem statement

Operations: Runbook, Health check (npm run doctor), SQLite salvage (neotoma storage recover-db, npm run recover:db, npm run recover:db:prod), Troubleshooting

Contributing

Neotoma is in active development. For questions or collaboration, open an issue or discussion. See CONTRIBUTING.md and SECURITY.md. License: MIT

Available Tools

67 tools
add_entity_messageA

Append a follow-up conversation_message to the thread for a submitted root entity (entity_id).

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesMessage body (markdown).
entity_idYesRoot submitted entity id.

TDQS

A3.8/5.0
Behavior3/5

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

With no annotations, the description carries the burden of behavioral disclosure. It indicates a write operation ('append') and adds context ('follow-up', 'submitted root entity'), but does not mention permissions, idempotency, or what happens if the entity is not submitted.

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

Conciseness5/5

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

The description is a single sentence that efficiently conveys the purpose and key details. No extraneous words or repetition.

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

Completeness4/5

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

For a simple tool with two parameters and no output schema, the description covers the action and parameter roles. It assumes prior context (entity already submitted, thread exists), which is reasonable given the tool name. Minor gap: no mention of message size limits or handling.

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

Parameters3/5

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

Schema coverage is 100% with adequate parameter descriptions. The tool description adds minor value by framing the message as a 'follow-up conversation' and connecting entity_id to a 'root entity', but does not significantly enhance meaning beyond the schema.

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

Purpose5/5

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

The description clearly states the action ('Append a follow-up conversation_message'), the resource ('thread for a submitted root entity'), and references the key parameter 'entity_id'. It distinguishes from the sibling 'add_issue_message' by specifying it is for entities, not issues.

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

Usage Guidelines3/5

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

The description implies usage when a user wants to add a follow-up message to an entity's thread, but it does not explicitly state when to use this tool versus alternatives like 'add_issue_message'. No when-not or prerequisite guidance is provided.

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

add_issue_messageA

Append a message to an issue thread. Provide entity_id or issue_number (issue_number is an integer). Pass guest_access_token when the local issue snapshot does not already carry the operator token. If remote append fails after local/GitHub side effects, inspect remote_submission_error instead of retrying blindly.

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyYesMessage body in markdown.
entity_idNoNeotoma `issue` entity_id. Use the id returned by submit_issue or Inspector.
issue_numberNoGitHub issue number in the configured repo; use entity_id for private/local issues.
reporter_channelNoOptional reporter channel (e.g. ci, local).
reporter_git_refNoOptional reporter git ref / branch name.
reporter_git_shaNoReporter git SHA (`git rev-parse HEAD`) the message author is testing against. Soft requirement on public issue threads.
guest_access_tokenNoOptional guest-scoped token for operator Neotoma read-through / remote append when mirroring a remote issue. If omitted, the issue entity's stored guest_access_token is used when present.
reporter_app_versionNoReporter app / CLI version (semver) the message author is testing. Soft requirement on public issue threads.

TDQS

A4.4/5.0
Behavior4/5

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

No annotations provided, so description carries full burden. It discloses side effects ('If remote append fails after local/GitHub side effects') and error handling, though it does not explicitly state the write nature (implied by 'append').

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

Conciseness5/5

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

Two sentences, no fluff. Every sentence conveys essential guidance including alternatives and error handling.

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

Completeness4/5

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

No output schema, but description covers error handling and side effects. Given 8 parameters (1 required), it provides sufficient context for an agent to invoke correctly, though success behavior is not described.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3. The description adds value by clarifying the optionality between entity_id and issue_number and explaining the purpose of guest_access_token beyond schema descriptions.

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

Purpose5/5

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

The description clearly states 'Append a message to an issue thread' with a specific verb and resource. It distinguishes from sibling 'add_entity_message' by targeting issues explicitly.

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

Usage Guidelines4/5

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

Provides explicit guidance on when to use entity_id vs issue_number, when to pass guest_access_token, and how to handle remote_submission_error. Lacks explicit when-not-to-use or direct alternative tool names, but context is strong.

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

add_peerC

Register a Neotoma peer (peer_config) for bidirectional sync: peer_url, entity_types allowlist, shared_secret for POST /sync/webhook verification.

ParametersJSON Schema
NameRequiredDescriptionDefault
peer_idYes
peer_urlYes
directionYes
peer_nameYes
sync_scopeYes
auth_methodYes
entity_typesYes
shared_secretNoOptional; generated when auth_method is shared_secret and omitted.
conflict_strategyYes
sync_target_user_idNoOptional. Authenticated user_id on the peer instance for outbound POST /sync/webhook target_user_id.
peer_public_key_thumbprintNoOptional AAuth public-key thumbprint expected from this peer when auth_method is aauth.

TDQS

C2.9/5.0
Behavior2/5

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

Without annotations, the description bears full responsibility but only hints at the registration process. It incorrectly implies only bidirectional sync while the schema includes push and pull. No mention of side effects, auth requirements, or post-registration behavior.

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

Conciseness3/5

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

The description is a single sentence with no wasted words. However, for an 11-parameter tool, it is under-specified and could benefit from a brief list of required fields.

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

Completeness2/5

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

Given high complexity (11 params, no output schema, no annotations), the description is insufficient. It does not explain the peer_config concept, expected return, or follow-up actions.

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

Parameters2/5

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

Schema description coverage is only 27%. The description adds meaning for peer_url, entity_types, and shared_secret but omits 8 of 11 parameters, including required ones like peer_id, direction, and auth_method.

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

Purpose5/5

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

The description clearly states the action 'Register' and the resource 'Neotoma peer', and mentions key aspects like peer_url, entity_types allowlist, and shared_secret. It distinguishes the tool from siblings such as remove_peer and sync_peer.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like sync_peer or remove_peer. It does not specify prerequisites or scenarios.

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

analyze_schema_candidatesB

Analyze raw_fragments to identify fields that should be promoted to schema fields. Returns recommendations with confidence scores based on frequency and type consistency.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNoUser ID for user-specific analysis (optional)
entity_typeNoEntity type to analyze (optional, analyzes all if not provided)
min_frequencyNoMinimum frequency threshold (default: 5)
min_confidenceNoMinimum confidence score 0-1 (default: 0.8)

TDQS

B3.3/5.0
Behavior2/5

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

No annotations are present, so the description must fully convey behavior. It only states the output (recommendations with confidence scores) but does not disclose whether the tool is read-only, requires special permissions, or has side effects. This is a significant gap.

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

Conciseness5/5

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

The description is two sentences, front-loaded with the action, and contains no extraneous words. Every sentence adds value.

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

Completeness3/5

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

Given the lack of output schema, the description should ideally clarify the structure of recommendations. It states 'recommendations with confidence scores' but no further detail on format or nesting. Adequate but not rich.

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

Parameters3/5

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

Schema coverage is 100%, so the baseline is 3. The description does not add additional meaning beyond what the schema already provides for each parameter, though it does mention 'confidence scores' which relates to min_confidence.

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

Purpose5/5

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

The description clearly states the verb 'Analyze' and the resource 'raw_fragments' to identify schema field candidates. It distinguishes from siblings like 'get_schema_recommendations' and 'register_schema' by focusing on analysis rather than retrieval or registration.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives (e.g., 'get_schema_recommendations'). The description does not specify prerequisites or conditions for use, leaving the agent to infer context.

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

audit_undeclared_fragmentsA

Report the accumulated undeclared raw_fragments awaiting schema declaration — fields stored on observations but excluded from the entity snapshot because no active schema declares them. Read-only; declares nothing. Returns, per entity_type, the undeclared fragment_keys with occurrence and affected-entity counts and a schema_missing flag (true when the type has stranded fragments but no active schema), plus total_entity_types / total_undeclared_fields rollups, in deterministic order (occurrences desc, affected desc, key asc; types by total occurrences desc). Optional entity_type scopes the audit to one type. The aggregate counterpart to the per-store unknown_fields signal: use it to triage the backlog before drafting update_schema_incremental / register_schema work.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo
entity_typeNoRestrict the audit to a single entity_type.

TDQS

A4.3/5.0
Behavior5/5

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

Without annotations, the description fully discloses read-only behavior, return structure (including order), and purpose. No contradictions or hidden behaviors.

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

Conciseness5/5

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

Concise yet thorough: main purpose first, then return details, then usage. No redundant sentences.

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

Completeness4/5

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

No output schema, but description compensates with detailed return structure. Missing explanation of user_id param limits completeness slightly.

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

Parameters2/5

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

Schema coverage is 50% (user_id lacks description). The description adds context for entity_type but omits user_id entirely. This leaves the agent guessing about user_id's role.

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

Purpose5/5

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

The description clearly states the tool reports undeclared fragments and contrasts with siblings like update_schema_incremental. The verb 'Report' and resource 'undeclared raw_fragments' are specific, and the purpose is unambiguous.

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

Usage Guidelines4/5

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

Explicitly says to use it for triage before schema work, and mentions optional entity_type scoping. It doesn't explicitly state when not to use, but the read-only nature is clear from context.

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

correct

Create a priority-1000 correction observation to override lower-priority extracted fields. Higher-priority sources remain authoritative; equal-priority ties follow configured source-kind precedence, then deterministic recency. Read back the entity snapshot and field provenance before claiming the correction took effect.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldYesField name to correct
valueYesCorrected value
user_idNoOptional. Inferred from authentication if omitted.
entity_idYesEntity ID to correct
overwriteNoApply even when expected_version is stale. Ignored when it is omitted.
entity_typeYesEntity type
idempotency_keyYesRequired. Client-provided idempotency key for replay-safe corrections.
expected_versionNoOptional opaque entity_version from a current entity read. A stale token returns ERR_FIELD_VERSION_CONFLICT and writes nothing.
correct_transaction
DestructiveIdempotent

Atomically compare and correct declared fields on multiple entities. Supply each loaded observation count and expected fields. Any conflict, denied write or snapshot mismatch rolls back every change. Retry the identical request and key after uncertainty. This primitive does not authorize application-level approval.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo
entitiesYes
idempotency_keyYes
create_interpretation

Create an interpretation row for an existing source from agent-extracted flat entities. Observations produced by this tool are linked to both source_id and interpretation_id. Use store with an interpretation block when the source-derived extraction can be batched in one store call.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo
entitiesYes
source_idYes
relationshipsNo
idempotency_keyNo
interpretation_configNoAudit configuration for a parser or agent-authored interpretation run. Callers may include extractor_type, extractor_version, model, prompt_hash, schema_version, agent_notes, and other provenance fields needed to explain how extracted observations were produced.
create_relationship

Create a typed relationship between two entities. The relationship_type vocabulary is a runtime registry, not a fixed list: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Use EMBEDS when a container entity (e.g. blog post, document) embeds an asset entity (e.g. image, attachment): source_entity_id = container, target_entity_id = asset. For images/files stored in Neotoma: store the file via store (get source_id), create an image/media entity with source_id, then create_relationship(EMBEDS, post_entity_id, image_entity_id). Optional metadata: caption, order. Both source_entity_id and target_entity_id must be entities you own; store the entity first (or in the same store call), then link it.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNoOptional explicit user id; inferred from authentication when omitted.
metadataNoOptional metadata attached to the relationship (e.g. `caption`, `order` for `EMBEDS` edges).
source_idNoOptional `sources` row id stamped as provenance on the relationship observation.
source_entity_idYesExisting entity id at the source end of the edge.
target_entity_idYesExisting entity id at the target end of the edge.
relationship_typeYesRelationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).
create_relationships

Create multiple typed relationships between existing entities in one batch

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo
source_idNo
relationshipsYes
delete_entity

Hide an entity from current snapshots and queries through an immutable lifecycle observation. After the explicit authority cutover, serialized action sequence controls visibility; before cutover, existing legacy behavior applies. Each accepted request is a separate action, without an idempotency key or conditional rollback baseline. Physical legal erasure is a separate operation.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNoOptional reason for deletion (audit)
user_idNoOptional. Inferred from authentication if omitted.
entity_idYesEntity ID to delete
entity_typeYesEntity type (e.g. company, person)
delete_relationship

Delete a relationship. Requires the exact relationship_type between the two entities; if unknown, call list_relationships with source_entity_id and target_entity_id first to discover it. Creates a deletion observation so the relationship is excluded from snapshots and queries. Immutable and reversible for audit. Returns 404 with a discovery hint when no live relationship matches the supplied triple.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNoOptional reason for deletion (audit)
user_idNoOptional. Inferred from authentication if omitted.
source_entity_idYesSource entity ID
target_entity_idYesTarget entity ID
relationship_typeYesExact relationship type of the existing edge — the same vocabulary create_relationship writes. Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it.
describe_entity_type

Return the full active schema for one entity_type: field_names, per-field type/required/description (field_summary), required_fields, schema_version, and the raw schema_definition. Call this before store when you know the entity_type but not its declared field shape, so the first store lands with zero unknown_fields and zero required_fields_missing warnings. Repair workflow: when a prior store or correct returned unknown_fields_count > 0 (or unknown_field: true), call describe_entity_type to see the declared fields, then re-store or correct the value into a declared field that fits; only add a new field (update_schema_incremental / register_schema, per the response hint) when no declared field fits. Read-only; no persistence side effects. Errors with InvalidParams when the entity_type has no active schema (use list_entity_types to discover types, or register_schema to create one). Scope note: describe prefers user scope (always passes the session user id), and so does update_schema_incremental when user_specific is omitted, so a type visible here can be extended without restating scope. Only an explicit user_specific: false narrows the update to global and can return ERR_SCHEMA_SCOPE_MISMATCH; never register_schema for that code.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo
entity_typeYes
describe_instance_policyA

Return this instance's data policy: what it is for (purpose), which entity types are in scope (in_scope_entity_types) or explicitly out of scope (out_of_scope_entity_types), whether person-data writes require a lawful-basis tag or provenance metadata, and the maximum field sensitivity class it will hold. Call this at the start of a session against an unfamiliar or shared instance, before your first store, so your writes comply instead of being rejected — policy discovered by trial-and-error rejection is strictly worse than reading it up front. Response shape is {"policy": <object|null>, "entity_id": <string|null>}. Returns {"policy": null, "entity_id": null} when the instance declares no policy; that means unrestricted, NOT deny-all. entity_id is an opaque identifier — pass it to correct() when authoring/updating the policy remotely rather than re-deriving or guessing it. When enforcement is "enforced", violating store/correct calls are rejected with ERR_STORE_POLICY_DENIED and nothing in the request is persisted; when "advisory", violating writes are accepted but you are still expected to comply. Takes no arguments: the policy is instance-wide, identical for every caller. Read-only; no persistence side effects.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

No annotations are provided, so the description carries the full burden; it exceeds it by stating read-only/no persistence side effects, instance-wide scope, no arguments, response shape, null semantics, and exact behavior for 'enforced' vs 'advisory' modes. It also warns that violating calls are rejected and nothing is persisted.

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

Conciseness5/5

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

The first sentence front-loads the core return value, followed by usage timing, response shape, edge-case semantics, and enforcement behavior. Despite its length, every sentence adds distinct value; there is no wasted or redundant wording.

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

Completeness5/5

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

With no output schema and no annotations, the description must explain return values and safety, and it does so fully: response shape, null-policy interpretation, entity_id handling for correct(), enforcement consequences, and read-only nature. This is sufficient for an agent to decide when and how to invoke it.

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

Parameters4/5

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

There are zero parameters, so the baseline is 4; the description reinforces this with 'Takes no arguments: the policy is instance-wide, identical for every caller,' which explains why the schema is empty and removes any temptation to supply caller-specific arguments.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Return this instance's data policy' and enumerates exactly which aspects are covered (purpose, scopes, write requirements, max sensitivity class). It clearly distinguishes itself from siblings like store/correct/describe_entity_type by framing it as the session-start introspection call.

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

Usage Guidelines5/5

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

Explicitly instructs when to call: 'at the start of a session against an unfamiliar or shared instance, before your first store' and gives a reason. It also defines what null policy means (unrestricted, not deny-all) and how to interpret enforcement modes, making the use decision clear.

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

get_authenticated_userA

Get the authenticated user ID for the current MCP session. Returns the user_id that is automatically used for all authenticated actions.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior4/5

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

The description discloses that the tool returns the user_id and notes its automatic use in authenticated actions. With no annotations, it adequately communicates the core behavior, though it could mention if the result is cached or requires prior authentication.

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

Conciseness5/5

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

Two concise sentences with no wasted words. The description is front-loaded with the action and resource, making it efficient.

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

Completeness4/5

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

Given no output schema, the description explains the return value ('user_id') and its significance ('automatically used for all authenticated actions'). This is sufficient for a simple tool, though it could specify the data type or format.

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

Parameters4/5

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

No parameters exist, so the schema coverage is 100%. The description adds no parameter information, which is acceptable since none are needed. Baseline of 4 is appropriate.

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

Purpose4/5

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

The description clearly states the tool retrieves the authenticated user ID with a specific verb ('Get') and resource ('authenticated user ID'). It is unambiguous, but does not differentiate from sibling tool 'get_session_identity' which may serve a similar purpose.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives like 'get_session_identity'. The description lacks context for appropriate usage scenarios or prerequisites.

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

get_entity_submission_statusA
Read-only

JSON entity snapshot for a submitted entity_id; optional guest_access_token for token-scoped read-back.

ParametersJSON Schema
NameRequiredDescriptionDefault
entity_idYes
guest_access_tokenNoOptional token from submit_entity.

TDQS

A4/5.0
Behavior4/5

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

Annotations already indicate readOnlyHint=true, and the description reinforces this with 'snapshot' and 'read-back'. It adds specific context about token-scoped access without contradicting annotations. No additional behavioral traits disclosed, but sufficient given annotations.

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

Conciseness5/5

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

Single sentence with clear structure, front-loading the core action and then specifying the optional parameter. No wasted words.

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

Completeness4/5

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

For a simple 2-parameter tool with annotations, the description covers the purpose and key parameters. However, without an output schema, it lacks details on the return structure or error behavior, leaving minor gaps in completeness.

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

Parameters3/5

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

Schema description coverage is 50%: guest_access_token has a description in the schema, entity_id has none. The description mentions both parameters but adds minimal semantics beyond what the schema provides (e.g., no format or constraint details). Adequate but not exceptional.

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

Purpose5/5

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

Clearly states the tool returns a JSON entity snapshot for a submitted entity_id, with optional guest_access_token for token-scoped read-back. It distinguishes itself from sibling tools like get_issue_status or get_relationship_snapshot by focusing on entity submissions.

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

Usage Guidelines3/5

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

The description implies usage (for retrieving a submission snapshot) but does not provide explicit when-to-use vs alternatives, nor exclusion criteria. The guest_access_token is mentioned but not explained when it should be used.

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

get_entity_type_countsA

Return canonical entity counts by entity_type for the authenticated user. Uses the same dashboard stats aggregation behind GET /stats and sorts results by count descending, then entity_type ascending. Use this when the user asks for counts by type, histograms, or sorted totals. This returns row counts, unlike list_entity_types where field_count is schema field width.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNoOptional. Inferred from authentication if omitted.

TDQS

A4.1/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It discloses that it uses the same aggregation as GET /stats and sorts results. It does not mention any destructive behavior, which is expected as it is a read operation. However, it could add more detail about output format or pagination, but for a simple count tool, this is adequate.

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

Conciseness5/5

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

The description is efficiently written in two informative sentences plus a third sentence differentiating from a sibling. There is no filler, and it is appropriately front-loaded.

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

Completeness5/5

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

Given the tool's simplicity (one optional parameter, no output schema, common read operation), the description is complete enough. It explains the return type (canonical entity counts), aggregation source, sorting, and usage context. No additional information is necessary for correct usage.

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

Parameters3/5

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

Schema coverage is 100% with one parameter (user_id) already described as optional and inferred from authentication. The description adds no further parameter details beyond what the schema provides, so baseline score of 3 applies.

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

Purpose5/5

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

The description clearly states the tool returns canonical entity counts by entity_type, using the same dashboard stats aggregation behind GET /stats, and sorts results by count descending then entity_type ascending. It also distinguishes itself from list_entity_types by specifying that this returns row counts while that returns field width.

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

Usage Guidelines4/5

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

Explicitly says when to use: 'Use this when the user asks for counts by type, histograms, or sorted totals.' It also mentions when not to use it by contrasting with list_entity_types. However, it does not explicitly state when not to use or provide alternative tools beyond the one sibling.

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

get_issue_statusA
Read-only

Return issue status and thread messages. Provide entity_id or issue_number (issue_number is an integer). Pass guest_access_token when token-scoped remote read-through is needed.

ParametersJSON Schema
NameRequiredDescriptionDefault
entity_idNoNeotoma `issue` entity_id. Use the id returned by submit_issue or Inspector.
skip_syncNoSkip implicit sync from GitHub when the issue has github_number (does not skip operator read-through for mirrored issues).
issue_numberNoGitHub issue number in the configured repo; use entity_id for private/local issues.
guest_access_tokenNoOptional guest-scoped token for operator read-through when the local issue mirrors remote_entity_id on issues.target_url. If omitted, guest_access_token on the issue snapshot is used when present.

TDQS

A4/5.0
Behavior4/5

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

Annotations declare readOnlyHint=true, which the description supports by stating 'Return'. Additionally describes sync skipping behavior and token scope for remote read-through, adding context beyond annotations.

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

Conciseness5/5

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

Two concise sentences: first states purpose, second covers parameter usage. No superfluous words; information is front-loaded.

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

Completeness4/5

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

Given no output schema, the description adequately states that status and thread messages are returned. Could be more detailed about structure, but covers the essential return content.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents all parameters. The description adds minor value by clarifying usage of guest_access_token and noting issue_number is an integer, but does not significantly extend schema info.

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

Purpose5/5

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

Description clearly states 'Return issue status and thread messages' with specific resource (issue) and verb (return). Distinguishes from siblings which are for other operations like creation, update, or deletion.

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

Usage Guidelines3/5

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

Provides guidance on how to identify the issue (entity_id or issue_number) and when to use guest_access_token. Lacks explicit when-not-to-use or comparisons with alternatives like get_entity_submission_status.

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

get_peer_statusB

Fetch peer_config by peer_id plus remote_health (/health probe, semver compat vs this server).

ParametersJSON Schema
NameRequiredDescriptionDefault
peer_idYes

TDQS

B3.4/5.0
Behavior3/5

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

With no annotations, the description carries full burden. It adds context about the remote health check including '/health probe' and 'semver compat vs this server', but does not disclose potential error conditions, authentication needs, or side effects.

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

Conciseness4/5

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

The description is a single, efficient sentence that front-loads the action and resource. It wastes no words, though slightly more structure could improve readability.

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

Completeness2/5

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

Given no output schema or annotations, the description lacks completeness. It does not explain the output structure, error handling, or prerequisites, leaving an agent with insufficient information for reliable invocation.

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

Parameters2/5

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

Schema description coverage is 0%, so description must compensate. It mentions 'peer_id' as the identifier but adds no details on format, constraints, or how the parameter is used beyond the schema.

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

Purpose5/5

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

The description clearly states 'Fetch peer_config by peer_id plus remote_health', specifying the action and resources. It distinguishes itself from sibling tools like 'list_peers' by focusing on a single peer's detailed status.

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

Usage Guidelines3/5

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

The description implies usage when you need peer config and health for a specific peer, but provides no explicit guidance on when to choose this tool over alternatives like 'list_peers' or 'sync_peer'.

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

get_relationship_snapshot

Get the current snapshot of a specific relationship with provenance

ParametersJSON Schema
NameRequiredDescriptionDefault
source_entity_idYesSource entity ID
target_entity_idYesTarget entity ID
relationship_typeYesRelationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it.
get_schema_recommendationsB

Get schema update recommendations for an entity type from raw_fragments analysis, agent suggestions, or inference.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourceNoRecommendation source (default: all)
statusNoFilter by recommendation status (default: pending)
user_idNoUser ID for user-specific recommendations (optional)
entity_typeYesEntity type to get recommendations for

TDQS

B3.2/5.0
Behavior2/5

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

With no annotations, description bears full burden. It implies a read operation but doesn't confirm safety, side effects, or response behavior. No mention of authorization, rate limits, or what happens if no recommendations exist.

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

Conciseness5/5

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

Single sentence efficiently conveys action and sources. Front-loaded with verb and resource, no redundancy.

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

Completeness2/5

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

No output schema provided, but description does not describe what recommendations contain (e.g., field changes, confidence). Missing details on pagination or ordering. Incomplete for a retrieval tool.

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

Parameters3/5

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

Schema has 100% description coverage. Description adds 'from raw_fragments analysis, agent suggestions, or inference' which partially overlaps with source enum. Adds marginal value beyond schema.

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

Purpose5/5

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

Description clearly states verb 'get', resource 'schema update recommendations', and scope 'for an entity type from raw_fragments, agent suggestions, or inference'. Distinguishes from sibling tools like analyze_schema_candidates by focusing on recommendations.

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

Usage Guidelines2/5

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

No guidance on when to use this tool vs alternatives like analyze_schema_candidates or other sibling tools. Lacks context about prerequisites or typical scenarios.

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

get_session_identityA

Resolve the current session's attribution: trust tier, AAuth / clientInfo fields, active anonymous-write policy, and whether the session is eligible for trusted writes. Safe to call as a preflight health check; does not write any rows.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior3/5

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

With no annotations provided, the description carries full burden. It states the tool does not write any rows, which is good. However, it lacks details on potential performance impact, authentication requirements, or any rate limits that might affect usage.

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

Conciseness5/5

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

The description is two sentences long, front-loaded with the purpose, and includes critical usage guidance. Every word contributes value without redundancy.

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

Completeness5/5

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

Given no output schema, the description adequately lists the key fields returned (trust tier, AAuth/clientInfo, anonymous-write policy, write eligibility) and clarifies safety. This is complete for a simple, zero-parameter introspection tool.

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

Parameters4/5

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

There are no parameters, so the schema coverage is trivially 100%. The description does not need to add parameter info. Per the guideline, 0 parameters yields a baseline of 4.

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

Purpose5/5

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

The description clearly states the tool resolves the current session's attribution details including trust tier, AAuth/clientInfo fields, and write eligibility. It distinguishes itself from sibling tools like get_authenticated_user by focusing on session identity rather than just user info.

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

Usage Guidelines4/5

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

The description explicitly states it is safe to call as a preflight health check and does not write any rows, which guides when to use it. However, it does not explicitly mention scenarios to avoid or alternative tools for related queries.

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

get_subscription_statusA

Return one subscription snapshot by subscription_id (webhook secret omitted).

ParametersJSON Schema
NameRequiredDescriptionDefault
subscription_idYes

TDQS

A3.7/5.0
Behavior3/5

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

No annotations are provided, so the description bears the full burden. It states the output is a snapshot and that the webhook secret is omitted, which is useful. However, it does not disclose permissions, error conditions, or whether the operation is a read (implied by name but not explicit). Lacks details on side effects or rate limits.

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

Conciseness5/5

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

The description is a single sentence, front-loaded with the main action, and includes a clarifying parenthetical. Every word earns its place; no fluff.

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

Completeness4/5

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

Given the tool's simplicity (one required param, no output schema, no annotations), the description is nearly complete. It tells what it returns and what is omitted. However, it could mention potential null return or error cases, but for a basic retrieval, this is sufficient.

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

Parameters2/5

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

Schema description coverage is 0%, requiring the description to compensate. The description only says 'by subscription_id', adding little beyond the schema's property name. It does not explain the format, constraints, or how to obtain the ID. Baseline would be 3 if coverage were high, but here it's low and the description fails to fill the gap.

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

Purpose5/5

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

Description clearly states 'Return one subscription snapshot by subscription_id', which is a specific verb and resource. It distinguishes from siblings like list_subscriptions (which returns multiple) and subscribe/unsubscribe (which are mutations). The parenthetical note about omitting webhook secret adds precision.

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

Usage Guidelines3/5

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

The description implies usage when you need a single subscription snapshot, but does not explicitly state when to use this vs. alternatives (e.g., list_subscriptions for multiple, subscribe for creation). No when-not-to-use guidance is provided.

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

health_check_snapshotsA

Check for stale entity snapshots (snapshots with observation_count=0 but observations exist). Returns health status and count of stale snapshots.

ParametersJSON Schema
NameRequiredDescriptionDefault
auto_fixNoIf true, automatically recompute stale snapshots (default: false)

TDQS

A4/5.0
Behavior3/5

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

No annotations exist, so the description carries full burden. It discloses the check logic and auto_fix action, but does not explain what recompute entails (e.g., permissions, side effects) or return details like health status format.

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

Conciseness5/5

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

Two sentences with no redundancy. The primary purpose and key parameter are front-loaded. Every word earns its place.

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

Completeness4/5

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

Given no output schema and one optional parameter, the description sufficiently explains purpose and auto_fix. However, it could explicitly state the return type (e.g., a JSON object with 'stale_count'), but overall it's adequate.

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

Parameters4/5

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

Schema coverage is 100% and the description adds meaning by explaining auto_fix default and effect. The description goes beyond schema by clarifying the conditional recompute behavior.

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

Purpose5/5

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

The description clearly states the tool checks for stale entity snapshots, defines the condition (observation_count=0 with existing observations), and specifies outputs (health status and count). It uses specific verb and resource, distinguishing it from unrelated tools.

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

Usage Guidelines3/5

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

The description implies usage for monitoring snapshot health, but does not explicitly state when to use it versus other tools or provide exclusions. No guidance on alternatives like other health checks is given.

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

identify_entity_by_signalsA

Resolve an entity from a multi-signal bundle (name, email, company, domain, phone, and open-ended string props). Returns best_match with identity_score, resolution_band (high/medium/low/unresolved), ranked candidates, and matched_signals. Use when you have partial or combined identity information and want a single-call resolution with confidence scoring.

ParametersJSON Schema
NameRequiredDescriptionDefault
signalsYesBundle of identity signals. All fields are optional strings. The five well-known keys (name, email, company, domain, phone) receive their canonical weights; any additional keys are treated as open-ended string signals with weight 0.4.
user_idNoOptional user_id override (scoped to callers with privilege to query on behalf of another user).
entity_typeNoRestrict resolution to this entity type. Takes precedence over entity_types.
entity_typesNoRestrict resolution to these entity types. Merged with synonym-expanded types when combined with signals.
max_candidatesNoMaximum candidates to return in the candidates array (best_match excluded). Default 5, max 20.
include_observationsNoWhen true, attach recent observations to best_match and each candidate.

TDQS

A4.2/5.0
Behavior3/5

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

No annotations exist, so the description must carry the full burden. It discloses output structure (best_match, identity_score, etc.) but does not mention side effects, idempotency, or authentication requirements. For a resolution tool, this is adequate but not comprehensive.

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

Conciseness5/5

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

Two sentences, front-loaded with purpose and output structure. No superfluous words. Every sentence earns its place.

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

Completeness4/5

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

Given the tool's complexity (nested signals, multiple parameters, no output schema), the description adequately covers return values and usage scenario. It does not explain the resolution algorithm fully, but that level of detail is unnecessary for agent selection.

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

Parameters4/5

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

Schema coverage is 100%, but the description adds value by explaining canonical weights for well-known keys and weight 0.4 for open-ended keys, which the schema lacks. This aids the agent in understanding signal importance.

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

Purpose5/5

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

The description clearly states the tool's action: resolving an entity from a multi-signal bundle (name, email, company, domain, phone, open-ended strings). It specifies output fields (best_match, identity_score, resolution_band, etc.), distinguishing it from sibling tools like retrieve_entities that use exact IDs.

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

Usage Guidelines4/5

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

Explicit guidance is provided: 'Use when you have partial or combined identity information and want a single-call resolution with confidence scoring.' It does not explicitly state when not to use or list alternatives, but the context of sibling tools implies alternatives for exact ID lookups.

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

list_entity_submissionsC
Read-only

List recent entities of a given entity_type for the authenticated user.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
offsetNo
entity_typeYes

TDQS

C2.6/5.0
Behavior2/5

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

Description adds 'recent' implying ordering but does not clarify ordering criteria or pagination behavior. Annotations already declare readOnlyHint=true, so minimal added value.

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

Conciseness3/5

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

Single sentence, no fluff, but omits important details about parameters and behavior. Conciseness should not come at cost of completeness.

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

Completeness2/5

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

No output schema, so description should indicate return structure. Does not mention pagination, ordering, or what 'recent entities' includes. Incomplete for a list tool with pagination parameters.

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

Parameters2/5

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

Only 'entity_type' is implicitly explained as the filter. 'limit' and 'offset' are not described despite being crucial for pagination. Schema description coverage is 0%, so description should compensate but does not.

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

Purpose4/5

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

Description clearly states verb 'list', resource 'entities', filter by 'entity_type', and scope 'for the authenticated user'. It distinguishes from sibling 'list_entity_types' but not from similar list tools like 'retrieve_entities'.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus alternatives like 'retrieve_entities' or 'submit_entity'. No when-not-to-use or prerequisites mentioned.

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

list_entity_typesA

List available entity types. Without keyword: returns a short summary (entity_type, schema_version, field_count) for all types. field_count here means schema field width, not stored entity row count. With keyword: returns full schema (field_names, field_summary) for matching types; pass summary: true to get summary only. Uses hybrid search when keyword is provided: keyword matching first, then vector semantic search. Use before storing structured data to determine the correct entity_type.

ParametersJSON Schema
NameRequiredDescriptionDefault
keywordNo
summaryNo
user_idNo

TDQS

A4.4/5.0
Behavior4/5

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

No annotations provided, but the description discloses key behaviors: two modes of operation, hybrid search mechanism, meaning of field_count. Lacks details on pagination or rate limits but sufficient for core functionality.

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

Conciseness5/5

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

Single well-structured paragraph, front-loaded with purpose, then behavior details. Every sentence adds value without redundancy.

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

Completeness4/5

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

Given the complexity (3 parameters, two modes, hybrid search), the description covers the key behaviors and return structure hints. Could mention user_id role and edge cases, but sufficient for most use cases.

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

Parameters4/5

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

With 0% schema description coverage, the description explains keyword and summary parameters thoroughly. user_id is not explained, leaving a gap, but the other two parameters are well-covered.

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

Purpose5/5

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

The description clearly states the tool lists available entity types, with distinct behaviors for with and without keyword. It distinguishes itself from sibling tools like get_entity_type_counts and retrieve_entities.

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

Usage Guidelines4/5

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

Explicitly says 'Use before storing structured data to determine the correct entity_type', giving clear when-to-use guidance. Does not mention when not to use or alternatives, but sibling tools are distinct.

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

list_interpretationsC

List interpretation runs for the authenticated user, optionally filtered by source_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
offsetNo
user_idNo
source_idNo

TDQS

C2.5/5.0
Behavior2/5

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

No annotations provided. Description states it lists runs for the authenticated user with optional source_id filter, but lacks details on authentication requirements, side effects, rate limits, or handling of empty results. The description is too brief to compensate for missing annotations.

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

Conciseness3/5

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

A single concise sentence, but it lacks detail. It is not wasteful, but the brevity sacrifices informativeness.

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

Completeness1/5

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

Without output schema or annotation support, the description is critically incomplete. It omits pagination details (limit/offset), the meaning of user_id, and what an interpretation run entails, leaving the agent with insufficient context.

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

Parameters2/5

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

Schema has 4 parameters (user_id, source_id, limit, offset) with 0% coverage in schema descriptions. The description only mentions source_id as an optional filter, adding no meaning for user_id, limit, or offset.

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

Purpose4/5

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

The description clearly states the action (list) and resource (interpretation runs) with authentication scope and optional filtering. However, it does not distinguish from any close sibling tools, as there is no other list-interpretations tool among siblings.

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

Usage Guidelines2/5

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

No explicit guidance on when to use this vs. alternatives. It mentions optional filtering but does not specify when not to use or prerequisites. No contrast with create_interpretation or other list tools.

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

list_observationsC

List all observations for a given entity

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
offsetNo
entity_idNo
created_sinceNoISO 8601 timestamp. Return only observations whose observed_at is greater than or equal to this value.
updated_sinceNoISO 8601 timestamp. Return only observations whose observed_at is greater than or equal to this value.

TDQS

C2/5.0
Behavior2/5

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

No annotations are present, so the description bears full responsibility. It fails to disclose pagination, default parameter behavior, or error responses, leaving agent uninformed.

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

Conciseness2/5

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

The description is a single short sentence, but it omits critical details and does not earn its place by being informative. It is under-specified rather than concise.

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

Completeness1/5

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

Given 5 parameters, no output schema, and no annotations, the description is woefully incomplete. An agent cannot determine proper usage, pagination, or what constitutes an observation.

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

Parameters1/5

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

Schema coverage is low (40%), but description adds no parameter information. The phrase 'for a given entity' suggests entity_id is needed, but the schema marks it not required, creating confusion.

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

Purpose3/5

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

The description states 'List all observations for a given entity', which identifies the resource and action. However, it does not differentiate from sibling list tools (e.g., list_interpretations, list_peers) and is ambiguous about whether entity_id is required.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool vs. alternatives. Among many list tools in the sibling list, the description lacks context for selection.

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

list_peersA

List peer_config rows for the current user (secrets redacted).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior3/5

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

No annotations are provided, so the description carries full burden. It discloses that secrets are redacted, which is a behavioral trait. However, it does not mention idempotency, authentication requirements, or output format. For a simple list operation, this is acceptable but not thorough.

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

Conciseness5/5

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

The description is a single concise sentence that effectively communicates the purpose and key behavioral note. No extraneous words; every part earns its place.

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

Completeness4/5

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

Given the simplicity of the tool (no parameters, no output schema), the description covers the essential aspects: purpose and secrets redaction. It could be slightly more explicit about returning all rows, but overall it is sufficient.

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

Parameters3/5

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

The input schema has no parameters, so schema description coverage is 100%. The description does not add parameter information, but none is needed. Baseline score of 3 applies.

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

Purpose5/5

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

The description clearly states the tool lists peer_config rows for the current user, with a note about secrets redaction. It uses a specific verb and resource, and the scope is explicit. It distinguishes from sibling tools like add_peer or remove_peer.

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

Usage Guidelines2/5

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

No explicit guidance is given on when to use this tool versus alternatives like get_peer_status or sync_peer. The name and description imply it's for listing, but no when-to-use or when-not-to-use information is provided.

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

list_potential_duplicatesA

List candidate duplicate entity pairs for an entity_type. Read-only fuzzy post-hoc detector; never auto-merges. Per-schema thresholds and fields come from the schema's duplicate_detection_threshold and duplicate_detection_fields; callers may override threshold per call. Confirm pairs with the user, then hand off to merge_entities.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of candidate pairs to return. Defaults to 50.
user_idNoOptional. Inferred from authentication if omitted.
thresholdNoSimilarity threshold in (0, 1]. Defaults to the schema's duplicate_detection_threshold or 0.85.
entity_typeYesEntity type to scan for duplicates (e.g. contact, company).

TDQS

A4.8/5.0
Behavior5/5

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

No annotations provided, but description fully covers behavioral traits: read-only, fuzzy post-hoc detector, never auto-merges, threshold override. No contradiction.

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

Conciseness5/5

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

Three sentences, each adding essential information. No wasted words. Purpose, usage, and behavior are front-loaded.

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

Completeness4/5

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

No output schema, but description covers key aspects: input, behavior, and next steps. Minor missing detail on return format (e.g., pairs with similarity scores), but sufficient for agent understanding.

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

Parameters4/5

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

Schema has 100% coverage for 4 parameters. Description adds meaning by explaining that per-schema thresholds come from schema fields and callers may override threshold per call, going beyond raw schema descriptions.

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

Purpose5/5

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

Description clearly states it lists candidate duplicate entity pairs for a given entity_type. Distinguishes itself from sibling merge_entities by explaining it is the detection step before merging.

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

Usage Guidelines5/5

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

Explicitly says it is read-only and never auto-merges, advises confirming with user before calling merge_entities. Explains threshold behavior and override capability.

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

list_recent_changesA
Read-only

List the most recently changed records across core Neotoma tables (entities, sources, observations, interpretations, relationships, timeline_events) for the authenticated user. Returns items ordered by latest activity_at.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of items to return (default 50, max 200).
offsetNoPagination offset (default 0).

TDQS

A3.9/5.0
Behavior4/5

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

The annotation 'readOnlyHint: true' already indicates a safe read operation. The description adds context about the tables scanned, ordering by 'activity_at', and authentication requirement, which enriches the behavioral understanding beyond the annotation.

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

Conciseness5/5

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

The description is a single, well-structured sentence that efficiently conveys the tool's purpose and key behavioral details (tables, ordering, authentication). No redundant information is present.

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

Completeness3/5

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

No output schema is provided, and the description does not specify the structure of returned items (e.g., whether they contain full records or just IDs). Given the tool aggregates across multiple tables, more detail about the output format would improve completeness.

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

Parameters3/5

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

Schema coverage is 100% and both parameters (limit, offset) have clear descriptions in the input schema. The description does not add any parameter-specific meaning; it only mentions ordering. With high schema coverage, a score of 3 is appropriate.

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

Purpose5/5

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

The description clearly states the verb 'List', the resource 'recently changed records across core Neotoma tables', and specifies the scope 'for the authenticated user'. It distinguishes itself from sibling list tools like list_interpretations or list_observations by aggregating across multiple tables.

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

Usage Guidelines3/5

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

The description implies this tool is for retrieving a recent activity feed, but it does not explicitly state when to use it versus the many sibling list tools (e.g., list_entity_submissions, list_relationships). No 'when not to use' or alternatives are provided, leaving the agent to infer usage context.

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

list_relationships

List relationships for an entity, or discover the relationship type(s) between two specific entities. Filter by entity_id (with direction), or by source_entity_id and/or target_entity_id, and optionally relationship_type. To discover the type before delete_relationship, pass both source_entity_id and target_entity_id: each returned relationship carries its relationship_type. Soft-deleted relationships are excluded by default, so a deleted edge will not be re-offered for deletion; pass include_deleted: true to include them for audit. Paginated via limit/offset.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of relationships to return.
offsetNoNumber of relationships to skip before returning results.
user_idNoOptional user_id override (scoped to callers with privilege to query on behalf of another user). When omitted, the authenticated user is used.
directionNoDirection applied when `entity_id` is set. `incoming`/`inbound` matches relationships where the entity is the target; `outgoing`/`outbound` matches relationships where the entity is the source; `both` (default) matches either side. both
entity_idNoEntity ID to match against either the source or target of each relationship (filtered further by `direction`). Legacy filter pattern; prefer `source_entity_id` / `target_entity_id` for new code.
include_deletedNoWhen `false` (default), soft-deleted relationships are excluded from the result. When `true`, soft-deleted edges are included (audit/history use). A relationship is soft-deleted once its highest-priority deletion observation is recorded; the snapshot row itself persists.
source_entity_idNoMatch relationships whose `source_entity_id` equals this value.
target_entity_idNoMatch relationships whose `target_entity_id` equals this value.
relationship_typeNoRelationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).
list_relationship_types

Discover the registered relationship vocabulary visible to the authenticated user, including types with no edges. Read this before writing an unfamiliar edge. Registration metadata is advisory except acyclic, which is enforced.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeNo
keywordNoCase-insensitive filter over name and description.
include_deactivatedNo
include_edge_countsNoInclude edge_count per type. Costs one aggregate query; "rows written", never evidence of registration.
list_subscriptionsA

List the current user's active subscriptions (webhook secrets omitted).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior2/5

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

No annotations provided; description only notes webhook secrets omitted. Lacks disclosure of side effects, auth requirements, rate limits, or response structure.

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

Conciseness5/5

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

Single sentence with clear verb and caveat. Front-loaded and no wasted words.

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

Completeness3/5

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

No output schema or annotations. Description is minimal but adequate for a simple list; lacks explanation of return format, pagination, or error handling.

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

Parameters4/5

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

No parameters (baseline 4). Description adds meaning by specifying scope and omission, which is helpful beyond schema.

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

Purpose5/5

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

Clearly states verb 'List', resource 'subscriptions', scope 'current user's active', and caveat about webhook secrets. Distinguishes from siblings like 'subscribe' and 'unsubscribe'.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus alternatives (e.g., subscribe, unsubscribe) or context for the list.

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

list_timeline_eventsB
Read-only

Query timeline events with filters (type, date range, source). Returns chronological events derived from date fields in sources.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
offsetNo
user_idNo
end_dateNo
order_byNoevent_timestamp
event_typeNo
start_dateNo

TDQS

B3.2/5.0
Behavior3/5

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

The annotation already indicates readOnlyHint=true. The description adds that events are chronological and derived from date fields, providing some context beyond the annotation, but does not disclose pagination behavior, ordering defaults, or other traits present in the schema.

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

Conciseness5/5

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

Two sentences with no wasted words. The first sentence immediately states the action and scoping filters. Information is front-loaded and essential.

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

Completeness2/5

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

With 7 parameters, no output schema, and no parameter description coverage, the description is too brief. It does not explain what constitutes a timeline event, how sources relate to parameters, or the meaning of ordering/pagination. More context is needed for a complete understanding.

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

Parameters2/5

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

Schema description coverage is 0% (no parameter descriptions). The description mentions filter types (type, date range, source) but does not map them to specific parameters (event_type, start_date/end_date, user_id) nor explain limit, offset, or order_by. It fails to compensate adequately for the lack of schema descriptions.

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

Purpose4/5

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

The description clearly states it queries timeline events with filters, specifying filter dimensions (type, date range, source). This provides a specific verb and resource, distinguishing it from sibling tools that list other entities like observations or relationships, though explicit differentiation is missing.

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

Usage Guidelines3/5

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

The description implies usage for querying timeline events with filters but provides no guidance on when to use this tool versus alternatives (e.g., list_observations or list_relationships) or when not to use it.

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

manage_bundlesA

Inspect and manage Neotoma bundles (the deliverable unit shipping schemas, record-type docs, and skills). action=list returns all bundles with type/version/enabled/always_active/provides count; action=info (with bundle) returns full manifest detail; action=install/enable/disable (with bundle) toggle persisted enable state. Default-install bundles (core, infrastructure, core_workflows) are always active and cannot be disabled. Disabling a schema bundle stops its types from auto-creating under guided/locked while preserving existing data. Returns structured JSON.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionYesThe bundle management action to perform.
bundleNoBundle name. Required for info, install, enable, and disable; ignored for list.

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations provided, the description carries full burden and excels: it explains action-specific outputs, persisted state toggling, exceptions for default bundles, side effects of disabling (stops auto-creating types while preserving data), and the return type (structured JSON). No contradictions 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.

Conciseness5/5

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

The description is concise and well-structured: three sentences with the main verb+resource up front, followed by action details and constraints. Every sentence adds necessary information without redundancy.

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

Completeness5/5

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

Despite lacking an output schema, the description covers all action types, required parameters, exceptions, side effects, and return format. The tool's complexity is fully addressed in a compact space.

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

Parameters4/5

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

Schema coverage is 100% and parameters already have descriptions, but the tool description adds behavioral meaning beyond the schema (e.g., what happens when disabling a bundle, what list returns). This goes beyond the baseline of 3 for high schema coverage.

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

Purpose5/5

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

The description clearly states the tool's purpose: 'Inspect and manage Neotoma bundles' and enumerates specific actions (list, info, install, enable, disable) with distinct outcomes. This differentiates it from sibling tools focused on entities, relationships, and other domains.

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

Usage Guidelines4/5

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

The description provides usage context for each action (e.g., 'action=info (with bundle) returns full manifest detail') and notes constraints like default-install bundles cannot be disabled. It does not explicitly name alternative tools, but the sibling list shows no overlapping bundle tools, so the guidance is sufficient.

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

merge_entitiesB

Merge duplicate entities. Rewrites observations from source entity to target entity and marks source as merged.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo
merge_reasonNo
to_entity_idNo
from_entity_idNo

TDQS

B3.3/5.0
Behavior2/5

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

No annotations provided, so description must disclose behavioral traits. It mentions rewriting observations and marking source, but does not clarify if source is deleted, whether observations are moved or copied, or any destructive side effects. Missing critical details for a mutation tool.

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

Conciseness5/5

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

Two concise sentences, no fluff, front-loaded with the primary action and key effect.

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

Completeness2/5

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

No output schema, so description should explain return value. Does not mention result of merge (e.g., success/failure, status of source entity). With 4 parameters and no schema descriptions, the description is too sparse for an agent to fully understand the tool's behavior.

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

Parameters2/5

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

Schema has 0% parameter descriptions. The description does not explain any parameter (from_entity_id, to_entity_id, merge_reason, user_id) beyond their names. Names are somewhat self-explanatory but incomplete for an agent to invoke correctly without format constraints.

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

Purpose5/5

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

The description clearly states the action (merge), resource (entities), and the effect: rewrites observations and marks source as merged. It distinguishes from sibling tools like split_entity.

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

Usage Guidelines3/5

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

Implied usage for deduplication, but no explicit guidance on when to use vs alternatives (e.g., delete_entity, split_entity). No prerequisites or exclusions mentioned.

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

neotoma_turn_summaryA

FU-2026-05-002. Compute the per-turn Neotoma status line (msg N/M, stored K, retrieved L) plus an optional ui:// widget URI for ext-apps clients. Call at the end of every turn after the closing assistant store completes. Pass the assistant message's conversation_id and turn_key; the server resolves stored/retrieved/issue entities, turn ordinal, and total message count. Agents emit the returned status_line in the user-visible reply; ext-apps clients additionally render widget_uri inline when present.

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idNo
turn_keyYes`turn_key` of the assistant `conversation_message` whose turn just completed. Format `{conversation_id}:{turn_id}:assistant` per the closing-store recipe. The server resolves the entity via `canonical_name_fields: ["turn_key"]`.
conversation_idYesStable conversation identifier (the `conversation_id` field on the `conversation` entity, host-provided or agent-derived per the turn identity rules). Used to disambiguate when the same `turn_key` string could in principle belong to multiple conversations.

TDQS

A4.1/5.0
Behavior3/5

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

No annotations provided, so description carries full burden. It explains what the tool computes and how entities are resolved, but does not disclose whether it is read-only/destructive, nor any side effects or permissions.

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

Conciseness4/5

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

Dense but concise; every sentence adds value. The ticket number 'FU-2026-05-002' is slightly extraneous but does not detract significantly. Front-loaded with main purpose.

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

Completeness4/5

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

Given no output schema, the description explains what the returned status_line and widget_uri are for. Missing explicit return structure and error handling, but adequate for a straightforward compute tool.

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

Parameters4/5

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

Adds meaning beyond schema: specifies turn_key format, explains conversation_id disambiguation, and notes server entity resolution. Only user_id lacks description in both schema and text, but it's optional.

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

Purpose5/5

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

The description explicitly states the tool computes the per-turn Neotoma status line and optional widget URI, with clear verb-resource pairing. The task is unique among siblings, no ambiguity.

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

Usage Guidelines4/5

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

Clearly says when to call 'at the end of every turn after the closing assistant store completes.' Does not explicitly state when not to call, but context is sufficient.

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

npm_check_updateA

Check if a newer npm version is available. Returns updateAvailable, message, suggestedCommand, and when include_release_notes is true optional release_url, release_notes_excerpt, breaking_changes_excerpt, enrichment_error. When include_capability_delta is true, adds new_tools (tools added since currentVersion), removed_tools (tools removed since currentVersion), capability_delta_recommendation (upgrade guidance string), and capability_delta_note (present ONLY when delta computation degraded — e.g. unparseable versions or missing manifest — its absence signals no degradation). Call at session start to encourage user to upgrade.

ParametersJSON Schema
NameRequiredDescriptionDefault
distTagNoDist tag to check (default: latest)latest
packageNameYesnpm package name (e.g. neotoma)
currentVersionYesCurrent version reported by the client
include_release_notesNoWhen true, fetches npm version metadata and optional GitHub release body (best-effort); adds release_url and excerpts. Default false to limit registry/GitHub load.
include_capability_deltaNoWhen true, adds new_tools, removed_tools, and capability_delta_recommendation to the response — a machine-readable list of MCP tools that were added or removed between currentVersion and the latest release. Sourced from the committed capability manifest (generated, not hand-maintained). Default false.

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations provided, the description bears full responsibility for disclosure. It thoroughly explains the tool's behavior: it fetches npm registry data, includes optional release notes and capability delta, indicates best-effort nature, and clarifies conditions under which fields appear (e.g., capability_delta_note only on degradation). No contradictions.

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

Conciseness4/5

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

The description is lengthy but each sentence contributes necessary detail. It fronts the core purpose and then systematically lists return fields and conditions. Could be slightly more concise, but the complexity of the tool justifies the length.

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

Completeness5/5

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

Given the absence of an output schema, the description fully documents all return fields and their conditional presence. It covers every aspect of the tool's behavior, leaving no ambiguity for an AI agent to invoke or interpret results.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3. The description adds value by explaining the effect of each boolean flag on the return object (e.g., include_release_notes adds release_url and excerpts; include_capability_delta adds new_tools, removed_tools, etc.). This goes beyond the schema's descriptions.

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

Purpose5/5

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

The description begins with 'Check if a newer npm version is available', a specific verb and resource. It then details the return values, clearly distinguishing this tool's purpose from any sibling tools, none of which deal with npm version checking.

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

Usage Guidelines4/5

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

The description explicitly states when to use the tool ('Call at session start to encourage user to upgrade'), providing clear context. It does not mention when not to use it or alternatives, but given the unique purpose among siblings, this is not a significant gap.

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

parse_fileA

Parse local or base64-encoded files into agent-readable text and first-page PDF images without storing anything. Use before store when you need to extract entities from a file.

ParametersJSON Schema
NameRequiredDescriptionDefault
file_pathNoLocal file path. Preferred in local environments.
mime_typeNoOptional MIME type. Auto-detected from file_path when omitted.
file_contentNoBase64-encoded file content.
original_filenameNoOptional filename hint for MIME detection and PDF parsing.

TDQS

A4.4/5.0
Behavior4/5

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

No annotations provided, so description handles transparency. Mentions no storage and output of text and images, but lacks detail on error handling, output format, or behavior with large files.

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

Conciseness5/5

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

Two sentences, front-loaded with purpose, no wasted words. Highly concise and easy to process.

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

Completeness4/5

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

No output schema, so description should clarify return format. Mentions 'text and first-page PDF images' but not structure or data type. Good for intended use but could be more complete.

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

Parameters3/5

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

Schema covers 100% of parameters with descriptions. The tool description adds context about preferred local file path but doesn't significantly enhance per-parameter semantics beyond schema.

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

Purpose5/5

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

Clearly states it parses files into text and first-page PDF images, and explicitly says it does not store anything, distinguishing it from the 'store' sibling tool.

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

Usage Guidelines5/5

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

Explicitly tells when to use: 'Use before store when you need to extract entities from a file.' Provides clear guidance on context and intended workflow.

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

patch_array_item

Atomically patch one item of a structured array field by a portable non-null scalar key, instead of read-modify-full-array-write. Requires the active schema to declare that array with merge_array_by_key and the same key_field; missing/mismatched policy fails closed. Loads current state and writes inside one transaction, so concurrent patches to DIFFERENT keys both survive. Pass expected_item_version to detect a same-key race or expected_item_absent for race-safe creation; a conflict returns the current item instead of overwriting.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemYesFields to set on the item identified by `key_value`. Merged onto the existing item (shallow) when the key already exists; `key_field` is always set to `key_value` on the written item regardless of what `item` contains.
fieldYesName of the array field to patch.
user_idNo
entity_idYes
key_fieldYesName of the field on each array item that identifies it. Must match the field's declared `merge_array_by_key` `key_field` for the write to be reflected in the snapshot's reducer output.
key_valueYesPortable non-null JSON scalar identifying the row. Numbers must be finite safe integers. The reducer preserves older rows with non-scalar or unsafe-number keys as unkeyed legacy rows, but new patches cannot create them.
entity_typeYes
idempotency_keyYes
expected_item_absentNoWhen true, create only if no item with `key_value` exists. Concurrent creators for the same key produce one success and one `409 ERR_ARRAY_ITEM_CONFLICT` with the committed item.
expected_item_versionNoContent-hash version of the item as last observed by the caller (returned as `item_version` by a prior patch, or computable client-side as SHA-256 over UTF-8 stable serialization: object keys sort lexicographically, arrays preserve order, and scalar values use JSON spellings). When supplied and stale, the patch is refused with `409 ERR_ARRAY_ITEM_CONFLICT` and nothing is written. Omit to always last-write-win on this one row (still scoped — never touches other keys).
publish_rendered_pageA

Turn a rendered_page into a ready-to-share guest URL in one call. Pass an existing rendered_page entity_id, or inline {title, html_body, custom_css} to create one. Mints a guest_access_token scoped to that page and returns the absolute …/entities//html?access_token= URL plus ttl_seconds. html_body is injected verbatim into a server template — no html/head/body wrappers. Each call mints a fresh token (tokens are hash-only at rest).

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoPage title (used when creating a new rendered_page). Rendered into <title> and the <h1> if no html_body header overrides.
user_idNoOptional. Inferred from authentication if omitted.
entity_idNoExisting rendered_page entity id to publish. Omit to create a new page from the inline fields below.
html_bodyNoPage body HTML, injected verbatim into the server template. Do NOT include <html>/<head>/<body> wrappers. Used when creating a new rendered_page.
custom_cssNoOptional CSS injected as an inline <style> in <head> (used when creating a new rendered_page).
idempotency_keyNoOptional idempotency key for the inline-create path (mutating op). Same key + same content reuses the same rendered_page instead of creating a duplicate. Ignored when entity_id is supplied.
meta_descriptionNoOptional <meta name=description> value, escaped on render (used when creating a new rendered_page).

TDQS

A4.7/5.0
Behavior5/5

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

The description discloses key behavioral traits: each call mints a fresh token, tokens are hash-only at rest, html_body is injected verbatim without wrapper elements, and idempotency key behavior for inline creation. These details go beyond the schema and annotations (which are absent), fully informing the agent of side effects and constraints.

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

Conciseness5/5

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

The description is a single, dense paragraph that front-loads the purpose and then efficiently covers details. Every sentence adds value, with no repetition or fluff. It is well-structured for an AI agent to parse quickly.

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

Completeness4/5

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

The description covers the major aspects: usage modes, parameter behavior, token generation, and return value. It lacks error handling specifics and does not mention authentication requirements beyond 'user_id inferred from authentication.' Given the complexity (7 parameters, multiple modes), it is fairly complete but could include a brief note on failure cases.

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

Parameters5/5

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

Although the input schema already has 100% description coverage, the description adds significant context: it explains the two usage modes (entity_id vs. inline fields), the verbatim injection of html_body, the purpose of idempotency_key, and the optional nature of user_id. This adds meaning beyond the schema alone.

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

Purpose5/5

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

The description clearly states the tool's purpose: turning a rendered_page into a ready-to-share guest URL. It outlines two distinct usage modes (pass an existing entity_id or create one inline) and specifies the return value (absolute URL with token and TTL). No sibling tool offers similar functionality, so it effectively distinguishes itself.

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

Usage Guidelines4/5

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

The description provides clear context on when to use the tool (to publish a rendered page) and the two modes. It does not explicitly exclude scenarios or mention alternatives, but given the sibling list lacks a direct alternative, a score of 4 is appropriate.

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

query_contacts_at_companyA

Answer "who do we have connected at company X": resolve company_name to the canonical company entity (exact-normalized match first, then a conservative fuzzy pass — the same resolution order used when a contact's organization field auto-links to a company at store time) and return every contact linked to it via a live works_at edge. Read-only: never creates a company entity — when no company matches, returns company: null and an empty contacts list. Optional owner_user_id scopes the search to a specific partner's network (must equal the authenticated user's id today; no cross-tenant admission yet); omit to search the authenticated user's own graph.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of linked contacts to return. Applied after the full works_at edge set is resolved, so `total_contacts` on the response reflects the true pre-limit count.
company_nameYesFree-text company name to resolve, e.g. "Northgate" or "North Gate". Matched exact-normalized first, then fuzzy (see COMPANY_FUZZY_MATCH_THRESHOLD in src/services/company_resolution.ts).
owner_user_idNoOptional user_id override scoping the query to a specific partner's network (which partner's contacts/company graph to search), matching the `user_id` override pattern on /list_relationships. Must equal the authenticated user's id today (the server has no cross-tenant admission yet); supplying a different value is rejected. When omitted, the authenticated user's own graph is searched.

TDQS

A4.4/5.0
Behavior5/5

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

With no annotations provided, the description fully carries the behavioral burden. It explicitly discloses read-only behavior ('never creates a company entity'), the no-match return shape ('company: null and an empty contacts list'), the owner_user_id restriction ('must equal the authenticated user's id today'), and the resolution algorithm. This is exemplary transparency.

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

Conciseness5/5

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

The description is a single dense paragraph, but every clause earns its place: purpose, resolution order, read-only guarantee, no-match behavior, and owner scoping. It is front-loaded with the purpose and uses a clear colon to separate the core question from details. No redundant wording.

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

Completeness4/5

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

The description covers resolution, read-only behavior, no-match scenarios, and owner override thoroughly. Since there is no output schema, it briefly mentions response elements (company:null, empty contacts, total_contacts in schema) but does not fully enumerate the response fields. Still, for a query tool of this complexity, it is largely complete.

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

Parameters3/5

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

Schema coverage is 100% for all three parameters, and the schema already explains limit, company_name matching, and owner_user_id semantics. The description adds context about resolution order and the live edge, but does not significantly enrich parameter-level meaning beyond what the schema provides. Baseline 3 is appropriate.

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

Purpose5/5

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

The description opens with the exact question it answers ('who do we have connected at company X') and clearly states it returns every contact linked to the resolved company via a live works_at edge. This specifies the verb (query/return), resource (contacts at a company), and scope (canonical company entity), and differentiates it from sibling tools like list_relationships by focusing on company resolution.

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

Usage Guidelines4/5

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

The description gives clear context: use when you need contacts linked to a company, with optional owner scoping. It explains the resolution order (exact-normalized then fuzzy) and the read-only nature, but does not explicitly name alternative tools or state when not to use this tool. This meets 'clear context, no exclusions'.

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

register_relationship_type

Register a relationship type after discovering the vocabulary with list_relationship_types. Requires an active grant with register_relationship_type and relationship_types permission; global scope additionally needs explicit global permission. Defaults to user scope. Refresh cached tool definitions after registration, then write the edge and read it back.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeNoDefaults to "user" — the safe branch. This deliberately inverts register_schema, whose user_specific defaults to false and whose default branch is therefore both the widest blast radius and the one that records no identity.user
acyclicNoENFORCED. When true, create_relationship refuses an edge of this type that would close a loop among edges OF THIS TYPE within this tenant. Opt-in: a type whose semantics permit cycles should leave this unset.
inverseNoAdvisory only. Name of the inverse edge.
symmetricNoAdvisory only. Whether the edge reads the same both ways.
descriptionNo
relationship_typeYesIdentifier-shaped name, 1-64 characters, matching ^[A-Za-z][A-Za-z0-9_]*$. Casing-agnostic. A new name that differs from an existing active type only by case is rejected; the pre-existing PART_OF/part_of and DEPENDS_ON/depends_on pairs are grandfathered.
source_entity_typesNoAdvisory only. Not enforced at write time.
target_entity_typesNoAdvisory only. Not enforced at write time.
register_schema

Register a new schema or schema version. Supports both global and user-specific schemas.

ParametersJSON Schema
NameRequiredDescriptionDefault
forceNoBypass the entity-type naming guards (forbidden test-artifact patterns and the plural-name guard) for this call only. Required when entity_type is rejected with a message naming "force: true" as the remedy — e.g. a name the plural guard misclassifies (like "hypothesis"). Does not affect any other validation.
user_idNoUser ID for user-specific schema (required if user_specific=true)
activateNo
entity_typeYes
user_specificNo
reducer_configYesPer-field conflict-resolution config. merge_policies maps each field to a strategy: last_write (default — latest observed_at wins), highest_priority (the observation with the largest source_priority wins), most_specific, or merge_array; with an optional tie_breaker (observed_at | source_priority). Set highest_priority to honor source_priority — without it, source_priority is stored but ignored.
schema_versionNo1.0
schema_definitionYesSchema definition with fields object
remove_peerC

Deactivate a peer by peer_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
peer_idYes

TDQS

C2.6/5.0
Behavior2/5

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

No annotations are provided, so the description bears full responsibility for disclosing behavior. It states 'Deactivate a peer' but does not clarify whether the action is reversible, what happens to associated data, or any authentication requirements. With zero annotations, this is insufficient.

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

Conciseness3/5

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

The description is very short (one sentence) and to the point. However, brevity comes at the cost of missing important details. It is not verbose, but could be improved slightly without losing conciseness.

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

Completeness2/5

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

Given the simplicity of the tool (1 param, no output schema), the description is minimally acceptable but lacks behavioral context. It does not explain return values, side effects, or any error conditions. For a deactivation operation, more completeness is expected.

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

Parameters2/5

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

The input schema has one parameter 'peer_id' with 0% description coverage. The description merely repeats the parameter name ('by peer_id') without adding any semantic detail about format, constraints, or examples. The schema provides only a type string, leaving the agent with minimal understanding.

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

Purpose4/5

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

The description clearly states the action ('Deactivate a peer') and the required input ('by peer_id'). It is specific enough to understand the tool's purpose, though it does not explicitly differentiate from sibling tools like 'sync_peer' or 'add_peer'.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives (e.g., 'add_peer' or 'sync_peer'). The description does not specify prerequisites, context, or when not to use it.

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

resolve_sync_conflictD

Stub; use correct on the entity for manual resolution today.

ParametersJSON Schema
NameRequiredDescriptionDefault
strategyYes
entity_idYes
sender_peer_urlNoRequired for prefer_remote — remote Neotoma base URL (GET /entities/{entity_id})
guest_access_tokenNoOptional query access_token for guest read on the remote instance

TDQS

D1.1/5.0
Behavior1/5

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

No annotations provided. The description gives no behavioral information such as side effects, permissions, or success/failure conditions. 'Stub' implies the tool may not be functional, which is a critical behavioral trait left unspecified.

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

Conciseness2/5

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

The description is very short but not effectively concise—it omits essential information. 'Stub' indicates a placeholder, and the instruction to use an alternative tool suggests this description is not final.

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

Completeness1/5

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

Given the tool has 4 parameters, no output schema, and no annotations, the description is grossly incomplete. It fails to explain what the tool does, when to use it, or what the parameters mean.

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

Parameters1/5

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

Schema description coverage is 50% (only sender_peer_url and guest_access_token have descriptions). The description adds no meaning to parameters; it does not explain entity_id, strategy enum values, or how they interact.

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

Purpose1/5

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

The description 'Stub; use correct on the entity for manual resolution today.' does not state what the tool does. 'Stub' implies it's incomplete or non-functional, and the reference to 'correct' confuses the purpose. No specific verb or resource is described.

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

Usage Guidelines1/5

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

No guidance on when to use this tool vs alternatives. The mention of 'use correct on the entity' suggests an alternative but provides no context or conditions for choosing this tool.

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

restore_entity

Restore visibility of an entity through an immutable lifecycle observation and expose its current factual reduction, including ordinary facts accepted while hidden. After the explicit authority cutover, serialized action sequence controls visibility; before cutover, existing legacy behavior applies. Each accepted request is a separate action, without an idempotency key or historical beforeimage restoration.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNoOptional reason for restoration (audit)
user_idNoOptional. Inferred from authentication if omitted.
entity_idYesEntity ID to restore
entity_typeYesEntity type (e.g. company, person)
restore_relationship

Restore a deleted relationship. Creates an immutable restoration observation that outranks earlier observations. Relationship becomes visible in snapshots and queries again; later explicit deletion remains possible.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNoOptional reason for restoration (audit)
user_idNoOptional. Inferred from authentication if omitted.
source_entity_idYesSource entity ID
target_entity_idYesTarget entity ID
relationship_typeYesExact relationship type of the existing edge — the same vocabulary create_relationship writes. Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it.
retrieve_entitiesA

Use this when you need filtered entity lists (by type, pagination, and optional published/date filters) or lexical/semantic retrieval via search. Strict mode: search cannot be combined with non-default sorting or published filters. Set include_snapshots=false for lightweight responses that omit snapshot/provenance/raw_fragments. Use snapshot_filters to filter by snapshot field values server-side (e.g. { "status": { "op": "eq", "value": "active" } } for active entities). Compatibility aliases search_query and query are accepted but search is canonical. For deep pagination under the default sort (sort_by=entity_id), pass the next_cursor from a prior response back as cursor instead of a large offset; offset beyond a bounded depth is rejected and cursor is not supported with search, non-default sort_by, or a non-zero offset in the same call.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of entities to return (default 100). Capped at 500 when `include_snapshots` is true (the default), since each snapshot is hydrated synchronously; lower the page size or set `include_snapshots=false` for larger pages.
queryNoCompatibility alias for `search`.
cursorNoOpaque keyset pagination cursor from a previous response's `next_cursor`. Returns the next page in O(page size) time regardless of position, unlike `offset` which is bounded and deprecated. Only supported with the default `sort_by=entity_id`; cannot be combined with `search` or a non-zero `offset`. Reusing a cursor after changing `sort_order` returns a structured error.
offsetNoDeprecated in favor of `cursor`. Still accepted for back-compat but internally bounded: values above 2000 are rejected with a structured hint pointing to `cursor`. Supplying a non-zero `offset` together with `cursor` is rejected as a validation error; use one or the other. (default 0).
searchNoCanonical free-text query for lexical/semantic retrieval. Cannot be combined with published filters or non-default sorting.
sort_byNoSort field. Non-default values cannot be combined with `search`. Predefined values: `entity_id`, `canonical_name`, `observation_count`, `last_observation_at`, `submitted_at` (orders by `snapshot.created_at`). In addition, `snapshot.<field>` is supported for any snapshot field (e.g. `snapshot.period_end` for time-series entity types such as `usage_digest`). The field value is sorted lexicographically as a string, so ISO-8601 date strings must use a consistent format so that lexicographic order matches temporal order.
user_idNoOptional explicit user ID (normally inferred from auth context).
publishedNoFilter by snapshot.published. Cannot be combined with `search`.
sort_orderNoSort direction. `desc` cannot be combined with `search`.
entity_typeNoOptional single entity type filter (for example: post, task, contact). Combined as a union with `entity_types` when both are supplied.
entity_typesNoOptional multi-type filter. When non-empty, results are restricted to entities whose type is in this list (IN filter), OR-combined with `entity_type`. An empty array is treated as no filter.
search_queryNoCompatibility alias for `search`.
created_sinceNoISO 8601 timestamp. Return only entities whose created_at is greater than or equal to this value.
updated_sinceNoISO 8601 timestamp. Return only entities whose updated_at is greater than or equal to this value.
include_mergedNoWhether to include merged entities (default false).
published_afterNoInclusive lower bound for snapshot.published_date (ISO date/datetime). Cannot be combined with `search`.
published_beforeNoInclusive upper bound for snapshot.published_date (ISO date/datetime). Cannot be combined with `search`.
snapshot_filtersNoFilter entities by snapshot field values. Each key is a snake_case snapshot field name (e.g. `status`, `priority`); the value specifies operator and comparison value. Filters are applied server-side via `snapshot->>{field}` JSONB extraction, so only entities whose snapshot contains a matching value are returned. Example: `{ "status": { "op": "eq", "value": "active" } }` returns only entities with `snapshot.status === "active"`. Supported ops: `eq`, `in`, `gt`, `lt`, `gte`, `lte`, `contains`, `contains_word`. `contains` is a raw case-insensitive SUBSTRING match — `{ "title": { "op": "contains", "value": "CTO" } }` also matches "director" and "doctor", and `"COO"` matches "coordinator". Prefer `contains_word` when you mean a whole word/token: it matches only when the value appears as a complete token delimited by punctuation or whitespace, so `"CTO"` matches "VP, CTO" and "CTO & Co-founder" but not "director"; `"Care"` does not match "Careers". Punctuation inside the term is handled: `"O'Brien"`, `"R&D"`, and `"100%"` match their stored values (separators in the term are normalized the same way as the stored value). Case-insensitivity for `contains_word` is ASCII-only.
include_snapshotsNoWhen false, omit snapshot/provenance/raw_fragments payloads for lightweight responses.
exclude_bookkeepingNoWhen true, omit chat bookkeeping types (`conversation`, `conversation_message`, etc.) from results. Default false. Has no effect when `entity_type` already filters to a bookkeeping type.
similarity_thresholdNoSemantic distance threshold when `search` is used. Lower is stricter (typical 1.0-1.05).

TDQS

A5/5.0
Behavior5/5

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

No annotations provided, so description carries full burden. It discloses strict-mode combination rules, alias handling, cursor and offset limitations, snapshot_filters behavior including `contains` vs `contains_word` semantics, case-insensitivity, and performance implications of include_snapshots. This significantly exceeds standard behavioral disclosure.

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

Conciseness5/5

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

The description is long but densely informative with no filler. It is front-loaded with the primary use-case and then systematically covers constraints, filtering, and pagination. Every sentence provides actionable guidance for a high-complexity tool (21 params).

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

Completeness5/5

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

Given 21 parameters, nested snapshot_filters object, and no output schema/annotations, the description covers use cases, constraints, filter semantics, pagination strategy, and performance advice. It mentions response elements (next_cursor, snapshot payloads) and error behavior. It is unusually complete for such a complex tool.

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

Parameters5/5

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

Schema covers all 21 parameters (100%), but the description adds substantial meaning: explains why limit is capped at 500 with snapshots, clarifies cursor vs offset trade-offs, snapshots filter operators with examples, lexicographic sort behavior, and the compatibility aliases. This is well beyond the schema's property descriptions.

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

Purpose5/5

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

The description explicitly states 'Use this when you need filtered entity lists' and 'lexical/semantic retrieval via search', clearly specifying a list/query operation on entities. It distinguishes from siblings like retrieve_entity_snapshot (single entity) by focusing on filtered lists and search.

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

Usage Guidelines5/5

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

Opens with 'Use this when you need filtered entity lists' and provides explicit constraints: search cannot combine with non-default sorting or published filters; include_snapshots=false for lightweight responses; cursor vs offset for deep pagination. Gives guidance on when to use snapshot_filters and compatibility aliases, plus conditions when cursor is unsupported.

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

retrieve_entity_by_identifierA

Retrieve entity by identifier (name, email, etc.) across entity types or specific type. Falls back to semantic search when keyword match returns no results. A literal entity_id (ent_) short-circuits to a direct primary-key lookup; if no entity has that id, the response carries a hint pointing to retrieve_entity_snapshot.

ParametersJSON Schema
NameRequiredDescriptionDefault
byNoRestrict snapshot-field matching to a single field (e.g. 'email', 'domain', 'company'). When omitted, checks a default identity-bearing set (name, full_name, title, email, domain, company).
limitNoMax matching entities (default 100).
identifierYesIdentifier to search for (name, email, tax_id, etc.) - will be normalized
entity_typeNoOptional: Limit search to specific entity type (e.g., 'company', 'person')
observations_limitNoMax observations per entity when include_observations is true (default 20, max 200).
include_observationsNoWhen true, include recent observations per matched entity (ordered by observed_at desc).

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description discloses key behaviors: fallback to semantic search, short-circuit for entity_id, optional observations, and hints for missing ids. It does not cover authentication or rate limits but covers the main behavioral traits.

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

Conciseness5/5

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

The description is extremely concise, consisting of two sentences that front-load the purpose and then add critical behavioral details. Every sentence contributes value with no redundancy.

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

Completeness4/5

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

Given the moderate complexity (6 params, no output schema), the description covers the search algorithm, optional observations, and sibling tool hint. It lacks return value specifics but is largely complete for a retrieval tool.

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

Parameters3/5

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

Schema description coverage is 100%, so the baseline is 3. The description adds minimal parameter-specific context beyond the schema (e.g., normalization of identifier). It does not significantly enhance parameter understanding.

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

Purpose5/5

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

The description clearly states the verb (retrieve), resource (entity), and the method (by identifier). It distinguishes from sibling tools like retrieve_entity_snapshot by noting the short-circuit behavior for literal entity_id and the hint to that tool.

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

Usage Guidelines3/5

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

Usage is implied but not explicitly stated. The description explains the fallback and short-circuit behavior but does not provide direct guidance on when to use this tool versus alternatives like retrieve_entities or retrieve_entity_snapshot.

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

retrieve_entity_snapshot

Retrieve the current snapshot of an entity with provenance information. Supports historical snapshots via 'at' parameter.

ParametersJSON Schema
NameRequiredDescriptionDefault
atNoEvent-time cutoff (ISO 8601). Reconstructs the snapshot from observations whose `observed_at` ≤ this timestamp. Reflects what *happened* by time T, regardless of when the observation was ingested into Neotoma. Use `at_ingested` instead when you need "what did we actually know at time T" semantics.
formatNoResponse text format. `markdown` (default for MCP) returns canonical deterministic markdown for KV-cache stability. `json` returns the raw snapshot payload for programmatic callers.
entity_idNo
at_ingestedNoIngestion-time cutoff (ISO 8601). Reconstructs the snapshot from observations whose `created_at` (row-insertion time) ≤ this timestamp. Excludes backfilled or late-arriving observations that have a past `observed_at` but arrived after this cutoff, preventing look-ahead leaks. When both `at` and `at_ingested` are supplied, both bounds are applied (AND logic): an observation must satisfy `observed_at ≤ at` AND `created_at ≤ at_ingested`.
include_cleared_fieldsNoInclude only selected explicit-null fields with winning provenance; requires complete owned acquisition and an active schema.
retrieve_field_provenanceC

Retrieve the provenance chain for a specific field in an entity snapshot

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldNo
entity_idNo

TDQS

C2.7/5.0
Behavior2/5

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

With no annotations, the description fails to disclose behavioral traits such as read-only nature, authentication needs, or what 'provenance chain' implies; merely states the action.

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

Conciseness3/5

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

The description is concise but overly brief; it gets the point across but could benefit from additional detail without being verbose.

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

Completeness2/5

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

Given the lack of output schema and annotations, the description is incomplete; it does not explain what the provenance chain contains or the return format, leaving the agent underinformed.

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

Parameters1/5

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

Schema description coverage is 0% and the description does not explain the two parameters (entity_id, field) beyond their names, leaving ambiguity about valid values and usage.

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

Purpose5/5

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

The description clearly states the verb 'retrieve' and the specific resource 'provenance chain for a specific field in an entity snapshot', distinguishing it from siblings like retrieve_entity_snapshot.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus alternatives, nor any mention of exclusions or prerequisites.

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

retrieve_file_urlC

Retrieve a signed URL for accessing a file

ParametersJSON Schema
NameRequiredDescriptionDefault
file_pathYes
expires_inNo

TDQS

C2.8/5.0
Behavior2/5

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

With no annotations, the description must disclose behavioral traits. It fails to mention that the tool likely requires the file to already exist, whether it modifies anything, or if it returns a URL string. The term 'signed' implies authentication needs but is not explained.

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

Conciseness5/5

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

Single sentence conveying the core function with no unnecessary words. Highly efficient and front-loaded.

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

Completeness2/5

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

Given no output schema and no annotations, the description is too brief. It omits key details like return type, error scenarios, prerequisites (file existence), and any side effects. The agent cannot reliably use this tool without additional assumptions.

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

Parameters2/5

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

Input schema has 0% description coverage. The description does not explain the parameters' meanings beyond their names. For expires_in, units and default are missing; file_path format is not clarified. The description adds little semantic value.

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

Purpose4/5

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

The description clearly states the action (Retrieve) and resource (a signed URL for accessing a file), which distinguishes it from siblings like parse_file (reads content) or store (uploads). However, it does not explicitly clarify whether the URL is temporary or scoped to the current user.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus alternatives, nor any prerequisites or limitations. The description only states the function without contextual cues about scenarios (e.g., file must exist, requires authentication).

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

retrieve_graph_neighborhoodB

Retrieve complete graph neighborhood around a node (entity or source): related entities, relationships, sources, and events.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of relationships to return. Default 100, max 500.
offsetNoNumber of relationships to skip (for pagination). Default 0.
node_idYesNode ID (entity_id or source_id) to get neighborhood for
node_typeNoType of node ('entity' for entities, 'source' for sources)entity
include_eventsNoInclude timeline events in response
include_sourcesNoInclude related sources in response
include_observationsNoInclude observations (for entities only)
include_relationshipsNoInclude relationships in response

TDQS

B3.3/5.0
Behavior2/5

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

No annotations are provided. The description claims 'complete' but the schema includes limit/offset for pagination, contradicting completeness. It also omits important traits like that include_observations is entity-only and that results may be truncated. Not transparent about pagination or performance.

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

Conciseness4/5

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

The description is a single clear sentence, efficient and front-loaded. However, it could be structured better (e.g., bullet points for components) to improve readability, but it's not verbose.

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

Completeness2/5

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

The tool has 8 parameters and no output schema, yet the description is very brief. It does not explain the output structure, pagination details (limit/offset), or the distinction between entity and source nodes. For a complex graph retrieval, more detail is needed to be complete.

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

Parameters3/5

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

Schema coverage is 100%, so baseline is 3. The description adds no additional meaning beyond the schema; it only lists components covered by parameters like include_relationships, include_sources, etc. No extra context on parameter values or behavior.

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

Purpose5/5

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

The description clearly states the action ('retrieve complete graph neighborhood') and the resource ('around a node'), listing the included components (entities, relationships, sources, events). This distinguishes it from siblings like retrieve_entities or list_relationships that retrieve only specific types.

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

Usage Guidelines3/5

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

The description implies usage when a complete neighborhood is needed but does not provide explicit guidance on when to use this tool versus alternatives like list_relationships or retrieve_related_entities. No when-not-to-use or alternative tools are mentioned.

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

split_entityA

R5 inverse of merge_entities. Re-points a predicate-selected subset of an entity's observations onto a new or pre-existing entity to repair over-merges (typically the pre-v1.2 heuristic name_key:title collapse on session-scoped types). Schema-agnostic predicate — supply any of observed_at_gte, source_id_in, or observation_field_equals. Observation content is never modified; only entity_id FK is re-bound. Idempotent via (user_id, idempotency_key) — reuse with a different predicate returns ERR_IDEMPOTENCY_MISMATCH. Typed relationships remain bound to the source; rebuild them with create_relationship.

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNoFree-text rationale recorded on the audit row.
user_idNo
predicateYesR5: declarative predicate describing which observations of the source entity should be re-pointed onto the new entity. Every form reads a column every observation row carries so the predicate surface is schema-agnostic. At least one form MUST be supplied.
new_entityYes
idempotency_keyYesRequired per MUST #11. Reuse with a different predicate returns `ERR_IDEMPOTENCY_MISMATCH`; reuse with the same predicate returns the original split result (`replayed: true`).
source_entity_idYes

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations, the description fully discloses behavior: observations are never modified, only FK rebound; idempotency and error conditions (ERR_IDEMPOTENCY_MISMATCH); relationships are not affected. This is comprehensive for a mutation tool.

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

Conciseness4/5

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

The description is concise (3 sentences) and front-loaded with the core purpose. It efficiently covers key behavioral aspects without unnecessary detail. Slightly dense but well-structured.

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

Completeness4/5

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

Given the tool's complexity (6 params, nested objects, no output schema), the description provides a solid overview of purpose, behavior, and parameter usage. However, it could briefly mention the expected response format or success indicators.

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

Parameters4/5

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

The schema covers 50% of parameters with descriptions, but the description adds significant value by explaining the predicate forms and their use cases (e.g., 'move every observation from this session forward'). It also clarifies idempotency_key semantics beyond the schema.

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

Purpose5/5

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

The description clearly states the tool is the inverse of merge_entities, specifically repoints observations to repair over-merges. It provides a concrete use case (pre-v1.2 heuristic name_key:title collapse) and distinguishes it from its sibling, merge_entities.

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

Usage Guidelines5/5

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

Explicitly states when to use (repair over-merges) and when not to (typed relationships remain bound, use create_relationship instead). Also notes idempotency key reuse behavior, giving clear guidance on proper invocation.

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

store

Unified storing for structured, file-backed, or combined payloads in one request. Choose path by source: file- or resource-sourced (attachment/file to preserve) → use file_content+mime_type or file_path; conversation- or tool-sourced (chat or other MCP) → use entities. You may send both entities and file input in the same call. File bytes create a content-addressed sources row (SHA-256 dedup per user); the response includes source_id / content_hash for the unstructured leg. The server does not invent structured fields from opaque blobs without an explicit interpretation block or a separate interpretation flow. Agents should parse and extract entities first when they need structured data from a readable file, then send those entities alongside the raw file. IMPORTANT FOR STRUCTURED DATA: Include ALL fields from source data. Schema fields go to observations; non-schema fields go to raw_fragments for future schema expansion. Relationships must link entities you own; a refused relationship is reported in relationships_refused rather than failing the call.

ParametersJSON Schema
NameRequiredDescriptionDefault
commitNoWhen false, runs in plan/dry-run mode: resolves entities and returns planned actions ("would_create" / "would_match_existing") without persisting observations or source rows. Useful for previewing a structured store before committing.
strictNoWhen true, refuse silent merges: only match an existing entity when the entity's schema declares canonical_name_fields that the request matches, or when target_id is supplied. Prevents accidental coalescing into a pre-existing record.
user_idNo
entitiesNo
file_pathNoA path on the SERVER's filesystem, not yours. The file is read by the Neotoma instance, so this only works when your client runs on the same machine as the instance — the axis is co-located vs remote, not desktop vs web. Against a hosted or otherwise remote instance it cannot see your disk and is rejected with ERR_FILE_PATH_IS_SERVER_LOCAL. To send a file from a remote client: upload the bytes (POST /sources/upload, multipart/form-data) and pass the returned source_id, or inline small files with file_content (base64) + mime_type. MIME type is auto-detected from the content or extension when not provided.
mime_typeNoMIME type (e.g., 'application/pdf', 'text/csv') - required with file_content, optional with file_path (auto-detected from extension)
file_contentNoBase64-encoded file content. Use file_path for local files instead of base64 encoding.
relationshipsNoOptional. Create relationships between entities in this request. Use `source_index` or `target_index` for entities in this request, and `source_entity_id` or `target_entity_id` for existing entities. Index and id endpoints may be mixed in one relationship.
external_actorNoUpstream artifact author (e.g. GitHub user) stamped into observation provenance alongside AAuth agent attribution. Matches `ExternalActorInputSchema` in `action_schemas.ts`.
interpretationNoOptional interpretation provenance for source-derived structured extraction. Supplying this creates an interpretation row and links new observations to it. Omit for ordinary already-structured/chat-native facts, which keep observations.interpretation_id NULL.
source_peer_idNoOptional Neotoma peer id to stamp on observations for cross-instance sync loop prevention (Phase 5). Requires `observation_source: sync` in practice.
source_storageNoStorage mode for file ingestion. Default 'inline' copies bytes into the database (portable, durable). 'reference' stores only a path + metadata row without copying bytes — zero DB bloat, but host-local and depends on the file staying in place. Requires file_path (not file_content). Derivations (observations/entities) are still materialized at ingest. Use 'reference' for large local files you control; use 'inline' for anything that must be shared or portable.
idempotency_keyNoRequired for structured path, optional for unstructured-only path.
source_priorityNoTrust/priority of this observation's source. Only affects snapshot resolution for fields whose merge strategy is highest_priority (set via register_schema reducer_config); under the default last_write strategy it is stored but ignored.
original_filenameNoOriginal filename or source label (optional). For unstructured: auto-detected from file_path if not provided. For structured (entities): omit when data is agent-provided (no file origin); the source will have no filename. Pass only when mirroring a real file name or when a display label is desired.
observation_sourceNoClassifies the *kind* of write being performed, orthogonal to `source_priority`. See `Observation.observation_source` for the full semantic contract. Defaults to `llm_summary` when unspecified. Applies to every observation created by this request.
file_idempotency_keyNoOptional idempotency key for file path when sending structured + unstructured in one call.
expected_entity_absentNoWhen true, atomically create exactly one structured entity only if its complete schema-declared physical identity is absent. Requires commit=true and a nonempty idempotency_key; file, relationship, interpretation, intake, target and sync combinations are refused. Omitted or false preserves ordinary upsert behavior. Exact retries return the original immutable operation receipt without new effects.
submit_entityA

Generic submission for entity types with an active submission_config. Creates the primary row plus optional conversation thread and guest_access_token; use submit_issue for GitHub-backed issues.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsYesPayload merged into the primary entity row (schema-required fields must be present).
entity_typeYesTarget entity type (must match an active submission_config target_entity_type).
initial_messageNoWhen conversation threading is enabled, overrides the first message body (defaults to fields.body or fields.content when omitted).

TDQS

A3.7/5.0
Behavior2/5

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

No annotations are provided, so the description must disclose all behavioral traits. It mentions creating a row and optional thread/token, but does not discuss side effects, idempotency, authorization needs, or what happens to existing submissions.

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

Conciseness5/5

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

The description is a single, well-structured sentence that front-loads the purpose, then details optional outputs, then provides an alternative—all in 20 words.

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

Completeness3/5

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

No output schema exists, so the description should hint at return values, but it does not. It covers the core function but omits behavioral context and output characteristics.

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

Parameters3/5

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

Schema coverage is 100%, so baseline is 3. The description adds context that fields is the payload and initial_message relates to conversation, but does not significantly enhance understanding beyond the schema descriptions.

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

Purpose5/5

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

The description clearly states it is a generic submission for entity types with an active submission_config, creates the primary row plus optional conversation thread and guest_access_token, and explicitly distinguishes from submit_issue for GitHub-backed issues.

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

Usage Guidelines4/5

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

It names the alternative submit_issue for GitHub-backed issues, providing clear differentiation. However, it does not elaborate on prerequisites or when not to use this tool beyond that.

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

submit_issueA

Submit an issue to the configured operator Neotoma instance; returns guest_access_token when accepted so callers can use token-scoped get_issue_status / add_issue_message read-back. No prior identity is required: a remote caller with no Bearer token, no AAuth signature and no guest token may submit whenever the operator instance's issue guest access policy permits guest writes — the token is an OUTPUT of the submit, not a precondition for it, so first contact needs no credential. Anonymity covers submission only; use the returned guest_access_token for add_issue_message and get_issue_status. Callers must provide at least one of reporter_git_sha or reporter_app_version. Deprecated alias: visibility 'advisory' is accepted as 'private' for one minor release and returns _deprecation: "visibility 'advisory' is deprecated; use 'private' instead."

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyYesIssue body in markdown.
titleYesIssue title.
labelsNoLabels to apply (e.g. bug, doc_gap, enhancement).
visibilityNoUse 'private' for PII-sensitive issues (Neotoma only, no GitHub mirror). Default: 'public'.
target_repoNoOptional GitHub mirror destination override (`owner/repo`). Use when filing issues about a repo other than the one Neotoma is globally configured for (e.g. `markmhendrickson/ateles`). Overrides only the GitHub mirror — Neotoma authoring home is unchanged.
reporter_channelNoOptional reporter channel (e.g. ci, local).
reporter_git_refNoOptional reporter git ref / branch name.
reporter_git_shaNoRequired (this OR reporter_app_version). Reporter git SHA (`git rev-parse HEAD`).
reporter_ci_run_idNoOptional CI or workflow run id.
conversation_turn_idNoEntity ID of the conversation turn (conversation_message entity) where this issue was observed. When provided, a REFERS_TO relationship is created from the filed issue to the conversation turn so the origin is traceable.
reporter_app_versionNoRequired (this OR reporter_git_sha). Reporter app / CLI version (semver).
reporter_patch_source_idNoOptional source id for reporter patch artifact.

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It is exceptionally transparent: it explains the authentication model (no Bearer token, AAuth signature, or guest token needed), that the token is an OUTPUT rather than a precondition, that anonymity covers only the submission, and the deprecated visibility alias behavior with exact response text. This gives the agent essential context about side effects and security aspects.

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

Conciseness4/5

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

The description is long but every sentence carries relevant information: purpose, token return, auth model, follow-up usage, required parameters, and deprecation warning. It is front-loaded with the main action. It could be better structured with bullet points for readability, but it is not verbose or wasteful.

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

Completeness4/5

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

Given 12 parameters, no output schema, and no annotations, the description compensates well by explaining the return token, auth preconditions, required params, and deprecation behavior. It does not elaborate on all potential side effects (e.g., GitHub mirror behavior, error cases), but covers the most critical contextual information an agent needs to invoke the tool correctly.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by reinforcing the conditional requirement for reporter_git_sha/reporter_app_version (already in schema) and, more importantly, by documenting the deprecated 'advisory' enum value for visibility, which is not present in the schema. This extra semantic detail about an accepted value improves parameter understanding.

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

Purpose5/5

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

The description clearly states the action ('Submit an issue') and target ('configured operator Neotoma instance'), with a specific verb and resource. It distinguishes this from sibling tools by naming the follow-up token-scoped read-back tools (get_issue_status / add_issue_message), making it clear this is the initial submission action.

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

Usage Guidelines4/5

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

The description provides explicit guidance: it states when this tool is appropriate (submitting without prior identity), what must be provided (at least one of reporter_git_sha or reporter_app_version), and how to proceed after acceptance (use returned token for get_issue_status/add_issue_message). It also notes the deprecated visibility alias, giving clear exclusions. However, it does not explicitly mention alternative tools for cases where a guest token already exists.

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

subscribeA

Create a substrate event subscription (webhook with HMAC delivery, or SSE via GET /events/stream). Requires at least one filter among entity_types, entity_ids, or event_types. Optional sync_peer_id skips webhook delivery when the substrate event carries the same source_peer_id (cross-instance loop prevention).

ParametersJSON Schema
NameRequiredDescriptionDefault
entity_idsNo
event_typesNo
webhook_urlNo
entity_typesNo
max_failuresNo
sync_peer_idNoWhen set, webhook deliveries skip substrate events whose `source_peer_id` equals this value (prevents notifying a peer about changes that originated from that peer).
webhook_secretNo
delivery_methodYes

TDQS

A3.9/5.0
Behavior3/5

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

No annotations provided, so description carries full burden. It discloses delivery methods, filter requirements, and sync_peer_id functionality. Missing details on authentication, rate limits, error conditions, or what happens on failures.

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

Conciseness5/5

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

Two sentences, front-loaded with purpose. Every sentence adds value without redundancy. Efficient and well-structured.

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

Completeness3/5

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

No output schema, so description should hint at return value (e.g., subscription ID). It does not. Lacks authentication info but covers filters and delivery methods adequately. Moderate complexity; missing return info reduces completeness.

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

Parameters3/5

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

Schema has 8 parameters with only 13% description coverage (only sync_peer_id described). The tool description adds meaning: explains filter requirement and loop prevention for sync_peer_id, but does not elaborate on webhook_url, webhook_secret, max_failures, or delivery_method semantics beyond listing.

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

Purpose5/5

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

The description clearly states the action 'Create' and the resource 'substrate event subscription' with specific delivery methods (webhook with HMAC, SSE). It distinguishes from siblings like 'unsubscribe' and 'list_subscriptions' by detailing the creation process.

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

Usage Guidelines4/5

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

Provides explicit prerequisites: at least one filter among entity_types, entity_ids, or event_types. Also explains the use of sync_peer_id for loop prevention. However, it does not mention when not to use this tool or compare with alternatives like 'get_subscription_status'.

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

sync_entity_submissionsA

Sync external mirrors for submissions (issue → GitHub sync; other types may no-op until providers are added).

ParametersJSON Schema
NameRequiredDescriptionDefault
entity_typeNoDefaults to issue when omitted.

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It reveals that other entity types may result in a no-op, which is helpful. However, it does not disclose side effects (e.g., overwriting, destructive actions) or permissions needed, leaving moderate gaps.

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

Conciseness4/5

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

The description is a single, efficient sentence that packs key information: purpose, scope (issue to GitHub), and caveat (no-op for others). It is front-loaded and concise, with no wasted words.

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

Completeness3/5

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

Given the simple input (one optional param) and no output schema, the description is fairly complete. It explains the primary use case and limitations, but leaves open questions about what 'sync' entails (direction, idempotence, success/failure behavior) and what 'external mirrors' refers to.

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

Parameters4/5

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

The schema description covers the default behavior ('Defaults to issue when omitted'), and the tool description adds meaning by explaining that 'issue' triggers GitHub sync while other types are no-ops. This goes beyond the schema, providing valuable context for parameter values.

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

Purpose4/5

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

The description clearly states the tool syncs external mirrors for submissions and gives a specific example (issue to GitHub sync). It uses a specific verb and resource, but does not explicitly distinguish itself from the sibling tool 'sync_issues', leaving slight ambiguity.

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

Usage Guidelines3/5

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

The description implies usage for syncing issues to GitHub and notes that other types may no-op until providers are added, providing some context. However, it lacks explicit when-to-use or when-not-to-use guidance and does not mention alternatives like 'sync_issues'.

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

sync_issues

Sync local Neotoma with a GitHub repo's issues. Pull leg: GitHub issues and their messages are pulled into local entities. Push leg: local public issues with no github_number are sanitized (PII stripped) and created on GitHub, then updated locally with the returned number/url. Target repo defaults to the server-configured repo (NEOTOMA_ISSUES_REPO); pass repo (owner/name) to mirror a different repo for one call without changing server config. The push leg is ON by default only for the configured default repo and OFF for any other repo unless push: true is passed. Pass commit: false for a dry run that reports what would be created, updated and pushed and writes nothing. Requires a GitHub token: NEOTOMA_ISSUES_GITHUB_TOKEN in the server environment (or gh auth login on the server host). Supports filtering by state, labels, and since date.

ParametersJSON Schema
NameRequiredDescriptionDefault
pushNoRun the push leg (local public → GitHub). Default: true when `repo` is omitted or equals the configured default repo; false for any other `repo`. Pass true to opt in for another repo.
repoNoGitHub repository to mirror, `owner/name`. Defaults to the server-configured repo (`NEOTOMA_ISSUES_REPO` / `issues.repo`). Must be the configured repo or be listed in the server's `NEOTOMA_ISSUES_ALLOWED_REPOS` (or `issues.allowed_repos`). A malformed or non-permitted value is rejected before any GitHub request or write.
sinceNoOnly sync issues updated after this ISO date.
stateNoFilter by issue state. Default: 'all'.
commitNoWhen false, dry run: report what would be created, updated and pushed (`plan`) and write nothing locally or on GitHub. Default: true.
labelsNoFilter by labels.
sync_peerC

Bounded outbound peer sync: POST signed /sync/webhook for observations (requires NEOTOMA_PUBLIC_BASE_URL, NEOTOMA_LOCAL_PEER_ID, peer sync_target_user_id). Optional limit.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax observations to consider this run (default 200)
peer_idYes

TDQS

C2.4/5.0
Behavior2/5

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

No annotations are provided, so the description carries full burden. It mentions 'POST' implying mutation, but does not disclose whether the operation is destructive, idempotent, or what side effects occur. The behavior beyond sending a request is opaque.

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

Conciseness4/5

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

The description is a single sentence, efficient and front-loaded with 'Bounded outbound peer sync'. However, it packs technical details (POST path, env vars) without punctuation or structure, making it somewhat cryptic.

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

Completeness2/5

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

Given the tool has 2 parameters and no output schema, the description omits critical details: success/failure behavior, response format, how 'limit' affects execution, and what 'observations' are synced. It is not sufficiently complete for an agent to use without additional context.

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

Parameters2/5

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

The schema has 50% coverage (peer_id lacks description). The description mentions 'peer sync_target_user_id' but the schema only has peer_id, causing confusion. It adds little meaning beyond the schema: it says limit is optional, but the schema already has a minimum/maximum/description. The description fails to clarify the role of peer_id.

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

Purpose3/5

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

The description states it performs 'bounded outbound peer sync' via POST to a webhook for observations, which gives a specific verb and resource. However, it doesn't clearly distinguish from sibling sync tools like 'sync_entity_submissions' or 'sync_issues', and the jargon may be unclear to an agent.

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

Usage Guidelines2/5

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

The description lists prerequisites (environment variables, peer sync_target_user_id) and mentions an optional limit, but provides no guidance on when to use this tool versus alternatives. There is no explicit when/when-not or contrast with sibling tools.

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

unsubscribeC

Deactivate a subscription by subscription_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
subscription_idYes

TDQS

C2.9/5.0
Behavior2/5

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

No annotations exist, so the description must disclose behavior. 'Deactivate' implies a state change but lacks details on effects, irreversibility, or prerequisites.

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

Conciseness3/5

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

The description is a single short sentence, which is concise but lacks necessary detail for an effective description.

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

Completeness2/5

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

With no output schema and minimal description, the tool lacks completeness. Return values, side effects, and usage notes are absent.

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

Parameters2/5

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

Schema coverage is 0%, and the description only repeats the parameter name without adding format, source, or validation details beyond the schema.

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

Purpose5/5

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

The description clearly states the verb 'deactivate' and the resource 'subscription', distinguishing it from sibling tools like 'subscribe' and 'list_subscriptions'.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus alternatives. Sibling 'subscribe' exists but no comparison or context provided.

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

update_schema_incremental

Incrementally update a schema by adding fields (fields_to_add — minor version bump), removing fields (fields_to_remove — major version bump; observation data preserved, snapshot-excluded until re-added), or changing the identity rule (canonical_name_fields — major version bump). Creates a new schema version and activates it immediately, so all new data stored after this call uses the updated schema. Optionally migrates existing raw_fragments to observations for historical data backfill.

canonical_name_fields re-keys how the type derives canonical_name / identity. Rules are ordered precedence with fallback — the first rule whose fields are all present wins, e.g. [{composite:["linkedin_url"]},"email","name"] keys on linkedin_url, else email, else name. Reach for it when same-name-different-entity collisions appear (e.g. a bulk import collapses distinct people who share a name because identity resolves on name alone). The existing reducer_config is preserved automatically, so this is the safe way to re-key without a full register_schema re-supply. Applies to NEW writes only — it does not retroactively re-key existing entities, so it will not by itself merge existing duplicates. Omit to keep the current rule; pass [] to clear it (succeeds only if the schema also declares identity_opt_out). The response echoes the resolved canonical_name_fields; call describe_entity_type first to see the current rule before replacing it.

Scope: omit user_specific to write to whichever scope your schema resolves to (your user-scoped override if you have one, else global); the response's scope (and user_id when scope is user) reports what was written. Pass user_specific: true or false only to override that. migrated_existing is true only when migrate_existing actually promoted fragments; migration_result.skipped says why any did not. If entity_type is rejected by a naming guard whose message names force: true as the remedy, retry with force: true.

On ERR_SCHEMA_SCOPE_MISMATCH (only after an explicit user_specific: false, when the type has no global registry row and no code-defined baseline) an active schema exists in a different scope than the call checked (details.guard_scope vs details.found_scope). Retry without user_specific, or with user_specific matching details.found_scope. Never call register_schema for that code — a second active row for the same entity_type risks dual-active corruption (#2374/#2378).

ParametersJSON Schema
NameRequiredDescriptionDefault
forceNoBypass the entity-type naming guards (forbidden test-artifact patterns and the plural-name guard) for this call only. Required when entity_type is rejected with a message naming "force: true" as the remedy — e.g. a name the plural guard misclassifies (like "hypothesis"). Does not affect any other validation.
user_idNoUser ID for user-specific schema (required if user_specific=true)
activateNoActivate schema immediately so it applies to new data (default: true). If false, schema is registered but not active.
entity_typeYesEntity type to update
fields_to_addNoFields to add to schema
user_specificNoExplicit scope override. Omit this to write to whichever scope your own read of the schema resolved (global row, or your user-scoped override if you have one) — the common case, and the safe default. Pass true to create or extend a user-specific override for you even if you currently resolve the global row. Pass false to extend the global row even if you have a user-scoped override: the new global version is built from the current global schema, never from your override; if the type has no global registry row and no code-defined baseline (but has your user-scoped schema), the call returns ERR_SCHEMA_SCOPE_MISMATCH. The response's "scope" field reports which scope was actually written.
schema_versionNoNew schema version (auto-increments if not provided)
fields_to_removeNoField names to remove from schema (triggers major version bump). Observation data is preserved; fields can be restored by re-adding them later.
migrate_existingNoMigrate existing raw_fragments to observations for historical data backfill (default: false). Note: New data automatically uses updated schema after activation, migration is only for old data. The response's "migrated_existing" reflects whether anything actually promoted, and "migration_result.skipped" names any fragment groups that did not (e.g. ambiguous ownership, already promoted by a prior call) — a request with migrate_existing: true can legitimately promote zero fragments.
canonical_name_fieldsNoReplace the entity type's identity rule (how canonical_name / entity identity is derived). Triggers a major version bump. Each item is a single field name (string) or an all-required composite ({composite:[...]}). Rules are ORDERED PRECEDENCE WITH FALLBACK: the resolver uses the first rule whose fields are all present, not an unordered set. Example: [{"composite":["linkedin_url"]},"email","name"] keys on linkedin_url when present, else email, else name. Omit to keep the current rule. Passing [] clears the rule, but only succeeds when the schema also declares identity_opt_out; otherwise it is rejected (a schema must declare canonical_name_fields OR identity_opt_out). The existing reducer_config is preserved automatically — this is the safe way to re-key a type without reconstructing it. Applies to NEW writes only; it does NOT retroactively re-key existing entities (they keep their stored canonical_name until re-derived), so re-keying will not by itself merge existing duplicates. To see the current rule before replacing it, call describe_entity_type first; the update response also echoes the resolved canonical_name_fields.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 17 tool updatesv0.25.0
    • Changedcorrect2 fields changed
      • addedInput schema / properties / expected_version
        Added value: +{
        +  "description": "Optional opaque entity_version from a current entity read. A stale token returns ERR_FIELD_VERSION_CONFLICT and writes nothing.",
        +  "type": "string"
        +}
      • addedInput schema / properties / overwrite
        Added value: +{
        +  "description": "Apply even when expected_version is stale. Ignored when it is omitted.",
        +  "type": "boolean"
        +}
    • Addedcorrect_transaction
    • Changedcreate_interpretation1 field changed
      • changedInput schema / properties / relationships / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "metadata": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "relationship_type": {
        -        "enum": [
        -          "PART_OF",
        -          "CORRECTS",
        -          "REFERS_TO",
        -          "SETTLES",
        -          "DUPLICATE_OF",
        -          "DEPENDS_ON",
        -          "SUPERSEDES",
        -          "EMBEDS",
        -          "works_at",
        -          "owns",
        -          "manages",
        -          "part_of",
        -          "related_to",
        -          "depends_on",
        -          "references",
        -          "transacted_with",
        -          "member_of",
        -          "reports_to",
        -          "located_at",
        -          "created_by",
        -          "funded_by",
        -          "acquired_by",
        -          "subsidiary_of",
        -          "partner_of",
        -          "competitor_of",
        -          "supplies_to",
        -          "contracted_with",
        -          "invested_in"
        -        ],
        -        "type": "string"
        -      },
        -      "source_index": {
        -        "description": "Index into the entities array for the source entity.",
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "target_index": {
        -        "description": "Index into the entities array for the target entity.",
        -        "minimum": 0,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "relationship_type",
        -      "source_index",
        -      "target_index"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "metadata": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "relationship_type": {
        -        "enum": [
        -          "PART_OF",
        -          "CORRECTS",
        -          "REFERS_TO",
        -          "SETTLES",
        -          "DUPLICATE_OF",
        -          "DEPENDS_ON",
        -          "SUPERSEDES",
        -          "EMBEDS",
        -          "works_at",
        -          "owns",
        -          "manages",
        -          "part_of",
        -          "related_to",
        -          "depends_on",
        -          "references",
        -          "transacted_with",
        -          "member_of",
        -          "reports_to",
        -          "located_at",
        -          "created_by",
        -          "funded_by",
        -          "acquired_by",
        -          "subsidiary_of",
        -          "partner_of",
        -          "competitor_of",
        -          "supplies_to",
        -          "contracted_with",
        -          "invested_in"
        -        ],
        -        "type": "string"
        -      },
        -      "source_index": {
        -        "description": "Index into the entities array for the source entity.",
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "target_entity_id": {
        -        "description": "Existing target entity ID.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "relationship_type",
        -      "source_index",
        -      "target_entity_id"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "metadata": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "relationship_type": {
        -        "enum": [
        -          "PART_OF",
        -          "CORRECTS",
        -          "REFERS_TO",
        -          "SETTLES",
        -          "DUPLICATE_OF",
        -          "DEPENDS_ON",
        -          "SUPERSEDES",
        -          "EMBEDS",
        -          "works_at",
        -          "owns",
        -          "manages",
        -          "part_of",
        -          "related_to",
        -          "depends_on",
        -          "references",
        -          "transacted_with",
        -          "member_of",
        -          "reports_to",
        -          "located_at",
        -          "created_by",
        -          "funded_by",
        -          "acquired_by",
        -          "subsidiary_of",
        -          "partner_of",
        -          "competitor_of",
        -          "supplies_to",
        -          "contracted_with",
        -          "invested_in"
        -        ],
        -        "type": "string"
        -      },
        -      "source_entity_id": {
        -        "description": "Existing source entity ID.",
        -        "type": "string"
        -      },
        -      "target_index": {
        -        "description": "Index into the entities array for the target entity.",
        -        "minimum": 0,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "relationship_type",
        -      "source_entity_id",
        -      "target_index"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "metadata": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "relationship_type": {
        -        "enum": [
        -          "PART_OF",
        -          "CORRECTS",
        -          "REFERS_TO",
        -          "SETTLES",
        -          "DUPLICATE_OF",
        -          "DEPENDS_ON",
        -          "SUPERSEDES",
        -          "EMBEDS",
        -          "works_at",
        -          "owns",
        -          "manages",
        -          "part_of",
        -          "related_to",
        -          "depends_on",
        -          "references",
        -          "transacted_with",
        -          "member_of",
        -          "reports_to",
        -          "located_at",
        -          "created_by",
        -          "funded_by",
        -          "acquired_by",
        -          "subsidiary_of",
        -          "partner_of",
        -          "competitor_of",
        -          "supplies_to",
        -          "contracted_with",
        -          "invested_in"
        -        ],
        -        "type": "string"
        -      },
        -      "source_entity_id": {
        -        "description": "Existing source entity ID.",
        -        "type": "string"
        -      },
        -      "target_entity_id": {
        -        "description": "Existing target entity ID.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "relationship_type",
        -      "source_entity_id",
        -      "target_entity_id"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "metadata": {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      "relationship_type": {
        +        "description": "Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).",
        +        "type": "string"
        +      },
        +      "source_index": {
        +        "description": "Index into the entities array for the source entity.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "target_index": {
        +        "description": "Index into the entities array for the target entity.",
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "relationship_type",
        +      "source_index",
        +      "target_index"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "metadata": {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      "relationship_type": {
        +        "description": "Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).",
        +        "type": "string"
        +      },
        +      "source_index": {
        +        "description": "Index into the entities array for the source entity.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "target_entity_id": {
        +        "description": "Existing target entity ID.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "relationship_type",
        +      "source_index",
        +      "target_entity_id"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "metadata": {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      "relationship_type": {
        +        "description": "Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).",
        +        "type": "string"
        +      },
        +      "source_entity_id": {
        +        "description": "Existing source entity ID.",
        +        "type": "string"
        +      },
        +      "target_index": {
        +        "description": "Index into the entities array for the target entity.",
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "relationship_type",
        +      "source_entity_id",
        +      "target_index"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "metadata": {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      "relationship_type": {
        +        "description": "Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).",
        +        "type": "string"
        +      },
        +      "source_entity_id": {
        +        "description": "Existing source entity ID.",
        +        "type": "string"
        +      },
        +      "target_entity_id": {
        +        "description": "Existing target entity ID.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "relationship_type",
        +      "source_entity_id",
        +      "target_entity_id"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedcreate_relationship2 fields changed
      • changedInput schema / properties / relationship_type / description
        Previous value: -"Typed relationship category. Canonical structural types are\n`PART_OF`, `CORRECTS`, `REFERS_TO`, `SETTLES`,\n`DUPLICATE_OF`, `DEPENDS_ON`, `SUPERSEDES`, `EMBEDS`. Domain\ntypes (e.g. `works_at`, `owns`, `manages`) are also accepted.\n"New value: +"Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use)."
      • removedInput schema / properties / relationship_type / enum
        Removed value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS",
        -  "works_at",
        -  "owns",
        -  "manages",
        -  "part_of",
        -  "related_to",
        -  "depends_on",
        -  "references",
        -  "transacted_with",
        -  "member_of",
        -  "reports_to",
        -  "located_at",
        -  "created_by",
        -  "funded_by",
        -  "acquired_by",
        -  "subsidiary_of",
        -  "partner_of",
        -  "competitor_of",
        -  "supplies_to",
        -  "contracted_with",
        -  "invested_in"
        -]
    • Changedcreate_relationships2 fields changed
      • addedInput schema / properties / relationships / items / properties / relationship_type / description
        Added value: +"Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use)."
      • removedInput schema / properties / relationships / items / properties / relationship_type / enum
        Removed value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS",
        -  "works_at",
        -  "owns",
        -  "manages",
        -  "part_of",
        -  "related_to",
        -  "depends_on",
        -  "references",
        -  "transacted_with",
        -  "member_of",
        -  "reports_to",
        -  "located_at",
        -  "created_by",
        -  "funded_by",
        -  "acquired_by",
        -  "subsidiary_of",
        -  "partner_of",
        -  "competitor_of",
        -  "supplies_to",
        -  "contracted_with",
        -  "invested_in"
        -]
    • Changeddelete_relationship2 fields changed
      • changedInput schema / properties / relationship_type / description
        Previous value: -"Exact relationship type of the existing edge. Accepts the same set create_relationship writes: structural types (PART_OF, REFERS_TO, EMBEDS) and domain types (works_at, related_to, owns)."New value: +"Exact relationship type of the existing edge — the same vocabulary create_relationship writes. Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it."
      • removedInput schema / properties / relationship_type / enum
        Removed value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS",
        -  "works_at",
        -  "owns",
        -  "manages",
        -  "part_of",
        -  "related_to",
        -  "depends_on",
        -  "references",
        -  "transacted_with",
        -  "member_of",
        -  "reports_to",
        -  "located_at",
        -  "created_by",
        -  "funded_by",
        -  "acquired_by",
        -  "subsidiary_of",
        -  "partner_of",
        -  "competitor_of",
        -  "supplies_to",
        -  "contracted_with",
        -  "invested_in"
        -]
    • Changedget_relationship_snapshot2 fields changed
      • changedInput schema / properties / relationship_type / description
        Previous value: -"Type of relationship"New value: +"Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it."
      • removedInput schema / properties / relationship_type / enum
        Removed value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS",
        -  "works_at",
        -  "owns",
        -  "manages",
        -  "part_of",
        -  "related_to",
        -  "depends_on",
        -  "references",
        -  "transacted_with",
        -  "member_of",
        -  "reports_to",
        -  "located_at",
        -  "created_by",
        -  "funded_by",
        -  "acquired_by",
        -  "subsidiary_of",
        -  "partner_of",
        -  "competitor_of",
        -  "supplies_to",
        -  "contracted_with",
        -  "invested_in"
        -]
    • Addedlist_relationship_types
    • Changedlist_relationships2 fields changed
      • changedInput schema / properties / relationship_type / description
        Previous value: -"Optional relationship_type filter. Closed enum matching the handler's\naccepted values; spec-driven clients passing any other value will be\nrejected at runtime with a Zod validation error.\n"New value: +"Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use)."
      • removedInput schema / properties / relationship_type / enum
        Removed value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS",
        -  "works_at",
        -  "owns",
        -  "manages",
        -  "part_of",
        -  "related_to",
        -  "depends_on",
        -  "references",
        -  "transacted_with",
        -  "member_of",
        -  "reports_to",
        -  "located_at",
        -  "created_by",
        -  "funded_by",
        -  "acquired_by",
        -  "subsidiary_of",
        -  "partner_of",
        -  "competitor_of",
        -  "supplies_to",
        -  "contracted_with",
        -  "invested_in"
        -]
    • Addedpatch_array_item
    • Addedregister_relationship_type
    • Changedregister_schema1 field changed
      • addedInput schema / properties / force
        Added value: +{
        +  "default": false,
        +  "description": "Bypass the entity-type naming guards (forbidden test-artifact patterns and the plural-name guard) for this call only. Required when entity_type is rejected with a message naming \"force: true\" as the remedy — e.g. a name the plural guard misclassifies (like \"hypothesis\"). Does not affect any other validation.",
        +  "type": "boolean"
        +}
    • Changedrestore_relationship2 fields changed
      • changedInput schema / properties / relationship_type / description
        Previous value: -"Exact relationship type of the existing edge. Accepts the same set create_relationship writes: structural types (PART_OF, REFERS_TO, EMBEDS) and domain types (works_at, related_to, owns)."New value: +"Exact relationship type of the existing edge — the same vocabulary create_relationship writes. Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it."
      • removedInput schema / properties / relationship_type / enum
        Removed value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS",
        -  "works_at",
        -  "owns",
        -  "manages",
        -  "part_of",
        -  "related_to",
        -  "depends_on",
        -  "references",
        -  "transacted_with",
        -  "member_of",
        -  "reports_to",
        -  "located_at",
        -  "created_by",
        -  "funded_by",
        -  "acquired_by",
        -  "subsidiary_of",
        -  "partner_of",
        -  "competitor_of",
        -  "supplies_to",
        -  "contracted_with",
        -  "invested_in"
        -]
    • Changedretrieve_entity_snapshot1 field changed
      • addedInput schema / properties / include_cleared_fields
        Added value: +{
        +  "default": false,
        +  "description": "Include only selected explicit-null fields with winning provenance; requires complete owned acquisition and an active schema.",
        +  "type": "boolean"
        +}
    • Changedstore4 fields changed
      • addedInput schema / properties / expected_entity_absent
        Added value: +{
        +  "description": "When true, atomically create exactly one structured entity only if\nits complete schema-declared physical identity is absent. Requires\ncommit=true and a nonempty idempotency_key; file, relationship,\ninterpretation, intake, target and sync combinations are refused.\nOmitted or false preserves ordinary upsert behavior. Exact retries\nreturn the original immutable operation receipt without new effects.\n",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / external_actor / properties / delivery_id / description
        Added value: +"Not carried over from a request body; set only by the signed\nGitHub webhook route.\n"
      • addedInput schema / properties / external_actor / properties / verified_via / description
        Added value: +"Accepted for compatibility, but a request body can only assert an\nexternal actor: the stored value is always `claim`. The stronger\ntiers are assigned by server-side verification paths (the signed\nGitHub webhook route, AAuth token claims, grant linkage).\n"
      • changedInput schema / properties / relationships / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "metadata": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "relationship_type": {
        -        "enum": [
        -          "PART_OF",
        -          "CORRECTS",
        -          "REFERS_TO",
        -          "SETTLES",
        -          "DUPLICATE_OF",
        -          "DEPENDS_ON",
        -          "SUPERSEDES",
        -          "EMBEDS",
        -          "works_at",
        -          "owns",
        -          "manages",
        -          "part_of",
        -          "related_to",
        -          "depends_on",
        -          "references",
        -          "transacted_with",
        -          "member_of",
        -          "reports_to",
        -          "located_at",
        -          "created_by",
        -          "funded_by",
        -          "acquired_by",
        -          "subsidiary_of",
        -          "partner_of",
        -          "competitor_of",
        -          "supplies_to",
        -          "contracted_with",
        -          "invested_in"
        -        ],
        -        "type": "string"
        -      },
        -      "source_index": {
        -        "description": "Index into the entities array for the source entity.",
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "target_index": {
        -        "description": "Index into the entities array for the target entity.",
        -        "minimum": 0,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "relationship_type",
        -      "source_index",
        -      "target_index"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "metadata": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "relationship_type": {
        -        "enum": [
        -          "PART_OF",
        -          "CORRECTS",
        -          "REFERS_TO",
        -          "SETTLES",
        -          "DUPLICATE_OF",
        -          "DEPENDS_ON",
        -          "SUPERSEDES",
        -          "EMBEDS",
        -          "works_at",
        -          "owns",
        -          "manages",
        -          "part_of",
        -          "related_to",
        -          "depends_on",
        -          "references",
        -          "transacted_with",
        -          "member_of",
        -          "reports_to",
        -          "located_at",
        -          "created_by",
        -          "funded_by",
        -          "acquired_by",
        -          "subsidiary_of",
        -          "partner_of",
        -          "competitor_of",
        -          "supplies_to",
        -          "contracted_with",
        -          "invested_in"
        -        ],
        -        "type": "string"
        -      },
        -      "source_index": {
        -        "description": "Index into the entities array for the source entity.",
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "target_entity_id": {
        -        "description": "Existing target entity ID.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "relationship_type",
        -      "source_index",
        -      "target_entity_id"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "metadata": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "relationship_type": {
        -        "enum": [
        -          "PART_OF",
        -          "CORRECTS",
        -          "REFERS_TO",
        -          "SETTLES",
        -          "DUPLICATE_OF",
        -          "DEPENDS_ON",
        -          "SUPERSEDES",
        -          "EMBEDS",
        -          "works_at",
        -          "owns",
        -          "manages",
        -          "part_of",
        -          "related_to",
        -          "depends_on",
        -          "references",
        -          "transacted_with",
        -          "member_of",
        -          "reports_to",
        -          "located_at",
        -          "created_by",
        -          "funded_by",
        -          "acquired_by",
        -          "subsidiary_of",
        -          "partner_of",
        -          "competitor_of",
        -          "supplies_to",
        -          "contracted_with",
        -          "invested_in"
        -        ],
        -        "type": "string"
        -      },
        -      "source_entity_id": {
        -        "description": "Existing source entity ID.",
        -        "type": "string"
        -      },
        -      "target_index": {
        -        "description": "Index into the entities array for the target entity.",
        -        "minimum": 0,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "relationship_type",
        -      "source_entity_id",
        -      "target_index"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "metadata": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "relationship_type": {
        -        "enum": [
        -          "PART_OF",
        -          "CORRECTS",
        -          "REFERS_TO",
        -          "SETTLES",
        -          "DUPLICATE_OF",
        -          "DEPENDS_ON",
        -          "SUPERSEDES",
        -          "EMBEDS",
        -          "works_at",
        -          "owns",
        -          "manages",
        -          "part_of",
        -          "related_to",
        -          "depends_on",
        -          "references",
        -          "transacted_with",
        -          "member_of",
        -          "reports_to",
        -          "located_at",
        -          "created_by",
        -          "funded_by",
        -          "acquired_by",
        -          "subsidiary_of",
        -          "partner_of",
        -          "competitor_of",
        -          "supplies_to",
        -          "contracted_with",
        -          "invested_in"
        -        ],
        -        "type": "string"
        -      },
        -      "source_entity_id": {
        -        "description": "Existing source entity ID.",
        -        "type": "string"
        -      },
        -      "target_entity_id": {
        -        "description": "Existing target entity ID.",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "relationship_type",
        -      "source_entity_id",
        -      "target_entity_id"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "metadata": {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      "relationship_type": {
        +        "description": "Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).",
        +        "type": "string"
        +      },
        +      "source_index": {
        +        "description": "Index into the entities array for the source entity.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "target_index": {
        +        "description": "Index into the entities array for the target entity.",
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "relationship_type",
        +      "source_index",
        +      "target_index"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "metadata": {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      "relationship_type": {
        +        "description": "Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).",
        +        "type": "string"
        +      },
        +      "source_index": {
        +        "description": "Index into the entities array for the source entity.",
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "target_entity_id": {
        +        "description": "Existing target entity ID.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "relationship_type",
        +      "source_index",
        +      "target_entity_id"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "metadata": {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      "relationship_type": {
        +        "description": "Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).",
        +        "type": "string"
        +      },
        +      "source_entity_id": {
        +        "description": "Existing source entity ID.",
        +        "type": "string"
        +      },
        +      "target_index": {
        +        "description": "Index into the entities array for the target entity.",
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "relationship_type",
        +      "source_entity_id",
        +      "target_index"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "metadata": {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      "relationship_type": {
        +        "description": "Relationship type. The vocabulary is a runtime registry, not a closed enum: call list_relationship_types to read what this instance accepts, and register_relationship_type to add to it. Names are identifier-shaped and casing-agnostic (both SCREAMING_SNAKE and lower_snake are in use).",
        +        "type": "string"
        +      },
        +      "source_entity_id": {
        +        "description": "Existing source entity ID.",
        +        "type": "string"
        +      },
        +      "target_entity_id": {
        +        "description": "Existing target entity ID.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "relationship_type",
        +      "source_entity_id",
        +      "target_entity_id"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedsync_issues3 fields changed
      • addedInput schema / properties / commit
        Added value: +{
        +  "description": "When false, dry run: report what would be created, updated and pushed (`plan`) and write nothing locally or on GitHub. Default: true.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / push / description
        Previous value: -"When false, skip the push leg (local public → GitHub). Default: true."New value: +"Run the push leg (local public → GitHub). Default: true when `repo` is omitted or equals the configured default repo; false for any other `repo`. Pass true to opt in for another repo."
      • addedInput schema / properties / repo
        Added value: +{
        +  "description": "GitHub repository to mirror, `owner/name`. Defaults to the server-configured repo (`NEOTOMA_ISSUES_REPO` / `issues.repo`). Must be the configured repo or be listed in the server's `NEOTOMA_ISSUES_ALLOWED_REPOS` (or `issues.allowed_repos`). A malformed or non-permitted value is rejected before any GitHub request or write.",
        +  "pattern": "^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?/(?!\\.{1,2}$)[A-Za-z0-9._-]{1,100}$",
        +  "type": "string"
        +}
    • Changedupdate_schema_incremental4 fields changed
      • addedInput schema / properties / force
        Added value: +{
        +  "default": false,
        +  "description": "Bypass the entity-type naming guards (forbidden test-artifact patterns and the plural-name guard) for this call only. Required when entity_type is rejected with a message naming \"force: true\" as the remedy — e.g. a name the plural guard misclassifies (like \"hypothesis\"). Does not affect any other validation.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / migrate_existing / description
        Previous value: -"Migrate existing raw_fragments to observations for historical data backfill (default: false). Note: New data automatically uses updated schema after activation, migration is only for old data."New value: +"Migrate existing raw_fragments to observations for historical data backfill (default: false). Note: New data automatically uses updated schema after activation, migration is only for old data. The response's \"migrated_existing\" reflects whether anything actually promoted, and \"migration_result.skipped\" names any fragment groups that did not (e.g. ambiguous ownership, already promoted by a prior call) — a request with migrate_existing: true can legitimately promote zero fragments."
      • removedInput schema / properties / user_specific / default
        Removed value: -false
      • changedInput schema / properties / user_specific / description
        Previous value: -"Create user-specific schema variant (default: false)"New value: +"Explicit scope override. Omit this to write to whichever scope your own read of the schema resolved (global row, or your user-scoped override if you have one) — the common case, and the safe default. Pass true to create or extend a user-specific override for you even if you currently resolve the global row. Pass false to extend the global row even if you have a user-scoped override: the new global version is built from the current global schema, never from your override; if the type has no global registry row and no code-defined baseline (but has your user-scoped schema), the call returns ERR_SCHEMA_SCOPE_MISMATCH. The response's \"scope\" field reports which scope was actually written."
  2. 4 tool updatesv0.22.2
    • Changeddelete_relationship2 fields changed
      • changedInput schema / properties / relationship_type / description
        Previous value: -"Relationship type (e.g. PART_OF, REFERS_TO, EMBEDS)"New value: +"Exact relationship type of the existing edge. Accepts the same set create_relationship writes: structural types (PART_OF, REFERS_TO, EMBEDS) and domain types (works_at, related_to, owns)."
      • changedInput schema / properties / relationship_type / enum
        Previous value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS"
        -]New value: +[
        +  "PART_OF",
        +  "CORRECTS",
        +  "REFERS_TO",
        +  "SETTLES",
        +  "DUPLICATE_OF",
        +  "DEPENDS_ON",
        +  "SUPERSEDES",
        +  "EMBEDS",
        +  "works_at",
        +  "owns",
        +  "manages",
        +  "part_of",
        +  "related_to",
        +  "depends_on",
        +  "references",
        +  "transacted_with",
        +  "member_of",
        +  "reports_to",
        +  "located_at",
        +  "created_by",
        +  "funded_by",
        +  "acquired_by",
        +  "subsidiary_of",
        +  "partner_of",
        +  "competitor_of",
        +  "supplies_to",
        +  "contracted_with",
        +  "invested_in"
        +]
    • Changedget_relationship_snapshot1 field changed
      • changedInput schema / properties / relationship_type / enum
        Previous value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS"
        -]New value: +[
        +  "PART_OF",
        +  "CORRECTS",
        +  "REFERS_TO",
        +  "SETTLES",
        +  "DUPLICATE_OF",
        +  "DEPENDS_ON",
        +  "SUPERSEDES",
        +  "EMBEDS",
        +  "works_at",
        +  "owns",
        +  "manages",
        +  "part_of",
        +  "related_to",
        +  "depends_on",
        +  "references",
        +  "transacted_with",
        +  "member_of",
        +  "reports_to",
        +  "located_at",
        +  "created_by",
        +  "funded_by",
        +  "acquired_by",
        +  "subsidiary_of",
        +  "partner_of",
        +  "competitor_of",
        +  "supplies_to",
        +  "contracted_with",
        +  "invested_in"
        +]
    • Changedrestore_relationship2 fields changed
      • changedInput schema / properties / relationship_type / description
        Previous value: -"Relationship type (e.g. PART_OF, REFERS_TO, EMBEDS)"New value: +"Exact relationship type of the existing edge. Accepts the same set create_relationship writes: structural types (PART_OF, REFERS_TO, EMBEDS) and domain types (works_at, related_to, owns)."
      • changedInput schema / properties / relationship_type / enum
        Previous value: -[
        -  "PART_OF",
        -  "CORRECTS",
        -  "REFERS_TO",
        -  "SETTLES",
        -  "DUPLICATE_OF",
        -  "DEPENDS_ON",
        -  "SUPERSEDES",
        -  "EMBEDS"
        -]New value: +[
        +  "PART_OF",
        +  "CORRECTS",
        +  "REFERS_TO",
        +  "SETTLES",
        +  "DUPLICATE_OF",
        +  "DEPENDS_ON",
        +  "SUPERSEDES",
        +  "EMBEDS",
        +  "works_at",
        +  "owns",
        +  "manages",
        +  "part_of",
        +  "related_to",
        +  "depends_on",
        +  "references",
        +  "transacted_with",
        +  "member_of",
        +  "reports_to",
        +  "located_at",
        +  "created_by",
        +  "funded_by",
        +  "acquired_by",
        +  "subsidiary_of",
        +  "partner_of",
        +  "competitor_of",
        +  "supplies_to",
        +  "contracted_with",
        +  "invested_in"
        +]
    • Changedstore1 field changed
      • changedInput schema / properties / file_path / description
        Previous value: -"Local file path (alternative to file_content). If provided, file will be read from filesystem. MIME type will be auto-detected from extension if not provided. Works in local environments (Cursor, Claude Code) where MCP server has filesystem access. Does NOT work in web-based environments (claude.ai, chatgpt.com) - use file_content for those."New value: +"A path on the SERVER's filesystem, not yours. The file is read by the Neotoma instance, so this only works when your client runs on the same machine as the instance — the axis is co-located vs remote, not desktop vs web. Against a hosted or otherwise remote instance it cannot see your disk and is rejected with ERR_FILE_PATH_IS_SERVER_LOCAL. To send a file from a remote client: upload the bytes (POST /sources/upload, multipart/form-data) and pass the returned source_id, or inline small files with file_content (base64) + mime_type. MIME type is auto-detected from the content or extension when not provided."
  3. 1 tool updatev0.21.5
    • Addeddescribe_instance_policy
  4. 7 tool updatesv0.21.0
    • Addedmanage_bundles
    • Addedquery_contacts_at_company
    • Changedregister_schema1 field changed
      • changedInput schema / properties / reducer_config / description
        Previous value: -"Reducer configuration with merge policies"New value: +"Per-field conflict-resolution config. merge_policies maps each field to a strategy: last_write (default — latest observed_at wins), highest_priority (the observation with the largest source_priority wins), most_specific, or merge_array; with an optional tie_breaker (observed_at | source_priority). Set highest_priority to honor source_priority — without it, source_priority is stored but ignored."
    • Changedretrieve_entities6 fields changed
      • addedInput schema / properties / cursor
        Added value: +{
        +  "description": "Opaque keyset pagination cursor from a previous response's `next_cursor`. Returns the next page in O(page size) time regardless of position, unlike `offset` which is bounded and deprecated. Only supported with the default `sort_by=entity_id`; cannot be combined with `search` or a non-zero `offset`. Reusing a cursor after changing `sort_order` returns a structured error.",
        +  "type": "string"
        +}
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum number of entities to return (default 100)."New value: +"Maximum number of entities to return (default 100). Capped at 500 when `include_snapshots` is true (the default), since each snapshot is hydrated synchronously; lower the page size or set `include_snapshots=false` for larger pages."
      • addedInput schema / properties / offset / deprecated
        Added value: +true
      • changedInput schema / properties / offset / description
        Previous value: -"Pagination offset (default 0)."New value: +"Deprecated in favor of `cursor`. Still accepted for back-compat but internally bounded: values above 2000 are rejected with a structured hint pointing to `cursor`. Supplying a non-zero `offset` together with `cursor` is rejected as a validation error; use one or the other. (default 0)."
      • changedInput schema / properties / snapshot_filters / additionalProperties / properties / op / enum
        Previous value: -[
        -  "eq",
        -  "in",
        -  "gt",
        -  "lt",
        -  "gte",
        -  "lte",
        -  "contains"
        -]New value: +[
        +  "eq",
        +  "in",
        +  "gt",
        +  "lt",
        +  "gte",
        +  "lte",
        +  "contains",
        +  "contains_word"
        +]
      • changedInput schema / properties / snapshot_filters / description
        Previous value: -"Filter entities by snapshot field values. Each key is a snake_case snapshot field name (e.g. `status`, `priority`); the value specifies operator and comparison value. Filters are applied server-side via `snapshot->>{field}` JSONB extraction, so only entities whose snapshot contains a matching value are returned. Example: `{ \"status\": { \"op\": \"eq\", \"value\": \"active\" } }` returns only entities with `snapshot.status === \"active\"`. Supported ops: `eq`, `in`, `gt`, `lt`, `gte`, `lte`, `contains`."New value: +"Filter entities by snapshot field values. Each key is a snake_case snapshot field name (e.g. `status`, `priority`); the value specifies operator and comparison value. Filters are applied server-side via `snapshot->>{field}` JSONB extraction, so only entities whose snapshot contains a matching value are returned. Example: `{ \"status\": { \"op\": \"eq\", \"value\": \"active\" } }` returns only entities with `snapshot.status === \"active\"`. Supported ops: `eq`, `in`, `gt`, `lt`, `gte`, `lte`, `contains`, `contains_word`. `contains` is a raw case-insensitive SUBSTRING match — `{ \"title\": { \"op\": \"contains\", \"value\": \"CTO\" } }` also matches \"director\" and \"doctor\", and `\"COO\"` matches \"coordinator\". Prefer `contains_word` when you mean a whole word/token: it matches only when the value appears as a complete token delimited by punctuation or whitespace, so `\"CTO\"` matches \"VP, CTO\" and \"CTO & Co-founder\" but not \"director\"; `\"Care\"` does not match \"Careers\". Punctuation inside the term is handled: `\"O'Brien\"`, `\"R&D\"`, and `\"100%\"` match their stored values (separators in the term are normalized the same way as the stored value). Case-insensitivity for `contains_word` is ASCII-only."
    • Changedretrieve_entity_snapshot2 fields changed
      • changedInput schema / properties / at / description
        Previous value: -"ISO 8601 timestamp for historical snapshot reconstruction"New value: +"Event-time cutoff (ISO 8601). Reconstructs the snapshot from observations whose `observed_at` ≤ this timestamp. Reflects what *happened* by time T, regardless of when the observation was ingested into Neotoma. Use `at_ingested` instead when you need \"what did we actually know at time T\" semantics."
      • addedInput schema / properties / at_ingested
        Added value: +{
        +  "description": "Ingestion-time cutoff (ISO 8601). Reconstructs the snapshot from observations whose `created_at` (row-insertion time) ≤ this timestamp. Excludes backfilled or late-arriving observations that have a past `observed_at` but arrived after this cutoff, preventing look-ahead leaks. When both `at` and `at_ingested` are supplied, both bounds are applied (AND logic): an observation must satisfy `observed_at ≤ at` AND `created_at ≤ at_ingested`.",
        +  "type": "string"
        +}
    • Changedstore2 fields changed
      • addedInput schema / properties / source_priority / description
        Added value: +"Trust/priority of this observation's source. Only affects snapshot resolution for fields whose merge strategy is highest_priority (set via register_schema reducer_config); under the default last_write strategy it is stored but ignored."
      • addedInput schema / properties / source_storage
        Added value: +{
        +  "description": "Storage mode for file ingestion. Default 'inline' copies bytes into the database (portable, durable). 'reference' stores only a path + metadata row without copying bytes — zero DB bloat, but host-local and depends on the file staying in place. Requires file_path (not file_content). Derivations (observations/entities) are still materialized at ingest. Use 'reference' for large local files you control; use 'inline' for anything that must be shared or portable.",
        +  "enum": [
        +    "inline",
        +    "reference"
        +  ],
        +  "type": "string"
        +}
    • Changedupdate_schema_incremental1 field changed
      • addedInput schema / properties / canonical_name_fields
        Added value: +{
        +  "description": "Replace the entity type's identity rule (how canonical_name / entity identity is derived). Triggers a major version bump. Each item is a single field name (string) or an all-required composite ({composite:[...]}). Rules are ORDERED PRECEDENCE WITH FALLBACK: the resolver uses the first rule whose fields are all present, not an unordered set. Example: [{\"composite\":[\"linkedin_url\"]},\"email\",\"name\"] keys on linkedin_url when present, else email, else name. Omit to keep the current rule. Passing [] clears the rule, but only succeeds when the schema also declares identity_opt_out; otherwise it is rejected (a schema must declare canonical_name_fields OR identity_opt_out). The existing reducer_config is preserved automatically — this is the safe way to re-key a type without reconstructing it. Applies to NEW writes only; it does NOT retroactively re-key existing entities (they keep their stored canonical_name until re-derived), so re-keying will not by itself merge existing duplicates. To see the current rule before replacing it, call describe_entity_type first; the update response also echoes the resolved canonical_name_fields.",
        +  "items": {
        +    "oneOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "properties": {
        +          "composite": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          }
        +        },
        +        "required": [
        +          "composite"
        +        ],
        +        "type": "object"
        +      }
        +    ]
        +  },
        +  "type": "array"
        +}
  5. 9 tool updatesv0.16.0
    • Addedaudit_undeclared_fragments
    • Addeddescribe_entity_type
    • Addedidentify_entity_by_signals
    • Changedlist_relationships1 field changed
      • addedInput schema / properties / include_deleted
        Added value: +{
        +  "default": false,
        +  "description": "When `false` (default), soft-deleted relationships are excluded from\nthe result. When `true`, soft-deleted edges are included (audit/history\nuse). A relationship is soft-deleted once its highest-priority\ndeletion observation is recorded; the snapshot row itself persists.\n",
        +  "type": "boolean"
        +}
    • Addedneotoma_turn_summary
    • Changednpm_check_update1 field changed
      • addedInput schema / properties / include_capability_delta
        Added value: +{
        +  "default": false,
        +  "description": "When true, adds new_tools, removed_tools, and capability_delta_recommendation to the response — a machine-readable list of MCP tools that were added or removed between currentVersion and the latest release. Sourced from the committed capability manifest (generated, not hand-maintained). Default false.",
        +  "type": "boolean"
        +}
    • Addedpublish_rendered_page
    • Changedretrieve_entities5 fields changed
      • changedInput schema / properties / entity_type / description
        Previous value: -"Optional entity type filter (for example: post, task, contact)."New value: +"Optional single entity type filter (for example: post, task, contact). Combined as a union with `entity_types` when both are supplied."
      • addedInput schema / properties / entity_types
        Added value: +{
        +  "description": "Optional multi-type filter. When non-empty, results are restricted to entities whose type is in this list (IN filter), OR-combined with `entity_type`. An empty array is treated as no filter.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / snapshot_filters
        Added value: +{
        +  "additionalProperties": {
        +    "properties": {
        +      "op": {
        +        "enum": [
        +          "eq",
        +          "in",
        +          "gt",
        +          "lt",
        +          "gte",
        +          "lte",
        +          "contains"
        +        ],
        +        "type": "string"
        +      },
        +      "value": {}
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  "description": "Filter entities by snapshot field values. Each key is a snake_case snapshot field name (e.g. `status`, `priority`); the value specifies operator and comparison value. Filters are applied server-side via `snapshot->>{field}` JSONB extraction, so only entities whose snapshot contains a matching value are returned. Example: `{ \"status\": { \"op\": \"eq\", \"value\": \"active\" } }` returns only entities with `snapshot.status === \"active\"`. Supported ops: `eq`, `in`, `gt`, `lt`, `gte`, `lte`, `contains`.",
        +  "type": "object"
        +}
      • changedInput schema / properties / sort_by / description
        Previous value: -"Sort field. Non-default values cannot be combined with `search`."New value: +"Sort field. Non-default values cannot be combined with `search`. Predefined values: `entity_id`, `canonical_name`, `observation_count`, `last_observation_at`, `submitted_at` (orders by `snapshot.created_at`). In addition, `snapshot.<field>` is supported for any snapshot field (e.g. `snapshot.period_end` for time-series entity types such as `usage_digest`). The field value is sorted lexicographically as a string, so ISO-8601 date strings must use a consistent format so that lexicographic order matches temporal order."
      • removedInput schema / properties / sort_by / enum
        Removed value: -[
        -  "entity_id",
        -  "canonical_name",
        -  "observation_count",
        -  "last_observation_at"
        -]
    • Changedsubmit_issue2 fields changed
      • addedInput schema / properties / conversation_turn_id
        Added value: +{
        +  "description": "Entity ID of the conversation turn (conversation_message entity) where this issue was observed. When provided, a REFERS_TO relationship is created from the filed issue to the conversation turn so the origin is traceable.",
        +  "type": "string"
        +}
      • addedInput schema / properties / target_repo
        Added value: +{
        +  "description": "Optional GitHub mirror destination override (`owner/repo`). Use when filing issues about a repo other than the one Neotoma is globally configured for (e.g. `markmhendrickson/ateles`). Overrides only the GitHub mirror — Neotoma authoring home is unchanged.",
        +  "type": "string"
        +}
  6. 55 tool updatesv0.15.0
    • Addedadd_entity_message
    • Addedadd_issue_message
    • Addedadd_peer
    • Addedanalyze_schema_candidates
    • Addedcorrect
    • Addedcreate_interpretation
    • Addedcreate_relationship
    • Addedcreate_relationships
    • Addeddelete_entity
    • Addeddelete_relationship
    • Addedget_authenticated_user
    • Addedget_entity_submission_status
    • Addedget_entity_type_counts
    • Addedget_issue_status
    • Addedget_peer_status
    • Addedget_relationship_snapshot
    • Addedget_schema_recommendations
    • Addedget_session_identity
    • Addedget_subscription_status
    • Addedhealth_check_snapshots
    • Addedlist_entity_submissions
    • Addedlist_entity_types
    • Addedlist_interpretations
    • Addedlist_observations
    • Addedlist_peers
    • Addedlist_potential_duplicates
    • Addedlist_recent_changes
    • Addedlist_relationships
    • Addedlist_subscriptions
    • Addedlist_timeline_events
    • Addedmerge_entities
    • Addednpm_check_update
    • Addedparse_file
    • Addedregister_schema
    • Addedremove_peer
    • Addedresolve_sync_conflict
    • Addedrestore_entity
    • Addedrestore_relationship
    • Addedretrieve_entities
    • Addedretrieve_entity_by_identifier
    • Addedretrieve_entity_snapshot
    • Addedretrieve_field_provenance
    • Addedretrieve_file_url
    • Addedretrieve_graph_neighborhood
    • Addedretrieve_related_entities
    • Addedsplit_entity
    • Addedstore
    • Addedsubmit_entity
    • Addedsubmit_issue
    • Addedsubscribe
    • Addedsync_entity_submissions
    • Addedsync_issues
    • Addedsync_peer
    • Addedunsubscribe
    • Addedupdate_schema_incremental
  7. 55 tool updatesv0.14.0
    • Removedadd_entity_message
    • Removedadd_issue_message
    • Removedadd_peer
    • Removedanalyze_schema_candidates
    • Removedcorrect
    • Removedcreate_interpretation
    • Removedcreate_relationship
    • Removedcreate_relationships
    • Removeddelete_entity
    • Removeddelete_relationship
    • Removedget_authenticated_user
    • Removedget_entity_submission_status
    • Removedget_entity_type_counts
    • Removedget_issue_status
    • Removedget_peer_status
    • Removedget_relationship_snapshot
    • Removedget_schema_recommendations
    • Removedget_session_identity
    • Removedget_subscription_status
    • Removedhealth_check_snapshots
    • Removedlist_entity_submissions
    • Removedlist_entity_types
    • Removedlist_interpretations
    • Removedlist_observations
    • Removedlist_peers
    • Removedlist_potential_duplicates
    • Removedlist_recent_changes
    • Removedlist_relationships
    • Removedlist_subscriptions
    • Removedlist_timeline_events
    • Removedmerge_entities
    • Removednpm_check_update
    • Removedparse_file
    • Removedregister_schema
    • Removedremove_peer
    • Removedresolve_sync_conflict
    • Removedrestore_entity
    • Removedrestore_relationship
    • Removedretrieve_entities
    • Removedretrieve_entity_by_identifier
    • Removedretrieve_entity_snapshot
    • Removedretrieve_field_provenance
    • Removedretrieve_file_url
    • Removedretrieve_graph_neighborhood
    • Removedretrieve_related_entities
    • Removedsplit_entity
    • Removedstore
    • Removedsubmit_entity
    • Removedsubmit_issue
    • Removedsubscribe
    • Removedsync_entity_submissions
    • Removedsync_issues
    • Removedsync_peer
    • Removedunsubscribe
    • Removedupdate_schema_incremental
  8. 3 tool updatesv0.13.0
    • Changedcreate_relationship7 fields changed
      • addedInput schema / properties / metadata
        Added value: +{
        +  "additionalProperties": true,
        +  "description": "Optional metadata attached to the relationship (e.g.\n`caption`, `order` for `EMBEDS` edges).\n",
        +  "type": "object"
        +}
      • addedInput schema / properties / relationship_type
        Added value: +{
        +  "description": "Typed relationship category. Canonical structural types are\n`PART_OF`, `CORRECTS`, `REFERS_TO`, `SETTLES`,\n`DUPLICATE_OF`, `DEPENDS_ON`, `SUPERSEDES`, `EMBEDS`. Domain\ntypes (e.g. `works_at`, `owns`, `manages`) are also accepted.\n",
        +  "enum": [
        +    "PART_OF",
        +    "CORRECTS",
        +    "REFERS_TO",
        +    "SETTLES",
        +    "DUPLICATE_OF",
        +    "DEPENDS_ON",
        +    "SUPERSEDES",
        +    "EMBEDS",
        +    "works_at",
        +    "owns",
        +    "manages",
        +    "part_of",
        +    "related_to",
        +    "depends_on",
        +    "references",
        +    "transacted_with",
        +    "member_of",
        +    "reports_to",
        +    "located_at",
        +    "created_by",
        +    "funded_by",
        +    "acquired_by",
        +    "subsidiary_of",
        +    "partner_of",
        +    "competitor_of",
        +    "supplies_to",
        +    "contracted_with",
        +    "invested_in"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / source_entity_id
        Added value: +{
        +  "description": "Existing entity id at the source end of the edge.",
        +  "type": "string"
        +}
      • addedInput schema / properties / source_id
        Added value: +{
        +  "description": "Optional `sources` row id stamped as provenance on the\nrelationship observation.\n",
        +  "type": "string"
        +}
      • addedInput schema / properties / target_entity_id
        Added value: +{
        +  "description": "Existing entity id at the target end of the edge.",
        +  "type": "string"
        +}
      • addedInput schema / properties / user_id
        Added value: +{
        +  "description": "Optional explicit user id; inferred from authentication\nwhen omitted.\n",
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[]New value: +[
        +  "relationship_type",
        +  "source_entity_id",
        +  "target_entity_id"
        +]
    • Changedlist_entity_types2 fields changed
      • addedInput schema / properties / keyword
        Added value: +{
        +  "type": "string"
        +}
      • addedInput schema / properties / summary
        Added value: +{
        +  "type": "boolean"
        +}
    • Changedsync_issues1 field changed
      • addedInput schema / properties / push
        Added value: +{
        +  "description": "When false, skip the push leg (local public → GitHub). Default: true.",
        +  "type": "boolean"
        +}
  9. 55 tool updatesv0.12.1
    • Addedadd_entity_message
    • Addedadd_issue_message
    • Addedadd_peer
    • Addedanalyze_schema_candidates
    • Addedcorrect
    • Addedcreate_interpretation
    • Addedcreate_relationship
    • Addedcreate_relationships
    • Addeddelete_entity
    • Addeddelete_relationship
    • Addedget_authenticated_user
    • Addedget_entity_submission_status
    • Addedget_entity_type_counts
    • Addedget_issue_status
    • Addedget_peer_status
    • Addedget_relationship_snapshot
    • Addedget_schema_recommendations
    • Addedget_session_identity
    • Addedget_subscription_status
    • Addedhealth_check_snapshots
    • Addedlist_entity_submissions
    • Addedlist_entity_types
    • Addedlist_interpretations
    • Addedlist_observations
    • Addedlist_peers
    • Addedlist_potential_duplicates
    • Addedlist_recent_changes
    • Addedlist_relationships
    • Addedlist_subscriptions
    • Addedlist_timeline_events
    • Addedmerge_entities
    • Addednpm_check_update
    • Addedparse_file
    • Addedregister_schema
    • Addedremove_peer
    • Addedresolve_sync_conflict
    • Addedrestore_entity
    • Addedrestore_relationship
    • Addedretrieve_entities
    • Addedretrieve_entity_by_identifier
    • Addedretrieve_entity_snapshot
    • Addedretrieve_field_provenance
    • Addedretrieve_file_url
    • Addedretrieve_graph_neighborhood
    • Addedretrieve_related_entities
    • Addedsplit_entity
    • Addedstore
    • Addedsubmit_entity
    • Addedsubmit_issue
    • Addedsubscribe
    • Addedsync_entity_submissions
    • Addedsync_issues
    • Addedsync_peer
    • Addedunsubscribe
    • Addedupdate_schema_incremental
  10. 31 tool updatesv0.11.0
    • Removedanalyze_schema_candidates
    • Removedcorrect
    • Removedcreate_relationship
    • Removeddelete_entity
    • Removeddelete_relationship
    • Removedget_authenticated_user
    • Removedget_entity_type_counts
    • Removedget_relationship_snapshot
    • Removedget_schema_recommendations
    • Removedhealth_check_snapshots
    • Removedlist_entity_types
    • Removedlist_observations
    • Removedlist_relationships
    • Removedlist_timeline_events
    • Removedmerge_entities
    • Removednpm_check_update
    • Removedparse_file
    • Removedregister_schema
    • Removedrestore_entity
    • Removedrestore_relationship
    • Removedretrieve_entities
    • Removedretrieve_entity_by_identifier
    • Removedretrieve_entity_snapshot
    • Removedretrieve_field_provenance
    • Removedretrieve_file_url
    • Removedretrieve_graph_neighborhood
    • Removedretrieve_related_entities
    • Removedstore
    • Removedstore_structured
    • Removedstore_unstructured
    • Removedupdate_schema_incremental
  11. 31 tool updatesv0.1.0
    • First observedanalyze_schema_candidates
    • First observedcorrect
    • First observedcreate_relationship
    • First observeddelete_entity
    • First observeddelete_relationship
    • First observedget_authenticated_user
    • First observedget_entity_type_counts
    • First observedget_relationship_snapshot
    • First observedget_schema_recommendations
    • First observedhealth_check_snapshots
    • First observedlist_entity_types
    • First observedlist_observations
    • First observedlist_relationships
    • First observedlist_timeline_events
    • First observedmerge_entities
    • First observednpm_check_update
    • First observedparse_file
    • First observedregister_schema
    • First observedrestore_entity
    • First observedrestore_relationship
    • First observedretrieve_entities
    • First observedretrieve_entity_by_identifier
    • First observedretrieve_entity_snapshot
    • First observedretrieve_field_provenance
    • First observedretrieve_file_url
    • First observedretrieve_graph_neighborhood
    • First observedretrieve_related_entities
    • First observedstore
    • First observedstore_structured
    • First observedstore_unstructured
    • First observedupdate_schema_incremental

TDQS

C2.8/5.0

Scored across 63 tools

Disambiguation3/5

Several clusters have blurry boundaries: retrieve_entities vs retrieve_entity_by_identifier vs identify_entity_by_signals vs retrieve_entity_snapshot all serve entity retrieval/resolution, and list_relationships vs retrieve_related_entities vs retrieve_graph_neighborhood overlap in what they return. Individual descriptions help (e.g., identify_entity_by_signals is clearly signal-based), but an agent faces genuine selection risk across these groups.

Naming Consistency3/5

The dominant verb_noun snake_case pattern (retrieve_X, list_X, create_X, delete_X, sync_peer) is mostly consistent, but there are notable breaks: bare single-verb tools (store, correct, subscribe, unsubscribe) sit alongside compound forms, and the same action uses inconsistent prefixes (retrieve_entities vs get_entity_submission_status vs list_entity_submissions). npm_check_update and neotoma_turn_summary break the convention entirely.

Tool Count2/5

At 63 tools this is well into the heavy range, and many tools feel like surface-area inflation beyond core domain work: npm_check_update, neotoma_turn_summary, health_check_snapshots, get_session_identity, and describe_instance_policy are auxiliary/observability concerns that dilute the tool surface. Even accounting for the large knowledge-graph + sync scope, the count is excessive.

Completeness4/5

The domain surface is unusually comprehensive: full entity lifecycle (store, retrieve, delete, restore, merge, split), relationship lifecycle (create, list, delete, restore, traverse), schema management (register, describe, update), issues (submit, status, sync), and subscriptions/peers all have complete CRUD coverage. The main gap is resolve_sync_conflict being a stub, but the rest of the surface leaves few dead ends.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Local-first, file-based memory layer for AI agents — one shared Markdown vault across Claude, Codex, Gemini, Cursor and any MCP client. Provides read/write memory tools with an audit trail, per-agent trust levels, and Git sync; no cloud and no lock-in.
    2
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    A local-first shared memory layer for MCP-aware agents like Claude, Codex, and Hermes, enabling persistent memory across chats and clients via Markdown files and SQLite FTS.
    6
    2
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Local-first, source-traceable memory for AI agents — no LLM at ingest, $0 per message, zero data egress. Gives Claude Code, Cursor, and any MCP client one shared persistent memory with semantic recall, belief revision, selective forgetting, and a provenance guard that blocks acting on stale or unconfirmed memories.
    23
    17 PyPI
    15
    MIT
  • A
    license
    Not graded
    quality
    F
    maintenance
    Local-first, auditable memory for AI agents. Provides durable context for MCP hosts with SQLite storage, CLI, and MCP tools for memory management.
    2
    Apache 2.0