.
├── server/src/ Node backend (the MCP client)
│ ├── index.ts entry point: mock bootstrap, Vite middleware (dev) or static files (prod)
│ ├── app.ts Express routes under /api
│ ├── config.ts environment configuration
│ ├── logger.ts one-line levelled logger
│ ├── mcp/ hub.ts (routing/validation/limits/cache/stats) · connection.ts · wiretap.ts
│ ├── analytics/ recipes.ts — multi-tool compositions
│ └── agent/ agent.ts — optional Claude tool-use loop
├── shared/ code used by server, UI, scripts and tests
│ ├── types.ts · catalog.ts · mcpResult.ts · analytics.ts
├── web/ React UI (Vite root)
│ └── src/{pages,components,lib}
├── mock/ mock MCP server + recorded fixtures
├── examples/ standalone TypeScript / Python programs and client configs
├── scripts/ record-fixtures.ts · gen-examples-doc.ts
├── tests/ Vitest suites
└── docs/
| Command | What it does |
|---|---|
npm run dev |
Backend + UI with hot reload, live NSE (http://localhost:5180) |
npm run dev:mock |
Same against the in-process mock MCP server |
npm run build |
Typecheck everything, build the UI to web/dist |
npm start / npm run start:mock |
Production server (needs npm run build first) |
npm run typecheck |
tsc --noEmit over server, shared, web, mock, tests, scripts, examples |
npm test |
Full offline test suite (mock MCP server) |
npm run test:live |
Opt-in smoke test against real NSE |
npm run mock-server |
Run the mock MCP servers standalone on port 5181 (point any MCP client at them) |
npm run record-fixtures |
Re-record mock fixtures from live NSE (polite: 1 request at a time, 600 ms apart) |
npm run docs:examples |
Regenerate docs/EXAMPLES.md from web/src/lib/examples.ts |
npm run example:ts |
Run the TypeScript quickstart |
All configuration is via environment variables (optionally a .env file — see .env.example).
NSE needs no credentials. Defaults are tuned to be gentle on NSE: concurrency 2, ≥ 250 ms
between request starts per server, 60 s cache for identical successful calls, 20 s timeout.
shared/types.ts for everything crossing HTTP.tools/list; add metadata to shared/catalog.ts.shared/analytics.ts take plain data and never call NSE.status (success, soft-error, tool-error, protocol-error, validation-error). Recipes throw RecipeError (422 for NSE data errors, 502 for NSE unavailability).log.info/warn/error one line per event; silent under NODE_ENV=test. LOG_LEVEL=debug shows transport errors.@modelcontextprotocol/sdk, express, zod (SDK peer) and @anthropic-ai/sdk.NSE added a tool. The Explorer shows it immediately with the generic view and the dashboard warns.
Add a TOOL_CATALOG entry, run npm run record-fixtures, then npm test (the catalog tests list what’s out of sync).
Add an example. Append to EXAMPLES in web/src/lib/examples.ts, run npm run docs:examples.
tests/catalog.test.ts validates its arguments against the real schema.
Add an analytic. Write a pure function in shared/analytics.ts, test it in tests/analytics.test.ts, use it in a recipe or view.
mock/server.ts is a real MCP server (official SDK, stateful Streamable HTTP, same paths as NSE).
It replays mock/fixtures/nse-fixtures.json: exact-argument matches first, INVALID* symbols
produce NSE-style soft errors, anything else returns the first recording for that tool — so
in mock mode a different symbol can return another symbol’s data. Fixtures are NSE data and
remain subject to NSE’s terms.