google-surf-mcp
google-surf-mcp
✨Анти-бот MCP для поиска: без API-ключа✨
English | 한국어

Только для демонстрации. По умолчанию реальный поиск выполняется в 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-extrastealthБлокировка ресурсов (изображения / медиа / шрифты) для скорости
Однократная загрузка профиля перед первым запуском
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 bootstrapbootstrap открывает окно 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 |
|
| где хранится прогретый профиль |
|
| локаль браузера |
| системная tz | например, |
|
| установите |
|
| мс простоя перед закрытием последовательного контекста и пула. |
|
| установите |
Устранение неполадок
CAPTCHA: автоматически открывается видимое окно Chrome (работает для всех 4 инструментов). Решите её один раз, выполните один поиск внутри, вызов повторится и продолжится. Чтобы вместо этого быстро завершаться с ошибкой, запускайте без подключенного дисплея.
"Chrome not found": установите Chrome или задайте
CHROME_PATH.Устаревшие селекторы: Google меняет классы. PR приветствуются.
Журнал изменений
См. CHANGELOG.md.
Лицензия
MIT
Available Tools
7 toolsextractKnown 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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) URL. Loopback/private IPs blocked unless SURF_ALLOW_PRIVATE=true. | |
| mode | No | 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. | full |
| max_chars | No | Maximum returned characters when response_content=full. Defaults to 1500 for abstract and 50000 for full. | |
| project_id | No | Project memory id. | |
| session_id | No | Stable host task id. Reuses the same project session after restart. | |
| memory_handle | No | Reuse the handle returned by a prior project-aware call. | |
| session_intent | No | Current durable task intent. A changed value creates an immutable revision. | |
| response_content | No | 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. | full |
Output Schema
| Name | Required | Description |
|---|---|---|
| doi | No | |
| url | No | |
| meta | No | |
| year | No | |
| error | No | |
| title | No | |
| is_pdf | No | |
| length | No | |
| memory | No | |
| authors | No | |
| content | No | |
| creator | No | |
| excerpt | No | |
| subject | No | |
| keywords | No | |
| language | No | |
| producer | No | |
| truncated | No | |
| created_at | No | |
| elapsed_ms | No | |
| page_count | No | |
| description | No | |
| modified_at | No | |
| publication | No | |
| published_at | No | |
| canonical_url | No | |
| memory_handle | No | |
| source_length | No | |
| extraction_quality | No |
TDQS
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.
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.
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.
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.
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.
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 CheckARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| pool | No | |
| cache | No | |
| error | No | |
| config | No | |
| cascade | No | |
| version | No | |
| research | No | |
| telemetry | No | |
| rateLimiter | No | |
| selfHealing | No | |
| nativeBrowser | No |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | Complete UTF-8 record body. Typed writes preserve it losslessly and return byte counts plus an exact get route. | |
| name | No | Project name for create/project_update, or entity name lookup for show. | |
| after | No | ||
| as_of | No | For context, reconstruct the project and plan view at this effective or recorded time. | |
| limit | No | Maximum local RAG results for action=search. | |
| query | No | Required for action=search. Searches stored local knowledge only and does not start live web discovery. | |
| roots | No | Approved local roots and optional path-independent role/alias manifest. sync merges roots by default; removal is explicit. | |
| title | No | Plan title, experiment name, or decision title. | |
| action | Yes | 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. | |
| before | No | ||
| fields | No | 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. | |
| intent | No | Durable intent for record_type=session. | |
| job_id | No | ||
| reason | No | Required reason for any correction. | |
| status | No | Use success, failed, or inconclusive to finish an experiment. Omit or use running when starting it. | |
| aliases | No | Ontology term aliases, or aliases moved during entity_split. | |
| dry_run | No | ||
| filters | No | Optional project, source, type, role, lane, and recorded-time filters. Excluded lanes are not executed. | |
| metrics | No | Terminal experiment metrics. | |
| purpose | No | ||
| queries | No | Independent questions returned as separate ranked groups inside one broker request. | |
| records | No | ||
| summary | No | Experiment result or decision summary. | |
| version | No | Ontology revision number. Defaults to 1 or the superseded term version plus one. | |
| asset_id | No | Stable logical identity. Revisions remain under this ID. | |
| git_root | No | Optional Git root recorded with a rebuild snapshot. | |
| revision | No | ||
| valid_to | No | Corrected assertion valid-time end. | |
| artifacts | No | Legacy experiment artifact paths. Typed writes should use artifact_references; no values are silently sliced. | |
| body_path | No | Local UTF-8 file for a streamed versioned body attachment up to 256 MiB. Use instead of body; only a compact receipt is returned. | |
| operation | No | Typed durable write operation. Use with asset_kind and idempotency_key. | |
| protected | No | ||
| record_id | No | Known exact record or alias ID for get, diff, or verify. | |
| root_mode | No | ||
| target_id | No | Assertion or entity id for show or correction. | |
| asset_kind | No | ||
| body_bytes | No | UTF-8 bytes to return. Use 0 for metadata-only readback; use a positive value and next_body_offset for exact paging. | |
| hypothesis | No | Hypothesis when starting an experiment. | |
| project_id | No | Stable project id. For search, this is the write-isolated primary scope. Omit to list projects or use all_projects. | |
| record_ids | No | ||
| request_id | No | 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. | |
| source_ids | No | Entity ids merged into target_id by entity_merge. | |
| valid_from | No | Corrected assertion valid-time start. | |
| access_tier | No | Operational access tier. It does not rank scientific quality. | |
| body_offset | No | ||
| export_view | No | Initial 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_mode | No | Preview first. Apply requires its confirm_token. Restore reverses deletion. | |
| record_type | No | Required 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. | |
| replacement | No | New assertion value, or new entity name for entity_split. | |
| set_current | No | For plan writes, select this revision as current. Defaults to true; use false for historical imports. | |
| to_revision | No | ||
| all_projects | No | Search or export every active named project. Excludes Inbox and cannot be combined with project ids. | |
| budget_bytes | No | ||
| detail_level | No | 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. | summary |
| effective_at | No | ||
| evidence_ids | No | Evidence retained on a corrected assertion. | |
| cancel_reason | No | ||
| change_reason | No | Reason for a new plan revision. | |
| changed_paths | No | Explicit root-relative files or collection boundaries to re-read. Existing roots and all unlisted entries are preserved. | |
| confirm_token | No | Token returned by the matching forget preview. | |
| experiment_id | No | Experiment to finish or associate with a decision. | |
| export_format | No | Visualization 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_revision | No | ||
| memory_handle | No | Existing project session handle for a session intent revision. | |
| ontology_kind | No | Ontology term kind for record_type=ontology. | |
| removed_paths | No | Explicit root-relative entries to remove from the active snapshot. Historical snapshots remain addressable. | |
| snapshot_path | No | ||
| after_revision | No | ||
| artifact_limit | No | ||
| missing_fields | No | ||
| query_variants | No | Optional local retrieval variants for action=search. They run inside one broker request and are fused before one rerank. | |
| since_revision | No | ||
| artifact_offset | No | ||
| correction_kind | No | Correction operation. Defaults to assertion. | |
| idempotency_key | No | Stable operation key. Reuse it after an uncertain response. | |
| source_sequence | No | ||
| wait_timeout_ms | No | ||
| plan_revision_id | No | Plan revision associated with an experiment or decision. | |
| source_reference | No | ||
| user_constraints | No | ||
| correction_reason | No | ||
| expected_revision | No | Optimistic concurrency revision. Stale values return a conflict. | |
| supersedes_term_id | No | Prior ontology term replaced by this revision. | |
| verification_level | No | ||
| artifact_references | No | ||
| include_project_ids | No | Additional read-only projects for one local search or integrated visualization export. | |
| protected_parent_ids | No | ||
| response_deadline_ms | No | 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. | |
| response_budget_bytes | No | 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. | |
| based_on_experiment_id | No | Experiment that motivated a plan revision. |
Output Schema
| Name | Required | Description |
|---|---|---|
| job | No | |
| diff | No | |
| meta | No | |
| error | No | |
| index | No | |
| plans | No | |
| query | No | |
| doctor | No | |
| entity | No | |
| forget | No | |
| groups | No | |
| memory | No | |
| record | No | |
| context | No | |
| current | No | |
| project | No | |
| receipt | No | |
| records | No | |
| results | No | |
| session | No | |
| entities | No | |
| imported | No | |
| projects | No | |
| receipts | No | |
| snapshot | No | |
| timeline | No | |
| assertion | No | |
| decisions | No | |
| elapsed_ms | No | |
| job_counts | No | |
| plan_count | No | |
| experiments | No | |
| entity_count | No | |
| query_status | No | |
| verification | No | |
| memory_handle | No | |
| session_count | No | |
| visualization | No | |
| decision_count | No | |
| document_count | No | |
| assertion_count | No | |
| correction_count | No | |
| experiment_count | No | |
| search_event_count | No | |
| source_entry_count | No | |
| active_source_snapshot | No | |
| entity_operation_count | No | |
| citation_observation_count | No |
TDQS
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.
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.
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.
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.
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.
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.
project_memory_searchLocal Project Memory SearchARead-onlyIdempotent
LOCAL PROJECT KNOWLEDGE SEARCH ONLY. With research enabled, one local broker lets multiple MCP sessions query the same knowledge base concurrently and orders writes safely. Always use this tool when the user asks to find, recall, inspect, or search information already stored in project memory, indexed local roots, papers, codebases, plans, experiments, or decisions. Use query_variants for multiple retrieval angles in one call instead of opening terminals or calling this tool repeatedly. Query embeddings are batched, candidates are fused with RRF, graph expansion starts from retrieved evidence, and the primary query is reranked once. Only bounded query-focused summaries from that final ranking are returned; stored bodies never bypass this response gate. If one retrieval lane times out, the other lanes still return and meta.degraded_lanes identifies the partial lane; do not repeat the same query automatically. Uses exact, BM25, vector, and graph retrieval. It never opens Google, a browser, or SearchApi. Use search or search_parallel only when new external information is required.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum local RAG results. | |
| query | No | One natural-language query over indexed local project knowledge. Use queries instead for independent grouped answers. | |
| filters | No | Optional project, source, type, role, lane, and recorded-time filters. Excluded lanes are not executed. | |
| queries | No | Independent questions returned as separate ranked groups inside one broker request. | |
| project_id | No | Primary project to search. Required unless all_projects=true. | |
| request_id | No | 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. | |
| all_projects | No | Search every active named project. Excludes Inbox and cannot be combined with project ids. | |
| query_variants | No | 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. | |
| include_project_ids | No | Additional read-only projects searched with the primary project. | |
| response_deadline_ms | No | 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. | |
| response_budget_bytes | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| job | No | |
| diff | No | |
| meta | No | |
| error | No | |
| index | No | |
| plans | No | |
| query | No | |
| doctor | No | |
| entity | No | |
| forget | No | |
| groups | No | |
| memory | No | |
| record | No | |
| context | No | |
| current | No | |
| project | No | |
| receipt | No | |
| records | No | |
| results | No | |
| session | No | |
| entities | No | |
| imported | No | |
| projects | No | |
| receipts | No | |
| snapshot | No | |
| timeline | No | |
| assertion | No | |
| decisions | No | |
| elapsed_ms | No | |
| job_counts | No | |
| plan_count | No | |
| experiments | No | |
| entity_count | No | |
| query_status | No | |
| verification | No | |
| memory_handle | No | |
| session_count | No | |
| visualization | No | |
| decision_count | No | |
| document_count | No | |
| assertion_count | No | |
| correction_count | No | |
| experiment_count | No | |
| search_event_count | No | |
| source_entry_count | No | |
| active_source_snapshot | No | |
| entity_operation_count | No | |
| citation_observation_count | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already show readOnlyHint=true, openWorldHint=false, and idempotentHint=true, and the description adds substantial non-obvious behavior: broker-based concurrency and write ordering, RRF fusion and reranking, the response gate that returns only bounded summaries, degraded-lane timeout behavior, and the explicit guarantee that it never opens external sources. No contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening line is emphatic and front-loaded, and the paragraph is dense rather than padded. Some redundancy exists (retrieval lanes are named both as behavior and as a parameter concept), and the broker/concurrency sentence is useful context but not essential to invoking the tool. Overall, nearly every sentence earns its place, though a slightly tighter structure would improve scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter tool with nested objects and an output schema, the description covers the critical contexts: when to choose it, what it will not do, how failures surface, how results are bounded, and how variants/timeouts behave. The schema already documents parameter details, so the description does not need to repeat them; nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds operational meaning beyond parameter names: query_variants is framed as the preferred way to get multiple retrieval angles, its batching/RRF/rerank behavior is described, and response_deadline_ms semantics are tied to QUERY_TIMEOUT and request_id. This is meaningful value on top of the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: searching local project knowledge, and immediately scopes it with 'LOCAL PROJECT KNOWLEDGE SEARCH ONLY.' It explicitly lists user intents that should route here (find, recall, inspect, search) and contrasts itself with external search tools, so an agent can distinguish it from siblings without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit when-to-use rule ('Always use this tool when the user asks to find, recall, inspect, or search information already stored in project memory...') and an explicit exclusion ('Use search or search_parallel only when new external information is required'). It also instructs the agent to prefer query_variants over repeated calls and tells it not to auto-retry after degraded lanes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scholar_searchGoogle Scholar SearchA
Use only for paper metadata such as authors, venue, year, versions, and citation counts. With research enabled, one local broker lets multiple MCP sessions query the same knowledge base concurrently and orders writes safely. Do not use it to discover or read paper content; use search with extract_mode instead. Returns title, authors, publication, year, snippet, citation count, related/version links, and an available full-text link. With research enabled, metadata and citation observations retain provider provenance and research_context exposes related prior searches. Google Scholar uses browser search, SearchApi primary, or configured fallback. Results are cached with the same TTL as search. Max 10 papers per call.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum papers. Integer 1-10, default 10. | |
| query | Yes | Google Scholar query. Supports quotes and author: operators. | |
| project_id | No | Project memory id. | |
| session_id | No | Stable host task id. Reuses the same project session after restart. | |
| memory_handle | No | Reuse the handle returned by a prior project-aware call. | |
| session_intent | No | Current durable task intent. A changed value creates an immutable revision. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| error | No | |
| query | No | |
| memory | No | |
| results | No | |
| elapsed_ms | No | |
| memory_handle | No | |
| research_context | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral detail beyond the annotations, such as the underlying provider chain ('browser search, SearchApi primary, or configured fallback'), caching behavior ('cached with the same TTL as search'), and output contents like full-text links. It also hints at write behavior ('orders writes safely'), which is consistent with readOnlyHint=false. The research-enabled concurrency and provenance details are less directly actionable but still informative.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the most important usage boundary, but it includes dense and somewhat tangential clauses about 'research enabled' behavior, provenance, and broker concurrency that blur the core message. It is not overly long, yet it could be tightened by separating the essential selection guidance from optional background details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core use case, exclusions, alternative tools, output fields, provider behavior, caching, and a hard result limit. Given the rich input and output schemas already present, only minor gaps remain—such as the precise effect of the research-mode parameters on writes—but nothing essential for typical tool selection and invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all six parameters thoroughly. The description repeats the max limit ('Max 10 papers per call') but does not add much meaning for parameters like project_id, session_id, memory_handle, or session_intent beyond what the schema already states. This lands at the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that this tool is for paper metadata retrieval only, listing specific fields like authors, venue, year, versions, and citation counts. It also explicitly contrasts itself with 'search with extract_mode' for reading full paper content, making its scope unmistakable relative to sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives direct usage boundaries: 'Use only for paper metadata' and 'Do not use it to discover or read paper content; use search with extract_mode instead.' It names the alternative tool and the condition for choosing it, leaving no ambiguity about when scholar_search is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchWeb Search and ExtractA
PRIMARY SINGLE-QUERY LIVE DISCOVERY AND CONTENT INGESTION TOOL. ALWAYS PERFORMS LIVE WEB SEARCH. 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 new external information from Google, public websites, papers, or repositories is required. When the task requires both finding and 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. Providing project_id also fuses stored project evidence with live results, but never makes this a local-only search. For stored project knowledge without live web discovery, use project_memory_search. limit accepts integers from 1 to 20. extract_limit accepts integers from 1 to 10, defaults to 5, and limits unique extracted URLs. Final results use one bounded response budget after ranking; 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, live web, exact, BM25, vector, code, and graph lanes are fused by RRF and one reranker. With research disabled, provider order and query BM25 rank are fused by a lightweight in-memory RRF reranker without opening local storage or loading the vector model. research_context returns up to three prior searches for deeper or adjacent follow-up work. Captured search, source, session, and project provenance form data lineage; extracted bodies become evidence while unread hits remain metadata. include_project_ids adds read-only cross-project retrieval through versioned ontology and verified schema/entity links without merging records. Browser search is the no-key default and SearchApi is the configured primary or fallback provider. Results are cached for 24h unless the TTL is disabled.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results. Integer 1-20, default 10. | |
| query | Yes | Google search query. Use site: filters and quotes for exact match. | |
| max_chars | No | Maximum returned characters per extracted result in response_content=full. Defaults to 1500 for abstract and 50000 for full. | |
| project_id | No | Project memory id. | |
| session_id | No | Stable host task id. Reuses the same project session after restart. | |
| extract_mode | No | 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. | none |
| extract_limit | No | Maximum unique result URLs to extract. Integer 1-10, default 5. | |
| memory_handle | No | Reuse the handle returned by a prior project-aware call. | |
| session_intent | No | Current durable task intent. A changed value creates an immutable revision. | |
| response_content | No | 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. | summary |
| include_project_ids | No | Additional read-only projects joined through ontology-aligned schema and identity links. New records stay in project_id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| error | No | |
| query | No | |
| memory | No | |
| results | No | |
| elapsed_ms | No | |
| memory_handle | No | |
| research_context | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide readOnlyHint=false, openWorldHint=true, and idempotentHint=false, but the description adds substantial behavioral context: it performs live web searches, caches results for 24h, describes response fields (applied, skipped, truncated, total_chars, bounded remaining_urls), explains research-mode fusion, and notes provenance tracking. None of this contradicts the annotations; it enriches them significantly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a dense single paragraph of over 300 words. While every sentence adds value, the lack of structure (no bullets, headings, or logical breaks) makes it hard to scan. It front-loads the primary purpose well, but the sheer length and monolithic formatting hurt readability. It is informative but not concise or well-organized, so a 3 is appropriate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (11 parameters, enums, output schema, multiple modes), the description is remarkably complete. It covers use cases, extraction modes, research-mode behavior, caching, response structure, provenance, and sibling differentiation. The output schema exists, so return values are documented there. Nothing critical for an agent to correctly invoke the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents all 11 parameters (coverage 100%), so the baseline is 3. However, the description adds meaning beyond the schema: it clarifies when to set extract_mode (abstract vs full), explains the relationship between extract_limit and unique URLs, details the effect of response_content, and describes how include_project_ids works with read-only cross-project retrieval. This goes beyond what the schema's individual descriptions provide, justifying a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'PRIMARY SINGLE-QUERY LIVE DISCOVERY AND CONTENT INGESTION TOOL. ALWAYS PERFORMS LIVE WEB SEARCH.' which states a specific verb, resource, and scope. It explicitly contrasts itself with siblings like project_memory_search and extract, clarifying it is for external live information only. This removes any ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use criteria: 'Use this tool only when new external information from Google, public websites, papers, or repositories is required.' It also names alternatives and conditions, such as 'Use extract separately only when the exact public URL is already known' and 'For stored project knowledge without live web discovery, use project_memory_search.' This is textbook usage guidance with clear exclusions.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results per query. Integer 1-20, default 10. | |
| queries | Yes | 2-12 independent live queries. | |
| max_chars | No | Maximum returned characters per extracted result in response_content=full. Defaults to 1500 for abstract and 50000 for full. | |
| project_id | No | Project memory id. | |
| session_id | No | Stable host task id. Reuses the same project session after restart. | |
| extract_mode | No | 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. | none |
| extract_limit | No | Call-wide maximum unique result URLs to extract. Integer 1-20, default 12 for abstract; full defaults to and allows at most 10. | |
| memory_handle | No | Reuse the handle returned by a prior project-aware call. | |
| session_intent | No | Current durable task intent. A changed value creates an immutable revision. | |
| response_content | No | 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. | summary |
| include_project_ids | No | Additional read-only projects joined through ontology-aligned schema and identity links. New records stay in project_id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | |
| error | No | |
| memory | No | |
| results | No | |
| elapsed_ms | No | |
| memory_handle | No | |
| research_context | No |
TDQS
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.
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.
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.
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.
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.
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.
7 tool updates
v1.1.3- Changed
extract1 field changed- changed
Output schema / properties / error / anyOfPrevious 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" + } +]
- Changed
health3 fields changed- added
Output schema / properties / error / properties / cancel_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / phaseAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / request_idAdded value: +{ + "type": "string" +}
- Changed
project_memory84 fields changed- added
Input schema / properties / access_tierAdded value: +{ + "description": "Operational access tier. It does not rank scientific quality.", + "enum": [ + "hot", + "warm", + "cold" + ], + "type": "string" +} - changed
Input schema / properties / action / descriptionPrevious 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." - changed
Input schema / properties / action / enumPrevious 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" +] - added
Input schema / properties / afterAdded value: +{ + "type": "string" +} - added
Input schema / properties / after_revisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / artifact_limitAdded value: +{ + "maximum": 1000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / artifact_offsetAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / artifact_referencesAdded 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" +} - changed
Input schema / properties / artifacts / descriptionPrevious value: -"Experiment artifact paths or identifiers."New value: +"Legacy experiment artifact paths. Typed writes should use artifact_references; no values are silently sliced." - changed
Input schema / properties / artifacts / maxItemsPrevious value: -100New value: +50000 - added
Input schema / properties / as_ofAdded 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" +} - added
Input schema / properties / asset_idAdded value: +{ + "description": "Stable logical identity. Revisions remain under this ID.", + "maxLength": 500, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / asset_kindAdded value: +{ + "enum": [ + "project", + "plan", + "task", + "method", + "experiment", + "attempt", + "arm", + "measurement", + "byte_ledger", + "artifact", + "document", + "decision", + "session" + ], + "type": "string" +} - added
Input schema / properties / beforeAdded value: +{ + "type": "string" +} - changed
Input schema / properties / body / descriptionPrevious 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." - changed
Input schema / properties / body / maxLengthPrevious value: -50000New value: +4194304 - added
Input schema / properties / body_bytesAdded 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" +} - added
Input schema / properties / body_offsetAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / body_pathAdded 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" +} - added
Input schema / properties / budget_bytesAdded value: +{ + "maximum": 1000000, + "minimum": 1000, + "type": "integer" +} - added
Input schema / properties / cancel_reasonAdded value: +{ + "maxLength": 500, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / changed_pathsAdded 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" +} - added
Input schema / properties / correction_reasonAdded value: +{ + "maxLength": 2000, + "type": "string" +} - added
Input schema / properties / dry_runAdded value: +{ + "type": "boolean" +} - added
Input schema / properties / effective_atAdded 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" +} - added
Input schema / properties / expected_revisionAdded value: +{ + "description": "Optimistic concurrency revision. Stale values return a conflict.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / fieldsAdded 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" +} - added
Input schema / properties / filtersAdded 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" +} - added
Input schema / properties / from_revisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / idempotency_keyAdded value: +{ + "description": "Stable operation key. Reuse it after an uncertain response.", + "maxLength": 500, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / job_idAdded value: +{ + "maxLength": 500, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / missing_fieldsAdded value: +{ + "items": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "maxItems": 1000, + "type": "array" +} - changed
Input schema / properties / name / descriptionPrevious 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." - added
Input schema / properties / operationAdded value: +{ + "description": "Typed durable write operation. Use with asset_kind and idempotency_key.", + "enum": [ + "create", + "patch", + "append_evidence", + "relocate", + "correct" + ], + "type": "string" +} - added
Input schema / properties / protectedAdded value: +{ + "type": "boolean" +} - added
Input schema / properties / protected_parent_idsAdded value: +{ + "items": { + "maxLength": 500, + "type": "string" + }, + "maxItems": 10000, + "type": "array" +} - added
Input schema / properties / purposeAdded value: +{ + "maxLength": 10000, + "type": "string" +} - added
Input schema / properties / queriesAdded 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" +} - added
Input schema / properties / record_idAdded value: +{ + "description": "Known exact record or alias ID for get, diff, or verify.", + "maxLength": 500, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / record_idsAdded value: +{ + "items": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "maxItems": 100, + "minItems": 1, + "type": "array" +} - added
Input schema / properties / recordsAdded 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" +} - added
Input schema / properties / removed_pathsAdded 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" +} - added
Input schema / properties / request_idAdded 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" +} - added
Input schema / properties / response_budget_bytesAdded 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" +} - added
Input schema / properties / response_deadline_msAdded 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" +} - added
Input schema / properties / revisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / root_modeAdded value: +{ + "enum": [ + "merge", + "replace", + "remove" + ], + "type": "string" +} - changed
Input schema / properties / roots / descriptionPrevious 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." - added
Input schema / properties / roots / items / properties / manifestAdded 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" +} - added
Input schema / properties / roots / items / properties / roleAdded value: +{ + "enum": [ + "experiment_record", + "result", + "method", + "log", + "paper", + "plan", + "config", + "source", + "report", + "other" + ], + "type": "string" +} - changed
Input schema / properties / roots / maxItemsPrevious value: -8New value: +64 - added
Input schema / properties / set_currentAdded value: +{ + "description": "For plan writes, select this revision as current. Defaults to true; use false for historical imports.", + "type": "boolean" +} - added
Input schema / properties / since_revisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / snapshot_pathAdded value: +{ + "maxLength": 4000, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / source_referenceAdded value: +{ + "maxLength": 2000, + "type": "string" +} - added
Input schema / properties / source_sequenceAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / to_revisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / user_constraintsAdded value: +{ + "items": { + "maxLength": 2000, + "type": "string" + }, + "maxItems": 1000, + "type": "array" +} - changed
Input schema / properties / valid_from / patternPrevious 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)))$" - changed
Input schema / properties / valid_to / patternPrevious 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)))$" - added
Input schema / properties / verification_levelAdded value: +{ + "enum": [ + "declared", + "present", + "hash_verified", + "restore_tested", + "replayed" + ], + "type": "string" +} - added
Input schema / properties / wait_timeout_msAdded value: +{ + "maximum": 60000, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / contextAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / currentAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / diffAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / doctorAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / error / properties / cancel_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / phaseAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / request_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / groupsAdded value: +{ + "items": { + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / importedAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / jobAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / query_statusAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / receiptAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / receiptsAdded value: +{ + "items": { + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / recordsAdded value: +{ + "items": { + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / body_handleAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / index_freshnessAdded value: +{ + "enum": [ + "current", + "stale" + ], + "type": "string" +} - added
Output schema / properties / results / items / properties / record_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / revision_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / source_spanAdded value: +{ + "additionalProperties": false, + "properties": { + "end": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "start": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "start", + "end" + ], + "type": "object" +} - added
Output schema / properties / snapshotAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / timelineAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / verificationAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +}
- Changed
project_memory_search29 fields changed- added
Input schema / properties / filtersAdded 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" +} - added
Input schema / properties / queriesAdded 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" +} - changed
Input schema / properties / query / descriptionPrevious 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." - added
Input schema / properties / request_idAdded 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" +} - added
Input schema / properties / response_budget_bytesAdded 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" +} - added
Input schema / properties / response_deadline_msAdded 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" +} - removed
Input schema / requiredRemoved value: -[ - "query" -] - added
Output schema / properties / contextAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / currentAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / diffAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / doctorAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / error / properties / cancel_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / phaseAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / request_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / groupsAdded value: +{ + "items": { + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / importedAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / jobAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / query_statusAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / receiptAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / receiptsAdded value: +{ + "items": { + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / recordsAdded value: +{ + "items": { + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / body_handleAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / index_freshnessAdded value: +{ + "enum": [ + "current", + "stale" + ], + "type": "string" +} - added
Output schema / properties / results / items / properties / record_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / revision_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / source_spanAdded value: +{ + "additionalProperties": false, + "properties": { + "end": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "start": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "start", + "end" + ], + "type": "object" +} - added
Output schema / properties / snapshotAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / timelineAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / verificationAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +}
- Changed
scholar_search3 fields changed- added
Output schema / properties / error / properties / cancel_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / phaseAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / request_idAdded value: +{ + "type": "string" +}
- Changed
search8 fields changed- added
Output schema / properties / error / properties / cancel_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / phaseAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / request_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / body_handleAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / index_freshnessAdded value: +{ + "enum": [ + "current", + "stale" + ], + "type": "string" +} - added
Output schema / properties / results / items / properties / record_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / revision_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / source_spanAdded value: +{ + "additionalProperties": false, + "properties": { + "end": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "start": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "start", + "end" + ], + "type": "object" +}
- Changed
search_parallel8 fields changed- added
Output schema / properties / error / properties / cancel_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / phaseAdded value: +{ + "type": "string" +} - added
Output schema / properties / error / properties / request_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / body_handleAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / index_freshnessAdded value: +{ + "enum": [ + "current", + "stale" + ], + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / record_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / revision_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / source_spanAdded value: +{ + "additionalProperties": false, + "properties": { + "end": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "start": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "start", + "end" + ], + "type": "object" +}
3 tool updates
v1.0.6- Changed
project_memory4 fields changed- added
Input schema / properties / detail_levelAdded 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" +} - added
Output schema / properties / decision_countAdded value: +{ + "type": "number" +} - added
Output schema / properties / experiment_countAdded value: +{ + "type": "number" +} - added
Output schema / properties / plan_countAdded value: +{ + "type": "number" +}
- Changed
project_memory_search3 fields changed- added
Output schema / properties / decision_countAdded value: +{ + "type": "number" +} - added
Output schema / properties / experiment_countAdded value: +{ + "type": "number" +} - added
Output schema / properties / plan_countAdded value: +{ + "type": "number" +}
- Changed
search2 fields changed- changed
Input schema / properties / response_content / defaultPrevious value: -"full"New value: +"summary" - changed
Input schema / properties / response_content / descriptionPrevious 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."
5 tool updates
v1.0.4- Changed
health1 field changed- added
Output schema / properties / nativeBrowserAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +}
- Changed
project_memory1 field changed- added
Input schema / properties / query_variantsAdded 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" +}
- Changed
project_memory_search1 field changed- added
Input schema / properties / query_variantsAdded 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" +}
- Changed
search1 field changed- changed
Input schema / properties / extract_mode / descriptionPrevious 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."
- Changed
search_parallel1 field changed- changed
Input schema / properties / extract_mode / descriptionPrevious 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."
6 tool updates
v1.0.2- Changed
extract4 fields changed- changed
Input schema / properties / max_chars / descriptionPrevious 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." - added
Input schema / properties / response_contentAdded 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" +} - added
Output schema / properties / source_lengthAdded value: +{ + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "type": "boolean" +}
- Changed
project_memory2 fields changed- added
Output schema / properties / results / items / properties / source_lengthAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / truncatedAdded value: +{ + "type": "boolean" +}
- Changed
project_memory_search2 fields changed- added
Output schema / properties / results / items / properties / source_lengthAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / truncatedAdded value: +{ + "type": "boolean" +}
- Changed
scholar_search1 field changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Max papers (default 10)."New value: +"Maximum papers. Integer 1-10, default 10."
- Changed
search6 fields changed- changed
Input schema / properties / extract_limit / descriptionPrevious 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." - changed
Input schema / properties / limit / descriptionPrevious value: -"Max results (default 10)."New value: +"Maximum results. Integer 1-20, default 10." - changed
Input schema / properties / max_chars / descriptionPrevious 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." - added
Input schema / properties / response_contentAdded 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" +} - added
Output schema / properties / results / items / properties / source_lengthAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / truncatedAdded value: +{ + "type": "boolean" +}
- Changed
search_parallel8 fields changed- removed
Input schema / properties / extract_limit / defaultRemoved value: -5 - changed
Input schema / properties / extract_limit / descriptionPrevious 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." - changed
Input schema / properties / extract_limit / maximumPrevious value: -10New value: +20 - changed
Input schema / properties / limit / descriptionPrevious value: -"Max results per query."New value: +"Maximum results per query. Integer 1-20, default 10." - changed
Input schema / properties / max_chars / descriptionPrevious 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." - added
Input schema / properties / response_contentAdded 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" +} - added
Output schema / properties / results / items / properties / results / items / properties / source_lengthAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / results / items / properties / truncatedAdded value: +{ + "type": "boolean" +}
8 tool updates
v1.0.0- Changed
extract23 fields changed- removed
Input schema / properties / max_chars / defaultRemoved value: -8000 - changed
Input schema / properties / max_chars / descriptionPrevious 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." - added
Input schema / properties / memory_handleAdded 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" +} - changed
Input schema / properties / mode / descriptionPrevious 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." - added
Input schema / properties / project_idAdded value: +{ + "description": "Project memory id.", + "maxLength": 64, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / session_idAdded value: +{ + "description": "Stable host task id. Reuses the same project session after restart.", + "maxLength": 200, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / session_intentAdded value: +{ + "description": "Current durable task intent. A changed value creates an immutable revision.", + "maxLength": 2000, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / authorsAdded value: +{ + "type": "string" +} - added
Output schema / properties / canonical_urlAdded value: +{ + "type": "string" +} - added
Output schema / properties / created_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / creatorAdded value: +{ + "type": "string" +} - added
Output schema / properties / descriptionAdded value: +{ + "type": "string" +} - added
Output schema / properties / doiAdded value: +{ + "type": "string" +} - added
Output schema / properties / keywordsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / languageAdded value: +{ + "type": "string" +} - added
Output schema / properties / memoryAdded value: +{ + "type": "string" +} - added
Output schema / properties / memory_handleAdded value: +{ + "type": "string" +} - added
Output schema / properties / modified_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / producerAdded value: +{ + "type": "string" +} - added
Output schema / properties / publicationAdded value: +{ + "type": "string" +} - added
Output schema / properties / published_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / subjectAdded value: +{ + "type": "string" +} - added
Output schema / properties / yearAdded value: +{ + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +}
- Changed
health1 field changed- added
Output schema / properties / researchAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +}
- Added
project_memory - Added
project_memory_search - Changed
scholar_search7 fields changed- added
Input schema / properties / memory_handleAdded 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" +} - added
Input schema / properties / project_idAdded value: +{ + "description": "Project memory id.", + "maxLength": 64, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / session_idAdded value: +{ + "description": "Stable host task id. Reuses the same project session after restart.", + "maxLength": 200, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / session_intentAdded value: +{ + "description": "Current durable task intent. A changed value creates an immutable revision.", + "maxLength": 2000, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / memoryAdded value: +{ + "type": "string" +} - added
Output schema / properties / memory_handleAdded value: +{ + "type": "string" +} - added
Output schema / properties / research_contextAdded 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" +}
- Changed
search37 fields changed- added
Input schema / properties / extract_limitAdded 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" +} - added
Input schema / properties / extract_modeAdded 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" +} - added
Input schema / properties / include_project_idsAdded 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" +} - added
Input schema / properties / max_charsAdded value: +{ + "description": "Maximum characters per extracted result. Defaults to 1500 for abstract and 50000 for full.", + "maximum": 50000, + "minimum": 200, + "type": "integer" +} - added
Input schema / properties / memory_handleAdded 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" +} - added
Input schema / properties / project_idAdded value: +{ + "description": "Project memory id.", + "maxLength": 64, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / session_idAdded value: +{ + "description": "Stable host task id. Reuses the same project session after restart.", + "maxLength": 200, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / session_intentAdded value: +{ + "description": "Current durable task intent. A changed value creates an immutable revision.", + "maxLength": 2000, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / memoryAdded value: +{ + "type": "string" +} - added
Output schema / properties / memory_handleAdded value: +{ + "type": "string" +} - added
Output schema / properties / research_contextAdded 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" +} - added
Output schema / properties / results / items / properties / authorsAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / canonical_urlAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / contentAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / created_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / creatorAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / document_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / doiAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / excerptAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / extract_errorAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / extraction_qualityAdded value: +{ + "enum": [ + "full_text", + "abstract", + "meta_abstract", + "metadata_only" + ], + "type": "string" +} - added
Output schema / properties / results / items / properties / fresh_webAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / results / items / properties / is_pdfAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / results / items / properties / keywordsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / languageAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / lengthAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / modified_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / page_countAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / producerAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / project_idsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / publicationAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / published_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / retrieval_familiesAdded value: +{ + "items": { + "enum": [ + "exact", + "bm25", + "vector", + "graph" + ], + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / scoreAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / source_familyAdded value: +{ + "enum": [ + "live", + "document", + "code", + "graph" + ], + "type": "string" +} - added
Output schema / properties / results / items / properties / subjectAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / yearAdded value: +{ + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +}
- Removed
search_extract - Changed
search_parallel43 fields changed- added
Input schema / properties / extract_limitAdded 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" +} - added
Input schema / properties / extract_modeAdded 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" +} - added
Input schema / properties / include_project_idsAdded 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" +} - added
Input schema / properties / max_charsAdded value: +{ + "description": "Maximum characters per extracted result. Defaults to 1500 for abstract and 50000 for full.", + "maximum": 50000, + "minimum": 200, + "type": "integer" +} - added
Input schema / properties / memory_handleAdded 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" +} - added
Input schema / properties / project_idAdded value: +{ + "description": "Project memory id.", + "maxLength": 64, + "minLength": 1, + "type": "string" +} - changed
Input schema / properties / queries / descriptionPrevious value: -"2-10 queries to run concurrently."New value: +"2-12 independent live queries." - added
Input schema / properties / queries / items / maxLengthAdded value: +400 - added
Input schema / properties / queries / items / minLengthAdded value: +1 - changed
Input schema / properties / queries / maxItemsPrevious value: -10New value: +12 - changed
Input schema / properties / queries / minItemsPrevious value: -1New value: +2 - added
Input schema / properties / session_idAdded value: +{ + "description": "Stable host task id. Reuses the same project session after restart.", + "maxLength": 200, + "minLength": 1, + "type": "string" +} - added
Input schema / properties / session_intentAdded value: +{ + "description": "Current durable task intent. A changed value creates an immutable revision.", + "maxLength": 2000, + "minLength": 1, + "type": "string" +} - added
Output schema / properties / memoryAdded value: +{ + "type": "string" +} - added
Output schema / properties / memory_handleAdded value: +{ + "type": "string" +} - added
Output schema / properties / research_contextAdded 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" +} - changed
Output schema / properties / results / items / properties / provider / enumPrevious value: -[ - "browser", - "searchapi" -]New value: +[ + "browser", + "searchapi", + "local" +] - added
Output schema / properties / results / items / properties / results / items / properties / authorsAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / canonical_urlAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / contentAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / created_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / creatorAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / document_idAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / doiAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / excerptAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / extract_errorAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / extraction_qualityAdded value: +{ + "enum": [ + "full_text", + "abstract", + "meta_abstract", + "metadata_only" + ], + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / fresh_webAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / results / items / properties / results / items / properties / is_pdfAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / results / items / properties / results / items / properties / keywordsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / results / items / properties / languageAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / lengthAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / results / items / properties / modified_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / page_countAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / results / items / properties / producerAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / project_idsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / results / items / properties / publicationAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / published_atAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / retrieval_familiesAdded value: +{ + "items": { + "enum": [ + "exact", + "bm25", + "vector", + "graph" + ], + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / results / items / properties / scoreAdded value: +{ + "type": "number" +} - added
Output schema / properties / results / items / properties / results / items / properties / source_familyAdded value: +{ + "enum": [ + "live", + "document", + "code", + "graph" + ], + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / subjectAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / results / items / properties / yearAdded value: +{ + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +}
3 tool updates
v0.8.0- Added
scholar_search - Changed
search_extract1 field changed- changed
Input schema / properties / max_chars / descriptionPrevious 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)."
- Changed
search_parallel3 fields changed- added
Output schema / properties / results / items / properties / degraded_reasonsAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Output schema / properties / results / items / properties / fallback_reasonAdded value: +{ + "type": "string" +} - added
Output schema / properties / results / items / properties / providerAdded value: +{ + "enum": [ + "browser", + "searchapi" + ], + "type": "string" +}
1 tool update
v0.6.8- Changed
extract1 field changed- changed
Input schema / properties / max_chars / descriptionPrevious 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)."
5 tool updates
v0.6.5- Added
extract - Added
health - Added
search - Added
search_extract - Added
search_parallel
5 tool updates
v0.6.1- Removed
extract - Removed
health - Removed
search - Removed
search_extract - Removed
search_parallel
1 tool update
v0.5.6- Changed
health3 fields changed- added
Output schema / properties / poolAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / selfHealingAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +} - added
Output schema / properties / telemetryAdded value: +{ + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" +}
5 tool updates
v0.5.2- Added
extract - Added
health - Added
search - Added
search_extract - Added
search_parallel
5 tool updates
v0.5.1- Removed
extract - Removed
health - Removed
search - Removed
search_extract - Removed
search_parallel
5 tool updates
v0.4.8- Added
extract - Added
health - Added
search - Added
search_extract - Added
search_parallel
TDQS
Scored across 7 tools
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 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.
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.
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
Related MCP Connectors
MCP server for Google search results via SERP API
One MCP for the Web. Easily search, crawl, navigate, and extract websites without getting blocked.…
Official SerpApi MCP server for Google, Bing, and other search engines.
Serper MCP — wraps the Serper Google Search API (serper.dev)
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceProvides Google search capabilities, web content extraction, and screenshot functionality with advanced bot detection avoidance through the MCP protocol.22 npm6-
- AlicenseBqualityFmaintenanceA powerful MCP server that enables parallel Google searching with multiple keywords simultaneously, providing structured results while handling CAPTCHAs and simulating user browsing patterns.187 npm273MIT
- MIT

Brave Search MCP Serverofficial
AlicenseAqualityAmaintenanceAn MCP implementation that integrates the Brave Search API, providing comprehensive search capabilities including web, local business, image, video, news searches, and AI-powered summarization.821,507 npm1,505MIT