trackmcp
Back to directory
Valyay

nanostores-mcp

View on GitHub

The MCP server for Nanostores that scans your codebase with AST analysis to find stores, subscribers, and dependency chains, and can ingest live events to spot noisy, error-prone, or unused stores.

1 stars TypeScriptOthers Updated Apr 21, 2026

Documentation

Nano Stores MCP

Model Context Protocol server for Nanostores β€” analyze, debug and monitor

your nanostores in AI assistants like Claude Desktop.

  • πŸ“Š 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
bash
npx nanostores-mcp

Ask your AI: _"Analyze my store architecture"_ or _"Which stores update most frequently?"_


Made at , product consulting for developer tools.


Table of Contents

Features

πŸ“Š Static Analysis (AST-based)

Understand your nanostores architecture without running your app:

  • Project scanning β€” find all stores, subscribers, and import/export relationships
  • Dependency graph β€” visualize how stores depend on each other (Mermaid diagrams)
  • Store inspection β€” type (atom/map/computed/batched/persistentAtom/persistentMap/router), location, usage patterns, related files
  • Framework-aware subscriber detection β€” recognizes `.subscribe()` / `.listen()` calls and component bindings across React, Vue, Svelte, and Angular
  • Vue SFC support β€” parses both `` and `` blocks in `.vue` files (requires `@vue/compiler-sfc`)
  • Svelte support β€” parses `` and instance `` blocks, auto-subscriptions (`$storeName` in templates), and filters out Svelte 5 runes (`$state`, `$derived`, `$effect`, etc.) so they are not mistaken for store references (requires `svelte`)
  • Angular DI support β€” resolves `@nanostores/angular` `NanostoresService` constructor injections and detects `this.nanostores.useStore(...)` call patterns in TypeScript component files

πŸ”₯ 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 from `nanostores` in your `node_modules` automatically

Requirements

RequirementVersion
Node.js`^20.0.0 \\>=22.0.0`

Required peer dependency (for static analysis):

bash
npm install nanostores

Optional peer dependencies β€” install only if you use the corresponding file format:

PackageWhen needed
`@vue/compiler-sfc`Vue SFC (`.vue`) file scanning
`svelte`Svelte (`.svelte`) file scanning
`@nanostores/logger`Runtime monitoring (`attachMcpLogger`)

Without these optional packages the server still works β€” it silently skips unsupported file types.

Installation

bash
npm install -g nanostores-mcp
# or
pnpm add -g nanostores-mcp

Or run directly without installation:

bash
npx nanostores-mcp

Configuration

Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

json
{
	"mcpServers": {
		"nanostores": {
			"command": "npx",
			"args": ["-y", "nanostores-mcp"],
			"env": {
				"NANOSTORES_MCP_ROOT": "/path/to/your/project"
			}
		}
	}
}

VS Code

Requires GitHub Copilot extension (VS Code 1.99+). Create `.vscode/mcp.json` in your project:

json
{
	"servers": {
		"nanostores": {
			"type": "stdio",
			"command": "npx",
			"args": ["-y", "nanostores-mcp"]
		}
	}
}

Tools are available in Copilot's Agent mode (select "Agent" in the Copilot Chat dropdown).

Cursor

Create `.cursor/mcp.json` in your project root (or `~/.cursor/mcp.json` for global):

json
{
	"mcpServers": {
		"nanostores": {
			"command": "npx",
			"args": ["-y", "nanostores-mcp"]
		}
	}
}

Zed

Add to your Zed `settings.json`:

json
{
	"context_servers": {
		"nanostores": {
			"command": "npx",
			"args": ["-y", "nanostores-mcp"],
			"env": {
				"NANOSTORES_MCP_ROOT": "/path/to/your/project"
			}
		}
	}
}

The server appears in Zed's Agent Panel settings.

Windsurf

Add to `~/.codeium/windsurf/mcp_config.json`:

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 Code

Add via CLI:

bash
claude mcp add --transport stdio nanostores -- npx -y nanostores-mcp

Or create `.mcp.json` in your project root (shared with the team):

json
{
	"mcpServers": {
		"nanostores": {
			"command": "npx",
			"args": ["-y", "nanostores-mcp"],
			"env": {
				"NANOSTORES_MCP_ROOT": "/path/to/your/project"
			}
		}
	}
}

Environment Variables

VariableDefaultDescription
`NANOSTORES_MCP_ROOT`cwdProject root path
`NANOSTORES_MCP_ROOTS`β€”Platform-delimited roots (`:` on Unix, `;` on Windows) for multi-project setup
`WORKSPACE_FOLDER`β€”Alias for `NANOSTORES_MCP_ROOT` β€” set automatically by VS Code and some editors
`WORKSPACE_FOLDER_PATHS`β€”Alias for `NANOSTORES_MCP_ROOTS` β€” set automatically by some editors
`NANOSTORES_MCP_LOGGER_ENABLED``true`Set to `false` or `0` to disable runtime event collection and the logger bridge
`NANOSTORES_MCP_LOGGER_PORT``3999`HTTP port for logger bridge
`NANOSTORES_MCP_LOGGER_HOST``127.0.0.1`Host to bind. Allowed values: `127.0.0.1`, `localhost`, `::1`
`NANOSTORES_DOCS_ROOT`auto-detectPath to documentation directory
`NANOSTORES_DOCS_PATTERNS``**/*.md`Comma-separated glob patterns for docs

How the Project Root Is Resolved

The server picks workspace roots in priority order:

1. Environment variables (highest priority) β€” `NANOSTORES_MCP_ROOTS` / `NANOSTORES_MCP_ROOT` / `WORKSPACE_FOLDER_PATHS` / `WORKSPACE_FOLDER`

2. Client roots β€” roots reported by the MCP client via the `roots/list` capability (set automatically by some editors)

3. Current working directory β€” `process.cwd()` used as fallback when neither env nor client roots are configured

When a tool is called without an explicit `projectRoot` argument the server uses the first configured root. In a multi-root setup always pass `projectRoot` to avoid ambiguity.

Quick Start

1. Static Analysis

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 from `nanostores` in your `node_modules`:

  • _"How do I use computed stores?"_
  • _"Show me the docs for persistentAtom"_

3. Runtime Monitoring (Optional)

Requires logger integration in your app. See Runtime Monitoring below.

  • _"Which stores update most frequently?"_
  • _"Show me recent activity for $user"_
  • _"Give me an overall health report"_

Verify Your Setup

Run these four tools in order to confirm everything is working:

code
nanostores_ping              β†’ should return server status and logger bridge state
nanostores_scan_project      β†’ should list your stores and subscribers
nanostores_docs_search       β†’ should return documentation results (requires nanostores in node_modules)
nanostores_runtime_overview  β†’ should return overview (or "no runtime data" if logger is disabled β€” that's fine)

If `nanostores_scan_project` returns zero stores, check that `NANOSTORES_MCP_ROOT` points to the correct project directory.

MCP Interface

MCP Resources

ResourceDescription
`nanostores://graph`Full dependency graph (text + Mermaid)
`nanostores://store/{key}`Store details by name or id
`nanostores://docs`Documentation index β€” all pages and tags
`nanostores://docs/page/{id}`Full content of a documentation page

MCP Tools

Static Analysis

ToolDescription
`nanostores_scan_project`Scan project for all stores, subscribers, and dependencies
`nanostores_store_summary`Detailed summary of a specific store
`nanostores_project_outline`High-level overview: store kinds, top directories, hub stores
`nanostores_store_subgraph`BFS-expanded dependency neighborhood of a store
`nanostores_store_impact`Downstream causal chain β€” what recomputes/re-renders if X changes

Runtime Monitoring

ToolDescription
`nanostores_runtime_overview`Overall health report with statistics for all stores
`nanostores_store_activity`Activity timeline for a specific store (filterable by kind/action)
`nanostores_find_noisy_stores`Identify stores with high change frequency or error rates
`nanostores_runtime_coverage`Compare static graph with runtime events to find coverage gaps

Documentation

ToolDescription
`nanostores_docs_search`Search docs by `query` (full-text), `storeKind` (atom, map, computed, persistentAtom, etc.), or both. Optional: `limit` (default 10), `tags`

Use `nanostores://docs/page/{id}` resource to read the full content of pages returned by search.

Utilities

ToolDescription
`nanostores_ping`Server health check and logger bridge status
`nanostores_clear_cache`Clear project index cache to force rescan

MCP Prompts

PromptParametersDescription
`explain-project``focus` _(optional)_AI-guided explanation of your project's store architecture. `focus` narrows to a feature/domain (e.g. `"cart"`, `"auth"`)
`explain-store``store_name` _(required)_Deep dive into a specific store's implementation and usage
`debug-store``store_name` _(required)_Comprehensive analysis combining static + runtime data
`debug-project-activity`β€”Project-wide performance analysis and optimization
`docs-how-to``task` _(required)_Step-by-step guidance for a Nanostores task, backed by docs (e.g. `"How do I sync a map store to localStorage?"`)

Advanced Tool Arguments

Most tools accept these optional arguments that significantly change their behavior:

ArgumentTypeUsed inDescription
`storeId``string``store_summary`, `store_subgraph`, `store_impact`Exact store identifier β€” format: `store:src/stores.ts#$counterName`. Takes priority over `name` when both are provided.
`name``string``store_summary`, `store_subgraph`, `store_impact`Store name (e.g. `"$user"`). Used when `storeId` is not provided.
`radius``number` (0–10, default `2`)`nanostores_store_subgraph`BFS hops around the store. `1` = direct deps only; `2` = deps of deps. Warning: on highly-connected hub stores (hub score > 5) radius β‰₯ 2 may return most of the project β€” start with `1`.
`projectRoot``string`most toolsWhich project root to analyze in multi-root setups. Omit to use the first configured root. Always specify this in multi-root projects.
`windowMs``number``store_activity`, `find_noisy_stores`, `runtime_overview`Look-back window in milliseconds (e.g. `60000` = last 60 s). Filters events to that time range.
`kinds``string[]``nanostores_store_activity`Filter events by type. Values: `"mount"`, `"unmount"`, `"change"`, `"action-start"`, `"action-end"`, `"action-error"`.
`actionName``string``nanostores_store_activity`Filter events to a specific action (e.g. `"increment"`).
`compact``boolean``scan_project`, `find_noisy_stores`, `runtime_overview`Return a compressed token-efficient table instead of full text. Useful for large projects to reduce context usage.

Runtime Monitoring

For runtime analysis, integrate the MCP Logger client into your application.

1. Install in your app and enable the logger bridge:

bash
npm install nanostores-mcp

The logger bridge starts automatically β€” no extra config needed. To disable it, set `NANOSTORES_MCP_LOGGER_ENABLED=false` in your MCP server config.

2. Define stores with logger attached (`src/stores.ts`):

typescript
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.

4. Ask your AI assistant:

  • _"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`

Logger Options

typescript
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;
	},
});

Flush Before Shutdown

typescript
import { getMcpLogger } from "nanostores-mcp/mcpLogger";

window.addEventListener("beforeunload", async () => {
	await getMcpLogger()?.forceFlush();
});

Reading Results

`nanostores_runtime_overview` health 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 with `action-error` events. High error counts indicate failing async actions.
  • Unmounted stores β€” stores seen at mount but never unmounted. May indicate memory leaks.

`nanostores_runtime_coverage`

Compares your static store graph against observed runtime events:

TermMeaning
static-onlyStore found by AST scan but no runtime events observed. Possible dead code, deferred initialization, or missing `attachMcpLogger` call.
runtime-onlyEvents received for a store not found by the scanner. Common for dynamically-created stores, factory patterns, or stores in `node_modules`.
Coverage by kindE.g. `atom: 3/5 (60%)` β€” 3 out of 5 atom stores received runtime events. 0% for a kind usually means `attachMcpLogger` was not called for those stores.

`nanostores_find_noisy_stores`

Returns stores ranked by total activity (changes + actions combined) within the `windowMs` period. 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.

Privacy & Security

The runtime logger is designed to stay on your local machine:

  • Loopback-only binding β€” the HTTP bridge accepts connections exclusively from `127.0.0.1`, `localhost`, or `::1`. Binding to `0.0.0.0` is 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 β€” use `maskEvent` to filter or redact events client-side before they are batched and sent:
typescript
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.

Example Queries

Ask your AI assistant natural language questions:

Static Analysis:

  • _"Analyze my store architecture for potential issues"_
  • _"What happens when $user changes? Show subscribers and derived stores"_

Runtime Debugging:

  • _"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"_

**With Playwright MCP:**

  • _"Open my app in the browser, interact with it, and analyze which stores cause the most recalculations"_

Documentation:

  • _"How do I use computed stores?"_
  • _"Show me best practices for persistent stores"_

Architecture

code
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   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, …) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Limitations & Caveats

Multi-root: same store name in multiple projects

In multi-root mode a store named `$user` can 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 specify `projectRoot` when 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 in `node_modules` will 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-sfc` or `svelte` are not installed, `.vue` / `.svelte` files 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 use `windowMs` to narrow your queries to recent data, or lower `batchMs` in `initMcpLogger` to deliver events more frequently and reduce the chance of buffer overflow during bursts.

`radius` on hub stores can be very large

Stores with many dependencies (hub score > 5) can return most of the project graph at `radius=2`. Start with `radius=1` and increase only if you need broader context.

Development

bash
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

Troubleshooting

Logger not receiving events:

1. Use the `ping` tool to verify logger bridge is enabled and running

2. Check browser console for `[nanostores-mcp]` warnings about connection issues

3. Confirm the port matches between server (`NANOSTORES_MCP_LOGGER_PORT`) and client URL

4. Test with a simple atom store to verify events flow

Port conflicts:

bash
# Change server port
NANOSTORES_MCP_LOGGER_PORT=4000 npx nanostores-mcp

# Update client
initMcpLogger({ url: "http://127.0.0.1:4000/nanostores-logger" });

TypeScript errors:

typescript
// Import from the mcpLogger subpath export
import { initMcpLogger, attachMcpLogger } from "nanostores-mcp/mcpLogger";

Documentation not found:

  • The server auto-detects docs from `nanostores` in your `node_modules`
  • Make sure `nanostores` is installed: `npm install nanostores`
  • Or set `NANOSTORES_DOCS_ROOT` to point at a docs directory manually

Nanostores ecosystem:

MCP:

License

MIT

Contributing

Contributions are welcome! Please open an issue or PR.

Frequently asked questions

What is nanostores-mcp?

nanostores-mcp is The MCP server for Nanostores that scans your codebase with AST analysis to find stores, subscribers, and dependency chains, and can ingest live events to spot noisy, error-prone, or unused stores.

How do I install nanostores-mcp?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is nanostores-mcp open source?

Yes β€” it is hosted on GitHub at https://github.com/Valyay/nanostores-mcp and has 1 stars.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP