Nanostores MCP

by Valyay

133 downloads Not rated yet

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

Explore

- 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

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.