Nanostores MCP
About
MCP transforms the Nanostores state layer from a collection of disparate files into a clear dependency map - enabling LLM and you to understand the architecture and helps spend less time mapping out dependencies and more time on actual architectural solutions especially in large
Details
- Author
- Valyay
- Downloads
- 133
- Categories
- Developer Tools, Other
Jump to
- Transforms Nanostores state layer into a dependency map
- Enables LLM and human understanding of architecture
- Reduces time spent on mapping dependencies
- Helps focus on actual architectural solutions
- Especially useful for large codebases
—
- 📊 Static Analysis:AST-based project scanning, dependency graphs, store inspection
- 🔥 Runtime Monitoring:Live events from@nanostores/logger, performance metrics, activity tracking
- 📚 Documentation:Search and browse Nanostores docs by topic or store kind
- 🎯 Zero Config:Works out of the box — auto-detects project roots and nanostores docs
- 🌐 Framework-Agnostic:Works with React, Vue, Svelte, Angular, Solid, Preact, Lit — any framework that uses Nanostores
Ask your AI:"Analyze my store architecture"or"Which stores update most frequently?"
Made atEvil Martians, product consulting fordeveloper tools.
- Features
- Requirements
- Installation
- Configuration
- Quick Start
- MCP Interface
- Resources
- Tools
- Advanced Tool Arguments
- Prompts
Understand your nanostores architecture without running your app:
🔥 Runtime Monitoring (Logger Integration)
Real-time insights into your running application:
- Live event capture— mount/unmount, value changes, action calls from@nanostores/logger
- Performance analysis— find noisy stores, high error rates, performance bottlenecks
- Activity metrics— change frequency, action success/failure rates, action duration
- Combined analysis— merge static structure with runtime behavior for deep debugging
Search and browse Nanostores documentation directly from your AI assistant:
- Full-text search— find guides, API references, and best practices by query
- Store-kind lookup— get docs relevant to a specific store type (atom, map, computed, etc.)
- Auto-detection— picks up docs fromnanostoresin yournode_modulesautomatically
Required peer dependency(for static analysis):
Optional peer dependencies— install only if you use the corresponding file format:
Without these optional packages the server still works — it silently skips unsupported file types.
npm install -g nanostores-mcp # or pnpm add -g nanostores-mcp
Add to~/Library/Application Support/Claude/claude_desktop_config.json(macOS) or%APPDATA%\Claude\claude_desktop_config.json(Windows):
{ "mcpServers": { "nanostores": { "command": "npx", "args": ["-y", "nanostores-mcp"], "env": { "NANOSTORES_MCP_ROOT": "/path/to/your/project" } } } }
RequiresGitHub Copilotextension (VS Code 1.99+). Create.vscode/mcp.jsonin your project:
{ "servers": { "nanostores": { "type": "stdio", "command": "npx", "args": ["-y", "nanostores-mcp"] } } }
Tools are available in Copilot'sAgent mode(select "Agent" in the Copilot Chat dropdown).
Create.cursor/mcp.jsonin your project root (or~/.cursor/mcp.jsonfor global):
{ "mcpServers": { "nanostores": { "command": "npx", "args": ["-y", "nanostores-mcp"] } } }
{ "context_servers": { "nanostores": { "command": "npx", "args": ["-y", "nanostores-mcp"], "env": { "NANOSTORES_MCP_ROOT": "/path/to/your/project" } } } }
The server appears in Zed'sAgent Panelsettings.
Add to~/.codeium/windsurf/mcp_config.json:
{ "mcpServers": { "nanostores": { "command": "npx", "args": ["-y", "nanostores-mcp"], "env": { "NANOSTORES_MCP_ROOT": "/path/to/your/project" } } } }
You can also open this file from the MCP icon in the Cascade panel → "Configure".
claude mcp add --transport stdio nanostores -- npx -y nanostores-mcp
Or create.mcp.jsonin your project root (shared with the team):
{ "mcpServers": { "nanostores": { "command": "npx", "args": ["-y", "nanostores-mcp"], "env": { "NANOSTORES_MCP_ROOT": "/path/to/your/project" } } } }
The server picks workspace roots in priority order:
- Environment variables(highest priority) —NANOSTORES_MCP_ROOTS/NANOSTORES_MCP_ROOT/WORKSPACE_FOLDER_PATHS/WORKSPACE_FOLDER
- Client roots— roots reported by the MCP client via theroots/listcapability (set automatically by some editors)
- Current working directory—process.cwd()used as fallback when neither env nor client roots are configured
When a tool is called without an explicitprojectRootargument the server uses thefirst configured root. In a multi-root setup always passprojectRootto avoid ambiguity.
Works out of the box — just point at your project and ask:
- "Analyze my store architecture"
- "Explain how nanostores is used in this project"
- "Give me a summary of the $cart store"
- "My stores changed — re-scan the project"← the AI will force a fresh scan
Auto-detected fromnanostoresin yournode_modules:
- "How do I use computed stores?"
- "Show me the docs for persistentAtom"
Requires logger integration in your app. SeeRuntime Monitoringbelow.
- "Which stores update most frequently?"
- "Show me recent activity for $user"
- "Give me an overall health report"
Run these four tools in order to confirm everything is working:
Ifnanostores_scan_projectreturns zero stores, check thatNANOSTORES_MCP_ROOTpoints to the correct project directory.
Usenanostores://docs/page/{id}resource to read the full content of pages returned by search.
Most tools accept these optional arguments that significantly change their behavior:
For runtime analysis, integrate the MCP Logger client into your application.
1. Install in your app and enable the logger bridge:
The logger bridge starts automatically — no extra config needed. To disable it, setNANOSTORES_MCP_LOGGER_ENABLED=falsein your MCP server config.
2. Define stores with logger attached(src/stores.ts):
import { atom, map, computed } from "nanostores"; import { initMcpLogger, attachMcpLogger } from "nanostores-mcp/mcpLogger"; // Automatically disabled in production (checks NODE_ENV / import.meta.env.DEV) initMcpLogger(); // Stores export const $count = atom(0); export const $user = map({ name: "", role: "guest" }); export const $greeting = computed($user, user => Hello, ${user.name}); // Attach logger — each call returns a cleanup function attachMcpLogger($count, "$count"); attachMcpLogger($user, "$user"); attachMcpLogger($greeting, "$greeting");
3. Use stores normally— events (mount, unmount, change, actions) are captured automatically and batched to the MCP server every second.
- "Which stores change most frequently?"→nanostores_find_noisy_stores
- "Show me recent activity for $user"→nanostores_store_activity
- "Give me an overall health report"→nanostores_runtime_overview
initMcpLogger({ url: "http://127.0.0.1:3999/nanostores-logger", // default; change if using a custom port batchMs: 1000, // default; lower for faster delivery (e.g. 200) projectRoot: "/absolute/path/to/project", // link runtime events with static analysis // Mask sensitive data — return null to skip event entirely maskEvent: event => { if (event.storeName === "authToken") return null; return event; }, });
import { getMcpLogger } from "nanostores-mcp/mcpLogger"; window.addEventListener("beforeunload", async () => { await getMcpLogger()?.forceFlush(); });
nanostores_runtime_overviewhealth summary
The overview groups stores into three categories:
- Top active stores— sorted by total event count (changes + actions). A store that appears here with hundreds of changes in seconds may be a performance concern.
- Error-prone stores— stores withaction-errorevents. High error counts indicate failing async actions.
- Unmounted stores— stores seen at mount but never unmounted. May indicate memory leaks.
Compares your static store graph against observed runtime events:
Returns stores ranked by total activity (changes + actions combined) within thewindowMsperiod. A store is considered "noisy" when its change frequency is disproportionately high relative to visible UI updates — use this to find re-render hotspots or thrashing computed chains.
The runtime logger is designed to stay on your local machine:
- Loopback-only binding— the HTTP bridge accepts connections exclusively from127.0.0.1,localhost, or::1. Binding to0.0.0.0is explicitly blocked. Data never leaves your machine.
- What is transmitted— from your app to the MCP server over localhost: store name, timestamp, event kind, and optionally value snapshots (truncated to 200 characters). Nothing is sent to Anthropic or any third party.
- Nothing is persisted— events are held in a ring buffer (5 000 events max) in process memory and discarded when the server restarts.
- Mask sensitive data— usemaskEventto filter or redact events client-side before they are batched and sent:
initMcpLogger({ maskEvent: event => { if (event.storeName === "$authToken") return null; // drop entirely if (event.storeName === "$paymentInfo") return { ...event, newValue: undefined }; // strip value return event; }, });
- CORS— the bridge rejects cross-origin requests from non-loopback origins.
Ask your AI assistant natural language questions:
- "Which stores update most frequently?"
- "Are there stores declared in code but never used at runtime?"
- "Debug the $user store — combine static analysis with runtime behavior"
- "Open my app in the browser, interact with it, and analyze which stores cause the most recalculations"
- "How do I use computed stores?"
- "Show me best practices for persistent stores"
┌──────────────────────┐ │ Your Application │ │ │ │ @nanostores/logger │ │ events │ └──────────┬───────────┘ │ HTTP POST (localhost:3999) ▼ ┌──────────────────────┐ │ nanostores-mcp │ │ │ │ ┌──────────────┐ │ │ │ Logger Bridge │ │ ← HTTP server for runtime events │ └──────┬───────┘ │ │ ▼ │ │ ┌──────────────┐ │ │ │ Event Store │ │ ← Ring buffer (5000 events) + stats │ └──────┬───────┘ │ │ │ │ │ ┌──────┴───────┐ │ │ │ AST Scanner │ │ ← ts-morph static analysis │ └──────┬───────┘ │ │ │ │ │ ┌──────┴───────┐ │ │ │ Docs Index │ │ ← Auto-detected from node_modules │ └──────┬───────┘ │ │ │ │ │ ┌──────┴───────┐ │ │ │ MCP Interface│ │ ← Resources, Tools, Prompts │ └──────────────┘ │ └──────────┬───────────┘ │ MCP Protocol (stdio) ▼ ┌──────────────────────┐ │ LLM Client │ │ (Claude, VS Code, …) │ └──────────────────────┘
Multi-root: same store name in multiple projects
In multi-root mode a store named$usercan exist in two different projects. The runtime event store uses a composite key (projectRoot + storeName) to keep them separate, but summary views may show the same name twice with no project label. Always specifyprojectRootwhen querying tools in a multi-root setup to get unambiguous results.
Static analysis only covers discovered files
The AST scanner follows TypeScript/JavaScript imports from your project root. Stores created dynamically at runtime, generated by factories, or living innode_moduleswill not appear in static results — they may show up as "runtime-only" in coverage reports.
Vue and Svelte parsing requires optional dependencies
If@vue/compiler-sfcorsvelteare not installed,.vue/.sveltefiles are silently skipped during scanning. Install them as dev dependencies if you want full coverage for those file types.
Event ring buffer is capped at 5 000 events
Older events are dropped when the buffer is full. For high-frequency stores usewindowMsto narrow your queries to recent data, or lowerbatchMsininitMcpLoggerto deliver events more frequently and reduce the chance of buffer overflow during bursts.
Stores with many dependencies (hub score > 5) can return most of the project graph atradius=2. Start withradius=1and increase only if you need broader context.
git clone https://github.com/Valyay/nanostores-mcp.git cd nanostores-mcp pnpm install pnpm dev # Run dev server pnpm build # TypeScript compile pnpm test # Run vitest pnpm lint # ESLint pnpm check # All checks: lint + format + test + build # Test with MCP Inspector npx @modelcontextprotocol/inspector pnpm run dev
- Use thepingtool to verify logger bridge is enabled and running
- Check browser console for[nanostores-mcp]warnings about connection issues
- Confirm the port matches between server (NANOSTORES_MCP_LOGGER_PORT) and client URL
- Test with a simple atom store to verify events flow
# Change server port NANOSTORES_MCP_LOGGER_PORT=4000 npx nanostores-mcp # Update client initMcpLogger({ url: "http://127.0.0.1:4000/nanostores-logger" });
// Import from the mcpLogger subpath export import { initMcpLogger, attachMcpLogger } from "nanostores-mcp/mcpLogger";
- The server auto-detects docs fromnanostoresin yournode_modules
- Make surenanostoresis installed:npm install nanostores
- Or setNANOSTORES_DOCS_ROOTto point at a docs directory manually
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





