rti-mcp 0.3.2__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.
@@ -0,0 +1,47 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ *.egg
6
+ build/
7
+ dist/
8
+ .eggs/
9
+
10
+ # Written by setuptools-scm at build time; the git tag is the real source.
11
+ rti_mcp/_version.py
12
+
13
+ # Virtualenvs
14
+ .venv/
15
+ venv/
16
+ env/
17
+ ENV/
18
+
19
+ # Tooling caches
20
+ .pytest_cache/
21
+ .ruff_cache/
22
+ .mypy_cache/
23
+ .coverage
24
+ htmlcov/
25
+ .tox/
26
+
27
+ # Editors / OS
28
+ .vscode/
29
+ .idea/
30
+ *.swp
31
+ .DS_Store
32
+ Thumbs.db
33
+
34
+ # --- Never commit these -------------------------------------------------
35
+ # The server's own state directory, if anyone points RTI_MCP_HOME at the
36
+ # repo. config.json holds a session URL that reads your RTI account.
37
+ .rti-mcp/
38
+ config.json
39
+ rti_config.json
40
+
41
+ # Downloaded replies, exported spreadsheets, saved portal pages: these are
42
+ # your real applications and your real name.
43
+ *.pdf
44
+ *.csv
45
+ *.xlsx
46
+ documents/
47
+ !tests/fixtures/*.html
@@ -0,0 +1,77 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.3.1] — 2026-08-07
10
+
11
+ First release published to PyPI: `pip install rti-mcp`.
12
+
13
+ 0.1.1, 0.2.0, 0.2.1 and 0.3.0 were never released. Each of those tags was cut
14
+ against a tree that still declared an older version in its source, so the
15
+ number on the tag and the number in the package disagreed. Versions now come
16
+ from the tag itself and cannot drift again.
17
+
18
+ ### Fixed
19
+
20
+ - `rti_list(search=...)` and `rti_search` now match on a row's status date, and
21
+ accept a date in either the ISO or the dd/mm/yyyy form. Both tools advertised
22
+ searching "by date", but the filter only ever saw the ISO filing date: asking
23
+ what moved on `07/08/2026` returned nothing, with no hint the query had been
24
+ understood as a literal string rather than a date.
25
+
26
+ ### Changed
27
+
28
+ - `rti_list` and `rti_search` descriptions now name every searchable field and
29
+ both accepted date formats, rather than the vaguer "or date".
30
+ - README spells out the Windows interpreter path for `claude mcp add`, and notes
31
+ that re-pointing an existing server needs `claude mcp remove` first.
32
+ - The version is derived from the git tag by setuptools-scm. No file in the tree
33
+ records it, so `rti_mcp.__version__`, the distribution metadata and the version
34
+ the MCP client sees are always the tag that was released. Building off an
35
+ untagged commit yields a `.devN` version that PyPI refuses, by design.
36
+
37
+ ### Added
38
+
39
+ - `pip install rti-mcp` — the project is on PyPI, so installing no longer needs
40
+ git or a clone.
41
+ - Tag-driven release workflow publishing via PyPI Trusted Publishing (OIDC), so
42
+ no API token is stored in the repository. It re-runs the full test matrix and
43
+ refuses to publish anything that is not built from a tagged commit.
44
+
45
+ ## [0.1.0] — 2026-08-07
46
+
47
+ First public release.
48
+
49
+ ### Added
50
+
51
+ - Eleven MCP tools over the RTI Online citizen "View History" area:
52
+ `rti_session_status`, `rti_set_session_url`, `rti_dashboard`, `rti_list`,
53
+ `rti_search`, `rti_overdue`, `rti_status`, `rti_details`, `rti_download`,
54
+ `rti_export_csv` and `rti_clear_cache`.
55
+ - Session URL stored in `~/.rti-mcp/config.json` and replaceable at runtime via
56
+ `rti_set_session_url`, so an expired portal session never requires editing an
57
+ MCP client config or restarting the server.
58
+ - Disk cache per (category, bucket) with a configurable TTL, keyed on the
59
+ session URL so a new login cannot serve another account's cached rows.
60
+ - Automatic recovery from the portal's navigation rules: single-use detail
61
+ tokens are never cached, several detail pages are read off one live list, and
62
+ a 403 triggers a re-walk from the seed URL.
63
+ - `unparsed_rows()` reporting, surfaced by `rti_session_status`, so a
64
+ registration-number format change shows up as a warning instead of silently
65
+ missing applications.
66
+ - Offline parser test suite over synthetic fixtures, and CI across Python
67
+ 3.10–3.13.
68
+
69
+ ### Known issues
70
+
71
+ - The portal's dashboard counts sometimes run a row or two ahead of its own
72
+ list pages. This is the portal's inconsistency; the row parser matches the
73
+ served table exactly, and `rti_dashboard` says so in its output.
74
+
75
+ [Unreleased]: https://github.com/gouthamganeshm/rti-mcp/compare/v0.3.1...HEAD
76
+ [0.3.1]: https://github.com/gouthamganeshm/rti-mcp/compare/v0.1.0...v0.3.1
77
+ [0.1.0]: https://github.com/gouthamganeshm/rti-mcp/releases/tag/v0.1.0
@@ -0,0 +1,137 @@
1
+ # Contributing
2
+
3
+ Thanks for looking. This is a small, focused tool: it reads one citizen's own
4
+ RTI Online history and exposes it to an MCP client. Contributions that keep it
5
+ that size are the easiest to merge.
6
+
7
+ ## Before anything else
8
+
9
+ **Never include a live session URL, a real registration number you would rather
10
+ keep private, or a real name and email in an issue, a PR, a test fixture or a
11
+ commit.** See [SECURITY.md](SECURITY.md). Fixtures in `tests/fixtures/` are
12
+ synthetic on purpose — keep them that way.
13
+
14
+ ## Setting up
15
+
16
+ ```bash
17
+ git clone https://github.com/gouthamganeshm/rti-mcp.git
18
+ cd rti-mcp
19
+ python -m venv .venv
20
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
21
+ pip install -e ".[dev]"
22
+ ```
23
+
24
+ Run the checks:
25
+
26
+ ```bash
27
+ ruff check .
28
+ pytest -q
29
+ ```
30
+
31
+ Both run offline. You do not need an RTI account, a session URL, or network
32
+ access to work on the parsers — which is the point of the fixture suite.
33
+
34
+ ## The thing that will break: the portal's HTML
35
+
36
+ This project has no API. It parses pages that a government portal can change
37
+ without warning, and the navigation rules it follows were established
38
+ empirically, not from documentation. `rti_mcp/client.py` opens with a map of
39
+ the page graph and the three rules the portal enforces with bare 403s. Read
40
+ that docstring before changing anything in the fetch path.
41
+
42
+ If the portal changes and something stops parsing:
43
+
44
+ 1. Save the page that broke, **by hand, with your own data stripped out** —
45
+ replace the name, email, registration numbers and tokens with obvious
46
+ fakes.
47
+ 2. Add it to `tests/fixtures/` and write a failing test.
48
+ 3. Fix the parser.
49
+
50
+ A PR with a fixture reproducing the breakage is worth far more than one
51
+ without, because nobody else can see your account.
52
+
53
+ ## House style
54
+
55
+ - Match the surrounding code. It favours small functions, explicit names, and
56
+ comments that explain *why* rather than what.
57
+ - Comment the portal's oddities where they bite. Several of the strange-looking
58
+ branches in `client.py` exist because the portal does something unreasonable;
59
+ a comment saying which is more valuable than a tidier-looking line.
60
+ - Surface anomalies rather than swallowing them. `unparsed_rows()` exists
61
+ because a silently dropped row is indistinguishable from an application that
62
+ does not exist. Please keep that instinct.
63
+ - Stay polite to the server. `MIN_REQUEST_GAP` paces requests ~0.6 s apart and
64
+ lists are cached; do not add features that hammer the portal, and do not add
65
+ anything that writes to it.
66
+
67
+ ## Scope
68
+
69
+ Happily accepted:
70
+
71
+ - Parser fixes for portal changes, with fixtures.
72
+ - Better error messages, especially around session expiry.
73
+ - New read-only tools over pages the portal already shows the account holder.
74
+ - Documentation, packaging and CI improvements.
75
+
76
+ Out of scope:
77
+
78
+ - **Anything that files, edits, appeals or pays.** This stays read-only. An
79
+ RTI application is a legal act; it should be a deliberate human one.
80
+ - Anything that automates login, solves the captcha, or intercepts the OTP.
81
+ The one-time manual login is a feature, not an obstacle to route around.
82
+ - Bulk scraping of other people's applications, or of the portal at large.
83
+ - Vendoring or committing real account data.
84
+
85
+ ## Pull requests
86
+
87
+ Keep them focused, explain what the portal was doing that made the change
88
+ necessary, and make sure `ruff check .` and `pytest -q` pass. Small PRs get
89
+ reviewed faster.
90
+
91
+ By contributing you agree your work is licensed under the MIT License, the same
92
+ as the rest of the project.
93
+
94
+ ## Releasing
95
+
96
+ Maintainers only. Releases are cut by pushing a version tag; the `Release`
97
+ workflow runs the full matrix, builds, and uploads to PyPI.
98
+
99
+ One-time setup on PyPI — add a **Trusted Publisher** under the project's
100
+ *Publishing* settings (for the very first upload, use *Publishing* → *Add a
101
+ pending publisher*, since the project does not exist yet):
102
+
103
+ | Field | Value |
104
+ |-------|-------|
105
+ | Owner | `gouthamganeshm` |
106
+ | Repository | `rti-mcp` |
107
+ | Workflow | `release.yml` |
108
+ | Environment | `pypi` |
109
+
110
+ This uses OIDC, so there is no API token to store or rotate. Then create a
111
+ `pypi` environment in the repository's settings if you want a manual approval
112
+ gate before the upload step runs.
113
+
114
+ To release:
115
+
116
+ 1. Move the `Unreleased` changelog entries under the new version, and add the
117
+ comparison links at the bottom.
118
+ 2. Commit that.
119
+ 3. Tag the commit and push:
120
+
121
+ ```bash
122
+ git tag v0.3.1
123
+ git push origin main --tags
124
+ ```
125
+
126
+ **There is no version to bump.** setuptools-scm reads it from the tag, so
127
+ `rti_mcp.__version__`, the distribution metadata and the version the MCP client
128
+ reports are all whatever you tagged. Tag `v0.3.1` and you publish `0.3.1`.
129
+
130
+ Two consequences worth knowing:
131
+
132
+ - A build from an untagged commit is a `.devN` version, not a release. PyPI
133
+ refuses those and the workflow fails early rather than uploading. Tag first.
134
+ - Tag the commit you actually want published. Retagging after a successful
135
+ upload does not help: PyPI never allows a version to be replaced or reused,
136
+ even after deletion. Dry-run anything uncertain against
137
+ [TestPyPI](https://test.pypi.org) first.
rti_mcp-0.3.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Goutham Ganesh M H
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,13 @@
1
+ include LICENSE
2
+ include README.md
3
+ include CHANGELOG.md
4
+ include CONTRIBUTING.md
5
+ include SECURITY.md
6
+ include requirements.txt
7
+
8
+ # Ship the test suite complete -- fixtures and conftest included -- so
9
+ # `pytest` works from an unpacked sdist, not just from a git checkout.
10
+ recursive-include tests *.py *.html
11
+
12
+ prune .github
13
+ global-exclude __pycache__ *.py[cod]
rti_mcp-0.3.2/PKG-INFO ADDED
@@ -0,0 +1,373 @@
1
+ Metadata-Version: 2.4
2
+ Name: rti-mcp
3
+ Version: 0.3.2
4
+ Summary: MCP server for querying your own applications on India's RTI Online portal
5
+ Author: Goutham Ganesh M H
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/gouthamganeshm/rti-mcp
8
+ Project-URL: Repository, https://github.com/gouthamganeshm/rti-mcp
9
+ Project-URL: Issues, https://github.com/gouthamganeshm/rti-mcp/issues
10
+ Project-URL: Changelog, https://github.com/gouthamganeshm/rti-mcp/blob/main/CHANGELOG.md
11
+ Keywords: mcp,rti,india,transparency,civic-tech,rtionline
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: End Users/Desktop
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 :: Internet :: WWW/HTTP :: Indexing/Search
21
+ Classifier: Topic :: Office/Business
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: mcp>=2.0.0
26
+ Requires-Dist: requests>=2.31.0
27
+ Requires-Dist: beautifulsoup4>=4.12.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8.0; extra == "dev"
30
+ Requires-Dist: ruff>=0.6; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # rti-mcp
34
+
35
+ [![CI](https://github.com/gouthamganeshm/rti-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/gouthamganeshm/rti-mcp/actions/workflows/ci.yml)
36
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
37
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
38
+
39
+ An [MCP](https://modelcontextprotocol.io) server for querying **your own**
40
+ applications on India's [RTI Online portal](https://rtionline.gov.in) — status,
41
+ filed text, replies and reply PDFs — without re-entering an OTP and two
42
+ captchas for every lookup.
43
+
44
+ Ask your assistant "which of my RTIs are overdue?" instead of clicking through
45
+ `View History` one application at a time.
46
+
47
+ ```
48
+ > Which of my RTI requests are more than 30 days overdue?
49
+
50
+ 14 of your 146 pending requests are past the Act's 30-day deadline.
51
+ The oldest is DGDOR/R/E/21/00133, filed 1,844 days ago…
52
+
53
+ > What happened to the NIMHANS one?
54
+
55
+ NIMNS/R/E/26/00220 — REQUEST DISPOSED OF as on 30/07/2026. A reply PDF
56
+ is available; want me to download it?
57
+ ```
58
+
59
+ ## Contents
60
+
61
+ - [Why this works](#why-this-works)
62
+ - [Install](#install)
63
+ - [Get your session URL](#get-your-session-url)
64
+ - [Register with your MCP client](#register-with-your-mcp-client)
65
+ - [Tools](#tools)
66
+ - [Configuration](#configuration)
67
+ - [How the portal behaves](#how-the-portal-behaves)
68
+ - [Troubleshooting](#troubleshooting)
69
+ - [Security](#security)
70
+ - [Disclaimer](#disclaimer)
71
+
72
+ ## Why this works
73
+
74
+ Logging in to RTI Online and clicking **View History** lands you on a
75
+ `citizen_view_history.php` URL whose `emailchk`, `cellchk` and `urletoken`
76
+ parameters are server-side encrypted blobs. That URL authenticates *itself* —
77
+ it keeps working from a plain HTTP client with no cookies carried over from the
78
+ browser, and it stays valid for a long time.
79
+
80
+ This server takes that one URL and walks the rest of the portal from it. You
81
+ pay the OTP + captcha cost once, whenever the URL eventually stops working.
82
+
83
+ It is **read-only**. It only ever reads your own account, and only what the
84
+ portal already shows you when you are logged in. It cannot file, appeal, edit
85
+ or pay. Anyone holding your URL can read the same data, so treat it like a
86
+ password — see [Security](#security).
87
+
88
+ ## Install
89
+
90
+ Requires **Python 3.10+**.
91
+
92
+ ```bash
93
+ python -m venv .venv
94
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
95
+ pip install rti-mcp
96
+ ```
97
+
98
+ Install into a virtual environment rather than system Python: the next section
99
+ asks for an absolute interpreter path, and a venv is what makes that path
100
+ stable.
101
+
102
+ <details>
103
+ <summary>From source, to hack on it</summary>
104
+
105
+ ```bash
106
+ git clone https://github.com/gouthamganeshm/rti-mcp.git
107
+ cd rti-mcp
108
+ python -m venv .venv
109
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
110
+ pip install -e ".[dev]"
111
+ ```
112
+
113
+ Or the unreleased `main`, without a working copy:
114
+
115
+ ```bash
116
+ pip install "git+https://github.com/gouthamganeshm/rti-mcp.git"
117
+ ```
118
+
119
+ </details>
120
+
121
+ > **Point your MCP config at an absolute interpreter path, never a bare
122
+ > `python`.** A bare `python` resolves to whatever environment happens to be
123
+ > active when the client spawns the server, and the server vanishes from the
124
+ > list with a `ModuleNotFoundError` the moment that differs from the
125
+ > environment holding the dependencies. Get the right path with:
126
+ >
127
+ > ```bash
128
+ > python -c "import sys; print(sys.executable)"
129
+ > ```
130
+
131
+ ## Get your session URL
132
+
133
+ 1. Open <https://rtionline.gov.in> and log in with your OTP and captcha.
134
+ 2. Click **View History**.
135
+ 3. Copy the entire URL from the address bar. It looks like:
136
+
137
+ ```
138
+ https://rtionline.gov.in/request/citizen_view_history.php?emailchk=…&cellchk=…&urletoken=…
139
+ ```
140
+
141
+ Then hand it to the server, either by asking your assistant —
142
+
143
+ > "Set my RTI session URL to `https://rtionline.gov.in/request/citizen_view_history.php?emailchk=…`"
144
+
145
+ — which calls `rti_set_session_url` and stores it in `~/.rti-mcp/config.json`,
146
+ or by exporting it before the client starts:
147
+
148
+ ```bash
149
+ export RTI_HISTORY_URL="https://rtionline.gov.in/request/citizen_view_history.php?emailchk=…"
150
+ ```
151
+
152
+ The stored config file wins over the environment variable, so
153
+ `rti_set_session_url` can refresh an expired URL at runtime without touching
154
+ your MCP client config or restarting anything.
155
+
156
+ ## Register with your MCP client
157
+
158
+ Each client keeps its own registry — registering with one does **not** populate
159
+ another's list.
160
+
161
+ <details open>
162
+ <summary><b>Claude Code</b></summary>
163
+
164
+ ```bash
165
+ claude mcp add rti-online -s user -- /absolute/path/to/.venv/bin/python -m rti_mcp
166
+ ```
167
+
168
+ On Windows the interpreter sits elsewhere in the venv, so pass that path instead:
169
+
170
+ ```bash
171
+ claude mcp add rti-online -s user -- C:\path\to\.venv\Scripts\python.exe -m rti_mcp
172
+ ```
173
+
174
+ Re-pointing an existing entry means removing it first — `claude mcp add` will not
175
+ overwrite one that is already registered:
176
+
177
+ ```bash
178
+ claude mcp remove rti-online -s user
179
+ ```
180
+
181
+ Or a project `.mcp.json` (key: `mcpServers`):
182
+
183
+ ```json
184
+ {
185
+ "mcpServers": {
186
+ "rti-online": {
187
+ "type": "stdio",
188
+ "command": "/absolute/path/to/.venv/bin/python",
189
+ "args": ["-m", "rti_mcp"]
190
+ }
191
+ }
192
+ }
193
+ ```
194
+
195
+ Verify with `claude mcp list`, or `/mcp` inside a session.
196
+ </details>
197
+
198
+ <details>
199
+ <summary><b>Claude Desktop</b></summary>
200
+
201
+ Edit `claude_desktop_config.json` (macOS:
202
+ `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`):
203
+
204
+ ```json
205
+ {
206
+ "mcpServers": {
207
+ "rti-online": {
208
+ "command": "C:\\path\\to\\.venv\\Scripts\\python.exe",
209
+ "args": ["-m", "rti_mcp"]
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ Restart Claude Desktop afterwards.
216
+ </details>
217
+
218
+ <details>
219
+ <summary><b>VS Code</b></summary>
220
+
221
+ `.vscode/mcp.json` — note the key is `servers`, not `mcpServers`:
222
+
223
+ ```json
224
+ {
225
+ "servers": {
226
+ "rti-online": {
227
+ "type": "stdio",
228
+ "command": "/absolute/path/to/.venv/bin/python",
229
+ "args": ["-m", "rti_mcp"]
230
+ }
231
+ }
232
+ }
233
+ ```
234
+
235
+ The server will not appear in the Extensions sidebar; that is expected.
236
+ </details>
237
+
238
+ <details>
239
+ <summary><b>Anything else (stdio)</b></summary>
240
+
241
+ The server speaks stdio and is also installed as a console script:
242
+
243
+ ```bash
244
+ rti-mcp
245
+ ```
246
+
247
+ Equivalent to `python -m rti_mcp`. Point any MCP-capable client at either.
248
+ </details>
249
+
250
+ ## Tools
251
+
252
+ | Tool | What it does |
253
+ | --- | --- |
254
+ | `rti_session_status` | Is the stored URL still good, and whose account is it |
255
+ | `rti_set_session_url` | Store a fresh URL after re-login; clears the cache |
256
+ | `rti_dashboard` | Registered / disposed / pending totals, requests and appeals |
257
+ | `rti_list` | List one bucket, with optional filter and paging |
258
+ | `rti_search` | Find applications by number fragment, authority code or status |
259
+ | `rti_overdue` | Pending requests past the Act's 30-day reply deadline |
260
+ | `rti_status` | Current status, remarks and reply availability for one application |
261
+ | `rti_details` | Full filed application: authority, information sought, CPIO |
262
+ | `rti_download` | Save the reply PDF or the attached request document |
263
+ | `rti_export_csv` | Export every request and appeal to CSV |
264
+ | `rti_clear_cache` | Force the next query to re-read the portal |
265
+
266
+ Things to ask for once it is wired up:
267
+
268
+ - "What's the status of NIMNS/R/E/26/00220?"
269
+ - "Which of my RTIs are more than 30 days overdue?"
270
+ - "Anything change on my applications today?"
271
+ - "Download the reply for the NIMHANS one."
272
+ - "Export everything to a spreadsheet."
273
+
274
+ ## Configuration
275
+
276
+ | Variable | Default | Meaning |
277
+ | --- | --- | --- |
278
+ | `RTI_HISTORY_URL` | — | Seed View History URL (fallback if no config file) |
279
+ | `RTI_MCP_HOME` | `~/.rti-mcp` | Config + cache location |
280
+ | `RTI_MCP_DOWNLOAD_DIR` | `~/.rti-mcp/documents` | Where PDFs and CSVs land |
281
+ | `RTI_MCP_CACHE_TTL` | `900` | Seconds a fetched list stays fresh |
282
+
283
+ Every list-returning tool also takes `refresh=true` to bypass the cache for one
284
+ call.
285
+
286
+ ## How the portal behaves
287
+
288
+ Worth knowing, because the constraints shaped the code:
289
+
290
+ - **No pagination.** A bucket's list page carries every row — several hundred
291
+ registered requests in one ~300 KB response. One fetch gets everything.
292
+ - **`registered` is the superset.** Its count equals disposed + pending, so
293
+ `rti_search` and `rti_export_csv` fetch one list per category, not three.
294
+ - **Detail links are single-use-ish.** Every list fetch mints fresh
295
+ `regId`/`token` params, valid only while that fetch is the most recent
296
+ *successful* navigation. Fetching a different list invalidates the previous
297
+ page's links.
298
+ - **A 403 poisons the session.** Once one request 403s, the next one fails too,
299
+ whatever it is. Re-walking seed → list clears it.
300
+
301
+ `client.py` encodes these rules: detail links are never cached to disk, several
302
+ details can be read off one live list, and a 403 triggers an automatic re-walk
303
+ from the seed URL. Requests are paced ~0.6 s apart to stay polite to a
304
+ government server.
305
+
306
+ One known quirk, surfaced rather than hidden: the dashboard's counts sometimes
307
+ run a row or two ahead of its own list pages (e.g. it says 146 pending while
308
+ the pending page lists 144). That is the portal's inconsistency, not a parsing
309
+ gap — the row parser matches the served table exactly, and any row it fails to
310
+ recognise is reported by `rti_session_status` instead of being dropped.
311
+
312
+ ## Troubleshooting
313
+
314
+ **The server does not appear in the client's tool list.**
315
+ Almost always the interpreter path. Run
316
+ `/absolute/path/to/python -m rti_mcp` in a terminal: if it fails with
317
+ `ModuleNotFoundError: No module named 'rti_mcp'`, the package is installed into
318
+ a different environment than the one your config names.
319
+
320
+ **"The RTI Online session URL is no longer valid."**
321
+ It expired. Log in again, open View History, copy the URL, and pass it to
322
+ `rti_set_session_url`. Nothing else needs changing.
323
+
324
+ **Results look stale.**
325
+ Lists are cached for 15 minutes. Pass `refresh=true`, or call
326
+ `rti_clear_cache`.
327
+
328
+ **A tool reports `unparsed_rows`.**
329
+ The portal changed its registration-number format and some applications are
330
+ missing from results. Please [open an
331
+ issue](https://github.com/gouthamganeshm/rti-mcp/issues) with the *shape* of
332
+ the number that failed — not your real one.
333
+
334
+ **Everything 403s.**
335
+ The session got poisoned mid-walk. The client recovers automatically; if it
336
+ persists, `rti_clear_cache` then retry.
337
+
338
+ ## Security
339
+
340
+ `~/.rti-mcp/config.json` holds a URL that grants read access to your entire RTI
341
+ account. Don't commit it, don't paste it into an issue, and don't put it in a
342
+ screenshot. **There is no logout** — revoking it means waiting for the portal
343
+ to expire it.
344
+
345
+ Full details, and how to report a vulnerability, in [SECURITY.md](SECURITY.md).
346
+
347
+ ## Disclaimer
348
+
349
+ Not affiliated with, endorsed by, or connected to the Government of India, the
350
+ Department of Personnel and Training, or the RTI Online portal.
351
+
352
+ This is an unofficial client that parses HTML the portal was not designed to
353
+ serve to programs, so it can break whenever the portal changes. It reads only
354
+ the account whose session URL you supply. Use it for your own applications;
355
+ don't point it at the portal at large, and don't remove the request pacing.
356
+
357
+ The 30-day figure `rti_overdue` uses is the
358
+ ordinary deadline under §7(1) of the RTI Act, 2005 — shorter and longer periods
359
+ apply in some cases (48 hours where life or liberty is concerned, 35 or 40 days
360
+ when routed through an APIO or a third party is involved). Check the Act before
361
+ relying on a date.
362
+
363
+ Use this at your own risk.
364
+
365
+ ## Contributing
366
+
367
+ Issues and PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). The test suite
368
+ runs entirely offline against synthetic fixtures, so you can work on the
369
+ parsers without an RTI account.
370
+
371
+ ## License
372
+
373
+ [MIT](LICENSE) © Goutham Ganesh M H