@useconductor/conductor 1.0.0
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/.claude-plugin/marketplace.json +33 -0
- package/.claude-plugin/plugin.json +23 -0
- package/.eslintrc.json +23 -0
- package/.gitattributes +6 -0
- package/.github/FUNDING.yml +15 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +91 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +63 -0
- package/.github/ISSUE_TEMPLATE/plugin_request.yml +71 -0
- package/.github/README.md +13 -0
- package/.github/workflows/README.md +22 -0
- package/.github/workflows/auto-release.yml +112 -0
- package/.github/workflows/ci.yml +49 -0
- package/.github/workflows/claude-code-review.yml +44 -0
- package/.github/workflows/claude.yml +36 -0
- package/.github/workflows/sync-install.yml +47 -0
- package/.mcp.json +9 -0
- package/.prettierrc.json +7 -0
- package/C.png +0 -0
- package/CHANGELOG.md +74 -0
- package/CLAUDE.md +118 -0
- package/CONTRIBUTING.md +231 -0
- package/LICENSE +201 -0
- package/README.md +179 -0
- package/SECURITY.md +47 -0
- package/commands/conductor-setup.md +11 -0
- package/commands/conductor-status.md +7 -0
- package/dist/ai/base.d.ts +44 -0
- package/dist/ai/base.d.ts.map +1 -0
- package/dist/ai/base.js +47 -0
- package/dist/ai/base.js.map +1 -0
- package/dist/ai/claude.d.ts +11 -0
- package/dist/ai/claude.d.ts.map +1 -0
- package/dist/ai/claude.js +149 -0
- package/dist/ai/claude.js.map +1 -0
- package/dist/ai/gemini.d.ts +15 -0
- package/dist/ai/gemini.d.ts.map +1 -0
- package/dist/ai/gemini.js +156 -0
- package/dist/ai/gemini.js.map +1 -0
- package/dist/ai/maestro.d.ts +22 -0
- package/dist/ai/maestro.d.ts.map +1 -0
- package/dist/ai/maestro.js +142 -0
- package/dist/ai/maestro.js.map +1 -0
- package/dist/ai/manager.d.ts +47 -0
- package/dist/ai/manager.d.ts.map +1 -0
- package/dist/ai/manager.js +450 -0
- package/dist/ai/manager.js.map +1 -0
- package/dist/ai/ollama.d.ts +16 -0
- package/dist/ai/ollama.d.ts.map +1 -0
- package/dist/ai/ollama.js +151 -0
- package/dist/ai/ollama.js.map +1 -0
- package/dist/ai/openai.d.ts +11 -0
- package/dist/ai/openai.d.ts.map +1 -0
- package/dist/ai/openai.js +132 -0
- package/dist/ai/openai.js.map +1 -0
- package/dist/ai/openrouter.d.ts +11 -0
- package/dist/ai/openrouter.d.ts.map +1 -0
- package/dist/ai/openrouter.js +139 -0
- package/dist/ai/openrouter.js.map +1 -0
- package/dist/bot/slack.d.ts +17 -0
- package/dist/bot/slack.d.ts.map +1 -0
- package/dist/bot/slack.js +144 -0
- package/dist/bot/slack.js.map +1 -0
- package/dist/bot/telegram.d.ts +19 -0
- package/dist/bot/telegram.d.ts.map +1 -0
- package/dist/bot/telegram.js +157 -0
- package/dist/bot/telegram.js.map +1 -0
- package/dist/cli/commands/ai.d.ts +4 -0
- package/dist/cli/commands/ai.d.ts.map +1 -0
- package/dist/cli/commands/ai.js +161 -0
- package/dist/cli/commands/ai.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +18 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +213 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts +15 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +281 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +16 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +750 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/lifecycle.d.ts +4 -0
- package/dist/cli/commands/lifecycle.d.ts.map +1 -0
- package/dist/cli/commands/lifecycle.js +84 -0
- package/dist/cli/commands/lifecycle.js.map +1 -0
- package/dist/cli/commands/marketplace.d.ts +13 -0
- package/dist/cli/commands/marketplace.d.ts.map +1 -0
- package/dist/cli/commands/marketplace.js +197 -0
- package/dist/cli/commands/marketplace.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +6 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +83 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/onboard.d.ts +10 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -0
- package/dist/cli/commands/onboard.js +207 -0
- package/dist/cli/commands/onboard.js.map +1 -0
- package/dist/cli/commands/plugin-create.d.ts +13 -0
- package/dist/cli/commands/plugin-create.d.ts.map +1 -0
- package/dist/cli/commands/plugin-create.js +122 -0
- package/dist/cli/commands/plugin-create.js.map +1 -0
- package/dist/cli/commands/plugins.d.ts +5 -0
- package/dist/cli/commands/plugins.d.ts.map +1 -0
- package/dist/cli/commands/plugins.js +30 -0
- package/dist/cli/commands/plugins.js.map +1 -0
- package/dist/cli/commands/release.d.ts +13 -0
- package/dist/cli/commands/release.d.ts.map +1 -0
- package/dist/cli/commands/release.js +243 -0
- package/dist/cli/commands/release.js.map +1 -0
- package/dist/cli/commands/telegram.d.ts +3 -0
- package/dist/cli/commands/telegram.d.ts.map +1 -0
- package/dist/cli/commands/telegram.js +20 -0
- package/dist/cli/commands/telegram.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +402 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/oauth.d.ts +8 -0
- package/dist/config/oauth.d.ts.map +1 -0
- package/dist/config/oauth.js +13 -0
- package/dist/config/oauth.js.map +1 -0
- package/dist/core/audit.d.ts +91 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/audit.js +233 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/circuit-breaker.d.ts +56 -0
- package/dist/core/circuit-breaker.d.ts.map +1 -0
- package/dist/core/circuit-breaker.js +107 -0
- package/dist/core/circuit-breaker.js.map +1 -0
- package/dist/core/conductor.d.ts +44 -0
- package/dist/core/conductor.d.ts.map +1 -0
- package/dist/core/conductor.js +200 -0
- package/dist/core/conductor.js.map +1 -0
- package/dist/core/config.d.ts +66 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +86 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/database.d.ts +59 -0
- package/dist/core/database.d.ts.map +1 -0
- package/dist/core/database.js +342 -0
- package/dist/core/database.js.map +1 -0
- package/dist/core/errors.d.ts +231 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +254 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/health.d.ts +72 -0
- package/dist/core/health.d.ts.map +1 -0
- package/dist/core/health.js +116 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/interfaces.d.ts +62 -0
- package/dist/core/interfaces.d.ts.map +1 -0
- package/dist/core/interfaces.js +8 -0
- package/dist/core/interfaces.js.map +1 -0
- package/dist/core/logger.d.ts +15 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +30 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/rbac.d.ts +132 -0
- package/dist/core/rbac.d.ts.map +1 -0
- package/dist/core/rbac.js +230 -0
- package/dist/core/rbac.js.map +1 -0
- package/dist/core/retry.d.ts +22 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +41 -0
- package/dist/core/retry.js.map +1 -0
- package/dist/core/webhooks.d.ts +92 -0
- package/dist/core/webhooks.d.ts.map +1 -0
- package/dist/core/webhooks.js +176 -0
- package/dist/core/webhooks.js.map +1 -0
- package/dist/core/zero-config.d.ts +22 -0
- package/dist/core/zero-config.d.ts.map +1 -0
- package/dist/core/zero-config.js +59 -0
- package/dist/core/zero-config.js.map +1 -0
- package/dist/dashboard/cli.d.ts +6 -0
- package/dist/dashboard/cli.d.ts.map +1 -0
- package/dist/dashboard/cli.js +42 -0
- package/dist/dashboard/cli.js.map +1 -0
- package/dist/dashboard/index.html +3426 -0
- package/dist/dashboard/server.d.ts +7 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +1427 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/mcp/server.d.ts +27 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +380 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/misc.d.ts +15 -0
- package/dist/mcp/tools/misc.d.ts.map +1 -0
- package/dist/mcp/tools/misc.js +49 -0
- package/dist/mcp/tools/misc.js.map +1 -0
- package/dist/plugins/builtin/calculator.d.ts +11 -0
- package/dist/plugins/builtin/calculator.d.ts.map +1 -0
- package/dist/plugins/builtin/calculator.js +166 -0
- package/dist/plugins/builtin/calculator.js.map +1 -0
- package/dist/plugins/builtin/colors.d.ts +15 -0
- package/dist/plugins/builtin/colors.d.ts.map +1 -0
- package/dist/plugins/builtin/colors.js +193 -0
- package/dist/plugins/builtin/colors.js.map +1 -0
- package/dist/plugins/builtin/cron.d.ts +40 -0
- package/dist/plugins/builtin/cron.d.ts.map +1 -0
- package/dist/plugins/builtin/cron.js +578 -0
- package/dist/plugins/builtin/cron.js.map +1 -0
- package/dist/plugins/builtin/crypto.d.ts +11 -0
- package/dist/plugins/builtin/crypto.d.ts.map +1 -0
- package/dist/plugins/builtin/crypto.js +83 -0
- package/dist/plugins/builtin/crypto.js.map +1 -0
- package/dist/plugins/builtin/database.d.ts +29 -0
- package/dist/plugins/builtin/database.d.ts.map +1 -0
- package/dist/plugins/builtin/database.js +230 -0
- package/dist/plugins/builtin/database.js.map +1 -0
- package/dist/plugins/builtin/docker.d.ts +12 -0
- package/dist/plugins/builtin/docker.d.ts.map +1 -0
- package/dist/plugins/builtin/docker.js +436 -0
- package/dist/plugins/builtin/docker.js.map +1 -0
- package/dist/plugins/builtin/fun.d.ts +11 -0
- package/dist/plugins/builtin/fun.d.ts.map +1 -0
- package/dist/plugins/builtin/fun.js +114 -0
- package/dist/plugins/builtin/fun.js.map +1 -0
- package/dist/plugins/builtin/gcal.d.ts +38 -0
- package/dist/plugins/builtin/gcal.d.ts.map +1 -0
- package/dist/plugins/builtin/gcal.js +280 -0
- package/dist/plugins/builtin/gcal.js.map +1 -0
- package/dist/plugins/builtin/gdrive.d.ts +26 -0
- package/dist/plugins/builtin/gdrive.d.ts.map +1 -0
- package/dist/plugins/builtin/gdrive.js +295 -0
- package/dist/plugins/builtin/gdrive.js.map +1 -0
- package/dist/plugins/builtin/github-actions.d.ts +38 -0
- package/dist/plugins/builtin/github-actions.d.ts.map +1 -0
- package/dist/plugins/builtin/github-actions.js +629 -0
- package/dist/plugins/builtin/github-actions.js.map +1 -0
- package/dist/plugins/builtin/github.d.ts +26 -0
- package/dist/plugins/builtin/github.d.ts.map +1 -0
- package/dist/plugins/builtin/github.js +800 -0
- package/dist/plugins/builtin/github.js.map +1 -0
- package/dist/plugins/builtin/gmail.d.ts +50 -0
- package/dist/plugins/builtin/gmail.d.ts.map +1 -0
- package/dist/plugins/builtin/gmail.js +445 -0
- package/dist/plugins/builtin/gmail.js.map +1 -0
- package/dist/plugins/builtin/hash.d.ts +11 -0
- package/dist/plugins/builtin/hash.d.ts.map +1 -0
- package/dist/plugins/builtin/hash.js +95 -0
- package/dist/plugins/builtin/hash.js.map +1 -0
- package/dist/plugins/builtin/homekit.d.ts +53 -0
- package/dist/plugins/builtin/homekit.d.ts.map +1 -0
- package/dist/plugins/builtin/homekit.js +341 -0
- package/dist/plugins/builtin/homekit.js.map +1 -0
- package/dist/plugins/builtin/index.d.ts +4 -0
- package/dist/plugins/builtin/index.d.ts.map +1 -0
- package/dist/plugins/builtin/index.js +96 -0
- package/dist/plugins/builtin/index.js.map +1 -0
- package/dist/plugins/builtin/jira.d.ts +50 -0
- package/dist/plugins/builtin/jira.d.ts.map +1 -0
- package/dist/plugins/builtin/jira.js +353 -0
- package/dist/plugins/builtin/jira.js.map +1 -0
- package/dist/plugins/builtin/linear.d.ts +35 -0
- package/dist/plugins/builtin/linear.d.ts.map +1 -0
- package/dist/plugins/builtin/linear.js +397 -0
- package/dist/plugins/builtin/linear.js.map +1 -0
- package/dist/plugins/builtin/lumen.d.ts +21 -0
- package/dist/plugins/builtin/lumen.d.ts.map +1 -0
- package/dist/plugins/builtin/lumen.js +404 -0
- package/dist/plugins/builtin/lumen.js.map +1 -0
- package/dist/plugins/builtin/memory.d.ts +22 -0
- package/dist/plugins/builtin/memory.d.ts.map +1 -0
- package/dist/plugins/builtin/memory.js +184 -0
- package/dist/plugins/builtin/memory.js.map +1 -0
- package/dist/plugins/builtin/n8n.d.ts +60 -0
- package/dist/plugins/builtin/n8n.d.ts.map +1 -0
- package/dist/plugins/builtin/n8n.js +519 -0
- package/dist/plugins/builtin/n8n.js.map +1 -0
- package/dist/plugins/builtin/network.d.ts +11 -0
- package/dist/plugins/builtin/network.d.ts.map +1 -0
- package/dist/plugins/builtin/network.js +88 -0
- package/dist/plugins/builtin/network.js.map +1 -0
- package/dist/plugins/builtin/notes.d.ts +47 -0
- package/dist/plugins/builtin/notes.d.ts.map +1 -0
- package/dist/plugins/builtin/notes.js +641 -0
- package/dist/plugins/builtin/notes.js.map +1 -0
- package/dist/plugins/builtin/notion.d.ts +47 -0
- package/dist/plugins/builtin/notion.d.ts.map +1 -0
- package/dist/plugins/builtin/notion.js +317 -0
- package/dist/plugins/builtin/notion.js.map +1 -0
- package/dist/plugins/builtin/shell.d.ts +12 -0
- package/dist/plugins/builtin/shell.d.ts.map +1 -0
- package/dist/plugins/builtin/shell.js +310 -0
- package/dist/plugins/builtin/shell.js.map +1 -0
- package/dist/plugins/builtin/slack.d.ts +31 -0
- package/dist/plugins/builtin/slack.d.ts.map +1 -0
- package/dist/plugins/builtin/slack.js +295 -0
- package/dist/plugins/builtin/slack.js.map +1 -0
- package/dist/plugins/builtin/spotify.d.ts +55 -0
- package/dist/plugins/builtin/spotify.d.ts.map +1 -0
- package/dist/plugins/builtin/spotify.js +623 -0
- package/dist/plugins/builtin/spotify.js.map +1 -0
- package/dist/plugins/builtin/stripe.d.ts +35 -0
- package/dist/plugins/builtin/stripe.d.ts.map +1 -0
- package/dist/plugins/builtin/stripe.js +376 -0
- package/dist/plugins/builtin/stripe.js.map +1 -0
- package/dist/plugins/builtin/system.d.ts +11 -0
- package/dist/plugins/builtin/system.d.ts.map +1 -0
- package/dist/plugins/builtin/system.js +91 -0
- package/dist/plugins/builtin/system.js.map +1 -0
- package/dist/plugins/builtin/text-tools.d.ts +11 -0
- package/dist/plugins/builtin/text-tools.d.ts.map +1 -0
- package/dist/plugins/builtin/text-tools.js +146 -0
- package/dist/plugins/builtin/text-tools.js.map +1 -0
- package/dist/plugins/builtin/timezone.d.ts +13 -0
- package/dist/plugins/builtin/timezone.d.ts.map +1 -0
- package/dist/plugins/builtin/timezone.js +164 -0
- package/dist/plugins/builtin/timezone.js.map +1 -0
- package/dist/plugins/builtin/todoist.d.ts +49 -0
- package/dist/plugins/builtin/todoist.d.ts.map +1 -0
- package/dist/plugins/builtin/todoist.js +540 -0
- package/dist/plugins/builtin/todoist.js.map +1 -0
- package/dist/plugins/builtin/translate.d.ts +11 -0
- package/dist/plugins/builtin/translate.d.ts.map +1 -0
- package/dist/plugins/builtin/translate.js +42 -0
- package/dist/plugins/builtin/translate.js.map +1 -0
- package/dist/plugins/builtin/url-tools.d.ts +11 -0
- package/dist/plugins/builtin/url-tools.d.ts.map +1 -0
- package/dist/plugins/builtin/url-tools.js +70 -0
- package/dist/plugins/builtin/url-tools.js.map +1 -0
- package/dist/plugins/builtin/vercel.d.ts +55 -0
- package/dist/plugins/builtin/vercel.d.ts.map +1 -0
- package/dist/plugins/builtin/vercel.js +514 -0
- package/dist/plugins/builtin/vercel.js.map +1 -0
- package/dist/plugins/builtin/weather.d.ts +13 -0
- package/dist/plugins/builtin/weather.d.ts.map +1 -0
- package/dist/plugins/builtin/weather.js +103 -0
- package/dist/plugins/builtin/weather.js.map +1 -0
- package/dist/plugins/builtin/x.d.ts +54 -0
- package/dist/plugins/builtin/x.d.ts.map +1 -0
- package/dist/plugins/builtin/x.js +402 -0
- package/dist/plugins/builtin/x.js.map +1 -0
- package/dist/plugins/manager.d.ts +77 -0
- package/dist/plugins/manager.d.ts.map +1 -0
- package/dist/plugins/manager.js +141 -0
- package/dist/plugins/manager.js.map +1 -0
- package/dist/plugins/validation.d.ts +18 -0
- package/dist/plugins/validation.d.ts.map +1 -0
- package/dist/plugins/validation.js +81 -0
- package/dist/plugins/validation.js.map +1 -0
- package/dist/security/auth.d.ts +23 -0
- package/dist/security/auth.d.ts.map +1 -0
- package/dist/security/auth.js +56 -0
- package/dist/security/auth.js.map +1 -0
- package/dist/security/keychain.d.ts +60 -0
- package/dist/security/keychain.d.ts.map +1 -0
- package/dist/security/keychain.js +213 -0
- package/dist/security/keychain.js.map +1 -0
- package/dist/utils/google-auth.d.ts +21 -0
- package/dist/utils/google-auth.d.ts.map +1 -0
- package/dist/utils/google-auth.js +135 -0
- package/dist/utils/google-auth.js.map +1 -0
- package/dist/utils/retry.d.ts +5 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +34 -0
- package/dist/utils/retry.js.map +1 -0
- package/docs/README.md +13 -0
- package/docs/api.md +210 -0
- package/docs/getting-started.md +100 -0
- package/docs/plugins.md +306 -0
- package/docs-site/.vitepress/config.ts +59 -0
- package/docs-site/README.md +12 -0
- package/docs-site/index.md +30 -0
- package/eslint.config.js +29 -0
- package/install.ps1 +334 -0
- package/install.sh +1119 -0
- package/local-install.sh +304 -0
- package/package.json +90 -0
- package/packages/README.md +11 -0
- package/packages/plugin-sdk/README.md +12 -0
- package/packages/plugin-sdk/package.json +22 -0
- package/packages/plugin-sdk/src/README.md +11 -0
- package/packages/plugin-sdk/src/index.ts +191 -0
- package/sdks/README.md +26 -0
- package/sdks/csharp/ConductorClient.cs +65 -0
- package/sdks/csharp/README.md +11 -0
- package/sdks/go/README.md +11 -0
- package/sdks/go/conductor.go +257 -0
- package/sdks/java/ConductorClient.java +27 -0
- package/sdks/java/README.md +11 -0
- package/sdks/php/README.md +11 -0
- package/sdks/php/src/Client.php +72 -0
- package/sdks/python/README.md +12 -0
- package/sdks/python/conductor/__init__.py +227 -0
- package/sdks/python/pyproject.toml +30 -0
- package/sdks/ruby/README.md +11 -0
- package/sdks/ruby/lib/conductor.rb +46 -0
- package/sdks/rust/Cargo.toml +14 -0
- package/sdks/rust/README.md +11 -0
- package/sdks/swift/README.md +11 -0
- package/sdks/swift/Sources/Conductor/ConductorClient.swift +65 -0
- package/skills/conductor-mcp/SKILL.md +38 -0
- package/src/README.md +20 -0
- package/src/ai/README.md +18 -0
- package/src/ai/base.ts +93 -0
- package/src/ai/claude.ts +162 -0
- package/src/ai/gemini.ts +188 -0
- package/src/ai/maestro.ts +168 -0
- package/src/ai/manager.ts +537 -0
- package/src/ai/ollama.ts +186 -0
- package/src/ai/openai.ts +147 -0
- package/src/ai/openrouter.ts +152 -0
- package/src/bot/README.md +12 -0
- package/src/bot/slack.ts +164 -0
- package/src/bot/telegram.ts +185 -0
- package/src/cli/README.md +24 -0
- package/src/cli/commands/README.md +20 -0
- package/src/cli/commands/ai.ts +170 -0
- package/src/cli/commands/doctor.ts +221 -0
- package/src/cli/commands/init.ts +348 -0
- package/src/cli/commands/install.ts +792 -0
- package/src/cli/commands/lifecycle.ts +95 -0
- package/src/cli/commands/marketplace.ts +253 -0
- package/src/cli/commands/mcp.ts +92 -0
- package/src/cli/commands/onboard.ts +248 -0
- package/src/cli/commands/plugin-create.ts +130 -0
- package/src/cli/commands/plugins.ts +36 -0
- package/src/cli/commands/release.ts +251 -0
- package/src/cli/commands/telegram.ts +25 -0
- package/src/cli/index.ts +450 -0
- package/src/config/README.md +11 -0
- package/src/config/oauth.ts +26 -0
- package/src/core/README.md +22 -0
- package/src/core/audit.ts +291 -0
- package/src/core/circuit-breaker.ts +129 -0
- package/src/core/conductor.ts +240 -0
- package/src/core/config.ts +149 -0
- package/src/core/database.ts +411 -0
- package/src/core/errors.ts +275 -0
- package/src/core/health.ts +159 -0
- package/src/core/interfaces.ts +75 -0
- package/src/core/logger.ts +33 -0
- package/src/core/rbac.ts +321 -0
- package/src/core/retry.ts +61 -0
- package/src/core/webhooks.ts +234 -0
- package/src/core/zero-config.ts +72 -0
- package/src/dashboard/README.md +15 -0
- package/src/dashboard/cli.ts +48 -0
- package/src/dashboard/index.html +3426 -0
- package/src/dashboard/server.ts +1544 -0
- package/src/mcp/README.md +20 -0
- package/src/mcp/server.ts +475 -0
- package/src/mcp/tools/README.md +11 -0
- package/src/mcp/tools/misc.ts +61 -0
- package/src/plugins/README.md +28 -0
- package/src/plugins/builtin/README.md +23 -0
- package/src/plugins/builtin/calculator.ts +178 -0
- package/src/plugins/builtin/colors.ts +201 -0
- package/src/plugins/builtin/cron.ts +649 -0
- package/src/plugins/builtin/crypto.ts +85 -0
- package/src/plugins/builtin/database.ts +235 -0
- package/src/plugins/builtin/docker.ts +426 -0
- package/src/plugins/builtin/fun.ts +118 -0
- package/src/plugins/builtin/gcal.ts +305 -0
- package/src/plugins/builtin/gdrive.ts +326 -0
- package/src/plugins/builtin/github-actions.ts +666 -0
- package/src/plugins/builtin/github.ts +912 -0
- package/src/plugins/builtin/gmail.ts +492 -0
- package/src/plugins/builtin/hash.ts +98 -0
- package/src/plugins/builtin/homekit.ts +389 -0
- package/src/plugins/builtin/index.ts +116 -0
- package/src/plugins/builtin/jira.ts +380 -0
- package/src/plugins/builtin/linear.ts +448 -0
- package/src/plugins/builtin/lumen.ts +497 -0
- package/src/plugins/builtin/memory.ts +200 -0
- package/src/plugins/builtin/n8n.ts +565 -0
- package/src/plugins/builtin/network.ts +92 -0
- package/src/plugins/builtin/notes.ts +689 -0
- package/src/plugins/builtin/notion.ts +348 -0
- package/src/plugins/builtin/shell.ts +334 -0
- package/src/plugins/builtin/slack.ts +327 -0
- package/src/plugins/builtin/spotify.ts +665 -0
- package/src/plugins/builtin/stripe.ts +388 -0
- package/src/plugins/builtin/system.ts +93 -0
- package/src/plugins/builtin/text-tools.ts +150 -0
- package/src/plugins/builtin/timezone.ts +173 -0
- package/src/plugins/builtin/todoist.ts +625 -0
- package/src/plugins/builtin/translate.ts +47 -0
- package/src/plugins/builtin/url-tools.ts +73 -0
- package/src/plugins/builtin/vercel.ts +546 -0
- package/src/plugins/builtin/weather.ts +112 -0
- package/src/plugins/builtin/x.ts +440 -0
- package/src/plugins/manager.ts +213 -0
- package/src/plugins/validation.ts +94 -0
- package/src/security/README.md +12 -0
- package/src/security/auth.ts +72 -0
- package/src/security/keychain.ts +226 -0
- package/src/utils/README.md +12 -0
- package/src/utils/google-auth.ts +159 -0
- package/src/utils/retry.ts +41 -0
- package/test-all.mjs +1256 -0
- package/test.mjs +633 -0
- package/tests/README.md +19 -0
- package/tests/calculator.test.ts +54 -0
- package/tests/docker.test.ts +42 -0
- package/tests/load.test.ts +129 -0
- package/tests/mcp.test.ts +14 -0
- package/tests/shell.test.ts +42 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# src/mcp
|
|
2
|
+
|
|
3
|
+
Model Context Protocol server implementation. Exposes plugin tools to AI agents via stdio or HTTP/SSE transport.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- `server.ts` - MCP server with circuit breaker, retry, audit logging, metrics, and Zod validation
|
|
8
|
+
- `tools/` - Tool definitions and handlers
|
|
9
|
+
|
|
10
|
+
## Architecture
|
|
11
|
+
|
|
12
|
+
The MCP server wraps every plugin tool with:
|
|
13
|
+
|
|
14
|
+
1. **Circuit breaker** — opens after repeated failures
|
|
15
|
+
2. **Retry with exponential backoff**
|
|
16
|
+
3. **Audit logging** — tamper-evident SHA-256 chained log
|
|
17
|
+
4. **Metrics** — in-memory call counts and latency per tool
|
|
18
|
+
5. **Zod validation** — validates inputs before handler invocation
|
|
19
|
+
|
|
20
|
+
Transport: `StdioServerTransport` for AI agent integration; HTTP/SSE for the dashboard.
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conductor MCP Server — The AI Tool Hub
|
|
3
|
+
*
|
|
4
|
+
* A world-class MCP server that exposes every Conductor plugin as an MCP tool.
|
|
5
|
+
* Any AI agent (Claude Code, Cursor, Cline, Aider, etc.) connects once and
|
|
6
|
+
* gets access to 100+ tools across GitHub, Docker, databases, file ops, and more.
|
|
7
|
+
*
|
|
8
|
+
* Architecture:
|
|
9
|
+
* - StdioServerTransport for direct AI agent integration
|
|
10
|
+
* - HTTP/SSE transport for web dashboards and remote agents
|
|
11
|
+
* - Auto-discovery of all enabled plugins
|
|
12
|
+
* - Zod-validated input schemas
|
|
13
|
+
* - Circuit breakers per tool (prevents cascading failures)
|
|
14
|
+
* - Automatic retries with exponential backoff
|
|
15
|
+
* - Audit logging (tamper-evident, SHA-256 chained)
|
|
16
|
+
* - Health check system with per-plugin status
|
|
17
|
+
* - Tool call metrics and latency tracking
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
21
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
22
|
+
import {
|
|
23
|
+
ListToolsRequestSchema,
|
|
24
|
+
CallToolRequestSchema,
|
|
25
|
+
ListResourcesRequestSchema,
|
|
26
|
+
ListPromptsRequestSchema,
|
|
27
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
28
|
+
import { createRequire } from 'module';
|
|
29
|
+
|
|
30
|
+
import type { Conductor } from '../core/conductor.js';
|
|
31
|
+
import { PluginManager } from '../plugins/manager.js';
|
|
32
|
+
import { validateTools } from '../plugins/validation.js';
|
|
33
|
+
import { CircuitBreaker, CircuitOpenError } from '../core/circuit-breaker.js';
|
|
34
|
+
import { withRetry } from '../core/retry.js';
|
|
35
|
+
import { AuditLogger } from '../core/audit.js';
|
|
36
|
+
import { HealthChecker } from '../core/health.js';
|
|
37
|
+
import { WebhookManager } from '../core/webhooks.js';
|
|
38
|
+
import { logger } from '../core/logger.js';
|
|
39
|
+
import { enableZeroConfigMode } from '../core/zero-config.js';
|
|
40
|
+
|
|
41
|
+
const _require = createRequire(import.meta.url);
|
|
42
|
+
const { version } = _require('../../package.json') as { version: string };
|
|
43
|
+
|
|
44
|
+
// ── Metrics ──────────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
interface ToolMetrics {
|
|
47
|
+
calls: number;
|
|
48
|
+
errors: number;
|
|
49
|
+
lastCallAt?: string;
|
|
50
|
+
avgLatencyMs: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const metrics: Map<string, ToolMetrics> = new Map();
|
|
54
|
+
|
|
55
|
+
function recordCall(name: string, success: boolean, latencyMs: number): void {
|
|
56
|
+
const existing = metrics.get(name) ?? { calls: 0, errors: 0, avgLatencyMs: 0 };
|
|
57
|
+
const n = existing.calls + 1;
|
|
58
|
+
metrics.set(name, {
|
|
59
|
+
calls: n,
|
|
60
|
+
errors: existing.errors + (success ? 0 : 1),
|
|
61
|
+
lastCallAt: new Date().toISOString(),
|
|
62
|
+
avgLatencyMs: existing.avgLatencyMs + (latencyMs - existing.avgLatencyMs) / n,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Tool Registry ────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
interface RegisteredTool {
|
|
69
|
+
name: string;
|
|
70
|
+
description: string;
|
|
71
|
+
inputSchema: Record<string, unknown>;
|
|
72
|
+
handler: (args: Record<string, unknown>) => Promise<unknown>;
|
|
73
|
+
plugin: string;
|
|
74
|
+
requiresApproval: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function buildToolRegistry(conductor: Conductor, pluginManager: PluginManager): Promise<RegisteredTool[]> {
|
|
78
|
+
const tools: RegisteredTool[] = [];
|
|
79
|
+
|
|
80
|
+
// Built-in conductor tools
|
|
81
|
+
tools.push({
|
|
82
|
+
name: 'conductor_status',
|
|
83
|
+
description: 'Get the current status of Conductor including enabled plugins and AI provider',
|
|
84
|
+
plugin: 'conductor',
|
|
85
|
+
requiresApproval: false,
|
|
86
|
+
inputSchema: { type: 'object', properties: {} },
|
|
87
|
+
handler: async () => {
|
|
88
|
+
const config = conductor.getConfig();
|
|
89
|
+
return {
|
|
90
|
+
version,
|
|
91
|
+
user: config.get('user.name') || 'not set',
|
|
92
|
+
ai_provider: config.get('ai.provider') || 'none',
|
|
93
|
+
plugins_enabled: config.get<string[]>('plugins.enabled') || [],
|
|
94
|
+
total_tools: tools.length,
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
tools.push({
|
|
100
|
+
name: 'conductor_tools_list',
|
|
101
|
+
description: 'List all available MCP tools grouped by plugin. Use this to discover what tools are available.',
|
|
102
|
+
plugin: 'conductor',
|
|
103
|
+
requiresApproval: false,
|
|
104
|
+
inputSchema: {
|
|
105
|
+
type: 'object',
|
|
106
|
+
properties: {
|
|
107
|
+
plugin: { type: 'string', description: 'Filter by plugin name' },
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
handler: async (args: { plugin?: string }) => {
|
|
111
|
+
const byPlugin: Record<string, string[]> = {};
|
|
112
|
+
for (const t of tools) {
|
|
113
|
+
if (args.plugin && t.plugin !== args.plugin) continue;
|
|
114
|
+
(byPlugin[t.plugin] ??= []).push(t.name);
|
|
115
|
+
}
|
|
116
|
+
return { plugins: byPlugin, total: tools.length };
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
tools.push({
|
|
121
|
+
name: 'conductor_health',
|
|
122
|
+
description: 'Get detailed health report for all Conductor subsystems',
|
|
123
|
+
plugin: 'conductor',
|
|
124
|
+
requiresApproval: false,
|
|
125
|
+
inputSchema: { type: 'object', properties: {} },
|
|
126
|
+
handler: async () => {
|
|
127
|
+
return await globalHealthChecker.detailed(version);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
tools.push({
|
|
132
|
+
name: 'conductor_audit_query',
|
|
133
|
+
description: 'Query the audit log for recent events. Supports filtering by actor, action, resource, result.',
|
|
134
|
+
plugin: 'conductor',
|
|
135
|
+
requiresApproval: false,
|
|
136
|
+
inputSchema: {
|
|
137
|
+
type: 'object',
|
|
138
|
+
properties: {
|
|
139
|
+
actor: { type: 'string', description: 'Filter by actor' },
|
|
140
|
+
action: { type: 'string', description: 'Filter by action type' },
|
|
141
|
+
resource: { type: 'string', description: 'Filter by resource' },
|
|
142
|
+
result: { type: 'string', enum: ['success', 'failure', 'denied', 'timeout'], description: 'Filter by result' },
|
|
143
|
+
limit: { type: 'number', description: 'Max entries to return', default: 50 },
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
handler: async (args: { actor?: string; action?: string; resource?: string; result?: string; limit?: number }) => {
|
|
147
|
+
return globalAuditLogger.query({ ...args, limit: args.limit ?? 50 });
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
tools.push({
|
|
152
|
+
name: 'conductor_metrics',
|
|
153
|
+
description: 'Get tool call metrics (calls, errors, avg latency)',
|
|
154
|
+
plugin: 'conductor',
|
|
155
|
+
requiresApproval: false,
|
|
156
|
+
inputSchema: { type: 'object', properties: {} },
|
|
157
|
+
handler: async () => {
|
|
158
|
+
const result: Record<string, ToolMetrics> = {};
|
|
159
|
+
for (const [name, m] of metrics) result[name] = m;
|
|
160
|
+
return { metrics: result };
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
tools.push({
|
|
165
|
+
name: 'conductor_webhooks_list',
|
|
166
|
+
description: 'List all webhook subscriptions',
|
|
167
|
+
plugin: 'conductor',
|
|
168
|
+
requiresApproval: false,
|
|
169
|
+
inputSchema: { type: 'object', properties: {} },
|
|
170
|
+
handler: async () => {
|
|
171
|
+
const subs = globalWebhookManager.list();
|
|
172
|
+
return {
|
|
173
|
+
subscriptions: subs.map((s) => ({
|
|
174
|
+
id: s.id,
|
|
175
|
+
url: s.url,
|
|
176
|
+
events: s.events,
|
|
177
|
+
active: s.active,
|
|
178
|
+
failures: s.consecutiveFailures,
|
|
179
|
+
})),
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Plugin tools (with Zod validation)
|
|
185
|
+
const pluginTools = await pluginManager.getEnabledTools();
|
|
186
|
+
const validatedTools = validateTools(pluginTools);
|
|
187
|
+
for (const pt of validatedTools) {
|
|
188
|
+
tools.push({
|
|
189
|
+
name: pt.name,
|
|
190
|
+
description: pt.description,
|
|
191
|
+
inputSchema: pt.inputSchema,
|
|
192
|
+
handler: pt.handler,
|
|
193
|
+
plugin: 'plugin',
|
|
194
|
+
requiresApproval: pt.requiresApproval ?? false,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return tools;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ── Global Infrastructure ────────────────────────────────────────────────────
|
|
202
|
+
|
|
203
|
+
let globalAuditLogger: AuditLogger;
|
|
204
|
+
let globalHealthChecker: HealthChecker;
|
|
205
|
+
let globalWebhookManager: WebhookManager;
|
|
206
|
+
const circuitBreakers: Map<string, CircuitBreaker> = new Map();
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Initialize global infrastructure (audit, health, webhooks).
|
|
210
|
+
* Called once when the MCP server starts.
|
|
211
|
+
*/
|
|
212
|
+
async function initInfrastructure(conductor: Conductor): Promise<void> {
|
|
213
|
+
const configDir = conductor.getConfig().getConfigDir();
|
|
214
|
+
|
|
215
|
+
// Audit logger
|
|
216
|
+
globalAuditLogger = new AuditLogger(configDir);
|
|
217
|
+
|
|
218
|
+
// Health checker
|
|
219
|
+
globalHealthChecker = new HealthChecker();
|
|
220
|
+
|
|
221
|
+
// Register health checks for each plugin
|
|
222
|
+
const pluginManager = new PluginManager(conductor);
|
|
223
|
+
await pluginManager.loadBuiltins();
|
|
224
|
+
for (const plugin of pluginManager.listPlugins()) {
|
|
225
|
+
globalHealthChecker.register(`plugin:${plugin.name}`, async () => ({
|
|
226
|
+
name: plugin.name,
|
|
227
|
+
status: plugin.enabled ? 'ok' : 'down',
|
|
228
|
+
message: plugin.enabled ? `${plugin.description}` : 'Plugin disabled',
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Webhook manager
|
|
233
|
+
globalWebhookManager = new WebhookManager(configDir);
|
|
234
|
+
await globalWebhookManager.load();
|
|
235
|
+
globalHealthChecker.setWebhookCount(globalWebhookManager.list().filter((s) => s.active).length);
|
|
236
|
+
|
|
237
|
+
// Graceful shutdown
|
|
238
|
+
process.on('SIGINT', async () => {
|
|
239
|
+
await globalAuditLogger.close();
|
|
240
|
+
process.exit(0);
|
|
241
|
+
});
|
|
242
|
+
process.on('SIGTERM', async () => {
|
|
243
|
+
await globalAuditLogger.close();
|
|
244
|
+
process.exit(0);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ── Server ───────────────────────────────────────────────────────────────────
|
|
249
|
+
|
|
250
|
+
export interface MCPServerOptions {
|
|
251
|
+
/** Transport mode. stdio for AI agents, http for web dashboards. */
|
|
252
|
+
transport?: 'stdio' | 'http';
|
|
253
|
+
/** HTTP port when transport is http. */
|
|
254
|
+
port?: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export async function startMCPServer(conductor: Conductor, options: MCPServerOptions = {}): Promise<void> {
|
|
258
|
+
// Enable zero-config mode (20+ tools work without API keys)
|
|
259
|
+
await enableZeroConfigMode(conductor);
|
|
260
|
+
|
|
261
|
+
// Initialize infrastructure
|
|
262
|
+
await initInfrastructure(conductor);
|
|
263
|
+
|
|
264
|
+
const pluginManager = new PluginManager(conductor);
|
|
265
|
+
const tools = await buildToolRegistry(conductor, pluginManager);
|
|
266
|
+
|
|
267
|
+
// Create circuit breakers for each tool
|
|
268
|
+
for (const tool of tools) {
|
|
269
|
+
circuitBreakers.set(tool.name, new CircuitBreaker());
|
|
270
|
+
globalHealthChecker.registerCircuitBreaker(tool.name, circuitBreakers.get(tool.name)!);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ── Startup summary ──────────────────────────────────────────────────────
|
|
274
|
+
const statuses = await pluginManager.getStatusSummary();
|
|
275
|
+
const ready = statuses.filter((s) => s.status === 'ready');
|
|
276
|
+
const notConfigured = statuses.filter((s) => s.status === 'not_configured');
|
|
277
|
+
const failed = statuses.filter((s) => s.status === 'init_failed');
|
|
278
|
+
|
|
279
|
+
process.stderr.write(`\n[conductor] v${version} — MCP server starting\n`);
|
|
280
|
+
process.stderr.write(`[conductor] ─────────────────────────────────────\n`);
|
|
281
|
+
|
|
282
|
+
for (const s of ready) {
|
|
283
|
+
process.stderr.write(`[conductor] ✓ ${s.name.padEnd(20)} ${s.toolCount} tool${s.toolCount !== 1 ? 's' : ''}\n`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
for (const s of notConfigured) {
|
|
287
|
+
process.stderr.write(`[conductor] ⚠ ${s.name.padEnd(20)} not configured\n`);
|
|
288
|
+
process.stderr.write(`[conductor] → ${s.setupCommand}\n`);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
for (const s of failed) {
|
|
292
|
+
process.stderr.write(`[conductor] ✗ ${s.name.padEnd(20)} init failed — ${s.error}\n`);
|
|
293
|
+
process.stderr.write(`[conductor] → conductor doctor ${s.name}\n`);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
process.stderr.write(`[conductor] ─────────────────────────────────────\n`);
|
|
297
|
+
process.stderr.write(`[conductor] ${tools.length} tools ready`);
|
|
298
|
+
if (notConfigured.length > 0)
|
|
299
|
+
process.stderr.write(` · ${notConfigured.length} need setup (run conductor plugins setup <name>)`);
|
|
300
|
+
if (failed.length > 0) process.stderr.write(` · ${failed.length} failed (run conductor doctor)`);
|
|
301
|
+
process.stderr.write(`\n\n`);
|
|
302
|
+
|
|
303
|
+
const server = new Server(
|
|
304
|
+
{ name: 'conductor', version },
|
|
305
|
+
{
|
|
306
|
+
capabilities: {
|
|
307
|
+
tools: {},
|
|
308
|
+
resources: {},
|
|
309
|
+
prompts: {},
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
// ── tools/list ───────────────────────────────────────────────────────────
|
|
315
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
316
|
+
tools: tools.map((t) => ({
|
|
317
|
+
name: t.name,
|
|
318
|
+
description: t.description,
|
|
319
|
+
inputSchema: t.inputSchema as Record<string, unknown>,
|
|
320
|
+
})),
|
|
321
|
+
}));
|
|
322
|
+
|
|
323
|
+
// ── tools/call ───────────────────────────────────────────────────────────
|
|
324
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
325
|
+
const { name, arguments: args = {} } = request.params;
|
|
326
|
+
const tool = tools.find((t) => t.name === name);
|
|
327
|
+
|
|
328
|
+
if (!tool) {
|
|
329
|
+
return {
|
|
330
|
+
content: [
|
|
331
|
+
{ type: 'text' as const, text: `Unknown tool: ${name}. Run conductor_tools_list to see available tools.` },
|
|
332
|
+
],
|
|
333
|
+
isError: true,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const start = Date.now();
|
|
338
|
+
|
|
339
|
+
try {
|
|
340
|
+
process.stderr.write(`[MCP] → ${name}\n`);
|
|
341
|
+
|
|
342
|
+
// Get or create circuit breaker for this tool
|
|
343
|
+
let breaker = circuitBreakers.get(name);
|
|
344
|
+
if (!breaker) {
|
|
345
|
+
breaker = new CircuitBreaker();
|
|
346
|
+
circuitBreakers.set(name, breaker);
|
|
347
|
+
globalHealthChecker.registerCircuitBreaker(name, breaker);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Execute through circuit breaker + retry
|
|
351
|
+
const result = await breaker.execute(async () =>
|
|
352
|
+
withRetry(async () => tool.handler(args), { maxAttempts: 3, baseDelay: 500, maxDelay: 10000 }),
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
const latency = Date.now() - start;
|
|
356
|
+
recordCall(name, true, latency);
|
|
357
|
+
globalHealthChecker.recordToolCall(true, latency);
|
|
358
|
+
|
|
359
|
+
// Audit log
|
|
360
|
+
await globalAuditLogger.toolCall('mcp', name, args, 'success', { latency_ms: latency });
|
|
361
|
+
|
|
362
|
+
// Emit webhook event
|
|
363
|
+
await globalWebhookManager.emit({
|
|
364
|
+
type: 'tool_called',
|
|
365
|
+
resource: name,
|
|
366
|
+
data: { latency_ms: latency, success: true },
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
|
370
|
+
process.stderr.write(`[MCP] ← ${name} (${latency}ms)\n`);
|
|
371
|
+
|
|
372
|
+
return {
|
|
373
|
+
content: [{ type: 'text' as const, text }],
|
|
374
|
+
};
|
|
375
|
+
} catch (err: unknown) {
|
|
376
|
+
const latency = Date.now() - start;
|
|
377
|
+
recordCall(name, false, latency);
|
|
378
|
+
globalHealthChecker.recordToolCall(false, latency);
|
|
379
|
+
|
|
380
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
381
|
+
const isCircuitOpen = err instanceof CircuitOpenError;
|
|
382
|
+
const result = isCircuitOpen ? 'denied' : 'failure';
|
|
383
|
+
|
|
384
|
+
// Audit log
|
|
385
|
+
await globalAuditLogger.toolCall('mcp', name, args, result as 'success' | 'failure' | 'denied' | 'timeout', {
|
|
386
|
+
latency_ms: latency,
|
|
387
|
+
error: message,
|
|
388
|
+
circuit_open: isCircuitOpen,
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// Emit webhook event
|
|
392
|
+
await globalWebhookManager.emit({
|
|
393
|
+
type: 'tool_failed',
|
|
394
|
+
resource: name,
|
|
395
|
+
data: { latency_ms: latency, error: message, circuit_open: isCircuitOpen },
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
logger.warn({ tool: name, error: message, latency_ms: latency, circuit_open: isCircuitOpen }, 'Tool call failed');
|
|
399
|
+
|
|
400
|
+
process.stderr.write(`[MCP] ✗ ${name}: ${message} (${latency}ms)\n`);
|
|
401
|
+
|
|
402
|
+
return {
|
|
403
|
+
content: [
|
|
404
|
+
{
|
|
405
|
+
type: 'text' as const,
|
|
406
|
+
text: isCircuitOpen
|
|
407
|
+
? `Service unavailable: ${name} is temporarily disabled due to repeated failures. Try again later.`
|
|
408
|
+
: `Error: ${message}`,
|
|
409
|
+
},
|
|
410
|
+
],
|
|
411
|
+
isError: true,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// ── resources/list ───────────────────────────────────────────────────────
|
|
417
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
418
|
+
resources: [],
|
|
419
|
+
}));
|
|
420
|
+
|
|
421
|
+
// ── prompts/list ─────────────────────────────────────────────────────────
|
|
422
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
|
|
423
|
+
prompts: [],
|
|
424
|
+
}));
|
|
425
|
+
|
|
426
|
+
// ── Transport ────────────────────────────────────────────────────────────
|
|
427
|
+
const transportMode = options.transport ?? 'stdio';
|
|
428
|
+
|
|
429
|
+
if (transportMode === 'http') {
|
|
430
|
+
const { SSEServerTransport } = await import('@modelcontextprotocol/sdk/server/sse.js');
|
|
431
|
+
const express = (await import('express')).default;
|
|
432
|
+
const rateLimit = (await import('express-rate-limit')).default;
|
|
433
|
+
const app = express();
|
|
434
|
+
const port = options.port ?? 3000;
|
|
435
|
+
|
|
436
|
+
// Rate limiting
|
|
437
|
+
app.use(rateLimit({ windowMs: 60_000, max: 1000, standardHeaders: true, legacyHeaders: false }));
|
|
438
|
+
|
|
439
|
+
// Health endpoints
|
|
440
|
+
app.get('/health', async (_req, res) => {
|
|
441
|
+
const report = await globalHealthChecker.detailed(version);
|
|
442
|
+
res.status(report.status === 'down' ? 503 : 200).json(report);
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
app.get('/health/ready', async (_req, res) => {
|
|
446
|
+
const ready = await globalHealthChecker.ready();
|
|
447
|
+
res.status(ready.ready ? 200 : 503).json(ready);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
451
|
+
let sseTransport: any = null;
|
|
452
|
+
|
|
453
|
+
app.get('/sse', async (_req, res) => {
|
|
454
|
+
sseTransport = new SSEServerTransport('/messages', res);
|
|
455
|
+
await server.connect(sseTransport);
|
|
456
|
+
process.stderr.write(`[MCP] SSE client connected\n`);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
app.post('/messages', async (req, res) => {
|
|
460
|
+
if (sseTransport) {
|
|
461
|
+
await sseTransport.handlePostMessage(req, res);
|
|
462
|
+
} else {
|
|
463
|
+
res.status(503).json({ error: 'No SSE connection established' });
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
app.listen(port, () => {
|
|
468
|
+
process.stderr.write(`[MCP] HTTP server listening on port ${port}\n`);
|
|
469
|
+
});
|
|
470
|
+
} else {
|
|
471
|
+
const transport = new StdioServerTransport();
|
|
472
|
+
await server.connect(transport);
|
|
473
|
+
process.stderr.write('[MCP] Connected via stdio\n');
|
|
474
|
+
}
|
|
475
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# src/mcp/tools
|
|
2
|
+
|
|
3
|
+
MCP tool definitions and handlers that bridge the protocol layer to plugin implementations.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- `misc.ts` - Miscellaneous tools not tied to a specific plugin
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
This directory contains tool definitions that are registered with the MCP server. Most tools are provided by plugins in `src/plugins/`, but cross-cutting or standalone tools live here. Each tool is wrapped with circuit breaker, retry, audit logging, and Zod validation by the MCP server.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { PluginManager } from '../../plugins/manager.js';
|
|
2
|
+
import { Conductor } from '../../core/conductor.js';
|
|
3
|
+
|
|
4
|
+
export interface MCPTool {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
inputSchema: Record<string, any>;
|
|
8
|
+
handler: (input: any) => Promise<any>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Get built-in tools that are always available. */
|
|
12
|
+
export function getBuiltinTools(conductor: Conductor): MCPTool[] {
|
|
13
|
+
return [
|
|
14
|
+
{
|
|
15
|
+
name: 'conductor_status',
|
|
16
|
+
description: 'Get the current status of Conductor',
|
|
17
|
+
inputSchema: { type: 'object', properties: {} },
|
|
18
|
+
handler: async () => {
|
|
19
|
+
const config = conductor.getConfig();
|
|
20
|
+
return {
|
|
21
|
+
user: config.get('user.name') || 'not set',
|
|
22
|
+
ai_provider: config.get('ai.provider') || 'none',
|
|
23
|
+
plugins_enabled: config.get<string[]>('plugins.enabled') || [],
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'conductor_recent_activity',
|
|
29
|
+
description: 'Get recent activity from Conductor',
|
|
30
|
+
inputSchema: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {
|
|
33
|
+
limit: { type: 'number', description: 'Number of entries', default: 10 },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
handler: async (input: { limit?: number }) => {
|
|
37
|
+
return await conductor.getRecentActivity(input.limit || 10);
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Get tools from enabled plugins only (not all registered plugins). */
|
|
44
|
+
export async function getPluginTools(pluginManager: PluginManager): Promise<MCPTool[]> {
|
|
45
|
+
// Only returns tools from plugins that are both enabled AND initialized
|
|
46
|
+
const pluginTools = await pluginManager.getEnabledTools();
|
|
47
|
+
|
|
48
|
+
return pluginTools.map((tool) => ({
|
|
49
|
+
name: tool.name,
|
|
50
|
+
description: tool.description,
|
|
51
|
+
inputSchema: tool.inputSchema,
|
|
52
|
+
handler: tool.handler,
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Get all available MCP tools (builtin + enabled plugins). */
|
|
57
|
+
export async function getAllTools(conductor: Conductor, pluginManager: PluginManager): Promise<MCPTool[]> {
|
|
58
|
+
const builtin = getBuiltinTools(conductor);
|
|
59
|
+
const pluginTools = await getPluginTools(pluginManager);
|
|
60
|
+
return [...builtin, ...pluginTools];
|
|
61
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# src/plugins
|
|
2
|
+
|
|
3
|
+
Plugin system for Conductor. Every capability is a plugin implementing the `Plugin` interface.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- `manager.ts` - `PluginManager` that handles registration, lazy initialization, and lifecycle
|
|
8
|
+
- `validation.ts` - Input validation for plugin tool calls
|
|
9
|
+
- `builtin/` - Built-in plugins shipped with Conductor
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
Plugins implement the `Plugin` interface:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
interface Plugin {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
version: string;
|
|
20
|
+
initialize(conductor: Conductor): Promise<void>;
|
|
21
|
+
isConfigured(): boolean;
|
|
22
|
+
getTools(): PluginTool[];
|
|
23
|
+
configSchema?: PluginConfigSchema;
|
|
24
|
+
getContext?(): Promise<string | null>;
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Plugins are **lazily initialized** — `PluginManager.getPlugin(name)` initializes on first call. Built-in plugins live in `builtin/`; external plugins are loaded from `~/.conductor/plugins/` as `.js` files.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# src/plugins/builtin
|
|
2
|
+
|
|
3
|
+
Built-in plugins shipped with Conductor. Each file implements a `Plugin` for a specific capability.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- `index.ts` - Registry of all builtin plugins
|
|
8
|
+
- `shell.ts` - Shell command execution with whitelist allowlist
|
|
9
|
+
- `github.ts` / `github-actions.ts` - GitHub repository and CI/CD operations
|
|
10
|
+
- `gcal.ts` / `gdrive.ts` / `gmail.ts` - Google Workspace integrations
|
|
11
|
+
- `slack.ts` - Slack messaging and channel management
|
|
12
|
+
- `linear.ts` / `notion.ts` / `todoist.ts` - Project management tools
|
|
13
|
+
- `docker.ts` - Docker container management
|
|
14
|
+
- `database.ts` - Database query operations
|
|
15
|
+
- `calculator.ts` / `crypto.ts` / `hash.ts` - Math and crypto utilities
|
|
16
|
+
- `text-tools.ts` / `url-tools.ts` / `translate.ts` - Text manipulation
|
|
17
|
+
- `weather.ts` / `timezone.ts` / `system.ts` - System and info tools
|
|
18
|
+
- `n8n.ts` / `vercel.ts` / `spotify.ts` / `x.ts` - Third-party service integrations
|
|
19
|
+
- `cron.ts` / `memory.ts` / `notes.ts` / `fun.ts` / `colors.ts` / `network.ts` / `homekit.ts` / `lumen.ts` - Utility plugins
|
|
20
|
+
|
|
21
|
+
## Architecture
|
|
22
|
+
|
|
23
|
+
Each plugin is auto-registered via `index.ts` and lazily initialized by `PluginManager`. Plugins declare their tools via `getTools()` and can provide config schemas for `conductor config setup <plugin>`. Secret credentials use `secret: true` fields stored in the OS keychain.
|