
Alexandria
io.github.The-40-Thieves由 GitHub 账号 The-40-Thieves 发布v11.0.0更新于 Oct 27, 2026
Search, read, and cite across 152 libraries: 11 tools, 3 prompts, and a full-text resource.
概览
Alexandria 让助手在 152 个公共数字图书馆中检索、阅读、引用并综合文献,可选向量入库与带引用的研究报告。
- 可以做什么
- 列出并检查 152 个图书馆来源,查看各来源状态与缺失的密钥
- 按标题、作者或关键词检索指定来源,或将自然语言问题并行路由到最合适的来源
- 读取条目的全文或元数据,并沿引用图谱查找参考文献与被引文献,可导出 BibTeX、RIS 或 APA
- 获取相似论文推荐,生成带行内引用的综合答案或多轮研究报告
- 将检索到的文本分块、评分并嵌入写入 pgvector 向量库,供后续语义检索
- 提供文献综述、事实核查和参考文献核验三个现成提示流程
- 适用场景
- 适合让助手跨学术、政府、新闻、法律、文化和开发者档案做文献与资料调研,并输出带引用的答案或报告而非原始搜索结果。也适合用检索到的开放获取文本搭建本地向量知识库。
- 运行要求
- 通过 npx 在本地运行,需要 Node.js;检索与阅读无需任何凭据。可选密钥:OPENAI_API_KEY(或 ALEXANDRIA_BASE_URL 加 ALEXANDRIA_API_KEY)用于路由、综合与嵌入;SUPABASE_URL 与 SUPABASE_SERVICE_ROLE_KEY 用于入库;以及 CORE_API_KEY、GITHUB_TOKEN、GOVINFO_API_KEY、EUROPEANA_API_KEY、GOOGLE_BOOKS_API_KEY、NASA_ADS_API_KEY、COURTLISTENER_API_KEY、SEMANTIC_SCHOLAR_API_KEY 等来源密钥。需要访问各上游图书馆 API 的网络。
安装
在 SourceWeft 中
- 打开 控制台中的 Alexandria,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
Alexandria
[npm version] [License: MIT] [CodSpeed] [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
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.
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.
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.
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: usesgpt-4o-minito route your natural language query to the right sources and generate optimized per-source search terms. Without this key, uselibrary_searchto query sources directly.library_ingest: usestext-embedding-3-smallto 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:
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)ALEXANDRIA_BASE_URL,ALEXANDRIA_API_KEY(shared defaults across every role)OPENAI_API_KEY, withbaseURLdefaulted tohttps://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:
To route through Cloudflare AI Gateway (its OpenAI-compatible endpoint):
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.
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, andlibrary_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
Copy .env.example to .env. Minimum configuration to run with no credentials (search and read only):
To enable library_ask:
To enable library_ingest:
Supabase Schema
Required only if using library_ingest:
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)
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:
With library_ask and library_ingest enabled:
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.
/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:
Locally the same thing is:
Register in Claude Desktop:
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:
Windsurf - mcp_config.json:
Codex CLI:
OpenCode - opencode.json:
Amazon Q - ~/.aws/amazonq/mcp.json (global) or q mcp add:
Kiro - .kiro/settings/mcp.json:
Gemini CLI:
Continue - add to the mcpServers array in your Continue config:
Adding Custom Providers
The pipeline is provider-agnostic. To add a new embedding model or vector store:
- Implement
EmbeddingProviderorVectorStoreProviderfromsrc/types.ts - Add your implementation to
src/pipeline/providers/ - Register it in
src/pipeline/providers/index.ts - Set
EMBEDDING_PROVIDERorVECTOR_STORE_PROVIDERin your env
来源:README.md,提交 5950776
工具
0版本历史
1- v11.0.0最新Sep 16, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分