Field Current

Field Current

A self-hosted research library with a read-only MCP endpoint for querying paper metadata, abstracts, and BibTeX entries.

Category
访问服务器

README

Field Current

Field Current is a small, self-hosted research library for keeping one narrow field current. It keeps checked paper metadata, abstracts, review decisions, author/affiliation evidence, and canonical BibTeX in one place, with a deliberately bounded read-only MCP surface for research agents. It runs as either one Node process with one SQLite file or two optional Cloudflare Workers backed by D1 and KV. The Node runtime supports an invite-only shared laboratory library with individual accounts, roles, browser sessions, and personal MCP tokens.

This is the research layer beside a PDF reader or reference manager, not a replacement for either one. It deliberately avoids Postgres, Redis, object storage, vector search, browser extensions, and word-processor plugins.

Existing installations retain the internal bibhub runtime identifiers for compatibility: database paths, environment variables, Docker volumes, systemd paths, Cloudflare resources, and MCP URLs do not change during the product rename.

What it includes

  • DBLP and arXiv title lookup with bounded responses, caching, and visible disagreements.
  • BibTeX import/export, deterministic cite keys, .bib/TeX audit, and safe re-key plans.
  • An arXiv discovery inbox. New works remain candidates until a curator or owner records a review.
  • Bidirectional citation cross-checks from existing works, with every seed relation retained.
  • Abstract display without downloading PDFs.
  • Optional author and paper-time institution evidence from OpenAlex.
  • A read-only MCP endpoint with exactly three tools: lookup, entries, and bib.

A fresh Node instance idles at roughly 115 MB RSS in the current test environment. Allow 256 MB RAM for a small installation. Disk use is the SQLite database plus a disposable metadata cache; Field Current does not store PDFs.

Docker quick start

Requirements: Docker Engine with Compose.

cp .env.example .env
chmod 600 .env
docker compose build
docker compose run --rm bibhub npm run users -- \
  bootstrap-owner --db /data/bibhub.db --username owner --display-name "Lab owner"

The bootstrap command prints a random temporary password once. Save it, then start the service:

docker compose up -d
docker compose ps

Open http://127.0.0.1:8788, sign in, and replace the temporary password. There is no web self-registration and the first owner can only be created from the local CLI.

The container runs as a non-root user with a read-only root filesystem. Its database and cache live in the named volume bibhub-data; the HTTP port binds to loopback by default. Put Caddy, Tailscale, or a private tunnel in front of it if remote access is needed.

Stop and remove the process without deleting the library:

docker compose down

Do not add -v unless you intentionally want to delete the bibhub-data volume.

Bare Node

Requirements: Node 22.18+ or Node 24.11+.

npm ci --omit=dev
umask 077
npm run users -- bootstrap-owner --db ./bibhub.db \
  --username owner --display-name "Lab owner"
BIBHUB_PUBLIC_ORIGIN=http://127.0.0.1:8788 npm run serve

The default listener is 127.0.0.1:8788, the compatibility database name is ./bibhub.db, and the response cache is ./.cache. Relevant environment variables are:

Variable Meaning
AUTH_TOKEN Optional legacy/break-glass owner bearer token. BIBHUB_TOKEN remains a compatible Node alias. A new Node install uses accounts instead.
BIBHUB_PUBLIC_ORIGIN Exact browser origin used for session and Origin checks; set the external HTTPS origin behind a proxy or tunnel.
MCP_READ_TOKEN Optional shared MCP compatibility token. New Node installs use one library:read token per user.
BIBHUB_HOST / PORT Listener, default 127.0.0.1:8788.
BIBHUB_DB SQLite path.
BIBHUB_CACHE Disposable DBLP/arXiv cache directory.
BIBHUB_WATCHLIST JSON array of arXiv discovery queries; default [] disables topic discovery. Cloudflare Workers accepts at most 5 terms per sweep to stay within the Free D1 query budget.
BIBHUB_CITATION_DISCOVERY Scheduled citation scans only; default false. Manual scans remain available.
BIBHUB_SWEEP_INTERVAL_HOURS Node/Docker interval, default 24; 0 disables the timer.
OPENALEX_API_KEY Optional free OpenAlex key for author enrichment and citation discovery.
SOURCE_CODE_URL Exact HTTPS source URL for this running revision; required before exposing an AGPL network instance.
SOURCE_REVISION Full 40- or 64-hex Git commit ID served by SOURCE_CODE_URL; required with it.

deploy/bibhub.service.example and deploy/bibhub.env.example provide a hardened systemd setup.

Laboratory accounts

One Node deployment is one shared laboratory library. Accounts control who may act on it; they do not create private copies of papers.

Role Access
reader Browse, search, export BibTeX, and use read-only MCP.
curator Reader access plus save/import and candidate review.
owner Curator access plus discovery, OpenAlex refresh, and local user administration.

Invite users from the host. Generated temporary passwords are printed once and must be changed on first sign-in:

npm run users -- invite --db ./bibhub.db --actor owner \
  --username alice --display-name "Alice" --role curator
npm run users -- list --db ./bibhub.db
npm run users -- disable --db ./bibhub.db --actor owner --username alice

Passwords use salted Node scrypt; the database stores only password material, session hashes, and API-token hashes. Browser sessions are HttpOnly, SameSite=Strict, and Secure when BIBHUB_PUBLIC_ORIGIN is HTTPS. Unsafe cookie-authenticated requests must match that configured Origin. Disabling a user or changing their password invalidates their sessions and API tokens. There is no public registration or “first visitor becomes admin” route.

The canonical paper rows remain global. A future multiple-direction feature should add tracks and membership/link tables around those works; the compatibility repos field is a collection label, not a tenant or permission boundary.

L40-style shared-server deployment

On a shared compute server, keep the release and SQLite/WAL on a local data filesystem rather than a nearly-full system disk or network filesystem. Run the process as a dedicated Unix user, bind only to 127.0.0.1, and put an HTTPS reverse proxy or outbound tunnel in front. A typical layout is:

/data/field-current/releases/<source-revision>
/data/field-current/state/bibhub.db
/data/field-current/state/cache/

Set BIBHUB_PUBLIC_ORIGIN to the exact external HTTPS origin. Do not expose the Node port on 0.0.0.0; MCP is served by the same process at /mcp. Back up the SQLite database with the built-in online backup command and verify the snapshot before every upgrade.

Discovery topics

No topic is enabled by default, so a new installation does not make scheduled arXiv requests. Node and Docker accept up to 20 queries; Cloudflare Workers accepts up to 5 so one sweep stays inside the Free D1 query budget. Each query may be at most 120 characters:

BIBHUB_WATCHLIST='["database provenance","scientific metadata"]'

Node and Docker run configured discovery once per interval when either the watchlist or scheduled citation discovery is enabled; the default is 24 hours after process start. npm run sweep performs one configured discovery pass and exits. The Cloudflare build runs its configured discovery daily. A match enters the review inbox; it never enters the formal library automatically.

Citation discovery

Citation discovery uses checked library entries as seeds and looks in both directions: works referenced by a seed and works that cite it. Results enter the same review inbox; they are never promoted into the formal library without an explicit review. When several seeds find the same candidate, the inbox keeps every seed and relation instead of creating duplicate candidates.

The browser's Scan citations action runs one authenticated seed at a time. Keeping the deployed Worker batch at one leaves headroom under Workers Free CPU and D1 query limits; the self-hosted Node endpoint may opt into a batch of up to three with its limit parameter. The same action is available over HTTP:

curl -X POST 'http://127.0.0.1:8788/api/citations/scan?limit=1' \
  -H "Authorization: Bearer $AUTH_TOKEN"

That bearer example is for Cloudflare or a deliberately configured legacy owner token. On a multi-user Node instance, owners use the browser session; personal MCP tokens are read-only and are rejected on this write route.

Manual scans are available whenever a free OPENALEX_API_KEY is configured, regardless of BIBHUB_CITATION_DISCOVERY. Set that flag to true only if scheduled scans are wanted. On Cloudflare, keep citation discovery on its dedicated BIBHUB_CITATION_CRON trigger rather than combining it with the arXiv sweep; the supplied Wrangler config uses 06:20 and 06:50 UTC.

OpenAlex citation data is useful for finding omissions, not for authoritative citation counts: coverage can be incomplete, delayed, or missing for an otherwise valid work. Seeds without a DOI, arXiv identity, or verified OpenAlex authorship snapshot are checkpointed as unsupported; their formal entries are not changed. Field Current treats the configured key as free-only: before every actual OpenAlex list or search attempt, including retries, it checks the endpoint-specific cost against the free daily allowance and keeps a US$0.10 reserve. Citation scans also use a database lease so manual and scheduled batches cannot race. Prepaid balance is never read or used.

Import and command-line tools

The browser can look up and save an individual work or paste a complete .bib into a collection. The same batch import is available over the authenticated API:

curl -X POST http://127.0.0.1:8788/api/import \
  -H "Authorization: Bearer $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary "$(jq -n --rawfile bib refs.bib --arg repo reading-list '{bib:$bib,repo:$repo}')"

The curl example uses the optional legacy owner token. The normal multi-user Node path is an owner/curator browser session, so a leaked MCP token can never import or review papers.

Local, read-mostly bibliography tools need no running server:

npm run cli -- selftest
npm run cli -- key --author "Vaswani, Ashish" --year 2017 --title "Attention Is All You Need"
npm run cli -- lookup "Attention Is All You Need"
npm run cli -- audit --bib refs.bib --tex paper.tex
npm run cli -- rekey --bib refs.bib --tex paper.tex

audit exits non-zero on missing, uncited, duplicate, or off-rule keys. rekey only prints a plan unless --apply is supplied, then rewrites the BibTeX and every supplied TeX file from one checked plan. The cite-key policy is documented in docs/citation-rules.md.

The database column and API parameter are still named repos/repo for compatibility; the browser presents these values as collections.

Backups

Create a consistent SQLite online backup while the Node service is running:

npm run backup
npm run verify:backup -- /path/to/bibhub-2026-08-06T06-20-00Z.sqlite

By default the snapshot is written under a backups/ directory beside the live database, with mode 0600. In Docker, run docker compose exec bibhub npm run backup; the snapshot stays in the persistent /data volume. Copy verified snapshots to a second machine or encrypted storage (docker compose cp bibhub:/data/backups/<file>.sqlite ./ copies one out). Restore only while Field Current is stopped: move the old database and its -wal/-shm sidecars aside together, install a verified snapshot at the configured database path, then start the service and check /readyz.

Optional author and affiliation evidence

Author enrichment is an explicit authenticated write, never a side effect of an MCP read. If OPENALEX_API_KEY is unset, the library continues to work and enrichment reports that it is disabled. Configure only a free OpenAlex key; Field Current contains no paid provider or billing fallback. Every billable list or search attempt stops before the protected US$0.10 free reserve.

curl -X POST http://127.0.0.1:8788/api/authorships?limit=5 \
  -H "Authorization: Bearer $AUTH_TOKEN"

Affiliations are institutions reported on a particular paper record, not a claim about an author's current employer. Stored evidence includes source work and author identifiers, retrieval time, match method, ROR/OpenAlex institution identifiers, and raw affiliation strings. Missing evidence means “not checked”; an empty checked result means the source supplied no affiliation.

Agents request the same analysis through entries({view:"authors", author:"..."}). Results keep paper abstracts, coauthors, venues, collections, coverage, and work-scoped institutions together so an agent does not have to infer employment from a name.

Cloudflare deployment

Cloudflare is optional. The public Wrangler template contains no account or resource IDs. Keep the instance copy ignored so automatic provisioning cannot add your IDs to a public commit:

npm ci
if [ ! -e wrangler.production.jsonc ] && [ ! -e wrangler.mcp.production.jsonc ]; then
  cp wrangler.jsonc wrangler.production.jsonc
  cp wrangler.mcp.jsonc wrangler.mcp.production.jsonc
  chmod 600 wrangler.production.jsonc wrangler.mcp.production.jsonc
else
  echo "keeping existing instance configs"
fi
npm run types
npm run check
npm test
npm run deploy

The copy step is for a brand-new instance only. During an upgrade, keep both ignored production files: they contain the bindings that point at the existing D1, KV, service, and rate-limit resources. Replacing either file can bind the next deploy to an empty resource.

The first deploy creates the D1 database and KV namespace and writes their IDs only into the ignored wrangler.production.jsonc. API access remains fail-closed until a secret is set. Initialize the database, then add the token:

npm run db:remote
npx wrangler secret put AUTH_TOKEN -c wrangler.production.jsonc
npx wrangler secret put OPENALEX_API_KEY -c wrangler.production.jsonc  # optional, free key only

Before exposing the AGPL version, add the same immutable SOURCE_CODE_URL and SOURCE_REVISION string variables to both private Wrangler configs. Existing main-Worker configs must also add /source to assets.run_worker_first. The main page's /source route and the MCP initialization metadata must identify the same running source.

Both deployment commands run a fail-closed source preflight before Wrangler. It checks both ignored production configs, even when only one Worker is being deployed. Run the same check without deploying with npm run source:preflight. In a Git checkout, the local Field Current source scope must be clean; unrelated files elsewhere in a containing monorepo are outside the check. A standalone source export without .git still receives all config checks.

The preflight cannot prove that an external SOURCE_CODE_URL contains the running files, and does not compare its revision with a private monorepo's unrelated HEAD. The publisher remains responsible for exporting the exact running source, committing it to the public repository, and putting that public commit ID in both production configs.

Set BIBHUB_WATCHLIST in the private config if scheduled topic discovery is wanted. Set BIBHUB_CITATION_DISCOVERY to true only if scheduled citation scans are wanted, then redeploy. The citation flag does not disable authenticated manual scans. Cloudflare's free-plan limits can change; verify the current plan before relying on it. The application does not bind R2 or require a payment method.

For a database created before the public migration ledger, inspect and apply only the needed one-time files described in manual-upgrades/README.md. Fresh databases need only npm run db:remote; the Node server applies the same ordered migration files at startup and refuses to listen if one fails or an already-applied file has changed.

Read-only MCP Worker

The MCP Worker follows protocol version 2026-07-28 using the TypeScript SDK v2 and Streamable HTTP at /mcp. Its public capability surface is fixed:

Tool Access
lookup Read-only DBLP/arXiv verification.
entries Read-only paper search and bounded author/affiliation analysis.
bib Read-only canonical BibTeX rendering.

It has no D1, KV, assets, cron, or general fetch binding. A named service binding can call only the main Worker's ReadEntrypoint methods, and MCP_READ_TOKEN is separate from the write-capable AUTH_TOKEN.

Deploy the main Worker first. Before continuing, store the generated MCP token in a password manager or configure the client that will use it; the shell variable is deliberately removed after deployment and cannot be recovered from Cloudflare:

npm run types:mcp
npm run check
mcp_read_token="$(openssl rand -base64 48)"
printf 'Save this MCP token now:\n%s\n' "$mcp_read_token"
printf 'MCP_READ_TOKEN=%s\n' "$mcp_read_token" \
  | npm run deploy:mcp -- --secrets-file /dev/stdin
unset mcp_read_token

For a new account, choose an unused integer namespace_id in the private MCP config before deploying. Existing instances must retain their current private namespace instead of copying the public example again.

Clients call https://bibhub-mcp.<your-workers-subdomain>.workers.dev/mcp with Authorization: Bearer <MCP_READ_TOKEN>.

Self-hosted Node MCP

The Node server exposes the same stateless MCP 2026-07-28 endpoint at /mcp, backed by a separate read-only SQLite connection. A signed-in user creates a named MCP token in the account panel, copies it once, and configures the client with:

Authorization: Bearer fcpat_...

Each token is independently revocable, limited to library:read, and rate-limited separately. The three-tool boundary remains lookup, entries, and bib; the token is rejected on HTTP write routes even when its owner is a curator or owner.

This personal access-token lane is intended for preconfigured laboratory clients. It is not an interactive OAuth authorization server. For arbitrary third-party MCP clients that need browser sign-in, deploy a standards-compliant OAuth 2.1 authorization server and Protected Resource Metadata in front of the endpoint; do not invent a token exchange or pass another service's access token through Field Current.

HTTP routes

Node /api/* routes accept an authenticated user session and enforce the role table above; read-only personal tokens may call GET routes only. Cloudflare and compatibility-mode Node deployments use their configured bearer token. Static assets and /healthz do not. The Node/Docker /readyz endpoint is unauthenticated for local health checks; Cloudflare /readyz requires AUTH_TOKEN so an unauthenticated caller cannot spend D1 reads. Health responses contain no database path, counts, or instance settings. /source is public by design and redirects only to the configured exact Corresponding Source revision.

Method and path Purpose
GET /source Redirect to the exact Corresponding Source for the running AGPL version.
POST /api/auth/login / POST /api/auth/logout Create or revoke a Node browser session.
GET /api/me / POST /api/auth/change-password Read the current account or replace a temporary password.
GET/POST/DELETE /api/tokens... Manage the current user's read-only MCP tokens.
GET /api/lookup?title=... Compare DBLP and arXiv metadata.
GET /api/entries?q=...&repo=... Browse checked entries.
POST /api/entries Add or update one checked entry.
POST /api/import Import a BibTeX batch into a collection.
GET /api/bib?repo=... Export BibTeX.
POST /api/audit / POST /api/rekey Audit or plan/apply cite-key changes.
GET /api/candidates?state=new&limit=50&offset=0 Read a page of the discovery inbox.
POST /api/candidates/review Record import/ignore and atomically promote imports.
POST /api/citations/scan?limit=1 Cross-check citations from checked library seeds.
POST /api/sweep Run discovery on demand.
POST /api/authorships?limit=... Refresh optional OpenAlex evidence.

Public-source boundary

The source distribution contains no library records, production resource IDs, review history, token, API key, database, cache, or author evidence. npm run public:check rejects common instance files, project-specific names, literal credentials, and Cloudflare resource IDs before release.

Do not publish this directory with inherited repository history: old commits can retain data that no longer exists in the current tree. Export the checked tree into a new repository with a new first commit and a public/noreply Git identity. Do not zip the working directory; ignored files are present locally. Export a safe, history-free tree with:

npm run export:public -- ../field-current-public

The command refuses to overwrite an existing destination, copies an explicit allowlist, and runs the public check again inside the exported tree. Initialize a new repository there and make a new first commit with a public/noreply Git identity.

Development

npm ci
npm run build:css
npm run types
npm run types:mcp
npm run check
npm test
npm run public:check
npm run export:public -- /path/to/new-empty-directory

The Node and Worker paths share bibliography, source, rendering, and validation modules. Keep MCP limited to lookup, entries, and bib; write operations belong only to the main authenticated service.

License and corresponding source

Field Current is licensed under AGPL-3.0-only; see LICENSE, NOTICE, and THIRD_PARTY_NOTICES. This directory is an independently licensed subproject when it appears inside a larger repository.

If you run a modified version and let users interact with it over a network, AGPL section 13 requires that those users receive a prominent, no-charge opportunity to obtain that running version's Corresponding Source. Field Current exposes /source in the web UI and publishes the same source location in MCP server metadata. Before exposing an instance, set both:

SOURCE_CODE_URL='https://code.example/field-current/tree/<full-commit-id>'
SOURCE_REVISION='<full-commit-id>'

The URL must identify the source for the version actually running, including a fork's modifications. A tag, moving branch, signed URL, or abbreviated hash is insufficient: the revision must be a full Git SHA-1 or SHA-256 object ID and an exact path segment of the query-free HTTPS URL. If either value is absent or invalid, /source fails closed with 503. Bibliographic records, notes, PDFs, credentials, and other instance data are not part of the software source distribution.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选
mcp-server-qdrant

mcp-server-qdrant

这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。

官方
精选