Changelog
All notable changes to anthroposophy.ai are documented in this file.
The format follows Keep a Changelog. Versioning follows Semantic Versioning.
1.3.0 - 2026-10-21
Reply shape of the subject index, paragraph ranges, per-lecture credit
This release changes the default reply of fetch_index_entry, serves a range of paragraphs, resolves the translator of an English text per lecture rather than per volume, rates English–German paragraph alignment from verified pairings only, labels each lecture's record type (including unknown), and separates the edition's lecture title from a heading the site wrote.
Discipline: a translation_credit with status: not_established names no translator; do not supply one. alignment_confidence is now a statement about verified paragraph pairings; paragraph_aligned: false on a passage means the German beside it is the paragraph of the same number, not a verified counterpart. site_heading is the site's wording, never the edition's; cite a lecture by the edition's title. A record_type of unknown means the edition's note on sources has not been read, not that the text is a stenogram. An index reference with neither a paragraph nor whole was listed before the pinning rule and does not say where in the unit to read.
Added
fetch_index_entry:detail(compact,headings,full). The default iscompactfor an entry whose compact reply is at most 20,000 characters andheadingsotherwise; aheadingsreply carries the definition section's references.sectionaccepts several ids or headings (a list, or comma-separated in REST). Every reply states itsdetailand how to ask for the others. REST twins:GET /v1/steiner/indexandGET /v1/steiner/index/<entry>?detail=§ion=.fetch_passage:through(a later paragraph of the same unit, at most 12 paragraphs); the reply names the span asGA n/<unit>/pNNN-pMMMwithextent: "range"and carries the aligned other-language paragraphs asaligned_witnesswhere pairings exist. Span URLs/v1/<corpus>/<lang>/ga/<ga>/<unit>/pNNN-pMMM.jsonand the HTML form;passage_jsonpasseswindowandthrough. Lecture pages carry a three-digit anchor per paragraph (#p003); old#p3links are redirected on the page.translation_credit.status(established,not_established, withreason) resolved per unit from the lecture's own source page;witness_qualityvaluesnot_established,automated,original_english.unit_kindon passages and lecture listings of suffixed units (second_lecture_same_day,second_translationwithsame_lecture_asandgerman_repeats,duplicate_text,second_piece_same_name,same_lecture_second_id,undetermined). Unit ids are unchanged.site_heading(nullable) andsite_heading_noteon every reply that names a unit;/about/site-headings/explains the field. Lecture pages show the edition's title with the site heading as a marked subtitle.record_type: "unknown"on every lecture unit with no record type on file;recordonfetch_lecture;evidence_sourceon volume rows andsourceon unit rows of the record-type data. Subject index rows show arecord unknownbadge, the place of delivery and the translator (or "no translator on record").alignment_reasonvalues from the pairing loader (beads:<method>,identity_contradicted,paragraph_counts_match);fetch_parallelstates each edition's reason.- Index references carry
extent(paragraph,rangeorunit),throughon a range (at most 12 paragraphs; its links go to the span) andwhole: truewhere the unit treats the heading's subject throughout;fetch_index_entrycompact rows gain a sixth column,whole; the record schema (/index/data/schema.json) lists the three fields. section_aliaseson index entries: names that lead to one heading of an entry rather than the whole entry (lesser guardian,greater guardianand their German forms, inguardian-of-the-threshold).fetch_index_entrygiven such a name returns that section withleads_to_sectionandleads_to_note; theindex_entrypointer onsearch_steinercarries the section.- A unit served under a slug can also be resolved by its date when exactly one unit carries that date and none is served under it (GA 98, 7 November 1907).
Changed
fetch_index_entrydefault reply iscompact(was the full record);compactandheadingsreplies are minified JSON. Entry lookup foldsae/oe/ue/ssand umlauts both ways, ignores case and a leading article.alignment_confidenceis taken from verified paragraph pairings; a rating that rests only on equal paragraph counts is at mostmedium.paragraph_alignedis true only where a pairing exists.translation_creditis resolved per unit; a volume's credit is no longer applied to its lectures.- Translator's endnotes are served as notes with speaker
the translator. - Server instructions and tool descriptions updated for the above; mirrored to
/llms.txt. MCP serverversionandSERVER_VERSIONare1.3.0.
Fixed
- Website navigation text at the tail of the GA 1f German files was served as passages; removed.
- GA 254, 10 October 1915 (German): two paragraphs joined by a column mark are split; later paragraph numbers in that unit move by one.
- GA 254 (German): misreadings corrected per the repair manifest.
- GA 82, 12 April 1922 (German and English): a paragraph repeated in the source text is served once; later paragraph numbers in that unit move down by one.
- GA 162, 24 May 1915 (English): paragraph 33 held the lecture's text twice and now holds its own text only; a misreading (
&for a letter) is corrected in both languages. - Sentences split across two paragraphs by a page break or a picture line are joined (GA 115, 4 November 1910; GA 35; further units found by the same scan), and paragraphs that repeated another paragraph's text are removed (GA 28, 29, 70b, 326); later paragraph numbers in an affected unit move down. Subject-index references follow the new numbers.
1.2.1 - 2026-10-19
Register of the Gesamtausgabe
This release makes the register of the Gesamtausgabe at /contents/ available to agents. The register lists every item of the edition that the publisher's catalogs, the archive's completion sheet, AnthroWiki or the English bookseller name, whether or not the site serves its text: the numbered volumes, numbers published only as sub-volumes, empty and superseded numbers, the art volumes of the K series, the digital notebook edition, announced companion volumes and the Beiträge booklets. Each record states whether the site serves German and English, the source of each served text, the editions and translations known, and the witness for every fact.
- Number lookup.
fetch_ga_registerresolves a GA number in any written form (GA 266/I,266a,K 58/1,eGA 47/48,Heft 24) to its register record. - Absence explained. A
search_steinercall scoped to a volume the corpus does not hold carriesregister_entry, stating what the number is: an empty number, an art volume, a volume not served.
Discipline: the register is bibliographic data, never Steiner's words; fetch passages before saying what a volume contains. Translations listed as known but not served are bibliography, not text the server holds. Where witnesses disagree, the record gives the candidates side by side.
Added
fetch_ga_registerMCP tool:ga(a number in any written form;*lists the edition,beitraegethe booklet series) and optionalscope(audited,parent,empty_number,superseded_number,art,digital_edition,companion,beitraege). Every fact is{value, w},wnaming keys of the record'switnesses. A miss returnsnot_in_registerwithdid_you_mean.register_entryonsearch_steinerresponses withabsence_signal='volume_not_held': the number's scope, titles, served state, and its HTML and JSON URLs.- Register data at
/contents/data/:ga.json(the listing), one<slug>.jsonper item (the number with/written-),beitraege.jsonandga.csv.
Changed
- Server instructions: bibliographic questions about a GA number are answered from
fetch_ga_register. Mirrored to/llms.txt. - MCP server
versionandSERVER_VERSIONare1.2.1.
1.2.0 - 2026-10-09
Concept index
This release adds a concept index at /index/. Each entry lists the chapters and lectures of the Gesamtausgabe where its concept is treated, under sub-headings: Steiner's own books (GA 1 to 28) first, then articles (GA 29 to 46), then lectures in date order. An entry contains no quotations. Every reference is a locus verified against the served corpus when the entry is built; a paragraph number is given only where one passage is the point.
- Orientation before keyword search. Unscoped searches whose query names an indexed concept, by its headword or an alias in English or German, carry an
index_entrypointer ahead of the hits. Search ranks by word frequency; the entry lists where the concept is treated. - Entry retrieval.
fetch_index_entryreturns an entry by id, headword or alias, whole or one sub-heading at a time. Each reference carries the GA volume and its title, the served unit id, language, edition, witnesses, record type where the publisher states one, and the viewer and JSON URLs for fetching the text.
Discipline: an entry says where to read, not what the text says. Its headings and scope lines are the index's wording, never Steiner's; quote only what fetch_passage returns. entry_not_found means no entry exists yet, not that the corpus is silent on the concept.
Added
/index/: one page per entry, served as HTML and as JSON at/index/data/<id>.json, with the record schema at/index/data/schema.json(index-entry/1.0) and a listing at/index/data/index.json. The HTML page shows the fields of the JSON record and nothing else.fetch_index_entryMCP tool:entry(id, headword or alias;*lists the entries) and optionalsection. A miss returnsentry_not_foundwithdid_you_mean.index_entryonsearch_steiner,search_anthroposophyand/v1/steiner/searchresponses when the query names an indexed concept and noga,ga_rangeor date filter is set: the entry's id, headwords, sub-headings with reference counts, and its HTML and JSON URLs. Placed first in the envelope.index_entryon atrace_claimsnode_not_foundresponse when the node names an indexed concept.
Changed
- Server instructions: concept-level questions start from
fetch_index_entry, and theindex_entrypointer is read before the hits. Mirrored to/llms.txt. - Site navigation includes Index.
- MCP server
versionandSERVER_VERSIONare1.2.0.
1.1.5 - 2026-08-27
Research workflows
This release makes the server's negative answers say what they are answers to, and answers three questions quote_safe never answered: who is speaking in a passage, how the volume was recorded, and how good a witness a translation is. The work reached production in three same-day deploys, briefly numbered 1.1.5 to 1.1.7; it is one release.
- Search for two words near each other.
word NEAR/10 wordnow executes. It was previously rejected as invalid syntax, rewritten into literal words, and the zero returned as an authoritative co-occurrence absence. - Tell a rewritten query from the one you sent. Responses carry
query_as_run. A sanitizer-rewritten query returnsabsence_signal='query_rewritten', which is not authoritative for the original; relaxation still runs on the content words. - Read what a phrase zero settles. A phrase or proximity zero keeps its verdict and empty
hitsand adds arelaxedblock: operators dropped, content words swept, andterm_document_countsper word — which separates 'never occur together' from 'absent'. - See how much of the original a translation holds.
witness_completenessgives the witness's word ratio to the original, banded, on passages, lectures and volumes. A translation that omits passages while reading as continuous prose is detectable before it is quoted from. - Tell who is speaking.
authorshipresolves the passage: a labelled transcript turn, prose written about Steiner in the third person, an editor's footnote, or a character's line in a drama — two of those volumes being not his composition at all. - Weigh the record and the translator.
recordgives the volume's record type where the publisher's subtitle states it.witness_qualitynames the translator or reports none recorded, and compares the passage's load-bearing names with its aligned German. - Read a German snippet. Snippets were rendered from the normalized index, so German arrived stemmed —
der zweit brief wird entsiegelt. They are now cut from the source text with the matched words marked. - Recognise a second locus as the same witness. 195 groups of lectures hold byte-identical text under two or three ids. Hits and passages carry
also_served_as.
Discipline: a 0-hit is authoritative that the queried wording cannot be quoted, never that the corpus lacks the idea; the instructions now say so where they previously said the opposite. quote_safe certifies the bytes only — speaker, record type, completeness and translation fidelity are separate fields. A clean entity_parity checks names alone, and a mismatch can equally mean a wrong alignment. Snippets remain non-quotable, and two loci in also_served_as are one witness, not two.
Added
query_as_runon every search response, and threeabsence_signalvalues:query_rewritten(the sanitizer rewrote the query, so the zero is not authoritative for the original),volume_not_held(thega=filter names a volume not in the corpus),translation_may_be_abridged(aga=-scoped zero in a translation under 75% of the original).relaxedblock on phrase, proximity and boolean zeros:operators_dropped,term_document_counts, andbroadwith a note when a single-word sweep exceeds 500 passages. Relaxed passages are never merged intohits.witness_completenessonfetch_passage,fetch_lectureand the volume endpoint:ratio,band,may_be_abridgedand the two word counts. Bands areseverebelow 0.50,shortbelow 0.75,watchbelow 0.85,comparableto 1.35,fuller_than_originalabove; under a 500-word original the ratio readstoo_short_to_judge.verify_locuswarns when a witness of the locus is abridged.authorshipresolves the speaker at passage level from four signals, most specific first: an editor's[^n]:footnote, a transcript speaker label, the per-lecture map, third-person prose. Newkindvaluesdialogue,report(is_steiner: null),dramatis_persona(withauthor),adapted_work(GA 42, GA 43) andeditorial. Labels come from a map of those recurring three or more times in their volume.recordon hits andfetch_passage: volume record type —stenogram,listeners_notes,own_manuscript,mixed_sources— with the publisher's subtitle as evidence. An absentrecordmeans unknown.witness_qualityon translation passages:translator(orstatus='unknown', which includes a credit naming only a publisher) andentity_parityagainst the aligned German, withmissing_from_translation,bead_confidenceand alikely_cause. Passages under 25 words, or with no alignment bead, readnot_checkable.also_served_as: the other lecture ids carrying byte-identical text, noted as the same witness rather than independent attestations.
Changed
- Server instructions: a 0-hit is described as authoritative that the wording cannot be quoted, not that the phrasing is absent from the corpus, and the
authorship.kindvocabulary is documented. The byte-for-byte quoting rule is unchanged. Mirrored to/llms.txt. - Phrase, proximity and boolean zeros are now relaxed into the
relaxedblock; such queries were previously never relaxed.hits,absence_signaland the verdict are unchanged. German phrase zeros sweep the query's capitalized nouns first. - Search snippets are rendered from the passage text rather than the normalized index, anchored on terms of four characters or more so articles do not draw the marks.
snippet_is_verbatimremainsfalse. - Advice arrays are tiered per MCP session: quotation and attribution lines accompany every response, the remaining guidance is sent on each tool's first call per session.
german_anchoron an unaligned bead reportsNOT ALIGNEDand notes the German may hold the content under different numbering; it previously reported a gap in the German original.- MCP server
versionandSERVER_VERSIONare1.1.5. The intermediate1.1.6and1.1.7values, served for about an hour during the day's staged deploys, describe this same surface.
Fixed
word NEAR/N wordraised a syntax error, was rewritten by the sanitizer into literal words including the operator itself, returned zero, and the zero was certified as verbatim co-occurrence absence. The infix form is rewritten toNEAR(a b, N)and executed; the tool documentation, which called NEAR both unsupported and supported, is consistent.- A
ga=filter naming a volume absent from the corpus returned a missing-language message listing no available languages. - A society annual report, a questioner's turn, an editor's footnote and a character's line in a drama were served with no authorship field, which by the corpus's stated default meant attributed to Rudolf Steiner.
- An edition credit naming a publisher with a null translator was served as a filled-in credit.
- German snippets were unreadable: the index stores stemmed, case-folded, diacritic-stripped text and
snippet()rendered from it. fetch_passageraised an operational error against a database without theparagraph_aligntable.
1.1.4 - 2026-07-06
Research workflows
This release serves quote-level verification — the byte-for-byte quotation discipline as an API operation rather than a client-side re-implementation — and fixes the bare-/mcp connector failure.
- Verify a quotation before printing it.
verify_quoteon a candidate inherited from the secondary literature returnsnear_misswith a word-level diff against the closest corpus window and the verbatim span at its locus — an inherited misquote is caught in one call instead of propagated. - Audit a document’s quote ledger in one call. Batch mode takes up to 50 quote+locus pairs and returns per-item verdicts plus an
all_quote_safesummary — a published artifact’s “verified” claim can be the API’s output rather than the author’s promise. - Locate a quote whose wording differs across editions. Without a locus,
verify_quotelocates candidates corpus-wide and checks every (lang, edition) witness, so a quotation taken from any indexed translation resolves to its locus. - Review an elision’s surroundings in one call.
fetch_passagewithwindow=Nreturns the passage plus up to N neighbors per side undercontext.before/context.after— checking that an ellipsis in a spliced quotation hides nothing meaning-inverting no longer costs one call per neighbor.
Discipline: only quote_safe: true clears a candidate for quotation marks. match_normalized means the wording matches but the typography does not — quote match.verbatim_text exactly as returned, never your candidate. near_miss means the corpus reads differently; quoting the candidate propagates drift. A locus-scoped no_match is authoritative for that locus; a corpus-search no_match is strong evidence of absence, not proof.
Added
- Tool
verify_quote: quote-level verification.verify_locusproves a locus exists; this proves a quotation matches. Single mode takescandidatewith optional scope (ga+lecture(+passage_number),lang,edition); batch mode takesquotes[](max 50) and returns per-item results plus a summary withall_quote_safe. Verdicts, strongest first:match(byte-for-byte substring of a witness; quote-safe),match_normalized(matches after typographic normalization only — quote style, dash family, whitespace runs, emphasis markers; not quote-safe;match.verbatim_textcarries the exact span to quote instead),match_spliced(candidate contains ellipses; every fragment matched in order within one lecture; quote-safe only when every fragment matched byte-for-byte),near_miss(closest corpus window, withsimilarityand a word-leveldifferencesdiff;near_miss.corpus_textcarries the verbatim span),no_match. Without a locus the check locates candidates corpus-wide via full-text search (exact phrase first, then bag-of-words with 0-hit relaxation); a locus-scopedno_matchis authoritative for that locus, a corpus-searchno_matchis strong evidence of absence, not proof. All (lang, edition) witnesses are checked by default, so a quotation from any indexed translation can be located. REST equivalent:POST /v1/steiner/verify-quote. Deployed 2026-07-06. fetch_passageparameterwindow(integer 0-5, default 0): returns up to N neighboring passages per side — same lecture, same lang + edition — undercontext.before/context.after, each with verbatim text, locus, and URL. One call to review the surroundings of a passage, e.g. the text elided by an ellipsis in a spliced quotation. Also on the REST passage endpoints as?window=N. Deployed 2026-07-06.
Changed
- MCP
tools/listreturns 19 tools (5 GA + 7 FMC + 5 sources + 2 claim-registry). - Server instructions extended: candidate quotations — especially those inherited from secondary literature or model memory — should be checked with
verify_quotebefore being placed inside quotation marks; onlyquote_safe: trueclears a candidate. - MCP server
versionandSERVER_VERSIONbumped to1.1.4. - Per-IP rate limiting is now enforced on both the REST and MCP surfaces (app-level token bucket, ~240 requests/minute/IP). Over-limit requests receive
429 Too Many Requestswith aRetry-Afterheader. This is generous flood protection, not a precise quota — a considerate client rarely encounters it; batch where the surface supports it (verify_quoteledger mode) and prefer targeted fetches over sweeps. - Search boolean operators are now normalized operator-aware: query operands are stemmed and case-folded while uppercase
OR/AND/NOT/NEAR, quoted phrases, prefix*, and column filters are preserved. Previously the query normalizer lowercased the whole query, demoting FTS5’s uppercase-only operators to literal terms, so anORunion became an implicit-AND and could return an authoritative zero where the individual terms matched — a manufactured verbatim-absence. A 0-hit now reportsabsence_signalall_alternatives_absentfor anORunion (every alternative absent) distinctly fromexact_phrase_absentfor a phrase/AND/NEARco-occurrence miss. Related surface additions:two_voice_volumeon search hits andfetch_passage(with anattribution_warningon the passage) flags correspondence volumes where a passage may be a letter by a correspondent rather than by Steiner;edition_coverage({lang: [editions]}) accompanies any single-gasearch andfetch_passage, and a 0-hit in a language a volume lacks returnsabsence_signal=language_not_availablerather than topical absence;fields=compact(REST?fields=compact) drops per-hitavailable_versions[]and edition metadata for large result sets; andgawithfrom_date/to_dateis documented as the scoping recipe for locating a passage within a long lecture. Deployed 2026-07-07. - Search hits and
fetch_passagenow carry anauthorshipobject on the corpus’s non-Steiner-bearing loci — correspondence letters, question-and-answer / discussion sessions, and editorial apparatus — resolving the speaker at lecture granularity, finer than the volume-leveltwo_voice_volumeflag.authorship.is_steinerisfalsewith a namedspeakerwhere a passage is authored by a correspondent, a questioner session, or an editor (not to be quoted as Steiner),truefor Steiner’s own hand (theattribution_warningis then suppressed), andnullwhere the source leaves the hand open; an absentauthorshipfield means the passage is attributed to Steiner. This narrows attribution from the whole volume to the individual lecture, so a question-and-answer session or a correspondent’s letter is flagged even in a volume the coarse flag does not cover. Deployed 2026-07-07.
Fixed
- MCP transport: requests to the bare
/mcppath (no trailing slash) received307 Temporary Redirectto/mcp/. MCP clients that do not follow redirects never completedinitialize, so connectors configured with the bare URL attached no tools. Both/mcpand/mcp/now serve the streamable-HTTP transport directly, with no redirect hop. The redirect had been present since the MCP endpoint first shipped; it surfaced when connector-side redirect handling changed. Deployed 2026-07-06.
1.1.3 - 2026-06-11
Research workflows
This release adds schema-set enumeration and documents the claim-registry tools deployed 2026-06-04.
- Enumerate the FMC schema set.
list_fmc_schemaspages the full set in deterministic id order (total_countplus offset/limit echo). Schemas were previously retrievable only individually byFMC00.NNNid; no enumeration path existed. - Filter schemas by topic or id range.
querymatches description text and linked-page slugs (descriptions are sparse upstream; linked pages carry most of the topical signal).prefixscopes an id range, e.g.prefix="FMC00.5". - Image retrieval handoff. Entries with
image_only: truecarry no usable description; pass the sameschema_idtofetch_fmc_schema_imagefor the diagram as inline ImageContent.fetch_fmc_schemaremains the single-schema detail record. - Trace registered claims.
trace_claims(node)returns registered claims touching a concept or work: typed relations with up to three verbatim anchors each (leg_a,leg_b,witness), every anchor carrying its locus, edition, content hash, and fetch URL.mode="divergence"restricts results to divergence claims. - Re-verify a claim before asserting it.
verify_claim(claim_id)re-runs a registered claim against the serving corpora: each anchored leg is checked by content-hash (registry integrity) and re-fetch (corpus drift). Per-leg verdicts:anchor_present,anchor_missing,hash_mismatch,fetch_error.
Discipline: list_fmc_schemas entries are curatorial_content — cite as ‘FMC schema FMC00.NNN (FMC curator, anthroposophy.eu, CC-BY-SA)’; descriptions are paraphrase and never go inside quotation marks. For claims, quote only anchor_text, byte-for-byte, and report relation types as given. node_not_found from trace_claims means no claims are registered for that node, not that the corpora are silent — use search_steiner / search_sources for frontier research. The registry’s selection principle (steinerian-anthroposophical) is named in every envelope.
Added
- Tool
list_fmc_schemas: enumeration and filtered discovery over the FMC schema set. Filters:prefix(schema-id prefix),query(case-insensitive substring over description text and linked-page slugs). Per-schema fields:schema_id,description(null when none exists),schema_image_url,linked_pages,page_url, andimage_only(the signal to callfetch_fmc_schema_image). Deterministic schema_id ordering withtotal_countand offset/limit echo. Closes the schema-discovery gap: the wiki’s schema-listing page is outside the mirror’s indexed namespace, sofetch_fmc_pagecould not reach it. - Tool
trace_claims(deployed 2026-06-04; documented here): registered claims touching a concept or work — typed relations across the corpora (Steiner GA, Bible, Aquinas, Church Fathers, Bhagavad Gita, and the other /sources/ works). Each claim carries a relation type (direct_citation,commentary_on,doctrinal_appropriation,thematic_affinity,ambient_influence,doctrinal_contrast,interpretive_continuation,complementary_polarity), amode_tag(resonance | divergence), a statement, and up to three verbatim anchors (leg_a,leg_b,witness) with loci, editions, content hashes, and fetch URLs.relation_sourceidentifies the asserting layer (curated / registered / citation_index / summary_engagement); machine-derived edges are weaker evidence than curated ones. The registry is compiled from reviewed claim files and deployed as an artifact; no write path is exposed on the public surface. - Tool
verify_claim(deployed 2026-06-04; documented here): live re-verification of a registered claim. Each anchored leg is checked by content-hash against the registry (integrity) and re-fetch against the serving corpora (drift). Per-leg verdicts:anchor_present,anchor_missing(treat the claim as unverified),hash_mismatch(registry integrity failure),fetch_error(infrastructure, not drift).ok=truemeans every anchored leg verified atverified_at. Claim ids come fromtrace_claimsenvelopes (edges[].claim_id).
Changed
- MCP
tools/listreturns 18 tools (4 GA + 7 FMC + 5 sources + 2 claim-registry). Corrects the 1.1.2 entry, which stated 14; the count at 1.1.2 was 15 (search_anthroposophyomitted from its FMC arithmetic). - MCP server
versionandSERVER_VERSIONbumped to1.1.3. The serverversionfield now references theSERVER_VERSIONconstant instead of carrying a second literal; the two values had drifted apart twice before 1.1.2.
1.1.2 - 2026-05-23
Research workflows
This release adds the /sources/ corpus. It is curated by Steiner-engagement, not by canon — these are the foundational texts the GA itself takes up.
- From a Steiner lecture to its source text.
find_source_chapters_for_ga_locus("GA 142, 1912-12-28")returns the Sources chapters the curator has linked to that lecture (Bhagavad Gita Discourses, Mahabharata Parvas, the Pauline epistles as the GA 142 counterpart text).fetch_source_chapterthen quotes the verses verbatim. - From a foundational text to Steiner’s treatment of it.
fetch_source_summaryon the Kaṭha Upanishad or De Anima Book II names the verified GA loci where Steiner engages it;fetch_passagereturns his actual words. - Cross-corpus surveys in a single call.
search_anthroposophy(query=..., corpus="all")fans GA + Free Man Creator (FMC) + Sources together, distinguishing hits by[ga] / [fmc] / [sources]tags with per-corpus totals. - Honest gap-detection. When the curator has examined a chapter and Steiner did not engage it,
steiner_status: "not_engaged"marks the absence explicitly. Aristotle’s De Anima carries this flag. - Stream-filtered comparative work.
search_sources(stream="indian")scopes to Vedic / Upanishadic / Gita / Mahabharata material;stream="greco-christian"to Patrologia + Aristotle + Aquinas + Hermetic Corpus;stream="western-european"to the Beguine + Rhineland + Theosophical + Goethean strands. - Curator’s cross-tradition congruences as named syntheses. Each summary surfaces the FMC curator’s explicit cross-tradition observations (e.g. De Anima’s tripartite soul ↔ Vedanta’s pancha-kosha ↔ Plotinus’s nous-triad ↔ Kabbalah’s nefesh / ruach / neshamah) as paraphrase the curator owns, never as quotes from those traditions.
Discipline: only fetch_source_chapter is quote-safe (quote_safe=true). fetch_source_summary, find_source_chapters_for_ga_locus, and every steiner_loci.statement field are FMC-curatorial paraphrase (quote_safe=false) — they capture the verified loci but they never go inside quotation marks.
Added
/sources/corpus integration — Sacred, Inspired and Foundational Texts across 5 wisdom-streams (Indian, Persian, Egyptian-Hebrew, Greco-Christian, Western-European). Vedic scripture, the Greek-philosophical tradition (Aristotle, Plato, Plotinus), Patrologia (Church Fathers), Aquinas (Summa Theologiae + Summa Contra Gentiles), Beguine + Rhineland mysticism, Hermetic Corpus, Rosicrucian Manifestos, Theosophical inheritance (Isis Unveiled, Secret Doctrine, Mahatma Letters), Goethean works.- Tool
search_sources: full-text search over /sources/ chapters. Filters:work,lang,edition,stream,tradition,form,year_from,year_to. Returns ranked chapter hits withchapter_locus, snippet, curatorial blurb, andsummary_url(when present) pointing at the FMC-curatorial paraphrase block. - Tool
fetch_source_chapter: retrieve verbatim chapter text bychapter_locus(<work>[/<subwork>...]/<chapter>). Returnstext_trust='verbatim',quote_safe=true, parent breadcrumbs, descriptor subtitle + blurb, andavailable_versions[]. Use to obtain quote-safe text from /sources/. - Tool
fetch_source_summary: retrieve the FMC-curatorial paraphrase block for a chapter or work — theme, soul-faculty, Steiner engagement (paraphrase + verified GA loci, or the honesty-gap sentinel “not engaged in the GA corpus”), cross-tradition congruences.text_trust='paraphrase',quote_safe=false. The structural verbatim-vs-paraphrase split that prevents accidental quotation of curator-summary content. - Tool
list_source_works: discovery — enumerate /sources/ works bystream,tradition,form,parent_locus,top_level_only,has_summary. Returns work_locus, name, tradition, year_approx, chapter_count, word_count, landing_url, summary_url. - Tool
find_source_chapters_for_ga_locus: reverse cross-reference (sources → GA). Given a GA locus (GA 142, 1912-12-28) or volume (142), returns which /sources/ chapters cite that lecture, with paraphrase statements. Driven by thesources_ga_xrefbridge, populated from chapter and work summaries. search_anthroposophyumbrella extended withcorpus='sources'andcorpus='all'.'all'fans GA + FMC + sources in a single call with round-robin interleave;'both'remains the back-compat default (GA + FMC). Response carriessources_totalalongsidega_totalandfmc_total.- Tool
fetch_fmc_schema_image: returns inline ImageContent for FMC schemas, mirror-first with upstream fallback. Resolves the image-fetch gap where MCP clients could not follow MediaWiki redirects to the upstream JPEGs.
Changed
- Top-of-document Quotation discipline (read first) block in server
instructionsextended with a /sources/ paragraph.fetch_source_chapterreturns quote-safe text (text_trust='verbatim');fetch_source_summaryreturns FMC-curatorial paraphrase (text_trust='paraphrase',quote_safe=false) — never quote, even when paraphrasing is tight. Eachsteiner_locientry inside a summary names a verified GA locus retrievable viafetch_passage; the surrounding statement is the curator’s paraphrase, not Steiner’s words.find_source_chapters_for_ga_locusreturns paraphrase as well. search_anthroposophy.corpusenum:['ga','fmc','both']→['ga','fmc','sources','both','all']. Tool description acknowledges sources as a third corpus alongside GA and FMC.- MCP
tools/listreturns 14 tools (4 GA + 5 FMC + 5 sources). - MCP server
versionandSERVER_VERSIONbumped to1.1.2. Both were stale prior to this release (1.1.0and1.0.0respectively).
Fixed
scripts/deploy_site.shparity probe: added retry/backoff (8 attempts, 0.5s × attempt#) to tolerate uvicorn’s multi-worker spawn window.systemctl is-activereturnedactivebefore all workers had bound to port 8044, causing a false rollback on the 2026-05-22 deploy.v2/server/main.py: removed a staleimport sources_sharedthat crashed all 4 anthro-api workers withModuleNotFoundErroron startup (the module is on the MCP service’s path, not the API service’s). The /sources/ REST endpoints remain deferred per the MCP-first pattern; the import was dead code.find_fmc_pages_for_ga_locus.inputSchema: removed the top-levelanyOfthat required eitherga_locusorga_volume. Anthropic’scustomtool API rejects top-levelanyOf/oneOf/allOfin input_schema; any agent call that included this tool in its toolset was failing with400 tools.N.custom.input_schema: input_schema does not support oneOf, allOf, or anyOf at the top level. The field-presence constraint is now enforced in the dispatch handler instead (which already validated the same rule and returnederror_code: "missing_argument"). A regression test (test_no_top_level_schema_combinators) sweeps every FMC tool schema for top-level combinators.
1.1.1 - 2026-05-18
Research workflows
This release adds the quotation-discipline layer for corpus citations.
- Anything inside quotation marks must be byte-for-byte from a corpus retrieval.
fetch_passage,fetch_source_chapter, or aquoted_spanrecord withstatus=stored— minor trimming, smoothing, or dropping a single word counts as paraphrase, even when self-labelled as quoting. - 0-hit responses carry an authoritative “do not quote” signal.
search_steiner/search_anthroposophy/search_sourcesreturncorpus_verdict: "NO_MATCH — ..."in the response payload whentotal == 0. The verdict is authoritative: the queried text is not in the indexed corpus. - Bare GA-volume-and-year citations are rejected as unverified. A citation such as “GA 26, 1924” without a specific lecture-date or passage-number is not a verified citation.
- Reverse-lookup questions get the dedicated tool. “Which FMC pages cite GA 146, 1913-06-02?” routes to
find_fmc_pages_for_ga_locus, not generic FTS — exact-locus questions answered by an exact-locus tool.
Citations in agent output therefore reflect retrieval rather than training memory; a “not in corpus” answer is authoritative.
Added
corpus_verdictfield onsearch_steinerandsearch_anthroposophyresponses whentotal == 0. Carries an authoritative “do not quote” signal in the response payload, so the agent reads it directly rather than relying only on session-level instructions.
Changed
- New top-of-document Quotation discipline (read first) block in server
instructions. Requiressearch_steiner→fetch_passagebefore opening quotation marks. 0-hit corpus results are authoritative. Bare GA-number-plus-year citations (e.g. “GA 26, 1924”) rejected as unverified. Byte-for-byte means byte-for-byte: dropping a single word (‘thus’, ‘then’, ‘also’) or trimming for slide-readability breaks verbatim status; self-labeling a paraphrase doesn’t exempt it. - Additional agent-discipline blocks in server
instructions: inline citation rendering at parity with web-source linking; section references must use<page_slug>#<section_anchor>form; reverse cross-reference questions must usefind_fmc_pages_for_ga_locus; stay inside the corpus whenverify_locusreturns true; citation follow-ups must verify both page and section anchor before answering. - Tool
find_fmc_pages_for_ga_locus: description lead rewritten around the question pattern it handles (“which FMC pages cite this lecture?”); routes away fromsearch_anthroposophyfor reverse-lookup queries. - Tool
search_anthroposophy: closing “When NOT to use this tool” block redirects exact-locus reverse lookups tofind_fmc_pages_for_ga_locus. - Shared FMC source-discipline contract (in
search_anthroposophy+fetch_fmc_pagedescriptions): closing Quotation-marks discipline sentence reserves quotation marks forquoted_spanrecords withstatus='stored'or verbatim Steiner passages fromfetch_passage.
Fixed
find_fmc_pages_for_ga_locus.inputSchemanow declaresanyOfrequiringga_locusorga_volume. Was permissive on{}.- Removed dead
corpusargument fromsearch_steiner/fetch_passage/fetch_paralleldispatch. Handlers passcorpus="steiner"as a literal.fetch_parallel.inputSchemano longer advertises the single-valuecorpusenum.
1.1.0 - 2026-05-14
Research workflows
This release adds the Free Man Creator (FMC) curatorial layer (anthroposophy.eu — pages, schemas, structured quoted-span records, and GA cross-references) to the MCP surface alongside the GA.
- Reverse cross-reference (GA → FMC).
find_fmc_pages_for_ga_locus("1913-06-02-GA146")returns the FMC pages citing a GA locus, with attribution class (adjacent/section-inferred/main-body-reference). - Curatorial page retrieval.
fetch_fmc_page("Krishna_impulse")returns ordered curatorial chunks (lead, sections, subsections, discussion notes) plusquoted_spanrecords with provenance. - Schema retrieval.
fetch_fmc_schema("FMC00.389A")returns description, image URL, linked pages, and cited GA loci. - Link-graph traversal.
traverse_anthroposophy_linksruns BFS over the FMC cross-link graph (depth 1-3, configurable max-nodes).
FMC content is CC-BY-SA paraphrase; quoted_span records carry the curator’s structured provenance (status=stored for inline verbatim, status=referenced for GA pointers that resolve via fetch_passage). The unified search_anthroposophy umbrella ranks GA + FMC hits together for queries spanning both.
Added
-
FMC (anthroposophy.eu) corpus integration. The curatorial wiki at anthroposophy.eu is now retrievable through the MCP connector alongside the Gesamtausgabe. License: CC-BY-SA.
-
Tool
search_anthroposophy: unified full-text search across the GA and FMC corpora. Filters:corpus,chunk_class,target_corpus,status,page_slug. Inherits GA filters (lang,edition,ga,ga_range,from_date,to_date). Detects ranking mode from query content (primary_seeking,comparative,curatorial,default) and adjusts interleave order accordingly. -
Tool
fetch_fmc_page: retrieve an FMC page by slug. Returns ordered curatorial chunks (lead, sections, subsections, discussion notes),quoted_spanrecords with provenance, and the page’s GA cross-references. -
Tool
fetch_fmc_schema: retrieve a schema byFMC00.NNNid. Returns description, image URL, linked pages, and cited GA loci. -
Tool
traverse_anthroposophy_links: BFS over the FMC link graph from a root page slug. Depth clamped to [1, 3]; configurablemax_nodes. -
Tool
find_fmc_pages_for_ga_locus: reverse cross-reference. Given a GA locus (1913-06-02-GA146) or volume (146), return all FMC pages that cite it with attribution class (adjacent,section-inferred,main-body-reference). -
Source-discipline contract enforced in tool response structure.
quoted_spanrecords withstatus=referencedcarry no verbatim text; agents followtarget_locusto the primary corpus. Records withstatus=storedcarry the fullembedded_attributionchain. All FMC retrieval results carryprimary_anchor(corpus, page_url, curator, license) andcontent_hashfor citation stability.
Changed
- MCP
tools/listreturns 9 tools (4 GA + 5 FMC).
1.0.0 - 2026-05-07
Research workflows
Initial release. The complete Gesamtausgabe (GA 1 through GA 354, public domain) behind a single MCP surface.
- Search the full corpus by keyword.
search_steinerruns FTS5 with Porter stemmer + diacritic normalization. Filters:lang,edition,ga,ga_range,from_date,to_date. - Verify a GA reference exists before citing.
verify_locusconfirms(ga, lecture_date)is in the corpus — useful as a citation gate before publishing or quoting. - Retrieve any passage verbatim.
fetch_passage(ga, lecture, passage_number, lang, edition)returns text + stable citation URL in either German original or available English translation. - View parallel translations side-by-side.
fetch_parallelreturns multiple editions of the same locus; per-edition translator + year + basis are surfaced, and analignment_confidenceflag warns when paragraph counts diverge between source and translation.
German originals and English translations are cross-retrievable per locus. Browseable HTML at /v1/steiner/<lang>/ga/<vol>/<date>/p<NNN>, with content-negotiated JSON via the .json suffix. The MCP surface is anonymous and per-IP rate-limited at the edge; no account required.
Added
-
Initial public release.
-
Gesamtausgabe corpus (GA 1 through GA 354). Rudolf Steiner’s books, lectures, and lecture cycles. Public domain.
-
Multilingual retrieval. English translations alongside German originals. Per-edition tracking (translator, year, basis).
alignment_confidenceflag marks paragraph-count divergence between source and translation. -
MCP server at https://anthroposophy.ai/mcp. Streamable HTTP transport per MCP spec 2025-03-26. Anonymous access; per-IP rate limiting at the edge.
-
Tool
search_steiner: FTS5 search over the Gesamtausgabe. Porter stemmer with diacritic normalization. Filters:lang,edition,ga,ga_range,from_date,to_date,corpus. -
Tool
verify_locus: confirm a GA reference exists in the indexed corpus before citing. -
Tool
fetch_passage: retrieve a verbatim Steiner passage by(ga, lecture, passage_number, lang, edition). Returns text and a stable citation URL. -
Tool
fetch_parallel: retrieve the same passage across multiple translation editions side-by-side. -
REST API at https://anthroposophy.ai/v1/.
-
Browseable passages at
/v1/steiner/<lang>/ga/<ga_volume>/<lecture_date>/p<NNN>. Content negotiation returns HTML to browsers, JSON to agents via the.jsonsuffix.