droid-mode 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 GitMaxd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # Droid Mode
2
+
3
+ Progressive Code-Mode MCP integration for Factory.ai Droid.
4
+
5
+ Access MCP tools **without** loading them into your context window.
6
+
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## The Problem
10
+
11
+ When you configure MCP servers in Factory.ai Droid, all their tools get injected into the model's context window. This causes:
12
+
13
+ - **Token bloat** - Large tool inventories eat your context
14
+ - **Cognitive overload** - Too many tools confuse the model
15
+ - **No selectivity** - Can't use just the tools you need
16
+
17
+ ## The Solution
18
+
19
+ Droid Mode lets you:
20
+
21
+ 1. Keep MCP servers `disabled: true` in `mcp.json` (they won't bloat context)
22
+ 2. Access them **on-demand** through progressive discovery
23
+ 3. Run procedural workflows that call MCP tools **outside** the LLM loop
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ npx droid-mode init
29
+ ```
30
+
31
+ This scaffolds the skill into `.factory/skills/droid-mode/`
32
+
33
+ ## Quick Start
34
+
35
+ ```bash
36
+ # 1. Discover available MCP servers
37
+ dm servers
38
+
39
+ # 2. List tools on a server
40
+ dm index --server context-repo
41
+
42
+ # 3. Search for relevant tools
43
+ dm search "collections" --server context-repo
44
+
45
+ # 4. Call a tool directly
46
+ dm call list_collections --server context-repo
47
+
48
+ # 5. Run a workflow
49
+ dm run --server context-repo \
50
+ --tools list_collections,get_document \
51
+ --workflow my-workflow.js
52
+ ```
53
+
54
+ ## Progressive Disclosure Model
55
+
56
+ | Level | Command | Purpose |
57
+ |-------|---------|---------|
58
+ | 1 | `dm servers` | Discover available MCP servers |
59
+ | 2 | `dm index --server X` | List tools on a server |
60
+ | 3 | `dm search "..." --server X` | Find relevant tools |
61
+ | 4 | `dm hydrate tool1 --server X` | Get full schemas |
62
+ | 5 | `dm run --server X ...` | Execute workflow |
63
+
64
+ ## Working with "Disabled" Servers
65
+
66
+ The key insight: `disabled: true` in `mcp.json` tells Droid "don't load these tools into context" - but Droid Mode can still access them directly!
67
+
68
+ ```json
69
+ // ~/.factory/mcp.json - Recommended setup
70
+ {
71
+ "mcpServers": {
72
+ "context-repo": {
73
+ "type": "stdio",
74
+ "command": "npx",
75
+ "args": ["-y", "context-repo-mcp"],
76
+ "disabled": true // ← Good! Keeps context clean
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ## Workflow Example
83
+
84
+ Create a workflow file:
85
+
86
+ ```javascript
87
+ // my-workflow.js
88
+ workflow = async () => {
89
+ const collections = await t.listCollections({})
90
+ log("Found", collections.length, "collections")
91
+
92
+ const docs = await t.listDocuments({})
93
+ return { collections, docs }
94
+ }
95
+ ```
96
+
97
+ Run it:
98
+
99
+ ```bash
100
+ dm run --server context-repo \
101
+ --tools list_collections,list_documents \
102
+ --workflow my-workflow.js
103
+ ```
104
+
105
+ ## Commands Reference
106
+
107
+ | Command | Description |
108
+ |---------|-------------|
109
+ | `dm servers` | List all available MCP servers |
110
+ | `dm index --server <name>` | List tools with required parameters |
111
+ | `dm search "<query>" --server <name>` | Search tools by keyword |
112
+ | `dm hydrate <tools...> --server <name>` | Get full schemas |
113
+ | `dm call <tool> --server <name>` | Call a tool directly |
114
+ | `dm run --workflow <file> --tools <a,b> --server <name>` | Execute workflow |
115
+ | `dm doctor --server <name>` | Diagnose connection |
116
+
117
+ ## Design Philosophy
118
+
119
+ > **Treat MCP as infrastructure, Skills as capability boundaries, and code as a reasoning amplifier — not as an authority.**
120
+
121
+ Inspired by [Cloudflare's Code Mode](https://blog.cloudflare.com/code-mode/) concept, adapted for Factory.ai's Skill architecture.
122
+
123
+ ## Requirements
124
+
125
+ - Node.js >= 18
126
+ - Factory.ai Droid CLI
127
+ - MCP servers configured in `~/.factory/mcp.json`
128
+
129
+ ## License
130
+
131
+ MIT
132
+
133
+ ## Author
134
+
135
+ [GitMaxd](https://github.com/Gitmaxd) · [@gitmaxd](https://x.com/gitmaxd)
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/cli.js ADDED
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import { defineCommand, runMain } from "citty";
5
+ import { copy, pathExists, ensureDir } from "fs-extra";
6
+ import { resolve, join, dirname } from "path";
7
+ import { fileURLToPath } from "url";
8
+ import { stat } from "fs/promises";
9
+ var __dirname = dirname(fileURLToPath(import.meta.url));
10
+ var init = defineCommand({
11
+ meta: {
12
+ name: "init",
13
+ description: "Initialize Droid Mode skill in your project"
14
+ },
15
+ args: {
16
+ force: {
17
+ type: "boolean",
18
+ description: "Skip existing file checks (still never overwrites)",
19
+ default: false
20
+ },
21
+ path: {
22
+ type: "string",
23
+ description: "Target directory (defaults to current directory)",
24
+ default: "."
25
+ }
26
+ },
27
+ async run({ args }) {
28
+ const targetDir = resolve(args.path);
29
+ const skillDir = join(targetDir, ".factory", "skills", "droid-mode");
30
+ const templatesDir = resolve(__dirname, "..", "templates", "skills", "droid-mode");
31
+ console.log("\n\u{1F916} Droid Mode Initializer\n");
32
+ if (!await pathExists(templatesDir)) {
33
+ console.error("\u274C Templates directory not found. Package may be corrupted.");
34
+ process.exit(1);
35
+ }
36
+ if (await pathExists(skillDir)) {
37
+ console.log("\u26A0\uFE0F .factory/skills/droid-mode already exists");
38
+ console.log(" Scaffolding new files only (existing files will NOT be overwritten)\n");
39
+ }
40
+ await ensureDir(skillDir);
41
+ let copied = 0;
42
+ let skipped = 0;
43
+ try {
44
+ await copy(templatesDir, skillDir, {
45
+ overwrite: false,
46
+ errorOnExist: false,
47
+ filter: async (src, dest) => {
48
+ const srcStat = await stat(src);
49
+ if (srcStat.isDirectory()) {
50
+ return true;
51
+ }
52
+ if (await pathExists(dest)) {
53
+ const relativePath2 = dest.replace(targetDir, ".");
54
+ console.log(`\u23ED\uFE0F Skipped: ${relativePath2} (already exists)`);
55
+ skipped++;
56
+ return false;
57
+ }
58
+ const relativePath = dest.replace(targetDir, ".");
59
+ console.log(`\u2705 Created: ${relativePath}`);
60
+ copied++;
61
+ return true;
62
+ }
63
+ });
64
+ } catch (error) {
65
+ console.error("\u274C Error during scaffolding:", error);
66
+ process.exit(1);
67
+ }
68
+ console.log("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
69
+ console.log("\u2705 Droid Mode initialized successfully!");
70
+ console.log(` \u{1F4C1} Files created: ${copied}`);
71
+ console.log(` \u23ED\uFE0F Files skipped: ${skipped}`);
72
+ console.log("\n\u{1F4D6} Quick Start:");
73
+ console.log(" dm servers # Discover MCP servers");
74
+ console.log(" dm index --server <name> # List tools");
75
+ console.log(' dm search "query" --server <name>');
76
+ console.log(" dm run --server <name> --tools <a,b> --workflow file.js");
77
+ console.log('\n\u{1F4A1} Tip: Keep MCP servers "disabled: true" in mcp.json');
78
+ console.log(" Droid Mode accesses them directly without context bloat!\n");
79
+ }
80
+ });
81
+ var main = defineCommand({
82
+ meta: {
83
+ name: "droid-mode",
84
+ version: "0.1.0",
85
+ description: "Progressive Code-Mode MCP integration for Factory.ai Droid"
86
+ },
87
+ subCommands: {
88
+ init
89
+ },
90
+ async run() {
91
+ console.log("\n\u{1F916} Droid Mode - Progressive MCP for AI Agents\n");
92
+ console.log("Usage:");
93
+ console.log(" droid-mode init [options] Initialize Droid Mode in your project");
94
+ console.log(" droid-mode --help Show help");
95
+ console.log(" droid-mode --version Show version\n");
96
+ console.log("Quick start:");
97
+ console.log(" npx droid-mode init\n");
98
+ console.log("What is Droid Mode?");
99
+ console.log(" Access MCP tools without loading them into context.");
100
+ console.log(" Progressive discovery: servers \u2192 tools \u2192 schemas \u2192 execute\n");
101
+ }
102
+ });
103
+ runMain(main);
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "droid-mode",
3
+ "version": "0.0.1",
4
+ "description": "Progressive Code-Mode MCP integration for Factory.ai Droid - access MCP tools without context bloat",
5
+ "type": "module",
6
+ "main": "dist/cli.js",
7
+ "bin": {
8
+ "droid-mode": "./dist/cli.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "templates"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsup",
16
+ "dev": "tsup --watch",
17
+ "prepublishOnly": "npm run build",
18
+ "typecheck": "tsc --noEmit"
19
+ },
20
+ "keywords": [
21
+ "droid-mode",
22
+ "factory.ai",
23
+ "mcp",
24
+ "model-context-protocol",
25
+ "cli",
26
+ "ai-agents",
27
+ "progressive-disclosure"
28
+ ],
29
+ "author": {
30
+ "name": "GitMaxd",
31
+ "url": "https://github.com/Gitmaxd"
32
+ },
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/Gitmaxd/droid-mode.git"
37
+ },
38
+ "engines": {
39
+ "node": ">=18"
40
+ },
41
+ "dependencies": {
42
+ "citty": "^0.1.6",
43
+ "fs-extra": "^11.3.3"
44
+ },
45
+ "devDependencies": {
46
+ "@types/fs-extra": "^11.0.4",
47
+ "@types/node": "^22.0.0",
48
+ "tsup": "^8.5.1",
49
+ "typescript": "^5.7.0"
50
+ }
51
+ }
@@ -0,0 +1,237 @@
1
+ ---
2
+ name: droid-mode
3
+ description: Progressive Code‑Mode MCP integration for Factory Droid. Discover tools incrementally, hydrate schemas on demand, and run procedural workflows that call MCP tools outside the LLM loop.
4
+ ---
5
+
6
+ # Droid Mode (Progressive Code‑Mode MCP Skill)
7
+
8
+ This skill implements the **PRD “Droid Mode”** pattern: treat MCP as backend infrastructure and use **local scripts** to perform **progressive tool discovery + schema hydration + procedural orchestration**.
9
+
10
+ Instead of injecting a full MCP tool inventory into the model context, Droid uses these scripts to:
11
+
12
+ 1. **Index** tools (compact list)
13
+ 2. **Search** tools (narrow candidates)
14
+ 3. **Hydrate** schemas (only for selected tools)
15
+ 4. **Run** a procedural workflow that calls MCP tools **outside** the LLM loop
16
+
17
+ Everything is **auditable**: caches, hydrated schemas, and workflow traces are written to `.factory/droid-mode/` (project) or `~/.factory/droid-mode/` (fallback).
18
+
19
+ ---
20
+
21
+ ## When to use this skill
22
+
23
+ Use this skill when you want any of the following:
24
+
25
+ - MCP servers with **many tools**, or rapidly changing inventories
26
+ - **Token efficiency** (avoid dumping schemas into prompt context)
27
+ - **Procedural** workflows (filter/join/iterate locally between tool calls)
28
+ - **Auditability** (explicit scripts + saved artifacts)
29
+
30
+ ---
31
+
32
+ ## Installation
33
+
34
+ ### Option A — Project skill (recommended for teams)
35
+
36
+ Copy this directory to:
37
+
38
+ - `<repo>/.factory/skills/droid-mode/`
39
+
40
+ Then call it from the repo root:
41
+
42
+ ```bash
43
+ ./.factory/skills/droid-mode/bin/dm --help
44
+ ```
45
+
46
+ ### Option B — User skill (personal)
47
+
48
+ Copy to:
49
+
50
+ - `~/.factory/skills/droid-mode/`
51
+
52
+ Then call it via absolute path:
53
+
54
+ ```bash
55
+ ~/.factory/skills/droid-mode/bin/dm --help
56
+ ```
57
+
58
+ ---
59
+
60
+ ## MCP server configuration
61
+
62
+ This skill can connect to an MCP server in two ways:
63
+
64
+ 1. **Auto-detect from Droid’s `mcp.json`** (preferred)
65
+ - Project: `.factory/mcp.json`
66
+ - User: `~/.factory/mcp.json` (overrides project server entries)
67
+
68
+ 2. **Explicit CLI flags** (useful in CI or quick experiments)
69
+
70
+ Supported overrides:
71
+ - `--http-url <url>` with optional `--headers-json '{"Authorization":"Bearer ..."}'`
72
+ - `--stdio-command <cmd>` with optional `--stdio-args "a,b,c"` and `--env-json '{"KEY":"VALUE"}'`
73
+
74
+ ### Recommended: configure ContextRepo as a stdio MCP server
75
+
76
+ If you use ContextRepo, the common approach is to run its MCP server locally (stdio) and let it talk to ContextRepo’s API using an API key.
77
+
78
+ Example (user-level config is preferred for secrets):
79
+
80
+ ```bash
81
+ droid mcp add contextrepo "npx -y context-repo-mcp" --env CONTEXTREPO_API_KEY=YOUR_KEY
82
+ ```
83
+
84
+ Notes:
85
+ - This skill intentionally **does not print** env values.
86
+ - It will also recognize `CONTEXT_REPO_API_KEY` and `CONTEXTREPO_TOKEN` if present.
87
+
88
+ ---
89
+
90
+ ## Progressive Disclosure Model
91
+
92
+ Droid-mode implements a four-level progressive disclosure model:
93
+
94
+ | Level | Command | Purpose |
95
+ |-------|---------|---------|
96
+ | 1 | `dm servers` | Discover available MCP servers |
97
+ | 2 | `dm index --server X` | List tools on a server |
98
+ | 3 | `dm hydrate tool1 tool2 --server X` | Get full schemas |
99
+ | 4 | `dm run --server X ...` | Execute workflow |
100
+
101
+ ### Working with "Disabled" Servers
102
+
103
+ Servers marked `disabled: true` in `mcp.json` are **fully available** to droid-mode. In fact, this is the recommended configuration:
104
+
105
+ - `disabled: true` tells Droid: "Don't load this server's tools into context"
106
+ - droid-mode connects directly, bypassing context injection
107
+ - Result: Token-efficient, on-demand MCP access
108
+
109
+ ```json
110
+ // ~/.factory/mcp.json - Recommended setup
111
+ {
112
+ "mcpServers": {
113
+ "context-repo": {
114
+ "type": "stdio",
115
+ "command": "npx",
116
+ "args": ["-y", "context-repo-mcp"],
117
+ "disabled": true
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ This is the **entire point** of droid-mode: access MCP servers without bloating the context window.
124
+
125
+ ---
126
+
127
+ ## Commands
128
+
129
+ > All commands accept `--server <name>` to pick an MCP server from `mcp.json`.
130
+ > If only one server is configured, it's auto-selected. Otherwise, use `dm servers` to discover available servers.
131
+
132
+ ### 0) List servers (discover available MCP servers)
133
+
134
+ ```bash
135
+ ./.factory/skills/droid-mode/bin/dm servers
136
+ ```
137
+
138
+ Lists all MCP servers configured in `mcp.json` (both project and user level).
139
+ Servers with `disabled: true` are shown as "disabled (good!)" since they won't bloat Droid's context.
140
+
141
+ ### 1) Doctor (sanity check)
142
+
143
+ ```bash
144
+ ./.factory/skills/droid-mode/bin/dm doctor --server contextrepo
145
+ ```
146
+
147
+ Checks:
148
+ - Finds `mcp.json`
149
+ - Resolves the server entry (user overrides project)
150
+ - Attempts `initialize` + `tools/list` (unless `--no-connect`)
151
+
152
+ ### 2) Index tools (compact list)
153
+
154
+ ```bash
155
+ ./.factory/skills/droid-mode/bin/dm index --server contextrepo
156
+ ```
157
+
158
+ Outputs a compact table (name + short description).
159
+ Use `--json` to return structured output.
160
+
161
+ ### 3) Search tools (narrow candidate set)
162
+
163
+ ```bash
164
+ ./.factory/skills/droid-mode/bin/dm search "semantic search over docs" --limit 8 --server contextrepo
165
+ ```
166
+
167
+ This searches the cached index, refreshing if missing or stale.
168
+
169
+ ### 4) Hydrate tool schemas (small subset)
170
+
171
+ ```bash
172
+ ./.factory/skills/droid-mode/bin/dm hydrate search_documents get_document --server contextrepo
173
+ ```
174
+
175
+ Writes an “hydration bundle” to:
176
+
177
+ - `.factory/droid-mode/hydrated/<server>/<timestamp>/`
178
+
179
+ Contents:
180
+ - `tools.json` (full tool definitions for the subset)
181
+ - `types.d.ts` (best-effort TS types for inputs/outputs)
182
+ - `toolmap.json` (safe JS identifiers → tool names)
183
+
184
+ ### 5) Run a procedural workflow (“code-mode”)
185
+
186
+ Create a workflow file that defines `workflow = async () => { ... }`.
187
+
188
+ Example:
189
+
190
+ ```js
191
+ // workflow.js
192
+ workflow = async () => {
193
+ const docs = await t.searchDocuments({ query: "Droid Mode PRD", limit: 5 })
194
+ const full = await Promise.all(docs.results.map(d => t.getDocument({ id: d.id })))
195
+ return { count: full.length, ids: full.map(x => x.id) }
196
+ }
197
+ ```
198
+
199
+ Run it:
200
+
201
+ ```bash
202
+ ./.factory/skills/droid-mode/bin/dm run --server contextrepo --tools search_documents,get_document --workflow workflow.js
203
+ ```
204
+
205
+ The runner:
206
+ - Hydrates only the requested tools
207
+ - Executes your workflow in a restricted JS sandbox (no imports/require/fetch)
208
+ - Emits a JSON result + an execution trace
209
+
210
+ ---
211
+
212
+ ## Output & audit artifacts
213
+
214
+ Artifacts are written under `.factory/droid-mode/` (project) when possible:
215
+
216
+ - `cache/<server>/tools.json` — cached tool inventory
217
+ - `hydrated/<server>/<timestamp>/...` — schema bundles
218
+ - `runs/<server>/<timestamp>/run.json` — workflow result + trace
219
+
220
+ ---
221
+
222
+ ## Security posture (practical guardrails)
223
+
224
+ This skill is designed so that:
225
+
226
+ - Credentials remain in `mcp.json` env/headers (or your OS keyring), not in prompts.
227
+ - The workflow sandbox does **not** expose `require`, `import`, `process`, or `fetch`.
228
+ - Network access for workflows is mediated through the MCP server only.
229
+ - Every tool call is traced (tool name, args hash, duration, and error flag).
230
+
231
+ Optional: You can add a **PreToolUse hook** to block direct `mcp__*` tool calls and force use of this skill. See `examples/hooks/`.
232
+
233
+ ---
234
+
235
+ ## Design philosophy (north star)
236
+
237
+ Treat MCP as infrastructure. Treat Skills as capability boundaries. Treat code as a reasoning amplifier — not as authority.