oh-my-claude-sisyphus 3.7.2 → 3.7.3
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/dist/__tests__/compatibility-security.test.d.ts +13 -0
- package/dist/__tests__/compatibility-security.test.d.ts.map +1 -0
- package/dist/__tests__/compatibility-security.test.js +403 -0
- package/dist/__tests__/compatibility-security.test.js.map +1 -0
- package/dist/__tests__/compatibility.test.d.ts +7 -0
- package/dist/__tests__/compatibility.test.d.ts.map +1 -0
- package/dist/__tests__/compatibility.test.js +484 -0
- package/dist/__tests__/compatibility.test.js.map +1 -0
- package/dist/__tests__/hud/analytics-display.test.js +4 -0
- package/dist/__tests__/hud/analytics-display.test.js.map +1 -1
- package/dist/cli/analytics.js +0 -0
- package/dist/cli/index.js +0 -0
- package/dist/compatibility/discovery.d.ts +58 -0
- package/dist/compatibility/discovery.d.ts.map +1 -0
- package/dist/compatibility/discovery.js +619 -0
- package/dist/compatibility/discovery.js.map +1 -0
- package/dist/compatibility/index.d.ts +51 -0
- package/dist/compatibility/index.d.ts.map +1 -0
- package/dist/compatibility/index.js +72 -0
- package/dist/compatibility/index.js.map +1 -0
- package/dist/compatibility/mcp-bridge.d.ts +138 -0
- package/dist/compatibility/mcp-bridge.d.ts.map +1 -0
- package/dist/compatibility/mcp-bridge.js +524 -0
- package/dist/compatibility/mcp-bridge.js.map +1 -0
- package/dist/compatibility/permission-adapter.d.ts +79 -0
- package/dist/compatibility/permission-adapter.d.ts.map +1 -0
- package/dist/compatibility/permission-adapter.js +369 -0
- package/dist/compatibility/permission-adapter.js.map +1 -0
- package/dist/compatibility/registry.d.ts +161 -0
- package/dist/compatibility/registry.d.ts.map +1 -0
- package/dist/compatibility/registry.js +389 -0
- package/dist/compatibility/registry.js.map +1 -0
- package/dist/compatibility/types.d.ts +249 -0
- package/dist/compatibility/types.d.ts.map +1 -0
- package/dist/compatibility/types.js +8 -0
- package/dist/compatibility/types.js.map +1 -0
- package/dist/features/rate-limit-wait/daemon.d.ts.map +1 -1
- package/dist/features/rate-limit-wait/daemon.js +3 -0
- package/dist/features/rate-limit-wait/daemon.js.map +1 -1
- package/dist/hud/analytics-display.d.ts +1 -1
- package/dist/hud/analytics-display.d.ts.map +1 -1
- package/dist/hud/analytics-display.js +24 -7
- package/dist/hud/analytics-display.js.map +1 -1
- package/docs/COMPATIBILITY.md +1051 -0
- package/package.json +3 -1
- package/dist/__tests__/analytics/analytics-summary.test.d.ts +0 -2
- package/dist/__tests__/analytics/analytics-summary.test.d.ts.map +0 -1
- package/dist/__tests__/analytics/analytics-summary.test.js +0 -267
- package/dist/__tests__/analytics/analytics-summary.test.js.map +0 -1
- package/dist/__tests__/analytics/cost-estimator.test.d.ts +0 -2
- package/dist/__tests__/analytics/cost-estimator.test.d.ts.map +0 -1
- package/dist/__tests__/analytics/cost-estimator.test.js +0 -212
- package/dist/__tests__/analytics/cost-estimator.test.js.map +0 -1
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts +0 -7
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts.map +0 -1
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js +0 -374
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js.map +0 -1
- package/dist/__tests__/hud/auto-tracking.integration.test.d.ts +0 -2
- package/dist/__tests__/hud/auto-tracking.integration.test.d.ts.map +0 -1
- package/dist/__tests__/hud/auto-tracking.integration.test.js +0 -12
- package/dist/__tests__/hud/auto-tracking.integration.test.js.map +0 -1
- package/dist/__tests__/learned-skills/config.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/config.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/config.test.js +0 -37
- package/dist/__tests__/learned-skills/config.test.js.map +0 -1
- package/dist/__tests__/learned-skills/detector.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/detector.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/detector.test.js +0 -99
- package/dist/__tests__/learned-skills/detector.test.js.map +0 -1
- package/dist/__tests__/learned-skills/finder.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/finder.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/finder.test.js +0 -59
- package/dist/__tests__/learned-skills/finder.test.js.map +0 -1
- package/dist/__tests__/learned-skills/loader.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/loader.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/loader.test.js +0 -69
- package/dist/__tests__/learned-skills/loader.test.js.map +0 -1
- package/dist/__tests__/learned-skills/parser.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/parser.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/parser.test.js +0 -81
- package/dist/__tests__/learned-skills/parser.test.js.map +0 -1
- package/dist/__tests__/learned-skills/validator.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/validator.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/validator.test.js +0 -85
- package/dist/__tests__/learned-skills/validator.test.js.map +0 -1
- package/dist/agents/codex-agents.d.ts +0 -20
- package/dist/agents/codex-agents.d.ts.map +0 -1
- package/dist/agents/codex-agents.js +0 -36
- package/dist/agents/codex-agents.js.map +0 -1
- package/dist/agents/document-writer.d.ts +0 -11
- package/dist/agents/document-writer.d.ts.map +0 -1
- package/dist/agents/document-writer.js +0 -209
- package/dist/agents/document-writer.js.map +0 -1
- package/dist/agents/frontend-engineer.d.ts +0 -11
- package/dist/agents/frontend-engineer.d.ts.map +0 -1
- package/dist/agents/frontend-engineer.js +0 -115
- package/dist/agents/frontend-engineer.js.map +0 -1
- package/dist/agents/librarian.d.ts +0 -12
- package/dist/agents/librarian.d.ts.map +0 -1
- package/dist/agents/librarian.js +0 -103
- package/dist/agents/librarian.js.map +0 -1
- package/dist/agents/metis.d.ts +0 -12
- package/dist/agents/metis.d.ts.map +0 -1
- package/dist/agents/metis.js +0 -117
- package/dist/agents/metis.js.map +0 -1
- package/dist/agents/momus.d.ts +0 -12
- package/dist/agents/momus.d.ts.map +0 -1
- package/dist/agents/momus.js +0 -128
- package/dist/agents/momus.js.map +0 -1
- package/dist/agents/multimodal-looker.d.ts +0 -11
- package/dist/agents/multimodal-looker.d.ts.map +0 -1
- package/dist/agents/multimodal-looker.js +0 -70
- package/dist/agents/multimodal-looker.js.map +0 -1
- package/dist/agents/oracle.d.ts +0 -13
- package/dist/agents/oracle.d.ts.map +0 -1
- package/dist/agents/oracle.js +0 -191
- package/dist/agents/oracle.js.map +0 -1
- package/dist/agents/orchestrator-sisyphus.d.ts +0 -11
- package/dist/agents/orchestrator-sisyphus.d.ts.map +0 -1
- package/dist/agents/orchestrator-sisyphus.js +0 -115
- package/dist/agents/orchestrator-sisyphus.js.map +0 -1
- package/dist/agents/prometheus.d.ts +0 -12
- package/dist/agents/prometheus.d.ts.map +0 -1
- package/dist/agents/prometheus.js +0 -195
- package/dist/agents/prometheus.js.map +0 -1
- package/dist/agents/sisyphus-junior.d.ts +0 -12
- package/dist/agents/sisyphus-junior.d.ts.map +0 -1
- package/dist/agents/sisyphus-junior.js +0 -93
- package/dist/agents/sisyphus-junior.js.map +0 -1
- package/dist/cli/components/CostDashboard.d.ts +0 -15
- package/dist/cli/components/CostDashboard.d.ts.map +0 -1
- package/dist/cli/components/CostDashboard.js +0 -15
- package/dist/cli/components/CostDashboard.js.map +0 -1
- package/dist/cli/components/LiveStats.d.ts +0 -16
- package/dist/cli/components/LiveStats.d.ts.map +0 -1
- package/dist/cli/components/LiveStats.js +0 -16
- package/dist/cli/components/LiveStats.js.map +0 -1
- package/dist/cli/components/SessionBrowser.d.ts +0 -14
- package/dist/cli/components/SessionBrowser.d.ts.map +0 -1
- package/dist/cli/components/SessionBrowser.js +0 -14
- package/dist/cli/components/SessionBrowser.js.map +0 -1
- package/dist/cli/tui.d.ts +0 -21
- package/dist/cli/tui.d.ts.map +0 -1
- package/dist/cli/tui.js +0 -21
- package/dist/cli/tui.js.map +0 -1
- package/dist/hooks/autopilot/signals.d.ts +0 -20
- package/dist/hooks/autopilot/signals.d.ts.map +0 -1
- package/dist/hooks/autopilot/signals.js +0 -75
- package/dist/hooks/autopilot/signals.js.map +0 -1
- package/dist/hooks/autopilot/summary.d.ts +0 -27
- package/dist/hooks/autopilot/summary.d.ts.map +0 -1
- package/dist/hooks/autopilot/summary.js +0 -160
- package/dist/hooks/autopilot/summary.js.map +0 -1
- package/dist/hooks/autopilot/transition.d.ts +0 -39
- package/dist/hooks/autopilot/transition.d.ts.map +0 -1
- package/dist/hooks/autopilot/transition.js +0 -216
- package/dist/hooks/autopilot/transition.js.map +0 -1
- package/dist/hooks/context-window-limit-recovery/constants.d.ts +0 -28
- package/dist/hooks/context-window-limit-recovery/constants.d.ts.map +0 -1
- package/dist/hooks/context-window-limit-recovery/constants.js +0 -85
- package/dist/hooks/context-window-limit-recovery/constants.js.map +0 -1
- package/dist/hooks/context-window-limit-recovery/index.d.ts +0 -62
- package/dist/hooks/context-window-limit-recovery/index.d.ts.map +0 -1
- package/dist/hooks/context-window-limit-recovery/index.js +0 -201
- package/dist/hooks/context-window-limit-recovery/index.js.map +0 -1
- package/dist/hooks/context-window-limit-recovery/parser.d.ts +0 -31
- package/dist/hooks/context-window-limit-recovery/parser.d.ts.map +0 -1
- package/dist/hooks/context-window-limit-recovery/parser.js +0 -241
- package/dist/hooks/context-window-limit-recovery/parser.js.map +0 -1
- package/dist/hooks/context-window-limit-recovery/types.d.ts +0 -84
- package/dist/hooks/context-window-limit-recovery/types.d.ts.map +0 -1
- package/dist/hooks/context-window-limit-recovery/types.js +0 -34
- package/dist/hooks/context-window-limit-recovery/types.js.map +0 -1
- package/dist/hooks/edit-error-recovery/index.d.ts +0 -62
- package/dist/hooks/edit-error-recovery/index.d.ts.map +0 -1
- package/dist/hooks/edit-error-recovery/index.js +0 -89
- package/dist/hooks/edit-error-recovery/index.js.map +0 -1
- package/dist/hooks/learned-skills/config.d.ts +0 -53
- package/dist/hooks/learned-skills/config.d.ts.map +0 -1
- package/dist/hooks/learned-skills/config.js +0 -103
- package/dist/hooks/learned-skills/config.js.map +0 -1
- package/dist/hooks/learned-skills/constants.d.ts +0 -24
- package/dist/hooks/learned-skills/constants.d.ts.map +0 -1
- package/dist/hooks/learned-skills/constants.js +0 -26
- package/dist/hooks/learned-skills/constants.js.map +0 -1
- package/dist/hooks/learned-skills/detection-hook.d.ts +0 -39
- package/dist/hooks/learned-skills/detection-hook.d.ts.map +0 -1
- package/dist/hooks/learned-skills/detection-hook.js +0 -83
- package/dist/hooks/learned-skills/detection-hook.js.map +0 -1
- package/dist/hooks/learned-skills/detector.d.ts +0 -30
- package/dist/hooks/learned-skills/detector.d.ts.map +0 -1
- package/dist/hooks/learned-skills/detector.js +0 -150
- package/dist/hooks/learned-skills/detector.js.map +0 -1
- package/dist/hooks/learned-skills/finder.d.ts +0 -21
- package/dist/hooks/learned-skills/finder.d.ts.map +0 -1
- package/dist/hooks/learned-skills/finder.js +0 -117
- package/dist/hooks/learned-skills/finder.js.map +0 -1
- package/dist/hooks/learned-skills/index.d.ts +0 -62
- package/dist/hooks/learned-skills/index.d.ts.map +0 -1
- package/dist/hooks/learned-skills/index.js +0 -137
- package/dist/hooks/learned-skills/index.js.map +0 -1
- package/dist/hooks/learned-skills/loader.d.ts +0 -20
- package/dist/hooks/learned-skills/loader.d.ts.map +0 -1
- package/dist/hooks/learned-skills/loader.js +0 -107
- package/dist/hooks/learned-skills/loader.js.map +0 -1
- package/dist/hooks/learned-skills/parser.d.ts +0 -21
- package/dist/hooks/learned-skills/parser.d.ts.map +0 -1
- package/dist/hooks/learned-skills/parser.js +0 -190
- package/dist/hooks/learned-skills/parser.js.map +0 -1
- package/dist/hooks/learned-skills/promotion.d.ts +0 -29
- package/dist/hooks/learned-skills/promotion.d.ts.map +0 -1
- package/dist/hooks/learned-skills/promotion.js +0 -87
- package/dist/hooks/learned-skills/promotion.js.map +0 -1
- package/dist/hooks/learned-skills/types.d.ts +0 -109
- package/dist/hooks/learned-skills/types.d.ts.map +0 -1
- package/dist/hooks/learned-skills/types.js +0 -8
- package/dist/hooks/learned-skills/types.js.map +0 -1
- package/dist/hooks/learned-skills/validator.d.ts +0 -15
- package/dist/hooks/learned-skills/validator.d.ts.map +0 -1
- package/dist/hooks/learned-skills/validator.js +0 -87
- package/dist/hooks/learned-skills/validator.js.map +0 -1
- package/dist/hooks/learned-skills/writer.d.ts +0 -27
- package/dist/hooks/learned-skills/writer.d.ts.map +0 -1
- package/dist/hooks/learned-skills/writer.js +0 -126
- package/dist/hooks/learned-skills/writer.js.map +0 -1
- package/dist/hooks/mnemosyne/config.d.ts +0 -53
- package/dist/hooks/mnemosyne/config.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/config.js +0 -103
- package/dist/hooks/mnemosyne/config.js.map +0 -1
- package/dist/hooks/mnemosyne/constants.d.ts +0 -24
- package/dist/hooks/mnemosyne/constants.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/constants.js +0 -26
- package/dist/hooks/mnemosyne/constants.js.map +0 -1
- package/dist/hooks/mnemosyne/detection-hook.d.ts +0 -39
- package/dist/hooks/mnemosyne/detection-hook.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/detection-hook.js +0 -83
- package/dist/hooks/mnemosyne/detection-hook.js.map +0 -1
- package/dist/hooks/mnemosyne/detector.d.ts +0 -30
- package/dist/hooks/mnemosyne/detector.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/detector.js +0 -150
- package/dist/hooks/mnemosyne/detector.js.map +0 -1
- package/dist/hooks/mnemosyne/finder.d.ts +0 -21
- package/dist/hooks/mnemosyne/finder.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/finder.js +0 -117
- package/dist/hooks/mnemosyne/finder.js.map +0 -1
- package/dist/hooks/mnemosyne/index.d.ts +0 -62
- package/dist/hooks/mnemosyne/index.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/index.js +0 -137
- package/dist/hooks/mnemosyne/index.js.map +0 -1
- package/dist/hooks/mnemosyne/loader.d.ts +0 -20
- package/dist/hooks/mnemosyne/loader.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/loader.js +0 -113
- package/dist/hooks/mnemosyne/loader.js.map +0 -1
- package/dist/hooks/mnemosyne/parser.d.ts +0 -21
- package/dist/hooks/mnemosyne/parser.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/parser.js +0 -190
- package/dist/hooks/mnemosyne/parser.js.map +0 -1
- package/dist/hooks/mnemosyne/promotion.d.ts +0 -29
- package/dist/hooks/mnemosyne/promotion.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/promotion.js +0 -87
- package/dist/hooks/mnemosyne/promotion.js.map +0 -1
- package/dist/hooks/mnemosyne/types.d.ts +0 -109
- package/dist/hooks/mnemosyne/types.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/types.js +0 -8
- package/dist/hooks/mnemosyne/types.js.map +0 -1
- package/dist/hooks/mnemosyne/validator.d.ts +0 -15
- package/dist/hooks/mnemosyne/validator.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/validator.js +0 -87
- package/dist/hooks/mnemosyne/validator.js.map +0 -1
- package/dist/hooks/mnemosyne/writer.d.ts +0 -27
- package/dist/hooks/mnemosyne/writer.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/writer.js +0 -126
- package/dist/hooks/mnemosyne/writer.js.map +0 -1
- package/dist/hooks/ralph-loop/index.d.ts +0 -116
- package/dist/hooks/ralph-loop/index.d.ts.map +0 -1
- package/dist/hooks/ralph-loop/index.js +0 -322
- package/dist/hooks/ralph-loop/index.js.map +0 -1
- package/dist/hooks/ralph-prd/index.d.ts +0 -130
- package/dist/hooks/ralph-prd/index.d.ts.map +0 -1
- package/dist/hooks/ralph-prd/index.js +0 -310
- package/dist/hooks/ralph-prd/index.js.map +0 -1
- package/dist/hooks/ralph-progress/index.d.ts +0 -102
- package/dist/hooks/ralph-progress/index.d.ts.map +0 -1
- package/dist/hooks/ralph-progress/index.js +0 -408
- package/dist/hooks/ralph-progress/index.js.map +0 -1
- package/dist/hooks/ralph-verifier/index.d.ts +0 -72
- package/dist/hooks/ralph-verifier/index.d.ts.map +0 -1
- package/dist/hooks/ralph-verifier/index.js +0 -223
- package/dist/hooks/ralph-verifier/index.js.map +0 -1
- package/dist/hooks/session-recovery/constants.d.ts +0 -56
- package/dist/hooks/session-recovery/constants.d.ts.map +0 -1
- package/dist/hooks/session-recovery/constants.js +0 -78
- package/dist/hooks/session-recovery/constants.js.map +0 -1
- package/dist/hooks/session-recovery/index.d.ts +0 -53
- package/dist/hooks/session-recovery/index.d.ts.map +0 -1
- package/dist/hooks/session-recovery/index.js +0 -321
- package/dist/hooks/session-recovery/index.js.map +0 -1
- package/dist/hooks/session-recovery/storage.d.ts +0 -76
- package/dist/hooks/session-recovery/storage.d.ts.map +0 -1
- package/dist/hooks/session-recovery/storage.js +0 -383
- package/dist/hooks/session-recovery/storage.js.map +0 -1
- package/dist/hooks/session-recovery/types.d.ts +0 -145
- package/dist/hooks/session-recovery/types.d.ts.map +0 -1
- package/dist/hooks/session-recovery/types.js +0 -8
- package/dist/hooks/session-recovery/types.js.map +0 -1
- package/dist/hooks/sisyphus-orchestrator/constants.d.ts +0 -23
- package/dist/hooks/sisyphus-orchestrator/constants.d.ts.map +0 -1
- package/dist/hooks/sisyphus-orchestrator/constants.js +0 -142
- package/dist/hooks/sisyphus-orchestrator/constants.js.map +0 -1
- package/dist/hooks/sisyphus-orchestrator/index.d.ts +0 -113
- package/dist/hooks/sisyphus-orchestrator/index.d.ts.map +0 -1
- package/dist/hooks/sisyphus-orchestrator/index.js +0 -309
- package/dist/hooks/sisyphus-orchestrator/index.js.map +0 -1
- package/dist/hooks/ultraqa-loop/index.d.ts +0 -94
- package/dist/hooks/ultraqa-loop/index.d.ts.map +0 -1
- package/dist/hooks/ultraqa-loop/index.js +0 -216
- package/dist/hooks/ultraqa-loop/index.js.map +0 -1
- package/dist/hooks/ultrawork-state/index.d.ts +0 -62
- package/dist/hooks/ultrawork-state/index.d.ts.map +0 -1
- package/dist/hooks/ultrawork-state/index.js +0 -208
- package/dist/hooks/ultrawork-state/index.js.map +0 -1
- package/dist/hud/sisyphus-state.d.ts +0 -31
- package/dist/hud/sisyphus-state.d.ts.map +0 -1
- package/dist/hud/sisyphus-state.js +0 -163
- package/dist/hud/sisyphus-state.js.map +0 -1
|
@@ -0,0 +1,1051 @@
|
|
|
1
|
+
# MCP/Plugin Compatibility Layer
|
|
2
|
+
|
|
3
|
+
The Compatibility Layer enables oh-my-claudecode to discover, register, and use external plugins, MCP servers, and tools. It provides a unified interface for managing external tools while maintaining security through an integrated permission system.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Overview](#overview)
|
|
8
|
+
- [Architecture](#architecture)
|
|
9
|
+
- [Plugin Discovery](#plugin-discovery)
|
|
10
|
+
- [MCP Server Discovery](#mcp-server-discovery)
|
|
11
|
+
- [Plugin Manifest Format](#plugin-manifest-format)
|
|
12
|
+
- [Tool Registration](#tool-registration)
|
|
13
|
+
- [Permission System](#permission-system)
|
|
14
|
+
- [MCP Bridge](#mcp-bridge)
|
|
15
|
+
- [API Reference](#api-reference)
|
|
16
|
+
- [Examples](#examples)
|
|
17
|
+
- [Troubleshooting](#troubleshooting)
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
The Compatibility Layer consists of four integrated systems working together:
|
|
22
|
+
|
|
23
|
+
1. **Discovery System** - Automatically finds plugins and MCP servers from user directories
|
|
24
|
+
2. **Tool Registry** - Central hub that registers and manages all external tools with conflict resolution
|
|
25
|
+
3. **Permission Adapter** - Integrates with OMC's permission system for safe tool execution
|
|
26
|
+
4. **MCP Bridge** - Connects to MCP servers and exposes their tools for use
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Plugins MCP Configs OMC Tools
|
|
30
|
+
↓ ↓ ↓
|
|
31
|
+
Discovery System ────────────────────────────┐
|
|
32
|
+
↓
|
|
33
|
+
Tool Registry ← ← ←┘
|
|
34
|
+
↓
|
|
35
|
+
Permission Adapter
|
|
36
|
+
↓
|
|
37
|
+
MCP Bridge
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
|
|
42
|
+
### Discovery System (`discovery.ts`)
|
|
43
|
+
|
|
44
|
+
Scans for external plugins and MCP servers from:
|
|
45
|
+
|
|
46
|
+
- `~/.claude/plugins/` - OMC/Claude Code plugins directory
|
|
47
|
+
- `~/.claude/installed-plugins/` - Alternative plugins location
|
|
48
|
+
- `~/.claude/settings.json` - Claude Code MCP server configs
|
|
49
|
+
- `~/.claude/claude_desktop_config.json` - Claude Desktop MCP server configs
|
|
50
|
+
- Plugin manifests (`plugin.json`) for embedded MCP servers
|
|
51
|
+
|
|
52
|
+
**Discovers:**
|
|
53
|
+
- Plugin skills and agents (from SKILL.md and agent .md files)
|
|
54
|
+
- MCP server configurations
|
|
55
|
+
- Tool definitions from plugin manifests
|
|
56
|
+
|
|
57
|
+
### Tool Registry (`registry.ts`)
|
|
58
|
+
|
|
59
|
+
Central hub for tool management:
|
|
60
|
+
|
|
61
|
+
- Registers tools from discovered plugins and MCP servers
|
|
62
|
+
- Handles tool name conflicts using priority-based resolution
|
|
63
|
+
- Routes commands to appropriate handlers
|
|
64
|
+
- Provides search and filtering capabilities
|
|
65
|
+
- Emits events for registration and connection status
|
|
66
|
+
|
|
67
|
+
**Key features:**
|
|
68
|
+
- Tools are namespaced (e.g., `plugin-name:tool-name`)
|
|
69
|
+
- Priority system for conflict resolution (higher priority wins)
|
|
70
|
+
- Short name lookup (finds `tool-name` even with namespace)
|
|
71
|
+
- Event listeners for monitoring registry state
|
|
72
|
+
|
|
73
|
+
### Permission Adapter (`permission-adapter.ts`)
|
|
74
|
+
|
|
75
|
+
Integrates external tools with OMC's permission system:
|
|
76
|
+
|
|
77
|
+
- Maintains safe patterns for read-only tools
|
|
78
|
+
- Auto-approves known-safe operations
|
|
79
|
+
- Prompts user for dangerous operations (write, execute)
|
|
80
|
+
- Caches permission decisions
|
|
81
|
+
- Determines delegation targets for tool execution
|
|
82
|
+
|
|
83
|
+
**Safe patterns:**
|
|
84
|
+
- Built-in patterns for common MCP tools (filesystem read, context7 queries)
|
|
85
|
+
- Plugin-contributed patterns from manifests
|
|
86
|
+
- Custom patterns can be registered at runtime
|
|
87
|
+
|
|
88
|
+
### MCP Bridge (`mcp-bridge.ts`)
|
|
89
|
+
|
|
90
|
+
Manages MCP server connections:
|
|
91
|
+
|
|
92
|
+
- Spawns server processes
|
|
93
|
+
- Sends JSON-RPC requests and handles responses
|
|
94
|
+
- Discovers tools and resources from servers
|
|
95
|
+
- Routes tool invocations to servers
|
|
96
|
+
- Handles connection lifecycle (connect, disconnect, reconnect)
|
|
97
|
+
|
|
98
|
+
**Protocol:** JSON-RPC 2.0 over process stdio with newline-delimited messages
|
|
99
|
+
|
|
100
|
+
## Plugin Discovery
|
|
101
|
+
|
|
102
|
+
### Directory Structure
|
|
103
|
+
|
|
104
|
+
Plugins are discovered from `~/.claude/plugins/` and `~/.claude/installed-plugins/`:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
~/.claude/plugins/
|
|
108
|
+
├── my-plugin/
|
|
109
|
+
│ ├── plugin.json (required)
|
|
110
|
+
│ ├── skills/ (optional)
|
|
111
|
+
│ │ ├── skill-1/
|
|
112
|
+
│ │ │ └── SKILL.md
|
|
113
|
+
│ │ └── skill-2/
|
|
114
|
+
│ │ └── SKILL.md
|
|
115
|
+
│ ├── agents/ (optional)
|
|
116
|
+
│ │ ├── agent-1.md
|
|
117
|
+
│ │ └── agent-2.md
|
|
118
|
+
│ └── commands/ (optional)
|
|
119
|
+
└── another-plugin/
|
|
120
|
+
└── plugin.json
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Plugin Manifest Structure
|
|
124
|
+
|
|
125
|
+
The `plugin.json` defines the plugin's metadata and tools:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"name": "my-plugin",
|
|
130
|
+
"version": "1.0.0",
|
|
131
|
+
"description": "My awesome plugin",
|
|
132
|
+
"namespace": "my-plugin",
|
|
133
|
+
"skills": "./skills/",
|
|
134
|
+
"agents": "./agents/",
|
|
135
|
+
"commands": "./commands/",
|
|
136
|
+
"mcpServers": {
|
|
137
|
+
"server-name": {
|
|
138
|
+
"command": "node",
|
|
139
|
+
"args": ["server.js"],
|
|
140
|
+
"env": {},
|
|
141
|
+
"enabled": true,
|
|
142
|
+
"description": "My MCP server"
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"permissions": [
|
|
146
|
+
{
|
|
147
|
+
"tool": "my-plugin:search",
|
|
148
|
+
"scope": "read",
|
|
149
|
+
"patterns": [".*"],
|
|
150
|
+
"reason": "Search is read-only"
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
"tools": [
|
|
154
|
+
{
|
|
155
|
+
"name": "my-tool",
|
|
156
|
+
"description": "Does something useful",
|
|
157
|
+
"handler": "tools/my-tool.js",
|
|
158
|
+
"inputSchema": {
|
|
159
|
+
"type": "object",
|
|
160
|
+
"properties": {
|
|
161
|
+
"query": { "type": "string" }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Skill and Agent Discovery
|
|
170
|
+
|
|
171
|
+
**Skills** are discovered from `SKILL.md` files in the skills directory. Each skill directory must contain a SKILL.md with frontmatter:
|
|
172
|
+
|
|
173
|
+
```markdown
|
|
174
|
+
---
|
|
175
|
+
name: my-skill
|
|
176
|
+
description: Describes what this skill does
|
|
177
|
+
tags: tag1, tag2
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
Skill documentation here...
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Agents** are discovered from `.md` files in the agents directory with similar frontmatter structure.
|
|
184
|
+
|
|
185
|
+
## MCP Server Discovery
|
|
186
|
+
|
|
187
|
+
### Claude Desktop Config
|
|
188
|
+
|
|
189
|
+
Located at `~/.claude/claude_desktop_config.json`:
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"mcpServers": {
|
|
194
|
+
"filesystem": {
|
|
195
|
+
"command": "npx",
|
|
196
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/"],
|
|
197
|
+
"enabled": true
|
|
198
|
+
},
|
|
199
|
+
"web": {
|
|
200
|
+
"command": "npx",
|
|
201
|
+
"args": ["-y", "@modelcontextprotocol/server-web"],
|
|
202
|
+
"enabled": true
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Claude Code Settings
|
|
209
|
+
|
|
210
|
+
Located at `~/.claude/settings.json`:
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"mcpServers": {
|
|
215
|
+
"my-server": {
|
|
216
|
+
"command": "node",
|
|
217
|
+
"args": ["server.js"],
|
|
218
|
+
"env": {
|
|
219
|
+
"API_KEY": "secret"
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Plugin-Embedded MCP Servers
|
|
227
|
+
|
|
228
|
+
Plugins can define MCP servers in their manifest:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"name": "plugin-with-server",
|
|
233
|
+
"mcpServers": {
|
|
234
|
+
"my-mcp": {
|
|
235
|
+
"command": "node",
|
|
236
|
+
"args": ["./mcp/server.js"]
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Plugin Manifest Format
|
|
243
|
+
|
|
244
|
+
### Complete Schema
|
|
245
|
+
|
|
246
|
+
| Field | Type | Required | Description |
|
|
247
|
+
|-------|------|----------|-------------|
|
|
248
|
+
| `name` | string | Yes | Plugin name (alphanumeric, hyphens, underscores) |
|
|
249
|
+
| `version` | string | Yes | Semantic version (e.g., "1.0.0") |
|
|
250
|
+
| `description` | string | No | Human-readable description |
|
|
251
|
+
| `namespace` | string | No | Prefix for tool names (defaults to plugin name) |
|
|
252
|
+
| `skills` | string\|string[] | No | Path(s) to skills directory |
|
|
253
|
+
| `agents` | string\|string[] | No | Path(s) to agents directory |
|
|
254
|
+
| `commands` | string\|string[] | No | Path(s) to commands directory |
|
|
255
|
+
| `mcpServers` | object | No | MCP server configurations (name → McpServerEntry) |
|
|
256
|
+
| `permissions` | PluginPermission[] | No | Permissions needed for plugin tools |
|
|
257
|
+
| `tools` | PluginToolDefinition[] | No | Tool definitions |
|
|
258
|
+
|
|
259
|
+
### McpServerEntry
|
|
260
|
+
|
|
261
|
+
| Field | Type | Required | Description |
|
|
262
|
+
|-------|------|----------|-------------|
|
|
263
|
+
| `command` | string | Yes | Command to run server (e.g., "node", "npx") |
|
|
264
|
+
| `args` | string[] | No | Command arguments |
|
|
265
|
+
| `env` | object | No | Environment variables to pass to server |
|
|
266
|
+
| `enabled` | boolean | No | Whether server connects on init (default: true) |
|
|
267
|
+
| `description` | string | No | Human-readable description |
|
|
268
|
+
|
|
269
|
+
### PluginPermission
|
|
270
|
+
|
|
271
|
+
| Field | Type | Description |
|
|
272
|
+
|-------|------|-------------|
|
|
273
|
+
| `tool` | string | Tool name requiring permission |
|
|
274
|
+
| `scope` | "read"\|"write"\|"execute"\|"all" | Permission scope |
|
|
275
|
+
| `patterns` | string[] | Regex patterns for allowed paths/commands |
|
|
276
|
+
| `reason` | string | Why this permission is needed |
|
|
277
|
+
|
|
278
|
+
### PluginToolDefinition
|
|
279
|
+
|
|
280
|
+
| Field | Type | Description |
|
|
281
|
+
|-------|------|-------------|
|
|
282
|
+
| `name` | string | Tool name (becomes `namespace:name`) |
|
|
283
|
+
| `description` | string | Human-readable description |
|
|
284
|
+
| `handler` | string | Path to handler function or command |
|
|
285
|
+
| `inputSchema` | object | JSON Schema for tool input |
|
|
286
|
+
|
|
287
|
+
## Tool Registration
|
|
288
|
+
|
|
289
|
+
### Registration Process
|
|
290
|
+
|
|
291
|
+
Tools are registered in this order:
|
|
292
|
+
|
|
293
|
+
1. **Plugin discovery** - Plugins found in configured paths
|
|
294
|
+
2. **Tool extraction** - Skills, agents, and tool definitions extracted from plugins
|
|
295
|
+
3. **MCP server discovery** - MCP servers found from config files
|
|
296
|
+
4. **Tool conversion** - MCP tools converted to ExternalTool format
|
|
297
|
+
5. **Conflict resolution** - Tools with same name resolved by priority
|
|
298
|
+
|
|
299
|
+
### Tool Naming
|
|
300
|
+
|
|
301
|
+
Tools use a namespaced format:
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
{namespace}:{tool-name}
|
|
305
|
+
|
|
306
|
+
Examples:
|
|
307
|
+
- my-plugin:search
|
|
308
|
+
- filesystem:read_file
|
|
309
|
+
- context7:query-docs
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Short names also work:
|
|
313
|
+
```javascript
|
|
314
|
+
getRegistry().getTool('search') // Finds 'my-plugin:search'
|
|
315
|
+
getRegistry().getTool('my-plugin:search') // Exact match
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Conflict Resolution
|
|
319
|
+
|
|
320
|
+
When two plugins provide a tool with the same name:
|
|
321
|
+
|
|
322
|
+
1. **Priority value** - Tool with higher priority wins (default: 50)
|
|
323
|
+
2. **Namespace** - Use full namespaced name to disambiguate
|
|
324
|
+
3. **Manual** - Check conflicts and re-register with different priority
|
|
325
|
+
|
|
326
|
+
```javascript
|
|
327
|
+
// Check for conflicts
|
|
328
|
+
const conflicts = registry.getConflicts();
|
|
329
|
+
|
|
330
|
+
// Get winner for conflict
|
|
331
|
+
const winner = conflicts[0].winner;
|
|
332
|
+
console.log(`${winner.source} won with priority ${winner.priority}`);
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Permission System
|
|
336
|
+
|
|
337
|
+
### Safe Patterns
|
|
338
|
+
|
|
339
|
+
Read-only tools are auto-approved without user prompting:
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
// Check if tool is safe
|
|
343
|
+
const result = checkPermission('mcp__filesystem__read_file');
|
|
344
|
+
// { allowed: true, reason: "Filesystem read (read-only)" }
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Built-in safe patterns cover:
|
|
348
|
+
|
|
349
|
+
- **Context7** - Documentation queries (read-only)
|
|
350
|
+
- **Filesystem** - Read operations only
|
|
351
|
+
- **Exa** - Web search (read-only, external)
|
|
352
|
+
|
|
353
|
+
### Permission Check Flow
|
|
354
|
+
|
|
355
|
+
```
|
|
356
|
+
Tool invocation
|
|
357
|
+
↓
|
|
358
|
+
Check safe patterns → Allowed (no prompt needed)
|
|
359
|
+
↓ (not in safe patterns)
|
|
360
|
+
Check dangerous patterns → Ask user
|
|
361
|
+
↓ (not dangerous)
|
|
362
|
+
Check tool capabilities → Safe caps (auto-approve) or Dangerous (ask user)
|
|
363
|
+
↓
|
|
364
|
+
Execute or Deny
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Auto-Approval Examples
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
// Read-only tools are safe
|
|
371
|
+
checkPermission('my-plugin:search')
|
|
372
|
+
// { allowed: true, reason: "Tool has safe capabilities: search" }
|
|
373
|
+
|
|
374
|
+
// Write/execute requires user confirmation
|
|
375
|
+
checkPermission('filesystem:write_file', { path: '/etc/passwd' })
|
|
376
|
+
// { allowed: false, askUser: true, reason: "Tool requires explicit permission" }
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Caching Permissions
|
|
380
|
+
|
|
381
|
+
Permission decisions are cached. Users can grant or deny persistently:
|
|
382
|
+
|
|
383
|
+
```javascript
|
|
384
|
+
// User grants permission
|
|
385
|
+
grantPermission('custom:dangerous-tool', { mode: 'aggressive' });
|
|
386
|
+
|
|
387
|
+
// Later calls use cached decision
|
|
388
|
+
checkPermission('custom:dangerous-tool', { mode: 'aggressive' });
|
|
389
|
+
// { allowed: true, reason: "User granted permission" }
|
|
390
|
+
|
|
391
|
+
// Clear cache when needed
|
|
392
|
+
clearPermissionCache();
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Registering Safe Patterns
|
|
396
|
+
|
|
397
|
+
Plugins can register safe patterns in manifest:
|
|
398
|
+
|
|
399
|
+
```json
|
|
400
|
+
{
|
|
401
|
+
"name": "my-plugin",
|
|
402
|
+
"permissions": [
|
|
403
|
+
{
|
|
404
|
+
"tool": "my-plugin:query-docs",
|
|
405
|
+
"scope": "read",
|
|
406
|
+
"patterns": [".*"],
|
|
407
|
+
"reason": "Documentation lookup is read-only"
|
|
408
|
+
}
|
|
409
|
+
]
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
These are automatically integrated when the plugin is initialized.
|
|
414
|
+
|
|
415
|
+
## MCP Bridge
|
|
416
|
+
|
|
417
|
+
### Connecting to Servers
|
|
418
|
+
|
|
419
|
+
```javascript
|
|
420
|
+
import { getMcpBridge } from './compatibility';
|
|
421
|
+
|
|
422
|
+
const bridge = getMcpBridge();
|
|
423
|
+
|
|
424
|
+
// Connect to a single server
|
|
425
|
+
const tools = await bridge.connect('filesystem');
|
|
426
|
+
console.log(`Connected. Available tools: ${tools.map(t => t.name).join(', ')}`);
|
|
427
|
+
|
|
428
|
+
// Auto-connect all enabled servers
|
|
429
|
+
const results = await bridge.autoConnect();
|
|
430
|
+
for (const [serverName, tools] of results) {
|
|
431
|
+
console.log(`${serverName}: ${tools.length} tools`);
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Invoking Tools
|
|
436
|
+
|
|
437
|
+
```javascript
|
|
438
|
+
// Invoke a tool on an MCP server
|
|
439
|
+
const result = await bridge.invokeTool('filesystem', 'read_file', {
|
|
440
|
+
path: '/home/user/.bashrc'
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
if (result.success) {
|
|
444
|
+
console.log('File contents:', result.data);
|
|
445
|
+
console.log('Time:', result.executionTime, 'ms');
|
|
446
|
+
} else {
|
|
447
|
+
console.error('Error:', result.error);
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Reading Resources
|
|
452
|
+
|
|
453
|
+
Some MCP servers provide resources (documents, APIs, etc.):
|
|
454
|
+
|
|
455
|
+
```javascript
|
|
456
|
+
// Read a resource
|
|
457
|
+
const result = await bridge.readResource('web', 'https://example.com');
|
|
458
|
+
|
|
459
|
+
if (result.success) {
|
|
460
|
+
console.log(result.data);
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Connection Management
|
|
465
|
+
|
|
466
|
+
```javascript
|
|
467
|
+
// Check connection status
|
|
468
|
+
if (bridge.isConnected('filesystem')) {
|
|
469
|
+
console.log('Connected to filesystem server');
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Get all server tools and resources
|
|
473
|
+
const tools = bridge.getServerTools('filesystem');
|
|
474
|
+
const resources = bridge.getServerResources('web');
|
|
475
|
+
|
|
476
|
+
// Disconnect from server
|
|
477
|
+
bridge.disconnect('filesystem');
|
|
478
|
+
|
|
479
|
+
// Disconnect from all servers
|
|
480
|
+
bridge.disconnectAll();
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### Events
|
|
484
|
+
|
|
485
|
+
Monitor bridge activity:
|
|
486
|
+
|
|
487
|
+
```javascript
|
|
488
|
+
const bridge = getMcpBridge();
|
|
489
|
+
|
|
490
|
+
bridge.on('server-connected', ({ server, toolCount }) => {
|
|
491
|
+
console.log(`Connected to ${server} with ${toolCount} tools`);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
bridge.on('server-disconnected', ({ server, code }) => {
|
|
495
|
+
console.log(`Disconnected from ${server}`);
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
bridge.on('server-error', ({ server, error }) => {
|
|
499
|
+
console.error(`Error from ${server}:`, error);
|
|
500
|
+
});
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
## API Reference
|
|
504
|
+
|
|
505
|
+
### Initialization
|
|
506
|
+
|
|
507
|
+
```typescript
|
|
508
|
+
import {
|
|
509
|
+
initializeCompatibility,
|
|
510
|
+
getRegistry,
|
|
511
|
+
getMcpBridge
|
|
512
|
+
} from './compatibility';
|
|
513
|
+
|
|
514
|
+
// Initialize everything
|
|
515
|
+
const result = await initializeCompatibility({
|
|
516
|
+
pluginPaths: ['~/.claude/plugins'],
|
|
517
|
+
mcpConfigPath: '~/.claude/claude_desktop_config.json',
|
|
518
|
+
autoConnect: true // Auto-connect to MCP servers
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
console.log(`Plugins: ${result.pluginCount}`);
|
|
522
|
+
console.log(`MCP servers: ${result.mcpServerCount}`);
|
|
523
|
+
console.log(`Tools: ${result.toolCount}`);
|
|
524
|
+
console.log(`Connected: ${result.connectedServers.join(', ')}`);
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Discovery Functions
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
import {
|
|
531
|
+
discoverPlugins,
|
|
532
|
+
discoverMcpServers,
|
|
533
|
+
discoverAll,
|
|
534
|
+
isPluginInstalled,
|
|
535
|
+
getPluginInfo,
|
|
536
|
+
getPluginPaths,
|
|
537
|
+
getMcpConfigPath
|
|
538
|
+
} from './compatibility';
|
|
539
|
+
|
|
540
|
+
// Discover plugins from custom paths
|
|
541
|
+
const plugins = discoverPlugins({
|
|
542
|
+
pluginPaths: ['/custom/plugins/path']
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// Discover MCP servers
|
|
546
|
+
const servers = discoverMcpServers({
|
|
547
|
+
mcpConfigPath: '~/.claude/claude_desktop_config.json',
|
|
548
|
+
settingsPath: '~/.claude/settings.json'
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// Discover everything at once
|
|
552
|
+
const result = discoverAll({
|
|
553
|
+
force: true // Force re-discovery even if cached
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
// Check plugin installation
|
|
557
|
+
if (isPluginInstalled('my-plugin')) {
|
|
558
|
+
const info = getPluginInfo('my-plugin');
|
|
559
|
+
console.log(`${info.name} v${info.version}`);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// Get configured paths
|
|
563
|
+
const pluginPaths = getPluginPaths();
|
|
564
|
+
const mcpPath = getMcpConfigPath();
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### Registry Functions
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
import {
|
|
571
|
+
getRegistry,
|
|
572
|
+
initializeRegistry,
|
|
573
|
+
routeCommand,
|
|
574
|
+
getExternalTool,
|
|
575
|
+
listExternalTools,
|
|
576
|
+
hasExternalPlugins,
|
|
577
|
+
hasMcpServers
|
|
578
|
+
} from './compatibility';
|
|
579
|
+
|
|
580
|
+
const registry = getRegistry();
|
|
581
|
+
|
|
582
|
+
// Register discovery and tools
|
|
583
|
+
await initializeRegistry({ force: true });
|
|
584
|
+
|
|
585
|
+
// Access tools
|
|
586
|
+
const allTools = listExternalTools();
|
|
587
|
+
const tool = getExternalTool('my-plugin:search');
|
|
588
|
+
|
|
589
|
+
// Route command
|
|
590
|
+
const route = routeCommand('search');
|
|
591
|
+
if (route) {
|
|
592
|
+
console.log(`Handler: ${route.handler}`);
|
|
593
|
+
console.log(`Requires permission: ${route.requiresPermission}`);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// Check what's available
|
|
597
|
+
if (hasExternalPlugins()) {
|
|
598
|
+
console.log('External plugins available');
|
|
599
|
+
}
|
|
600
|
+
if (hasMcpServers()) {
|
|
601
|
+
console.log('MCP servers available');
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Get all plugins and servers
|
|
605
|
+
const plugins = registry.getAllPlugins();
|
|
606
|
+
const servers = registry.getAllMcpServers();
|
|
607
|
+
|
|
608
|
+
// Search tools
|
|
609
|
+
const results = registry.searchTools('filesystem');
|
|
610
|
+
|
|
611
|
+
// Listen to events
|
|
612
|
+
registry.addEventListener(event => {
|
|
613
|
+
if (event.type === 'tool-registered') {
|
|
614
|
+
console.log(`Registered: ${event.data.tool}`);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### Permission Functions
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
import {
|
|
623
|
+
checkPermission,
|
|
624
|
+
grantPermission,
|
|
625
|
+
denyPermission,
|
|
626
|
+
clearPermissionCache,
|
|
627
|
+
addSafePattern,
|
|
628
|
+
getSafePatterns,
|
|
629
|
+
shouldDelegate,
|
|
630
|
+
getDelegationTarget,
|
|
631
|
+
integrateWithPermissionSystem,
|
|
632
|
+
processExternalToolPermission
|
|
633
|
+
} from './compatibility';
|
|
634
|
+
|
|
635
|
+
// Check if tool is allowed
|
|
636
|
+
const check = checkPermission('my-tool:dangerous-op');
|
|
637
|
+
if (check.allowed) {
|
|
638
|
+
console.log('Allowed:', check.reason);
|
|
639
|
+
} else if (check.askUser) {
|
|
640
|
+
console.log('Ask user:', check.reason);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// Cache user decisions
|
|
644
|
+
grantPermission('custom:tool', { mode: 'aggressive' });
|
|
645
|
+
denyPermission('risky:tool');
|
|
646
|
+
clearPermissionCache();
|
|
647
|
+
|
|
648
|
+
// Manage safe patterns
|
|
649
|
+
const patterns = getSafePatterns();
|
|
650
|
+
addSafePattern({
|
|
651
|
+
tool: 'my-safe-tool',
|
|
652
|
+
pattern: /^\/safe\/path/,
|
|
653
|
+
description: 'Only allows /safe/path',
|
|
654
|
+
source: 'myapp'
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// Check if tool should be delegated
|
|
658
|
+
if (shouldDelegate('external:tool')) {
|
|
659
|
+
const target = getDelegationTarget('external:tool');
|
|
660
|
+
console.log(`Delegate to: ${target.type}/${target.target}`);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Integrate with permission system at startup
|
|
664
|
+
integrateWithPermissionSystem();
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
### MCP Bridge Functions
|
|
668
|
+
|
|
669
|
+
```typescript
|
|
670
|
+
import {
|
|
671
|
+
getMcpBridge,
|
|
672
|
+
resetMcpBridge,
|
|
673
|
+
invokeMcpTool,
|
|
674
|
+
readMcpResource
|
|
675
|
+
} from './compatibility';
|
|
676
|
+
|
|
677
|
+
const bridge = getMcpBridge();
|
|
678
|
+
|
|
679
|
+
// Connect to server
|
|
680
|
+
const tools = await bridge.connect('filesystem');
|
|
681
|
+
|
|
682
|
+
// Invoke tool
|
|
683
|
+
const result = await invokeMcpTool('filesystem', 'read_file', {
|
|
684
|
+
path: '/etc/hosts'
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
// Read resource
|
|
688
|
+
const resourceResult = await readMcpResource('web', 'https://api.example.com');
|
|
689
|
+
|
|
690
|
+
// Check connections
|
|
691
|
+
const status = bridge.getConnectionStatus();
|
|
692
|
+
|
|
693
|
+
// Clean up
|
|
694
|
+
bridge.disconnectAll();
|
|
695
|
+
resetMcpBridge();
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
## Examples
|
|
699
|
+
|
|
700
|
+
### Example 1: Initialize and List Tools
|
|
701
|
+
|
|
702
|
+
```javascript
|
|
703
|
+
import { initializeCompatibility, getRegistry } from './compatibility';
|
|
704
|
+
|
|
705
|
+
async function listAvailableTools() {
|
|
706
|
+
// Initialize the compatibility layer
|
|
707
|
+
const result = await initializeCompatibility({
|
|
708
|
+
autoConnect: true
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
console.log(`Discovered ${result.pluginCount} plugins`);
|
|
712
|
+
console.log(`Connected to ${result.connectedServers.length} MCP servers`);
|
|
713
|
+
|
|
714
|
+
// List all available tools
|
|
715
|
+
const registry = getRegistry();
|
|
716
|
+
const tools = registry.getAllTools();
|
|
717
|
+
|
|
718
|
+
console.log('\nAvailable tools:');
|
|
719
|
+
for (const tool of tools) {
|
|
720
|
+
console.log(` ${tool.name} (${tool.type})`);
|
|
721
|
+
console.log(` Description: ${tool.description}`);
|
|
722
|
+
console.log(` Capabilities: ${tool.capabilities?.join(', ')}`);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
listAvailableTools().catch(console.error);
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
### Example 2: Search and Use a Tool
|
|
730
|
+
|
|
731
|
+
```javascript
|
|
732
|
+
import {
|
|
733
|
+
initializeCompatibility,
|
|
734
|
+
getRegistry,
|
|
735
|
+
checkPermission,
|
|
736
|
+
getMcpBridge
|
|
737
|
+
} from './compatibility';
|
|
738
|
+
|
|
739
|
+
async function searchAndRead() {
|
|
740
|
+
await initializeCompatibility();
|
|
741
|
+
|
|
742
|
+
const registry = getRegistry();
|
|
743
|
+
|
|
744
|
+
// Search for filesystem tools
|
|
745
|
+
const fileTools = registry.searchTools('filesystem');
|
|
746
|
+
console.log(`Found ${fileTools.length} filesystem tools`);
|
|
747
|
+
|
|
748
|
+
// Find read_file tool
|
|
749
|
+
const readTool = fileTools.find(t => t.name.includes('read'));
|
|
750
|
+
|
|
751
|
+
if (readTool) {
|
|
752
|
+
// Check permission
|
|
753
|
+
const perm = checkPermission(readTool.name);
|
|
754
|
+
|
|
755
|
+
if (perm.allowed) {
|
|
756
|
+
const bridge = getMcpBridge();
|
|
757
|
+
const result = await bridge.invokeTool(
|
|
758
|
+
readTool.source,
|
|
759
|
+
'read_file',
|
|
760
|
+
{ path: '/etc/hosts' }
|
|
761
|
+
);
|
|
762
|
+
|
|
763
|
+
if (result.success) {
|
|
764
|
+
console.log('File contents:', result.data);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
searchAndRead().catch(console.error);
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
### Example 3: Handle Plugin with MCP Server
|
|
774
|
+
|
|
775
|
+
```javascript
|
|
776
|
+
import {
|
|
777
|
+
discoverPlugins,
|
|
778
|
+
initializeRegistry,
|
|
779
|
+
getMcpBridge
|
|
780
|
+
} from './compatibility';
|
|
781
|
+
|
|
782
|
+
async function setupPluginMcp() {
|
|
783
|
+
// Discover plugins (includes MCP servers defined in manifests)
|
|
784
|
+
const plugins = discoverPlugins();
|
|
785
|
+
const pluginWithMcp = plugins.find(p => p.manifest.mcpServers);
|
|
786
|
+
|
|
787
|
+
if (pluginWithMcp) {
|
|
788
|
+
console.log(`Plugin ${pluginWithMcp.name} has embedded MCP servers:`);
|
|
789
|
+
for (const serverName of Object.keys(pluginWithMcp.manifest.mcpServers || {})) {
|
|
790
|
+
console.log(` - ${serverName}`);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Initialize registry (registers MCP servers from plugins)
|
|
794
|
+
await initializeRegistry();
|
|
795
|
+
|
|
796
|
+
// Connect to plugin's MCP server
|
|
797
|
+
const bridge = getMcpBridge();
|
|
798
|
+
const fullServerName = `${pluginWithMcp.name}:${serverName}`;
|
|
799
|
+
|
|
800
|
+
try {
|
|
801
|
+
const tools = await bridge.connect(fullServerName);
|
|
802
|
+
console.log(`Connected to ${fullServerName} with ${tools.length} tools`);
|
|
803
|
+
} catch (err) {
|
|
804
|
+
console.error('Failed to connect:', err.message);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
setupPluginMcp().catch(console.error);
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
### Example 4: Conflict Resolution
|
|
813
|
+
|
|
814
|
+
```javascript
|
|
815
|
+
import { getRegistry } from './compatibility';
|
|
816
|
+
|
|
817
|
+
function showConflicts() {
|
|
818
|
+
const registry = getRegistry();
|
|
819
|
+
const conflicts = registry.getConflicts();
|
|
820
|
+
|
|
821
|
+
if (conflicts.length === 0) {
|
|
822
|
+
console.log('No tool conflicts');
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
console.log(`Found ${conflicts.length} conflicts:\n`);
|
|
827
|
+
|
|
828
|
+
for (const conflict of conflicts) {
|
|
829
|
+
console.log(`Tool: ${conflict.name}`);
|
|
830
|
+
console.log(` Winner: ${conflict.winner.source} (priority: ${conflict.winner.priority})`);
|
|
831
|
+
console.log(' Alternatives:');
|
|
832
|
+
for (const tool of conflict.tools) {
|
|
833
|
+
if (tool !== conflict.winner) {
|
|
834
|
+
console.log(` - ${tool.source} (priority: ${tool.priority})`);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
console.log();
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
showConflicts();
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### Example 5: Custom Permission Pattern
|
|
845
|
+
|
|
846
|
+
```javascript
|
|
847
|
+
import {
|
|
848
|
+
addSafePattern,
|
|
849
|
+
checkPermission,
|
|
850
|
+
getSafePatterns
|
|
851
|
+
} from './compatibility';
|
|
852
|
+
|
|
853
|
+
function registerCustomPatterns() {
|
|
854
|
+
// Register a safe pattern for a plugin tool
|
|
855
|
+
addSafePattern({
|
|
856
|
+
tool: 'analytics:track',
|
|
857
|
+
pattern: /^(page_view|event|error)$/,
|
|
858
|
+
description: 'Only allows tracking specific event types',
|
|
859
|
+
source: 'myapp'
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
// Now check permission with valid input
|
|
863
|
+
let result = checkPermission('analytics:track');
|
|
864
|
+
console.log('Safe:', result.allowed); // true
|
|
865
|
+
|
|
866
|
+
// View all patterns
|
|
867
|
+
const patterns = getSafePatterns();
|
|
868
|
+
const myPatterns = patterns.filter(p => p.source === 'myapp');
|
|
869
|
+
console.log('My patterns:', myPatterns.length);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
registerCustomPatterns();
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
## Troubleshooting
|
|
876
|
+
|
|
877
|
+
### Plugins Not Discovered
|
|
878
|
+
|
|
879
|
+
**Problem:** `discoverPlugins()` returns empty array.
|
|
880
|
+
|
|
881
|
+
**Checklist:**
|
|
882
|
+
- Plugins are in `~/.claude/plugins/` or `~/.claude/installed-plugins/`
|
|
883
|
+
- Each plugin has a `plugin.json` in the root or `.claude-plugin/` subdirectory
|
|
884
|
+
- Plugin name doesn't conflict with reserved names (e.g., 'oh-my-claudecode')
|
|
885
|
+
- File permissions allow reading the directory
|
|
886
|
+
|
|
887
|
+
**Debug:**
|
|
888
|
+
```javascript
|
|
889
|
+
import { getPluginPaths } from './compatibility';
|
|
890
|
+
|
|
891
|
+
const paths = getPluginPaths();
|
|
892
|
+
console.log('Scanning paths:', paths);
|
|
893
|
+
|
|
894
|
+
// Check if directory exists
|
|
895
|
+
import { existsSync } from 'fs';
|
|
896
|
+
for (const path of paths) {
|
|
897
|
+
console.log(`${path}: ${existsSync(path) ? 'exists' : 'missing'}`);
|
|
898
|
+
}
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
### MCP Server Won't Connect
|
|
902
|
+
|
|
903
|
+
**Problem:** `bridge.connect()` times out.
|
|
904
|
+
|
|
905
|
+
**Checklist:**
|
|
906
|
+
- Server command is correct (e.g., `npx`, `node`)
|
|
907
|
+
- Command is executable and in PATH
|
|
908
|
+
- Arguments are valid
|
|
909
|
+
- Server implements MCP protocol (JSON-RPC 2.0)
|
|
910
|
+
- Check stderr output for errors
|
|
911
|
+
|
|
912
|
+
**Debug:**
|
|
913
|
+
```javascript
|
|
914
|
+
import { getMcpBridge } from './compatibility';
|
|
915
|
+
|
|
916
|
+
const bridge = getMcpBridge();
|
|
917
|
+
|
|
918
|
+
bridge.on('server-error', ({ server, error }) => {
|
|
919
|
+
console.error(`Server error from ${server}:`, error);
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
bridge.on('connect-error', ({ server, error }) => {
|
|
923
|
+
console.error(`Failed to connect to ${server}:`, error);
|
|
924
|
+
});
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
### Tools Not Showing Up
|
|
928
|
+
|
|
929
|
+
**Problem:** Registered tools don't appear in `getRegistry().getAllTools()`.
|
|
930
|
+
|
|
931
|
+
**Causes and solutions:**
|
|
932
|
+
- Plugin not discovered - Check plugin discovery first
|
|
933
|
+
- Tools not extracted - Ensure SKILL.md files exist in skills directory
|
|
934
|
+
- Namespace conflict - Two plugins with same namespace
|
|
935
|
+
- Tool registration failed - Check registry events for errors
|
|
936
|
+
|
|
937
|
+
**Debug:**
|
|
938
|
+
```javascript
|
|
939
|
+
import { getRegistry, discoverPlugins } from './compatibility';
|
|
940
|
+
|
|
941
|
+
const plugins = discoverPlugins();
|
|
942
|
+
for (const plugin of plugins) {
|
|
943
|
+
console.log(`${plugin.name}: ${plugin.tools.length} tools`);
|
|
944
|
+
for (const tool of plugin.tools) {
|
|
945
|
+
console.log(` - ${tool.name}`);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// Check what's actually registered
|
|
950
|
+
const registry = getRegistry();
|
|
951
|
+
const registered = registry.getAllTools();
|
|
952
|
+
console.log(`Registry has ${registered.length} tools`);
|
|
953
|
+
|
|
954
|
+
// Listen for registration events
|
|
955
|
+
registry.addEventListener(event => {
|
|
956
|
+
if (event.type === 'tool-registered') {
|
|
957
|
+
console.log('Registered:', event.data.tool);
|
|
958
|
+
} else if (event.type === 'tool-conflict') {
|
|
959
|
+
console.log('Conflict:', event.data.name, '→', event.data.winner);
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
```
|
|
963
|
+
|
|
964
|
+
### Permission Always Denied
|
|
965
|
+
|
|
966
|
+
**Problem:** Tools requiring permission always get denied even after user approval.
|
|
967
|
+
|
|
968
|
+
**Solutions:**
|
|
969
|
+
- Clear permission cache: `clearPermissionCache()`
|
|
970
|
+
- Ensure you're using same tool name/input for cached decision
|
|
971
|
+
- Check if tool matches a dangerous pattern that overrides caching
|
|
972
|
+
|
|
973
|
+
**Debug:**
|
|
974
|
+
```javascript
|
|
975
|
+
import {
|
|
976
|
+
checkPermission,
|
|
977
|
+
grantPermission,
|
|
978
|
+
getSafePatterns
|
|
979
|
+
} from './compatibility';
|
|
980
|
+
|
|
981
|
+
// Check if tool is in dangerous patterns
|
|
982
|
+
const patterns = getSafePatterns();
|
|
983
|
+
console.log('Safe patterns:', patterns.length);
|
|
984
|
+
|
|
985
|
+
// Manually grant
|
|
986
|
+
grantPermission('my-tool');
|
|
987
|
+
|
|
988
|
+
// Verify it's cached
|
|
989
|
+
const result = checkPermission('my-tool');
|
|
990
|
+
console.log('Allowed:', result.allowed);
|
|
991
|
+
console.log('Reason:', result.reason);
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
### Manifest Parse Errors
|
|
995
|
+
|
|
996
|
+
**Problem:** Plugin loads but manifest parsing fails.
|
|
997
|
+
|
|
998
|
+
**Checklist:**
|
|
999
|
+
- `plugin.json` is valid JSON (use `npm install -g jsonlint` to validate)
|
|
1000
|
+
- Required fields present: `name`, `version`
|
|
1001
|
+
- No syntax errors in paths or configs
|
|
1002
|
+
- File encoding is UTF-8
|
|
1003
|
+
|
|
1004
|
+
**Debug:**
|
|
1005
|
+
```javascript
|
|
1006
|
+
import { getPluginInfo } from './compatibility';
|
|
1007
|
+
|
|
1008
|
+
const plugin = getPluginInfo('my-plugin');
|
|
1009
|
+
if (plugin && !plugin.loaded) {
|
|
1010
|
+
console.error('Failed to load:', plugin.error);
|
|
1011
|
+
console.log('Manifest:', plugin.manifest);
|
|
1012
|
+
}
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
### MCP Tool Invocation Fails
|
|
1016
|
+
|
|
1017
|
+
**Problem:** Tool invocation returns error.
|
|
1018
|
+
|
|
1019
|
+
**Debug:**
|
|
1020
|
+
```javascript
|
|
1021
|
+
import { getMcpBridge } from './compatibility';
|
|
1022
|
+
|
|
1023
|
+
const bridge = getMcpBridge();
|
|
1024
|
+
|
|
1025
|
+
// Check connection
|
|
1026
|
+
console.log('Connected:', bridge.isConnected('myserver'));
|
|
1027
|
+
|
|
1028
|
+
// Get available tools
|
|
1029
|
+
const tools = bridge.getServerTools('myserver');
|
|
1030
|
+
console.log('Available tools:', tools.map(t => t.name));
|
|
1031
|
+
|
|
1032
|
+
// Try invocation with error details
|
|
1033
|
+
const result = await bridge.invokeTool('myserver', 'tool-name', {});
|
|
1034
|
+
if (!result.success) {
|
|
1035
|
+
console.error('Error:', result.error);
|
|
1036
|
+
console.error('Time:', result.executionTime, 'ms');
|
|
1037
|
+
}
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
## Best Practices
|
|
1041
|
+
|
|
1042
|
+
1. **Initialize early** - Call `initializeCompatibility()` on startup
|
|
1043
|
+
2. **Cache registry** - Reuse `getRegistry()` instance, don't repeatedly initialize
|
|
1044
|
+
3. **Handle permissions gracefully** - Always check `checkPermission()` before invoking dangerous tools
|
|
1045
|
+
4. **Monitor events** - Use event listeners to track plugin/server status changes
|
|
1046
|
+
5. **Version check** - Include version constraints in plugin manifests for compatibility
|
|
1047
|
+
6. **Test plugins locally** - Before publishing, test with local discovery paths
|
|
1048
|
+
7. **Use namespaces** - Set `namespace` in manifest to avoid conflicts
|
|
1049
|
+
8. **Document permissions** - Clearly explain why plugins need specific scopes
|
|
1050
|
+
9. **Handle errors** - MCP connections can fail; implement retry logic
|
|
1051
|
+
10. **Clean up** - Call `disconnectAll()` and `resetMcpBridge()` on shutdown
|