nsuid-mapper
by maixiang-sh
README.md
# nsuid-mapper-web
Web page, HTTP API and MCP server for [nsuid-mapper](https://github.com/maixiang-sh/nsuid-mapper),
on Cloudflare Workers at **https://nsuid-mapper.ohneko.com**.
Unofficial project; not affiliated with or endorsed by Nintendo.
| Path | What |
| ----------------- | ----------------------------------------------------------------------------------- |
| `/` | Web page: map an NSUID or store link, with product details and store links |
| `/api/v1/map` | Public HTTP API, mapping only |
| `/mcp` | Public MCP server (Streamable HTTP, stateless), one tool: `map_nsuid` |
| `/docs/` | API and MCP docs, including install instructions to paste to an agent |
| `/openapi.json` | OpenAPI description of the HTTP API |
| `/llms.txt` | Summary for AI tools |
| `/api/web/lookup` | Backend of the web page; the only place product data (Savanna) is used. Not public. |
## How it works
- Mapping comes from nsuid-mapper, installed from GitHub at a pinned commit and imported
from `nsuid-mapper/source`. Update it with `bun add github:maixiang-sh/nsuid-mapper#<commit>`.
- Results are cached in KV (`MAP_CACHE`): one day when every target mapped, five minutes
otherwise. Upstream failures are not cached.
- Only cache misses reach Nintendo, and only they count against the per-IP rate limit
(`API_LIMITER`, about 20 a minute; Cloudflare counts approximately).
- Without `from`, the source store is found by asking the JP, US, GB, HK and KR stores.
- Requests that would reach Nintendo pass a guard: the pause switch, then about 20 a minute
per IP (429), then about 300 a minute from everyone together (503 `busy`). Cached results
skip the guard. KV failures (including a used-up daily quota) never fail a request: a read
counts as a miss and a write is skipped.
## If the service is abused
Pause every new lookup; cached results are still served:
```bash
bun x wrangler deploy --var UPSTREAM_ENABLED:false
```
Resume with `bun run deploy`. The variable can also be changed in the Cloudflare dashboard,
but the next deploy resets it to `wrangler.jsonc`.
| File | Role |
| --------------- | ---------------------------------------------------------- |
| `src/index.ts` | Routes |
| `src/map.ts` | Input validation and the mapping cache |
| `src/run.ts` | Mapping as offered by the API and MCP, with error outcomes |
| `src/api.ts` | HTTP API handler |
| `src/mcp.ts` | MCP server |
| `src/detect.ts` | Finding the source store |
| `src/lookup.ts` | Web page backend: input parsing, product details, links |
| `src/web.ts` | Web page backend handler |
| `src/limit.ts` | Pause switch and rate limits |
| `src/cache.ts` | KV access that never fails a request |
| `public/` | Web page, docs page, OpenAPI and llms.txt |
## Development
Requires [Bun](https://bun.sh). Deploying needs `CLOUDFLARE_API_TOKEN` and
`CLOUDFLARE_ACCOUNT_ID` in the environment, or `bun x wrangler login`.
```bash
bun install
bun run dev # local server at http://localhost:8787 (requests reach Nintendo)
bun run check # typecheck, format check, tests
bun run deploy # deploy to Cloudflare
```
## License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues