Aldine
REMOTE · DEMO.ALDINE.DEV · 2 COMPONENTS
Self-hosted collaborative LaTeX editor: read and edit files, typeset, get the errors and the PDF.
Available components
Last scanned (8 hours ago)
Scores higher than 52% of remote servers
Reachable. Last reached 4 Nov 2026.
Category Documents and Files
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security57
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation not yet verified: we couldn't confirm whether this endpoint requires it. View diagnostics → Unverified
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- HSTS check failed: the Strict-Transport-Security header is absent. See how to fix → View diagnostics → Fail
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability77
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 3915 tokens (~230/item across 17 items; 16 tools + 1 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management13
- Stability observed for 4 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage96
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 88% of tool parameters carry a description.Partial
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 16 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 17 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
- Supports UI / widget rendering.Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 3 Nov 26 +1
- Server version: 1.6.0 → 1.7.0 functional
- 2 Nov 26 0
- Server version: 1.5.0 → 1.6.0 functional
- 1 Nov 26 +1
- Tool “trash_project” rewrote its description, which is the text the model reads security
- Tool “batch_write” is now declared destructive security
- Tool “edit_file” is now declared destructive security
- Tool “write_file” is now declared destructive security
- Stability: unverified → 0.03 ▲ functional
- Server version: 1.4.0 → 1.5.0 functional
- Tool “batch_write” changed its title: Change several files in one commit cosmetic
- Tool “commit” changed its title: Commit pending changes cosmetic
- Tool “compile” changed its title: Typeset the project cosmetic
- Tool “create_project” changed its title: Create a project cosmetic
- Tool “edit_file” changed its title: Edit a file cosmetic
- Tool “get_pdf_url” changed its title: Get a link to the PDF cosmetic
- Tool “list_citations” changed its title: List citation keys cosmetic
- Tool “list_labels” changed its title: List labels cosmetic
- Tool “list_projects” changed its title: List projects cosmetic
- Tool “ping” changed its title: Check the connection cosmetic
- Tool “project_structure” changed its title: Show a project's files cosmetic
- Tool “read_file” changed its title: Read a file cosmetic
- Tool “references_add” changed its title: Add a reference by DOI or arXiv id cosmetic
- Tool “trash_project” changed its title: Move a project to the trash cosmetic
- Tool “wordcount” changed its title: Count words cosmetic
- Tool “write_file” changed its title: Write a whole file cosmetic
- 31 Oct 26 64
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 4 Nov 2026 · Probed https://demo.aldine.dev/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=demo.aldine.dev | CN=YE2,O=Let's Encrypt,C=US | 1 Nov 2026 | 30 Jan 2027 | ECDSA 256 | ECDSA-SHA384 | 6f74eddc50ccec982afb4295746f8ece456 |
| SANs: demo.aldine.dev | ||||||
| CN=YE2,O=Let's Encrypt,C=US (CA) | CN=Root YE,O=ISRG,C=US | 3 Sept 2025 | 2 Sept 2028 | ECDSA 384 | ECDSA-SHA384 | 4df3b15dd6c0784c507cd37b58e6f115 |
| CN=Root YE,O=ISRG,C=US (CA) | CN=ISRG Root X2,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | ECDSA 384 | ECDSA-SHA384 | 872165fc34b6e5fba8add5b3705fb53a |
| CN=ISRG Root X2,O=Internet Security Research Group,C=US (CA) | CN=ISRG Root X1,O=Internet Security Research Group,C=US | 13 May 2026 | 2 Sept 2032 | ECDSA 384 | SHA256-RSA | 6c8f1dc727c7117f7baf853ac980f9cd |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of demo.aldine.dev. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| dev. | present | 60074 | 8 | Verified |
| aldine.dev. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication Inconclusive
We could not reach the endpoint well enough to judge its authorisation posture.
| Result | Inconclusive |
|---|---|
| HTTP status | 200 |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://demo.aldine.dev/mcp | Verified | 200 | |
| http (plaintext) | http://demo.aldine.dev/mcp | HTTPS enforced | 308 | https://demo.aldine.dev/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
batch_write Change several files in one commit ~267
Apply one multi-file change as ONE named commit (author Claude). Each entry carries full content (new files) or quote-anchored edits (existing files, same rules as edit_file). All edits resolve before anything is written — a stale_anchor or ambiguous_anchor writes nothing (the error names the entry as path); fix that entry and resend the whole batch. A version_conflict on any entry also writes nothing: re-read that file and resend. Use it for a coherent change across files; use edit_file for a single file. message = the intent, imperative ("Add related-work section"). The result's commit and head are that commit; a batch that leaves every file as it was makes no commit and answers commit:null with unchanged:true (nothing is pending).
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| files | array | yes | – |
| message | string | yes | Commit message stating the intent of the change, at most 200 characters. |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
commit Commit pending changes ~258
Commit the files you have written on this branch that are not yet committed, as one commit under message (author Claude). Only your own paths land: a collaborator's unsaved typing stays out of it and reaches history as their own autosave. Call it when the user asks for a named checkpoint — every write already commits on its own as it lands, so {committed:false} is the normal answer, not a failure: it means they landed already, and the result names the current head and your latest commits on the branch. For a multi-file change you are making right now, use batch_write instead — it writes and commits it in one step under its own message. message titles the commit and replaces the per-file titles those writes would have had.
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| message | string | yes | Commit message stating the intent of the checkpoint, at most 200 characters. |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
compile Typeset the project ~443
Typeset the project with latexmk: parsed errors [{type,file,line,message,context?,source?}] (type "error" rows before "warning" rows, first 50; errorsTotal counts the errors and warningsTotal the warnings, whether or not the list was capped; box warnings are omitted; context is the source line the engine was reading, source the tool that raised a warning — latex, a package name, biber — and a biber row names the .bib and its line), on failure ≤4 KB of the log around the first error, pages, and a deep link into Aldine. With errors present the PDF is complete but the bibliography and cross-references are not rebuilt — say so. pdfUrl is a signed link to this run's PDF that anyone can open for 15 minutes — hand it to the user as the way to see the result, and call get_pdf_url for a fresh link later instead of recompiling. pdfStale:true means this run wrote no PDF: pdfUrl shows the previous one, or is null when that no longer exists. Takes up to ~2 minutes; progress notifications arrive while it runs. Compile after a coherent set of edits, not after each one, and never just to check syntax. On errors: fix and recompile at most 3 times, narrating each attempt ("attempt 2 of 3: added natbib"), then stop and ask the user, quoting the failing file:line. A project with no .tex file cannot be typeset: write the main document first. A compiler-not-responding, compiler-cannot-see-the-project, missing-package (hint), quota, or typeset-already-running error is for the user to act on — relay it, do not retry.
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
create_project Create a project ~207
Create a new project, blank or from a template, and return its id for the write tools, with contentVersion (pass it as base_version to the first write) and the files the template seeded. Needs a token with access to all projects — a project-scoped token cannot create; if refused, relay that to the user (they can mint an unscoped token in Settings → Agent access).
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | Project name shown in the workspace. |
| template | string | – | Template id from the workspace gallery: a folder template ("article", "beamer", "report", "iac-paper") or a venue kit ("venue:neurips", "venue:elsarticle", …; the publisher's class files are download… |
No output schema declared.
No examples provided.
edit_file Edit a file ~565
Replace exact quoted text inside an existing file — the default way to change a document, and the only safe way to change one a person has open (edits merge with their live typing; write_file would discard it). Each quote: ≥8 characters, copied verbatim from a read, matching exactly one place (or set occurrence). Nothing is applied on any error result. {error:"stale_anchor"}: the quote is not in the file — re-read it, re-anchor from the candidates, retry; at most 2 retries, then tell the user what you tried and ask. {error:"ambiguous_anchor"}: the quote matches several places — the candidates carry the occurrence that picks each; resend with it, no re-read needed. {error:"version_conflict"}: this file changed after the read that base_version came from (writes to other files never conflict, so parallel tools on different files are safe) — re-read this file, then re-apply once. Committed as author Claude before the tool answers, under message (the intent, imperative — "Tighten the abstract"); without one the commit is titled "Edit <path>". The result's commit and head are that commit; an edit that leaves the file as it was makes no commit and answers commit:null with unchanged:true (nothing is pending).
| Name | Type | Req | Description |
|---|---|---|---|
| base_version | integer | – | contentVersion (or fileVersion) from your read of this file, or contentVersion from project_structure for a file you are creating. Refused with {error:"version_conflict", reason, currentVersion, file… |
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| edits | array | yes | – |
| message | string | – | Commit message stating the intent of this change, imperative ("Tighten the abstract"), at most 200 characters. It titles the commit in the History panel; every call is one commit. |
| path | string | yes | File path relative to the project root, e.g. "main.tex" or "sections/intro.tex" — no leading "/", no "..", and hidden folders (.git, .aldine-out) are off limits. |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
get_pdf_url Get a link to the PDF ~209
A fresh signed link to the PDF on disk for the branch, without recompiling — use it when a compile result's pdfUrl has expired (15 minutes) or the user asks to see the PDF again. Returns {pdfUrl, pdfFile, pages, typesetAt, deepLink}; pdfStale is always false here because the link is to that file, whichever typeset wrote it (by you or by a person). It does not contain edits made since that typeset: if you have written on this branch since your last compile result, call compile instead. No output yet → compile first.
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
list_citations List citation keys ~142
Citation keys defined in the project's .bib files: [{key, title, author, year, file}]. Always call it before writing a \cite — never invent a key. A key you need that is missing: add it with references_add, or ask the user.
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
list_labels List labels ~124
\label targets defined in the project's .tex files: [{label, file}]. Call it before writing \ref, \eqref, or \cref — never invent a label.
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
list_projects List projects ~72
List the LaTeX projects this token can reach: id, name, branches, rootFile, engine, agentCreated (true for projects made with create_project — the only ones trash_project accepts). Call it when you do not know the project id. A token scoped to one project makes the project argument optional everywhere.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
ping Check the connection ~47
Check that the Aldine connector is reachable and authenticated. If it fails, tell the user their Aldine instance is not responding or the connector needs reconnecting — do not go on to other tools.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
project_structure Show a project's files ~146
File tree of a project branch plus rootFile, engine, and contentVersion (pass it as base_version to edit_file, write_file or a batch_write entry — a write is refused only when its own file changed after that version). Call it before working in a project you have not read yet.
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
read_file Read a file ~275
Read a text file as the editor shows it right now (open documents are flushed first). Reads cap at ~100 KB — window larger files with from_line/to_line (1-based, inclusive; the result echoes the window it served, to_line clamped to the last line). Read before you edit: edit_file quotes must match this content verbatim. The result carries contentVersion (the branch version — pass it as base_version when you write this file) and fileVersion (the version at which this file itself last changed). Text is decided by content, not extension: a file with binary bytes is refused.
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| from_line | integer | – | – |
| path | string | yes | File path relative to the project root, e.g. "main.tex" or "sections/intro.tex" — no leading "/", no "..", and hidden folders (.git, .aldine-out) are off limits. |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
| to_line | integer | – | – |
No output schema declared.
No examples provided.
references_add Add a reference by DOI or arXiv id ~341
Resolve a DOI, doi.org URL, arXiv id, or OpenAlex id to a BibTeX entry and append it to a .bib file on the branch (default: references.bib next to the root file). A bibFile that does not exist is created, folders included (created:true in the result). Returns {key, bibFile, duplicate, created} — use \cite{key} right away; a note says when no .tex on the branch loads that .bib (\addbibresource or \bibliography), in which case the citation stays undefined until one does. Titles are not lookups: for a paper you only know by name, ask the user for its DOI or arXiv id. If the lookup budget is reached or the upstream service fails, tell the user — do not retry in a loop.
| Name | Type | Req | Description |
|---|---|---|---|
| bibFile | string | – | Target .bib path relative to the project root. Defaults to references.bib beside the root file; a missing file (and its folders) is created. |
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
| query | string | yes | A DOI (10.xxxx/…), doi.org URL, arXiv id (2301.12345 or arXiv:2301.12345), or OpenAlex id (W…). |
No output schema declared.
No examples provided.
trash_project Move a project to the trash ~156
Move a project that was created with create_project to the trash, where its owner can restore it from the workspace for 30 days; nothing in Aldine is deleted for good by this tool, but a GitLab repository Aldine provisioned for the project is deleted (a restore provisions a new one). Refused for any project a person created (agentCreated:false in list_projects) — ask them to delete it in Aldine themselves — and for projects the token's owner does not own. Use it for scratch projects the user asked you to throw away; never on your own initiative.
| Name | Type | Req | Description |
|---|---|---|---|
| project | string | yes | Project id (from list_projects or create_project). Required: this tool never falls back to a scoped token's project. |
No output schema declared.
No examples provided.
wordcount Count words ~149
Word count of the document as it compiles — the root file plus its \input/\include graph, commands and comments excluded: {rootFile, total, files}. Use it for length questions instead of estimating from source. A project with no main document yet is an error, not a count of 0.
| Name | Type | Req | Description |
|---|---|---|---|
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
write_file Write a whole file ~488
Create a new file, or replace a whole file. For an existing file prefer edit_file — a whole-file write on an open document teleports collaborators' viewports and can drop their in-flight typing. Pass base_version (contentVersion from a prior read of this file) to get {error:"version_conflict"} instead of overwriting newer content — only a change to this file conflicts, never one to another file; on conflict re-read and re-write once, then ask. Folders come into being with the first file written inside them. The first .tex written into a project with no main document becomes the main document (newRoot in the result). Committed as author Claude before the tool answers, under message (the intent, imperative); without one the commit is titled "Update <path>". The result's commit and head are that commit; content identical to the file makes no commit and answers commit:null with unchanged:true (nothing is pending).
| Name | Type | Req | Description |
|---|---|---|---|
| base_version | integer | – | contentVersion (or fileVersion) from your read of this file, or contentVersion from project_structure for a file you are creating. Refused with {error:"version_conflict", reason, currentVersion, file… |
| branch | string | – | Branch name (defaults to 'main'). Every result, error results included, echoes {branch, head} — head is the branch's current commit (after a write, the commit that write made). Pass the branch explic… |
| content | string | yes | – |
| message | string | – | Commit message stating the intent of this change, imperative ("Tighten the abstract"), at most 200 characters. It titles the commit in the History panel; every call is one commit. |
| path | string | yes | File path relative to the project root, e.g. "main.tex" or "sections/intro.tex" — no leading "/", no "..", and hidden folders (.git, .aldine-out) are off limits. |
| project | string | – | Project id. Optional when the access token is scoped to exactly one project. |
No output schema declared.
No examples provided.
How do I install the Aldine MCP server?
Aldine is a hosted endpoint at https://demo.aldine.dev/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · demo.aldine.dev
claude mcp add --transport http trahloff-aldine 'https://demo.aldine.dev/mcp'
What is the Aldine MCP server?
Aldine is an MCP server listed in the public MCP registry as io.github.trahloff/aldine. Self-hosted collaborative LaTeX editor: read and edit files, typeset, get the errors and the PDF. This page covers its hosted endpoint (https://demo.aldine.dev/mcp).
Is the Aldine MCP server safe to use?
Aldine scores 66 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Aldine MCP server expose?
Aldine exposes 16 tools: ping, list_projects, project_structure, read_file, edit_file, and 11 more. Their descriptions and schemas cost roughly 3,889 tokens of context every time the server is loaded.
Does the Aldine MCP server require authentication?
Its publisher declares no required credentials for Aldine. We have not been able to confirm that against the live endpoint, and a server can require authorisation without declaring it here.
Is the Aldine MCP server still maintained?
Aldine is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.