Skip to main content
Glama

Alexandria

npm version License: MIT Install in Cursor Install in VS Code Install in Goose

A Model Context Protocol (MCP) server for querying, reading, and ingesting texts from 152 public digital libraries. Works with any MCP-compatible client (Claude Desktop, Cursor, VS Code Copilot, etc.).

Tools

Tool

Description

library_list_sources

List all 152 sources with descriptions and full-text capabilities

library_ask(query, max_sources?, results_per_source?)

Natural language search — routes your query to the best sources, searches in parallel, returns unified deduplicated results

library_search(query, source, limit?)

Search a specific source by title, author, or keywords

library_read(id, source)

Fetch full text or metadata for an item (200k char limit)

library_index(id, source)

Dry run: chunk and score text quality without writing anything

library_ingest(id, source)

Chunk → embed → store in your vector database. Idempotent.

library_recommend(id, limit?)

Get similar papers via Semantic Scholar's recommendation engine (up to 500)

library_answer(query, max_sources?, results_per_source?, read_top?)

Ask a question and get a synthesized answer with inline [n] citations, fused across sources with reciprocal rank fusion; warnings[] flags an uncited or all-dropped answer

library_research(query, depth?, breadth?, max_minutes?)

Recursive multi-round research: generates queries, answers each, extracts learnings, and writes a final cited report over every source found

library_health_check(source?, cluster?)

Report per-source health (ok, degraded, down, key_missing, unknown), merging this process's live error rate/latency with the last off-process probe run

library_citations(id, source, direction, limit?, format?)

List the works an item cites (direction: "references") or the works that cite it (direction: "citations"), via OpenAlex's citation graph with OpenCitations as a fallback; format: "bibtex" | "ris" | "apa" also returns a formatted bibliography string

library_ask is the primary entry point. library_search is for targeted queries against a known source. library_index / library_ingest are for building a vector knowledge base from retrieved texts. library_answer and library_research synthesize a cited answer or report instead of returning raw results. library_health_check tells you whether a source is worth calling before you call it. library_citations walks the citation graph around an item and can export it as a bibliography.

library_ask, library_search, library_answer, library_research, library_health_check, and library_citations take a response_format: "concise" | "detailed" parameter (default concise); concise trims results and citations to the high-signal fields (title, source, id, year, hasFullText, url; answer/report + citations; name, cluster, status), detailed returns the full payload, including routing reasons, relevance scores, per-stage diagnostics, and per-source error rate/latency/quota usage. In detailed mode, library_search also attaches a resource_link content item for each full-text result, pointing at that item's library://doc/{source}/{id} resource (see below): a client with resource support can read the full text directly instead of a second library_read call.

Related MCP server: Paper Search MCP

Prompts

Three ready-made research workflows, surfaced by MCP clients as slash commands (Claude Code's /alexandria:<name>, VS Code's /alexandria.prompt). Each returns a single message naming the tools to call, in order. It does not call any tool itself.

Prompt

Description

literature_review(topic, depth?)

Survey a topic across sources and produce a cited report

fact_check_claim(claim)

Check one claim against the library and report whether it is supported

verify_bibliography(references)

Check that a list of references (one per line) resolves to real, findable items

Resources

library://doc/{source}/{id} reads the same text library_read(id, source) returns (including the open-access fallback below), addressed by the source/id pair library_search or library_ask returned. Clients that support MCP resources (Claude Code's @srv:uri, VS Code's Add Context) can pull an item's full text directly.

Sources (152)

152 sources across 19 clusters (36 hidden pending a key or config not present in this deployment). Full per-source detail, including auth env vars and last-verified dates, is generated in docs/sources.md.

Cluster

Sources

Hidden

academic

22

3

ai_research

3

0

archives

4

2

culture

8

3

developer

17

5

economics

11

3

geopolitical

3

3

government

7

3

law

4

1

literature

16

2

markets

2

1

news_global

5

2

news_regional

15

0

real_estate

2

2

science

8

2

security

14

0

standards

3

0

video

1

1

web

7

3

Total

152

36

Credentials

Most tools query external library APIs directly and need no credentials at all. The two optional dependencies are scoped to specific tools:

OpenAI, optional (platform.openai.com)

Required by two tools only:

  • library_ask: uses gpt-4o-mini to route your natural language query to the right sources and generate optimized per-source search terms. Without this key, use library_search to query sources directly.

  • library_ingest: uses text-embedding-3-small to embed chunked text before writing to the vector store.

library_list_sources, library_search, library_read, library_index, and library_recommend all work without an OpenAI key.

Pointing roles at a gateway instead of OpenAI directly

Every LLM/embedding call (routing in library_ask, embeddings in library_ingest) goes through a small per-role provider table (src/utils/providers.ts, THE-318) instead of talking to OpenAI's SDK directly. There are five roles: router, synth, research, embeddings, rerank. Each is resolved from env in this order:

  1. ALEXANDRIA_<ROLE>_BASE_URL, ALEXANDRIA_<ROLE>_API_KEY, ALEXANDRIA_<ROLE>_MODEL (per-role overrides; <ROLE> is the role name upper-cased, e.g. ALEXANDRIA_ROUTER_BASE_URL)

  2. ALEXANDRIA_BASE_URL, ALEXANDRIA_API_KEY (shared defaults across every role)

  3. OPENAI_API_KEY, with baseURL defaulted to https://api.openai.com/v1

With only OPENAI_API_KEY set, every role resolves through step 3, which is exactly today's behavior (gpt-4o-mini for router/synth against api.openai.com, text-embedding-3-small for embeddings).

To route every role through a LiteLLM gateway instead:

ALEXANDRIA_BASE_URL=http://100.78.123.100:4001/v1
ALEXANDRIA_API_KEY=sk-litellm-...

To route through Cloudflare AI Gateway (its OpenAI-compatible endpoint):

ALEXANDRIA_BASE_URL=https://gateway.ai.cloudflare.com/v1/<account_id>/<gateway_id>/openai
ALEXANDRIA_API_KEY=<your OpenAI key, forwarded through the gateway>

Or point just one role at a gateway while the rest stay on OpenAI directly, e.g. ALEXANDRIA_ROUTER_BASE_URL + ALEXANDRIA_ROUTER_API_KEY for routing only.

See docs/cloudflare.md for the fuller Cloudflare integration guide: AI Gateway's newer unified endpoint, Workers AI for the embeddings/rerank roles, Tunnel + Access for a private /mcp, WAF rate limiting for a public one, R2 as an optional cache store, the Browser Run fetch tier below, and why Alexandria stays a hybrid (Node core, Cloudflare services) rather than a full Workers port.

When ALEXANDRIA_<ROLE>_BASE_URL/ALEXANDRIA_BASE_URL is set and OPENAI_API_KEY is also present, OPENAI_API_KEY is wired up as a one-shot fallback: a network error or 5xx from the gateway falls through to a direct OpenAI call once before the request fails. chatJSON (used by routing) always validates the model's response against a zod schema and retries once, on the same backend, with the validation error appended to the prompt, which helps when a gateway is proxying a smaller or local model that doesn't reliably follow the JSON contract on the first try. It requests response_format: json_object only against api.openai.com, or when ALEXANDRIA_<ROLE>_JSON_MODE=1 confirms the gateway/model supports it; otherwise it asks for JSON in the prompt instead.

Supabase — optional (supabase.com)

Required by one tool only:

  • library_ingest — writes chunked, embedded text into a pgvector table for semantic search. Without this, retrieved texts stay in-context and are not persisted anywhere.

Everything else — searching, reading, browsing, getting recommendations — queries external sources in real time and needs no database.

Source-specific keys

Some sources require their own API key. These are free registrations. Sources without a key listed here work without any credentials.

Env Var

Source(s)

Get It

CORE_API_KEY

core

core.ac.uk/services/api

COURTLISTENER_API_KEY

courtlistener

courtlistener.com/profile/tokens

GOVINFO_API_KEY

govinfo; also accepted by congress and regulations as a fallback for DATA_GOV_API_KEY

api.data.gov/signup. Does not cover smithsonian, which needs its own SMITHSONIAN_API_KEY from the same signup page

GOOGLE_BOOKS_API_KEY

googlebooks

Google Cloud Console → APIs & Services → Books API

BHL_API_KEY

bhl

biodiversitylibrary.org/getapikey

DIGITALNZ_API_KEY

digitalnz

digitalnz.org/developers

DPLA_API_KEY

dpla

pro.dp.la/developers/api-codex

EUROPEANA_API_KEY

europeana

apis.europeana.eu — test key immediate, personal ~1 week

GITHUB_TOKEN

required by githubsearch and githubmcp; optional for ghsa and openiti

github.com/settings/tokens, public repo read scope. githubsearch and githubmcp are hidden without it; ghsa falls back to 60s pacing and openiti to an unauthenticated search path

NASA_ADS_API_KEY

nasaads

ui.adsabs.harvard.edu/user/settings/token

SPRINGER_OA_API_KEY + SPRINGER_META_API_KEY

springer

dev.springernature.com — same registration, two keys

ZENODO_API_KEY

zenodo

zenodo.org/account/settings/applications/tokens/new — optional, increases rate limits

SMITHSONIAN_API_KEY

smithsonian

api.data.gov/signup. Its own key, separate from GOVINFO_API_KEY

SEMANTIC_SCHOLAR_API_KEY

semanticscholar

semanticscholar.org/product/api — optional, increases rate limits

TROVE_API_KEY

trove

trove.nla.gov.au/about/create-something/using-api — ~1 week approval

YOUTUBE_API_KEY

youtube

console.cloud.google.com — enable YouTube Data API v3; search only, transcripts need no key

Privacy Policy

Alexandria has no telemetry of its own: it runs on infrastructure you control, and nothing about your queries, results, or credentials is sent to the Alexandria project.

  • Queries go to the upstream public library sources the agent selects for a given request, using each source's own public API under that source's own terms.

  • library_ask, library_answer, library_research, and library_ingest, when an OpenAI (or OpenAI-compatible gateway) key is configured, also send your query text and retrieved excerpts to the LLM and embeddings provider the operator set up. See docs/cloudflare.md for the Cloudflare AI Gateway routing path and docs/fetch-tier-runtime.md for how outbound fetches to library sources are guarded.

  • Nothing is stored by the project itself. The operator's own data/ directory holds local caches (state DB, per-process read cache) on the machine running the server, and nowhere else.

Full text: PRIVACY.md.

Setup

git clone https://github.com/The-40-Thieves/alexandria-mcp
cd alexandria-mcp
npm install
npm run build

Copy .env.example to .env. Minimum configuration to run with no credentials (search and read only):

TRANSPORT=stdio

To enable library_ask:

TRANSPORT=stdio
OPENAI_API_KEY=sk-...

To enable library_ingest:

TRANSPORT=stdio
OPENAI_API_KEY=sk-...
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...

Supabase Schema

Required only if using library_ingest:

create table if not exists knowledge_chunks (
  id bigserial primary key,
  content text not null,
  embedding vector(1536),
  mcp_name text,
  metadata jsonb,
  created_at timestamptz default now()
);

create table if not exists source_docs (
  id bigserial primary key,
  source_url text not null,
  mcp_name text not null,
  title text,
  source text,
  chunk_count int,
  indexed_at timestamptz,
  unique (source_url, mcp_name)
);

create index if not exists knowledge_chunks_embedding_hnsw_idx
  on knowledge_chunks using hnsw (embedding vector_cosine_ops);

If you set this schema up before Task 12, you had an ivfflat index instead (knowledge_chunks_embedding_idx) - docs/sql/match_chunks.sql drops it and creates the hnsw one shown above, since HNSW builds incrementally and needs no lists tuning constant as the table grows. If corpus-as-cache hits seem to be missing results a plain <=> scan would have found, raise the query-time hnsw.ef_search session setting (default 40) at the cost of a slower query - see the commented recommendation in docs/sql/match_chunks.sql.

Corpus as cache

library_answer can also read straight from knowledge_chunks - previously ingested text, already embedded - as one more ranked list next to the live per-source search, skipping the network entirely for a hit it already has the full text for. This only ever serves chunks from a source whose registry freshness is static or daily (never realtime), and only above ALEXANDRIA_CORPUS_MIN_SIM cosine similarity (default 0.92).

It needs one more piece of schema beyond the table above: run docs/sql/match_chunks.sql in the Supabase SQL editor. It defines match_knowledge_chunks(), the nearest-neighbor search function SupabaseVectorStoreProvider.query() calls via .rpc(), and the hnsw index above. This file was written against the current pgvector/supabase-js docs but has not been run against a live database - verify it against your own project before relying on it.

Claude Code (npx)

claude mcp add --env OPENAI_API_KEY=sk-... alexandria -- npx -y @the-40-thieves/alexandria-mcp

Search and read work with no environment variables at all; the --env flag above is only needed to enable library_ask, library_answer, library_research, and library_ingest. See Credentials for the full list of optional keys.

Claude Desktop (stdio)

Minimum config (search and read only), using the published package via npx:

{
  "mcpServers": {
    "library": {
      "command": "npx",
      "args": ["-y", "@the-40-thieves/alexandria-mcp"],
      "env": {
        "TRANSPORT": "stdio"
      }
    }
  }
}

With library_ask and library_ingest enabled:

{
  "mcpServers": {
    "library": {
      "command": "npx",
      "args": ["-y", "@the-40-thieves/alexandria-mcp"],
      "env": {
        "TRANSPORT": "stdio",
        "OPENAI_API_KEY": "sk-...",
        "SUPABASE_URL": "https://your-project.supabase.co",
        "SUPABASE_SERVICE_ROLE_KEY": "eyJ..."
      }
    }
  }
}

From a local checkout instead of the published package, replace command/ args with "command": "node", "args": ["/path/to/alexandria-mcp/dist/index.js"].

Railway (HTTP)

HTTP mode is off by default. Set TRANSPORT=http to serve Streamable HTTP on /mcp instead of speaking stdio, and PORT to choose the listen port (default 3000; Railway sets PORT for you). Every request gets its own MCP server and transport, so the endpoint is stateless and safe to run behind a load balancer.

Env Var

Values

Default

TRANSPORT

stdio or http

stdio

PORT

any port number, HTTP mode only

3000

/mcp (only) is guarded: DNS-rebinding-safe Host/Origin validation (ALEXANDRIA_ALLOWED_ORIGINS, a comma-separated hostname list - loopback is always allowed regardless) and a per-client-IP rate limit (ALEXANDRIA_HTTP_RATE_LIMIT, default 60/minute, 429 with a JSON-RPC error body once exceeded). See docs/fetch-tier-runtime.md for the details and src/httpGuards.ts for the implementation.

Set ALEXANDRIA_ALLOWED_ORIGINS on any deployment reachable by a hostname other than loopback. With it unset, Host-header validation is off and the server logs one warning at startup saying so: a deployment's Host header is its own hostname, which cannot be in an allowlist that does not exist, so enforcing the check without one would 403 every request. Setting it is what turns DNS-rebinding protection on. The Origin check is unconditional either way, so a browser request carrying an Origin outside the list is always rejected.

POST /mcp requires content-type: application/json (anything else is 415) and a body no larger than 100 KiB (413, connection closed).

Behind a reverse proxy or PaaS edge (Cloudflare Tunnel, Railway's own edge, ...) the rate limiter's per-client key defaults to req.socket.remoteAddress, which is the proxy's address for every caller, not the caller's - set ALEXANDRIA_TRUSTED_PROXY=1 to key on CF-Connecting-IP (falling back to the rightmost X-Forwarded-For entry, the one appended by the last hop; the leftmost entry is whatever the original caller sent) instead. Only set this once /mcp is reachable exclusively through a proxy you trust to set those headers honestly - see docs/cloudflare.md's Tunnel and Access section.

Serves both eras of the MCP protocol on the same /mcp endpoint: createMcpHandler(factory, { legacy: 'stateless' }) (@modelcontextprotocol/server, adapted to node:http by toNodeHandler() from @modelcontextprotocol/node) answers a 2026-07-28 server/discover probe or per-request envelope on the modern path, and falls back to the same stateless idiom the pre-2026 SDK used for a 2025-era initialize handshake. One createServer() factory backs both. stdio uses the connection-pinned serveStdio(factory) from @modelcontextprotocol/server/stdio, which selects the era from the connection's opening exchange. Note: the 2025-era fallback path answers over text/event-stream (SSE) rather than a bare JSON body, since the SDK exposes no equivalent to v1's enableJsonResponse for that path. Any MCP client built on a Streamable HTTP transport (the SDK's own StreamableHTTPClientTransport included) already parses either format transparently.

Set those (plus any source keys) in the Railway dashboard and deploy:

railway up

Locally the same thing is:

TRANSPORT=http PORT=3000 npm start

Register in Claude Desktop:

{
  "mcpServers": {
    "library": {
      "url": "https://your-service.up.railway.app/mcp"
    }
  }
}

Health check: GET /health returns { status: "ok", version: "11.0.0", sources: { total: 152, visible: 116, hidden: 36, calls: 0, errors: 0 }, byKind: { rest: 118, hub: 0, rss: 22, mcp: 6, scrape: 6 }, quota: { day: "2026-09-02", reserved: 0, sources: 0, backend: "state" }, cache: { entries: 0 }, tools: 11 }.

Metrics: GET /metrics returns per-source counters (calls, errors, timeouts, cacheHits, quotaRejections, latencyMsTotal) and per-tool counters (invocations, llmCalls) as JSON, e.g. { "sources": { "arxiv": { "calls": 12, "errors": 0, "timeouts": 0, "cacheHits": 3, "quotaRejections": 0, "latencyMsTotal": 4210 } }, "tools": { "library_ask": { "invocations": 5, "llmCalls": 5 } } }. Only sources/tools actually called since the process started appear.

Install in other clients

All of these run the published package via npx; search and read work with no environment variables, and --env/env block additions enable library_ask, library_answer, library_research, and library_ingest the same way the Claude Code and Claude Desktop sections above do.

GitHub Copilot - .vscode/mcp.json:

{
  "servers": {
    "alexandria": {
      "command": "npx",
      "args": ["-y", "@the-40-thieves/alexandria-mcp"]
    }
  }
}

Windsurf - mcp_config.json:

{
  "mcpServers": {
    "alexandria": {
      "command": "npx",
      "args": ["-y", "@the-40-thieves/alexandria-mcp"]
    }
  }
}

Codex CLI:

codex mcp add alexandria -- npx -y @the-40-thieves/alexandria-mcp

OpenCode - opencode.json:

{
  "mcp": {
    "alexandria": {
      "type": "local",
      "command": ["npx", "-y", "@the-40-thieves/alexandria-mcp"]
    }
  }
}

Amazon Q - ~/.aws/amazonq/mcp.json (global) or q mcp add:

{
  "mcpServers": {
    "alexandria": {
      "command": "npx",
      "args": ["-y", "@the-40-thieves/alexandria-mcp"]
    }
  }
}

Kiro - .kiro/settings/mcp.json:

{
  "mcpServers": {
    "alexandria": {
      "command": "npx",
      "args": ["-y", "@the-40-thieves/alexandria-mcp"]
    }
  }
}

Gemini CLI:

gemini extensions install https://github.com/The-40-Thieves/alexandria-mcp

Continue - add to the mcpServers array in your Continue config:

{
  "name": "alexandria",
  "command": "npx",
  "args": ["-y", "@the-40-thieves/alexandria-mcp"]
}

Adding Custom Providers

The pipeline is provider-agnostic. To add a new embedding model or vector store:

  1. Implement EmbeddingProvider or VectorStoreProvider from src/types.ts

  2. Add your implementation to src/pipeline/providers/

  3. Register it in src/pipeline/providers/index.ts

  4. Set EMBEDDING_PROVIDER or VECTOR_STORE_PROVIDER in your env

// Example: Ollama embedding provider
import type { EmbeddingProvider } from '../../types.js';

export class OllamaEmbeddingProvider implements EmbeddingProvider {
  readonly dimensions = 768;

  async embed(texts: string[]): Promise<number[][]> {
    // your implementation
  }
}

Available Tools

11 tools
library_answerAnswer With Cited SourcesA
Read-only

Ask a question in plain English and get a synthesized answer with inline [n] citations, fused across sources with reciprocal rank fusion. Use this instead of library_ask when you want a cited answer rather than raw results. Every factual sentence is cited or dropped; an uncited or all-dropped answer is flagged in warnings[]. Requires OPENAI_API_KEY (or ALEXANDRIA_SYNTH_API_KEY). Set response_format: "detailed" for the full result set, routing, citation grades, and resolvability.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesNatural language question
read_topNoHow many top full-text results to read and cite (default 4)
max_sourcesNoMax number of sources to search (default 6)
response_formatNoconcise (default) trims results/citations to high-signal fields; detailed returns the full payload, including routing reasons, scores, and stage diagnostics.concise
results_per_sourceNoResults to fetch per source (default 5)

Output Schema

ParametersJSON Schema
NameRequiredDescription
answerYes
resultsNo
routingNo
warningsNo
citationsYes

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already mark it read-only/open-world; the description adds genuine behavioral detail: 'Every factual sentence is cited or dropped', warnings[] flagging, 'fused across sources with reciprocal rank fusion', and the required API key. These are not visible in annotations or schema.

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

Conciseness5/5

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

Purpose and sibling routing are front-loaded, and each subsequent sentence adds distinct information: citation behavior, warning flags, auth requirement, and response_format variant. No filler.

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

Completeness5/5

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

With an output schema present, return structure does not need description. The description covers purpose, when-to-use, safety/behavior, auth prerequisites, and the detailed variant, leaving no critical gap for an agent deciding to call this tool.

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

Parameters4/5

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

Schema covers 100% of the 5 params, so the baseline is 3. The description enriches two critical params: query is framed as 'plain English', and response_format:'detailed' is tied to specific outputs (routing, citation grades, resolvability).

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

Purpose5/5

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

States the exact operation: 'Ask a question in plain English and get a synthesized answer with inline [n] citations'. The sentence 'Use this instead of library_ask when you want a cited answer rather than raw results' explicitly differentiates it from the closest sibling, so an agent can select it without opening schemas.

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

Usage Guidelines5/5

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

Names the alternative 'library_ask' and the condition that selects it ('when you want a cited answer rather than raw results'). Also gives a conditional usage branch: 'Set response_format: "detailed" for the full result set, routing, citation grades, and resolvability.'

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

library_askNatural Language Library SearchA
Read-only

Ask for content in plain English; automatically selects the best sources from all 152 libraries, generates optimized per-source queries, and searches in parallel. Use this as the default entry point for any natural-language request. Use library_search instead when you already know which source to query. Requires OPENAI_API_KEY (already set for embeddings). Set response_format: "detailed" for routing reasons and per-stage diagnostics.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesNatural language description of what you want to find
max_sourcesNoMax number of sources to search (default 5)
response_formatNoconcise (default) trims results/citations to high-signal fields; detailed returns the full payload, including routing reasons, scores, and stage diagnostics.concise
results_per_sourceNoResults to fetch per source (default 5)

Output Schema

ParametersJSON Schema
NameRequiredDescription
queryYes
errorsYes
intentYes
stage1No
stage2No
resultsYes
routingYes
total_resultsYes
sources_searchedYes

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already establish the safety profile (readOnlyHint=true, destructiveHint=false, openWorldHint=true), and the description adds context beyond them: it discloses the routing behavior, parallel search execution, the automatic source-selection logic, and the OPENAI_API_KEY environment requirement. It does not cover rate limits or failure behavior, but with annotations carrying the safety burden, the added behavioral context is solid.

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

Conciseness4/5

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

Three sentences, with core behavior front-loaded and routing guidance following immediately. Every sentence earns its place, but the response_format directive in the final sentence partially duplicates what the schema already documents, so it is not maximally tight.

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

Completeness4/5

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

For a complex routing tool, the description covers the essential operational context: what it does, when to use it, the sibling alternative, an environment prerequisite, and a configuration hint. Since an output schema exists, the omission of return-value details is acceptable. Only minor gaps remain, such as rate limits or cost implications of parallel searching.

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

Parameters3/5

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

Schema description coverage is 100%, so every parameter — including the response_format enum meanings — is already documented in the input schema. The description's 'Set response_format: detailed for routing reasons' adds framing but largely restates what the schema's enum description already says about diagnostics and routing reasons. This is the appropriate baseline-3 case where the schema does the heavy lifting.

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

Purpose5/5

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

The description opens with a specific verb and resource: it takes plain-English requests and routes them across all 152 libraries, generating per-source queries and searching in parallel. It also differentiates itself from its key sibling, library_search, by explicitly naming what it is not ('when you already know which source to query'). An agent can tell what this tool does without opening the schema.

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

Usage Guidelines5/5

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

The description explicitly declares this the default entry point for any natural-language request and names the exact alternative condition, 'Use library_search instead when you already know which source to query.' This is the strongest form of usage guidance: it gives when-to-use, when-not-to-use, and the sibling tool that applies instead.

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

library_citationsGet References or Citations (with Bibliography Export)A
Read-onlyIdempotent

List the works a scholarly item cites (direction: "references") or the works that cite it (direction: "citations"), resolved through OpenAlex's citation graph with OpenCitations as a fallback when OpenAlex has no record. Accepts an id/source from library_search or library_ask, or a bare DOI/arXiv id. Set format: "bibtex" | "ris" | "apa" to also return a formatted bibliography string; BibTeX prefers Crossref's own citation when a DOI is resolvable, for the first 20 results only (a paced, one-at-a-time doi.org lookup per item), with later results using a locally generated entry instead. Set response_format: "detailed" for full result fields.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesItem identifier from library_search/library_ask, or a bare DOI/arXiv id
limitNoMax results
formatNoAlso return a `formatted` bibliography string in this style
sourceYesLibrary source name. Run library_list_sources for the current list and descriptions.
directionYesreferences: works this item cites. citations: works that cite this item.
response_formatNoconcise (default) trims results/citations to high-signal fields; detailed returns the full payload, including routing reasons, scores, and stage diagnostics.concise

Output Schema

ParametersJSON Schema
NameRequiredDescription
seedYes
resultsYes
directionYes
formattedNo

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the readOnly/idempotent annotations, the description discloses OpenAlex-to-OpenCitations fallback behavior, Crossref DOI lookup pacing (one-at-a-time, first 20 only), and what 'detailed' returns including routing reasons and diagnostics. This is substantial behavioral context.

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

Conciseness5/5

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

Three sentences front-load the core operation and direction semantics, then pack necessary caveats into later clauses. Every clause adds decision-relevant information with no fluff.

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

Completeness5/5

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

The description covers identifiers, direction, fallback sources, formatting behavior, response modes, and diagnostics. Combined with the rich schema and output schema, an agent has what it needs to invoke this tool correctly.

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

Parameters4/5

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

Schema coverage is 100%, but the description adds important cross-parameter meaning: format triggers a formatted bibliography string, BibTeX has special Crossref behavior, and response_format controls field richness. This enriches the schema rather than repeating it.

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

Purpose5/5

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

The description names a specific verb ('List'), the resource (works cited by or citing a scholarly item), and the two directions with clear semantics. It also distinguishes itself from sibling query tools by framing the output as a citation graph operation.

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

Usage Guidelines4/5

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

The description clearly signals that this tool is for resolved items, explicitly accepting IDs from library_search or library_ask or a bare DOI/arXiv ID. It explains when to use format and response_format, though it does not explicitly name sibling tools to exclude.

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

library_health_checkCheck Source HealthA
Read-onlyIdempotent

Report per-source health: 'ok', 'degraded', 'down', 'key_missing', or 'unknown', merging this process's live error rate and latency with the last off-process probe run. The probe layer reads eval/probe-latest.json, which published installs do not ship, so on a published install a source's status stays 'unknown' until this process itself calls it. Use before relying on a source that has been erroring, or to check whether a key is configured. Optionally filter by source or cluster. Set response_format: "detailed" for error rate, latency, and quota usage.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourceNoLibrary source name. Run library_list_sources for the current list and descriptions.
clusterNoRestrict to sources in this cluster
response_formatNoconcise (default) trims results/citations to high-signal fields; detailed returns the full payload, including routing reasons, scores, and stage diagnostics.concise

Output Schema

ParametersJSON Schema
NameRequiredDescription
probeAtNo
sourcesYes
generatedAtYes

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true and idempotentHint=true, so safety is covered. The description adds valuable behavioral context beyond annotations: the probe layer reads eval/probe-latest.json, the published-install caveat ('status stays unknown until this process itself calls it'), and the data merge behavior. This meaningfully informs the agent about edge cases and internal mechanics.

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

Conciseness5/5

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

The description is three sentences: core function with output states, behavioral caveat, and usage/parameter guidance. It is front-loaded, every sentence earns its place, and there is no redundant filler.

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

Completeness5/5

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

The tool has a rich output schema, clear annotations, and a description that covers purpose, behavior, edge cases, usage triggers, and parameter guidance. For a read-only health-reporting tool with all-optional parameters, nothing an agent needs to invoke it correctly is missing.

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

Parameters4/5

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

Schema description coverage is 100%, so baseline is 3. The description adds value by explaining that response_format: 'detailed' exposes 'error rate, latency, and quota usage'—quotas are not mentioned in the schema—and by framing source/cluster as optional filters. This is a modest but genuine addition beyond the schema.

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

Purpose5/5

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

The description states a specific verb ('Report') and resource ('per-source health'), enumerates the exact output states ('ok', 'degraded', 'down', 'key_missing', 'unknown'), and describes the data fusion mechanism. This clearly distinguishes it from siblings like library_list_sources (listing) or library_search (retrieval).

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

Usage Guidelines4/5

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

The description gives explicit when-to-use guidance: 'Use before relying on a source that has been erroring, or to check whether a key is configured.' It does not explicitly name exclusions or alternative tools, but the context is clear and actionable for an agent.

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

library_indexPreview Chunking (Dry Run)A
Read-onlyIdempotent

Dry run: fetch text, chunk semantically, score OCR quality. No writes. Full-text sources only.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
sourceYesLibrary source name. Run library_list_sources for the current list and descriptions.

Output Schema

ParametersJSON Schema
NameRequiredDescription
titleYes
sourceYes
sourceIdYes
totalChunksYes
ingestPolicyNo
sampleChunksYes
droppedChunksYes
avgQualityScoreYes
estimatedTokensYes

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint false. The description adds specific behavioral details: fetching text, semantic chunking, and OCR quality scoring, plus the full-text source constraint. It does not contradict annotations and provides useful context beyond them.

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

Conciseness5/5

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

The description is exceptionally concise, front-loaded with the core purpose, and every clause adds information: 'Dry run', 'fetch text, chunk semantically, score OCR quality', 'No writes', 'Full-text sources only'. No waste.

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

Completeness3/5

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

The description covers the core function and constraints, and an output schema exists, which helps. However, the undocumented id parameter is a notable gap, and the description doesn't explain what 'score OCR quality' means in practice. Overall, it's adequate but not complete for an agent to use without ambiguity.

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

Parameters2/5

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

Schema description coverage is 50%: the source parameter is documented with a helpful reference to library_list_sources, but the id parameter has no description. The tool description does not mention parameters at all, so it fails to compensate for the undocumented id. An agent would have to infer that id identifies a document, which is a significant gap.

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

Purpose5/5

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

The description clearly states the tool's specific actions: dry run, fetch text, chunk semantically, score OCR quality, with explicit constraints (no writes, full-text sources only). This distinguishes it from sibling tools like library_ingest or library_read, making its purpose unambiguous.

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

Usage Guidelines4/5

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

The description provides clear context for when to use the tool: it's a dry run, no writes, and only for full-text sources. While it doesn't name specific alternatives, these constraints imply when it's appropriate versus the ingest tool. This is sufficient guidance for an agent.

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

library_ingestIngest Into Vector DatabaseA
Idempotent

Chunk, embed, and store a text. Idempotent. Full-text sources only. Requires OPENAI_API_KEY + SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
sourceYesLibrary source name. Run library_list_sources for the current list and descriptions.

Output Schema

ParametersJSON Schema
NameRequiredDescription
titleYes
sourceYes
sourceIdYes
chunksDroppedYes
chunksWrittenYes
skippedDuplicateYes

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already provide idempotency and safety hints, so the description needs less behavioral disclosure. It adds worthwhile context: the chunk-embed-store processing stages, source-type limitation, and required authentication environment variables. It does not go into failure modes or error behavior, but the bar is lowered by 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.

Conciseness4/5

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

The description is compact and front-loads the core action. Each sentence adds a distinct type of information: operation, idempotency, source scope, and prerequisites. It is slightly terse, but not bloated.

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

Completeness3/5

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

For a two-parameter tool with an output schema and helpful annotations, the description covers key constraints and auth needs. Still, the meaning of 'id' is left unexplained, and the relationship to the 'source' parameter is only implied, leaving a notable gap for an agent preparing a correct call.

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

Parameters2/5

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

Schema coverage is only 50%, and the description does not explain how 'id' and 'source' map to the action beyond saying 'a text.' The schema's source description is helpful, but the id parameter has no description anywhere, and the tool description does not compensate for that gap.

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

Purpose5/5

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

The description names a specific pipeline ('Chunk, embed, and store a text') and a concrete resource (vector database), which clearly separates it from the sibling tools like library_read or library_search. The title reinforces the resource, and the 'Full-text sources only' constraint adds precision.

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

Usage Guidelines3/5

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

The description gives clear preconditions ('Full-text sources only', required API keys) that tell an agent when it is allowed to use the tool. However, it does not explicitly explain when to prefer this over a sibling like library_index, and no alternatives are named.

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

library_list_sourcesList Available Library SourcesA
Read-onlyIdempotent

List all 152 library sources (count computed from the live registry at startup) with descriptions and capabilities.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
sourcesYes

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already cover read-only, idempotent, non-destructive behavior. The description adds meaningful behavioral context beyond that: the source count of 152 is computed dynamically from the live registry at startup, so it may change between runs. It also signals that the response is a complete enumeration rather than a paginated or filtered subset.

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

Conciseness5/5

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

A single front-loaded sentence conveys the action, the full scope, the count, and the returned detail level. The parenthetical about the live registry is compact and adds value without wasting space.

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

Completeness5/5

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

For a parameterless list tool, the description is complete: it states what is listed, how much is listed, and what information each entry carries. Combined with the output schema and annotations, an agent has everything needed to invoke and interpret the tool correctly.

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

Parameters4/5

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

The tool has zero parameters, so the description does not need to explain parameter usage. The baseline of 4 applies because there is no parameter burden for the description to carry.

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

Purpose5/5

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

The description states a specific verb and resource: 'List all 152 library sources' with the content of the listing ('descriptions and capabilities'). This clearly distinguishes it from siblings like library_search or library_read, which operate on content rather than enumerating sources.

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

Usage Guidelines3/5

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

The intended use case is implied—use this to discover the full set of available library sources before selecting one—but there is no explicit when-to-use, when-not-to-use, or mention of alternatives. The description is sufficient for the obvious listing purpose, but it does not actively route the agent away from sibling tools.

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

library_readRead Full Text or MetadataA
Read-onlyIdempotent

Fetch text from a library source. Full-text sources return cleaned text (truncated at 200k chars). Metadata sources return item details and an external URL.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesItem identifier from library_search or library_ask
sourceYesLibrary source name. Run library_list_sources for the current list and descriptions.

Output Schema

ParametersJSON Schema
NameRequiredDescription
doiNo
noteNo
textNo
yearNo
pagesNo
titleYes
authorsYes
languageNo
charCountNo
truncatedNo
externalUrlNo
truncatedAtNo
unavailableNo
metadataOnlyNo

TDQS

A3.8/5.0
Behavior4/5

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

The description adds useful behavioral details beyond the annotations: full-text results are cleaned and truncated at 200k characters, and metadata sources return details plus an external URL. This complements the readOnlyHint and idempotentHint annotations without contradiction.

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

Conciseness5/5

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

The description is compact and front-loaded: the first sentence states the core purpose, and the second sentence adds the key variant behavior. Every sentence earns its place with no redundancy.

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

Completeness4/5

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

Given the output schema exists, the description appropriately avoids detailing return values. It covers the main behavioral variation and works with the schema to give the agent enough to call the tool correctly. Minor gaps like error behavior are not critical here.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already explains both id and source. The description adds context about source type behavior but does not introduce new parameter-specific semantics beyond what the schema provides.

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

Purpose4/5

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

The description clearly identifies the operation: fetching text from a library source. It adds meaningful differentiation between full-text and metadata sources, which helps distinguish this tool from search-oriented siblings like library_search or library_ask.

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

Usage Guidelines3/5

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

The description implies usage context through the phrase 'from a library source' and the parameter note that ids come from library_search or library_ask. However, it does not explicitly say when to use this tool versus alternatives or state exclusions, leaving some inference to the agent.

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

library_recommendGet Similar Papers (Semantic Scholar)A
Read-onlyIdempotent

Get papers similar to a given paper using Semantic Scholar's recommendation engine. Pass a paperId from a semanticscholar search result. Returns up to 500 similar papers.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesSemantic Scholar paperId
limitNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultsYes

TDQS

A4/5.0
Behavior3/5

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

Annotations already provide readOnly, openWorld, idempotent, and non-destructive hints, so the description carries a lower burden. It adds input provenance ('paperId from a semanticscholar search result') and a result-count ceiling, but doesn't disclose potential external API failures, rate limits, or invalid-ID behavior.

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

Conciseness5/5

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

Three short sentences, no filler, and the core purpose is front-loaded before usage guidance. Every sentence adds information.

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

Completeness4/5

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

For a two-parameter, output-schema-backed tool with strong annotations, the description provides enough context: source of the id, operation, and result limit. It doesn't discuss failure modes, but the simplicity and annotations make that a minor gap.

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

Parameters3/5

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

Schema coverage is 50%; id is documented in the schema, and the description enriches it by requiring it come from a Semantic Scholar search result. limit has no schema description but the 'Returns up to 500 similar papers' phrase indirectly conveys its meaning, though not fully.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Get papers similar to a given paper' via Semantic Scholar's recommendation engine. This clearly separates it from siblings like library_search and library_citations by identifying the operation as recommendation rather than search or citation lookup.

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

Usage Guidelines4/5

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

It gives an explicit when-to-use condition: you need an existing paperId from a Semantic Scholar search result and want similar papers. It doesn't spell out alternatives or exclusions, but the context is clear enough for an agent to pick this over search or citations.

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

library_researchRecursive Cited ResearchA
Read-only

Deep research on a topic: outlines 3 to 7 coverage objectives, generates search queries, answers each with library_answer, extracts learnings and follow-up questions, then recurses with half the breadth. Stops once every objective is covered by a learning, at the given depth, at the time budget, or once a round finds no new sources. Requires OPENAI_API_KEY (or ALEXANDRIA_RESEARCH_API_KEY / ALEXANDRIA_SYNTH_API_KEY). Set response_format: "detailed" for the per-round breakdown, elapsed time, citation grades, resolvability, and the objectives/coverage outline.

ParametersJSON Schema
NameRequiredDescriptionDefault
depthNoRecursion depth (default 2)
queryYesResearch topic or question
breadthNoQueries generated in the first round; halves each round (default 4)
max_minutesNoWall-clock time budget in minutes (default 6)
response_formatNoconcise (default) trims results/citations to high-signal fields; detailed returns the full payload, including routing reasons, scores, and stage diagnostics.concise

Output Schema

ParametersJSON Schema
NameRequiredDescription
reportYes
roundsNo
coverageNo
warningsNo
citationsYes
elapsedMsNo
objectivesNo

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare the tool read-only and non-destructive. The description adds valuable behavioral context beyond that: it requires an external API key, calls library_answer as a sub-step, recurses with halved breadth, and stops on coverage/depth/time/no-new-sources. It does not repeat safety hints or contradict them.

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

Conciseness5/5

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

The description is dense but every sentence adds distinct information: the algorithm, the stopping conditions, the auth requirement, and the response_format distinctions. It front-loads the core purpose and avoids filler or restating the title.

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

Completeness5/5

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

For a complex recursive tool, the description covers the main workflow, termination criteria, hard prerequisite, and output options. An output schema exists, so return-value details need not be spelled out. Nothing required for an agent to decide on and invoke the tool correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3. The description adds extra meaning by explaining response_format 'detailed' returns per-round breakdown, elapsed time, citation grades, resolvability, and objectives/coverage outline, and by clarifying that breadth halves each round. This goes beyond the schema's brief parameter descriptions.

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

Purpose5/5

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

The description opens with 'Deep research on a topic' and gives a concrete algorithm: outline objectives, generate queries, answer via library_answer, extract learnings, recurse. This is a specific verb plus resource and process, and it clearly distinguishes the tool from single-shot siblings like library_ask or library_search by framing it as a recursive orchestration tool.

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

Usage Guidelines4/5

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

The description provides clear context for when to use the tool: 'Deep research on a topic' with 3–7 coverage objectives and recursion. It also implies it should be used for multi-round, exhaustive research rather than simple lookups, though it does not explicitly name exclusions or alternative tools, so it stops short of a 5.

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

Tool Schema Changelog

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

  1. 11 tool updatesv11.0.0
    • First observedlibrary_answer
    • First observedlibrary_ask
    • First observedlibrary_citations
    • First observedlibrary_health_check
    • First observedlibrary_index
    • First observedlibrary_ingest
    • First observedlibrary_list_sources
    • First observedlibrary_read
    • First observedlibrary_recommend
    • First observedlibrary_research
    • First observedlibrary_search

TDQS

A4.4/5.0

Scored across 11 tools

Disambiguation5/5

Each tool targets a distinct operation—listing, health, natural-language search, specific search, read, dry-run indexing, ingest, recommend, answer, deep research, citations. Overlaps like ask vs. answer are clearly differentiated by descriptions.

Naming Consistency5/5

All tools follow the library_<verb> pattern with consistent snake_case naming. Verbs are clear and predictable (list, search, read, ingest, etc.), with minor noun-based exceptions like 'health_check' and 'citations' that still fit the pattern.

Tool Count5/5

11 tools is well within the ideal 3-15 range and each serves a distinct purpose, covering the full lifecycle from discovery to ingestion to synthesis without redundancy.

Completeness5/5

The tool set covers discovery (list_sources), health (health_check), search (ask, search), retrieval (read), ingestion (index, ingest), recommendation, synthesis (answer, research), and citations. No obvious gaps exist for a library server's expected operations.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables comprehensive academic research by searching and analyzing papers from PubMed, Google Scholar, ArXiv, and JSTOR. Provides full-text access, citation management, and research organization through five powerful consolidated tools.
    47 npm
    15
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Enables searching and downloading academic papers from 14 platforms including arXiv, PubMed, Google Scholar, Web of Science, Springer, and Sci-Hub with unified data format and intelligent rate limiting.
    19
    368 npm
    184
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides real-time access to over 200 million scientific papers and full-text extraction from major academic sources including arXiv, OpenAlex, and PubMed Central. It enables users to search, fetch metadata, and analyze citations across multiple research disciplines through a unified Model Context Protocol interface.
    109 npm
    57
    MIT