bharat-mcp
Offline, read-only MCP server for Indian GST/PAN/Aadhaar/IFSC/pincode/state/holiday/compliance-deadline checks.
Validate GSTIN structure, state code, embedded PAN, and mod-36 checksum.
Validate PAN shape and holder type.
Check Aadhaar format and Verhoeff checksum without storing or looking it up.
Check IFSC format and identify well-known bank codes.
Look up pincode state, district, and post offices from bundled data.
Look up states/UTs by name, GST code, ISO code, or RTO prefix; list all 36.
List or check Central Government holidays for 2026/2027.
List standard GST, TDS, advance tax, EPF/ESI, and ROC due dates in a date range.
Results include notes/data dates and clarify that format validity is not proof of registration or issuance.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bharat-mcp validate GSTIN 27AAPFU0939F1ZV and tell me the state"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
bharat-mcp
Give your AI agent accurate Indian GST, PAN, pincode and compliance knowledge.
An MCP server with eight small tools for Indian data that an AI agent should not work out in its head: checksums, code tables, lookups and due dates. It runs offline. The checksums are calculated, the datasets ship inside the package, and nothing you type is sent anywhere. Every answer says what it is based on and how old that data is.
Real output from the built server over stdio, saved by npm run proof. The fake differs from the real one in the last character only.
Does it actually help? What we measured
We put the same questions to Claude models with no tools and compared them with the tool. Everything below is reproducible; see Reproduce everything.
Test 1: is this GSTIN valid? 40 GSTINs, 20 real and 20 with exactly one character changed (so the shape is right and only the checksum can tell). The answer key is the checksum itself. A separate Python implementation of the checksum agrees with this package on 20,000 random strings (cross-check), and the algorithm reproduces the commonly published sample GSTINs used in the tests.
Opus and Sonnet scored 40/40 with no tools. Haiku scored 38/40: it accepted one fake (
25WKRPW1917M3ZS) and rejected one real GSTIN (01RLFCG9549K2Z7).The tool scored 40/40 in 9 ms for all 40 calls over stdio. The three models took 43 to 70 seconds for the same 40 questions.
So, to be straightforward about it: current Claude models are mostly right on this when asked carefully, and we could not reproduce "an AI approves a fake GSTIN" with Sonnet or Opus. What the tool gives you is a different kind of answer: the same one every time, in microseconds, with the reason ("the check character should be 4, not 5") and a clear note that well-formed is not the same as registered. A cheaper model, a rushed prompt or a long agent run is where a slip like Haiku's shows up.
Test 2: data a model cannot calculate.
Pincode to state (30 random pincodes): both Haiku and Sonnet got 29/30. Both put
262122(Pilibhit) in Uttarakhand instead of Uttar Pradesh. We do not headline the district results, because India Post lists post-office divisions, not always revenue districts, and some names changed after our data (Allahabad is now Prayagraj, Karimganj is now Sribhumi). That is also a limit of this package: see data sources.2027 Central Government holidays (17): the DoPT order for 2027 was issued in July 2026. Haiku matched 5 and said "unknown" for 12, which is the honest answer. Sonnet matched 13 and differed on 4, with no hedging, including Dussehra on 20 October 2027, which is the 2026 date (the order says 9 October 2027). Holi, Muharram and Guru Nanak's Birthday differ by one day; the order is the authority for these, not an astronomical calendar.
How the model runs were made, and their limits. Each model was a fresh Claude Code subagent given one prompt with all the questions and told not to use tools, code, files or the web. The transcripts were checked afterwards: the only tool call in every run was the one that returns the answer. Limits: all 40 GSTINs went into one prompt (a single casual question may behave differently); only Claude models were tested; 40 questions is a small sample (one mistake is 2.5 points); and the tool's own data cannot be used to prove the tool right, which is why Test 2 has no score for it. The raw answers and scored results are in bench/results/ and the method is in bench/llm/. To test your own model: npm run bench:llm -- --backend api --model <model-id> (needs ANTHROPIC_API_KEY in your shell). That runner is tested with a stand-in model only; the Claude results above were produced the way described here, not with it.
Try it on your own model (including local ones through Ollama)
npm run bench:llm runs the GSTIN test against an Anthropic model, and npm run bench:ollama -- --model <name> runs it against a model served by Ollama (it needs a model with tool-calling support). Both compare the model on its own with the model plus bharat-mcp. See bench/llm/OLLAMA.md.
I have not run this on a real Ollama model yet; the runner is tested against a stand-in server only. If you run it, please open an issue with the result.
Related MCP server: BharatPay MCP
Tools
Tool | What it does | Works offline |
| 15-character structure, state code, embedded PAN and the mod-36 check character, with decoded parts. Regular-taxpayer GSTINs only (14th character Z) | yes |
| Shape plus holder type (individual, company, firm, HUF, trust and so on) | yes |
| Format and Verhoeff checksum only. Nothing is stored or looked up; only the last 4 digits are returned | yes |
| IFSC format and bank code, with the bank name for well-known banks | yes |
| State, district and post offices for a 6-digit pincode | yes (bundled data) |
| State and union territory by name, GST code, ISO code or RTO prefix; QRMP GSTR-3B due-day group | yes |
| Central Government closed holidays for 2026 and 2027, or check one date | yes |
| GST, TDS, advance tax, EPF/ESI and ROC due dates in a date range, with legal basis and authority | yes |
All tools are read-only.
See it work in a terminal
git clone https://github.com/lllakshit/bharat-mcp.git
cd bharat-mcp && npm install && npm run build
npm run demonpm run demo starts the built server over stdio, exactly as Claude Desktop or Cursor would, and calls every tool:
Bad input comes back as an MCP error (isError: true), not as a guess.
There is also a 30-second video of this run. It is a replay of a real recording: the output and its timing are from an actual run (docs/proof/demo-timing.json); the typed command and the title cards are added. Build it yourself with npm run video (macOS).
Install
Requires Node 18 or newer.
Claude Desktop: add this to claude_desktop_config.json (on macOS: ~/Library/Application Support/Claude/claude_desktop_config.json), then restart Claude:
{
"mcpServers": {
"bharat": {
"command": "npx",
"args": ["-y", "@llakshit/bharat-mcp"]
}
}
}Cursor: add the same block to ~/.cursor/mcp.json (or .cursor/mcp.json in a project).
Claude Code:
claude mcp add bharat -- npx -y @llakshit/bharat-mcpFrom source (before or instead of npm): npm run build, then use "command": "node", "args": ["/path/to/bharat-mcp/dist/cli.js"] in the config above.
Then ask your agent: "Is GSTIN 29AAGCB7383J1Z5 valid?" It should call validate_gstin and tell you the check character is wrong.
You can also use the functions directly: import { validateGstin } from "@llakshit/bharat-mcp".
Speed and size
Measured on Apple M1 (8 cores, 16 GB, darwin arm64, Node v26.12.1) with npm run bench:
| 1,913,919 calls/s (0.52 µs each) |
| p50 0.06 ms, p99 0.15 ms |
| p50 0.04 ms (first call 21 ms, which reads the data file once) |
| p50 0.15 ms |
Cold start to tool list | 181 ms median |
Memory after loading all data | about 132 MB |
Package | 851 KB download, 3.2 MB unpacked, 40 files |
These are one machine and one run. Treat them as the order of magnitude, not a guarantee.
Tests
63 tests cover the validators (including every single-character mistake in the sample GSTINs and Aadhaar numbers), the data, the date logic and the MCP server end to end. CI runs them on Node 22 and 24, runs the built server on Node 18 and 20, and audits the dependencies.
Data sources and limits
Short version; the full detail is in DATA-SOURCES.md.
Data | Source | As of | Limit |
Pincodes | GeoNames postal codes for India, CC BY 4.0, built from the India Post list | downloaded 7 Nov 2026 | District names follow India Post and can be older than the official name (for example Allahabad, now Prayagraj). A pincode created after the download is missing. |
States, GST codes, RTO prefixes | CBIC/GSTN GST state codes, ISO 3166-2:IN, MoRTH series | 7 Nov 2026 | Hand-curated |
Holidays | DoPT orders for 2026 (dated 3 Jul 2025) and 2027 (dated 16 Jul 2026; checked against the official memorandum) | 7 Nov 2026 | Central Government (Delhi) closed holidays only. No state, bank or stock-exchange holidays. Moon-dependent dates can shift. |
Compliance deadlines | Statutory due dates under the CGST Rules, Income-tax rules, EPF/ESI and Companies Act | 7 Nov 2026 | Starter set. Standard dates only; government extensions are not included. Checked against secondary calendars, not yet line by line against each notification, so every entry is marked |
Things this server deliberately does not do:
It does not tell you a GSTIN, PAN or Aadhaar number is real or registered. A pass (
valid_format: true) means well-formed. Only the GST portal, the Income Tax Department or UIDAI can say more.It does not look up Aadhaar numbers, store them, or log them.
It does not scrape government portals or captcha-protected pages.
It does not recognise TDS/TCS, UN-body or non-resident GSTIN formats; they are reported as not supported, not as fake.
It does not include IFSC branch data yet. The RBI data has no clear reuse licence, so only the format and bank code are checked.
It does not shift a due date that falls on a Sunday or holiday. It flags it.
Every tool result carries its own note or data_as_of, so a model reading the answer can see how far to trust it.
Reproduce everything
npm install && npm run build
npm test # 63 tests
npm run demo # the terminal tour above
npm run bench # speed and size
python3 bench/crosscheck.py # independent Python checksum vs this package, 20,000 strings
node bench/llm/tool-check.mjs # the 40 GSTIN questions put to the tool over stdio
node bench/llm/report.mjs # the benchmark table, from the saved results
npm run proof # regenerates every screenshot in docs/img from real runs
npm run video # macOS only: records a real demo run and builds bharat-mcp-demo.mp4 from itThe screenshots in docs/img are SVG renderings of real terminal output. The raw text of each run is in docs/proof/, so you can compare them line by line.
Develop
npm install
npm test
npm run typecheck
npm run build
npm run smoke # starts the built server over stdio and calls itRebuild the pincode file from GeoNames: download IN.zip from https://download.geonames.org/export/zip/, unzip it, then node scripts/build-pincodes.mjs path/to/IN.txt.
Contributing
Issues and pull requests are welcome, especially:
a wrong or out-of-date due date (please link the official notification),
a state or bank code that is missing,
tell me which Indian data you want next.
Licence
Code: MIT. Bundled data keeps the licence of its source; see DATA-SOURCES.md.
Available Tools
8 toolscompliance_deadlinesGST, TDS, ROC and payroll due datesARead-onlyIdempotent
Lists standard Indian compliance due dates (GST returns, TDS deposits and returns, advance tax, EPF/ESI, ROC filings) falling between two dates, with the legal basis and official authority for each. Defaults to the next 31 days from today in IST. Pass a state to get the right QRMP GSTR-3B date. These are the standard statutory dates; government extensions are not included, so always confirm with the official notification before relying on a date.
Inputs: to, from, state, categories.
india_holidaysIndian central government holidaysARead-onlyIdempotent
Lists the Central Government closed (gazetted) holidays for a year, or checks whether a given date is one (if both are given, date is used). Covers 2026 and 2027, from the DoPT order. It does NOT include state holidays, bank holidays or stock-exchange holidays, and moon-dependent festival dates can shift by a day.
Inputs: date, year.
lookup_pincodeLook up an Indian pincodeARead-onlyIdempotent
Returns the state, district and post offices for a 6-digit Indian pincode from the bundled GeoNames postal-code list (CC BY 4.0, built from the India Post list). District names can be older than the current official name, and a pincode created after the data date (see data_as_of) will not be found.
Inputs: pincode (required).
state_infoState and union territory codesARead-onlyIdempotent
Looks up an Indian state or union territory by name, GST state code (for example 27), ISO code (IN-MH) or vehicle registration prefix (MH). Returns the GST code, RTO prefixes, capital, and the QRMP GSTR-3B due day group. With no query it lists all 36.
Inputs: query.
validate_aadhaar_formatCheck an Aadhaar number's formatARead-onlyIdempotent
Checks only the FORMAT of an Aadhaar number: 12 digits, not starting with 0 or 1, and the Verhoeff checksum. Nothing is stored, logged or looked up, and only the last 4 digits are returned. A pass does not mean the number was issued to anyone. Do not use this to identify people.
Inputs: aadhaar (required).
validate_gstinValidate a GSTINARead-onlyIdempotent
Checks an Indian GSTIN offline: 15-character structure, state code, embedded PAN, and the mod-36 check character. Returns the decoded parts. Use this instead of guessing whether a GSTIN is well-formed; a model cannot calculate the check character reliably. Covers regular-taxpayer GSTINs (14th character Z); TDS/TCS, UN-body and non-resident formats are not supported. A pass only means well-formed, not registered or active.
Inputs: gstin (required).
validate_ifscCheck an IFSC code's formatARead-onlyIdempotent
Checks the format of an IFSC code (4 bank letters, a zero, 6 branch characters) and names the bank for well-known bank codes. It does not confirm that the branch exists or give the branch address.
Inputs: ifsc (required).
validate_panValidate a PANARead-onlyIdempotent
Checks an Indian PAN offline: the 5 letters, 4 digits, 1 letter shape and the holder type in the 4th character (individual, company, firm, HUF, trust and so on). A pass does not prove the PAN was issued or who owns it.
Inputs: pan (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Each tool targets a clearly distinct resource: pincode lookup, holiday calendar, compliance dates, state reference, and four separate identifier validators (Aadhaar, GSTIN, IFSC, PAN). The four validate_* tools can't be confused with each other since each names a different document type, and lookup_pincode vs state_info differ in input (6-digit code vs name/GST/ISO/RTO code). No two tools appear to do the same thing.
Names split cleanly into verb_noun action tools (lookup_pincode, validate_gstin, validate_aadhaar_format, validate_ifsc, validate_pan) and bare-noun reference tools (india_holidays, compliance_deadlines, state_info). The internal convention within each group is consistent and the split is semantically meaningful, but mixing two naming schemes keeps it from a perfect score.
Eight tools is well within the ideal 3-15 range and each one covers a distinct reference artifact or validator an India-focused agent would actually need. Nothing feels padded or redundant, and nothing core is missing from the count.
The surface covers the common Indian identifier and date references (pincode, GSTIN, PAN, Aadhaar format, IFSC, holidays, compliance calendar, states) with no dead ends within scope. Gaps are moderate but real: IFSC bank naming is partial with no branch data, holidays only span 2026-2027, and there is no validator for other common identifiers (e.g. UPI, phone, vehicle registration) or reverse pincode-to-district listing beyond the single lookup.
Maintenance
Related MCP Connectors
15 deterministic validation tools for AI agents: tax IDs (15 countries), VAT, IBAN, LEI, HS codes.
Free Indian data and AI: pincode, IFSC, GSTIN, holidays, GST invoice, OCR, translation. No key.
Validate IBAN, BIC, VAT, national IDs, phones, postal codes offline; 240+ identifiers.
Offline IBAN/BIC/EU VAT/card/ISBN/GTIN validators + live USD stablecoin peg-health verdict.
Related MCP Servers
- AlicenseAqualityAmaintenanceAn offline-first MCP server for Indian financial, tax, and government APIs, providing tools for identity validation (PAN, Aadhaar, GSTIN), tax calculations (Income Tax, TDS, GST), and master data lookups (IFSC, Pincode, HSN/SAC) with zero authentication required.76145 PyPI86MIT
- AlicenseAqualityCmaintenanceProvides AI agents with Indian fintech utilities including IFSC bank lookups, PAN/GSTIN validation, mutual fund NAVs, UPI VPA identification, pincode lookups, and INR formatting, all with zero authentication and zero cost.7MIT
- AlicenseAqualityDmaintenanceEnables LLMs to query real-time Indian bank branch details, postal PIN codes, validate GSTIN/PAN structures, check e-commerce serviceability, and compute GST breakdowns using free public APIs and offline verification logic.69 npm1MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to validate IBAN, BIC, EU VAT, GTIN/EAN/UPC, and ISBN codes offline through format and check-digit checks, and retrieve related metadata.26,592 npmMIT