neshan-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. neshan_mcp-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +42 -0
  2. neshan_mcp-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  3. neshan_mcp-0.1.0/.github/banner.png +0 -0
  4. neshan_mcp-0.1.0/.github/dependabot.yml +10 -0
  5. neshan_mcp-0.1.0/.github/workflows/ci.yml +22 -0
  6. neshan_mcp-0.1.0/.github/workflows/publish.yml +51 -0
  7. neshan_mcp-0.1.0/.gitignore +6 -0
  8. neshan_mcp-0.1.0/LICENSE +21 -0
  9. neshan_mcp-0.1.0/PKG-INFO +436 -0
  10. neshan_mcp-0.1.0/README.md +408 -0
  11. neshan_mcp-0.1.0/pyproject.toml +56 -0
  12. neshan_mcp-0.1.0/server.json +32 -0
  13. neshan_mcp-0.1.0/src/neshan_mcp/__init__.py +5 -0
  14. neshan_mcp-0.1.0/src/neshan_mcp/codec.py +173 -0
  15. neshan_mcp-0.1.0/src/neshan_mcp/http.py +337 -0
  16. neshan_mcp-0.1.0/src/neshan_mcp/maps.py +566 -0
  17. neshan_mcp-0.1.0/src/neshan_mcp/registry.py +16 -0
  18. neshan_mcp-0.1.0/src/neshan_mcp/routes.py +368 -0
  19. neshan_mcp-0.1.0/src/neshan_mcp/server.py +91 -0
  20. neshan_mcp-0.1.0/tests/conftest.py +90 -0
  21. neshan_mcp-0.1.0/tests/fixtures/raw/air_point.txt +1 -0
  22. neshan_mcp-0.1.0/tests/fixtures/raw/air_quality.txt +1 -0
  23. neshan_mcp-0.1.0/tests/fixtures/raw/nearby.txt +1 -0
  24. neshan_mcp-0.1.0/tests/fixtures/raw/photos.txt +1 -0
  25. neshan_mcp-0.1.0/tests/fixtures/raw/photos_menu.txt +1 -0
  26. neshan_mcp-0.1.0/tests/fixtures/raw/place.txt +1 -0
  27. neshan_mcp-0.1.0/tests/fixtures/raw/place_milad.txt +1 -0
  28. neshan_mcp-0.1.0/tests/fixtures/raw/place_photos.txt +1 -0
  29. neshan_mcp-0.1.0/tests/fixtures/raw/reverse.txt +1 -0
  30. neshan_mcp-0.1.0/tests/fixtures/raw/reviews.txt +1 -0
  31. neshan_mcp-0.1.0/tests/fixtures/raw/reviews_featured.txt +1 -0
  32. neshan_mcp-0.1.0/tests/fixtures/raw/route_arrive.json +1 -0
  33. neshan_mcp-0.1.0/tests/fixtures/raw/route_car.json +1 -0
  34. neshan_mcp-0.1.0/tests/fixtures/raw/route_depart.json +1 -0
  35. neshan_mcp-0.1.0/tests/fixtures/raw/route_eta.json +1 -0
  36. neshan_mcp-0.1.0/tests/fixtures/raw/route_stops.json +1 -0
  37. neshan_mcp-0.1.0/tests/fixtures/raw/route_toll.json +1 -0
  38. neshan_mcp-0.1.0/tests/fixtures/raw/route_walk.json +1 -0
  39. neshan_mcp-0.1.0/tests/fixtures/raw/route_zone_in.json +1 -0
  40. neshan_mcp-0.1.0/tests/fixtures/raw/search.txt +1 -0
  41. neshan_mcp-0.1.0/tests/fixtures/raw/search_filtered.txt +1 -0
  42. neshan_mcp-0.1.0/tests/fixtures/raw/search_street.txt +1 -0
  43. neshan_mcp-0.1.0/tests/fixtures/raw/transit.json +1 -0
  44. neshan_mcp-0.1.0/tests/test_codec.py +152 -0
  45. neshan_mcp-0.1.0/tests/test_live_maps.py +157 -0
  46. neshan_mcp-0.1.0/tests/test_maps.py +421 -0
  47. neshan_mcp-0.1.0/uv.lock +1344 -0
@@ -0,0 +1,42 @@
1
+ name: Bug report
2
+ description: A tool failed or returned wrong data
3
+ labels: [bug]
4
+ body:
5
+ - type: input
6
+ id: tool
7
+ attributes:
8
+ label: Tool
9
+ description: Which tool, e.g. ns_search
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: input
14
+ attributes:
15
+ label: Arguments and result
16
+ description: The arguments the agent sent and the error or wrong output. Remove anything personal.
17
+ render: json
18
+ validations:
19
+ required: true
20
+ - type: textarea
21
+ id: expected
22
+ attributes:
23
+ label: What you expected
24
+ description: e.g. what neshan.org/maps shows for the same query
25
+ - type: input
26
+ id: client
27
+ attributes:
28
+ label: MCP client and OS
29
+ placeholder: Claude Desktop 1.x on Windows 11
30
+ - type: dropdown
31
+ id: network
32
+ attributes:
33
+ label: Network
34
+ options:
35
+ - Direct connection
36
+ - VPN or proxy
37
+ - NESHAN_MCP_PROXY set
38
+ - type: input
39
+ id: version
40
+ attributes:
41
+ label: neshan-mcp version
42
+ placeholder: "0.1.0"
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Question or idea
4
+ url: https://github.com/sepehr071/neshan-mcp/discussions
5
+ about: Ask how to use it or suggest a new tool
Binary file
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: monthly
7
+ - package-ecosystem: uv
8
+ directory: /
9
+ schedule:
10
+ interval: monthly
@@ -0,0 +1,22 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python: ["3.10", "3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v7
16
+ - uses: astral-sh/setup-uv@v10.2.0
17
+ with:
18
+ python-version: ${{ matrix.python }}
19
+ - run: uv sync --locked
20
+ - run: uv run ruff check .
21
+ - run: uv run ruff format --check .
22
+ - run: uv run pytest -q
@@ -0,0 +1,51 @@
1
+ name: Publish
2
+
3
+ # Tag a release (git tag v0.1.0 && git push --tags) after bumping the version in
4
+ # pyproject.toml and server.json.
5
+ on:
6
+ push:
7
+ tags: ["v*"]
8
+
9
+ jobs:
10
+ pypi:
11
+ runs-on: ubuntu-latest
12
+ environment: pypi
13
+ permissions:
14
+ id-token: write # PyPI trusted publishing
15
+ contents: write # GitHub Release
16
+ steps:
17
+ - uses: actions/checkout@v7
18
+ - uses: astral-sh/setup-uv@v10.2.0
19
+ - name: Check versions match the tag
20
+ run: |
21
+ TAG=${GITHUB_REF_NAME#v}
22
+ grep -q "^version = \"$TAG\"" pyproject.toml
23
+ test "$(jq -r .version server.json)" = "$TAG"
24
+ test "$(jq -r '.packages[0].version' server.json)" = "$TAG"
25
+ - run: uv sync --locked && uv run pytest -q
26
+ - run: uv build
27
+ - uses: pypa/gh-action-pypi-publish@release/v1
28
+ - run: gh release create "$GITHUB_REF_NAME" dist/* --generate-notes --title "$GITHUB_REF_NAME"
29
+ env:
30
+ GH_TOKEN: ${{ github.token }}
31
+
32
+ mcp-registry:
33
+ needs: pypi
34
+ runs-on: ubuntu-latest
35
+ permissions:
36
+ id-token: write # MCP Registry login via GitHub OIDC
37
+ contents: read
38
+ steps:
39
+ - uses: actions/checkout@v7
40
+ - name: Wait for PyPI to serve the new version
41
+ run: |
42
+ for i in $(seq 1 30); do
43
+ curl -sf "https://pypi.org/pypi/neshan-mcp/${GITHUB_REF_NAME#v}/json" >/dev/null && exit 0
44
+ sleep 10
45
+ done
46
+ exit 1
47
+ - name: Install mcp-publisher
48
+ run: |
49
+ curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.8.1/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
50
+ - run: ./mcp-publisher login github-oidc
51
+ - run: ./mcp-publisher publish
@@ -0,0 +1,6 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ dist/
5
+ .pytest_cache/
6
+ .ruff_cache/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sepehr Radmard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,436 @@
1
+ Metadata-Version: 2.5
2
+ Name: neshan-mcp
3
+ Version: 0.1.0
4
+ Summary: Unofficial read-only MCP server for Neshan (نشان), the Iranian map: place search, details, reviews, photos and nearby places, reverse geocoding, air quality, car, motorcycle, bicycle, walking and transit directions, travel times and Tehran traffic-zone checks.
5
+ Project-URL: Homepage, https://github.com/sepehr071/neshan-mcp
6
+ Project-URL: Issues, https://github.com/sepehr071/neshan-mcp/issues
7
+ Project-URL: Website, https://mcpfarsi.ir/
8
+ Author-email: Sepehr Radmard <sepehrr80@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: air-quality,directions,geocoding,iran-map,mcp,model-context-protocol,neshan,neshan-map,persian,places,public-transit,reverse-geocoding,routing,tehran,traffic
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Scientific/Engineering :: GIS
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: curl-cffi>=0.16.3
24
+ Requires-Dist: httpx-curl-cffi>=0.1.5
25
+ Requires-Dist: httpx>=0.27
26
+ Requires-Dist: mcp<3,>=2.2
27
+ Description-Content-Type: text/markdown
28
+
29
+ <!-- mcp-name: io.github.sepehr071/neshan-mcp -->
30
+
31
+ <div align="center">
32
+
33
+ <img src="https://raw.githubusercontent.com/sepehr071/neshan-mcp/main/.github/banner.png" alt="neshan-mcp: unofficial Neshan map MCP server for Claude, Cursor and Copilot, showing a live route from Azadi Tower to the Tehran Grand Bazaar" width="100%">
34
+
35
+ # neshan-mcp: Neshan map of Iran MCP server for AI agents
36
+
37
+ **Let your AI agent search places, get directions and check Tehran's traffic zones on Neshan (نشان).**<br>
38
+ `neshan-mcp` is an unofficial, read-only MCP server for [Neshan](https://neshan.org/maps), the Iranian map and navigation app.<br>
39
+ Its 11 tools cover place search, place details, reviews, photos and menus, nearby places, reverse geocoding, city air quality,
40
+ car, motorcycle, bicycle, walking and bus/metro directions, travel times to several places and Tehran traffic-zone checks.
41
+ No API key or account is needed.
42
+
43
+ [![PyPI](https://img.shields.io/pypi/v/neshan-mcp?color=2563eb)](https://pypi.org/project/neshan-mcp/)
44
+ [![Python](https://img.shields.io/pypi/pyversions/neshan-mcp)](https://pypi.org/project/neshan-mcp/)
45
+ [![CI](https://github.com/sepehr071/neshan-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/sepehr071/neshan-mcp/actions/workflows/ci.yml)
46
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.sepehr071%2Fneshan--mcp-7c3aed)](https://registry.modelcontextprotocol.io/?q=neshan-mcp)
47
+ [![License: MIT](https://img.shields.io/badge/license-MIT-16a34a)](https://github.com/sepehr071/neshan-mcp/blob/main/LICENSE)
48
+
49
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_neshan--mcp-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=neshan&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22neshan-mcp%22%5D%7D)
50
+
51
+ [For AI agents](#for-ai-agents) · [Quick start](#quick-start) · [What it can do](#what-it-can-do) · [Tools](#tools) · [FAQ](#faq) · [فارسی](#فارسی)
52
+
53
+ </div>
54
+
55
+ ---
56
+
57
+ ## For AI agents
58
+
59
+ - **What:** unofficial MCP server (model context protocol) for neshan.org/maps, the Neshan map of Iran. Queries can be Persian or English; answers keep Neshan's Persian names, addresses and steps.
60
+ - **Install:** `uvx neshan-mcp` or `claude mcp add neshan -- uvx neshan-mcp`. Transport: stdio. Needs [uv](https://docs.astral.sh/uv/getting-started/installation/) (Python 3.10+).
61
+ - **Auth:** none, no API key or account. Optional `NESHAN_MCP_PROXY` (HTTP proxy URL, or a comma-separated list); system proxy settings are ignored.
62
+ - **Access:** read-only. It cannot log in, save places or post reviews, so no confirmation is needed before calling any tool.
63
+ - **Tools:** 11, all prefixed `ns_`. Typical sequences: `ns_search` -> `ns_place` / `ns_reviews` / `ns_photos` / `ns_nearby`;
64
+ `ns_search` -> `ns_travel_times` -> `ns_route`; `ns_zone_check` before driving into central Tehran.
65
+ - **Use when:** the user asks where something is in Iran, what is near a place, whether a business is open, what people say about it or what its menu looks like, what address a coordinate is, how polluted a city's air is, whether an address is inside Tehran's traffic zone, or how to get from A to B and how long it takes, now or at a given time.
66
+ - **Do not use when:** the user wants places outside Iran, taxi or delivery prices, or to save places in a Neshan account.
67
+ - **Output:** compact JSON. Coordinates are `lat,lng` (latitude first). Distances in metres or km, times in minutes, fares in Toman, review dates in the Persian calendar, departure times in Tehran time.
68
+ - **Network:** every tool works from an Iranian connection. Through a foreign connection all tools worked in testing except `ns_nearby`, which Neshan answers with HTTP 403; set `NESHAN_MCP_PROXY` to an Iranian proxy for it.
69
+ - **Machine-readable:** [`server.json`](https://github.com/sepehr071/neshan-mcp/blob/main/server.json) and the
70
+ [iran-mcp catalog](https://github.com/sepehr071/iran-mcp).
71
+
72
+ ## Why
73
+
74
+ Neshan knows Iran in detail: businesses with opening hours and reviews, live traffic, Tehran's traffic and odd-even
75
+ plans, bus, BRT and metro lines. Its developer API needs a paid key, and its web map is built for clicking.
76
+ `neshan-mcp` gives an agent the same public data the web map shows any visitor, in a few small calls:
77
+
78
+ > **You:** How long does it take to drive from Azadi Tower to the Tehran Grand Bazaar, and will I enter the traffic zone?
79
+ >
80
+ > **Agent:** *calls* `ns_search("برج آزادی")`, `ns_search("بازار بزرگ تهران")`, then
81
+ > `ns_route(origin="35.699739,51.338097", destination="35.671897,51.422428", steps=false)`
82
+ >
83
+ > Neshan suggests 48 minutes (13 km) via Jomhouri-e Eslami and Mostafa Khomeini streets; the route via Saeedi
84
+ > expressway and Shoush is 16 km and takes 45 minutes. All three routes enter the traffic-plan zone (طرح ترافیک)
85
+ > and the odd-even zone, which run from 06:30 to 18:00. The bazaar itself is inside both zones.
86
+
87
+ <sub>Real answer from a live call on 2026-10-31 at 17:21 Tehran time; times change with traffic.</sub>
88
+
89
+ Every reply is compact JSON with only the fields that matter, so it does not flood the agent's context.
90
+
91
+ ## What it can do
92
+
93
+ - **Find places** by name or category near a city or a point: cafes, pharmacies, petrol stations, streets, squares. Filter by open now and rating, the way the site does
94
+ - **Read a place**: address, coordinates, phones, website, rating and votes, open now, hours for each weekday, newest photos
95
+ - **Read reviews**, newest first or the ones Neshan features, and **browse photos**, including the menu album
96
+ - **See what is nearby**: restaurants, cafes, parks, toilets, banks, ATMs, parking and bus stops around a place
97
+ - **Reverse geocode** a coordinate into a street address and province
98
+ - **Check air quality**: today's AQI of a city, its pollutants and every monitoring station, or the index at a point
99
+ - **Get directions** by car, motorcycle, bicycle or on foot: alternatives, live travel time, Persian turn-by-turn steps, up to 3 stops
100
+ - **Plan by time**: leave at a given time or arrive by one (car, Tehran, Karaj and Mashhad), with Neshan's traffic forecast
101
+ - **Rank by travel time**: one origin to up to 10 places, fastest first
102
+ - **Check Tehran's zones**: is a point inside the traffic-plan zone or the odd-even zone, and does a route enter them; avoid them or toll roads
103
+ - **Take public transport**: bus, BRT and metro options with lines, stops, walking and fares in Toman
104
+ - **Read-only by design**: no login, no saving, no posting
105
+
106
+ Example prompts:
107
+
108
+ - "Find 24-hour pharmacies near Milad Tower that are open now and rated 4 or more."
109
+ - "Is Lamiz Coffee in Gisha open now? What's its phone number, and what do people say about it?"
110
+ - "Show me the menu photos of Milad Tower."
111
+ - "Which of these three branches is closest by car from Azadi Square?"
112
+ - "I need to be at Milad Tower at 9 tomorrow. When should I leave from Azadi Square?"
113
+ - "Is Ferdowsi Square inside Tehran's traffic zone?"
114
+ - "How polluted is the air in Isfahan today?"
115
+ - <span dir="rtl">نزدیک‌ترین داروخانه شبانه‌روزی به برج میلاد کجاست؟</span>
116
+ - <span dir="rtl">از میدان آزادی تا بازار تهران با ماشین چقدر راه است؟ وارد طرح ترافیک می‌شوم؟</span>
117
+ - <span dir="rtl">با مترو و اتوبوس از میدان آزادی به برج میلاد چطور بروم و هزینه‌اش چقدر است؟</span>
118
+
119
+ ## Quick start
120
+
121
+ You need [uv](https://docs.astral.sh/uv/getting-started/installation/). No API key or account.
122
+
123
+ <details open>
124
+ <summary><b>Claude Code</b></summary>
125
+
126
+ ```bash
127
+ claude mcp add neshan -- uvx neshan-mcp
128
+ ```
129
+ </details>
130
+
131
+ <details>
132
+ <summary><b>Claude Desktop</b></summary>
133
+
134
+ Settings → Developer → Edit Config, then add:
135
+
136
+ ```json
137
+ {
138
+ "mcpServers": {
139
+ "neshan": { "command": "uvx", "args": ["neshan-mcp"] }
140
+ }
141
+ }
142
+ ```
143
+ </details>
144
+
145
+ <details>
146
+ <summary><b>Cursor</b></summary>
147
+
148
+ Add the Claude Desktop block above to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project).
149
+ </details>
150
+
151
+ <details>
152
+ <summary><b>VS Code (Copilot agent mode)</b></summary>
153
+
154
+ Click **Install in VS Code** above, or add to `.vscode/mcp.json`:
155
+
156
+ ```json
157
+ {
158
+ "servers": {
159
+ "neshan": { "type": "stdio", "command": "uvx", "args": ["neshan-mcp"] }
160
+ }
161
+ }
162
+ ```
163
+ </details>
164
+
165
+ <details>
166
+ <summary><b>Codex CLI</b></summary>
167
+
168
+ ```bash
169
+ codex mcp add neshan -- uvx neshan-mcp
170
+ ```
171
+
172
+ Or in `~/.codex/config.toml`:
173
+
174
+ ```toml
175
+ [mcp_servers.neshan]
176
+ command = "uvx"
177
+ args = ["neshan-mcp"]
178
+ ```
179
+ </details>
180
+
181
+ <details>
182
+ <summary><b>Gemini CLI</b></summary>
183
+
184
+ Add to `~/.gemini/settings.json`:
185
+
186
+ ```json
187
+ {
188
+ "mcpServers": {
189
+ "neshan": { "command": "uvx", "args": ["neshan-mcp"] }
190
+ }
191
+ }
192
+ ```
193
+ </details>
194
+
195
+ <details>
196
+ <summary><b>Windsurf</b></summary>
197
+
198
+ Add the Claude Desktop block to `~/.codeium/windsurf/mcp_config.json`.
199
+ </details>
200
+
201
+ <details>
202
+ <summary><b>Anything else</b></summary>
203
+
204
+ It is a standard stdio MCP server: run `uvx neshan-mcp`, or `pip install neshan-mcp` and run `neshan-mcp`.
205
+ </details>
206
+
207
+ ## Tools
208
+
209
+ Points are `lat,lng`, e.g. `35.6997,51.3380`. Place ids come from `ns_search`.
210
+
211
+ | Tool | What it does |
212
+ |---|---|
213
+ | `ns_search` | Find places, businesses, streets and squares on the Neshan map by name or category near a city or point |
214
+ | `ns_place` | Get one place's details on Neshan: address, coordinates, phones, website, rating, opening hours and photos |
215
+ | `ns_reviews` | List visitors' reviews of a place on Neshan: star rating, Persian date, comment, likes and owner reply |
216
+ | `ns_photos` | List a place's photos on Neshan as image URLs, 10 per page, with date and uploader, including menu photos |
217
+ | `ns_nearby` | List what is around a place on Neshan by category: restaurants, cafes, parks, toilets, banks, ATMs, parking |
218
+ | `ns_reverse_geocode` | Turn a latitude/longitude into Neshan's street address and province (reverse geocoding) |
219
+ | `ns_air_quality` | Get today's air quality index (AQI) of an Iranian city from Neshan, with pollutants and the readings of each station |
220
+ | `ns_route` | Get car, motorcycle, bicycle or walking directions on Neshan: distance, travel time and turn-by-turn steps |
221
+ | `ns_travel_times` | Get the travel time from one point to several places on Neshan, fastest first |
222
+ | `ns_zone_check` | Check whether a point is inside Tehran's traffic-plan zone or odd-even (air-pollution) zone, with plan hours |
223
+ | `ns_transit_route` | Get bus, BRT and metro options between two points on Neshan, with lines, stops, walking and fares |
224
+
225
+ All 11 tools are annotated `readOnlyHint: true`.
226
+
227
+ ## How it works
228
+
229
+ ```text
230
+ AI agent (Claude, Cursor, Copilot, ...)
231
+ │
232
+ │ MCP over stdio
233
+ ▼
234
+ neshan-mcp (runs on your machine)
235
+ │
236
+ │ HTTPS
237
+ └──────▶ neshan.org/maps/pwa-api search, places, reviews, photos, routes, transit, air quality
238
+ ```
239
+
240
+ `neshan-mcp` runs locally and calls the same endpoints the neshan.org/maps web app uses, with no hosted server in
241
+ between and no API key. Requests go out through a Chrome-impersonating client and look like the web app's own.
242
+ It sends at most 3 requests at a time with a little jitter, caches answers (places and addresses for 5 minutes,
243
+ live routes for 1 minute, transit, zones and air quality for 10 minutes), retries a failed call up to twice, and
244
+ only talks to `neshan.org`.
245
+
246
+ Neshan's web app encodes most of its answers: they arrive as shuffled base64 text, and transit answers are also
247
+ XOR-encoded. The server decodes them the same way the web app's own script does. If Neshan changes the scheme, the
248
+ server reads the new values from the site's current JavaScript once, the way a browser loads it, and retries. An
249
+ answer it still cannot read is reported as an error, never as made-up data.
250
+
251
+ ## Good to know
252
+
253
+ - **Coordinates are `lat,lng`.** Latitude first. A swapped pair is rejected with a hint.
254
+ - **`near` takes a city or a point.** 23 big cities by name in English or Persian (Tehran, Mashhad, Isfahan, Shiraz,
255
+ Tabriz, Karaj, Qom, Ahvaz, ...). For a smaller town, put its name in the query.
256
+ - **Search returns at most 30 places**, with no paging. Sponsored results (marked آگهی on the site) are left out.
257
+ `open_now` and `min_rating` use Neshan's own filters (open now; 3.5+, 4+, 4.5+).
258
+ - **Travel times are Neshan's estimates** for leaving now, or for `depart_at`. Departure and arrival times are
259
+ Tehran time (`YYYY-MM-DD HH:MM`, Gregorian); Neshan offers them for cars in Tehran, Karaj and Mashhad.
260
+ - **Toll roads are flagged** (`toll_road`), but not priced: Neshan's web app never shows a toll amount.
261
+ - **Transit has no travel time.** Neshan's web map gives fares, lines and stops, but no duration, for bus and metro.
262
+ - **`ns_nearby` needs an Iranian connection.** Neshan answers it with HTTP 403 from abroad; set `NESHAN_MCP_PROXY`
263
+ to an Iranian proxy, or use `ns_search` with the place's `lat,lng` as `near`.
264
+ - **Air-quality cities** use their English name (`Tehran`, `bandar abbas`) or the Persian name for the 23 cities above.
265
+ A city without monitoring stations returns "no data".
266
+ - **Persian output.** Names, addresses, hours (Persian digits), steps and review dates are as Neshan shows them.
267
+ - **What it does not do:** no login, saving or reviewing; no places outside Iran; no live traffic incidents; no
268
+ temperature or AI review summaries (Neshan serves those only to signed-in users).
269
+
270
+ ## FAQ
271
+
272
+ <details>
273
+ <summary><b>Is there a Neshan MCP server or a free Neshan API?</b></summary>
274
+
275
+ Neshan sells a developer API that needs an API key. `neshan-mcp` is an unofficial MCP server with 11 read-only
276
+ tools that calls the public endpoints of the neshan.org web map instead, so it needs no key, account or payment.
277
+ </details>
278
+
279
+ <details>
280
+ <summary><b>Does it need a Neshan API key?</b></summary>
281
+
282
+ No. It uses no API key, token or login. Install it with `uvx neshan-mcp` and ask in plain language.
283
+ </details>
284
+
285
+ <details>
286
+ <summary><b>Is my car allowed in Tehran's traffic zone right now?</b></summary>
287
+
288
+ `ns_zone_check` tells you whether a point is inside the traffic-plan zone (طرح ترافیک) or the odd-even zone (طرح
289
+ آلودگی هوا) and the hours Neshan shows for each plan, e.g. 06:30 to 18:00. Whether your own car may enter depends on
290
+ your permit and plate, which the server does not know. `ns_route` can route around both zones with
291
+ `avoid_traffic_zone` and `avoid_odd_even`.
292
+ </details>
293
+
294
+ <details>
295
+ <summary><b>What is Tehran's air quality today?</b></summary>
296
+
297
+ Ask the agent; `ns_air_quality("Tehran")` returns today's AQI on the 0-500 scale with Neshan's label (e.g. قابل قبول,
298
+ acceptable), the pollutant readings and every monitoring station, most polluted first.
299
+ </details>
300
+
301
+ <details>
302
+ <summary><b>How do I use it with Claude, Cursor or Copilot?</b></summary>
303
+
304
+ Add the server with `claude mcp add neshan -- uvx neshan-mcp`, or use the matching config in
305
+ [Quick start](#quick-start), then ask in Persian or English.
306
+ </details>
307
+
308
+ <details>
309
+ <summary><b>Does it work outside Iran?</b></summary>
310
+
311
+ Yes, except for `ns_nearby`. Everything else worked through a foreign connection in testing. If your network is
312
+ blocked, set `NESHAN_MCP_PROXY` to an HTTP proxy. System proxy variables are ignored on purpose.
313
+ </details>
314
+
315
+ <details>
316
+ <summary><b>How is it different from balad-mcp?</b></summary>
317
+
318
+ [balad-mcp](https://github.com/sepehr071/balad-mcp) reads Balad, another Iranian map. Both search places and give
319
+ directions; `neshan-mcp` adds bicycle, walking and public-transit routes, departure-time routing, a zone check for any
320
+ point in Tehran and air quality. You can install both and compare.
321
+ </details>
322
+
323
+ <details>
324
+ <summary><b>Can it save places or write reviews?</b></summary>
325
+
326
+ No. It has no login and only reads public data.
327
+ </details>
328
+
329
+ <details>
330
+ <summary><b>How do I debug what the agent sees?</b></summary>
331
+
332
+ ```bash
333
+ npx @modelcontextprotocol/inspector uvx neshan-mcp
334
+ ```
335
+ </details>
336
+
337
+ ## Configuration
338
+
339
+ | Variable | Default | Meaning |
340
+ |---|---|---|
341
+ | `NESHAN_MCP_PROXY` | unset | Optional HTTP proxy URL for the neshan.org requests; system proxy settings are ignored. A comma-separated list is used one at a time: the next proxy takes over when one is blocked or cannot connect |
342
+
343
+ <a id="فارسی"></a>
344
+
345
+ ## فارسی: سرور MCP نقشه نشان
346
+
347
+ <div dir="rtl">
348
+
349
+ **neshan-mcp** یک سرور MCP غیررسمی و فقط‌خواندنی برای [نقشه نشان](https://neshan.org/maps) است. با آن دستیار هوش مصنوعی شما (Claude، Cursor، Copilot و برنامه‌های دیگر) می‌تواند مکان‌ها را پیدا کند، مسیر بدهد و محدوده طرح ترافیک تهران را بررسی کند. کلید API و حساب کاربری لازم نیست.
350
+
351
+ **چه کارهایی می‌کند**
352
+
353
+ - **جستجوی مکان** با نام یا دسته (کافه، داروخانه، پمپ بنزین، خیابان، میدان) در یک شهر یا نزدیک یک نقطه، با فیلتر «باز باشد» و امتیاز، همان‌طور که در سایت نشان است.
354
+ - **جزئیات مکان**: آدرس، مختصات، تلفن، وب‌سایت، امتیاز، ساعت کاری هر روز هفته و تازه‌ترین عکس‌ها.
355
+ - **نظرات کاربران** (تازه‌ترین یا برگزیده) و **عکس‌ها**، از جمله عکس منو.
356
+ - **امکانات نزدیک** هر مکان: رستوران، کافه، پارک، سرویس بهداشتی، بانک، خودپرداز، پارکینگ و ایستگاه اتوبوس.
357
+ - **تبدیل مختصات به آدرس**.
358
+ - **کیفیت هوا**: شاخص امروز هر شهر، آلاینده‌ها و همه ایستگاه‌های سنجش.
359
+ - **مسیریابی** با خودرو، موتور، دوچرخه و پیاده، با زمان سفر زنده، گام‌های مسیر به فارسی و تا ۳ توقف بین راه.
360
+ - **مسیریابی با زمان حرکت یا رسیدن** برای خودرو در تهران، کرج و مشهد، با پیش‌بینی ترافیک نشان.
361
+ - **مقایسه زمان سفر** از یک مبدا تا حداکثر ۱۰ مقصد، از سریع‌ترین به کندترین.
362
+ - **طرح ترافیک و زوج و فرد**: آیا یک نقطه داخل محدوده است و آیا مسیر وارد آن می‌شود، با امکان دور زدن محدوده‌ها و عوارضی.
363
+ - **حمل‌ونقل عمومی**: گزینه‌های اتوبوس، بی‌آرتی و مترو با خط‌ها، ایستگاه‌ها و هزینه سفر به تومان.
364
+
365
+ **نکته‌ها**
366
+
367
+ - فقط‌خواندنی است: وارد حساب نمی‌شود، مکانی ذخیره نمی‌کند و نظر ثبت نمی‌کند.
368
+ - مختصات را به شکل `lat,lng` بدهید، یعنی اول عرض جغرافیایی (مثل `35.6997,51.3380`).
369
+ - ابزار امکانات نزدیک (`ns_nearby`) فقط با اینترنت ایران کار می‌کند. بیرون از ایران متغیر `NESHAN_MCP_PROXY` را روی یک پراکسی با خروجی ایران بگذارید.
370
+ - زمان حرکت و رسیدن به وقت تهران و تاریخ میلادی است (مثل `2026-11-01 08:00`).
371
+ - برای مسیرهای عوارضی فقط نشانه عوارضی بودن برمی‌گردد، چون خود سایت نشان مبلغ عوارض را نمایش نمی‌دهد.
372
+ - پاسخ‌های سایت نشان رمزگذاری‌شده است و این سرور آن‌ها را به همان روشی باز می‌کند که خود سایت باز می‌کند.
373
+
374
+ **نصب** (اول [uv](https://docs.astral.sh/uv/getting-started/installation/) را نصب کنید). در Claude Code:
375
+
376
+ </div>
377
+
378
+ ```bash
379
+ claude mcp add neshan -- uvx neshan-mcp
380
+ ```
381
+
382
+ <div dir="rtl">
383
+
384
+ در Claude Desktop، Cursor و برنامه‌های دیگر همان تنظیم بخش [Quick start](#quick-start) را بگذارید.
385
+
386
+ **نمونه پرسش‌ها**
387
+
388
+ - «نزدیک‌ترین داروخانه شبانه‌روزی به برج میلاد کجاست و الان باز است؟»
389
+ - «از میدان آزادی تا بازار تهران با ماشین چقدر طول می‌کشد؟ وارد طرح ترافیک می‌شوم؟»
390
+ - «فردا ساعت ۹ باید برج میلاد باشم؛ کی از میدان آزادی راه بیفتم؟»
391
+ - «با مترو و اتوبوس از میدان آزادی به برج میلاد چطور بروم و چقدر خرج دارد؟»
392
+ - «هوای اصفهان امروز آلوده است؟»
393
+ - «کافه لمیز گیشا الان باز است؟ مردم درباره‌اش چه گفته‌اند؟»
394
+
395
+ </div>
396
+
397
+ ## Development
398
+
399
+ ```bash
400
+ git clone https://github.com/sepehr071/neshan-mcp && cd neshan-mcp
401
+ uv sync
402
+ uv run ruff check . && uv run ruff format --check .
403
+ uv run python -m pytest -q # offline unit tests
404
+ uv run python -m pytest -m live -q # calls neshan.org
405
+ uv build
406
+ ```
407
+
408
+ Place tools live in `src/neshan_mcp/maps.py`, routing tools in `src/neshan_mcp/routes.py` and the decoding of
409
+ Neshan's answers in `src/neshan_mcp/codec.py`. Each tool is a typed async function with a docstring that tells the
410
+ agent when to use it. Issues and PRs are welcome.
411
+
412
+ Releases: bump the version in `pyproject.toml` and `server.json`, then push a `v*` tag. GitHub Actions publishes to PyPI.
413
+
414
+ ## Related servers
415
+
416
+ - [balad-mcp](https://github.com/sepehr071/balad-mcp) for Balad, another Iranian map: places, reviews and driving routes
417
+ - [iran-mcp](https://github.com/sepehr071/iran-mcp): catalog of all Iranian-service MCP servers
418
+ - [mrbilit-mcp](https://github.com/sepehr071/mrbilit-mcp) for Iranian flights, trains, buses and hotels
419
+ - [jabama-mcp](https://github.com/sepehr071/jabama-mcp) for villas and stays across Iran
420
+ - [snapp-mcp](https://github.com/sepehr071/snapp-mcp) for Snappfood and SnappMarket
421
+
422
+ ## Disclaimer
423
+
424
+ Unofficial and not affiliated with or endorsed by Neshan. It is read-only and uses the endpoints of the neshan.org
425
+ web app, which can change without notice. Travel times, zone hours and air quality are informational; check
426
+ official sources before relying on them.
427
+
428
+ ## Author
429
+
430
+ <a href="https://www.linkedin.com/in/sepehr-radmard"><img src="https://raw.githubusercontent.com/sepehr071/iran-mcp/main/assets/author-banner.png" alt="Sepehr Radmard: open-source MCP servers for the Iranian web. LinkedIn: linkedin.com/in/sepehr-radmard" width="100%"></a>
431
+
432
+ Built and maintained by **Sepehr Radmard** (سپهر رادمرد). Connect on [LinkedIn](https://www.linkedin.com/in/sepehr-radmard) or follow [@sepehr071 on GitHub](https://github.com/sepehr071) for more MCP servers for Iranian websites, all listed in [iran-mcp](https://github.com/sepehr071/iran-mcp). If this saves you time, a star on the repo helps other people find it.
433
+
434
+ ## License
435
+
436
+ [MIT](https://github.com/sepehr071/neshan-mcp/blob/main/LICENSE)