MCP API key and bearer token setup for each client
Get a free Quran Gallery key and send it as a bearer token from Claude Code, Cursor, VS Code, Gemini CLI or mcp-remote, then test it with one curl call.
Cette page n’est pas encore traduite — version anglaise affichée.
Sur cette page
A key is optional. Without one, every client in this section works on the keyless tier. A free key raises the limit and lifts the page-range caps. This page shows, for each client, where the key goes, how to test it, and what the two errors you are most likely to meet look like.
1. Get a free key
- Sign in at accounts.qurangallery.com (the Developers page; the server’s own
GETanswer links to the same address). Create an account if you have none. - Create a key and give it a name you will recognise, such as
laptop-claude-code. - Copy the full key when it is shown. It is shown once; afterwards only its first characters are visible. Keys start with
qg_sk_.
How keys are created, rotated and revoked is covered in API keys.
2. What a key changes
| Without a key | With a free key | |
|---|---|---|
| Tool calls | 10 a minute and 200 a day, per IP address | 60 requests a minute, per key |
shamela_read (unit: 'range') | Up to 5 pages per call | Up to 20 |
shamela_read (unit: 'section') | Up to 10 pages per call | Up to 100 |
The full table, with the RateLimit-* headers, is in Limits and errors.
3. Per-client setup
In every example, qg_sk_... stands for your own key. Do not paste the placeholder as it is: a key that is sent is always checked, so the placeholder is refused with a 401 (see what a 401 looks like). Where a client can read the key from an environment variable or ask for it, that is shown instead of a literal value.
The server URL is the same everywhere:
https://qurangallery.com/mcp/shamelaClaude Code
Set the key in your shell, then register the server with --header. The shell expands the variable, so the key is not typed into the command:
export QG_MCP_KEY='qg_sk_...'
claude mcp add --transport http quran-gallery
https://qurangallery.com/mcp/shamela
--header "Authorization: Bearer $QG_MCP_KEY"claude mcp add stores the header value in the Claude Code configuration for the scope you chose, so that file now holds the key. Run claude mcp list to confirm the server shows as connected. To go back to keyless use, run claude mcp remove quran-gallery and add it again without --header.
Cursor
In ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project), add headers. Cursor resolves ${env:NAME} in headers, so the key can stay in an environment variable instead of the file:
{
"mcpServers": {
"quran-gallery": {
"url": "https://qurangallery.com/mcp/shamela",
"headers": { "Authorization": "Bearer ${env:QG_MCP_KEY}" }
}
}
}Start Cursor from a shell where QG_MCP_KEY is set, or set it for your user account, then toggle the server off and on in Cursor’s MCP list. If the variable is not set when Cursor starts, the header is wrong and the server answers 401.
VS Code
Use an input, so VS Code asks for the key once and keeps it out of .vscode/mcp.json:
{
"inputs": [
{
"type": "promptString",
"id": "qg-key",
"description": "Quran Gallery API key (qg_sk_...)",
"password": true
}
],
"servers": {
"quran-gallery": {
"type": "http",
"url": "https://qurangallery.com/mcp/shamela",
"headers": { "Authorization": "Bearer ${input:qg-key}" }
}
}
}Start the server from the Start action above its entry. VS Code asks for the key on the first start. According to the same VS Code reference, a server that needs an interactive input like this one is not forwarded to Copilot harness sessions, so use it in VS Code chat (VS Code).
Gemini CLI
With the command, using --header (or -H):
gemini mcp add --transport http quran-gallery
https://qurangallery.com/mcp/shamela
--header "Authorization: Bearer qg_sk_..."In settings.json, the streaming URL is httpUrl and the key goes in headers:
{
"mcpServers": {
"quran-gallery": {
"httpUrl": "https://qurangallery.com/mcp/shamela",
"headers": { "Authorization": "Bearer qg_sk_..." }
}
}
}Gemini CLI writes settings.json in your project folder by default, or in ~/.gemini/ with --scope user. Either way the key is now in that file: keep it out of git (Gemini CLI).
mcp-remote (Claude Desktop and other clients that run local commands)
mcp-remote is a local bridge for clients that can start a program but cannot connect to a URL (Connect any MCP client). It takes the header as the argument after --header, and the value can read an environment variable:
{
"mcpServers": {
"quran-gallery": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://qurangallery.com/mcp/shamela",
"--header",
"Authorization:${QG_AUTH}"
],
"env": { "QG_AUTH": "Bearer qg_sk_..." }
}
}
}The space inside Bearer qg_sk_... sits in env rather than in args, because some clients mangle a space inside an argument. The mcp-remote README describes this for Cursor, Codex CLI and Claude Desktop on Windows. It needs Node.js.
4. Test a key with one call
Before blaming a client, send an initialize request yourself. Read the key into a shell variable first, so it does not end up in your history:
read -rs QG_MCP_KEY # paste the key, press Enter
curl -s -i https://qurangallery.com/mcp/shamela
-H 'Content-Type: application/json'
-H 'Accept: application/json, text/event-stream'
-H "Authorization: Bearer $QG_MCP_KEY"
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'A valid key returns HTTP/2 200 and a JSON body whose serverInfo.name is qurangallery-shamela, with ratelimit-limit: 60 in the headers (the keyed limit). Run it once, not in a loop.
5. What the errors look like
What a 401 looks like
A key that is sent is always checked. A wrong, deleted or placeholder key is refused rather than treated as keyless. This is the real response to a placeholder key, read from the live endpoint on 2026-11-01:
HTTP/2 401
www-authenticate: Bearer realm="qurangallery-mcp", error="invalid_token"
{"jsonrpc":"2.0","id":null,"error":{"code":-32001,"message":"That API key is not valid."}}Fix it by sending the real key, or by removing the Authorization header altogether. A header with nothing after Bearer, which is what an unset environment variable in a header template produces, gets the same 401.
What a 429 looks like
A rate limit gives HTTP 429, the JSON-RPC code -32004, and a retry-after header in seconds. The bodies below are quoted from the server code, not from a live trigger, because producing a 429 means spending the keyless allowance.
Keyless, the message names the limit and where to get a key:
{"jsonrpc":"2.0","id":null,"error":{"code":-32004,"message":"Keyless limit reached: 10 tool calls a minute per IP. A free API key raises it to 60 a minute: https://accounts.qurangallery.com/developers"}}The daily limit says “200 tool calls a day” in place of the minute figure. With a key, the message is Rate limit exceeded. Wait for the retry-after seconds and try again. The other errors (403, 503) are in Limits and errors.
6. Key hygiene
- Never commit a key. Keep it in your shell, a password manager or the client’s secret input (the VS Code
inputsabove), and keep any config file that holds a literal key out of git. - One key per machine or tool, named for it, so you can delete one without breaking the others.
- If a key leaks, delete it first, then create a replacement. A deleted key can keep working for up to a minute because verified keys are cached (Limits and errors).
- Never put a key in a URL. The server reads it only from
Authorization: Bearer; a query parameter does nothing. - Do not paste a key into a chat. Your assistant does not need to see it; the client sends it.