Use the Shamela MCP server from Python, LangChain and agents
Call the Quran Gallery MCP server from Python with langchain-mcp-adapters and LlamaIndex, pass a key, and print volume, page and matchedIn per passage.
هذه الصفحة غير مترجمة بعد — تُعرض النسخة الإنجليزية.
في هذه الصفحة
You can call the server from your own code, not only from a chat app. The endpoint is a standard remote MCP server over streamable HTTP, so any client library that speaks that transport works:
https://qurangallery.com/mcp/shamelaNo account or key is needed to try it. Without a key you get the keyless limits (10 requests a minute, 200 a day, per IP address); with a free key you get 60 a minute. See Limits and errors.
This page holds the recipes that were run against the live endpoint on 1 November 2026, with the package versions they ran on. Recipes that were not run are not on this page.
| Package | Version run |
|---|---|
langchain-mcp-adapters | 0.3.2 |
langchain-core | 1.7.3 |
llama-index-tools-mcp | 0.4.8 |
llama-index-core | 0.14.25 |
mcp (Python SDK) | 1.30.0 |
Python 3.12.8 was used. Both libraries listed 14 tools from this endpoint, the same set described in the full tool surface.
Connect with LangChain
langchain-mcp-adapters turns each MCP tool into a LangChain tool. Install it, then point it at the URL with the http transport (streamable HTTP):
pip install langchain-mcp-adaptersimport asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
async def main():
client = MultiServerMCPClient(
{
"shamela": {
"transport": "http",
"url": "https://qurangallery.com/mcp/shamela",
}
}
)
tools = await client.get_tools()
print(len(tools), "tools")
asyncio.run(main())The output when this was run was 14 tools.
Connect with LlamaIndex
pip install llama-index-tools-mcpimport asyncio
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
async def main():
client = BasicMCPClient("https://qurangallery.com/mcp/shamela")
spec = McpToolSpec(client=client)
tools = await spec.to_tool_list_async()
print(len(tools), "tools")
asyncio.run(main())The output when this was run was 14 tools. The tool list feeds a LlamaIndex agent the same way any other tool list does.
Call a tool and read the citation
This script calls shamela_search_library and prints the book, the printed volume and page, and where the words were found. It does not need a model or a model key, so it is the quickest way to check your setup.
import asyncio
import json
from langchain_mcp_adapters.client import MultiServerMCPClient
async def main():
client = MultiServerMCPClient(
{
"shamela": {
"transport": "http",
"url": "https://qurangallery.com/mcp/shamela",
}
}
)
tools = {t.name: t for t in await client.get_tools()}
blocks = await tools["shamela_search_library"].ainvoke(
{"query": "إنما الأعمال بالنيات", "scope": "hadith-primary", "limit": 3}
)
result = json.loads(blocks[0]["text"])
for p in result["passages"]:
print(p["book"], p["printedPage"], p["matchedIn"])
asyncio.run(main())Output when this was run:
سنن ابن ماجه - ت الأرنؤوط 5/ 305 body
صحيح البخاري - ط السلطانية 1/ 6 body
سنن أبي داود - ت الأرنؤوط 3/ 526 footnoteThree things to notice, each explained in Reading a result:
printedPageis volume and page in that printing, such as5/ 305.matchedInisbody,footnote,bothorunknown. The third row above matched in a footnote, which is an editor’s note and not the author’s text. See Main text or footnotes.scopeis required. See Choosing a scope.
The query must be in Arabic; a query with no Arabic words is a tool error that tells the caller to translate it. When you give these tools to a model, the model does that translation before it calls.
Pass a key
A key raises the limit from 10 to 60 requests a minute. Create a free one at accounts.qurangallery.com/developers, keep it in an environment variable, and send it as a bearer token in the headers of the connection. Never put a real key in source code.
import os
connection = {
"transport": "http",
"url": "https://qurangallery.com/mcp/shamela",
"headers": {"Authorization": f"Bearer {os.environ['QG_API_KEY']}"},
}Use connection as the value under "shamela" in MultiServerMCPClient. LlamaIndex’s BasicMCPClient has a headers argument for the same header:
client = BasicMCPClient(
"https://qurangallery.com/mcp/shamela",
headers={"Authorization": f"Bearer {os.environ['QG_API_KEY']}"},
)A key that is sent is checked. A key that is not valid gets a 401 instead of falling back to the keyless tier, so a typo shows up at once. When this was run with a deliberately invalid placeholder key, the connection failed. It was not run with a valid key. Full setup, including the clients that take a key in a config file, is in Bearer-token setup.
Not covered here
The OpenAI Responses API remote-MCP tool and the Anthropic Messages API MCP connector can also call a remote MCP server by URL. They need a model account to run, and were not run for this page, so they are not described. For those, use the endpoint URL above and the client’s own documentation.