Skip to main content
Glama

google-surf-mcp

✨Анти-бот MCP для поиска: без API-ключа✨

English | 한국어

google-surf-mcp MCP server

demo

Только для демонстрации. По умолчанию реальный поиск выполняется в headless-режиме (без видимого браузера). Установите SURF_HEADLESS=false, чтобы сделать Chrome видимым, как на видео выше.

MCP для поиска в Google. Без API-ключа. Просто работает.

  • ✅ Действительно работает (протестировано 6 бесплатных MCP для поиска в Google, все остальные не справились)

  • ✅ Поиск + извлечение URL в одном MCP (заменяет обычную комбинацию MCP поиска и MCP загрузчика)

  • ✅ 4 инструмента: search / search_parallel / extract / search_extract

  • ✅ Без API-ключа, без прокси, без сервисов разгадывания капчи

  • ✅ Автоматическое восстановление после CAPTCHA (открывается Chrome, человек решает один раз, вызов повторяется)

  • ✅ Защита от SSRF в extract (по умолчанию блокирует localhost, частные IP-адреса и метаданные AWS)

Что это

Подключите его к любому MCP-клиенту, и вы получите поиск Google в качестве инструмента.

Никаких сервисов разгадывания капчи. Когда в любом инструменте срабатывает CAPTCHA, открывается окно Chrome, чтобы человек мог её решить. Каждое решение сохраняет репутацию профиля в Google. Создано для устойчивого и этичного использования.

Для однократной установки требуется прогрев профиля (~1 сек) (см. раздел «Установка»).

Предназначено для локального использования. Не подходит для stateless / serverless развертывания.

Related MCP server: G-Search MCP

Показатели

результат

последовательно

~1.5 сек/запрос (первый вызов ~4 сек, включая настройку)

параллельно x4

~1.5 сек (первый вызов ~9 сек, включая прогрев пула)

параллельно x10

~4.5 сек

search_extract x5

~5 сек (поиск + 5 параллельных извлечений)

Измерено на рабочей станции с подключением 1 Гбит/с.

Стек

  • Playwright + постоянный профиль Chrome

  • playwright-extra stealth

  • Блокировка ресурсов (изображения / медиа / шрифты) для скорости

  • Однократная загрузка профиля перед первым запуском

  • Mozilla Readability + Turndown для извлечения статей

Установка

Требуются Node 18+ и Google Chrome (или Chromium) в системе.

npx google-surf-mcp   # actual MCP - register in client config

Или локальное клонирование:

git clone https://github.com/HarimxChoi/google-surf-mcp
cd google-surf-mcp
npm install
npm run bootstrap

bootstrap открывает окно Chrome. Выполните в нем один поиск в Google. Закройте. Профиль прогрет.

При необходимости переопределите пути:

CHROME_PATH=/path/to/chrome SURF_TZ=America/New_York npm run bootstrap

Использование с Claude Code

Вставьте это в ваш ~/.claude.json:

{
  "mcpServers": {
    "google-surf": {
      "command": "npx",
      "args": ["-y", "google-surf-mcp"]
    }
  }
}

Перезапустите Claude Code. Готово. Инструменты search, search_parallel, extract, search_extract теперь доступны.

Для других MCP-клиентов используйте ту же структуру JSON в их файле конфигурации.

Вариант с локальным клонированием:

{
  "mcpServers": {
    "google-surf": {
      "command": "node",
      "args": ["/abs/path/to/google-surf-mcp/build/index.js"]
    }
  }
}

Инструменты

  • search(query, limit?) — одиночный запрос, ~1.5 сек. Возвращает заголовок / URL / сниппет. Спонсорская реклама отфильтровывается.

  • search_parallel(queries[], limit?) — пул из 4, максимум 10 запросов за вызов.

  • extract(url, max_chars?) — загрузка URL, возврат статьи в формате markdown (Readability с резервным текстовым вариантом). Ошибки возвращают { error }, никогда не вызывают исключение.

  • search_extract(query, limit?, max_chars?) — поиск + параллельное извлечение в одном вызове. Возвращает результаты SERP, дополненные полным содержанием статей. Ошибки на отдельных страницах изолированы.

search_extract — это главный инструмент: SERP + полное содержание статьи за один вызов. Заменяет обычную комбинацию «MCP поиска + MCP загрузчика URL», которую обычно собирают агенты.

Переменные окружения

переменная

по умолчанию

примечания

CHROME_PATH

автоопределение

абсолютный путь к бинарному файлу Chrome

SURF_PROFILE_ROOT

~/.google-surf-mcp

где хранится прогретый профиль

SURF_LOCALE

en-US

локаль браузера

SURF_TZ

системная tz

например, America/New_York

SURF_HEADLESS

true

установите false для видимого запуска Chrome (демо / отладка). Автовосстановление CAPTCHA всегда работает в видимом режиме.

SURF_IDLE_CLOSE_MS

30000

мс простоя перед закрытием последовательного контекста и пула. 0 отключает автозакрытие. Меньше = быстрее очистка, больше = теплый кэш для редких вызовов.

SURF_ALLOW_PRIVATE

false

установите true, чтобы разрешить extract загружать частные/loopback адреса (localhost, 127.0.0.1, 10.x, 192.168.x, 169.254.x и т.д.). По умолчанию блокирует их как защиту от SSRF.

Устранение неполадок

  • CAPTCHA: автоматически открывается видимое окно Chrome (работает для всех 4 инструментов). Решите её один раз, выполните один поиск внутри, вызов повторится и продолжится. Чтобы вместо этого быстро завершаться с ошибкой, запускайте без подключенного дисплея.

  • "Chrome not found": установите Chrome или задайте CHROME_PATH.

  • Устаревшие селекторы: Google меняет классы. PR приветствуются.

Журнал изменений

См. CHANGELOG.md.

Лицензия

MIT

Available Tools

7 tools
extractKnown URL ExtractA

SECONDARY KNOWN-URL CONTENT EXTRACTION TOOL. Use only when the exact public URL is already known and no new web discovery is required. If sources still need to be found, use search or search_parallel with extract_mode instead. For semantic reading of a public PDF or GitHub repository, use this tool before local download or parsing. Local PDF tools are for local files, forms, OCR recovery, or visual layout inspection; general repository tools are for editing, building, testing, or full Git history. Fetch one public URL and return clean content. With research enabled, one local broker lets multiple MCP sessions query the same knowledge base concurrently and orders writes safely. For GitHub repository URLs, metadata reads the README; abstract and full use the same bounded download gate and differ only in indexed source depth. HTML via Mozilla Readability; academic PDFs (arxiv/biorxiv/Nature/OpenReview/NeurIPS/JMLR/PMLR/Springer/PubMed-via-PMC) auto-detected via Content-Type, %PDF magic, citation_pdf_url meta, and per-domain URL rules. Tiered depth: mode="metadata" returns document metadata without body text, mode="abstract" returns about 1500 chars for relevance checks, and mode="full" reads the full bounded source. response_content controls whether the response contains a 1500-character summary or up to 50000 characters. PDF and landing-page metadata are merged when available. With research enabled, abstract and full PDF reads are stored as searchable evidence with bibliographic metadata and provenance. Best-effort: failures return an errorInfo instead of throwing.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesPublic http(s) URL. Loopback/private IPs blocked unless SURF_ALLOW_PRIVATE=true.
modeNoExtraction depth. `full` = whole article body (default; uses Playwright if needed). `abstract` = cheap survey: PDF page 1 OR HTML meta description (~1500 chars); use to triage relevance before paying for full text. `metadata` = document metadata without body text: title, authors, publication details, dates, DOI, keywords, canonical URL, and PDF properties when available. Academic PDFs (arxiv/biorxiv/Nature/OpenReview/NeurIPS/JMLR/PMLR/Springer/PubMed-via-PMC) are auto-detected; abstract mode skips Playwright for them.full
max_charsNoMaximum returned characters when response_content=full. Defaults to 1500 for abstract and 50000 for full.
project_idNoProject memory id.
session_idNoStable host task id. Reuses the same project session after restart.
memory_handleNoReuse the handle returned by a prior project-aware call.
session_intentNoCurrent durable task intent. A changed value creates an immutable revision.
response_contentNoControls only the returned body. full returns up to max_chars; summary returns a 1500-character evidence excerpt. Research storage keeps the full captured text in deterministic chunks.full

Output Schema

ParametersJSON Schema
NameRequiredDescription
doiNo
urlNo
metaNo
yearNo
errorNo
titleNo
is_pdfNo
lengthNo
memoryNo
authorsNo
contentNo
creatorNo
excerptNo
subjectNo
keywordsNo
languageNo
producerNo
truncatedNo
created_atNo
elapsed_msNo
page_countNo
descriptionNo
modified_atNo
publicationNo
published_atNo
canonical_urlNo
memory_handleNo
source_lengthNo
extraction_qualityNo

TDQS

A4.8/5.0
Behavior5/5

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

Despite annotations already providing some signals, the description adds substantial behavioral detail: best-effort failures return errorInfo instead of throwing, PDF and GitHub URL handling are explained, research-enabled memory writes are disclosed, and mode/response_content behavior is specified. This goes well beyond the annotation surface and gives the agent a realistic model of side effects and failure behavior.

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 front-loaded with purpose and usage, then organized into behavior, modes, and failure semantics. It is dense but mostly relevant; a few sentences, such as the local broker concurrency note, feel tangential and partly overlap with what the schema already conveys. This prevents a 5 but is still well-structured.

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

Completeness5/5

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

For a tool with 8 parameters, an output schema, and meaningful side-effect behavior, the description is complete: it covers when to use it, when not to, mode semantics, output size controls, PDF and GitHub behavior, memory/research implications, and error handling. Nothing critical for correct invocation or selection is missing.

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, but the description adds real meaning beyond the schema: it explains what each mode returns, how response_content interacts with max_chars, how PDF auto-detection works, and how memory/research parameters relate to stored evidence. It does not substantially clarify project_id, session_id, memory_handle, or session_intent beyond the schema, so a 4 is appropriate rather than 5.

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 'SECONDARY KNOWN-URL CONTENT EXTRACTION TOOL' and states 'Fetch one public URL and return clean content,' giving a specific verb, resource, and scope. It also explicitly distinguishes this tool from search and search_parallel, so an agent can tell it apart from siblings without guessing.

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?

Usage guidance is explicit and actionable: 'Use only when the exact public URL is already known and no new web discovery is required.' It names alternatives with conditions ('use search or search_parallel with extract_mode instead') and even clarifies when local PDF and repository tools should be preferred. This leaves little room for misrouting.

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

healthMCP Health CheckA
Read-onlyIdempotent

MCP server status: cascade mode + transitions, rate-limiter usage, cache size, config. Call this if searches start failing or returning empty -- check cascade.totalCaptchas and rateLimiter.queueSize, and reduce search volume if they are high.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
poolNo
cacheNo
errorNo
configNo
cascadeNo
versionNo
researchNo
telemetryNo
rateLimiterNo
selfHealingNo
nativeBrowserNo

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds value by explaining what status fields the agent should inspect and how to interpret them (thresholds/actions), which is useful behavioral context beyond the annotations.

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

Conciseness5/5

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

The description is two sentences and every part earns its place: the field list gives what the tool reports, and the second sentence gives the trigger condition and expected action. It is front-loaded with the core status purpose before the usage guidance.

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 this is a zero-parameter health-check tool, the annotations cover read-only/idempotent behavior, and an output schema exists, the description is complete. It even goes beyond the minimum by telling the agent when to call it and what to do with the returned values.

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 tool has zero parameters, so there is no input semantics for the description to clarify. The description instead compensates by naming the output fields that matter (cascade.totalCaptchas, rateLimiter.queueSize), which adds context beyond the empty schema.

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 identifies a health-check/status resource and enumerates the fields it exposes (cascade mode, transitions, rate-limiter usage, cache size, config). It lacks an explicit action verb like 'get' or 'return', but 'MCP server status' plus the title makes the purpose unambiguous and distinguishable from the search-oriented siblings.

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?

The description explicitly tells the agent when to call the tool: 'if searches start failing or returning empty'. It also gives follow-up guidance, telling the agent to check cascade.totalCaptchas and rateLimiter.queueSize and reduce search volume if they are high. This is a clear, actionable usage rule, and it implicitly separates this diagnostic tool from the search tools.

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

project_memoryProject MemoryA

PROJECT MEMORY MANAGEMENT. With research enabled, one local broker lets multiple MCP sessions query the same knowledge base concurrently and orders writes safely. It links session intent, immutable plan revisions, experiments, decisions, versioned ontology, and bitemporal data lineage; corrections can use entity merge or split without discarding history. Use project_update for revision-checked changes to an existing project profile; context reads that same versioned profile. Use query_status/query_cancel with a caller-supplied search request_id to inspect or cooperatively stop a long retrieval. Use context for the bounded current project view; current to generate a compact CURRENT.md; get/get_batch for exact records and body spans; record/record_batch for durable idempotent writes; timeline/diff for history; sync for declared source deltas; job_status/job_wait/job_cancel for background progress and safe stage-boundary cancellation; verify for preservation levels; snapshot/snapshot_import/snapshot_rollback for versioned offline transfer and append-only recovery; doctor for passive diagnostics; rebuild for derived indexes; export for graph views; and forget for reversible deletion. Typed record writes return compact receipts and never echo submitted bodies. action=search remains a compatibility alias, but project_memory_search should be used for local knowledge retrieval. Ontology revisions use supersedes_term_id. Corrections preserve bitemporal data lineage and support assertion replacement plus entity merge or split. rebuild indexes approved local roots and code structure into a reproducible snapshot; export writes an interactive HTML viewer, Graphviz DOT, D3 JSON, or a Neo4j import bundle. HTML always includes PKM, Lineage, and Ontology tabs, an embedded-project selector, empty-canvas focus reset, and visible PNG or JSON download. forget previews impact before reversible project or assertion deletion. Search, search_parallel, scholar_search, and extract automatically capture sources and provenance; project_memory manages their durable structure.

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyNoComplete UTF-8 record body. Typed writes preserve it losslessly and return byte counts plus an exact get route.
nameNoProject name for create/project_update, or entity name lookup for show.
afterNo
as_ofNoFor context, reconstruct the project and plan view at this effective or recorded time.
limitNoMaximum local RAG results for action=search.
queryNoRequired for action=search. Searches stored local knowledge only and does not start live web discovery.
rootsNoApproved local roots and optional path-independent role/alias manifest. sync merges roots by default; removal is explicit.
titleNoPlan title, experiment name, or decision title.
actionYesTyped project-memory operation. create: project_id and name required. project_update: versioned profile update with expected_revision and idempotency_key. get/get_batch: exact IDs and bounded body spans; body_bytes=0 returns metadata only. record/record_batch: typed durable writes with idempotency_key. context/current/timeline/diff: compact current or historical views. query_status/query_cancel: inspect or cooperatively cancel caller-identified local retrieval. sync/rebuild: incremental source and derived indexing. job_status/job_wait/job_cancel: durable background work. snapshot/snapshot_import/snapshot_rollback: offline transfer and append-only recovery. export: HTML, DOT, JSON, or Neo4j. forget: reversible deletion preview and confirmation. Unrelated local questions use project_memory_search.
beforeNo
fieldsNoTyped structured fields stored with the record revision. measurement requires metric, value, unit, evaluator_contract, dataset, split, tokenizer, context_length, targets, carrier_precision, and source_locator; byte_ledger requires byte_components, denominator, and scope. Put unknown required values in missing_fields.
intentNoDurable intent for record_type=session.
job_idNo
reasonNoRequired reason for any correction.
statusNoUse success, failed, or inconclusive to finish an experiment. Omit or use running when starting it.
aliasesNoOntology term aliases, or aliases moved during entity_split.
dry_runNo
filtersNoOptional project, source, type, role, lane, and recorded-time filters. Excluded lanes are not executed.
metricsNoTerminal experiment metrics.
purposeNo
queriesNoIndependent questions returned as separate ranked groups inside one broker request.
recordsNo
summaryNoExperiment result or decision summary.
versionNoOntology revision number. Defaults to 1 or the superseded term version plus one.
asset_idNoStable logical identity. Revisions remain under this ID.
git_rootNoOptional Git root recorded with a rebuild snapshot.
revisionNo
valid_toNoCorrected assertion valid-time end.
artifactsNoLegacy experiment artifact paths. Typed writes should use artifact_references; no values are silently sliced.
body_pathNoLocal UTF-8 file for a streamed versioned body attachment up to 256 MiB. Use instead of body; only a compact receipt is returned.
operationNoTyped durable write operation. Use with asset_kind and idempotency_key.
protectedNo
record_idNoKnown exact record or alias ID for get, diff, or verify.
root_modeNo
target_idNoAssertion or entity id for show or correction.
asset_kindNo
body_bytesNoUTF-8 bytes to return. Use 0 for metadata-only readback; use a positive value and next_body_offset for exact paging.
hypothesisNoHypothesis when starting an experiment.
project_idNoStable project id. For search, this is the write-isolated primary scope. Omit to list projects or use all_projects.
record_idsNo
request_idNoCaller-chosen ID for one local query. Supply it before a long request so project_memory query_status/query_cancel can inspect or cancel the same operation.
source_idsNoEntity ids merged into target_id by entity_merge.
valid_fromNoCorrected assertion valid-time start.
access_tierNoOperational access tier. It does not rank scientific quality.
body_offsetNo
export_viewNoInitial HTML tab or non-HTML export scope. graph is PKM; ontology shows types, shared schema, verified identity links, and typed instances; lineage shows aligned data and research lineage.graph
forget_modeNoPreview first. Apply requires its confirm_token. Restore reverses deletion.
record_typeNoRequired for record. session stores intent; plan creates an immutable revision; experiment starts or finishes a run; decision links a conclusion; ontology creates a versioned type or relation; correction replaces an assertion or merges/splits entities.
replacementNoNew assertion value, or new entity name for entity_split.
set_currentNoFor plan writes, select this revision as current. Defaults to true; use false for historical imports.
to_revisionNo
all_projectsNoSearch or export every active named project. Excludes Inbox and cannot be combined with project ids.
budget_bytesNo
detail_levelNoFor show with project_id and no target_id, both values return a bounded summary. full is retained only for compatibility and never returns every durable record body.summary
effective_atNo
evidence_idsNoEvidence retained on a corrected assertion.
cancel_reasonNo
change_reasonNoReason for a new plan revision.
changed_pathsNoExplicit root-relative files or collection boundaries to re-read. Existing roots and all unlisted entries are preserved.
confirm_tokenNoToken returned by the matching forget preview.
experiment_idNoExperiment to finish or associate with a decision.
export_formatNoVisualization file format. html writes one offline explorer with PKM, Lineage, Ontology, project selection, and current-view PNG or anonymized JSON download; d3 writes node-link JSON; dot writes Graphviz DOT; neo4j writes an import-ready CSV and Cypher bundle.d3
from_revisionNo
memory_handleNoExisting project session handle for a session intent revision.
ontology_kindNoOntology term kind for record_type=ontology.
removed_pathsNoExplicit root-relative entries to remove from the active snapshot. Historical snapshots remain addressable.
snapshot_pathNo
after_revisionNo
artifact_limitNo
missing_fieldsNo
query_variantsNoOptional local retrieval variants for action=search. They run inside one broker request and are fused before one rerank.
since_revisionNo
artifact_offsetNo
correction_kindNoCorrection operation. Defaults to assertion.
idempotency_keyNoStable operation key. Reuse it after an uncertain response.
source_sequenceNo
wait_timeout_msNo
plan_revision_idNoPlan revision associated with an experiment or decision.
source_referenceNo
user_constraintsNo
correction_reasonNo
expected_revisionNoOptimistic concurrency revision. Stale values return a conflict.
supersedes_term_idNoPrior ontology term replaced by this revision.
verification_levelNo
artifact_referencesNo
include_project_idsNoAdditional read-only projects for one local search or integrated visualization export.
protected_parent_idsNo
response_deadline_msNoCaller-selected 1-300 second response deadline. Returns available lane results or QUERY_TIMEOUT with request_id. Native reads remain tracked until they settle; stored evidence and writes are unaffected.
response_budget_bytesNoExplicit result-array byte budget. Without an override, summaries adapt to unique result, question and source-family counts. Stored bodies and retrieval scope are not truncated by this budget; envelope metadata is separate.
based_on_experiment_idNoExperiment that motivated a plan revision.

Output Schema

ParametersJSON Schema
NameRequiredDescription
jobNo
diffNo
metaNo
errorNo
indexNo
plansNo
queryNo
doctorNo
entityNo
forgetNo
groupsNo
memoryNo
recordNo
contextNo
currentNo
projectNo
receiptNo
recordsNo
resultsNo
sessionNo
entitiesNo
importedNo
projectsNo
receiptsNo
snapshotNo
timelineNo
assertionNo
decisionsNo
elapsed_msNo
job_countsNo
plan_countNo
experimentsNo
entity_countNo
query_statusNo
verificationNo
memory_handleNo
session_countNo
visualizationNo
decision_countNo
document_countNo
assertion_countNo
correction_countNo
experiment_countNo
search_event_countNo
source_entry_countNo
active_source_snapshotNo
entity_operation_countNo
citation_observation_countNo

TDQS

A4/5.0
Behavior4/5

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

Annotations are all false (readOnlyHint=false, openWorldHint=false, idempotentHint=false), so they declare nothing positive and the description carries the burden. It adds meaningful behavioral context: concurrent querying with safe write ordering, 'Typed record writes return compact receipts and never echo submitted bodies,' corrections that 'preserve bitemporal data lineage and support assertion replacement plus entity merge or split,' forget that 'previews impact before reversible project or assertion deletion,' and that search-family tools 'automatically capture sources and provenance.' No contradiction with annotations. Small deduction for not covering auth requirements, rate limits, or failure semantics beyond hints like QUERY_TIMEOUT.

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 dense and every sentence carries information, but it is a very long wall of text with essentially no paragraph breaks for scannability. The central routing sentence is a massive run-on listing 15+ action mappings in one clause ('Use context for the bounded current project view; current to generate a compact CURRENT.md; get/get_batch for exact records and body spans; record/record_batch for durable idempotent writes; ...'). The core concept is front-loaded well, but an agent parsing this would benefit from bullets or segmentation. Appropriately sized for the tool's complexity, poorly structured for consumption.

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 90-parameter destination tool with an output schema, this is near-complete: it covers the broker/concurrency model, what the store links, a full action routing table, behavior of writes, correction semantics, export output characteristics, and sibling differentiation. The output schema means return values need no explanation. Deductions for not addressing access control/permissions, rate limits, or multi-step error-recovery flows beyond idempotency-key mentions. Given the enormous scope, the coverage is strong but not exhaustive.

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 66%, so the schema already documents most parameters and the baseline is 3. The description adds value mostly at the action-routing level (which parameter combinations belong to which action) and via behavioral notes like 'Ontology revisions use supersedes_term_id' and export format specifics (HTML always includes PKM, Lineage, and Ontology tabs). However, it does not deeply compensate for the remaining undocumented ~34% of parameters; many parameter meanings are only discoverable through the schema or the action enum's own long description. Marginal addition over the schema, hence a 3.

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 states a specific role: a local broker that lets multiple MCP sessions query the same knowledge base concurrently while ordering writes safely, and it enumerates what the store links (session intent, plan revisions, experiments, decisions, versioned ontology, bitemporal lineage). It also distinguishes itself from siblings by explicitly naming project_memory_search as the sibling for local knowledge retrieval. Slight deduction because the tool is a 25-plus-action dispatcher, so the 'purpose' is necessarily broad rather than a single verb+resource.

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?

The description provides an explicit routing map for nearly every action: 'Use project_update for revision-checked changes...', 'Use context for the bounded current project view; current to generate a compact CURRENT.md; get/get_batch for exact records...', plus job_*, snapshot_*, doctor, rebuild, export, and forget. It also gives a negative rule: 'action=search remains a compatibility alias, but project_memory_search should be used' and 'Unrelated local questions use project_memory_search.' This is model-guidance of the highest quality.

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

search_parallelParallel Web Search and ExtractA

PRIMARY MULTI-QUERY LIVE DISCOVERY AND CONTENT INGESTION TOOL. ALWAYS PERFORMS MULTIPLE LIVE WEB SEARCHES. With research enabled, one local broker lets multiple MCP sessions query the same knowledge base concurrently and orders writes safely. Use this tool only when 2-12 new external queries are required. Providing project_id adds stored evidence but never makes the searches local-only. When the task requires broad discovery plus reading public web pages, PDFs, papers, or GitHub repositories, set extract_mode=abstract or full in this call. Do not download public PDFs, clone repositories, or invoke local parsers first. Select extract_mode=full, not abstract, when the user asks to read originals, full text, document bodies, or code, or to compare source contents. Use extract separately only when the exact public URL is already known and no new discovery is required. Use general repository tools only for editing, building, testing, or full Git history. For stored project knowledge without live web discovery, use project_memory_search. Each query limit accepts integers from 1 to 20. Call-wide extract_limit accepts 1-20 with default 12 for abstract, and 1-10 with default 10 for full. Final results use one call-wide bounded response budget after ranking; at most 36 ranked rows are returned across query groups and full captured bodies remain local. Use extract on one selected URL when longer response text is explicitly required. The response includes applied, skipped, truncated, total_chars, and a bounded remaining_urls list. GitHub none mode reads the README; abstract and full can sparse-index eligible repositories with Tree-sitter. With research enabled and project_id set, each query fuses live, exact, BM25, vector, code, and graph lanes through RRF and one reranker. With research disabled, each query independently fuses provider order and query BM25 rank through a lightweight in-memory RRF reranker without opening local storage or loading the vector model. research_context returns prior project searches; capture retains data lineage and include_project_ids uses versioned ontology and verified cross-project schema/entity links. Extracted bodies become evidence while unread hits remain metadata. Native Chrome uses one authenticated local broker across MCP sessions and keeps one hidden process with up to four reusable tabs. Query starts are staggered and each tab continuously consumes the remaining queue. SearchApi fallback replaces failed queries individually.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum results per query. Integer 1-20, default 10.
queriesYes2-12 independent live queries.
max_charsNoMaximum returned characters per extracted result in response_content=full. Defaults to 1500 for abstract and 50000 for full.
project_idNoProject memory id.
session_idNoStable host task id. Reuses the same project session after restart.
extract_modeNoContent depth in this search call. Use none only when titles and snippets are enough, abstract for relevance evidence, and full when the user asks to read originals, full text, document bodies, or code, or to compare source contents. Use abstract or full here instead of following search with separate extraction, PDF download, or repository clone. For GitHub results, none reads the README; abstract and full use the same repository eligibility gate but index different source amounts.none
extract_limitNoCall-wide maximum unique result URLs to extract. Integer 1-20, default 12 for abstract; full defaults to and allows at most 10.
memory_handleNoReuse the handle returned by a prior project-aware call.
session_intentNoCurrent durable task intent. A changed value creates an immutable revision.
response_contentNoControls only returned bodies. summary is the default and returns 1500-character evidence excerpts; full returns up to max_chars. Research storage keeps the full captured text in deterministic chunks.summary
include_project_idsNoAdditional read-only projects joined through ontology-aligned schema and identity links. New records stay in project_id.

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaNo
errorNo
memoryNo
resultsNo
elapsed_msNo
memory_handleNo
research_contextNo

TDQS

A4.7/5.0
Behavior5/5

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

Annotations are minimal (readOnlyHint false, openWorldHint true, idempotentHint false), so the description carries the full burden. It discloses writes ('orders writes safely'), concurrency ('one local broker lets multiple MCP sessions query the same knowledge base concurrently'), fallback behavior ('SearchApi fallback replaces failed queries individually'), and result bounds ('at most 36 ranked rows are returned'). This far exceeds what annotations provide and is fully consistent with them.

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 dense paragraph exceeding 300 words. While every sentence adds substantive information, the lack of paragraph breaks or bullets makes it harder to scan. The content is front-loaded with the primary purpose, but the wall of text could be better structured without losing information. It is not concise, though it is thorough.

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 11 parameters, an output schema, and complex behavioral nuances (research modes, extract modes, browser fallback, response budgets), the description covers all essential aspects. It explains return fields ('applied, skipped, truncated, total_chars, and a bounded remaining_urls list'), clarifies modes, and addresses edge cases like project_id not making searches local-only. An agent can confidently invoke this 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% and parameter descriptions are already detailed. The description adds meaningful context beyond the schema, such as clarifying the relationship between extract_mode and extract_limit, explaining that 'Use abstract or full here instead of following search with separate extraction, PDF download, or repository clone,' and detailing the response budget. This adds value beyond the schema, though not every nuance is 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 opens with a clear statement of what the tool does: 'PRIMARY MULTI-QUERY LIVE DISCOVERY AND CONTENT INGESTION TOOL. ALWAYS PERFORMS MULTIPLE LIVE WEB SEARCHES.' It also distinguishes itself from siblings by specifying when to use it: 'Use this tool only when 2-12 new external queries are required.' This makes its purpose unambiguous and clearly differentiated from extract, project_memory_search, and repository tools.

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?

The description provides explicit usage guidance: 'Use this tool only when 2-12 new external queries are required,' 'Use extract separately only when the exact public URL is already known and no new discovery is required,' and 'Use general repository tools only for editing, building, testing, or full Git history.' It also names alternatives like project_memory_search for stored knowledge without live discovery. This is comprehensive and actionable.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 7 tool updatesv1.1.3
    • Changedextract1 field changed
      • changedOutput schema / properties / error / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "code": {
        -        "type": "string"
        -      },
        -      "message": {
        -        "type": "string"
        -      },
        -      "retry_after_ms": {
        -        "type": "number"
        -      },
        -      "retryable": {
        -        "type": "boolean"
        -      },
        -      "user_action": {
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "code",
        -      "message",
        -      "retryable"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "cancel_reason": {
        +        "type": "string"
        +      },
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "phase": {
        +        "type": "string"
        +      },
        +      "request_id": {
        +        "type": "string"
        +      },
        +      "retry_after_ms": {
        +        "type": "number"
        +      },
        +      "retryable": {
        +        "type": "boolean"
        +      },
        +      "user_action": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message",
        +      "retryable"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedhealth3 fields changed
      • addedOutput schema / properties / error / properties / cancel_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / phase
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / request_id
        Added value: +{
        +  "type": "string"
        +}
    • Changedproject_memory84 fields changed
      • addedInput schema / properties / access_tier
        Added value: +{
        +  "description": "Operational access tier. It does not rank scientific quality.",
        +  "enum": [
        +    "hot",
        +    "warm",
        +    "cold"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / action / description
        Previous value: -"create: project_id and name required. show: inspect a known project, assertion, entity, or durable record. search: compatibility alias for project_memory_search. record: project_id and record_type required. rebuild: project_id required; roots optional. export: project_id, include_project_ids, or all_projects=true required. forget: project_id and forget_mode required; apply also requires confirm_token."New value: +"Typed project-memory operation. create: project_id and name required. project_update: versioned profile update with expected_revision and idempotency_key. get/get_batch: exact IDs and bounded body spans; body_bytes=0 returns metadata only. record/record_batch: typed durable writes with idempotency_key. context/current/timeline/diff: compact current or historical views. query_status/query_cancel: inspect or cooperatively cancel caller-identified local retrieval. sync/rebuild: incremental source and derived indexing. job_status/job_wait/job_cancel: durable background work. snapshot/snapshot_import/snapshot_rollback: offline transfer and append-only recovery. export: HTML, DOT, JSON, or Neo4j. forget: reversible deletion preview and confirmation. Unrelated local questions use project_memory_search."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "create",
        -  "show",
        -  "search",
        -  "record",
        -  "rebuild",
        -  "export",
        -  "forget"
        -]New value: +[
        +  "create",
        +  "project_update",
        +  "show",
        +  "search",
        +  "record",
        +  "record_batch",
        +  "get",
        +  "get_batch",
        +  "context",
        +  "timeline",
        +  "diff",
        +  "sync",
        +  "job_status",
        +  "job_wait",
        +  "job_cancel",
        +  "query_status",
        +  "query_cancel",
        +  "verify",
        +  "current",
        +  "snapshot",
        +  "snapshot_import",
        +  "snapshot_rollback",
        +  "doctor",
        +  "rebuild",
        +  "export",
        +  "forget"
        +]
      • addedInput schema / properties / after
        Added value: +{
        +  "type": "string"
        +}
      • addedInput schema / properties / after_revision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / artifact_limit
        Added value: +{
        +  "maximum": 1000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / artifact_offset
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / artifact_references
        Added value: +{
        +  "items": {
        +    "properties": {
        +      "artifact_id": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "available": {
        +        "type": "boolean"
        +      },
        +      "content_hash": {
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "location": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "media_type": {
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "member": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "observed_at": {
        +        "format": "date-time",
        +        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +        "type": "string"
        +      },
        +      "path": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "role": {
        +        "maxLength": 200,
        +        "type": "string"
        +      },
        +      "size": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "verification": {
        +        "enum": [
        +          "declared",
        +          "present",
        +          "hash_verified",
        +          "restore_tested",
        +          "replayed"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "artifact_id"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 50000,
        +  "type": "array"
        +}
      • changedInput schema / properties / artifacts / description
        Previous value: -"Experiment artifact paths or identifiers."New value: +"Legacy experiment artifact paths. Typed writes should use artifact_references; no values are silently sliced."
      • changedInput schema / properties / artifacts / maxItems
        Previous value: -100New value: +50000
      • addedInput schema / properties / as_of
        Added value: +{
        +  "description": "For context, reconstruct the project and plan view at this effective or recorded time.",
        +  "format": "date-time",
        +  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +  "type": "string"
        +}
      • addedInput schema / properties / asset_id
        Added value: +{
        +  "description": "Stable logical identity. Revisions remain under this ID.",
        +  "maxLength": 500,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / asset_kind
        Added value: +{
        +  "enum": [
        +    "project",
        +    "plan",
        +    "task",
        +    "method",
        +    "experiment",
        +    "attempt",
        +    "arm",
        +    "measurement",
        +    "byte_ledger",
        +    "artifact",
        +    "document",
        +    "decision",
        +    "session"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / before
        Added value: +{
        +  "type": "string"
        +}
      • changedInput schema / properties / body / description
        Previous value: -"Plan body for record_type=plan."New value: +"Complete UTF-8 record body. Typed writes preserve it losslessly and return byte counts plus an exact get route."
      • changedInput schema / properties / body / maxLength
        Previous value: -50000New value: +4194304
      • addedInput schema / properties / body_bytes
        Added value: +{
        +  "description": "UTF-8 bytes to return. Use 0 for metadata-only readback; use a positive value and next_body_offset for exact paging.",
        +  "maximum": 1048576,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / body_offset
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / body_path
        Added value: +{
        +  "description": "Local UTF-8 file for a streamed versioned body attachment up to 256 MiB. Use instead of body; only a compact receipt is returned.",
        +  "maxLength": 4000,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / budget_bytes
        Added value: +{
        +  "maximum": 1000000,
        +  "minimum": 1000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / cancel_reason
        Added value: +{
        +  "maxLength": 500,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / changed_paths
        Added value: +{
        +  "description": "Explicit root-relative files or collection boundaries to re-read. Existing roots and all unlisted entries are preserved.",
        +  "items": {
        +    "properties": {
        +      "path": {
        +        "maxLength": 2000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "root": {
        +        "maxLength": 32,
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "root",
        +      "path"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 100000,
        +  "type": "array"
        +}
      • addedInput schema / properties / correction_reason
        Added value: +{
        +  "maxLength": 2000,
        +  "type": "string"
        +}
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "type": "boolean"
        +}
      • addedInput schema / properties / effective_at
        Added value: +{
        +  "format": "date-time",
        +  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +  "type": "string"
        +}
      • addedInput schema / properties / expected_revision
        Added value: +{
        +  "description": "Optimistic concurrency revision. Stale values return a conflict.",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / fields
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Typed structured fields stored with the record revision. measurement requires metric, value, unit, evaluator_contract, dataset, split, tokenizer, context_length, targets, carrier_precision, and source_locator; byte_ledger requires byte_components, denominator, and scope. Put unknown required values in missing_fields.",
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / filters
        Added value: +{
        +  "description": "Optional project, source, type, role, lane, and recorded-time filters. Excluded lanes are not executed.",
        +  "properties": {
        +    "kinds": {
        +      "items": {
        +        "maxLength": 100,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "maxItems": 20,
        +      "type": "array"
        +    },
        +    "recorded_after": {
        +      "format": "date-time",
        +      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +      "type": "string"
        +    },
        +    "recorded_before": {
        +      "format": "date-time",
        +      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +      "type": "string"
        +    },
        +    "retrieval_lanes": {
        +      "items": {
        +        "enum": [
        +          "exact",
        +          "bm25",
        +          "vector",
        +          "graph"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 4,
        +      "type": "array"
        +    },
        +    "roles": {
        +      "items": {
        +        "enum": [
        +          "experiment_record",
        +          "result",
        +          "method",
        +          "log",
        +          "paper",
        +          "plan",
        +          "config",
        +          "source",
        +          "report",
        +          "other"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 10,
        +      "type": "array"
        +    },
        +    "source_families": {
        +      "items": {
        +        "enum": [
        +          "document",
        +          "code",
        +          "graph"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 3,
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / from_revision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / idempotency_key
        Added value: +{
        +  "description": "Stable operation key. Reuse it after an uncertain response.",
        +  "maxLength": 500,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / job_id
        Added value: +{
        +  "maxLength": 500,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / missing_fields
        Added value: +{
        +  "items": {
        +    "maxLength": 500,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 1000,
        +  "type": "array"
        +}
      • changedInput schema / properties / name / description
        Previous value: -"Project name for create, or entity name lookup for show."New value: +"Project name for create/project_update, or entity name lookup for show."
      • addedInput schema / properties / operation
        Added value: +{
        +  "description": "Typed durable write operation. Use with asset_kind and idempotency_key.",
        +  "enum": [
        +    "create",
        +    "patch",
        +    "append_evidence",
        +    "relocate",
        +    "correct"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / protected
        Added value: +{
        +  "type": "boolean"
        +}
      • addedInput schema / properties / protected_parent_ids
        Added value: +{
        +  "items": {
        +    "maxLength": 500,
        +    "type": "string"
        +  },
        +  "maxItems": 10000,
        +  "type": "array"
        +}
      • addedInput schema / properties / purpose
        Added value: +{
        +  "maxLength": 10000,
        +  "type": "string"
        +}
      • addedInput schema / properties / queries
        Added value: +{
        +  "description": "Independent questions returned as separate ranked groups inside one broker request.",
        +  "items": {
        +    "properties": {
        +      "id": {
        +        "maxLength": 100,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "limit": {
        +        "maximum": 20,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "query": {
        +        "maxLength": 400,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "query_variants": {
        +        "items": {
        +          "maxLength": 400,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 19,
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "id",
        +      "query"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 20,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / record_id
        Added value: +{
        +  "description": "Known exact record or alias ID for get, diff, or verify.",
        +  "maxLength": 500,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / record_ids
        Added value: +{
        +  "items": {
        +    "maxLength": 500,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 100,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / records
        Added value: +{
        +  "items": {
        +    "properties": {
        +      "access_tier": {
        +        "enum": [
        +          "hot",
        +          "warm",
        +          "cold"
        +        ],
        +        "type": "string"
        +      },
        +      "aliases": {
        +        "items": {
        +          "maxLength": 2000,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 1000,
        +        "type": "array"
        +      },
        +      "artifact_references": {
        +        "items": {
        +          "properties": {
        +            "artifact_id": {
        +              "maxLength": 500,
        +              "minLength": 1,
        +              "type": "string"
        +            },
        +            "available": {
        +              "type": "boolean"
        +            },
        +            "content_hash": {
        +              "maxLength": 200,
        +              "type": "string"
        +            },
        +            "location": {
        +              "maxLength": 2000,
        +              "type": "string"
        +            },
        +            "media_type": {
        +              "maxLength": 200,
        +              "type": "string"
        +            },
        +            "member": {
        +              "maxLength": 2000,
        +              "type": "string"
        +            },
        +            "observed_at": {
        +              "format": "date-time",
        +              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +              "type": "string"
        +            },
        +            "path": {
        +              "maxLength": 2000,
        +              "type": "string"
        +            },
        +            "role": {
        +              "maxLength": 200,
        +              "type": "string"
        +            },
        +            "size": {
        +              "maximum": 9007199254740991,
        +              "minimum": 0,
        +              "type": "integer"
        +            },
        +            "verification": {
        +              "enum": [
        +                "declared",
        +                "present",
        +                "hash_verified",
        +                "restore_tested",
        +                "replayed"
        +              ],
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "artifact_id"
        +          ],
        +          "type": "object"
        +        },
        +        "maxItems": 50000,
        +        "type": "array"
        +      },
        +      "asset_id": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "body": {
        +        "maxLength": 4194304,
        +        "type": "string"
        +      },
        +      "body_path": {
        +        "maxLength": 4000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "correction_reason": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "effective_at": {
        +        "format": "date-time",
        +        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +        "type": "string"
        +      },
        +      "evidence_ids": {
        +        "items": {
        +          "maxLength": 500,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 50000,
        +        "type": "array"
        +      },
        +      "expected_revision": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "fields": {
        +        "additionalProperties": {},
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "idempotency_key": {
        +        "maxLength": 500,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "kind": {
        +        "enum": [
        +          "project",
        +          "plan",
        +          "task",
        +          "method",
        +          "experiment",
        +          "attempt",
        +          "arm",
        +          "measurement",
        +          "byte_ledger",
        +          "artifact",
        +          "document",
        +          "decision",
        +          "session"
        +        ],
        +        "type": "string"
        +      },
        +      "missing_fields": {
        +        "items": {
        +          "maxLength": 500,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 1000,
        +        "type": "array"
        +      },
        +      "operation": {
        +        "enum": [
        +          "create",
        +          "patch",
        +          "append_evidence",
        +          "relocate",
        +          "correct"
        +        ],
        +        "type": "string"
        +      },
        +      "protected": {
        +        "type": "boolean"
        +      },
        +      "set_current": {
        +        "type": "boolean"
        +      },
        +      "source_reference": {
        +        "maxLength": 2000,
        +        "type": "string"
        +      },
        +      "source_sequence": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "kind",
        +      "operation",
        +      "idempotency_key"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 100,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / removed_paths
        Added value: +{
        +  "description": "Explicit root-relative entries to remove from the active snapshot. Historical snapshots remain addressable.",
        +  "items": {
        +    "properties": {
        +      "path": {
        +        "maxLength": 2000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "root": {
        +        "maxLength": 32,
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "root",
        +      "path"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 100000,
        +  "type": "array"
        +}
      • addedInput schema / properties / request_id
        Added value: +{
        +  "description": "Caller-chosen ID for one local query. Supply it before a long request so project_memory query_status/query_cancel can inspect or cancel the same operation.",
        +  "maxLength": 200,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / response_budget_bytes
        Added value: +{
        +  "description": "Explicit result-array byte budget. Without an override, summaries adapt to unique result, question and source-family counts. Stored bodies and retrieval scope are not truncated by this budget; envelope metadata is separate.",
        +  "maximum": 1000000,
        +  "minimum": 1000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_deadline_ms
        Added value: +{
        +  "description": "Caller-selected 1-300 second response deadline. Returns available lane results or QUERY_TIMEOUT with request_id. Native reads remain tracked until they settle; stored evidence and writes are unaffected.",
        +  "maximum": 300000,
        +  "minimum": 1000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / revision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / root_mode
        Added value: +{
        +  "enum": [
        +    "merge",
        +    "replace",
        +    "remove"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / roots / description
        Previous value: -"Approved local roots to index. Omit to rebuild derived state from stored sources."New value: +"Approved local roots and optional path-independent role/alias manifest. sync merges roots by default; removal is explicit."
      • addedInput schema / properties / roots / items / properties / manifest
        Added value: +{
        +  "items": {
        +    "properties": {
        +      "aliases": {
        +        "items": {
        +          "maxLength": 2000,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 100,
        +        "type": "array"
        +      },
        +      "path": {
        +        "maxLength": 2000,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "role": {
        +        "enum": [
        +          "experiment_record",
        +          "result",
        +          "method",
        +          "log",
        +          "paper",
        +          "plan",
        +          "config",
        +          "source",
        +          "report",
        +          "other"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "path",
        +      "role"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 100000,
        +  "type": "array"
        +}
      • addedInput schema / properties / roots / items / properties / role
        Added value: +{
        +  "enum": [
        +    "experiment_record",
        +    "result",
        +    "method",
        +    "log",
        +    "paper",
        +    "plan",
        +    "config",
        +    "source",
        +    "report",
        +    "other"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / roots / maxItems
        Previous value: -8New value: +64
      • addedInput schema / properties / set_current
        Added value: +{
        +  "description": "For plan writes, select this revision as current. Defaults to true; use false for historical imports.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / since_revision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / snapshot_path
        Added value: +{
        +  "maxLength": 4000,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / source_reference
        Added value: +{
        +  "maxLength": 2000,
        +  "type": "string"
        +}
      • addedInput schema / properties / source_sequence
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / to_revision
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / user_constraints
        Added value: +{
        +  "items": {
        +    "maxLength": 2000,
        +    "type": "string"
        +  },
        +  "maxItems": 1000,
        +  "type": "array"
        +}
      • changedInput schema / properties / valid_from / pattern
        Previous value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"New value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • changedInput schema / properties / valid_to / pattern
        Previous value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"New value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
      • addedInput schema / properties / verification_level
        Added value: +{
        +  "enum": [
        +    "declared",
        +    "present",
        +    "hash_verified",
        +    "restore_tested",
        +    "replayed"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / wait_timeout_ms
        Added value: +{
        +  "maximum": 60000,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedOutput schema / properties / context
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / current
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / diff
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / doctor
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / error / properties / cancel_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / phase
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / request_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / groups
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "propertyNames": {
        +      "type": "string"
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / imported
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / job
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / query_status
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / receipt
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / receipts
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "propertyNames": {
        +      "type": "string"
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / records
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "propertyNames": {
        +      "type": "string"
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / body_handle
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / index_freshness
        Added value: +{
        +  "enum": [
        +    "current",
        +    "stale"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / record_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / revision_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / source_span
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "end": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "start": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "start",
        +    "end"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / snapshot
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / timeline
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / verification
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
    • Changedproject_memory_search29 fields changed
      • addedInput schema / properties / filters
        Added value: +{
        +  "description": "Optional project, source, type, role, lane, and recorded-time filters. Excluded lanes are not executed.",
        +  "properties": {
        +    "kinds": {
        +      "items": {
        +        "maxLength": 100,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "maxItems": 20,
        +      "type": "array"
        +    },
        +    "recorded_after": {
        +      "format": "date-time",
        +      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +      "type": "string"
        +    },
        +    "recorded_before": {
        +      "format": "date-time",
        +      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +      "type": "string"
        +    },
        +    "retrieval_lanes": {
        +      "items": {
        +        "enum": [
        +          "exact",
        +          "bm25",
        +          "vector",
        +          "graph"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 4,
        +      "type": "array"
        +    },
        +    "roles": {
        +      "items": {
        +        "enum": [
        +          "experiment_record",
        +          "result",
        +          "method",
        +          "log",
        +          "paper",
        +          "plan",
        +          "config",
        +          "source",
        +          "report",
        +          "other"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 10,
        +      "type": "array"
        +    },
        +    "source_families": {
        +      "items": {
        +        "enum": [
        +          "document",
        +          "code",
        +          "graph"
        +        ],
        +        "type": "string"
        +      },
        +      "maxItems": 3,
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedInput schema / properties / queries
        Added value: +{
        +  "description": "Independent questions returned as separate ranked groups inside one broker request.",
        +  "items": {
        +    "properties": {
        +      "id": {
        +        "maxLength": 100,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "limit": {
        +        "maximum": 20,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "query": {
        +        "maxLength": 400,
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "query_variants": {
        +        "items": {
        +          "maxLength": 400,
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 19,
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "id",
        +      "query"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 20,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • changedInput schema / properties / query / description
        Previous value: -"Natural-language query over indexed local project knowledge."New value: +"One natural-language query over indexed local project knowledge. Use queries instead for independent grouped answers."
      • addedInput schema / properties / request_id
        Added value: +{
        +  "description": "Caller-chosen ID for one local query. Supply it before a long request so project_memory query_status/query_cancel can inspect or cancel the same operation.",
        +  "maxLength": 200,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / response_budget_bytes
        Added value: +{
        +  "description": "Explicit result-array byte budget. Without an override, summaries adapt to unique result, question and source-family counts. Stored bodies and retrieval scope are not truncated by this budget; envelope metadata is separate.",
        +  "maximum": 1000000,
        +  "minimum": 1000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_deadline_ms
        Added value: +{
        +  "description": "Caller-selected 1-300 second response deadline. Returns available lane results or QUERY_TIMEOUT with request_id. Native reads remain tracked until they settle; stored evidence and writes are unaffected.",
        +  "maximum": 300000,
        +  "minimum": 1000,
        +  "type": "integer"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "query"
        -]
      • addedOutput schema / properties / context
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / current
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / diff
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / doctor
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / error / properties / cancel_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / phase
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / request_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / groups
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "propertyNames": {
        +      "type": "string"
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / imported
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / job
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / query_status
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / receipt
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / receipts
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "propertyNames": {
        +      "type": "string"
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / records
        Added value: +{
        +  "items": {
        +    "additionalProperties": {},
        +    "propertyNames": {
        +      "type": "string"
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / body_handle
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / index_freshness
        Added value: +{
        +  "enum": [
        +    "current",
        +    "stale"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / record_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / revision_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / source_span
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "end": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "start": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "start",
        +    "end"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / snapshot
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / timeline
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / verification
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
    • Changedscholar_search3 fields changed
      • addedOutput schema / properties / error / properties / cancel_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / phase
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / request_id
        Added value: +{
        +  "type": "string"
        +}
    • Changedsearch8 fields changed
      • addedOutput schema / properties / error / properties / cancel_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / phase
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / request_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / body_handle
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / index_freshness
        Added value: +{
        +  "enum": [
        +    "current",
        +    "stale"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / record_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / revision_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / source_span
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "end": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "start": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "start",
        +    "end"
        +  ],
        +  "type": "object"
        +}
    • Changedsearch_parallel8 fields changed
      • addedOutput schema / properties / error / properties / cancel_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / phase
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / error / properties / request_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / body_handle
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / index_freshness
        Added value: +{
        +  "enum": [
        +    "current",
        +    "stale"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / record_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / revision_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / source_span
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "end": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "start": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "start",
        +    "end"
        +  ],
        +  "type": "object"
        +}
  2. 3 tool updatesv1.0.6
    • Changedproject_memory4 fields changed
      • addedInput schema / properties / detail_level
        Added value: +{
        +  "default": "summary",
        +  "description": "For show with project_id and no target_id, both values return a bounded summary. full is retained only for compatibility and never returns every durable record body.",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / decision_count
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / experiment_count
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / plan_count
        Added value: +{
        +  "type": "number"
        +}
    • Changedproject_memory_search3 fields changed
      • addedOutput schema / properties / decision_count
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / experiment_count
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / plan_count
        Added value: +{
        +  "type": "number"
        +}
    • Changedsearch2 fields changed
      • changedInput schema / properties / response_content / default
        Previous value: -"full"New value: +"summary"
      • changedInput schema / properties / response_content / description
        Previous value: -"Controls only the returned body. full returns up to max_chars; summary returns a 1500-character evidence excerpt. Research storage keeps the full captured text in deterministic chunks."New value: +"Controls only the returned body. summary is the default and returns a 1500-character evidence excerpt; full returns up to max_chars. Research storage keeps the full captured text in deterministic chunks."
  3. 5 tool updatesv1.0.4
    • Changedhealth1 field changed
      • addedOutput schema / properties / nativeBrowser
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
    • Changedproject_memory1 field changed
      • addedInput schema / properties / query_variants
        Added value: +{
        +  "description": "Optional local retrieval variants for action=search. They run inside one broker request and are fused before one rerank.",
        +  "items": {
        +    "maxLength": 400,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 19,
        +  "type": "array"
        +}
    • Changedproject_memory_search1 field changed
      • addedInput schema / properties / query_variants
        Added value: +{
        +  "description": "Optional retrieval variants executed inside this one broker request. Exact identifiers and quoted phrases are added deterministically, candidates are fused with RRF, and the primary query is reranked once. Do not make repeated terminal or tool calls for query variants.",
        +  "items": {
        +    "maxLength": 400,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 19,
        +  "type": "array"
        +}
    • Changedsearch1 field changed
      • changedInput schema / properties / extract_mode / description
        Previous value: -"Content depth in this search call. Use abstract or full during research instead of following search with separate extract calls. For GitHub results, none reads the README; abstract and full use the same repository eligibility gate but index different source amounts."New value: +"Content depth in this search call. Use none only when titles and snippets are enough, abstract for relevance evidence, and full when the user asks to read originals, full text, document bodies, or code, or to compare source contents. Use abstract or full here instead of following search with separate extraction, PDF download, or repository clone. For GitHub results, none reads the README; abstract and full use the same repository eligibility gate but index different source amounts."
    • Changedsearch_parallel1 field changed
      • changedInput schema / properties / extract_mode / description
        Previous value: -"Content depth in this search call. Use abstract or full during research instead of following search with separate extract calls. For GitHub results, none reads the README; abstract and full use the same repository eligibility gate but index different source amounts."New value: +"Content depth in this search call. Use none only when titles and snippets are enough, abstract for relevance evidence, and full when the user asks to read originals, full text, document bodies, or code, or to compare source contents. Use abstract or full here instead of following search with separate extraction, PDF download, or repository clone. For GitHub results, none reads the README; abstract and full use the same repository eligibility gate but index different source amounts."
  4. 6 tool updatesv1.0.2
    • Changedextract4 fields changed
      • changedInput schema / properties / max_chars / description
        Previous value: -"Truncate body to this many chars. Defaults to 1500 for abstract and 50000 for full."New value: +"Maximum returned characters when response_content=full. Defaults to 1500 for abstract and 50000 for full."
      • addedInput schema / properties / response_content
        Added value: +{
        +  "default": "full",
        +  "description": "Controls only the returned body. full returns up to max_chars; summary returns a 1500-character evidence excerpt. Research storage keeps the full captured text in deterministic chunks.",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / source_length
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / truncated
        Added value: +{
        +  "type": "boolean"
        +}
    • Changedproject_memory2 fields changed
      • addedOutput schema / properties / results / items / properties / source_length
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / truncated
        Added value: +{
        +  "type": "boolean"
        +}
    • Changedproject_memory_search2 fields changed
      • addedOutput schema / properties / results / items / properties / source_length
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / truncated
        Added value: +{
        +  "type": "boolean"
        +}
    • Changedscholar_search1 field changed
      • changedInput schema / properties / limit / description
        Previous value: -"Max papers (default 10)."New value: +"Maximum papers. Integer 1-10, default 10."
    • Changedsearch6 fields changed
      • changedInput schema / properties / extract_limit / description
        Previous value: -"Maximum unique result URLs to extract. For parallel search this is one call-wide limit, not a per-query limit."New value: +"Maximum unique result URLs to extract. Integer 1-10, default 5."
      • changedInput schema / properties / limit / description
        Previous value: -"Max results (default 10)."New value: +"Maximum results. Integer 1-20, default 10."
      • changedInput schema / properties / max_chars / description
        Previous value: -"Maximum characters per extracted result. Defaults to 1500 for abstract and 50000 for full."New value: +"Maximum returned characters per extracted result in response_content=full. Defaults to 1500 for abstract and 50000 for full."
      • addedInput schema / properties / response_content
        Added value: +{
        +  "default": "full",
        +  "description": "Controls only the returned body. full returns up to max_chars; summary returns a 1500-character evidence excerpt. Research storage keeps the full captured text in deterministic chunks.",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / source_length
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / truncated
        Added value: +{
        +  "type": "boolean"
        +}
    • Changedsearch_parallel8 fields changed
      • removedInput schema / properties / extract_limit / default
        Removed value: -5
      • changedInput schema / properties / extract_limit / description
        Previous value: -"Maximum unique result URLs to extract. For parallel search this is one call-wide limit, not a per-query limit."New value: +"Call-wide maximum unique result URLs to extract. Integer 1-20, default 12 for abstract; full defaults to and allows at most 10."
      • changedInput schema / properties / extract_limit / maximum
        Previous value: -10New value: +20
      • changedInput schema / properties / limit / description
        Previous value: -"Max results per query."New value: +"Maximum results per query. Integer 1-20, default 10."
      • changedInput schema / properties / max_chars / description
        Previous value: -"Maximum characters per extracted result. Defaults to 1500 for abstract and 50000 for full."New value: +"Maximum returned characters per extracted result in response_content=full. Defaults to 1500 for abstract and 50000 for full."
      • addedInput schema / properties / response_content
        Added value: +{
        +  "default": "summary",
        +  "description": "Controls only returned bodies. summary is the default and returns 1500-character evidence excerpts; full returns up to max_chars. Research storage keeps the full captured text in deterministic chunks.",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / source_length
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / truncated
        Added value: +{
        +  "type": "boolean"
        +}
  5. 8 tool updatesv1.0.0
    • Changedextract23 fields changed
      • removedInput schema / properties / max_chars / default
        Removed value: -8000
      • changedInput schema / properties / max_chars / description
        Previous value: -"Truncate body to this many chars (default 8000, set via SURF_EXTRACT_MAX_CHARS)."New value: +"Truncate body to this many chars. Defaults to 1500 for abstract and 50000 for full."
      • addedInput schema / properties / memory_handle
        Added value: +{
        +  "description": "Reuse the handle returned by a prior project-aware call.",
        +  "format": "uuid",
        +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +  "type": "string"
        +}
      • changedInput schema / properties / mode / description
        Previous value: -"Extraction depth. `full` = whole article body (default; uses Playwright if needed). `abstract` = cheap survey: PDF page 1 OR HTML meta description (~1500 chars); use to triage relevance before paying for full text. `metadata` = page count only (PDF). Academic PDFs (arxiv/biorxiv/Nature/OpenReview/NeurIPS/JMLR/PMLR/Springer/PubMed-via-PMC) are auto-detected; abstract mode skips Playwright for them."New value: +"Extraction depth. `full` = whole article body (default; uses Playwright if needed). `abstract` = cheap survey: PDF page 1 OR HTML meta description (~1500 chars); use to triage relevance before paying for full text. `metadata` = document metadata without body text: title, authors, publication details, dates, DOI, keywords, canonical URL, and PDF properties when available. Academic PDFs (arxiv/biorxiv/Nature/OpenReview/NeurIPS/JMLR/PMLR/Springer/PubMed-via-PMC) are auto-detected; abstract mode skips Playwright for them."
      • addedInput schema / properties / project_id
        Added value: +{
        +  "description": "Project memory id.",
        +  "maxLength": 64,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / session_id
        Added value: +{
        +  "description": "Stable host task id. Reuses the same project session after restart.",
        +  "maxLength": 200,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / session_intent
        Added value: +{
        +  "description": "Current durable task intent. A changed value creates an immutable revision.",
        +  "maxLength": 2000,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedOutput schema / properties / authors
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / canonical_url
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / created_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / creator
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / description
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / doi
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / keywords
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / language
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / memory
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / memory_handle
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / modified_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / producer
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / publication
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / published_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / subject
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / year
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Changedhealth1 field changed
      • addedOutput schema / properties / research
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
    • Addedproject_memory
    • Addedproject_memory_search
    • Changedscholar_search7 fields changed
      • addedInput schema / properties / memory_handle
        Added value: +{
        +  "description": "Reuse the handle returned by a prior project-aware call.",
        +  "format": "uuid",
        +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +  "type": "string"
        +}
      • addedInput schema / properties / project_id
        Added value: +{
        +  "description": "Project memory id.",
        +  "maxLength": 64,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / session_id
        Added value: +{
        +  "description": "Stable host task id. Reuses the same project session after restart.",
        +  "maxLength": 200,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / session_intent
        Added value: +{
        +  "description": "Current durable task intent. A changed value creates an immutable revision.",
        +  "maxLength": 2000,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedOutput schema / properties / memory
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / memory_handle
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / research_context
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "prior_searches": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "query": {
        +            "type": "string"
        +          },
        +          "relation": {
        +            "enum": [
        +              "same",
        +              "related",
        +              "recent"
        +            ],
        +            "type": "string"
        +          },
        +          "results": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "searched_at": {
        +            "type": "string"
        +          },
        +          "surface": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "query",
        +          "relation",
        +          "searched_at",
        +          "results"
        +        ],
        +        "type": "object"
        +      },
        +      "maxItems": 3,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "prior_searches"
        +  ],
        +  "type": "object"
        +}
    • Changedsearch37 fields changed
      • addedInput schema / properties / extract_limit
        Added value: +{
        +  "default": 5,
        +  "description": "Maximum unique result URLs to extract. For parallel search this is one call-wide limit, not a per-query limit.",
        +  "maximum": 10,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / extract_mode
        Added value: +{
        +  "default": "none",
        +  "description": "Content depth in this search call. Use abstract or full during research instead of following search with separate extract calls. For GitHub results, none reads the README; abstract and full use the same repository eligibility gate but index different source amounts.",
        +  "enum": [
        +    "none",
        +    "abstract",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / include_project_ids
        Added value: +{
        +  "description": "Additional read-only projects joined through ontology-aligned schema and identity links. New records stay in project_id.",
        +  "items": {
        +    "maxLength": 64,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 8,
        +  "type": "array"
        +}
      • addedInput schema / properties / max_chars
        Added value: +{
        +  "description": "Maximum characters per extracted result. Defaults to 1500 for abstract and 50000 for full.",
        +  "maximum": 50000,
        +  "minimum": 200,
        +  "type": "integer"
        +}
      • addedInput schema / properties / memory_handle
        Added value: +{
        +  "description": "Reuse the handle returned by a prior project-aware call.",
        +  "format": "uuid",
        +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +  "type": "string"
        +}
      • addedInput schema / properties / project_id
        Added value: +{
        +  "description": "Project memory id.",
        +  "maxLength": 64,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / session_id
        Added value: +{
        +  "description": "Stable host task id. Reuses the same project session after restart.",
        +  "maxLength": 200,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / session_intent
        Added value: +{
        +  "description": "Current durable task intent. A changed value creates an immutable revision.",
        +  "maxLength": 2000,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedOutput schema / properties / memory
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / memory_handle
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / research_context
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "prior_searches": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "query": {
        +            "type": "string"
        +          },
        +          "relation": {
        +            "enum": [
        +              "same",
        +              "related",
        +              "recent"
        +            ],
        +            "type": "string"
        +          },
        +          "results": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "searched_at": {
        +            "type": "string"
        +          },
        +          "surface": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "query",
        +          "relation",
        +          "searched_at",
        +          "results"
        +        ],
        +        "type": "object"
        +      },
        +      "maxItems": 3,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "prior_searches"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / results / items / properties / authors
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / canonical_url
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / content
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / created_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / creator
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / document_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / doi
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / excerpt
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / extract_error
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / extraction_quality
        Added value: +{
        +  "enum": [
        +    "full_text",
        +    "abstract",
        +    "meta_abstract",
        +    "metadata_only"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / fresh_web
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / results / items / properties / is_pdf
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / results / items / properties / keywords
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / language
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / length
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / modified_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / page_count
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / producer
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / project_ids
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / publication
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / published_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / retrieval_families
        Added value: +{
        +  "items": {
        +    "enum": [
        +      "exact",
        +      "bm25",
        +      "vector",
        +      "graph"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / score
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / source_family
        Added value: +{
        +  "enum": [
        +    "live",
        +    "document",
        +    "code",
        +    "graph"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / subject
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / year
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
    • Removedsearch_extract
    • Changedsearch_parallel43 fields changed
      • addedInput schema / properties / extract_limit
        Added value: +{
        +  "default": 5,
        +  "description": "Maximum unique result URLs to extract. For parallel search this is one call-wide limit, not a per-query limit.",
        +  "maximum": 10,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / extract_mode
        Added value: +{
        +  "default": "none",
        +  "description": "Content depth in this search call. Use abstract or full during research instead of following search with separate extract calls. For GitHub results, none reads the README; abstract and full use the same repository eligibility gate but index different source amounts.",
        +  "enum": [
        +    "none",
        +    "abstract",
        +    "full"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / include_project_ids
        Added value: +{
        +  "description": "Additional read-only projects joined through ontology-aligned schema and identity links. New records stay in project_id.",
        +  "items": {
        +    "maxLength": 64,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 8,
        +  "type": "array"
        +}
      • addedInput schema / properties / max_chars
        Added value: +{
        +  "description": "Maximum characters per extracted result. Defaults to 1500 for abstract and 50000 for full.",
        +  "maximum": 50000,
        +  "minimum": 200,
        +  "type": "integer"
        +}
      • addedInput schema / properties / memory_handle
        Added value: +{
        +  "description": "Reuse the handle returned by a prior project-aware call.",
        +  "format": "uuid",
        +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +  "type": "string"
        +}
      • addedInput schema / properties / project_id
        Added value: +{
        +  "description": "Project memory id.",
        +  "maxLength": 64,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / queries / description
        Previous value: -"2-10 queries to run concurrently."New value: +"2-12 independent live queries."
      • addedInput schema / properties / queries / items / maxLength
        Added value: +400
      • addedInput schema / properties / queries / items / minLength
        Added value: +1
      • changedInput schema / properties / queries / maxItems
        Previous value: -10New value: +12
      • changedInput schema / properties / queries / minItems
        Previous value: -1New value: +2
      • addedInput schema / properties / session_id
        Added value: +{
        +  "description": "Stable host task id. Reuses the same project session after restart.",
        +  "maxLength": 200,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / session_intent
        Added value: +{
        +  "description": "Current durable task intent. A changed value creates an immutable revision.",
        +  "maxLength": 2000,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedOutput schema / properties / memory
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / memory_handle
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / research_context
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "prior_searches": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "query": {
        +            "type": "string"
        +          },
        +          "relation": {
        +            "enum": [
        +              "same",
        +              "related",
        +              "recent"
        +            ],
        +            "type": "string"
        +          },
        +          "results": {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          "searched_at": {
        +            "type": "string"
        +          },
        +          "surface": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "query",
        +          "relation",
        +          "searched_at",
        +          "results"
        +        ],
        +        "type": "object"
        +      },
        +      "maxItems": 3,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "prior_searches"
        +  ],
        +  "type": "object"
        +}
      • changedOutput schema / properties / results / items / properties / provider / enum
        Previous value: -[
        -  "browser",
        -  "searchapi"
        -]New value: +[
        +  "browser",
        +  "searchapi",
        +  "local"
        +]
      • addedOutput schema / properties / results / items / properties / results / items / properties / authors
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / canonical_url
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / content
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / created_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / creator
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / document_id
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / doi
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / excerpt
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / extract_error
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / extraction_quality
        Added value: +{
        +  "enum": [
        +    "full_text",
        +    "abstract",
        +    "meta_abstract",
        +    "metadata_only"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / fresh_web
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / is_pdf
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / keywords
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / language
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / length
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / modified_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / page_count
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / producer
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / project_ids
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / publication
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / published_at
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / retrieval_families
        Added value: +{
        +  "items": {
        +    "enum": [
        +      "exact",
        +      "bm25",
        +      "vector",
        +      "graph"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / score
        Added value: +{
        +  "type": "number"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / source_family
        Added value: +{
        +  "enum": [
        +    "live",
        +    "document",
        +    "code",
        +    "graph"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / subject
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / results / items / properties / year
        Added value: +{
        +  "maximum": 9007199254740991,
        +  "minimum": -9007199254740991,
        +  "type": "integer"
        +}
  6. 3 tool updatesv0.8.0
    • Addedscholar_search
    • Changedsearch_extract1 field changed
      • changedInput schema / properties / max_chars / description
        Previous value: -"Truncate each result body. Default depends on mode: ~1500 for abstract, 8000 for full."New value: +"Truncate each result body. Default depends on mode: ~1500 for abstract, 8000 for full (SURF_EXTRACT_MAX_CHARS, capped at 20000 here)."
    • Changedsearch_parallel3 fields changed
      • addedOutput schema / properties / results / items / properties / degraded_reasons
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / results / items / properties / fallback_reason
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / provider
        Added value: +{
        +  "enum": [
        +    "browser",
        +    "searchapi"
        +  ],
        +  "type": "string"
        +}
  7. 1 tool updatev0.6.8
    • Changedextract1 field changed
      • changedInput schema / properties / max_chars / description
        Previous value: -"Truncate body to this many chars (default 8000)."New value: +"Truncate body to this many chars (default 8000, set via SURF_EXTRACT_MAX_CHARS)."
  8. 5 tool updatesv0.6.5
    • Addedextract
    • Addedhealth
    • Addedsearch
    • Addedsearch_extract
    • Addedsearch_parallel
  9. 5 tool updatesv0.6.1
    • Removedextract
    • Removedhealth
    • Removedsearch
    • Removedsearch_extract
    • Removedsearch_parallel
  10. 1 tool updatev0.5.6
    • Changedhealth3 fields changed
      • addedOutput schema / properties / pool
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / selfHealing
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / telemetry
        Added value: +{
        +  "additionalProperties": {},
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
  11. 5 tool updatesv0.5.2
    • Addedextract
    • Addedhealth
    • Addedsearch
    • Addedsearch_extract
    • Addedsearch_parallel
  12. 5 tool updatesv0.5.1
    • Removedextract
    • Removedhealth
    • Removedsearch
    • Removedsearch_extract
    • Removedsearch_parallel
  13. 5 tool updatesv0.4.8
    • Addedextract
    • Addedhealth
    • Addedsearch
    • Addedsearch_extract
    • Addedsearch_parallel

TDQS

A4.4/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a clearly scoped role: search for single-query live lookup, search_parallel for multi-query lookup, extract for known-URL reading, scholar_search for paper metadata, and project_memory_search for local-only retrieval. Even potential overlaps like search's extract_mode vs extract are explicitly separated by whether discovery is still needed.

Naming Consistency3/5

Naming is reasonably readable but not consistent: some tools are bare verbs (search, extract), some are noun+search (scholar_search, project_memory_search), and health is a standalone noun while project_memory is a broad domain name. There is no uniform verb_noun or noun_verb convention across the surface.

Tool Count5/5

Seven tools is well-scoped for the server's purpose: live web search, parallel search, extraction, scholar metadata, local memory search, memory management, and health. Each tool occupies a distinct place, and the count is within the ideal range without redundant or missing entries.

Completeness5/5

The surface covers the full workflow: discover via search, extract via extract or search mode, search scholar metadata, retrieve from local project memory, and manage that memory's full lifecycle. Project_memory is especially thorough, offering writes, updates, timelines, deletion, rollback, snapshots, and diagnostics, so agents should not hit dead ends.

Maintenance

ActivitySlowing
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers