Skip to main content
Glama
Muslim Prayer Reminder MCP

Muslim Prayer Reminder MCP

Local prayer times

Next prayer at a glance

Your setup, your choice

Location-aware timetables with 12 calculation methods.

Next-prayer countdowns and configurable reminder windows.

Connect to the hosted endpoint or run locally over stdio.


⚡ Quick Start

1. Run via NPX (Zero Installation)

Add to your Claude Desktop or Cursor MCP configuration:

{
  "mcpServers": {
    "muslim-prayer": {
      "command": "npx",
      "args": ["-y", "muslim-prayer-mcp"]
    }
  }
}

2. Connect via Remote Streamable HTTP (Cloudflare Workers)

{
  "mcpServers": {
    "muslim-prayer": {
      "url": "https://muslim-prayer-mcp.najetareqz.workers.dev/mcp"
    }
  }
}

3. 1-Click Install in Cursor

Install in Cursor


Related MCP server: Remote MCP Server on Cloudflare

Analytics dashboard

/analytics displays daily, weekly, monthly, and selected-period active-user counts from a minimal SQLite Durable Object. It counts only identifiable ChatGPT tool users arriving through verified OpenAI egress IPs. It records no individual tool calls, handshakes, sessions, IPs, bot activity, or location details. The dashboard is public unless ANALYTICS_TOKEN or AUTH_TOKEN is configured.

  • Protect it: set a Worker secret named ANALYTICS_TOKEN (Cloudflare dashboard, Worker, Settings, Variables and Secrets). Open /analytics and enter any username with the token as the password. /api/analytics also accepts Authorization: Bearer <token>.

  • Data model: one row per distinct verified ChatGPT subject per UTC day, using a 64-bit truncated SHA-256 pseudonym with the public prefix mpr:v1:. No per-call analytics are retained; activity is kept for up to 180 days.

  • Quota guardrails: 500 tracked distinct users per UTC day maximum; reporting has four fixed ranges (7/30/90/180 days) and at most one persisted snapshot per range each UTC day. When the cap is reached, additional user-days are not counted; prayer tools still work.

  • Verification and limits: the subject and OpenAI IP-range checks are conservative signals, not proof of a human. Non-ChatGPT users, missing subject IDs, installs with no tool calls, and clients without verifiable provenance are not counted. No Worker-level scheme can reserve free quotas for the rest of the Cloudflare account.

📺 Live Video Demonstration

Watch the Muslim Prayer Reminder MCP in action inside ChatGPT, Claude, and Cursor:


🏛️ System Architecture

flowchart TD
    subgraph ClientLayer ["AI Clients & Environments"]
        Cursor["Cursor IDE"]
        Claude["Claude Desktop / Web"]
        ChatGPT["ChatGPT Apps Directory"]
        Agent["Autonomous AI Agent"]
    end

    subgraph TransportLayer ["Model Context Protocol"]
        HTTP["Streamable HTTP /mcp"]
        Stdio["Stdio Transport CLI"]
    end

    subgraph ResolverLayer ["Layered Location Resolver"]
        Explicit["User coordinates + timezone or supported city"] --> Truncate["2-Decimal Sanitizer ~1.1km"]
        UserPref["Stored KV Preferences"] --> Resolver["Location Normalizer"]
        Headers["Verified end-user location headers"] --> Resolver
        Resolver --> Missing["No usable user location: location_required"]
        Truncate --> Resolver
    end

    GeoIP["Cloudflare network metadata"] --> Analytics["Operational analytics only"]

    subgraph EngineLayer ["In-Isolate Solar Calculation Engine"]
        Resolver --> Authority["Authority Selector"]
        Authority --> AdhanEngine["Astronomical Solar Solver"]
        AdhanEngine --> FiqhRules["Fiqh Clamping 48° & Madhab Calibration"]
        FiqhRules --> DueLogic["Prayer Window & Due Evaluator"]
    end

    subgraph OutputLayer ["Formatted Payloads & Disclosures"]
        DueLogic --> MCPResponse["JSON-RPC Structured Output"]
        MCPResponse --> DisclosureNotice["Mandatory Theological Notice"]
        DisclosureNotice --> Middleware["Deterministic Host Middleware"]
        Middleware --> FinalOutput["Appended AI Response: 🕌 It is time for Maghrib prayer"]
    end

    ClientLayer --> TransportLayer
    TransportLayer --> ResolverLayer

MCP Prompts and Resources

In addition to the five calculation and preference tools, compatible MCP clients can use two protocol-native, read-only learning features:

  • Prompt: check_prayer_times_with_disclosure guides a client to obtain real prayer times using the tool, ask for missing location, and explain the calculation authority, reason for selection, and high-latitude adjustments.

  • Resource: prayer://calculation-guide provides a short guide to location requirements, Asr conventions, twilight methods, and differences from local mosque timetables.

These features do not guess prayer times, read private preferences, or replace the calculation tools. They are available through the current hosted MCP endpoint. Older local npm versions may not provide the new prompt and resource until updated.


🛠️ MCP Tools Catalog

The server exposes 5 finely-tuned tools conforming to the latest Model Context Protocol standard with full Zod output contracts:

Tool Name

Operation Mode

Open World

Description

get_prayer_status

Temporary state write

Safe

Checks if an obligatory prayer is currently due. Returns active prayer, countdown, calculation authority, and selection justification.

get_today_prayer_times

Read-Only

Safe

Computes today's full timetable (Fajr, Sunrise, Dhuhr, Asr, Maghrib, Isha) in UTC and localized string format.

get_next_prayer

Read-Only

Safe

Returns the immediate upcoming prayer, exact scheduled timestamp, countdown minutes, and regional authority.

configure_prayer_preferences

Overwrites saved settings (destructiveHint: true)

Safe

Updates supplied preferences; switching fixed location can clear the previous location and timezone. Previous values are not retained for undo.

get_prayer_preferences

Read-Only

Safe

Reads saved public preference settings.


📐 Astronomical & Theological Rigor

Prayer calculations use astronomical models and configured regional methods; high-latitude substitutes and geographic heuristics are disclosed:

Sovereign Authority

Jurisdiction

Fajr Angle

Isha Angle / Interval

Default Asr Madhab

Umm al-Qura University

Saudi Arabia

18.5°

+90 min

Shafi / Standard

Egyptian General Survey

Egypt, Palestine, Levant

19.5°

17.5°

Shafi (configured Palestinian service offsets applied)

Diyanet İşleri Başkanlığı

Turkey, Balkans, Central Asia

18.0°

17.0°

Hanafi (Double shadow ratio)

Univ. of Islamic Sciences, Karachi

Pakistan, India, Bangladesh

18.0°

18.0°

Hanafi (Double shadow ratio)

ISNA

United States, Canada

15.0°

15.0°

Shafi / Standard

Muslim World League (MWL)

Europe, Global Fallback

18.0°

17.0°

Shafi / Standard

Configured Singapore method

Malaysia, Singapore, Indonesia

20.0°

18.0°

Shafi / Standard

High-Latitude Polar Adjustments

In latitudes above 48° North or South where twilight persists throughout the night in summer, the engine automatically engages fiqh-compliant clamping (Middle of the Night & One-Seventh Rule), preventing computational errors or impossible timetables.


🔌 Install & Multi-Agent Setup

Connect Muslim Prayer Reminder to any AI agent harness, developer IDE, or container runtime:

1-Click & Matrix Overview

Environment / Harness

Protocol Mode

Quick Command / Deeplink

Cursor IDE

Remote HTTP

Install in Cursor

Claude Code

Native Plugin

/plugin marketplace add tareq7/muslim-prayer-mcp

Codex

Native Plugin

codex plugin marketplace add tareq7/muslim-prayer-mcp

GitHub Copilot CLI

Copilot Plugin

copilot plugin marketplace add tareq7/muslim-prayer-mcp

Claude Desktop

Stdio CLI

npx -y muslim-prayer-mcp via claude_desktop_config.json

VS Code & Cline

Local NPX

npx -y muslim-prayer-mcp via .vscode/mcp.json

Windsurf & Devin

Remote HTTP

Remote URL to mcp_config.json

Gemini CLI

Native Extension

gemini mcp add --transport http muslim-prayer https://muslim-prayer-mcp.najetareqz.workers.dev/mcp

Pi Agent Harness

Git Extension

pi install git:github.com/tareq7/muslim-prayer-mcp

OpenCode

Agent Plugin

Auto-loaded via opencode.json & AGENTS.md

Docker Container

Container

docker build -t muslim-prayer-mcp . then docker run --rm -i muslim-prayer-mcp (stdio)


Claude Code

Run inside your Claude Code session:

/plugin marketplace add tareq7/muslim-prayer-mcp
/plugin install muslim-prayer-mcp@muslim-prayer-mcp

(Note: Send as two separate prompts). In the Claude Code Desktop app, click the + button next to the prompt box ➔ Plugins ➔ Add plugin to browse and install from the marketplace.


Codex

Run in your terminal:

codex plugin marketplace add tareq7/muslim-prayer-mcp
codex plugin add muslim-prayer-mcp@muslim-prayer-mcp

Run codex and open /hooks (or start a new thread). This also activates the plugin in the Codex Desktop app upon restart.


GitHub Copilot CLI

In your terminal:

copilot plugin marketplace add tareq7/muslim-prayer-mcp
copilot plugin install muslim-prayer-mcp@muslim-prayer-mcp

Or inside an interactive Copilot CLI session:

/plugin marketplace add tareq7/muslim-prayer-mcp
/plugin install muslim-prayer-mcp@muslim-prayer-mcp

Cursor IDE

Click to install with one click:
Install in Cursor

Or manually add to .cursor/mcp.json:

{
  "mcpServers": {
    "muslim-prayer": {
      "url": "https://muslim-prayer-mcp.najetareqz.workers.dev/mcp"
    }
  }
}

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "muslim-prayer": {
      "command": "npx",
      "args": ["-y", "muslim-prayer-mcp"]
    }
  }
}

VS Code & Cline

Add this to .vscode/mcp.json using VS Code's servers format:

{
  "servers": {
    "muslim-prayer": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "muslim-prayer-mcp"]
    }
  }
}

Cline settings use the mcpServers format shown in Quick Start.


Windsurf & Devin

Add to mcp_config.json:

{
  "mcpServers": {
    "muslim-prayer": {
      "url": "https://muslim-prayer-mcp.najetareqz.workers.dev/mcp"
    }
  }
}

Gemini CLI

Connect directly using the live edge endpoint:

gemini mcp add --transport http muslim-prayer https://muslim-prayer-mcp.najetareqz.workers.dev/mcp

Pi Agent Harness

pi install git:github.com/tareq7/muslim-prayer-mcp

OpenCode

Add to your opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "muslim-prayer": {
      "type": "remote",
      "url": "https://muslim-prayer-mcp.najetareqz.workers.dev/mcp"
    }
  }
}

OpenCode automatically loads this repository's AGENTS.md and skills/muslim-prayer-mcp/SKILL.md.


Docker Container

docker build -t muslim-prayer-mcp .
docker run --rm -i muslim-prayer-mcp

💻 Deterministic Host Middleware

For platforms building autonomous AI agents (Next.js, LangChain, Vercel AI SDK), the included middleware deterministically appends prayer notices to AI responses without hallucination:

import { PrayerReminderMiddleware } from 'muslim-prayer-mcp/middleware';

const prayerMiddleware = new PrayerReminderMiddleware({
  workerBaseUrl: 'https://muslim-prayer-mcp.najetareqz.workers.dev',
  userId: 'user_session_42',
});

// Wrap any LLM completion
const rawLlmOutput = await callLlm('Can you review this pull request?');
const { responseText, reminderAppended } = await prayerMiddleware.processResponse(rawLlmOutput, {
  'X-User-Coordinates': '24.71, 46.68', // Riyadh
  'X-User-Timezone': 'Asia/Riyadh',
});

console.log(responseText);
// => The code looks solid, but let's optimize line 42...
//
// 🕌 It is time for Asr prayer.

🧪 Comprehensive Test Suite

The engine includes 44 unit, integration, and end-to-end tests validating astronomical accuracy across 10 worldwide benchmark coordinates:

npm test
▶ Astronomical Prayer Calculation Suite
  ✔ calculates valid prayer timetable for Riyadh in correct chronological sequence
  ✔ calculates valid prayer timetable for Makkah in correct chronological sequence
  ✔ calculates valid prayer timetable for Cairo in correct chronological sequence
  ✔ calculates valid prayer timetable for Dubai in correct chronological sequence
  ✔ calculates valid prayer timetable for London in correct chronological sequence
  ✔ calculates valid prayer timetable for Paris in correct chronological sequence
  ✔ calculates valid prayer timetable for New York in correct chronological sequence
  ✔ calculates valid prayer timetable for Jakarta in correct chronological sequence
  ✔ calculates valid prayer timetable for Karachi in correct chronological sequence
  ✔ calculates valid prayer timetable for Sydney (Southern Hem) in correct chronological sequence
  ✔ verifies Hanafi Asr is strictly later than Shafi Asr
  ✔ handles Daylight Saving Time (DST) transitions safely
  ✔ automatically resolves Palestinian Awqaf standard for Gaza
  ✔ handles high-latitude polar city with MiddleOfTheNight rule safely
...
ℹ tests 44 | pass 44 | fail 0

🔒 Security & Privacy Policy

  • Coordinate Truncation: All user coordinates are truncated to 2 decimal places upon arrival (~1.1 km resolution). Precise location is mathematically non-recoverable.

  • No Outbound Tracking: Astronomical math is computed locally within the isolated V8 runtime; zero external requests are made to third-party tracking APIs.

  • Fail-Open Architecture: Host middleware is designed to fail open; network issues or latency spikes will never block primary AI conversation streams.

  • Full Disclosure Process: See SECURITY.md for supported versions, SLA, and private reporting.


Registries & ratings


📄 Governance, Ownership & Community

Verified location and calculation disclosures (v1.1.0)

Prayer tools accept a supported city, coordinates with timezone, or complete stored fixed settings. Missing location returns location_required; connector/IP geolocation and automatic Makkah fallback are not used. Explicit per-call inputs override fixed preferences. Host headers must represent the end user.

highLatitudeAdjustment discloses twilight substitutions and polar clamping; effectiveLatitude is present only for the +/-48-degree substitute and never echoes the original coordinate. calculationDetails reports location basis and regional, user, and method offsets. Invalid offsets that reverse prayer windows return invalid_calculation. Preferences expose fixedCoordinatesConfigured and fixedCityConfigured while redacting coordinates.

Analytics stores only pseudonymous verified ChatGPT user-days for up to 180 days. It does not store individual requests, session identifiers, errors, locations, or bot traffic. Snapshot reports refresh at most once per UTC day, and daily tracking stops after 500 distinct users to protect free quotas. Both dashboard aliases honor configured service authentication; without an analytics/service token, access is public. See the privacy policy for the precise trust boundaries.

Preference and display-time contracts

Explicit coordinates require timezone in the same request. Stored fixed-location timezones are never inherited for new explicit coordinates. calculationDetails.timezoneSource identifies explicit, city, stored, or host input; city timezones must match the canonical city zone or an IANA alias. Coordinate timezones are checked against an approximate offline lookup and nearby boundary cells; contradictory values return location_timezone_mismatch with expectedTimezone. Supply city or coordinates, never both. Geographic default authority follows the lookup, not the supplied display timezone.

Fixed mode requires a supported city or coordinates with timezone. New fixed coordinates require timezone in the same configuration request. Failed configuration updates save nothing. Switching to auto_travel preserves fixed location for reuse; clearFixedLocation:true removes city, coordinates and timezone and defaults to auto-travel, preserving unrelated preferences. Clear cannot accompany replacement location/timezone or incomplete fixed mode.

For identified users, prayer_window and exact_window emit once per prayer/date/mode; persistent emits throughout the prayer period. Locale changes and toggling reminders do not reset deduplication. Anonymous calls do not persist deduplication. expiresAtUtc retains its prayer-period meaning; prayerWindowExpiresAtUtc names the same boundary, and reminderWindowExpiresAtUtc describes eligibility, capped by the prayer boundary in exact mode. These fields appear when a reminder is emitted. Cross-region KV updates and deduplication remain best effort.

The Palestinian regional profile is a configured service heuristic using the Egyptian method with Dhuhr -1 and Maghrib +3 minute offsets. Its broad coordinate/timezone/country rules do not establish jurisdiction. Exact adoption of these parameters by the Palestinian ministry has not been verified from a primary source. Users can override method and offsets. Other regional choices are service defaults, not nationwide mandates. Method descriptions follow Adhan documentation.

The supported city vocabulary and aliases are advertised in each location input schema and generated skill. The service registers five tools only. Duplicate suffixed tools or old schemas in a connector require refreshing its registration; they are not separate server operations.

Timezone validation uses @photostructure/tz-lookup 11.7.0 (compact, approximate geographic data). Canonical IANA aliases are accepted; matching sampled UTC offsets is not sufficient, because DST transition dates can differ. Near boundaries, adjacent lookup zones within roughly 0.05 degrees are accepted and disclosed as nearby_boundary. This is not precise jurisdiction detection. Mathematical poles retain an explicit civil timezone choice; ocean cells require a matching nautical zone or nearby civil zone. New and updated fixed-city preferences store the canonical city timezone; contradictory supplied values are rejected. Legacy city records are presented canonically without rewriting other data on a read.

The caller must supply current city or coordinates/timezone in auto_travel mode; there is no automatic IP geolocation. Stored method preferences remain active while traveling. exact_window uses the saved duration or, when unset, the service default of 20 minutes unless an operator overrides it. Omitting the duration preserves existing preferences.

Available Tools

5 tools
configure_prayer_preferencesConfigure User Prayer PreferencesA
DestructiveIdempotent
Inspect

Updates persistent prayer preferences, overwriting supplied settings while preserving omitted settings. Setting fixedCity replaces stored fixedCoordinates and stores the canonical city timezone; contradictory timezones are rejected; setting fixedCoordinates replaces stored fixedCity. Can disable reminders. Fixed mode requires a supported fixedCity or fixedCoordinates with timezone; new coordinates require timezone in the same request. clearFixedLocation removes saved location and timezone and defaults to auto_travel. Combined fixed-location calculation settings are validated for the current and next local day before saving. Invalid combinations preserve the previous preferences. Auto-travel chronology is checked when a query supplies its location. Previous values are not retained for undo.

NameRequiredDescriptionDefault
localeNoLanguage for reminder text: en or ar
madhabNoJurisprudential Asr shadow calculation: Shafi or Hanafi
userIdYesNonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved.
enabledNoWhether prayer reminders are enabled
timezoneNoIANA timezone identifier (e.g. Asia/Riyadh, Europe/London)
fixedCityNoSupported cities: makkah, madinah, riyadh, cairo, gaza, jerusalem, alquds, ramallah, hebron, nablus, rafah, khanyunis, dubai, abudhabi, kuwait, doha, amman, istanbul, london, paris, newyork, toronto, jakarta, singapore, karachi, kualalumpur, tehran, sydney, tromso. Aliases: gazacity, nyc, kuwaitcity. Case, spaces and punctuation are ignored.
locationModeNoLocation strategy: fixed uses saved location; auto_travel requires the caller to supply current city or coordinates/timezone on each query and never uses IP geolocation.
reminderModeNoReminder display policy: prayer_window, exact_window, persistent
fixedCoordinatesNoFixed geographical coordinates
highLatitudeRuleNoHigh latitude twilight adjustment rule
calculationMethodNoIslamic prayer calculation authority
minuteAdjustmentsNoCustom per-prayer minute offsets (-60 to +60). For fixed locations, combined settings must preserve timetable chronology for the current and next local day before saving; auto-travel offsets are validated when a query supplies its location.
clearFixedLocationNoRemove stored fixedCity, fixedCoordinates and timezone. Switches to auto_travel unless locationMode is supplied. Cannot combine with a new fixed location/timezone.
exactWindowMinutesNoDuration in minutes for exact_window mode. Omitted updates preserve the saved value; if unset, the service default is 20 minutes unless the operator overrides it.

Output Schema

NameRequiredDescription
successYesWhether configuration succeeded
preferencesYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: states that supplied settings overwrite while omitted ones persist, that fixedCity/fixedCoordinates mutually replace each other, that contradictory timezones are rejected, that invalid combinations preserve prior preferences, and critically that 'Previous values are not retained for undo' — which operationalizes the destructiveHint. This is exactly the kind of mutation/validation/irreversibility context structured fields cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core update semantics before diving into mode-specific rules, and nearly every sentence encodes a distinct constraint. It is dense and slightly verbose in places where it mirrors schema wording, but there is little true padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 14-parameter destructive mutation tool with nested objects and an output schema, the description covers persistence semantics, mutual exclusivity, validation timing, and irreversibility — everything an agent needs to call it safely. Return values are properly left to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine cross-parameter precedence rules the schema describes only per-field (fixedCity replaces stored fixedCoordinates, fixedCoordinates replaces fixedCity, clearFixedLocation and combined setting validation). It adds meaning beyond the per-parameter descriptions, though some sentences restate schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Updates persistent prayer preferences') and immediately characterizes the update semantics as merge-style ('overwriting supplied settings while preserving omitted settings'). This clearly separates it from the read-only siblings get_prayer_preferences / get_prayer_status without needing to name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete conditions for the key modes: fixed mode requires a supported city or coordinates+timezone, new coordinates require a timezone in the same request, clearFixedLocation defaults to auto_travel, and contradictory timezones are rejected. It does not explicitly say when to prefer this tool over get_prayer_preferences or when NOT to call it, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_next_prayerGet Upcoming Prayer and CountdownA
Read-onlyIdempotent
Inspect

Returns the immediate next prayer name, scheduled time, authority calculation method, and remaining countdown in minutes. MANDATORY: The LLM must always explicitly disclose to the user which calculation authority method was used and why it was selected (see authorityNotice in response).

NameRequiredDescriptionDefault
cityNoSupported cities: makkah, madinah, riyadh, cairo, gaza, jerusalem, alquds, ramallah, hebron, nablus, rafah, khanyunis, dubai, abudhabi, kuwait, doha, amman, istanbul, london, paris, newyork, toronto, jakarta, singapore, karachi, kualalumpur, tehran, sydney, tromso. Aliases: gazacity, nyc, kuwaitcity. Case, spaces and punctuation are ignored.
madhabNoOptional Asr shadow jurisprudence override (Shafi or Hanafi)
userIdNoNonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved.
latitudeNoOptional explicit latitude override
timezoneNoIANA timezone; required in the same request when latitude/longitude are supplied. Must agree with the city or be compatible with the coordinate timezone lookup.
longitudeNoOptional explicit longitude override
calculationMethodNoOptional calculation authority override (auto-resolved from location by default)

Output Schema

NameRequiredDescription
madhabYesActive Asr jurisprudence
timezoneYesResolved IANA timezone
nextPrayerYesName of the upcoming prayer
authorityNoticeNo
nextPrayerAtUtcYesUTC timestamp of the upcoming prayer
selectionReasonNo
currentLocalDateYesCurrent local date YYYY-MM-DD
remainingMinutesYesMinutes remaining until prayer start
calculationMethodYesActive calculation authority
minuteAdjustmentsNo
calculationDetailsNo
nextPrayerLocalTimeYesFormatted local time HH:mm
authorityDescriptionNo
highLatitudeAdjustmentNo

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this a safe, idempotent, non-destructive read, so the bar is lower. The description nonetheless adds a real behavioral obligation that annotations cannot convey: the LLM must explicitly disclose the calculation authority method and its rationale, pointing at authorityNotice in the response. That is meaningful, non-redundant context beyond the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences: the first front-loads the return payload, the second carries the single non-obvious operational rule. There is no filler, no restatement of the title, and no repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not enumerate return values, and annotations cover the safety profile; the description correctly spends its budget on the one thing neither structured field can express, the mandatory authority disclosure. The only gap is the absence of any routing guidance against its closely related siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and every parameter (city aliases, madhab enum, timezone/lat/long dependencies, calculationMethod enum) is already documented in the schema. The description only alludes to the calculation method being auto-resolved, adding essentially no syntax or format detail beyond what the schema supplies, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Returns the immediate next prayer name, scheduled time...') plus the distinctive extra payload (countdown in minutes), which separates it from get_today_prayer_times and get_prayer_status. It stops short of explicitly naming or contrasting those siblings, so an agent must infer the boundary from names alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use or when-not-to-use guidance, nor any reference to the four sibling tools that overlap in subject matter (e.g. get_prayer_status vs get_today_prayer_times). The MANDATORY disclosure sentence is an output obligation, not tool-selection guidance, so usage is only implied by the 'next prayer' framing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_prayer_preferencesRetrieve Stored Prayer PreferencesB
Read-onlyIdempotent
Inspect

Returns the currently active calculation settings and preferences for a user. Read-only operation.

NameRequiredDescriptionDefault
userIdYesNonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved.

Output Schema

NameRequiredDescription
localeNo
madhabNo
enabledNo
messageNo
timezoneNo
fixedCityNo
locationModeNo
reminderModeNo
updatedAtUtcNo
highLatitudeRuleNo
calculationMethodNo
minuteAdjustmentsNo
exactWindowMinutesNo
fixedCityConfiguredYes
fixedCoordinatesConfiguredYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so 'Read-only operation' merely restates structured data. The only added behavioral value is 'currently active', which hints that inactive/stored-but-unused preferences are excluded from the result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the resource description. The second sentence is redundant with readOnlyHint and could be cut, a minor waste rather than a structural flaw.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and annotations fully cover the safety profile. For a one-parameter read tool the description is nearly sufficient; only the missing routing guidance versus sibling tools leaves a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single userId parameter is fully documented with pattern and length constraints, so the schema does the heavy lifting. The description adds nothing about the parameter, which is the expected baseline for this coverage level.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Returns) and resource (calculation settings and preferences) with the scoping qualifier 'currently active', which separates it from the write-oriented sibling configure_prayer_preferences. It never names that sibling, so differentiation is inferable rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use or when-not-to-use guidance and no mention of alternatives. An agent must infer from the tool name alone that this is the read counterpart to configure_prayer_preferences and not, say, a status check like get_prayer_status.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_prayer_statusCheck Muslim Prayer Due StatusAInspect

Checks if a Muslim obligatory prayer (Fajr, Dhuhr, Asr, Maghrib, Isha) is currently due for the user location and returns active reminder details. MANDATORY: The LLM must always explicitly disclose to the user which calculation authority method was used and why it was selected (see authorityNotice in response).

NameRequiredDescriptionDefault
cityNoSupported cities: makkah, madinah, riyadh, cairo, gaza, jerusalem, alquds, ramallah, hebron, nablus, rafah, khanyunis, dubai, abudhabi, kuwait, doha, amman, istanbul, london, paris, newyork, toronto, jakarta, singapore, karachi, kualalumpur, tehran, sydney, tromso. Aliases: gazacity, nyc, kuwaitcity. Case, spaces and punctuation are ignored.
madhabNoOptional Asr shadow jurisprudence override (Shafi or Hanafi)
userIdNoNonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved.
latitudeNoOptional explicit latitude override
timezoneNoIANA timezone; required in the same request when latitude/longitude are supplied. Must agree with the city or be compatible with the coordinate timezone lookup.
longitudeNoOptional explicit longitude override
calculationMethodNoOptional calculation authority override (auto-resolved from location by default)

Output Schema

NameRequiredDescription
madhabYesActive Asr jurisprudence
prayerNoThe name of the currently due prayer if applicable
timezoneYesResolved IANA timezone
localDateYesCurrent local date in YYYY-MM-DD
nextPrayerYesThe name of the next upcoming prayer
reminderDueYesWhether a prayer is currently due for reminder
expiresAtUtcNoUTC expiration time of the active prayer window
reminderTextNoLocalized reminder message
startedAtUtcNoUTC start time of the active prayer window
authorityNoticeYesMandatory theological transparency notice; detailed provenance is at top level
nextPrayerAtUtcYesUTC timestamp of the next upcoming prayer
selectionReasonNoReason for authority selection
calculationMethodYesActive calculation authority
minuteAdjustmentsNoApplied minute adjustments
calculationDetailsNo
authorityDescriptionNoDescription of the calculation authority
nextPrayerCalculationNoAdjustment disclosure for the actual schedule of the next event, including tomorrow
highLatitudeAdjustmentNo
prayerWindowExpiresAtUtcNoEnd of the active prayer period; same boundary as legacy expiresAtUtc
reminderWindowExpiresAtUtcNoReminder eligibility end; exact_window is capped by the prayer period boundary. Fields appear when a reminder is emitted.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds a genuine behavioral requirement not present in the annotations: the agent must disclose the calculation authority method used and why, pointing at authorityNotice in the response. However, it never explains the notable annotation signal that readOnlyHint is false for what reads like a status query (does it persist reminder state?), leaving a real behavioral question unanswered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core behavior, with the mandatory disclosure instruction isolated in its own clearly-marked clause. Slightly heavy on imperative phrasing but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the description covers the core behavior plus a mandatory output-disclosure obligation. It does not explain how location is supplied (city vs. coordinates vs. userId) or the auto-resolution default, which is a modest gap for a 7-parameter, zero-required tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the enums are documented inline, so the schema carries the parameter burden. The description only implies location-based resolution and hints at the calculation authority concept, adding no format, default, or dependency detail beyond what the schema already states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ('Checks if a Muslim obligatory prayer ... is currently due') and enumerates the five prayers covered, which distinguishes it in spirit from get_next_prayer and get_today_prayer_times. It stops short of explicitly naming those siblings or contrasting the scopes, so it is clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the phrase 'currently due,' which suggests a real-time status check, but there is no explicit when-to-use, when-not-to-use, or routing to get_next_prayer / get_today_prayer_times. The MANDATORY sentence governs output disclosure, not tool selection, so it does not fill this gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_today_prayer_timesGet Full Daily Prayer TimetableA
Read-onlyIdempotent
Inspect

Retrieves today prayer timetable (Fajr, Sunrise, Dhuhr, Asr, Maghrib, Isha) in UTC and formatted local time. MANDATORY: The LLM must always explicitly disclose to the user which calculation authority method was used and why it was selected (see authorityNotice in response).

NameRequiredDescriptionDefault
cityNoSupported cities: makkah, madinah, riyadh, cairo, gaza, jerusalem, alquds, ramallah, hebron, nablus, rafah, khanyunis, dubai, abudhabi, kuwait, doha, amman, istanbul, london, paris, newyork, toronto, jakarta, singapore, karachi, kualalumpur, tehran, sydney, tromso. Aliases: gazacity, nyc, kuwaitcity. Case, spaces and punctuation are ignored.
dateNoDate in YYYY-MM-DD format (defaults to today)
madhabNoOptional Asr shadow jurisprudence override (Shafi or Hanafi)
userIdNoNonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved.
latitudeNoOptional explicit latitude override
timezoneNoIANA timezone; required in the same request when latitude/longitude are supplied. Must agree with the city or be compatible with the coordinate timezone lookup.
longitudeNoOptional explicit longitude override
calculationMethodNoOptional calculation authority override (auto-resolved from location by default)

Output Schema

NameRequiredDescription
madhabYesActive Asr jurisprudence
timesUtcYes
timezoneYesResolved IANA timezone
localDateYesLocal schedule date YYYY-MM-DD
timesLocalYes
authorityNoticeNo
selectionReasonNo
calculationMethodYesActive calculation authority
minuteAdjustmentsNo
calculationDetailsNo
authorityDescriptionNo
highLatitudeAdjustmentNo

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds genuinely non-obvious behavioral context: the response carries an authorityNotice and the LLM is mandated to disclose the calculation method and its rationale to the user — a caller-side obligation not derivable from the annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly constructed sentences with the purpose front-loaded and zero filler. The second sentence is an operational mandate rather than a description, but it is short and clearly flagged with 'MANDATORY', so it earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value details need not be restated, and the description still flags the authorityNotice field. The one gap is location resolution: with zero required parameters, the description never explains what happens if no city or coordinates are supplied, which an agent needs to know before calling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including per-parameter docs, enum membership, city aliases, and the latitude/longitude/timezone dependency rules, so the schema carries the load. The description mentions only that location drives method auto-resolution and notes the authority override, adding no syntax or format detail beyond the schema; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — retrieve today's prayer timetable — and enumerates the six prayers returned plus the UTC/local-time duality. It is distinguishable from siblings like get_next_prayer and get_prayer_status by the word 'timetable', but it never explicitly contrasts itself with them, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the agent can infer 'use me when the user wants the whole day's schedule' rather than a single next prayer. No alternatives are named, no conditions or exclusions are given, and the relationship to get_next_prayer / get_prayer_status is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv1.1.3
    • Changedconfigure_prayer_preferences13 fields changed
      • addedInput schema / properties / clearFixedLocation
        Added value: +{
        +  "description": "Remove stored fixedCity, fixedCoordinates and timezone. Switches to auto_travel unless locationMode is supplied. Cannot combine with a new fixed location/timezone.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / exactWindowMinutes / description
        Previous value: -"Duration in minutes for exact_window mode"New value: +"Duration in minutes for exact_window mode. Omitted updates preserve the saved value; if unset, the service default is 20 minutes unless the operator overrides it."
      • changedInput schema / properties / fixedCity / description
        Previous value: -"Predefined city name for fixed location (e.g. Riyadh, London)"New value: +"Supported cities: makkah, madinah, riyadh, cairo, gaza, jerusalem, alquds, ramallah, hebron, nablus, rafah, khanyunis, dubai, abudhabi, kuwait, doha, amman, istanbul, london, paris, newyork, toronto, jakarta, singapore, karachi, kualalumpur, tehran, sydney, tromso. Aliases: gazacity, nyc, kuwaitcity. Case, spaces and punctuation are ignored."
      • changedInput schema / properties / locationMode / description
        Previous value: -"Location strategy: auto_travel or fixed"New value: +"Location strategy: fixed uses saved location; auto_travel requires the caller to supply current city or coordinates/timezone on each query and never uses IP geolocation."
      • changedInput schema / properties / minuteAdjustments / description
        Previous value: -"Custom per-prayer minute offsets (-60 to +60)"New value: +"Custom per-prayer minute offsets (-60 to +60). For fixed locations, combined settings must preserve timetable chronology for the current and next local day before saving; auto-travel offsets are validated when a query supplies its location."
      • changedInput schema / properties / userId / description
        Previous value: -"Unique user identifier"New value: +"Nonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved."
      • addedInput schema / properties / userId / maxLength
        Added value: +256
      • addedInput schema / properties / userId / pattern
        Added value: +"\\S"
      • addedOutput schema / properties / preferences / properties / fixedCityConfigured
        Added value: +{
        +  "type": "boolean"
        +}
      • removedOutput schema / properties / preferences / properties / fixedCoordinates
        Removed value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "latitude": {
        -      "type": "number"
        -    },
        -    "longitude": {
        -      "type": "number"
        -    }
        -  },
        -  "required": [
        -    "latitude",
        -    "longitude"
        -  ],
        -  "type": "object"
        -}
      • addedOutput schema / properties / preferences / properties / fixedCoordinatesConfigured
        Added value: +{
        +  "type": "boolean"
        +}
      • removedOutput schema / properties / preferences / properties / userId
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / properties / preferences / required
        Added value: +[
        +  "fixedCoordinatesConfigured",
        +  "fixedCityConfigured"
        +]
    • Changedget_next_prayer14 fields changed
      • addedInput schema / allOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "city",
        +        "latitude"
        +      ]
        +    }
        +  },
        +  {
        +    "not": {
        +      "required": [
        +        "city",
        +        "longitude"
        +      ]
        +    }
        +  }
        +]
      • addedInput schema / dependencies
        Added value: +{
        +  "latitude": [
        +    "longitude",
        +    "timezone"
        +  ],
        +  "longitude": [
        +    "latitude",
        +    "timezone"
        +  ]
        +}
      • addedInput schema / properties / city
        Added value: +{
        +  "description": "Supported cities: makkah, madinah, riyadh, cairo, gaza, jerusalem, alquds, ramallah, hebron, nablus, rafah, khanyunis, dubai, abudhabi, kuwait, doha, amman, istanbul, london, paris, newyork, toronto, jakarta, singapore, karachi, kualalumpur, tehran, sydney, tromso. Aliases: gazacity, nyc, kuwaitcity. Case, spaces and punctuation are ignored.",
        +  "type": "string"
        +}
      • changedInput schema / properties / timezone / description
        Previous value: -"Optional IANA timezone override"New value: +"IANA timezone; required in the same request when latitude/longitude are supplied. Must agree with the city or be compatible with the coordinate timezone lookup."
      • changedInput schema / properties / userId / description
        Previous value: -"Unique user or device ID"New value: +"Nonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved."
      • addedInput schema / properties / userId / maxLength
        Added value: +256
      • addedInput schema / properties / userId / minLength
        Added value: +1
      • addedInput schema / properties / userId / pattern
        Added value: +"\\S"
      • addedOutput schema / properties / authorityNotice / properties / calculationDetails
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "appliedMinuteAdjustments": {
        +      "additionalProperties": {
        +        "type": "number"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "calendarAlignmentAdjusted": {
        +      "type": "boolean"
        +    },
        +    "customMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "expectedTimezone": {
        +      "description": "Timezone from city registry or approximate coordinate lookup",
        +      "type": "string"
        +    },
        +    "fallbackLocationUsed": {
        +      "type": "boolean"
        +    },
        +    "highLatitudeRuleSource": {
        +      "enum": [
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "locationBasis": {
        +      "enum": [
        +        "explicit_coordinates",
        +        "explicit_city",
        +        "stored_fixed_coordinates",
        +        "stored_fixed_city",
        +        "host_coordinates",
        +        "host_city",
        +        "network_geolocation",
        +        "default_location"
        +      ],
        +      "type": "string"
        +    },
        +    "locationIsApproximate": {
        +      "type": "boolean"
        +    },
        +    "madhabSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "methodMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "methodSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "regionalMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "timezoneSource": {
        +      "description": "Source of the validated timezone or disclosed ocean/pole choice",
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "city_default",
        +        "host_header"
        +      ],
        +      "type": "string"
        +    },
        +    "timezoneValidation": {
        +      "description": "Validation basis; ocean locations require the matching nautical timezone or an adjacent coastal civil timezone; mathematical poles allow an explicit civil timezone with disclosure",
        +      "enum": [
        +        "coordinate_lookup",
        +        "nearby_boundary",
        +        "city_registry",
        +        "polar_choice",
        +        "ocean_choice"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / authorityNotice / properties / highLatitudeAdjustment
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "adjustedPrayers": {
        +      "items": {
        +        "enum": [
        +          "Fajr",
        +          "Sunrise",
        +          "Dhuhr",
        +          "Asr",
        +          "Maghrib",
        +          "Isha"
        +        ],
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "applied": {
        +      "type": "boolean"
        +    },
        +    "astronomicalLatitudeClamped": {
        +      "type": "boolean"
        +    },
        +    "effectiveLatitude": {
        +      "anyOf": [
        +        {
        +          "const": 48,
        +          "type": "number"
        +        },
        +        {
        +          "const": -48,
        +          "type": "number"
        +        }
        +      ],
        +      "description": "Substitute latitude only; never the user coordinate"
        +    },
        +    "explanation": {
        +      "type": "string"
        +    },
        +    "methodSpecificTwilightRule": {
        +      "const": "MoonsightingCommittee",
        +      "type": "string"
        +    },
        +    "rule": {
        +      "enum": [
        +        "MiddleOfTheNight",
        +        "SeventhOfTheNight",
        +        "TwilightAngle"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "applied",
        +    "rule",
        +    "astronomicalLatitudeClamped",
        +    "adjustedPrayers",
        +    "explanation"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / calculationDetails
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "appliedMinuteAdjustments": {
        +      "additionalProperties": {
        +        "type": "number"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "calendarAlignmentAdjusted": {
        +      "type": "boolean"
        +    },
        +    "customMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "expectedTimezone": {
        +      "description": "Timezone from city registry or approximate coordinate lookup",
        +      "type": "string"
        +    },
        +    "fallbackLocationUsed": {
        +      "type": "boolean"
        +    },
        +    "highLatitudeRuleSource": {
        +      "enum": [
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "locationBasis": {
        +      "enum": [
        +        "explicit_coordinates",
        +        "explicit_city",
        +        "stored_fixed_coordinates",
        +        "stored_fixed_city",
        +        "host_coordinates",
        +        "host_city",
        +        "network_geolocation",
        +        "default_location"
        +      ],
        +      "type": "string"
        +    },
        +    "locationIsApproximate": {
        +      "type": "boolean"
        +    },
        +    "madhabSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "methodMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "methodSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "regionalMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "timezoneSource": {
        +      "description": "Source of the validated timezone or disclosed ocean/pole choice",
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "city_default",
        +        "host_header"
        +      ],
        +      "type": "string"
        +    },
        +    "timezoneValidation": {
        +      "description": "Validation basis; ocean locations require the matching nautical timezone or an adjacent coastal civil timezone; mathematical poles allow an explicit civil timezone with disclosure",
        +      "enum": [
        +        "coordinate_lookup",
        +        "nearby_boundary",
        +        "city_registry",
        +        "polar_choice",
        +        "ocean_choice"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / highLatitudeAdjustment
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "adjustedPrayers": {
        +      "items": {
        +        "enum": [
        +          "Fajr",
        +          "Sunrise",
        +          "Dhuhr",
        +          "Asr",
        +          "Maghrib",
        +          "Isha"
        +        ],
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "applied": {
        +      "type": "boolean"
        +    },
        +    "astronomicalLatitudeClamped": {
        +      "type": "boolean"
        +    },
        +    "effectiveLatitude": {
        +      "anyOf": [
        +        {
        +          "const": 48,
        +          "type": "number"
        +        },
        +        {
        +          "const": -48,
        +          "type": "number"
        +        }
        +      ],
        +      "description": "Substitute latitude only; never the user coordinate"
        +    },
        +    "explanation": {
        +      "type": "string"
        +    },
        +    "methodSpecificTwilightRule": {
        +      "const": "MoonsightingCommittee",
        +      "type": "string"
        +    },
        +    "rule": {
        +      "enum": [
        +        "MiddleOfTheNight",
        +        "SeventhOfTheNight",
        +        "TwilightAngle"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "applied",
        +    "rule",
        +    "astronomicalLatitudeClamped",
        +    "adjustedPrayers",
        +    "explanation"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / properties / locationSource
        Removed value: -{
        -  "description": "Source of location resolution",
        -  "type": "string"
        -}
      • changedOutput schema / required
        Previous value: -[
        -  "currentLocalDate",
        -  "timezone",
        -  "nextPrayer",
        -  "nextPrayerAtUtc",
        -  "nextPrayerLocalTime",
        -  "remainingMinutes",
        -  "calculationMethod",
        -  "madhab",
        -  "locationSource"
        -]New value: +[
        +  "currentLocalDate",
        +  "timezone",
        +  "nextPrayer",
        +  "nextPrayerAtUtc",
        +  "nextPrayerLocalTime",
        +  "remainingMinutes",
        +  "calculationMethod",
        +  "madhab"
        +]
    • Changedget_prayer_preferences8 fields changed
      • changedInput schema / properties / userId / description
        Previous value: -"Unique user identifier"New value: +"Nonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved."
      • addedInput schema / properties / userId / maxLength
        Added value: +256
      • addedInput schema / properties / userId / pattern
        Added value: +"\\S"
      • addedOutput schema / properties / fixedCityConfigured
        Added value: +{
        +  "type": "boolean"
        +}
      • removedOutput schema / properties / fixedCoordinates
        Removed value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "latitude": {
        -      "type": "number"
        -    },
        -    "longitude": {
        -      "type": "number"
        -    }
        -  },
        -  "required": [
        -    "latitude",
        -    "longitude"
        -  ],
        -  "type": "object"
        -}
      • addedOutput schema / properties / fixedCoordinatesConfigured
        Added value: +{
        +  "type": "boolean"
        +}
      • removedOutput schema / properties / userId
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / required
        Added value: +[
        +  "fixedCoordinatesConfigured",
        +  "fixedCityConfigured"
        +]
    • Changedget_prayer_status17 fields changed
      • addedInput schema / allOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "city",
        +        "latitude"
        +      ]
        +    }
        +  },
        +  {
        +    "not": {
        +      "required": [
        +        "city",
        +        "longitude"
        +      ]
        +    }
        +  }
        +]
      • addedInput schema / dependencies
        Added value: +{
        +  "latitude": [
        +    "longitude",
        +    "timezone"
        +  ],
        +  "longitude": [
        +    "latitude",
        +    "timezone"
        +  ]
        +}
      • addedInput schema / properties / city
        Added value: +{
        +  "description": "Supported cities: makkah, madinah, riyadh, cairo, gaza, jerusalem, alquds, ramallah, hebron, nablus, rafah, khanyunis, dubai, abudhabi, kuwait, doha, amman, istanbul, london, paris, newyork, toronto, jakarta, singapore, karachi, kualalumpur, tehran, sydney, tromso. Aliases: gazacity, nyc, kuwaitcity. Case, spaces and punctuation are ignored.",
        +  "type": "string"
        +}
      • changedInput schema / properties / timezone / description
        Previous value: -"Optional IANA timezone override (e.g. Asia/Riyadh)"New value: +"IANA timezone; required in the same request when latitude/longitude are supplied. Must agree with the city or be compatible with the coordinate timezone lookup."
      • changedInput schema / properties / userId / description
        Previous value: -"Unique user or device ID for preference and deduplication tracking"New value: +"Nonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved."
      • addedInput schema / properties / userId / maxLength
        Added value: +256
      • addedInput schema / properties / userId / minLength
        Added value: +1
      • addedInput schema / properties / userId / pattern
        Added value: +"\\S"
      • changedOutput schema / properties / authorityNotice / description
        Previous value: -"Mandatory theological transparency notice"New value: +"Mandatory theological transparency notice; detailed provenance is at top level"
      • addedOutput schema / properties / calculationDetails
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "appliedMinuteAdjustments": {
        +      "additionalProperties": {
        +        "type": "number"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "calendarAlignmentAdjusted": {
        +      "type": "boolean"
        +    },
        +    "customMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "expectedTimezone": {
        +      "description": "Timezone from city registry or approximate coordinate lookup",
        +      "type": "string"
        +    },
        +    "fallbackLocationUsed": {
        +      "type": "boolean"
        +    },
        +    "highLatitudeRuleSource": {
        +      "enum": [
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "locationBasis": {
        +      "enum": [
        +        "explicit_coordinates",
        +        "explicit_city",
        +        "stored_fixed_coordinates",
        +        "stored_fixed_city",
        +        "host_coordinates",
        +        "host_city",
        +        "network_geolocation",
        +        "default_location"
        +      ],
        +      "type": "string"
        +    },
        +    "locationIsApproximate": {
        +      "type": "boolean"
        +    },
        +    "madhabSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "methodMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "methodSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "regionalMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "timezoneSource": {
        +      "description": "Source of the validated timezone or disclosed ocean/pole choice",
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "city_default",
        +        "host_header"
        +      ],
        +      "type": "string"
        +    },
        +    "timezoneValidation": {
        +      "description": "Validation basis; ocean locations require the matching nautical timezone or an adjacent coastal civil timezone; mathematical poles allow an explicit civil timezone with disclosure",
        +      "enum": [
        +        "coordinate_lookup",
        +        "nearby_boundary",
        +        "city_registry",
        +        "polar_choice",
        +        "ocean_choice"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • removedOutput schema / properties / dedupeKey
        Removed value: -{
        -  "description": "Deduplication cache key",
        -  "type": "string"
        -}
      • addedOutput schema / properties / highLatitudeAdjustment
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "adjustedPrayers": {
        +      "items": {
        +        "enum": [
        +          "Fajr",
        +          "Sunrise",
        +          "Dhuhr",
        +          "Asr",
        +          "Maghrib",
        +          "Isha"
        +        ],
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "applied": {
        +      "type": "boolean"
        +    },
        +    "astronomicalLatitudeClamped": {
        +      "type": "boolean"
        +    },
        +    "effectiveLatitude": {
        +      "anyOf": [
        +        {
        +          "const": 48,
        +          "type": "number"
        +        },
        +        {
        +          "const": -48,
        +          "type": "number"
        +        }
        +      ],
        +      "description": "Substitute latitude only; never the user coordinate"
        +    },
        +    "explanation": {
        +      "type": "string"
        +    },
        +    "methodSpecificTwilightRule": {
        +      "const": "MoonsightingCommittee",
        +      "type": "string"
        +    },
        +    "rule": {
        +      "enum": [
        +        "MiddleOfTheNight",
        +        "SeventhOfTheNight",
        +        "TwilightAngle"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "applied",
        +    "rule",
        +    "astronomicalLatitudeClamped",
        +    "adjustedPrayers",
        +    "explanation"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / properties / locationSource
        Removed value: -{
        -  "description": "Source of location resolution",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nextPrayerCalculation
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Adjustment disclosure for the actual schedule of the next event, including tomorrow",
        +  "properties": {
        +    "authorityNotice": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "authorityDescription": {
        +          "description": "Full descriptive name of the calculation authority",
        +          "type": "string"
        +        },
        +        "madhab": {
        +          "description": "The Asr jurisprudence school",
        +          "enum": [
        +            "Shafi",
        +            "Hanafi"
        +          ],
        +          "type": "string"
        +        },
        +        "method": {
        +          "description": "The calculation authority method",
        +          "enum": [
        +            "UmmAlQura",
        +            "MuslimWorldLeague",
        +            "Egyptian",
        +            "Karachi",
        +            "NorthAmerica",
        +            "Dubai",
        +            "Qatar",
        +            "Kuwait",
        +            "MoonsightingCommittee",
        +            "Singapore",
        +            "Turkey",
        +            "Tehran"
        +          ],
        +          "type": "string"
        +        },
        +        "requiredDisplayInstruction": {
        +          "description": "Mandatory theological notice for AI presentation",
        +          "type": "string"
        +        },
        +        "selectionReason": {
        +          "description": "Rationale for selecting this authority",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "method",
        +        "madhab",
        +        "authorityDescription",
        +        "selectionReason",
        +        "requiredDisplayInstruction"
        +      ],
        +      "type": "object"
        +    },
        +    "calculationDetails": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "appliedMinuteAdjustments": {
        +          "additionalProperties": {
        +            "type": "number"
        +          },
        +          "propertyNames": {
        +            "type": "string"
        +          },
        +          "type": "object"
        +        },
        +        "calendarAlignmentAdjusted": {
        +          "type": "boolean"
        +        },
        +        "customMinuteAdjustments": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "asr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "dhuhr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "fajr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "isha": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "maghrib": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "sunrise": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "expectedTimezone": {
        +          "description": "Timezone from city registry or approximate coordinate lookup",
        +          "type": "string"
        +        },
        +        "fallbackLocationUsed": {
        +          "type": "boolean"
        +        },
        +        "highLatitudeRuleSource": {
        +          "enum": [
        +            "stored_preference",
        +            "geographic_default"
        +          ],
        +          "type": "string"
        +        },
        +        "locationBasis": {
        +          "enum": [
        +            "explicit_coordinates",
        +            "explicit_city",
        +            "stored_fixed_coordinates",
        +            "stored_fixed_city",
        +            "host_coordinates",
        +            "host_city",
        +            "network_geolocation",
        +            "default_location"
        +          ],
        +          "type": "string"
        +        },
        +        "locationIsApproximate": {
        +          "type": "boolean"
        +        },
        +        "madhabSource": {
        +          "enum": [
        +            "explicit_override",
        +            "stored_preference",
        +            "geographic_default"
        +          ],
        +          "type": "string"
        +        },
        +        "methodMinuteAdjustments": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "asr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "dhuhr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "fajr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "isha": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "maghrib": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "sunrise": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "methodSource": {
        +          "enum": [
        +            "explicit_override",
        +            "stored_preference",
        +            "geographic_default"
        +          ],
        +          "type": "string"
        +        },
        +        "regionalMinuteAdjustments": {
        +          "additionalProperties": false,
        +          "properties": {
        +            "asr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "dhuhr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "fajr": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "isha": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "maghrib": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            },
        +            "sunrise": {
        +              "maximum": 60,
        +              "minimum": -60,
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "timezoneSource": {
        +          "description": "Source of the validated timezone or disclosed ocean/pole choice",
        +          "enum": [
        +            "explicit_override",
        +            "stored_preference",
        +            "city_default",
        +            "host_header"
        +          ],
        +          "type": "string"
        +        },
        +        "timezoneValidation": {
        +          "description": "Validation basis; ocean locations require the matching nautical timezone or an adjacent coastal civil timezone; mathematical poles allow an explicit civil timezone with disclosure",
        +          "enum": [
        +            "coordinate_lookup",
        +            "nearby_boundary",
        +            "city_registry",
        +            "polar_choice",
        +            "ocean_choice"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "highLatitudeAdjustment": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "adjustedPrayers": {
        +          "items": {
        +            "enum": [
        +              "Fajr",
        +              "Sunrise",
        +              "Dhuhr",
        +              "Asr",
        +              "Maghrib",
        +              "Isha"
        +            ],
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "applied": {
        +          "type": "boolean"
        +        },
        +        "astronomicalLatitudeClamped": {
        +          "type": "boolean"
        +        },
        +        "effectiveLatitude": {
        +          "anyOf": [
        +            {
        +              "const": 48,
        +              "type": "number"
        +            },
        +            {
        +              "const": -48,
        +              "type": "number"
        +            }
        +          ],
        +          "description": "Substitute latitude only; never the user coordinate"
        +        },
        +        "explanation": {
        +          "type": "string"
        +        },
        +        "methodSpecificTwilightRule": {
        +          "const": "MoonsightingCommittee",
        +          "type": "string"
        +        },
        +        "rule": {
        +          "enum": [
        +            "MiddleOfTheNight",
        +            "SeventhOfTheNight",
        +            "TwilightAngle"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "rule",
        +        "astronomicalLatitudeClamped",
        +        "adjustedPrayers",
        +        "explanation"
        +      ],
        +      "type": "object"
        +    },
        +    "localDate": {
        +      "type": "string"
        +    },
        +    "usesCurrentCalculation": {
        +      "description": "If true, this next event uses the top-level calculationDetails, highLatitudeAdjustment and authorityNotice; duplicate fields are omitted. Otherwise its own distinct metadata is included.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "localDate",
        +    "usesCurrentCalculation"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / prayerWindowExpiresAtUtc
        Added value: +{
        +  "description": "End of the active prayer period; same boundary as legacy expiresAtUtc",
        +  "type": "string"
        +}
      • addedOutput schema / properties / reminderWindowExpiresAtUtc
        Added value: +{
        +  "description": "Reminder eligibility end; exact_window is capped by the prayer period boundary. Fields appear when a reminder is emitted.",
        +  "type": "string"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "reminderDue",
        -  "localDate",
        -  "nextPrayer",
        -  "nextPrayerAtUtc",
        -  "timezone",
        -  "calculationMethod",
        -  "madhab",
        -  "locationSource"
        -]New value: +[
        +  "reminderDue",
        +  "localDate",
        +  "nextPrayer",
        +  "nextPrayerAtUtc",
        +  "timezone",
        +  "calculationMethod",
        +  "madhab",
        +  "authorityNotice"
        +]
    • Changedget_today_prayer_times14 fields changed
      • addedInput schema / allOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "city",
        +        "latitude"
        +      ]
        +    }
        +  },
        +  {
        +    "not": {
        +      "required": [
        +        "city",
        +        "longitude"
        +      ]
        +    }
        +  }
        +]
      • addedInput schema / dependencies
        Added value: +{
        +  "latitude": [
        +    "longitude",
        +    "timezone"
        +  ],
        +  "longitude": [
        +    "latitude",
        +    "timezone"
        +  ]
        +}
      • addedInput schema / properties / city
        Added value: +{
        +  "description": "Supported cities: makkah, madinah, riyadh, cairo, gaza, jerusalem, alquds, ramallah, hebron, nablus, rafah, khanyunis, dubai, abudhabi, kuwait, doha, amman, istanbul, london, paris, newyork, toronto, jakarta, singapore, karachi, kualalumpur, tehran, sydney, tromso. Aliases: gazacity, nyc, kuwaitcity. Case, spaces and punctuation are ignored.",
        +  "type": "string"
        +}
      • changedInput schema / properties / timezone / description
        Previous value: -"Optional IANA timezone override"New value: +"IANA timezone; required in the same request when latitude/longitude are supplied. Must agree with the city or be compatible with the coordinate timezone lookup."
      • changedInput schema / properties / userId / description
        Previous value: -"Unique user or device ID"New value: +"Nonblank user identifier; at most 256 UTF-8 bytes and 256 characters. Whitespace in nonblank identifiers is preserved."
      • addedInput schema / properties / userId / maxLength
        Added value: +256
      • addedInput schema / properties / userId / minLength
        Added value: +1
      • addedInput schema / properties / userId / pattern
        Added value: +"\\S"
      • addedOutput schema / properties / authorityNotice / properties / calculationDetails
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "appliedMinuteAdjustments": {
        +      "additionalProperties": {
        +        "type": "number"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "calendarAlignmentAdjusted": {
        +      "type": "boolean"
        +    },
        +    "customMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "expectedTimezone": {
        +      "description": "Timezone from city registry or approximate coordinate lookup",
        +      "type": "string"
        +    },
        +    "fallbackLocationUsed": {
        +      "type": "boolean"
        +    },
        +    "highLatitudeRuleSource": {
        +      "enum": [
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "locationBasis": {
        +      "enum": [
        +        "explicit_coordinates",
        +        "explicit_city",
        +        "stored_fixed_coordinates",
        +        "stored_fixed_city",
        +        "host_coordinates",
        +        "host_city",
        +        "network_geolocation",
        +        "default_location"
        +      ],
        +      "type": "string"
        +    },
        +    "locationIsApproximate": {
        +      "type": "boolean"
        +    },
        +    "madhabSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "methodMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "methodSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "regionalMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "timezoneSource": {
        +      "description": "Source of the validated timezone or disclosed ocean/pole choice",
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "city_default",
        +        "host_header"
        +      ],
        +      "type": "string"
        +    },
        +    "timezoneValidation": {
        +      "description": "Validation basis; ocean locations require the matching nautical timezone or an adjacent coastal civil timezone; mathematical poles allow an explicit civil timezone with disclosure",
        +      "enum": [
        +        "coordinate_lookup",
        +        "nearby_boundary",
        +        "city_registry",
        +        "polar_choice",
        +        "ocean_choice"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / authorityNotice / properties / highLatitudeAdjustment
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "adjustedPrayers": {
        +      "items": {
        +        "enum": [
        +          "Fajr",
        +          "Sunrise",
        +          "Dhuhr",
        +          "Asr",
        +          "Maghrib",
        +          "Isha"
        +        ],
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "applied": {
        +      "type": "boolean"
        +    },
        +    "astronomicalLatitudeClamped": {
        +      "type": "boolean"
        +    },
        +    "effectiveLatitude": {
        +      "anyOf": [
        +        {
        +          "const": 48,
        +          "type": "number"
        +        },
        +        {
        +          "const": -48,
        +          "type": "number"
        +        }
        +      ],
        +      "description": "Substitute latitude only; never the user coordinate"
        +    },
        +    "explanation": {
        +      "type": "string"
        +    },
        +    "methodSpecificTwilightRule": {
        +      "const": "MoonsightingCommittee",
        +      "type": "string"
        +    },
        +    "rule": {
        +      "enum": [
        +        "MiddleOfTheNight",
        +        "SeventhOfTheNight",
        +        "TwilightAngle"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "applied",
        +    "rule",
        +    "astronomicalLatitudeClamped",
        +    "adjustedPrayers",
        +    "explanation"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / calculationDetails
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "appliedMinuteAdjustments": {
        +      "additionalProperties": {
        +        "type": "number"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "calendarAlignmentAdjusted": {
        +      "type": "boolean"
        +    },
        +    "customMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "expectedTimezone": {
        +      "description": "Timezone from city registry or approximate coordinate lookup",
        +      "type": "string"
        +    },
        +    "fallbackLocationUsed": {
        +      "type": "boolean"
        +    },
        +    "highLatitudeRuleSource": {
        +      "enum": [
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "locationBasis": {
        +      "enum": [
        +        "explicit_coordinates",
        +        "explicit_city",
        +        "stored_fixed_coordinates",
        +        "stored_fixed_city",
        +        "host_coordinates",
        +        "host_city",
        +        "network_geolocation",
        +        "default_location"
        +      ],
        +      "type": "string"
        +    },
        +    "locationIsApproximate": {
        +      "type": "boolean"
        +    },
        +    "madhabSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "methodMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "methodSource": {
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "geographic_default"
        +      ],
        +      "type": "string"
        +    },
        +    "regionalMinuteAdjustments": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "asr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "dhuhr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "fajr": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "isha": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "maghrib": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        },
        +        "sunrise": {
        +          "maximum": 60,
        +          "minimum": -60,
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "timezoneSource": {
        +      "description": "Source of the validated timezone or disclosed ocean/pole choice",
        +      "enum": [
        +        "explicit_override",
        +        "stored_preference",
        +        "city_default",
        +        "host_header"
        +      ],
        +      "type": "string"
        +    },
        +    "timezoneValidation": {
        +      "description": "Validation basis; ocean locations require the matching nautical timezone or an adjacent coastal civil timezone; mathematical poles allow an explicit civil timezone with disclosure",
        +      "enum": [
        +        "coordinate_lookup",
        +        "nearby_boundary",
        +        "city_registry",
        +        "polar_choice",
        +        "ocean_choice"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • removedOutput schema / properties / coordinates
        Removed value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "latitude": {
        -      "description": "Latitude in degrees",
        -      "type": "number"
        -    },
        -    "longitude": {
        -      "description": "Longitude in degrees",
        -      "type": "number"
        -    }
        -  },
        -  "required": [
        -    "latitude",
        -    "longitude"
        -  ],
        -  "type": "object"
        -}
      • addedOutput schema / properties / highLatitudeAdjustment
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "adjustedPrayers": {
        +      "items": {
        +        "enum": [
        +          "Fajr",
        +          "Sunrise",
        +          "Dhuhr",
        +          "Asr",
        +          "Maghrib",
        +          "Isha"
        +        ],
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "applied": {
        +      "type": "boolean"
        +    },
        +    "astronomicalLatitudeClamped": {
        +      "type": "boolean"
        +    },
        +    "effectiveLatitude": {
        +      "anyOf": [
        +        {
        +          "const": 48,
        +          "type": "number"
        +        },
        +        {
        +          "const": -48,
        +          "type": "number"
        +        }
        +      ],
        +      "description": "Substitute latitude only; never the user coordinate"
        +    },
        +    "explanation": {
        +      "type": "string"
        +    },
        +    "methodSpecificTwilightRule": {
        +      "const": "MoonsightingCommittee",
        +      "type": "string"
        +    },
        +    "rule": {
        +      "enum": [
        +        "MiddleOfTheNight",
        +        "SeventhOfTheNight",
        +        "TwilightAngle"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "applied",
        +    "rule",
        +    "astronomicalLatitudeClamped",
        +    "adjustedPrayers",
        +    "explanation"
        +  ],
        +  "type": "object"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "localDate",
        -  "timezone",
        -  "coordinates",
        -  "calculationMethod",
        -  "madhab",
        -  "timesUtc",
        -  "timesLocal"
        -]New value: +[
        +  "localDate",
        +  "timezone",
        +  "calculationMethod",
        +  "madhab",
        +  "timesUtc",
        +  "timesLocal"
        +]
  2. 5 tool updatesv1.0.1
    • First observedconfigure_prayer_preferences
    • First observedget_next_prayer
    • First observedget_prayer_preferences
    • First observedget_prayer_status
    • First observedget_today_prayer_times

TDQS

A4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct question: current due status, today's timetable, next prayer countdown, read preferences, and update preferences. The overlapping domain (prayer times) is cleanly partitioned by purpose, so an agent can select the right tool without ambiguity.

Naming Consistency5/5

All names follow a consistent snake_case verb_noun pattern: get_* for read operations and configure_* for the write operation. The convention is predictable and readable throughout.

Tool Count5/5

Five tools is well-scoped for a prayer reminder server: three focused query tools and two preference-management tools. Each tool earns its place, and there is no obvious redundancy.

Completeness4/5

The surface covers the core lifecycle: current status, daily timetable, next prayer, and preference read/update. Minor gaps exist, such as querying prayer times for an arbitrary date or month, but agents can work around them for typical reminder workflows.

Maintenance

ActivityNo data
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers