io.github.ehsanghaffar/ganjoor-mcp-server
NPM · GANJOOR-MCP-SERVER
MCP server for the Ganjoor (گنجور) Persian classical poetry API at https://ganjoor.net
Available components
Last scanned (5 hours ago)
Scores higher than 45% of npm servers
Category Education and Research
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security81
- No malware found by supply-chain analysis.Pass
- CVE check failed: a known high-severity CVE affects zod 3.25.76, a direct dependency. A fixed version is available. View diagnostics → Fail
- No install/post-install scripts declared.Pass
- 30 of 93 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency48
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 12 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability62
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 14015 tokens (~318/item across 44 items; 44 tools + 0 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 Management70
- Stability observed for 21 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 44 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 45 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
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.
- 5 Nov 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 67 to 70. That category is still filling its 30-day observation window: 20 days of observed history at the previous scan, 21 at this one. The score rises as the window fills, whether or not the server changes.
- 3 Nov 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 60 to 63. That category is still filling its 30-day observation window: 18 days of observed history at the previous scan, 19 at this one. The score rises as the window fills, whether or not the server changes.
- 1 Nov 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 53 to 57. That category is still filling its 30-day observation window: 16 days of observed history at the previous scan, 17 at this one. The score rises as the window fills, whether or not the server changes.
- 29 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 43 to 47. That category is still filling its 30-day observation window: 13 days of observed history at the previous scan, 14 at this one. The score rises as the window fills, whether or not the server changes.
- 27 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 37 to 40. That category is still filling its 30-day observation window: 11 days of observed history at the previous scan, 12 at this one. The score rises as the window fills, whether or not the server changes.
- 25 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 30 to 33. That category is still filling its 30-day observation window: 9 days of observed history at the previous scan, 10 at this one. The score rises as the window fills, whether or not the server changes.
- 24 Oct 26 −5
- CVE-2023-54404 affects this package: high ▼ security
- Known CVEs: pass → fail ▼ security
- 23 Oct 26 +4
- Stability: unverified → 0.27 ▲ functional
- Package version: 0.1.0 → 0.1.1 functional
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 5 Nov 2026 · Analysed npm/ganjoor-mcp-server@0.1.1
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | npm |
Background: How many MCP packages publish verified provenance →
Vulnerabilities 1 finding
| ID | CVE | Severity | Vector | Fix available |
|---|---|---|---|---|
| GHSA-mrhx-c7xc-m3w5 | CVE-2023-54404 | high | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | yes |
Background: What a vulnerability scan can and cannot prove →
Dependencies 93 packages
| Packages resolved | 93 |
|---|---|
| Stale | 30 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
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 →
ganjoor_analyze_poem_rhyme Analyze Poem Rhyme ~223
Detect the rhyme letter (قافیه) and rhyme pattern of a poem by its numeric id. Args: - poem_id (number): Numeric poem id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, rhyme, rhyme_letter, fail_verse } — `rhyme` is the full rhyming ending as the prosody engine sees it, and `rhyme_letter` is its last character. Examples: - "What is the rhyme of poem 2623?" -> poem_id=2623 Notes: - Some poems (short texts, composite editions) have no determinable rhyme; those return rhyme=null plus a fail_verse note explaining where analysis stopped.
| Name | Type | Req | Description |
|---|---|---|---|
| poem_id | integer | yes | Numeric poem id to analyze. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_analyze_poem_rhythm Analyze Poem Rhythm (Metre) ~208
Detect the prosodic metre (وزن) of a poem by its numeric id. Runs Ganjoor's prosody engine over the poem's verses and returns the matched metre together with its confidence and the competing alternatives considered. Args: - poem_id (number): Numeric poem id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, metre: { id, rhythm }, confidence, alternatives: [{ id, rhythm, score }] } Examples: - "What metre is poem 2623 in?" -> poem_id=2623 Notes: - The detected metre may differ from the poem's stored metre for edited or composite texts.
| Name | Type | Req | Description |
|---|---|---|---|
| poem_id | integer | yes | Numeric poem id to analyze. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_find_similar_poems Find Similar Poems By Metre And Rhyme ~658
Find poems that share a poem's prosodic metre and rhyme letter — the basis of Ganjoor's "related poems" (شعرهای مرتبط) pages. Two Persian poems matching in metre and rhyme can be read as answers to each other (reply-poetry), so this is also how you trace how one poet answered another. Args: - metre (string): The prosodic metre pattern, exactly as listed by ganjoor_list_rhythms - rhyme (string): Optional rhyme letter filter (e.g. 'ا', 'ب'). Empty means any. - poet_id (number): Restrict to a poet id. 0 = all poets (default: 0) - cat_id (number): Restrict to a category id. 0 = all categories (default: 0) - couplet_count_min (number): Only poems with at least this many couplets (default: 0) - couplet_count_max (number): Only poems with at most this many couplets (default: 0, meaning no cap) - page (number): Page number, starting from 1 (default: 1) - page_size (number): Results per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { count, page, page_size, has_more, next_page, poems: [{ id, title, full_title, full_url, plain_text }] } Examples: - "Which Hafez poems share metre 'فاعلاتن مفاعلن فعلن'?" -> metre='فاعلاتن مفاعلن فعلن', poet_id=2 - "Poems in metre X rhyming on ب" -> metre='...', rhyme='ب' Notes: - `metre` must match the metre notation exactly; call ganjoor_list_rhythms to get valid values. - A metre with no rhyme filter returns a very large set — always page.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | – | Restrict to a category id. 0 = all categories. |
| couplet_count_max | integer | – | Only poems with at most this many couplets. 0 disables the filter. |
| couplet_count_min | integer | – | Only poems with at least this many couplets. 0 disables the filter. |
| metre | string | yes | Prosodic metre pattern exactly as returned by ganjoor_list_rhythms, e.g. 'فاعلاتن مفاعلن فعلن'. |
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| poet_id | integer | – | Restrict to a poet id. 0 = all poets. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| rhyme | string | – | Optional rhyme letter, e.g. 'ا' or 'ب'. Empty matches any rhyme. |
No output schema declared.
No examples provided.
ganjoor_get_category Get Ganjoor Category ~461
Get a Ganjoor category (a book, section, or sub-collection) by numeric id. A category is the container for poems inside a poet's work — for example Hafez's ghazals (category id 10) or Rumi's Masnavi. The response includes the breadcrumb path, the direct children (sub-sections), and optionally the poems it contains. Args: - cat_id (number): Category id. Hafez's root category is 9. - include_poems (boolean): Include the poems inside this category (default: true) - include_children (boolean): Include the direct child categories/sections (default: true) - poem_limit (number): Maximum poems to return when include_poems is true, 1-200 (default: 50) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: Category metadata: id, title, breadcrumb, description, table-of-contents style, child categories, and (optionally) contained poems with their ids, titles and URLs. Set include_poems=false to skip the poem list; use ganjoor_list_category_poems when you only want the poems and their total count. Examples: - "What is inside Hafez's ghazals?" -> cat_id=10, include_children=false - "List Hafez's sections" -> cat_id=9, include_poems=false Notes: - A category that directly contains poems returns those poems; a pure section returns children instead. Follow `children` to descend.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | yes | Category id. Hafez's root category is 9; use ganjoor_list_books or ganjoor_get_poet to discover others. |
| include_children | boolean | – | Include the direct child categories. |
| include_poems | boolean | – | Include the poems contained directly in this category. |
| poem_limit | integer | – | Maximum poems to include when include_poems is true. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_category_geotags Get Category Geo Tags ~233
Get the geographic and historical locations tagged to poems within a Ganjoor category and its descendants. Each tag pairs a place with the Hijri/Gregorian date a poem commemorates, which is how Ganjoor records historical events (a battle, a siege) in poetry. Args: - cat_id (number): Category id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { total, tags: [{ id, latitude, longitude, lunar_date, gregorian_date, child_cat }] } Examples: - "Where are the events in Hafez's poetry set?" -> cat_id=9 Notes: - Tag lists can be large (tens of entries for a whole diwan). - Coordinates are decimal degrees, WGS84.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | yes | Category id whose subtree should be scanned for geo tags. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_category_people_graph Get Category People Graph ~234
Get the network of historical people relevant to a Ganjoor category or work. Returns every person tagged in a poem under this category's subtree, plus their kinship and affiliation ties one hop out — the data behind Ganjoor's "characters" (شخصیتها) tab. Args: - cat_id (number): Category id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { node_count, edge_count, nodes: [{ id, name, importance }], edges: [{ from_person_id, to_person_id, relation }] } Examples: - "Which historical figures appear in the Shahnameh?" -> cat_id=<Shahnameh category id> Notes: - Empty graphs are normal for categories with no person tagging — that is not an error.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | yes | Category id to build the people graph for. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_category_top_recitations Get Top Recitations For A Category ~251
Get the most-liked recitations within a category — Ganjoor's "top 1" (بهترین) listings for a book. Args: - cat_id (number): Category id - include_poem_text (boolean): Include each poem's text (default: false) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { cat_id, count, recitations: [{ recitation_id, poem_id, poem_title, artist, score, plain_text? }] } Examples: - "The best-known recitations of Hafez's ghazals" -> find the ghazals category id, then call this Notes: - Ordering is by community upvote score, which changes over time. - The ghazals category for Hafez is id 10.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | yes | Category id. |
| include_poem_text | boolean | – | Include the full poem text alongside each recitation. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_couplet_sections Get Sections For A Couplet ~254
Find which structural sections a specific couplet of a poem belongs to. A verse carries up to four nested section indices; this endpoint resolves one couplet to the stanzas that contain it, which you need when analysing a ghazal's opening or closing section. Args: - poem_id (number): Numeric poem id - couplet_index (number): 0-based couplet number - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, couplet_index, sections: [{ id, index, number, section_type, metre, rhyme }] } Examples: - "Which section is couplet 5 of poem 2623 in?" -> poem_id=2623, couplet_index=5 Notes: - An empty list means the couplet index is out of range for that poem.
| Name | Type | Req | Description |
|---|---|---|---|
| couplet_index | integer | yes | 0-based couplet number. |
| poem_id | integer | yes | Numeric poem id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_faq_item Get Ganjoor FAQ Item ~203
Get one Ganjoor FAQ entry by its numeric id. Args: - faq_id (number): FAQ item id (from ganjoor_get_faq_items) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { id, category_id, question, answer, answer_excerpt, pinned } Examples: - "Show FAQ item 7" -> faq_id=7 Notes: - Despite its name, answerExcerpt carries the complete body; fullAnswer is always empty upstream. - Only published items are served. An upstream 500 usually means the id does not exist — re-check the id from ganjoor_get_faq_items.
| Name | Type | Req | Description |
|---|---|---|---|
| faq_id | integer | yes | Numeric FAQ item id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_faq_items Get Ganjoor FAQ Items ~292
Get every published question-and-answer in a Ganjoor FAQ category. Args: - cat_id (number): FAQ category id (from ganjoor_list_faq_categories) - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { cat_id, total, count, page, page_size, has_more, next_page, items: [{ id, question, answer, answer_excerpt }] } Examples: - "How does Ganjoor decide which text to use?" -> cat_id=<id>, then read the answers Notes: - Answers are Persian prose and may contain HTML markup from the source; return them verbatim. - Despite its name, answerExcerpt carries the complete body — fullAnswer is always empty upstream.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | yes | FAQ category id. |
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_hafez_faal Get Hafez Faal (Divination) ~201
Draw a random Hafez ghazal as a Persian divination (فال حافظ). This is the traditional "ask Hafez" reading: one ghazal selected at random, to be interpreted in the context of the question asked. Each call draws a different ghazal. Args: - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: A complete Hafez ghazal in the same shape as ganjoor_get_poem_by_id. Examples: - "Draw a faal for me" -> no arguments - "What does Hafez say about my question?" -> no arguments Notes: - Non-deterministic. The interpretation is traditionally left to the reader.
| Name | Type | Req | Description |
|---|---|---|---|
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_language_tagged_sections Get Language-Tagged Poem Sections ~409
List poem sections Ganjoor has tagged with a specific language, newest-scoped by poet. Ganjoor tags translated or bilingual stanzas with a language code (for example `ar` for Arabic quoted lines, or `en` for English ones). This finds those passages across the corpus. Args: - language (string): Language code, e.g. 'ar' for Arabic, 'en' for English, 'fa-IR' for Persian - poet_id (number): Restrict to a poet id. 0 = all poets (default: 0) - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { language, count, page, page_size, has_more, next_page, sections: [{ id, poem_id, poem_title, poet_name }] } Examples: - "Which passages quote Arabic?" -> language='ar' - "Arabic stanzas in Hafez" -> language='ar', poet_id=2 Notes: - Coverage is patchy: most Persian stanzas are untagged, so an empty result does not mean no such passage exists.
| Name | Type | Req | Description |
|---|---|---|---|
| language | string | yes | Language code to filter by, e.g. 'ar', 'en', 'fa-IR'. |
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| poet_id | integer | – | Restrict to a poet id. 0 = all poets. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_page_url Resolve Ganjoor Page Id To URL ~203
Resolve any Ganjoor page id (poem, category, or poet) to its public web URL path. Useful when you have a bare numeric id from an index or a citation and need to cite or link it. Args: - id (number): Any Ganjoor page id — poem, category, or poet - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { id, url, full_url } Examples: - "What is the link for id 13836?" -> id=13836 Notes: - Ids are globally unique across poems, categories and poets on Ganjoor.
| Name | Type | Req | Description |
|---|---|---|---|
| id | integer | yes | Page id to resolve. Works for poems, categories, and poets. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_person Get Ganjoor Person ~210
Get one person's full record — biography, dates, places, and external references. Args: - person_id (number): Numeric person id (from ganjoor_list_people) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { id, name, description, wiki_url, birth_year_hijri, death_year_hijri, birth_location, death_location, family_tree_caption, machine_generated, importance, gender } Examples: - "Who is person 22?" -> person_id=22 Notes: - `machine_generated` marks entries created automatically; their biographies may be sparse. - Follow with ganjoor_get_person_poems or ganjoor_get_person_relations for context.
| Name | Type | Req | Description |
|---|---|---|---|
| person_id | integer | yes | Numeric person id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_person_family_tree Get Person Family Tree ~276
Get the full connected kinship component reachable from a person — ancestors, descendants, spouses, and siblings. This returns the whole clan cluster, not just one hop, which makes it the right tool for tracing a figure's lineage across generations. Args: - person_id (number): Numeric person id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { person_id, root_id, person_count, people: [{ id, name, birth_year_hijri, death_year_hijri, family_tree_caption }], relation_count, relations: [{ person1_id, person1_name, person2_id, person2_name, relation_label }] } Examples: - "Show me this figure's lineage" -> person_id=<id> Notes: - Components can be large for well-documented dynasties (the Kayumars tree has ~56 people). - Data quality varies: some edges are machine-generated and may be speculative — check the machine_generated flag per person.
| Name | Type | Req | Description |
|---|---|---|---|
| person_id | integer | yes | Numeric person id to start the traversal from. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_person_poems Get Poems Tagged With A Person ~257
Get every poem Ganjoor has tagged with a given person. This is the strongest link between a historical figure and the poetry about them. Args: - person_id (number): Numeric person id - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { person_id, total, count, page, page_size, has_more, next_page, poems: [{ id, title, full_url }] } Examples: - "Which poems mention this figure?" -> person_id=<id> Notes: - Tagging is curated and incomplete for older figures.
| Name | Type | Req | Description |
|---|---|---|---|
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| person_id | integer | yes | Numeric person id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_person_relations Get Person Relations ~268
Get a person's kinship and affiliation edges — parents, siblings, spouses, teachers, and contemporaries. Args: - person_id (number): Numeric person id - relation_type (string): Optional filter — only relations of this kind, e.g. 'father', 'son', 'spouse', 'student', 'teacher' - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { person_id, relation_count, relations: [{ id, from_person_id, from_person_name, to_person_id, to_person_name, relation_kind, relation_name }] } Examples: - "Who was this person's teacher?" -> person_id=<id>, relation_type='teacher' Notes: - Edges are stored undirected with a kind; the same edge appears once. - Use ganjoor_get_person_family_tree for the whole connected component.
| Name | Type | Req | Description |
|---|---|---|---|
| person_id | integer | yes | Numeric person id. |
| relation_type | string | – | Optional filter on the relation kind, e.g. 'father', 'spouse', 'teacher'. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_poem Get Ganjoor Poem By URL ~627
Fetch a complete poem by its Ganjoor URL, including verses, metre, rhyme, and recitations. This is the main way to read a poem. The URL is the same as the browser address on ganjoor.net, e.g. "hafez/ghazal/sh494". Use ganjoor_search_poems or ganjoor_list_category_poems to discover URLs, and ganjoor_get_poem_by_id when you only have a numeric id. Args: - url (string): Poem URL slug, with or without leading slash, e.g. 'hafez/ghazal/sh494' - include_category (boolean): Include the book/category metadata (default: true) - include_siblings (boolean): Include the list of other poems in the same book (default: false) - include_recitations (boolean): Include audio recitations (default: true) - include_images (boolean): Include manuscript images (default: false) - include_comments (boolean): Include published reader comments (default: false) - include_verse_details (boolean): Include per-verse ids, positions, and couplet summaries (default: true) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: Poem id, title, full title, poet, book/category path, plain text, and the ordered verse list grouped into couplets. For JSON: { id, title, full_title, full_url, poet, category, couplets_count, verses: [{ couplet_index, position, text }], recitations: [...], next_poem, previous_poem } Examples: - "Show me Hafez's ghazal 494" -> url='hafez/ghazal/sh494' - "Read this poem with its commentary" -> include_comments=true Notes: - Persian text is returned verbatim; it is right-to-left, so present it as-is. - Keep include_siblings and include_comments false unless needed — both can be very large.
| Name | Type | Req | Description |
|---|---|---|---|
| include_category | boolean | – | Include the poem's category/book metadata. |
| include_comments | boolean | – | Include published reader comments. |
| include_images | boolean | – | Include manuscript image links. |
| include_recitations | boolean | – | Include audio recitations of the poem. |
| include_siblings | boolean | – | Include all other poems in the same book. Can be very large. |
| include_verse_details | boolean | – | Include per-verse ids, positions, and AI summaries. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| url | string | yes | Ganjoor URL slug. Examples: 'hafez/ghazal/sh494', '/hafez/ghazal/sh494', 'mowhaddam/ghazal/ha1'. The leading slash is optional. |
No output schema declared.
No examples provided.
ganjoor_get_poem_by_id Get Ganjoor Poem By Id ~381
Fetch a complete poem by its numeric Ganjoor id. Same content as ganjoor_get_poem, but keyed on the numeric poem id instead of the URL. Use it when you have an id from search results or another tool and do not want to build a URL. Args: - poem_id (number): Numeric poem id - include_category (boolean): Include the book/category metadata (default: true) - include_recitations (boolean): Include audio recitations (default: false) - include_comments (boolean): Include published reader comments (default: false) - include_verse_details (boolean): Include per-verse ids and positions plus the prose summary for each couplet (default: true). Set false for a leaner payload; the verse text itself is always returned. - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: Identical shape to ganjoor_get_poem. Examples: - "Show poem 2623" -> poem_id=2623 - "What is poem 13836?" -> poem_id=13836 Notes: - Combined with ganjoor_get_page_url you can also resolve an id to its web address.
| Name | Type | Req | Description |
|---|---|---|---|
| include_category | boolean | – | Include category metadata. |
| include_comments | boolean | – | Include reader comments. |
| include_recitations | boolean | – | Include audio recitations. |
| include_verse_details | boolean | – | Include per-verse ids, positions, and summaries. |
| poem_id | integer | yes | Numeric poem id, e.g. 2623 for a Hafez ghazal. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_poem_effective_corrections Get Poem Text Corrections ~194
Get the editorial corrections applied to a poem's text — the before/after record of every fix. Useful for understanding why the text on Ganjoor differs from an older printed edition. Args: - poem_id (number): Numeric poem id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, correction_count, corrections: [{ id, verse_order, text, original_text }] } Examples: - "What corrections were made to poem 2623?" -> poem_id=2623 Notes: - Each entry pairs the corrected text with the original, per verse order.
| Name | Type | Req | Description |
|---|---|---|---|
| poem_id | integer | yes | Numeric poem id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_poem_geotags Get Poem Geo Tags ~210
Get the geographic and historical locations tagged to a single poem. A geo tag pins a poem to a place and to the Hijri/Gregorian date it commemorates — for instance a poem about a battle fought at a named site. Args: - poem_id (number): Numeric poem id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, tag_count, tags: [{ id, latitude, longitude, lunar_date, gregorian_date }] } Examples: - "Where is the event in poem 2623?" -> poem_id=2623 Notes: - For a whole diwan, use ganjoor_get_category_geotags instead.
| Name | Type | Req | Description |
|---|---|---|---|
| poem_id | integer | yes | Numeric poem id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_poem_images Get Poem Manuscript Images ~199
Get the manuscript and facsimile images Ganjoor holds for a poem. These are photographs of the physical manuscripts, with a thumbnail and a full-resolution link per image — useful for checking a textual variant against its source. Args: - poem_id (number): Numeric poem id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, image_count, images: [{ id, url, thumbnail_url, alt, description }] } Examples: - "Show the manuscript for poem 2623" -> poem_id=2623 Notes: - Most poems have no images; an empty list is the normal case.
| Name | Type | Req | Description |
|---|---|---|---|
| poem_id | integer | yes | Numeric poem id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_poem_quoted_poems Get Poems Quoted By A Poem ~470
Get the poems that a given poem quotes or alludes to, and the poems that quote it. Matching in metre and rhyme is common in Persian poetry — poets answer each other by reusing the other's metre and rhyme. This endpoint maps those links in both directions. Args: - poem_id (number): Numeric poem id - only_both_poems (boolean): Only keep pairs where both poems claim the quotation (default: false) - published_only (boolean): Only keep published records (default: true) - main_list_only (boolean): Only keep records curated onto the main "related poems" list (default: false) - skip (number): Results to skip (default: 0) - items_count (number): How many to return. 0 or negative returns all (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, total, returned, quotes: [{ id, related_poem_id, related_poet_name, related_poem_title, related_poem_url, is_prior, quoted_couplet, quoting_couplet, claimed_by_both, note }] } Examples: - "Which poems does this one answer?" -> poem_id=<id> Notes: - Each record pairs the quoted couplet with the couplet in the other poem that quotes it, so the actual verbal borrowing is visible. - `is_prior: true` means this poem came first chronologically. - `items_count=0` returns everything, which can be large.
| Name | Type | Req | Description |
|---|---|---|---|
| items_count | integer | – | How many results to return. 0 or less returns all. |
| main_list_only | boolean | – | Only include records curated onto the main related-poems list. |
| only_both_poems | boolean | – | Only include quotations both poems acknowledge. |
| poem_id | integer | yes | Numeric poem id. |
| published_only | boolean | – | Only include published records. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| skip | integer | – | Results to skip. |
No output schema declared.
No examples provided.
ganjoor_get_poem_recitations Get Poem Recitations ~254
List every audio recitation published for one poem. Args: - poem_id (number): Numeric poem id - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, count, page, page_size, has_more, next_page, recitations: [{ id, artist, title, publish_date, duration_seconds }] } Examples: - "How has poem 2623 been recited?" -> poem_id=2623 Notes: - Text fields are intentionally blank upstream; fetch the poem itself for its text.
| Name | Type | Req | Description |
|---|---|---|---|
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| poem_id | integer | yes | Numeric poem id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_poem_sections Get Poem Sections ~236
Get the structural sections of a poem — the stanzas (بند), couplets (مثنوی), and tercets (رباعی) it is built from. Ganjoor models a poem as nested sections so that poetry written in distinct forms within one poem (e.g. a ghazal that closes with a qet'e) can be analysed per-section. Args: - poem_id (number): Numeric poem id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, section_count, sections: [{ id, index, number, section_type, verse_type, metre, rhyme }] } Examples: - "What is the structure of poem 2623?" -> poem_id=2623 Notes: - Section `index` values feed directly into ganjoor_get_related_sections.
| Name | Type | Req | Description |
|---|---|---|---|
| poem_id | integer | yes | Numeric poem id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_poem_verses Get Ganjoor Poem Verses ~369
Get just the verses of a poem by id — a lightweight alternative to fetching the whole poem. Each verse comes back in order with its couplet index and whether it is the first or second hemi- stich. Optionally restrict to a single couplet. Args: - poem_id (number): Numeric poem id - couplet_index (number): Return only this couplet (0-based). Omit for the whole poem. - include_summary (boolean): Include the per-couplet prose summary (default: false) - include_original_text (boolean): Include the uncorrected original text where available (default: false) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, verse_count, verses: [{ id, order, couplet_index, position, text }] } Examples: - "Quote the verses of poem 2623" -> poem_id=2623 - "Show only couplet 3" -> poem_id=2623, couplet_index=3 Notes: - Position 0 is the first hemistich, position 1 the second; couplet_index groups them.
| Name | Type | Req | Description |
|---|---|---|---|
| couplet_index | integer | – | Return only this 0-based couplet. Omit to get the whole poem. |
| include_original_text | boolean | – | Include the pre-correction original text where the API has it. |
| include_summary | boolean | – | Include the modern Persian summary attached to each couplet. |
| poem_id | integer | yes | Numeric poem id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_poet Get Ganjoor Poet ~439
Get a single poet's full profile (including biography) by numeric id or URL slug. Use this to turn a slug like "/hafez" into the numeric poet id, or to read a poet's biography and catalogue of works. Args: - id (number): Numeric poet id (optional if `url` is given). Hafez = 2, Saadi = 7, Rumi = 5. - url (string): Poet URL slug such as 'hafez' or '/hafez' (optional if `id` is given) - include_cats (boolean): Include the poet's top-level book/section list (default: true) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: Poet profile with id, name, nickname, biography, birth/death (Hijri + places), plus for JSON: { id, name, nickname, biography, birth_year_hijri, death_year_hijri, birth_place, death_place, full_url, cats: [{ id, title, full_url, cat_type }] } Examples: - "Tell me about Hafez" -> url='hafez' - "What are Saadi's works?" -> id=7, include_cats=true Notes: - Supply exactly one of `id` or `url`. If both are given, `id` wins.
| Name | Type | Req | Description |
|---|---|---|---|
| id | integer | – | Numeric Ganjoor record id (poet, category, poem, person, ...). |
| include_cats | boolean | – | Include the poet's top-level list of books/sections. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| url | string | – | Ganjoor URL slug. Examples: 'hafez/ghazal/sh494', '/hafez/ghazal/sh494', 'mowhaddam/ghazal/ha1'. The leading slash is optional. |
No output schema declared.
No examples provided.
ganjoor_get_poets_by_century Get Ganjoor Poets By Century ~220
Get every Ganjoor poet grouped into historical half-centuries. The first group (id 0) holds the "pinned"/featured poets shown on the Ganjoor home page. Each later group carries a name, an approximate Gregorian year range, and the poets active in that period. Args: - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { centuries: [{ id, name, start_year, end_year, poet_count, poets: [{ id, name, full_url }] }] } Examples: - "Which poets are from the 14th century?" -> inspect the century entries and their poets Notes: - The whole payload is returned at once; it is a few hundred KB at most. - Grouping is editorial, so a poet appears exactly once.
| Name | Type | Req | Description |
|---|---|---|---|
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_random_poem Get Random Ganjoor Poem ~245
Get a random poem from Ganjoor, optionally from a specific poet. Args: - poet_id (number): Poet to draw from. 0 = a random poet (default: 0). Hafez = 2. - include_recitations (boolean): Include audio recitations (default: false) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: A single complete poem in the same shape as ganjoor_get_poem_by_id. Examples: - "Surprise me with a poem" -> no arguments - "A random Saadi poem" -> poet_id=7 Notes: - Non-deterministic: repeated calls return different poems.
| Name | Type | Req | Description |
|---|---|---|---|
| include_recitations | boolean | – | Include audio recitations. |
| poet_id | integer | – | Poet id to draw from. 0 = any poet. Hafez = 2, Saadi = 7, Rumi = 5. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_recent_comments Get Recent Ganjoor Comments ~345
Get the most recent published reader comments across Ganjoor, optionally filtered. Comments are scholarly notes attached to a specific couplet of a poem. Args: - term (string): Optional text filter applied to comment bodies - filter_user_id (string): Optional UUID — only comments by this user - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { count, page, page_size, has_more, next_page, comments: [{ id, poem_id, poem_title, couplet_index, user, text, date, has_owner_response }] } Examples: - "What are people discussing?" -> no arguments - "Comments about 'انتظار'" -> term='انتظار' Notes: - Ordering is by recency, so results change over time — not suitable for questions whose answer must stay stable. - Replies are not included, only top-level comments.
| Name | Type | Req | Description |
|---|---|---|---|
| filter_user_id | string | – | Optional user UUID — only that user's comments. |
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| term | string | – | Optional substring filter applied to comment text. |
No output schema declared.
No examples provided.
ganjoor_get_recitation Get Ganjoor Recitation ~199
Get one published recitation by its numeric id, including its audio file location and poem reference. Args: - recitation_id (number): Recitation id (from ganjoor_search_recitations or a poem's recitation list) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { id, poem_id, poem_title, poem_url, title, artist, artist_url, audio_url, publish_date, duration_seconds, review_status } Examples: - "Details for recitation 37535" -> recitation_id=37535 Notes: - Audio URLs point at Ganjoor's CDN and are stable once published.
| Name | Type | Req | Description |
|---|---|---|---|
| recitation_id | integer | yes | Numeric recitation id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_recitation_sync_info Get Recitation Verse Sync Timing ~205
Get the per-verse timing map for a recitation, showing when each couplet begins in the audio. Useful for following along with the text while a recitation plays. Args: - recitation_id (number): Recitation id - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { recitation_id, sync_point_count, total_duration_ms, sync_points: [{ verse_order, text, start_time_ms, start_time_seconds }] } Examples: - "Sync data for recitation 37535" -> recitation_id=37535 Notes: - Not every recitation has timing data; an empty list is normal for older uploads.
| Name | Type | Req | Description |
|---|---|---|---|
| recitation_id | integer | yes | Numeric recitation id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_get_redirect_url Resolve Ganjoor Redirect ~254
Resolve a legacy or short Ganjoor URL to its current canonical address. Ganjoor has renamed many sections over the years; this endpoint maps an old path to today's one. Args: - url (string): The URL path to resolve, with or without a leading slash - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { requested_url, redirect_url, full_url, has_redirect } — redirect_url is null and has_redirect is false when Ganjoor has no redirect for that URL (which includes URLs that are already canonical). Examples: - "Where does an old Hafez section URL go now?" -> url='hafez/divan/ghazal/sh1' Notes: - Ganjoor only keeps explicit redirects for paths it actually renamed; most valid URLs return has_redirect=false rather than a target.
| Name | Type | Req | Description |
|---|---|---|---|
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| url | string | yes | URL path to resolve, e.g. 'hafez/divan'. |
No output schema declared.
No examples provided.
ganjoor_get_related_sections Get Related Poem Sections ~337
Find sections from other poems that match a given poem section in metre and rhyme. This is the section-level counterpart of ganjoor_find_similar_poems and is how Ganjoor links reply-poems and cross-poet allusions at stanza granularity. Args: - poem_id (number): Numeric poem id - section_index (number): 0-based section index within the poem (from ganjoor_get_poem_sections) - skip (number): Results to skip (default: 0) - items_count (number): How many to return. 0 or negative returns all (default: 10) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { poem_id, section_index, total, related_sections: [{ id, poem_id, section_index, poet_name, full_url }] } Examples: - "What matches the first section of poem 2623?" -> poem_id=2623, section_index=0 Notes: - `items_count=0` returns every match, which can be thousands — prefer a bounded count.
| Name | Type | Req | Description |
|---|---|---|---|
| items_count | integer | – | How many related sections to return. 0 or less returns all. |
| poem_id | integer | yes | Numeric poem id. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| section_index | integer | yes | 0-based section index within the poem. |
| skip | integer | – | Results to skip for pagination. |
No output schema declared.
No examples provided.
ganjoor_get_section Get Poem Section ~256
Get one section of a poem by its section id, including its verses and its own related sections. Args: - section_id (number): Section id — get these from ganjoor_get_poem_sections - include_verses (boolean): Include the section's verses (default: true) - include_related (boolean): Include related sections from other poems (default: false) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: Section metadata, its metre/rhyme, optionally its verses and its related sections. Examples: - "Show me section 38101" -> section_id=38101 Notes: - A section id differs from a poem id; use ganjoor_get_poem_sections first to map between them.
| Name | Type | Req | Description |
|---|---|---|---|
| include_related | boolean | – | Include sections from other poems related to this one. |
| include_verses | boolean | – | Include the section's verses. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| section_id | integer | yes | Section id from ganjoor_get_poem_sections. |
No output schema declared.
No examples provided.
ganjoor_list_books List Ganjoor Books ~454
List Ganjoor books (named collections such as دیوان حافظ or غزلیات سعدی), alphabetically. Every returned entry is a category of type "Book". Use the resulting category id with ganjoor_get_category to browse the poems inside, or with ganjoor_get_category_poems to list them. Args: - name (string): Optional filter — only books whose name contains this substring (case-insensitive) - poet_id (number): Optional filter — only books belonging to this poet id - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { count, page, page_size, has_more, next_page, books: [{ id, name, poet_id, poet_name, full_url }] } Examples: - "What books does Hafez have?" -> poet_id=2 - "Find books matching 'ghazal'" -> name='ghazal' - "Show me Molavi's collections" -> poet_id=5 Notes: - Filtering happens server-side, so it is much cheaper than fetching everything and filtering locally. - Ganjoor's book catalog is a curated subset: some major poets (including Hafez) have no entries. For them use ganjoor_get_poet with include_cats=true, which lists a poet's sections directly.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | – | Case-insensitive substring filter on the book name, e.g. 'ghazal' or 'divan'. |
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| poet_id | integer | – | Only books belonging to this poet id. 0 disables the filter. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_list_category_poems List Poems In A Ganjoor Category ~353
List the poems contained in a Ganjoor category, optionally filtered by the author's name. Args: - cat_id (number): Category id to list poems from - title_contains (string): Optional filter — only poems whose title contains this text - page (number): Page number, starting from 1 (default: 1) - page_size (number): Poems per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { total, count, page, page_size, has_more, next_page, category: { id, title, full_url }, poems: [{ id, title, url_slug, full_url, excerpt }] } Examples: - "Which poems are in category 10?" -> cat_id=10 - "Find the 'شمارهٔ ۱' poems in a category" -> title_contains='شمارهٔ ۱' Notes: - Title filtering is done client-side because the upstream category endpoint is unpaged. - For large collections, combine this with page_size to walk the whole diwan.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | yes | Category id to list poems from. |
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| title_contains | string | – | Optional case-insensitive substring filter applied to poem titles. |
No output schema declared.
No examples provided.
ganjoor_list_faq_categories List Ganjoor FAQ Categories ~163
List the Ganjoor site's published FAQ (پرسشهای متداول) categories. These are editorial explanations of how Ganjoor works — text sourcing, version differences, contribution rules. Args: - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { count, categories: [{ id, title, description, item_count }] } Examples: - "What topics does Ganjoor's FAQ cover?" -> no arguments Notes: - Follow up with ganjoor_get_faq_items using a category id.
| Name | Type | Req | Description |
|---|---|---|---|
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_list_people List Ganjoor People ~345
List the historical and literary figures Ganjoor has catalogued as related persons (شخصیتها). These are people who appear in a poem's commentary or annotations — rulers, prophets, companions, poets' contemporaries — as distinct from poets themselves. Args: - search (string): Optional filter — only people whose name contains this text - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { total, count, page, page_size, has_more, next_page, people: [{ id, name, birth_year_hijri, death_year_hijri, birth_location, death_location, importance, gender }] } Examples: - "Who does Ganjoor know about?" -> no arguments - "Find the person named 'حافظ'" -> search='حافظ' Notes: - Filtering is done client-side; the full list is a few hundred entries. - `importance` ranks how central the person is; higher means better documented.
| Name | Type | Req | Description |
|---|---|---|---|
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| search | string | – | Case-insensitive substring filter on the person's name. |
No output schema declared.
No examples provided.
ganjoor_list_poets List Ganjoor Poets ~355
List all poets published on Ganjoor.net, including their biographies. Returns one row per poet with: id, name, nickname, URL slug, root category id, birth/death years (Hijri), and birth/death places. Use this first when you need to translate a poet's name to a numeric id for other Ganjoor tools. Args: - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: A paginated poet list. For JSON: { total, count, page, page_size, has_more, next_page, poets: [{ id, name, nickname, full_url, root_cat_id, birth_year_hijri, death_year_hijri, birth_place, death_place }] } Examples: - "Who is on Ganjoor?" -> page_size=50 - "List the poets born in the 10th century Hijri" -> fetch pages and filter birth_year_hijri Notes: - Only public, read-only data. No authentication required. - The list is long (~170 poets); paginate rather than requesting page_size=100 repeatedly.
| Name | Type | Req | Description |
|---|---|---|---|
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_list_rhythms List Ganjoor Metres (Rhythms) ~323
List every Persian prosodic metre (وزن) used in the Ganjoor corpus, with its verse-pattern notation. Use this to translate a metre name into the id Ganjoor uses, or to discover the metre vocabulary before calling ganjoor_find_similar_poems or ganjoor_analyze_poem_rhythm. Args: - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 50) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { count, page, page_size, has_more, next_page, rhythms: [{ id, rhythm, verse_count }] } Examples: - "What metres exist?" -> no arguments - "Find the metre 'فاعلاتن'" -> page through results looking for the pattern Notes: - `rhythm` is the classical Persian scansion pattern; `verse_count` is how many Ganjoor poems use it. - There are roughly 50-70 metres; one page of 100 usually covers everything.
| Name | Type | Req | Description |
|---|---|---|---|
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
No output schema declared.
No examples provided.
ganjoor_search_poems Search Ganjoor Poems ~517
Full-text search across all poems on Ganjoor, optionally scoped to one poet or category. The search matches Persian text inside poem bodies and titles. Use this when you know what the poem says but not what it is called; use ganjoor_list_category_poems when you know the book. Args: - term (string): Search text. Persian phrases work best; matches are substring based. - poet_id (number): Restrict to one poet (default: 0 = all poets) - cat_id (number): Restrict to one category (default: 0 = all categories) - page (number): Page number, starting from 1 (default: 1) - page_size (number): Results per page, 1-100 (default: 20) - include_text (boolean): Include each poem's full text in the response (default: false) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { count, page, page_size, has_more, next_page, poems: [{ id, title, full_title, full_url, plain_text? }] } Examples: - "Find poems mentioning 'دل'" -> term='دل', poet_id=2 - "Search Hafez for 'صبر'" -> term='صبر', poet_id=2 - "Give me the full text of the matches" -> include_text=true Notes: - Narrow with `poet_id` or `cat_id` first: unfiltered search over all poems is broad and slow to page through. - Set `include_text=true` only for a small page; full poems are long.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | – | Restrict to a category id. 0 searches all categories. |
| include_text | boolean | – | Include the full poem text for each result. |
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| poet_id | integer | – | Restrict to a poet id. 0 searches all poets. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| term | string | yes | Persian text to search for, e.g. 'صبر', 'دل', 'معرفت'. |
No output schema declared.
No examples provided.
ganjoor_search_recitations Search Ganjoor Recitations ~442
Search the published audio recitations (روایت) of Ganjoor poems, optionally by reciter or poem. Each recitation is a sung or spoken performance of one poem by a named artist, published on ganjoor.net. Args: - search_term (string): Optional text to match against the reciter's (artist's) name - poet_id (number): Restrict to a poet id. 0 = all poets (default: 0) - cat_id (number): Restrict to a category id. 0 = all categories (default: 0) - page (number): Page number, starting from 1 (default: 1) - page_size (number): Items per page, 1-100 (default: 20) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { count, page, page_size, has_more, next_page, recitations: [{ id, poem_id, poem_title, poem_url, artist, title, publish_date, duration_seconds }] } Examples: - "Any recitations by محمدرضا ضیاء?" -> search_term='محمدرضا ضیاء' - "Recitations of Hafez's ghazals" -> poet_id=2 Notes: - When scoped to a poet or category, results are ordered by poem id; otherwise by publish date, newest first.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | – | Restrict to a category id. 0 = all categories. |
| page | integer | – | Page number, starting from 1. |
| page_size | integer | – | Maximum items to return per page (1-100, default 20). |
| poet_id | integer | – | Restrict to a poet id. 0 = all poets. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| search_term | string | – | Text to match against the reciter's name. Empty matches all artists. |
No output schema declared.
No examples provided.
ganjoor_semantic_search_poems Semantic Search Ganjoor Poems ~484
Meaning-based ("find a poem about...") search over Ganjoor's poetry collection. Use this when you want poems by theme or feeling rather than an exact word. Describe the idea in natural language — in English or Persian — and Ganjoor's embedding search returns the closest verses. Prefer ganjoor_search_poems when you have an exact phrase to look for. Args: - query (string): Natural-language description of the poem's theme, 1-500 characters - top_k (number): How many poems to return, 1-50 (default: 10) - poet_id (number): Restrict to a poet id. 0 = all poets (default: 0) - cat_id (number): Restrict to a category id. 0 = all categories (default: 0) - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON: { count, results: [{ id, title, full_title, full_url, plain_text }] } ordered by relevance. Examples: - "Poems about patience and divine trust" -> query='patience and trust in God' - "غزلی دربارهٔ جدایی از معشوق" -> query='a ghazal about separation from the beloved' Notes: - Ganjoor's semantic backend is an optional feature that some deployments leave disabled; when it is off this tool returns a 503 with a message saying so. In that case fall back to ganjoor_search_poems with a Persian keyword describing the theme. - Relevance ordering is approximate — always quote the returned text rather than paraphrasing it.
| Name | Type | Req | Description |
|---|---|---|---|
| cat_id | integer | – | Restrict to a category id. 0 searches all categories. |
| poet_id | integer | – | Restrict to a poet id. 0 searches all poets. |
| query | string | yes | Natural-language description of the theme, e.g. 'a poem about longing for the beloved'. |
| response_format | string | – | Output format: 'markdown' for human-readable text (default) or 'json' for machine-readable structured data. |
| top_k | integer | – | Number of poems to return (1-50, default 10). |
No output schema declared.
No examples provided.
How do I install the io.github.ehsanghaffar/ganjoor-mcp-server server?
io.github.ehsanghaffar/ganjoor-mcp-server runs locally as an npm package, launched with npx -y ganjoor-mcp-server. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · ganjoor-mcp-server
claude mcp add ehsanghaffar-ganjoor-mcp-server -- npx -y ganjoor-mcp-server
What is the io.github.ehsanghaffar/ganjoor-mcp-server server?
io.github.ehsanghaffar/ganjoor-mcp-server is listed in the public MCP registry as io.github.ehsanghaffar/ganjoor-mcp-server. MCP server for the Ganjoor (گنجور) Persian classical poetry API at https://ganjoor.net. This page covers its npm package (ganjoor-mcp-server).
Is the io.github.ehsanghaffar/ganjoor-mcp-server server safe to use?
io.github.ehsanghaffar/ganjoor-mcp-server scores 73 out of 100 on VerifyMCP. We recorded 1 known advisory against it as of 5 November 2026. It declares no install or post-install scripts. 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 io.github.ehsanghaffar/ganjoor-mcp-server server expose?
io.github.ehsanghaffar/ganjoor-mcp-server exposes 44 tools: ganjoor_list_poets, ganjoor_get_poet, ganjoor_get_poets_by_century, ganjoor_list_books, ganjoor_get_category, and 39 more. Their descriptions and schemas cost roughly 13,717 tokens of context every time the server is loaded.
Is the io.github.ehsanghaffar/ganjoor-mcp-server server still maintained?
io.github.ehsanghaffar/ganjoor-mcp-server is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the io.github.ehsanghaffar/ganjoor-mcp-server server under?
io.github.ehsanghaffar/ganjoor-mcp-server declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.