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 +21 -0
- package/README.md +135 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +103 -0
- package/package.json +51 -0
- package/templates/skills/droid-mode/SKILL.md +237 -0
- package/templates/skills/droid-mode/bin/dm +424 -0
- package/templates/skills/droid-mode/examples/hooks/README.md +13 -0
- package/templates/skills/droid-mode/examples/workflows/workflow.example.js +21 -0
- package/templates/skills/droid-mode/lib/config.mjs +135 -0
- package/templates/skills/droid-mode/lib/hydrate.mjs +164 -0
- package/templates/skills/droid-mode/lib/mcp_client.mjs +175 -0
- package/templates/skills/droid-mode/lib/mcp_http.mjs +132 -0
- package/templates/skills/droid-mode/lib/mcp_stdio.mjs +152 -0
- package/templates/skills/droid-mode/lib/run.mjs +213 -0
- package/templates/skills/droid-mode/lib/search.mjs +67 -0
- package/templates/skills/droid-mode/lib/tool_index.mjs +89 -0
- package/templates/skills/droid-mode/lib/util.mjs +160 -0
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
|
+
[](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
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.
|