npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

droid-mode

v1.0.0

Published

Progressive Code-Mode MCP integration for Factory.ai Droid - access MCP tools without context bloat

Readme

Progressive MCP for AI Agents. Zero Context Bloat.

npm version License: MIT Node.js Status

Access MCP tools on-demand without loading schemas into your context window.

Quick Start · Architecture · Benchmarks · Commands


A Personal Note

I spend most of my time in Factory.ai's Droid CLI, and I'm a big believer in MCP - it's the right abstraction for giving AI agents access to external tools. But I kept bumping into an interesting constraint. Every MCP server adds its tool schemas to the context window, which means adding servers costs tokens whether you use those tools or not. I wanted ten servers available; I didn't want to pay for ten servers in every prompt. This seemed like a solvable inefficiency, and I was curious enough to dig in.

Droid Mode is what emerged: a Skill that provides daemon-backed MCP access with progressive disclosure. Built on 28 years of Linux system administration experience, it treats MCP servers as infrastructure - persistent connections, lazy schema loading, code-mode execution outside the context window. The result is zero token overhead and 13% better latency than native MCP. Per-project daemon isolation handles governance, and everything is traced for accountability. It's experimental research software, but I've tested it thoroughly and use it daily. I'm sharing it as an early AI explorer who believes we're just scratching the surface of what performant agent architectures can look like.

- GitMaxd


The Problem

When you configure MCP servers, all tool definitions are loaded into your context window at startup (source). This is standard behavior for MCP clients - the model needs to "see" available tools to use them. The result is a compounding cost:

| Configuration | Token Overhead | Impact | |---------------|----------------|--------| | 1 server (22 tools) | ~2,400 tokens | Acceptable | | 3 servers (~60 tools) | ~7,200 tokens | Noticeable | | 5 servers (~100 tools) | ~12,000 tokens | Significant |

Those tokens are consumed before your agent writes a single line. On an 8K context window, a single server claims ~30% of your budget; five servers would exceed it entirely. Even on 200K windows, ~12,000 tokens represents ~6% overhead, and it compounds across every message in a conversation.

The Solution

Droid Mode introduces progressive disclosure for MCP tools:

  1. Discover: List available servers (dm servers) - ~10 tokens
  2. Index: Browse tool names and descriptions (dm index) - ~50 tokens
  3. Hydrate: Load full schemas only when needed (dm hydrate) - zero tokens
  4. Execute: Run tools via daemon or workflow (dm call, dm run) - zero tokens

Code-Mode Execution: Steps 3-4 run as shell commands, not LLM tool calls. The LLM never sees the schemas or results unless you explicitly include them. This is why token cost is zero: operations happen outside the context window entirely.

Key Insight: Servers with disabled: true in mcp.json are fully accessible to Droid Mode. The disabled flag tells Factory.ai Droid "don't inject these tools into context", but Droid Mode connects directly, bypassing context injection entirely.

Token Efficiency

| Scenario | Native MCP | Droid Mode | Savings | |----------|------------|------------|---------| | 3 tools used | ~330 tokens | 0 tokens | 100% | | 10 tools | ~1,100 tokens | 0 tokens | 100% | | 22 tools (full server) | ~2,400 tokens | 0 tokens | 100% | | 5 servers (~100 tools) | ~12,000 tokens | 0 tokens | 100% |

Tools are loaded only when called. Your context window stays clean.


Architecture

Droid Mode uses a daemon architecture to maintain persistent MCP connections, eliminating the overhead of spawning new processes for each tool call.

flowchart LR
    A[AI Agent] --> B[dm CLI]
    B --> C[Unix Socket]
    C --> D[Droid Mode Daemon]
    D --> E[Connection Pool]
    E --> F1[MCP Server 1]
    E --> F2[MCP Server 2]
    E --> F3[MCP Server N]

How the Daemon Works

| Component | Purpose | |-----------|---------| | Per-Project Sockets | Each project gets its own daemon at ~/.factory/run/dm-daemon-<hash>.sock | | Connection Pool | Lazy-initialized clients with automatic lifecycle management | | Auto-Warm | Pre-connects frequently used servers on daemon start | | Idle Pruning | Closes unused connections after 10 minutes (configurable) |

The daemon starts automatically on first dm call. Without it, each call spawns a fresh MCP process (~2.5s average). With the daemon, calls reuse pooled connections (~680ms average).

Multi-Project Isolation

When working across multiple projects, each project automatically gets its own daemon:

# Project A - starts daemon bound to Project A's config
cd ~/projects/frontend && dm daemon start
# Socket: ~/.factory/run/dm-daemon-a1b2c3d4.sock

# Project B - starts separate daemon with Project B's config  
cd ~/projects/backend && dm daemon start
# Socket: ~/.factory/run/dm-daemon-e5f6g7h8.sock

# List all running daemons
dm daemon status --all

This prevents configuration bleed between projects and ensures governance compliance when projects have different MCP server access policies.


Performance Benchmarks

Independent benchmarks comparing Droid Mode against native MCP (direct stdio).

| Configuration | Per-Tool Latency | 10-Tool Total | vs. Native | |---------------|------------------|---------------|------------| | Droid Mode (Daemon) | 678ms | 6.8s | 13% faster | | Native MCP | 777ms | 7.8s | baseline | | Droid Mode (No Daemon) | 2,488ms | 24.9s | 220% slower |

  • Hardware: macOS Darwin 25.2.0
  • MCP Server: Context Repo MCP (context-repo-mcp)
  • Protocol: MCP 2025-06-18
  • Runs: 5 iterations averaged
  • Date: January 2026

Single-tool breakdown (5 runs):

| Run | No Daemon | Daemon | Native MCP | |-----|-----------|--------|------------| | 1 | 2,948ms | 845ms | 866ms | | 2 | 2,442ms | 610ms | 789ms | | 3 | 2,300ms | 613ms | 798ms | | 4 | 2,415ms | 706ms | 742ms | | 5 | 2,334ms | 617ms | 690ms | | Avg | 2,488ms | 678ms | 777ms |

Key finding: The daemon maintains persistent connections, beating native MCP by ~13% while eliminating all schema overhead from your context window.


Quick Start

# 1. Initialize Droid Mode in your project
npx droid-mode init
✓ Initialized successfully   12 files created

QUICK START
1. Discover MCP servers        dm servers
2. Hydrate a tool              dm hydrate <tool> --server <name>
3. Call the tool               dm call <tool> --server <name>
# 2. Discover available MCP servers
dm servers
MCP Servers (from ~/.factory/mcp.json)
┌─────────────────┬───────┬──────────────────┐
│ Name            │ Type  │ Status           │
├─────────────────┼───────┼──────────────────┤
│ context-repo    │ stdio │ disabled (good!) │
│ convex          │ stdio │ disabled (good!) │
└─────────────────┴───────┴──────────────────┘
# 3. Call a tool
dm call list_collections --server context-repo
{
  "collections": [
    { "id": "docs", "name": "Documentation", "count": 42 },
    { "id": "code", "name": "Code Samples", "count": 18 }
  ]
}

The daemon starts automatically on first call. For manual control:

dm daemon start    # Start daemon
dm daemon status   # Check connections
dm daemon stop     # Stop daemon

Progressive Disclosure Model

| Level | Command | What You Get | Token Cost | |-------|---------|--------------|------------| | 1 | dm servers | List of configured MCP servers | ~10 | | 2 | dm index --server X | Tool names, descriptions, required params | ~50 | | 3 | dm search "query" --server X | Filtered tools matching keyword | ~20 | | 4 | dm hydrate tool --server X | Full JSON schema + TypeScript types | on-demand | | 5 | dm call tool --server X | Execute tool directly (primary) | 0 | | 6 | dm run --workflow file.js --server X | Multi-tool workflow (advanced) | 0 |


Command Reference

Discovery

| Command | Description | |---------|-------------| | dm servers | List all MCP servers from mcp.json | | dm index --server <name> | List tools with required parameters | | dm search "<query>" --server <name> | Search tools by keyword | | dm hydrate <tools...> --server <name> | Get full schemas + generate TypeScript types |

Execution

| Command | Description | |---------|-------------| | dm call <tool> --server <name> | Primary: Call a single tool (interactive use) | | dm run --workflow <file> --tools <a,b> --server <name> | Advanced: Multi-tool workflow automation |

Daemon

| Command | Description | |---------|-------------| | dm daemon start | Start background daemon for current project | | dm daemon stop | Stop current project's daemon | | dm daemon status | Show current project's daemon status | | dm daemon status --all | List all running daemons across projects | | dm daemon list | Alias for status --all | | dm daemon warm [server] | Pre-warm server connection(s) | | dm call ... --no-daemon | Bypass daemon for single call |

Diagnostics

| Command | Description | |---------|-------------| | dm doctor --server <name> | Diagnose connection issues | | dm config <server> <key> <value> | Configure server settings |


Direct Tool Calls (Primary)

For most use cases, use dm call to execute tools directly:

# Hydrate once (caches schema)
dm hydrate list_collections --server context-repo

# Call directly - results returned as JSON
dm call list_collections --server context-repo
dm call list_collections --server context-repo --args '{"limit": 5}'

No workflow file needed. This is the preferred method for interactive use and single-tool operations.


Workflows (Advanced)

Note: Workflows are for multi-tool orchestration with loops, conditionals, or pre-programmed patterns. For simple single-tool calls, use dm call instead.

Workflows let you run procedural logic across multiple MCP tools in a sandboxed environment.

// my-workflow.js
workflow = async () => {
  const collections = await t.listCollections({})
  log("Found", collections.length, "collections")
  
  for (const col of collections.slice(0, 3)) {
    const docs = await t.listDocuments({ collection: col.id })
    log(`  ${col.name}: ${docs.length} documents`)
  }
  
  return { success: true, count: collections.length }
}
dm run --server context-repo \
  --tools list_collections,list_documents \
  --workflow my-workflow.js
Found 5 collections
  Documentation: 42 documents
  Code Samples: 18 documents
  Architecture: 7 documents

Workflow completed in 1.2s
Result: { success: true, count: 5 }
Trace: .factory/droid-mode/runs/context-repo/20260103T142531/run.json

Sandbox Security

Workflows execute in a restricted VM context:

  • Blocked: require, import, fetch, process, eval
  • Allowed: t.* (tool calls), log(), sleep(), assert()
  • Traced: Every tool call is logged with timing and result hash

Configuration

Recommended mcp.json Setup

{
  "mcpServers": {
    "context-repo": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "context-repo-mcp"],
      "disabled": true
    },
    "another-server": {
      "type": "stdio",
      "command": "node",
      "args": ["./path/to/server.js"],
      "disabled": true
    }
  }
}

Set "disabled": true for all MCP servers you want to access via Droid Mode. They remain fully functional, just not injected into your context window.

Configuration Locations

  • Project: .factory/mcp.json
  • User: ~/.factory/mcp.json (user config takes precedence)

For more information on Factory.ai Droid and MCP configuration, see the Factory.ai documentation.


Artifacts

All outputs are written to .factory/droid-mode/:

| Path | Contents | |------|----------| | cache/<server>/tools.json | Cached tool inventory | | hydrated/<server>/<timestamp>/schemas.json | Full JSON schemas | | hydrated/<server>/<timestamp>/types.d.ts | Generated TypeScript types | | runs/<server>/<timestamp>/run.json | Workflow execution trace |


Requirements & Limitations

Requirements

  • Node.js >= 18
  • Factory.ai Droid CLI
  • MCP servers configured in ~/.factory/mcp.json or .factory/mcp.json

Current Limitations

  • Windows: Daemon mode uses Unix sockets (/tmp/dm-daemon.sock). Windows support is not yet implemented.
  • HTTP Transport: Exists in code but documentation pending.
  • Hooks: PreToolUse hooks exist in examples/hooks/ but are not yet documented.

Recommended: AGENTS.md Snippet

For best results with AI agents, add this snippet to your project's AGENTS.md file (suggested location: after your Build & Test section):

## Droid Mode (MCP Tool Access)

Access MCP tools without context bloat. Hydrate schemas on-demand, call tools directly.

### Commands

```bash
# 1. Discover
dm servers
dm index --server <name>

# 2. Prepare (one-time per tool)
dm hydrate <tool> --server <name>

# 3. Execute (primary - direct call)
dm call <tool> --server <name>
dm call <tool> --server <name> --args '{"key": "value"}'

# 4. Advanced: Multi-tool workflows (for complex automation only)
dm run --server <name> --tools a,b --workflow file.js

Use dm call for everyday tool calls. Use dm run only for multi-tool orchestration.

Path Resolution

Try workspace first: ./.factory/skills/droid-mode/bin/dm Fallback to personal: ~/.factory/skills/droid-mode/bin/dm

Gotchas

  • Use dm call for single tools - Don't create workflow files for simple calls
  • Keep commands minimal - No timing, progress bars, or diagnostics unless requested
  • macOS compatibility - Avoid GNU-specific flags (date +%s%3N, sed -i, grep -P)
  • Disabled servers work - "disabled": true prevents context bloat but servers remain accessible

</details>

This helps AI agents use droid-mode correctly by documenting naming conventions, sandbox restrictions, and common pitfalls.

---

## Experimental Status

> **⚠️ This is experimental software (v0.0.x)**
>
> Droid Mode is under active development to improve MCP usability in Factory.ai Droid. The API may change between versions.
>
> **Feedback welcome!** Open an issue on GitHub or reach out on X.

---

## Design Philosophy

> Treat MCP as infrastructure, Skills as capability boundaries, and code as a reasoning amplifier, not as authority.

Inspired by [Cloudflare's Code Mode](https://blog.cloudflare.com/code-mode/) concept, adapted for Factory.ai's Skill architecture.

---

## License

MIT

## Author

[GitMaxd](https://github.com/Gitmaxd) · [@gitmaxd](https://x.com/gitmaxd)

---

<div align="center">

**[GitHub](https://github.com/Gitmaxd/droid-mode)** · **[npm](https://www.npmjs.com/package/droid-mode)** · **[Issues](https://github.com/Gitmaxd/droid-mode/issues)**

</div>