@geraldmaron/construct 1.4.1 → 1.5.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/.env.example +36 -0
- package/README.md +41 -7
- package/bin/construct +1029 -65
- package/bin/construct-postinstall.mjs +27 -2
- package/config/tag-vocabulary.json +264 -0
- package/examples/distribution/sources/deck-one-pager.md +1 -1
- package/lib/acp/server.mjs +21 -7
- package/lib/adapters-sync.mjs +2 -1
- package/lib/audit-trail.mjs +185 -2
- package/lib/beads/auto-close.mjs +2 -1
- package/lib/beads/drift.mjs +2 -1
- package/lib/bridges/copilot-proxy.mjs +20 -5
- package/lib/certification/skill-inventory.mjs +10 -1
- package/lib/cli/approvals.mjs +147 -0
- package/lib/cli-commands.mjs +105 -14
- package/lib/comment-lint.mjs +127 -8
- package/lib/config/schema.mjs +7 -30
- package/lib/config/source-target-registry.mjs +70 -0
- package/lib/config/source-targets.mjs +179 -205
- package/lib/contracts/coverage.mjs +77 -0
- package/lib/contracts/validate.mjs +102 -13
- package/lib/contracts/violation-log.mjs +50 -4
- package/lib/db/migrate.mjs +69 -0
- package/lib/db/migrations/001_orchestration_runs.sql +9 -0
- package/lib/db/migrations/002_queue_provider.sql +50 -0
- package/lib/db/migrations/003_worker_registry.sql +17 -0
- package/lib/db/migrations/004_trace_events.sql +16 -0
- package/lib/db/migrations/005_shared_memory.sql +15 -0
- package/lib/db/migrations/006_orchestration_runs_tenant.sql +5 -0
- package/lib/decisions/enforced-baseline.json +0 -2
- package/lib/decisions/registry.mjs +3 -2
- package/lib/deployment/parity-contract.mjs +1 -1
- package/lib/deployment-mode.mjs +78 -2
- package/lib/diagram-export.mjs +10 -1
- package/lib/distill.mjs +5 -2
- package/lib/docs-verify.mjs +2 -1
- package/lib/doctor/cli.mjs +1 -0
- package/lib/doctor/command-on-path.mjs +24 -0
- package/lib/doctor/diagnosis.mjs +109 -0
- package/lib/doctor/embedding-health.mjs +50 -0
- package/lib/doctor/engine-health.mjs +93 -0
- package/lib/doctor/graph-validate.mjs +47 -0
- package/lib/doctor/index.mjs +23 -4
- package/lib/doctor/sidecar-providers.mjs +56 -0
- package/lib/doctor/watchers/consistency.mjs +93 -1
- package/lib/doctor/watchers/cx-budget.mjs +1 -1
- package/lib/doctor/watchers/graph-staleness.mjs +1 -1
- package/lib/doctor/watchers/mcp-protocol.mjs +17 -0
- package/lib/doctor/watchers/oracle-liveness.mjs +92 -0
- package/lib/doctor/watchers/orchestration-runs.mjs +108 -0
- package/lib/doctor/watchers/provider-breaker.mjs +78 -0
- package/lib/document-export.mjs +52 -27
- package/lib/document-extract/docling-client.mjs +9 -5
- package/lib/document-extract/docling-sidecar.py +30 -0
- package/lib/document-extract.mjs +1 -1
- package/lib/document-ingest.mjs +9 -0
- package/lib/embed/approval-queue.mjs +184 -88
- package/lib/embed/authority-guard.mjs +65 -2
- package/lib/embed/capability-jobs.mjs +365 -0
- package/lib/embed/capability-lifecycle.mjs +219 -0
- package/lib/embed/capability-loader.mjs +303 -0
- package/lib/embed/capability-runtime.mjs +58 -0
- package/lib/embed/cli.mjs +185 -8
- package/lib/embed/config.mjs +4 -0
- package/lib/embed/daemon.mjs +125 -6
- package/lib/embed/demand-fetch.mjs +190 -54
- package/lib/embed/inbox.mjs +12 -10
- package/lib/embed/presets/ops-triage.mjs +236 -0
- package/lib/embed/presets/pm-feedback.mjs +341 -0
- package/lib/embed/presets/tpm.mjs +401 -0
- package/lib/embed/providers/jira.mjs +72 -1
- package/lib/embed/providers/registry.mjs +140 -33
- package/lib/embed/worker.mjs +5 -0
- package/lib/embedded-contract/capability.mjs +4 -0
- package/lib/embedded-contract/execution.mjs +1 -1
- package/lib/embedded-contract/model-resolve.mjs +53 -3
- package/lib/embedded-contract/workflow-defs.mjs +48 -73
- package/lib/embedded-contract/workflow-invoke.mjs +144 -4
- package/lib/embedded-contract/workflows/architecture-review.manifest.json +15 -0
- package/lib/embedded-contract/workflows/data-structure.manifest.json +14 -0
- package/lib/embedded-contract/workflows/evidence-ingest.manifest.json +14 -0
- package/lib/embedded-contract/workflows/memo-draft.manifest.json +14 -0
- package/lib/embedded-contract/workflows/operations-triage.manifest.json +18 -0
- package/lib/embedded-contract/workflows/operations.manifest.json +18 -0
- package/lib/embedded-contract/workflows/pm-feedback.manifest.json +18 -0
- package/lib/embedded-contract/workflows/prd-draft.manifest.json +15 -0
- package/lib/embedded-contract/workflows/proposal-review.manifest.json +15 -0
- package/lib/embedded-contract/workflows/research-synthesis.manifest.json +14 -0
- package/lib/embedded-contract/workflows/risk-review.manifest.json +15 -0
- package/lib/embedded-contract/workflows/structure-notes.manifest.json +14 -0
- package/lib/embedded-contract/workflows/transcript-process.manifest.json +14 -0
- package/lib/embedded-contract/workflows/triage.manifest.json +14 -0
- package/lib/env-config.mjs +60 -11
- package/lib/export-validate.mjs +34 -2
- package/lib/extensions/index.mjs +27 -0
- package/lib/extensions/loader.mjs +120 -0
- package/lib/extensions/manifest-schema.mjs +141 -0
- package/lib/extensions/manifests/anthropic.manifest.json +12 -0
- package/lib/extensions/manifests/atlassian-confluence.manifest.json +12 -0
- package/lib/extensions/manifests/atlassian-jira.manifest.json +53 -0
- package/lib/extensions/manifests/directory.manifest.json +12 -0
- package/lib/extensions/manifests/docling.manifest.json +37 -0
- package/lib/extensions/manifests/echo.manifest.json +8 -0
- package/lib/extensions/manifests/feedback.manifest.json +12 -0
- package/lib/extensions/manifests/github-copilot.manifest.json +12 -0
- package/lib/extensions/manifests/github.manifest.json +52 -0
- package/lib/extensions/manifests/linear.manifest.json +50 -0
- package/lib/extensions/manifests/local.manifest.json +12 -0
- package/lib/extensions/manifests/ollama.manifest.json +12 -0
- package/lib/extensions/manifests/openai.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-anthropic.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-deepseek.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-google.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-llama.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-qwen.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter.manifest.json +12 -0
- package/lib/extensions/manifests/postgres.manifest.json +12 -0
- package/lib/extensions/manifests/salesforce.manifest.json +12 -0
- package/lib/extensions/manifests/slack.manifest.json +58 -0
- package/lib/extensions/manifests/whisper.manifest.json +36 -0
- package/lib/extensions/validate.mjs +175 -0
- package/lib/features.mjs +13 -9
- package/lib/flows/checkpoint.mjs +184 -0
- package/lib/flows/constants.mjs +27 -0
- package/lib/flows/define.mjs +146 -0
- package/lib/flows/engine.mjs +249 -0
- package/lib/flows/errors.mjs +19 -0
- package/lib/flows/index.mjs +27 -0
- package/lib/flows/joins.mjs +18 -0
- package/lib/flows/schema.mjs +90 -0
- package/lib/flows/state.mjs +31 -0
- package/lib/frameworks/loader.mjs +99 -0
- package/lib/frameworks/schema.mjs +157 -0
- package/lib/graph/build-from-corpus.mjs +67 -0
- package/lib/graph/build-from-embed.mjs +82 -0
- package/lib/graph/build-from-registry.mjs +164 -3
- package/lib/graph/cli.mjs +456 -12
- package/lib/graph/gap-queries.mjs +156 -0
- package/lib/graph/gaps.mjs +41 -0
- package/lib/graph/impacted.mjs +129 -0
- package/lib/graph/runtime-evidence.mjs +177 -0
- package/lib/graph/security-coverage.mjs +113 -0
- package/lib/graph/staleness.mjs +241 -10
- package/lib/graph/store.mjs +24 -7
- package/lib/graph/validate.mjs +161 -0
- package/lib/headhunt.mjs +9 -8
- package/lib/health-check.mjs +15 -7
- package/lib/hook-health.mjs +1 -1
- package/lib/hooks/agent-tracker.mjs +10 -4
- package/lib/hooks/edit-guard.mjs +3 -3
- package/lib/hooks/graph-impact-advisory.mjs +2 -2
- package/lib/hooks/guard-bash.mjs +41 -15
- package/lib/hooks/mcp-health-check.mjs +11 -4
- package/lib/hooks/model-fallback.mjs +50 -6
- package/lib/hooks/orchestration-dispatch-guard.mjs +14 -3
- package/lib/hooks/pre-compact.mjs +181 -173
- package/lib/hooks/rule-verifier.mjs +2 -1
- package/lib/hooks/session-reflect.mjs +2 -1
- package/lib/hooks/session-start.mjs +3 -3
- package/lib/host/readiness.mjs +109 -0
- package/lib/host-capabilities.mjs +13 -2
- package/lib/host-disposition.mjs +29 -8
- package/lib/identity.mjs +92 -0
- package/lib/ingest/degraded-extract.mjs +96 -0
- package/lib/ingest/docling-remote.mjs +2 -1
- package/lib/ingest/provider-extract.mjs +7 -19
- package/lib/ingest/sidecar-providers.mjs +196 -0
- package/lib/ingest-tooling.mjs +11 -5
- package/lib/init-unified.mjs +55 -38
- package/lib/init-update.mjs +2 -1
- package/lib/install/legacy-global-cleanup.mjs +25 -0
- package/lib/install/stage-project.mjs +41 -4
- package/lib/intake/daemon.mjs +99 -8
- package/lib/intake/git-queue.mjs +110 -38
- package/lib/intake/prepare.mjs +2 -0
- package/lib/intake/queue-registry.mjs +50 -0
- package/lib/intake/queue.mjs +133 -17
- package/lib/intake/session-prelude.mjs +57 -8
- package/lib/integrations/intake-integrations.mjs +61 -111
- package/lib/intent-classifier.mjs +43 -5
- package/lib/libreoffice-export.mjs +8 -8
- package/lib/logging/rotate.mjs +5 -4
- package/lib/mcp/broker.mjs +332 -17
- package/lib/mcp/denied-store.mjs +95 -0
- package/lib/mcp/destructive-approval.mjs +57 -0
- package/lib/mcp/destructive-gate.mjs +30 -0
- package/lib/mcp/dispatch-envelope.mjs +199 -0
- package/lib/mcp/memory-bridge.mjs +2 -1
- package/lib/mcp/server.mjs +185 -1268
- package/lib/mcp/tool-definitions-memory.mjs +376 -0
- package/lib/mcp/tool-definitions-project.mjs +271 -0
- package/lib/mcp/tool-definitions-skills.mjs +311 -0
- package/lib/mcp/tool-definitions-workflow.mjs +398 -0
- package/lib/mcp/tool-definitions.mjs +25 -0
- package/lib/mcp/tool-rate-limit.mjs +47 -0
- package/lib/mcp/tool-registry.mjs +107 -0
- package/lib/mcp/tool-safety.mjs +95 -0
- package/lib/mcp/tool-surface-parity.mjs +60 -0
- package/lib/mcp/tools/orchestration-delegation-next.tool.mjs +68 -0
- package/lib/mcp/tools/orchestration-run.mjs +197 -19
- package/lib/mcp/tools/orchestration-task-result.tool.mjs +77 -0
- package/lib/mcp/tools/project.mjs +25 -8
- package/lib/mcp/tools/provider-write.mjs +187 -0
- package/lib/mcp/tools/scope.mjs +0 -3
- package/lib/mcp/tools/skills.mjs +1 -1
- package/lib/mcp/tools/storage.mjs +2 -2
- package/lib/mcp/tools/web-search-governance.mjs +96 -0
- package/lib/mcp/tools/web-search.mjs +5 -76
- package/lib/mcp/transport/auth.mjs +238 -0
- package/lib/mcp/transport/http.mjs +136 -0
- package/lib/mcp/transport/mode.mjs +31 -0
- package/lib/mcp/transport/stdio.mjs +22 -0
- package/lib/mcp-catalog.json +4 -4
- package/lib/mcp-manager.mjs +34 -23
- package/lib/mcp-platform-config.mjs +53 -20
- package/lib/mode-capabilities.mjs +109 -0
- package/lib/model-router.mjs +42 -9
- package/lib/models/catalog.mjs +40 -1
- package/lib/net-guard.mjs +247 -0
- package/lib/observation-store.mjs +6 -2
- package/lib/ollama/provision-context.mjs +2 -1
- package/lib/opencode-config.mjs +22 -3
- package/lib/opencode-runtime-plugin.mjs +120 -2
- package/lib/oracle/actions.mjs +204 -10
- package/lib/oracle/cli.mjs +24 -3
- package/lib/oracle/daemon-entry.mjs +6 -0
- package/lib/oracle/dispatch.mjs +2 -1
- package/lib/oracle/execute.mjs +2 -2
- package/lib/oracle/gaps.mjs +3 -3
- package/lib/oracle/heartbeat.mjs +53 -0
- package/lib/oracle/read-model.mjs +69 -13
- package/lib/oracle/reconcile.mjs +3 -46
- package/lib/oracle/routing.mjs +37 -31
- package/lib/oracle/synthesize.mjs +1 -1
- package/lib/orchestration/classification.mjs +434 -0
- package/lib/orchestration/delegation-flow.mjs +132 -0
- package/lib/orchestration/flow-selection.mjs +418 -0
- package/lib/orchestration/gates.mjs +244 -0
- package/lib/orchestration/host-sampling.mjs +121 -0
- package/lib/orchestration/policy-constants.mjs +48 -0
- package/lib/orchestration/provider-outcome.mjs +197 -0
- package/lib/orchestration/readiness.mjs +114 -13
- package/lib/orchestration/run-store-postgres.mjs +32 -26
- package/lib/orchestration/run-store-sqlite.mjs +8 -14
- package/lib/orchestration/run-store.mjs +25 -12
- package/lib/orchestration/runtime.mjs +508 -62
- package/lib/orchestration/store.mjs +87 -12
- package/lib/orchestration/trace-store.mjs +125 -0
- package/lib/orchestration/web-capability.mjs +60 -0
- package/lib/orchestration/worker-runtime.mjs +162 -0
- package/lib/orchestration/worker.mjs +763 -80
- package/lib/orchestration-policy.mjs +67 -1111
- package/lib/output-quality.mjs +61 -2
- package/lib/packs/cli.mjs +144 -0
- package/lib/packs/core-pack.mjs +112 -0
- package/lib/packs/enablement.mjs +187 -0
- package/lib/packs/index.mjs +23 -0
- package/lib/packs/loader.mjs +176 -0
- package/lib/packs/manifest-schema.mjs +58 -0
- package/lib/packs/prompts.mjs +120 -0
- package/lib/packs/validate.mjs +208 -0
- package/lib/path-policy.mjs +56 -0
- package/lib/plugin-registry.mjs +4 -5
- package/lib/policy/audit-gate.mjs +42 -0
- package/lib/policy/consumption-budget.mjs +149 -0
- package/lib/policy/engine.mjs +81 -6
- package/lib/policy/role-authority.mjs +89 -0
- package/lib/prompt-composer.js +19 -3
- package/lib/providers/contract/adapters/confluence/governed-write.mjs +215 -0
- package/lib/providers/contract/adapters/confluence/manifest.json +17 -0
- package/lib/providers/contract/adapters/confluence/transport.mjs +135 -0
- package/lib/providers/contract/adapters/github/governed-write.mjs +121 -0
- package/lib/providers/contract/adapters/github/index.mjs +38 -3
- package/lib/providers/contract/adapters/jira/adf.mjs +151 -0
- package/lib/providers/contract/adapters/jira/createmeta.mjs +143 -0
- package/lib/providers/contract/adapters/jira/governed-write.mjs +182 -0
- package/lib/providers/contract/adapters/jira/manifest.json +17 -0
- package/lib/providers/contract/adapters/jira/transport.mjs +119 -0
- package/lib/providers/contract.mjs +207 -0
- package/lib/providers/credential-bootstrap.mjs +7 -4
- package/lib/providers/credential-sources.mjs +14 -2
- package/lib/providers/directory/index.mjs +261 -0
- package/lib/providers/feedback/index.mjs +392 -0
- package/lib/providers/filter-audit.mjs +68 -0
- package/lib/providers/filter-schema.mjs +54 -0
- package/lib/providers/github/index.mjs +31 -0
- package/lib/providers/instance-config.mjs +215 -0
- package/lib/providers/op-locate.mjs +96 -0
- package/lib/providers/op-run.mjs +64 -9
- package/lib/providers/registry.mjs +26 -3
- package/lib/providers/secret-audit-wiring.mjs +41 -18
- package/lib/providers/secret-resolver.mjs +263 -31
- package/lib/publish-template.mjs +6 -3
- package/lib/publish-tooling.mjs +4 -0
- package/lib/publish.mjs +32 -4
- package/lib/queue/pg-queue.mjs +395 -0
- package/lib/reflect.mjs +2 -1
- package/lib/registry/assemble.mjs +28 -2
- package/lib/registry/catalog.mjs +6 -0
- package/lib/registry/consolidation.mjs +8 -1
- package/lib/registry/custom-scaffold.mjs +200 -0
- package/lib/registry/custom-schema.mjs +137 -0
- package/lib/registry/loader.mjs +15 -4
- package/lib/registry/manifests/format-engines.default.json +15 -0
- package/lib/registry/manifests/surface-map.default.json +46 -0
- package/lib/registry/retired-paths.mjs +1 -0
- package/lib/registry/surface-map.mjs +100 -50
- package/lib/registry/validate.mjs +3 -3
- package/lib/render-visual-check.mjs +240 -0
- package/lib/resources/budget.mjs +40 -17
- package/lib/roles/flavor-bindings.mjs +36 -14
- package/lib/roles/gateway.mjs +15 -8
- package/lib/roots.mjs +107 -0
- package/lib/runtime/uv-bootstrap.mjs +32 -6
- package/lib/runtime/whisper-bootstrap.mjs +11 -3
- package/lib/runtime-env.mjs +5 -2
- package/lib/sandbox.mjs +1 -1
- package/lib/scheduler/index.mjs +8 -20
- package/lib/schema-infer.mjs +31 -2
- package/lib/scopes/lifecycle.mjs +29 -25
- package/lib/scopes/loader.mjs +49 -12
- package/lib/scopes/teams.mjs +1 -1
- package/lib/security/ingest-boundary.mjs +80 -0
- package/lib/security/recall-wrapper.mjs +99 -0
- package/lib/security/trust.mjs +132 -0
- package/lib/service-manager.mjs +93 -24
- package/lib/setup.mjs +41 -23
- package/lib/skills-apply.mjs +4 -2
- package/lib/specialists/postconditions.mjs +2 -2
- package/lib/state-root.mjs +147 -0
- package/lib/status.mjs +597 -6
- package/lib/storage/admin.mjs +84 -7
- package/lib/storage/backend-registry.mjs +73 -0
- package/lib/storage/backend.mjs +63 -9
- package/lib/storage/embeddings-openai.mjs +12 -2
- package/lib/storage/hybrid-query.mjs +11 -3
- package/lib/storage/retrieval-hardening.mjs +384 -0
- package/lib/storage/shared-memory.mjs +158 -0
- package/lib/storage/vector-client.mjs +69 -2
- package/lib/team/health.mjs +72 -0
- package/lib/telemetry/backends/local.mjs +9 -3
- package/lib/telemetry/client.mjs +3 -7
- package/lib/template-registry.mjs +10 -12
- package/lib/tenant/context.mjs +82 -0
- package/lib/tenant/isolation.mjs +129 -0
- package/lib/test-corpus-inventory.mjs +103 -2
- package/lib/uninstall/uninstall.mjs +78 -12
- package/lib/validator.mjs +4 -6
- package/lib/worker/entrypoint.mjs +2 -1
- package/lib/worker/run.mjs +2 -2
- package/lib/worker/trace.mjs +5 -11
- package/lib/workflow-state.mjs +52 -8
- package/lib/workflows/liveness.mjs +203 -0
- package/lib/workflows/loader.mjs +177 -0
- package/lib/workflows/manifest-schema.mjs +71 -0
- package/lib/workflows/surface-parity.mjs +118 -0
- package/lib/workflows/validate.mjs +127 -0
- package/lib/writes/control-plane.mjs +140 -0
- package/lib/writes/envelope.mjs +206 -0
- package/lib/writes/sent-log.mjs +86 -0
- package/lib/writes/write-intent.mjs +109 -0
- package/package.json +20 -7
- package/personas/construct.md +12 -3
- package/registry/agent-manifest.json +117 -0
- package/registry/capabilities.json +1987 -0
- package/rules/common/comments.md +1 -0
- package/schemas/brand-voice.schema.json +24 -0
- package/schemas/capability-registry.schema.json +72 -0
- package/schemas/certification-run.schema.json +130 -0
- package/schemas/demo-recording.schema.json +46 -0
- package/schemas/eval-dataset.schema.json +79 -0
- package/schemas/execution-capability-profile.schema.json +46 -0
- package/schemas/execution-policy.schema.json +114 -0
- package/schemas/improvement-proposal.schema.json +65 -0
- package/schemas/mcp-tool-output.schema.json +61 -0
- package/schemas/platform-capabilities.schema.json +83 -0
- package/schemas/project-config.schema.json +215 -0
- package/schemas/project-demo.schema.json +60 -0
- package/schemas/provider-behavior-matrix.schema.json +91 -0
- package/schemas/scope.schema.json +197 -0
- package/schemas/specialist-trace.schema.json +107 -0
- package/schemas/team.schema.json +99 -0
- package/schemas/unified-registry.schema.json +546 -0
- package/scripts/sync-specialists.mjs +336 -106
- package/skills/docs/adr-workflow.md +1 -1
- package/skills/docs/codebase-research-workflow.md +3 -3
- package/skills/docs/prd-workflow.md +5 -6
- package/skills/docs/runbook-workflow.md +2 -2
- package/skills/docs/user-research-workflow.md +3 -3
- package/skills/operating/fleet-health-routing.md +77 -0
- package/skills/roles/ai-engineer.md +1 -1
- package/skills/roles/architect.md +0 -1
- package/skills/roles/business-strategist.md +1 -1
- package/skills/roles/data-analyst.telemetry.md +1 -1
- package/skills/roles/data-engineer.md +1 -1
- package/skills/roles/data-engineer.pipeline.md +1 -1
- package/skills/roles/data-engineer.vector-retrieval.md +1 -2
- package/skills/roles/data-engineer.warehouse.md +1 -1
- package/skills/roles/designer.accessibility.md +1 -1
- package/skills/roles/designer.md +0 -1
- package/skills/roles/devil-advocate.md +1 -1
- package/skills/roles/docs-keeper.md +1 -1
- package/skills/roles/evaluator.md +1 -1
- package/skills/roles/explorer.md +1 -1
- package/skills/roles/platform-engineer.md +1 -1
- package/skills/roles/qa.ai-eval.md +1 -2
- package/skills/roles/qa.api-contract.md +0 -1
- package/skills/roles/qa.data-pipeline.md +0 -1
- package/skills/roles/qa.md +0 -1
- package/skills/roles/qa.web-ui.md +0 -1
- package/skills/roles/release-manager.md +1 -1
- package/skills/roles/researcher.md +0 -2
- package/skills/roles/reviewer.md +0 -3
- package/skills/roles/security.ai.md +1 -1
- package/skills/roles/security.legal-compliance.md +1 -1
- package/skills/roles/security.md +0 -1
- package/skills/roles/security.privacy.md +0 -1
- package/skills/roles/security.supply-chain.md +1 -1
- package/skills/roles/sre.md +1 -1
- package/skills/roles/test-automation.md +1 -1
- package/skills/roles/trace-reviewer.md +1 -1
- package/skills/roles/ux-researcher.md +1 -1
- package/specialists/artifact-manifest.json +36 -36
- package/specialists/org/contracts/accessibility-to-qa.json +11 -3
- package/specialists/org/contracts/any-to-business-strategist.json +19 -7
- package/specialists/org/contracts/any-to-debugger.json +7 -1
- package/specialists/org/contracts/any-to-designer.json +7 -1
- package/specialists/org/contracts/any-to-docs-keeper.json +18 -4
- package/specialists/org/contracts/any-to-explorer.json +13 -4
- package/specialists/org/contracts/any-to-sre-incident.json +6 -2
- package/specialists/org/contracts/any-to-trace-reviewer.json +16 -4
- package/specialists/org/contracts/architect-to-ai-engineer.json +6 -2
- package/specialists/org/contracts/architect-to-data-engineer.json +17 -5
- package/specialists/org/contracts/architect-to-devil-advocate.json +11 -3
- package/specialists/org/contracts/architect-to-engineer.json +20 -4
- package/specialists/org/contracts/architect-to-evaluator.json +15 -5
- package/specialists/org/contracts/architect-to-legal-compliance.json +15 -5
- package/specialists/org/contracts/architect-to-operations.json +17 -4
- package/specialists/org/contracts/architect-to-platform-engineer.json +20 -4
- package/specialists/org/contracts/construct-to-orchestrator.json +10 -2
- package/specialists/org/contracts/data-analyst-to-product-manager.json +11 -2
- package/specialists/org/contracts/engineer-to-qa.json +20 -4
- package/specialists/org/contracts/engineer-to-reviewer.json +29 -5
- package/specialists/org/contracts/explorer-to-engineer.json +11 -3
- package/specialists/org/contracts/legal-compliance-to-release-manager.json +12 -4
- package/specialists/org/contracts/operations-to-user.json +53 -0
- package/specialists/org/contracts/operations-triage-output.json +53 -0
- package/specialists/org/contracts/pm-requirements-candidates.json +53 -0
- package/specialists/org/contracts/product-manager-to-architect.json +30 -10
- package/specialists/org/contracts/product-manager-to-data-analyst.json +13 -3
- package/specialists/org/contracts/product-manager-to-ux-researcher.json +15 -5
- package/specialists/org/contracts/qa-to-release-manager.json +11 -3
- package/specialists/org/contracts/researcher-to-architect.json +10 -2
- package/specialists/org/contracts/researcher-to-product-manager.json +16 -5
- package/specialists/org/contracts/reviewer-to-security.json +17 -3
- package/specialists/org/contracts/test-automation-to-engineer.json +11 -3
- package/specialists/org/contracts/trace-reviewer-to-sre.json +12 -4
- package/specialists/org/contracts/user-to-construct.json +11 -4
- package/specialists/org/frameworks/cx-architect-constraint-option-failure.md +66 -0
- package/specialists/org/frameworks/cx-engineer-feasibility-blast-radius.md +66 -0
- package/specialists/org/frameworks/cx-ops-dependency-sequencing.md +74 -0
- package/specialists/org/frameworks/cx-pm-value-tradeoff.md +66 -0
- package/specialists/org/frameworks/cx-qa-risk-based-coverage.md +69 -0
- package/specialists/org/groups/engineering-group.json +2 -6
- package/specialists/org/groups/governance-group.json +2 -3
- package/specialists/org/groups/operations-group.json +5 -8
- package/specialists/org/groups/product-group.json +4 -8
- package/specialists/org/groups/quality-group.json +3 -7
- package/specialists/org/groups/strategy-group.json +6 -9
- package/specialists/org/models.json.example +8 -0
- package/specialists/org/scopes/creative.json +6 -1
- package/specialists/org/scopes/operations.json +7 -1
- package/specialists/org/scopes/research.json +6 -1
- package/specialists/org/scopes/rnd.json +7 -1
- package/specialists/org/specialists/cx-architect.json +27 -8
- package/specialists/org/specialists/cx-designer.json +22 -8
- package/specialists/org/specialists/cx-engineer.json +71 -7
- package/specialists/org/specialists/cx-operations.json +89 -15
- package/specialists/org/specialists/cx-orchestrator.json +16 -4
- package/specialists/org/specialists/cx-product-manager.json +28 -9
- package/specialists/org/specialists/cx-qa.json +16 -6
- package/specialists/org/specialists/cx-researcher.json +41 -7
- package/specialists/org/specialists/cx-reviewer.json +61 -11
- package/specialists/org/specialists/cx-security.json +30 -10
- package/specialists/org/teams/design-team.json +3 -4
- package/specialists/org/teams/engineering-team.json +3 -10
- package/specialists/org/teams/governance-team.json +3 -5
- package/specialists/org/teams/operations-team.json +6 -12
- package/specialists/org/teams/product-management-team.json +2 -3
- package/specialists/org/teams/quality-team.json +4 -12
- package/specialists/org/teams/research-team.json +3 -3
- package/specialists/org/teams/strategy-team.json +7 -14
- package/specialists/prompts/cx-architect.md +20 -1
- package/specialists/prompts/cx-data-analyst.md +1 -1
- package/specialists/prompts/cx-designer.md +12 -4
- package/specialists/prompts/cx-engineer.md +15 -1
- package/specialists/prompts/cx-operations.md +14 -2
- package/specialists/prompts/cx-orchestrator.md +9 -5
- package/specialists/prompts/cx-product-manager.md +5 -1
- package/specialists/prompts/cx-qa.md +6 -2
- package/specialists/prompts/cx-researcher.md +27 -31
- package/specialists/prompts/cx-reviewer.md +19 -1
- package/specialists/prompts/cx-security.md +5 -1
- package/templates/distribution/construct-brand.typ +123 -59
- package/templates/distribution/construct-decision.typ +6 -3
- package/templates/distribution/construct-pdf.typ +11 -4
- package/templates/distribution/construct-prd.typ +6 -3
- package/templates/distribution/construct-research.typ +7 -4
- package/vendor/pandoc-ext/README.md +3 -0
- package/vendor/pandoc-ext/diagram.lua +687 -0
- package/lib/providers/contract/adapters/git/index.mjs +0 -115
- package/lib/providers/contract/adapters/slack/index.mjs +0 -175
- package/specialists/org/contracts/business-strategist-to-product-manager.json +0 -39
- package/specialists/org/contracts/construct-to-rd-lead.json +0 -53
- package/specialists/org/contracts/data-engineer-to-platform-engineer.json +0 -36
- package/specialists/org/contracts/designer-to-accessibility.json +0 -36
- package/specialists/org/contracts/platform-engineer-to-engineer.json +0 -31
- package/specialists/org/contracts/qa-to-test-automation.json +0 -42
- package/specialists/org/contracts/rd-lead-to-architect.json +0 -38
- package/specialists/org/contracts/sre-to-release-manager.json +0 -36
- package/specialists/org/specialists/cx-accessibility.json +0 -69
- package/specialists/org/specialists/cx-ai-engineer.json +0 -75
- package/specialists/org/specialists/cx-business-strategist.json +0 -72
- package/specialists/org/specialists/cx-data-engineer.json +0 -71
- package/specialists/org/specialists/cx-devil-advocate.json +0 -71
- package/specialists/org/specialists/cx-docs-keeper.json +0 -82
- package/specialists/org/specialists/cx-evaluator.json +0 -69
- package/specialists/org/specialists/cx-explorer.json +0 -69
- package/specialists/org/specialists/cx-legal-compliance.json +0 -74
- package/specialists/org/specialists/cx-oracle.json +0 -46
- package/specialists/org/specialists/cx-platform-engineer.json +0 -80
- package/specialists/org/specialists/cx-rd-lead.json +0 -73
- package/specialists/org/specialists/cx-release-manager.json +0 -77
- package/specialists/org/specialists/cx-sre.json +0 -94
- package/specialists/org/specialists/cx-test-automation.json +0 -69
- package/specialists/org/specialists/cx-trace-reviewer.json +0 -69
- package/specialists/org/specialists/cx-ux-researcher.json +0 -68
- package/specialists/org/teams/accessibility-team.json +0 -39
- package/specialists/org/teams/ux-research-team.json +0 -39
- package/specialists/prompts/cx-accessibility.md +0 -55
- package/specialists/prompts/cx-ai-engineer.md +0 -124
- package/specialists/prompts/cx-business-strategist.md +0 -58
- package/specialists/prompts/cx-data-engineer.md +0 -55
- package/specialists/prompts/cx-devil-advocate.md +0 -59
- package/specialists/prompts/cx-docs-keeper.md +0 -164
- package/specialists/prompts/cx-evaluator.md +0 -49
- package/specialists/prompts/cx-explorer.md +0 -71
- package/specialists/prompts/cx-legal-compliance.md +0 -58
- package/specialists/prompts/cx-oracle.md +0 -98
- package/specialists/prompts/cx-platform-engineer.md +0 -97
- package/specialists/prompts/cx-rd-lead.md +0 -59
- package/specialists/prompts/cx-release-manager.md +0 -54
- package/specialists/prompts/cx-sre.md +0 -111
- package/specialists/prompts/cx-test-automation.md +0 -55
- package/specialists/prompts/cx-trace-reviewer.md +0 -101
- package/specialists/prompts/cx-ux-researcher.md +0 -53
package/lib/mcp/server.mjs
CHANGED
|
@@ -8,21 +8,33 @@
|
|
|
8
8
|
* Consumed by Claude Code, OpenCode, and any MCP-compatible host.
|
|
9
9
|
*/
|
|
10
10
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
11
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
12
11
|
import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
import { resolveTransportMode, TRANSPORT_HTTP } from './transport/mode.mjs';
|
|
13
|
+
import { startStdioTransport } from './transport/stdio.mjs';
|
|
14
|
+
import { startHttpTransport } from './transport/http.mjs';
|
|
13
15
|
import { resolve, dirname } from 'node:path';
|
|
14
16
|
import { fileURLToPath } from 'node:url';
|
|
15
|
-
import { realpathSync } from 'node:fs';
|
|
17
|
+
import { realpathSync, readFileSync } from 'node:fs';
|
|
16
18
|
import { loadToolkitEnv } from '../toolkit-env.mjs';
|
|
17
19
|
import { loadConstructEnv, prepareConstructEnv } from '../runtime-env.mjs';
|
|
18
20
|
import { getInstalledVersion } from '../version.mjs';
|
|
19
21
|
import { getDeploymentMode } from '../deployment-mode.mjs';
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
import { injectTraceContext } from '../telemetry/otel-tracer.mjs';
|
|
23
|
+
import { TOOL_SAFETY, DEFAULT_OUTPUT_SCHEMA } from './tool-safety.mjs';
|
|
24
|
+
import { RAW_HARDCODED_TOOL_DEFS } from './tool-definitions.mjs';
|
|
25
|
+
import { isBrokered } from './broker.mjs';
|
|
26
|
+
import { resolveProjectRoot } from '../roots.mjs';
|
|
27
|
+
import { createToolCallHandler } from './dispatch-envelope.mjs';
|
|
28
|
+
|
|
29
|
+
// Apply project .env and config.env values to process.env, letting project
|
|
30
|
+
// .env win over config.env and config.env win over shell env, so
|
|
31
|
+
// telemetry/OpenRouter credentials are always correct regardless of host env.
|
|
32
|
+
// PROJECT_ROOT (walked up from the server's cwd, per lib/roots.mjs) is the
|
|
33
|
+
// user's repo, distinct from ROOT_DIR below (the toolkit install/checkout
|
|
34
|
+
// used for asset lookups and loadToolkitEnv's fill-missing toolkit .env).
|
|
24
35
|
{
|
|
25
|
-
const
|
|
36
|
+
const PROJECT_ROOT = resolveProjectRoot(process.cwd());
|
|
37
|
+
const confEnv = prepareConstructEnv({ warn: false, rootDir: PROJECT_ROOT });
|
|
26
38
|
for (const [k, v] of Object.entries(confEnv)) {
|
|
27
39
|
process.env[k] = v;
|
|
28
40
|
}
|
|
@@ -61,8 +73,12 @@ import {
|
|
|
61
73
|
} from './tools/scope.mjs';
|
|
62
74
|
import { modelResolve, triageRecommend, workflowInvoke, capabilityDescribe, executionResolve, artifactWorkflow } from './tools/embedded-contract.mjs';
|
|
63
75
|
import { authorArtifact } from './tools/artifact-author.mjs';
|
|
76
|
+
import { providerWrite } from './tools/provider-write.mjs';
|
|
64
77
|
import { findTool } from './tools/find-tool.mjs';
|
|
65
78
|
import { recoverToolName, recordToolNameMiss, isGatewayName } from './tool-recovery.mjs';
|
|
79
|
+
import { assertCoreSubsetOfCatalog } from './tool-surface-parity.mjs';
|
|
80
|
+
import { scanToolModules } from './tool-registry.mjs';
|
|
81
|
+
import { enableSecretAuditTrail } from '../providers/secret-audit-wiring.mjs';
|
|
66
82
|
import { buildOrchestrationReadiness } from '../orchestration/readiness.mjs';
|
|
67
83
|
|
|
68
84
|
const DEFAULT_ROOT_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
@@ -78,6 +94,40 @@ const opts = { ROOT_DIR };
|
|
|
78
94
|
|
|
79
95
|
const VERSION = getInstalledVersion()?.version || 'unknown';
|
|
80
96
|
const DEPLOYMENT_MODE = getDeploymentMode(process.env, { cwd: ROOT_DIR });
|
|
97
|
+
|
|
98
|
+
// A long-running server caches VERSION at module load and never re-checks it, so
|
|
99
|
+
// on a dev-checkout-as-live-install topology a server up for days keeps serving
|
|
100
|
+
// stale code with no signal. VERSION_STAMP_PATH is the on-disk artifact this
|
|
101
|
+
// process was started from (ROOT_DIR/package.json, honoring CX_TOOLKIT_DIR);
|
|
102
|
+
// STARTED_DISK_VERSION is that file's version at startup. readVersionSkew()
|
|
103
|
+
// re-reads the same file on every status read (one stat + a small JSON parse)
|
|
104
|
+
// and reports restartRequired when the two disagree — the server cannot safely
|
|
105
|
+
// hot-swap its own module graph, so the only correct action is to surface the
|
|
106
|
+
// mismatch for the host/user to act on, not to auto-restart in-process.
|
|
107
|
+
|
|
108
|
+
const VERSION_STAMP_PATH = resolve(ROOT_DIR, 'package.json');
|
|
109
|
+
const STARTED_DISK_VERSION = (() => {
|
|
110
|
+
try {
|
|
111
|
+
return JSON.parse(readFileSync(VERSION_STAMP_PATH, 'utf8')).version || VERSION;
|
|
112
|
+
} catch {
|
|
113
|
+
return VERSION;
|
|
114
|
+
}
|
|
115
|
+
})();
|
|
116
|
+
|
|
117
|
+
export function readVersionSkew() {
|
|
118
|
+
let diskVersion = STARTED_DISK_VERSION;
|
|
119
|
+
try {
|
|
120
|
+
diskVersion = JSON.parse(readFileSync(VERSION_STAMP_PATH, 'utf8')).version || STARTED_DISK_VERSION;
|
|
121
|
+
} catch {
|
|
122
|
+
diskVersion = STARTED_DISK_VERSION;
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
startedVersion: STARTED_DISK_VERSION,
|
|
126
|
+
diskVersion,
|
|
127
|
+
restartRequired: diskVersion !== STARTED_DISK_VERSION,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
81
131
|
const INSTRUCTIONS = [
|
|
82
132
|
`Construct MCP — agent orchestration for this workspace (v${VERSION}, ${DEPLOYMENT_MODE} mode).`,
|
|
83
133
|
'Tools cover: project context and diff review, skills/templates/teams, document ingestion and vector storage,',
|
|
@@ -110,11 +160,13 @@ server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
|
|
|
110
160
|
name: 'Construct',
|
|
111
161
|
version: VERSION,
|
|
112
162
|
deploymentMode: DEPLOYMENT_MODE,
|
|
113
|
-
mcpBroker: process.env
|
|
163
|
+
mcpBroker: isBrokered(process.env, { cwd: ROOT_DIR }) ? 'on' : 'off',
|
|
164
|
+
mcpBrokerMode: isBrokered(process.env, { cwd: ROOT_DIR }) ? 'dispatch' : 'off',
|
|
114
165
|
capabilities: [
|
|
115
166
|
'project-context', 'skills', 'templates', 'teams', 'document-ingestion',
|
|
116
167
|
'vector-storage', 'workflow', 'telemetry', 'memory',
|
|
117
168
|
],
|
|
169
|
+
...readVersionSkew(),
|
|
118
170
|
fullHealth: 'run `construct status`',
|
|
119
171
|
dashboard: 'run `construct dev`, then open the printed URL',
|
|
120
172
|
};
|
|
@@ -125,1208 +177,34 @@ server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
|
|
|
125
177
|
|
|
126
178
|
// The full construct-mcp tool catalog. Only a curated core is exposed flat in
|
|
127
179
|
// ListTools; the long tail is reachable through the construct_call meta-tool, so
|
|
128
|
-
// the serialized tool surface stays small on every host and model. The
|
|
129
|
-
// flat surface alone (~
|
|
180
|
+
// the serialized tool surface stays small on every host and model. The 76-tool
|
|
181
|
+
// flat surface alone (~15k tokens) overran a 32k local-model window.
|
|
130
182
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
type: 'string',
|
|
157
|
-
description: 'Working directory for the git command.',
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
name: 'scan_file',
|
|
164
|
-
description: 'Scans a file for secrets and code quality issues.',
|
|
165
|
-
inputSchema: {
|
|
166
|
-
type: 'object',
|
|
167
|
-
properties: {
|
|
168
|
-
file_path: {
|
|
169
|
-
type: 'string',
|
|
170
|
-
description: 'Absolute path to the file to scan.',
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
required: ['file_path'],
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
name: 'extract_document_text',
|
|
178
|
-
description: 'Extracts readable text from a local document path. Uses node-native extractors (unpdf/mammoth) first; escalates to the docling Python sidecar or whisper.cpp when needed (same pipeline as `construct ingest`). Supports PDF, DOCX, XLSX, PPTX, HTML, plain text, email, and transcripts.',
|
|
179
|
-
inputSchema: {
|
|
180
|
-
type: 'object',
|
|
181
|
-
properties: {
|
|
182
|
-
file_path: {
|
|
183
|
-
type: 'string',
|
|
184
|
-
description: 'Absolute or relative path to the document file.',
|
|
185
|
-
},
|
|
186
|
-
max_chars: {
|
|
187
|
-
type: 'number',
|
|
188
|
-
description: 'Maximum characters to return (default 20000, hard cap 200000).',
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
required: ['file_path'],
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
name: 'ingest_document',
|
|
196
|
-
description: 'Converts a local document into a normalized markdown file, placing it into an indexed project path by default.',
|
|
197
|
-
inputSchema: {
|
|
198
|
-
type: 'object',
|
|
199
|
-
properties: {
|
|
200
|
-
file_path: {
|
|
201
|
-
type: 'string',
|
|
202
|
-
description: 'Absolute or relative path to the source document.',
|
|
203
|
-
},
|
|
204
|
-
out_path: {
|
|
205
|
-
type: 'string',
|
|
206
|
-
description: 'Optional explicit markdown output path.',
|
|
207
|
-
},
|
|
208
|
-
out_dir: {
|
|
209
|
-
type: 'string',
|
|
210
|
-
description: 'Optional directory for generated markdown output files.',
|
|
211
|
-
},
|
|
212
|
-
target: {
|
|
213
|
-
type: 'string',
|
|
214
|
-
description: 'Output mode: knowledge/internal, knowledge/external, knowledge/decisions, knowledge/how-tos, knowledge/reference, or sibling. Defaults to knowledge/internal.',
|
|
215
|
-
},
|
|
216
|
-
cwd: {
|
|
217
|
-
type: 'string',
|
|
218
|
-
description: 'Project root used to resolve default output paths and storage sync.',
|
|
219
|
-
},
|
|
220
|
-
sync: {
|
|
221
|
-
type: 'boolean',
|
|
222
|
-
description: 'When true, sync file-state into configured SQL/vector storage after writing output.',
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
required: ['file_path'],
|
|
226
|
-
},
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
name: 'infer_document_schema',
|
|
230
|
-
description: 'Infers a structured field schema from a local document using AI. Returns field names, types, formats, examples, and confidence. Supports all document types handled by extract_document_text. Pass multiple file_paths to get a reconciled unified schema across documents.',
|
|
231
|
-
inputSchema: {
|
|
232
|
-
type: 'object',
|
|
233
|
-
properties: {
|
|
234
|
-
file_path: {
|
|
235
|
-
type: 'string',
|
|
236
|
-
description: 'Absolute or relative path to the document file. For unified inference across multiple documents, use file_paths instead.',
|
|
237
|
-
},
|
|
238
|
-
file_paths: {
|
|
239
|
-
type: 'array',
|
|
240
|
-
items: { type: 'string' },
|
|
241
|
-
description: 'Multiple document paths for unified schema inference. Reconciles fields across all documents.',
|
|
242
|
-
},
|
|
243
|
-
max_chars: {
|
|
244
|
-
type: 'number',
|
|
245
|
-
description: 'Maximum characters of document text to send to the model (default 40000, hard cap 200000).',
|
|
246
|
-
},
|
|
247
|
-
save: {
|
|
248
|
-
type: 'boolean',
|
|
249
|
-
description: 'When true, write the schema result as a .schema.json artifact under .cx/knowledge/reference/schemas/.',
|
|
250
|
-
},
|
|
251
|
-
cwd: {
|
|
252
|
-
type: 'string',
|
|
253
|
-
description: 'Project root used to resolve output paths when save is true.',
|
|
254
|
-
},
|
|
255
|
-
sample_size: {
|
|
256
|
-
type: 'number',
|
|
257
|
-
description: 'For unified inference: max number of documents to sample (default 10).',
|
|
258
|
-
},
|
|
259
|
-
threshold: {
|
|
260
|
-
type: 'number',
|
|
261
|
-
description: 'For unified inference: minimum fraction of documents a field must appear in to be included (default 0.5).',
|
|
262
|
-
},
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
name: 'list_schema_artifacts',
|
|
268
|
-
description: 'Lists all inferred schema artifacts (.schema.json files) in the project.',
|
|
269
|
-
inputSchema: {
|
|
270
|
-
type: 'object',
|
|
271
|
-
properties: {
|
|
272
|
-
cwd: {
|
|
273
|
-
type: 'string',
|
|
274
|
-
description: 'Project directory to search (default: process.cwd()).',
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
name: 'storage_status',
|
|
281
|
-
description: 'Returns SQL, local vector index, and ingested-artifact status for the current project.',
|
|
282
|
-
inputSchema: {
|
|
283
|
-
type: 'object',
|
|
284
|
-
properties: {
|
|
285
|
-
cwd: {
|
|
286
|
-
type: 'string',
|
|
287
|
-
description: 'Project directory to inspect.',
|
|
288
|
-
},
|
|
289
|
-
project: {
|
|
290
|
-
type: 'string',
|
|
291
|
-
description: 'Optional explicit project key for SQL document counts.',
|
|
292
|
-
},
|
|
293
|
-
},
|
|
294
|
-
},
|
|
295
|
-
},
|
|
296
|
-
{
|
|
297
|
-
name: 'storage_sync',
|
|
298
|
-
description: 'Syncs file-state documents into the local vector index and configured SQL storage.',
|
|
299
|
-
inputSchema: {
|
|
300
|
-
type: 'object',
|
|
301
|
-
properties: {
|
|
302
|
-
cwd: {
|
|
303
|
-
type: 'string',
|
|
304
|
-
description: 'Project directory to sync.',
|
|
305
|
-
},
|
|
306
|
-
project: {
|
|
307
|
-
type: 'string',
|
|
308
|
-
description: 'Optional explicit project key.',
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
name: 'storage_reset',
|
|
315
|
-
description: 'Resets SQL/vector storage state for a project. Requires explicit confirm=true.',
|
|
316
|
-
inputSchema: {
|
|
317
|
-
type: 'object',
|
|
318
|
-
properties: {
|
|
319
|
-
cwd: {
|
|
320
|
-
type: 'string',
|
|
321
|
-
description: 'Project directory whose storage should be reset.',
|
|
322
|
-
},
|
|
323
|
-
project: {
|
|
324
|
-
type: 'string',
|
|
325
|
-
description: 'Optional explicit project key.',
|
|
326
|
-
},
|
|
327
|
-
reset_sql: {
|
|
328
|
-
type: 'boolean',
|
|
329
|
-
description: 'Set false to keep SQL state intact.',
|
|
330
|
-
},
|
|
331
|
-
reset_vector: {
|
|
332
|
-
type: 'boolean',
|
|
333
|
-
description: 'Set false to keep the local vector index intact.',
|
|
334
|
-
},
|
|
335
|
-
reset_ingested: {
|
|
336
|
-
type: 'boolean',
|
|
337
|
-
description: 'Set true to also delete ingested markdown artifacts under .cx/knowledge/.',
|
|
338
|
-
},
|
|
339
|
-
confirm: {
|
|
340
|
-
type: 'boolean',
|
|
341
|
-
description: 'Must be true or the reset is rejected.',
|
|
342
|
-
},
|
|
343
|
-
},
|
|
344
|
-
},
|
|
345
|
-
},
|
|
346
|
-
{
|
|
347
|
-
name: 'delete_ingested_artifacts',
|
|
348
|
-
description: 'Deletes ingested markdown artifacts. Requires explicit confirm=true and only allows files under the ingested artifact directory.',
|
|
349
|
-
inputSchema: {
|
|
350
|
-
type: 'object',
|
|
351
|
-
properties: {
|
|
352
|
-
cwd: {
|
|
353
|
-
type: 'string',
|
|
354
|
-
description: 'Project directory whose ingested artifacts should be deleted.',
|
|
355
|
-
},
|
|
356
|
-
files: {
|
|
357
|
-
type: 'array',
|
|
358
|
-
description: 'Optional relative file paths under .cx/knowledge/. Omit to delete all ingested markdown artifacts.',
|
|
359
|
-
items: { type: 'string' },
|
|
360
|
-
},
|
|
361
|
-
confirm: {
|
|
362
|
-
type: 'boolean',
|
|
363
|
-
description: 'Must be true or deletion is rejected.',
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
},
|
|
367
|
-
},
|
|
368
|
-
{
|
|
369
|
-
name: 'project_context',
|
|
370
|
-
description: 'Returns project context: .cx/context.md content, recent commits, and working tree status.',
|
|
371
|
-
inputSchema: {
|
|
372
|
-
type: 'object',
|
|
373
|
-
properties: {
|
|
374
|
-
cwd: {
|
|
375
|
-
type: 'string',
|
|
376
|
-
description: 'Project directory (default: process.cwd()).',
|
|
377
|
-
},
|
|
378
|
-
},
|
|
379
|
-
},
|
|
380
|
-
},
|
|
381
|
-
{
|
|
382
|
-
name: 'get_skill',
|
|
383
|
-
description: 'Reads a specific skill playbook from the Construct knowledge base (e.g. "docs/adr-workflow", "roles/engineer", "architecture/security-arch").',
|
|
384
|
-
inputSchema: {
|
|
385
|
-
type: 'object',
|
|
386
|
-
properties: {
|
|
387
|
-
path: { type: 'string', description: 'Relative path to the skill (without .md extension)' },
|
|
388
|
-
},
|
|
389
|
-
required: ['path'],
|
|
390
|
-
},
|
|
391
|
-
},
|
|
392
|
-
{
|
|
393
|
-
name: 'orchestration_policy',
|
|
394
|
-
description: 'Classifies a request into intent, execution track, specialists, approval boundaries, and the contract chain that applies. The contractChain field names the typed producer→consumer handoffs expected for this dispatch plan. When `candidates` is supplied, also returns `contextPackets` keyed by specialist with the role-filtered artifact bundle each specialist should receive (omitted artifacts include the reason they were dropped).',
|
|
395
|
-
inputSchema: {
|
|
396
|
-
type: 'object',
|
|
397
|
-
properties: {
|
|
398
|
-
request: { type: 'string', description: 'User request or objective text.' },
|
|
399
|
-
fileCount: { type: 'number', description: 'Approximate number of files involved.' },
|
|
400
|
-
moduleCount: { type: 'number', description: 'Approximate number of modules involved.' },
|
|
401
|
-
introducesContract: { type: 'boolean', description: 'Whether the change introduces a new contract/dependency.' },
|
|
402
|
-
explicitDrive: { type: 'boolean', description: 'Whether drive/full-send mode is explicitly active.' },
|
|
403
|
-
approval: {
|
|
404
|
-
type: 'object',
|
|
405
|
-
description: 'Approval-boundary flags.',
|
|
406
|
-
properties: {
|
|
407
|
-
scopeChange: { type: 'boolean' },
|
|
408
|
-
productDecision: { type: 'boolean' },
|
|
409
|
-
riskAcceptance: { type: 'boolean' },
|
|
410
|
-
irreversibleAction: { type: 'boolean' },
|
|
411
|
-
blockedDependency: { type: 'boolean' },
|
|
412
|
-
},
|
|
413
|
-
},
|
|
414
|
-
candidates: {
|
|
415
|
-
type: 'array',
|
|
416
|
-
description: 'Pre-retrieved artifacts to consider for each specialist. Each item: {id, path, title, kind, summary, score}. When supplied, the response includes `contextPackets` keyed by specialist.',
|
|
417
|
-
items: { type: 'object' },
|
|
418
|
-
},
|
|
419
|
-
budget: {
|
|
420
|
-
type: 'object',
|
|
421
|
-
description: 'Token budget for the per-specialist context packet (default: 6000).',
|
|
422
|
-
properties: { maxTokens: { type: 'number' } },
|
|
423
|
-
},
|
|
424
|
-
triage: {
|
|
425
|
-
type: 'object',
|
|
426
|
-
description: 'Optional R&D triage block from a related intake packet — surfaced in each specialist\'s taskSummary.',
|
|
427
|
-
},
|
|
428
|
-
intakeId: {
|
|
429
|
-
type: 'string',
|
|
430
|
-
description: 'Optional id of a pending intake packet. When supplied, the tool generates a task graph from the packet\'s triage, persists it to .cx/task-graphs/, emits a task_graph.created trace event correlated by traceId, and returns the graph in `taskGraph`.',
|
|
431
|
-
},
|
|
432
|
-
project: {
|
|
433
|
-
type: 'string',
|
|
434
|
-
description: 'Project scope for the generated task graph (defaults to basename(cwd)).',
|
|
435
|
-
},
|
|
436
|
-
traceId: {
|
|
437
|
-
type: 'string',
|
|
438
|
-
description: 'Optional traceId to link task_graph.created with the originating intake.received event.',
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
},
|
|
442
|
-
},
|
|
443
|
-
{
|
|
444
|
-
name: 'list_skills',
|
|
445
|
-
description: 'Lists all available categories and playbooks in the Construct knowledge base.',
|
|
446
|
-
inputSchema: {
|
|
447
|
-
type: 'object',
|
|
448
|
-
properties: {},
|
|
449
|
-
},
|
|
450
|
-
},
|
|
451
|
-
{
|
|
452
|
-
name: 'worker_run',
|
|
453
|
-
description: 'Runs a bounded shell command via the worker plane: timeout, path-policy denial, restricted env, stdout/stderr artifacts under `.cx/runtime/worker/<jobId>.{stdout,stderr}.log`. When `graphId` + `nodeId` are supplied, an evidence record is appended to that task graph node so it can transition to `done`. Emits `worker.started` / `worker.completed` / `evidence.recorded` trace events correlated by `traceId`.',
|
|
454
|
-
inputSchema: {
|
|
455
|
-
type: 'object',
|
|
456
|
-
properties: {
|
|
457
|
-
command: { type: 'string', description: 'Shell command to run (e.g. `npm test`).' },
|
|
458
|
-
args: { type: 'array', items: { type: 'string' }, description: 'Argv to pass alongside the command (when not embedded in the command string).' },
|
|
459
|
-
workspaceRef: { type: 'string', description: 'Absolute path the job runs in. Must be inside `allowedPaths` (default: cwd).' },
|
|
460
|
-
allowedPaths: { type: 'array', items: { type: 'string' }, description: 'Absolute path allowlist for the workspace. Default: [cwd] so the job can\'t reach outside the project.' },
|
|
461
|
-
timeoutSeconds: { type: 'number', description: 'Hard timeout. Default: 300.' },
|
|
462
|
-
envPolicy: { type: 'string', description: 'restricted (default — only PATH/HOME/USER/TZ/LANG/LC_ALL/TMPDIR plus allowedEnvKeys) | inherit.' },
|
|
463
|
-
allowedEnvKeys: { type: 'array', items: { type: 'string' }, description: 'Additional env keys allowed through under restricted policy.' },
|
|
464
|
-
graphId: { type: 'string', description: 'Optional task graph id — when present with `nodeId`, evidence is recorded on that node.' },
|
|
465
|
-
nodeId: { type: 'string', description: 'Optional task graph node id — when present with `graphId`, evidence is recorded.' },
|
|
466
|
-
evidenceType: { type: 'string', description: 'Evidence type (e.g. `test-result`, `lint-result`, `build-result`). Default: test-result.' },
|
|
467
|
-
evidenceSummary: { type: 'string', description: 'Optional override for the evidence summary string.' },
|
|
468
|
-
traceId: { type: 'string', description: 'Optional traceId to correlate with the rest of the agent\'s trace.' },
|
|
469
|
-
taskId: { type: 'string', description: 'Optional task id (used when graphId/nodeId aren\'t supplied — purely for trace context).' },
|
|
470
|
-
project: { type: 'string', description: 'Optional project scope.' },
|
|
471
|
-
jobId: { type: 'string', description: 'Optional job id. Default: worker-<ts>-<rand>.' },
|
|
472
|
-
},
|
|
473
|
-
required: ['command'],
|
|
474
|
-
},
|
|
475
|
-
},
|
|
476
|
-
{
|
|
477
|
-
name: 'broker_check',
|
|
478
|
-
description: 'Queries the MCP broker policy gate for a pending action without executing it. Agents call this BEFORE attempting a high-risk action so the response (allowed / approvalRequired / reason / source) can be surfaced to the user in the agent\'s voice rather than triggering a denial after the fact. In solo mode the broker is off by default — returns `brokerActive: false` with `allowed: true` so the call is cheap and agents don\'t waste tokens on an inactive gate. Always emits a `tool.called` trace event for audit-trail parity. Reads specialists/org fence rules in team / enterprise mode.',
|
|
479
|
-
inputSchema: {
|
|
480
|
-
type: 'object',
|
|
481
|
-
properties: {
|
|
482
|
-
role: { type: 'string', description: 'Persona name (e.g. `engineer`, `security`). Must match a key in specialists/org for team / enterprise mode.' },
|
|
483
|
-
project: { type: 'string', description: 'Optional project scope for the decision.' },
|
|
484
|
-
tool: { type: 'string', description: 'The tool the agent wants to invoke (e.g. `github`, `fs`).' },
|
|
485
|
-
action: { type: 'string', description: 'The action on that tool (e.g. `create_pr`, `edit:lib/foo.mjs`).' },
|
|
486
|
-
risk: { type: 'string', description: 'low | medium | high. high actions need approval for non-autonomous roles.' },
|
|
487
|
-
traceId: { type: 'string', description: 'Optional traceId to correlate this check with the rest of the agent\'s trace.' },
|
|
488
|
-
},
|
|
489
|
-
required: ['role', 'tool', 'action'],
|
|
490
|
-
},
|
|
491
|
-
},
|
|
492
|
-
{
|
|
493
|
-
name: 'agent_contract',
|
|
494
|
-
description: 'Looks up explicit agent-to-agent service contracts (from specialists/org). Specialists should call this at the start of a handoff to see the expected input shape, preconditions, and what postconditions they must satisfy. Use without args to get all contracts; pass producer/consumer to narrow; pass id for a specific contract.',
|
|
495
|
-
inputSchema: {
|
|
496
|
-
type: 'object',
|
|
497
|
-
properties: {
|
|
498
|
-
id: { type: 'string', description: 'Exact contract id (e.g. "architect-to-engineer")' },
|
|
499
|
-
producer: { type: 'string', description: 'Producer agent name (e.g. "cx-architect"). Returns outgoing contracts.' },
|
|
500
|
-
consumer: { type: 'string', description: 'Consumer agent name (e.g. "cx-engineer"). Returns incoming contracts.' },
|
|
501
|
-
},
|
|
502
|
-
},
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
name: 'find_tool',
|
|
506
|
-
description: 'Find Construct tools by intent when you do not know the exact name. Describe what you want to do; returns the best-matching tools with their input schemas, ranked by hybrid semantic + lexical relevance. Then invoke a result via the `call` gateway (or directly if it is a flat tool).',
|
|
507
|
-
inputSchema: {
|
|
508
|
-
type: 'object',
|
|
509
|
-
properties: {
|
|
510
|
-
query: { type: 'string', description: 'Natural-language description of the task (e.g. "export a markdown file to pdf").' },
|
|
511
|
-
limit: { type: 'number', description: 'Max tools to return (default 5, max 20).' },
|
|
512
|
-
},
|
|
513
|
-
required: ['query'],
|
|
514
|
-
},
|
|
515
|
-
},
|
|
516
|
-
{
|
|
517
|
-
name: 'get_template',
|
|
518
|
-
description: 'Reads a doc template by name (e.g. "prd", "meta-prd", "prfaq", "evidence-brief", "adr", "runbook"). Resolves .cx/templates/docs/{name}.md first, then templates/docs/{name}.md.',
|
|
519
|
-
inputSchema: {
|
|
520
|
-
type: 'object',
|
|
521
|
-
properties: {
|
|
522
|
-
name: { type: 'string', description: 'Template name without .md extension' },
|
|
523
|
-
},
|
|
524
|
-
required: ['name'],
|
|
525
|
-
},
|
|
526
|
-
},
|
|
527
|
-
{
|
|
528
|
-
name: 'list_templates',
|
|
529
|
-
description: 'Lists shipped and project-override doc templates.',
|
|
530
|
-
inputSchema: { type: 'object', properties: {} },
|
|
531
|
-
},
|
|
532
|
-
{
|
|
533
|
-
name: 'search_skills',
|
|
534
|
-
description: 'Searches for a pattern within the Construct knowledge base skills.',
|
|
535
|
-
inputSchema: {
|
|
536
|
-
type: 'object',
|
|
537
|
-
properties: {
|
|
538
|
-
pattern: { type: 'string', description: 'Regex pattern to search for' },
|
|
539
|
-
},
|
|
540
|
-
required: ['pattern'],
|
|
541
|
-
},
|
|
542
|
-
},
|
|
543
|
-
{
|
|
544
|
-
name: 'list_teams',
|
|
545
|
-
description: 'Lists all available Construct team templates with members, focus, and promotion gates.',
|
|
546
|
-
inputSchema: { type: 'object', properties: {} },
|
|
547
|
-
},
|
|
548
|
-
{
|
|
549
|
-
name: 'suggest_skills',
|
|
550
|
-
description: 'Rank skills from the central catalog for a natural-language intent. Optional specialistId filters entitlement metadata.',
|
|
551
|
-
inputSchema: {
|
|
552
|
-
type: 'object',
|
|
553
|
-
properties: {
|
|
554
|
-
intent: { type: 'string', description: 'Task description or keywords' },
|
|
555
|
-
specialistId: { type: 'string', description: 'Optional cx-* id for entitlement hints' },
|
|
556
|
-
limit: { type: 'number', description: 'Max suggestions (default 5)' },
|
|
557
|
-
},
|
|
558
|
-
required: ['intent'],
|
|
559
|
-
},
|
|
560
|
-
},
|
|
561
|
-
{
|
|
562
|
-
name: 'cx_trace',
|
|
563
|
-
description: 'Records an agent trace for observability. Call at the start of every significant task with your agent name and the user goal.',
|
|
564
|
-
inputSchema: {
|
|
565
|
-
type: 'object',
|
|
566
|
-
properties: {
|
|
567
|
-
name: { type: 'string', description: 'Agent name (e.g. cx-engineer)' },
|
|
568
|
-
id: { type: 'string', description: 'Optional trace UUID — auto-generated if omitted' },
|
|
569
|
-
session_id: { type: 'string', description: 'Session ID to group related spans' },
|
|
570
|
-
metadata: { type: 'object', description: 'Extra metadata (teamId, workflowId, etc.)' },
|
|
571
|
-
input: { type: ['string', 'object'], description: 'Agent goal or user request' },
|
|
572
|
-
output: { type: ['string', 'object'], description: 'Agent deliverable or response' },
|
|
573
|
-
timestamp: { type: 'string', description: 'ISO start time (default: now)' },
|
|
574
|
-
},
|
|
575
|
-
required: ['name'],
|
|
576
|
-
},
|
|
577
|
-
},
|
|
578
|
-
{
|
|
579
|
-
name: 'cx_score',
|
|
580
|
-
description: 'Attaches a quality score to a trace. Call after producing a significant deliverable.',
|
|
581
|
-
inputSchema: {
|
|
582
|
-
type: 'object',
|
|
583
|
-
properties: {
|
|
584
|
-
trace_id: { type: 'string', description: 'The trace ID returned by cx_trace' },
|
|
585
|
-
name: { type: 'string', description: 'Score name — use "quality"' },
|
|
586
|
-
value: { type: 'number', description: 'Score from 0.0 (poor) to 1.0 (excellent)' },
|
|
587
|
-
comment: { type: 'string', description: 'Brief explanation of the score' },
|
|
588
|
-
},
|
|
589
|
-
required: ['trace_id', 'name', 'value'],
|
|
590
|
-
},
|
|
591
|
-
},
|
|
592
|
-
{
|
|
593
|
-
name: 'cx_trace_update',
|
|
594
|
-
description: 'Updates an existing trace with output and metadata. Use when a trace was created early but the result becomes available later.',
|
|
595
|
-
inputSchema: {
|
|
596
|
-
type: 'object',
|
|
597
|
-
properties: {
|
|
598
|
-
trace_id: { type: 'string', description: 'The trace ID returned by cx_trace' },
|
|
599
|
-
output: { type: ['string', 'object'], description: 'Final output / deliverable content' },
|
|
600
|
-
metadata: { type: 'object', description: 'Additional metadata to merge into the trace' },
|
|
601
|
-
},
|
|
602
|
-
required: ['trace_id'],
|
|
603
|
-
},
|
|
604
|
-
},
|
|
605
|
-
{
|
|
606
|
-
name: 'session_list',
|
|
607
|
-
description: 'List construct sessions for the current project. Returns distilled session index entries with id, project, status, and summary.',
|
|
608
|
-
inputSchema: {
|
|
609
|
-
type: 'object',
|
|
610
|
-
properties: {
|
|
611
|
-
cwd: { type: 'string', description: 'Project directory (default: process.cwd()).' },
|
|
612
|
-
status: { type: 'string', description: 'Filter by status: active, completed, closed.' },
|
|
613
|
-
limit: { type: 'number', description: 'Max results (default: 20).' },
|
|
614
|
-
},
|
|
615
|
-
},
|
|
616
|
-
},
|
|
617
|
-
{
|
|
618
|
-
name: 'session_load',
|
|
619
|
-
description: 'Load a full distilled session record by ID. Returns summary, decisions, files changed, open questions, and task snapshot.',
|
|
620
|
-
inputSchema: {
|
|
621
|
-
type: 'object',
|
|
622
|
-
properties: {
|
|
623
|
-
cwd: { type: 'string', description: 'Project directory (default: process.cwd()).' },
|
|
624
|
-
session_id: { type: 'string', description: 'The session ID to load.' },
|
|
625
|
-
},
|
|
626
|
-
required: ['session_id'],
|
|
627
|
-
},
|
|
628
|
-
},
|
|
629
|
-
{
|
|
630
|
-
name: 'session_search',
|
|
631
|
-
description: 'Search sessions by keyword in summary or project name.',
|
|
632
|
-
inputSchema: {
|
|
633
|
-
type: 'object',
|
|
634
|
-
properties: {
|
|
635
|
-
cwd: { type: 'string', description: 'Project directory (default: process.cwd()).' },
|
|
636
|
-
query: { type: 'string', description: 'Search keyword.' },
|
|
637
|
-
},
|
|
638
|
-
required: ['query'],
|
|
639
|
-
},
|
|
640
|
-
},
|
|
641
|
-
{
|
|
642
|
-
name: 'session_save',
|
|
643
|
-
description: 'Update the active session with distilled context: summary, decisions, files changed, open questions, task snapshot.',
|
|
644
|
-
inputSchema: {
|
|
645
|
-
type: 'object',
|
|
646
|
-
properties: {
|
|
647
|
-
cwd: { type: 'string', description: 'Project directory (default: process.cwd()).' },
|
|
648
|
-
session_id: { type: 'string', description: 'The session ID to update.' },
|
|
649
|
-
summary: { type: 'string', description: 'Brief summary of what happened (2-3 sentences).' },
|
|
650
|
-
decisions: { type: 'array', items: { type: 'string' }, description: 'Key decisions made during the session.' },
|
|
651
|
-
files_changed: { type: 'array', items: { type: 'object', properties: { path: { type: 'string' }, reason: { type: 'string' } } }, description: 'Files modified with reasons.' },
|
|
652
|
-
open_questions: { type: 'array', items: { type: 'string' }, description: 'Unresolved questions or blockers.' },
|
|
653
|
-
task_snapshot: { type: 'array', items: { type: 'object', properties: { id: { type: 'string' }, subject: { type: 'string' }, status: { type: 'string' } } }, description: 'Current task state.' },
|
|
654
|
-
status: { type: 'string', description: 'Session status: active, completed, closed.' },
|
|
655
|
-
},
|
|
656
|
-
required: ['session_id'],
|
|
657
|
-
},
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
name: 'memory_search',
|
|
661
|
-
description: 'Search the observation store for patterns, decisions, and insights learned by specialists across sessions. Returns semantically matched observations scoped by role, category, or project.',
|
|
662
|
-
inputSchema: {
|
|
663
|
-
type: 'object',
|
|
664
|
-
properties: {
|
|
665
|
-
query: { type: 'string', description: 'Semantic search query (e.g., project name, pattern, component).' },
|
|
666
|
-
role: { type: 'string', description: 'Filter by specialist role (e.g., cx-engineer, cx-architect).' },
|
|
667
|
-
category: { type: 'string', description: 'Filter by category: pattern, anti-pattern, dependency, decision, insight, session-summary.' },
|
|
668
|
-
project: { type: 'string', description: 'Filter by project name.' },
|
|
669
|
-
limit: { type: 'number', description: 'Max results (default: 10).' },
|
|
670
|
-
},
|
|
671
|
-
required: ['query'],
|
|
672
|
-
},
|
|
673
|
-
},
|
|
674
|
-
{
|
|
675
|
-
name: 'memory_add_observations',
|
|
676
|
-
description: 'Record observations (patterns, insights, decisions, anti-patterns) that specialists discover during work. These are indexed for semantic search and surface in future sessions.',
|
|
677
|
-
inputSchema: {
|
|
678
|
-
type: 'object',
|
|
679
|
-
properties: {
|
|
680
|
-
observations: {
|
|
681
|
-
type: 'array',
|
|
682
|
-
items: {
|
|
683
|
-
type: 'object',
|
|
684
|
-
properties: {
|
|
685
|
-
role: { type: 'string', description: 'Specialist role (e.g., cx-engineer).' },
|
|
686
|
-
category: { type: 'string', description: 'Category: pattern, anti-pattern, dependency, decision, insight.' },
|
|
687
|
-
summary: { type: 'string', description: 'Brief summary (max 500 chars).' },
|
|
688
|
-
content: { type: 'string', description: 'Detailed observation (max 2000 chars).' },
|
|
689
|
-
tags: { type: 'array', items: { type: 'string' }, description: 'Tags for filtering.' },
|
|
690
|
-
confidence: { type: 'number', description: 'Confidence 0.0-1.0 (default: 0.8).' },
|
|
691
|
-
},
|
|
692
|
-
required: ['summary'],
|
|
693
|
-
},
|
|
694
|
-
description: 'Observations to record (max 10 per call).',
|
|
695
|
-
},
|
|
696
|
-
},
|
|
697
|
-
required: ['observations'],
|
|
698
|
-
},
|
|
699
|
-
},
|
|
700
|
-
{
|
|
701
|
-
name: 'memory_create_entities',
|
|
702
|
-
description: 'Track recurring entities (components, services, APIs, dependencies) that specialists encounter. Enables "what do we know about X?" queries.',
|
|
703
|
-
inputSchema: {
|
|
704
|
-
type: 'object',
|
|
705
|
-
properties: {
|
|
706
|
-
entities: {
|
|
707
|
-
type: 'array',
|
|
708
|
-
items: {
|
|
709
|
-
type: 'object',
|
|
710
|
-
properties: {
|
|
711
|
-
name: { type: 'string', description: 'Entity name (normalized to lowercase).' },
|
|
712
|
-
type: { type: 'string', description: 'Type: component, service, dependency, api, concept, file-group.' },
|
|
713
|
-
summary: { type: 'string', description: 'Brief description (max 500 chars).' },
|
|
714
|
-
observation_ids: { type: 'array', items: { type: 'string' }, description: 'Link to observation IDs.' },
|
|
715
|
-
},
|
|
716
|
-
required: ['name'],
|
|
717
|
-
},
|
|
718
|
-
description: 'Entities to create or update (max 10 per call).',
|
|
719
|
-
},
|
|
720
|
-
},
|
|
721
|
-
required: ['entities'],
|
|
722
|
-
},
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
name: 'memory_recent',
|
|
726
|
-
description: 'Returns the most recent observations for the current project, deduplicated by (role, summary). Use this when the session-start hint indicates prior observations are available — fetch them on demand instead of paying for them every session.',
|
|
727
|
-
inputSchema: {
|
|
728
|
-
type: 'object',
|
|
729
|
-
properties: {
|
|
730
|
-
cwd: { type: 'string', description: 'Project directory (default: process.cwd()).' },
|
|
731
|
-
project: { type: 'string', description: 'Filter by project name (default: inferred from cwd).' },
|
|
732
|
-
limit: { type: 'number', description: 'Max distinct observations (default: 10, max: 50).' },
|
|
733
|
-
},
|
|
734
|
-
},
|
|
735
|
-
},
|
|
736
|
-
{
|
|
737
|
-
name: 'rovo_search',
|
|
738
|
-
description: 'Cross-system semantic search via Atlassian Rovo. Searches Jira, Confluence, and other accessible sources. Returns excerpts with source attribution. Does NOT store results in the observation store. Use for broad queries across all sources, not just focal projects.',
|
|
739
|
-
inputSchema: {
|
|
740
|
-
type: 'object',
|
|
741
|
-
properties: {
|
|
742
|
-
query: { type: 'string', description: 'Search query (e.g., "Iverson reliability", "DR failover").' },
|
|
743
|
-
top_k: { type: 'number', description: 'Max results (default: 10, max: 50).' },
|
|
744
|
-
sources: { type: 'string', description: 'Comma-separated source filter (e.g., "jira,confluence").' },
|
|
745
|
-
},
|
|
746
|
-
required: ['query'],
|
|
747
|
-
},
|
|
748
|
-
},
|
|
749
|
-
{
|
|
750
|
-
name: 'efficiency_snapshot',
|
|
751
|
-
description: 'Returns the read-efficiency snapshot for the current session — repeated reads, large reads, hot-spot files, and recommendations. Use this when investigating why a session feels slow or to surface optimization opportunities.',
|
|
752
|
-
inputSchema: {
|
|
753
|
-
type: 'object',
|
|
754
|
-
properties: {
|
|
755
|
-
home_dir: { type: 'string', description: 'Home directory override (default: os.homedir()).' },
|
|
756
|
-
},
|
|
757
|
-
},
|
|
758
|
-
},
|
|
759
|
-
{
|
|
760
|
-
name: 'session_usage',
|
|
761
|
-
description: 'Returns locally recorded interaction token and cost usage for the current Construct session.',
|
|
762
|
-
inputSchema: {
|
|
763
|
-
type: 'object',
|
|
764
|
-
properties: {
|
|
765
|
-
cwd: { type: 'string', description: 'Project directory (default: process.cwd()).' },
|
|
766
|
-
home_dir: { type: 'string', description: 'Home directory override for reading ~/.cx session logs.' },
|
|
767
|
-
},
|
|
768
|
-
},
|
|
769
|
-
},
|
|
770
|
-
{
|
|
771
|
-
name: 'provider_fetch',
|
|
772
|
-
description: 'Look up current data for a configured repo, project, or team. This is an internal lookup against sources the operator has already authorized (set in config.env). Call this immediately — no user approval needed — whenever the user asks about a specific repo, project, or team name (e.g. "what is project iverson", "cloud-reliability status", "PLAT issues"). Pass the user\'s query and the tool resolves the right source automatically. Returns repo metadata, README, docs, open PRs, issues, and recent commits, then stores them as observations.',
|
|
773
|
-
inputSchema: {
|
|
774
|
-
type: 'object',
|
|
775
|
-
required: ['query'],
|
|
776
|
-
properties: {
|
|
777
|
-
query: { type: 'string', description: 'The user\'s question or the project/repo name (e.g. "project iverson", "hashicorp/project-iverson", "PLAT"). The tool matches this against configured GITHUB_REPOS, JIRA_PROJECTS, LINEAR_TEAMS.' },
|
|
778
|
-
root_dir: { type: 'string', description: 'Data root dir override (default: homedir()). Use CX_DATA_DIR value if set.' },
|
|
779
|
-
team_id: { type: 'string', description: 'Optional team id (from the unified registry). Scopes the fetch to that team\'s declared sources; observations are tagged team:<id>.' },
|
|
780
|
-
target_ids: { type: 'array', items: { type: 'string' }, description: 'Optional source-target ids to restrict to (must belong to team_id). A target outside the team returns a typed OUT_OF_SCOPE error rather than a silent wrong-source fetch.' },
|
|
781
|
-
},
|
|
782
|
-
},
|
|
783
|
-
},
|
|
784
|
-
{
|
|
785
|
-
name: 'scope_show',
|
|
786
|
-
description: 'Return the active Construct scope (id, displayName, roles, departments, intake taxonomy, doc templates). Use when a specialist needs to know which role set, classification taxonomy, or doc templates apply before drafting work.',
|
|
787
|
-
inputSchema: {
|
|
788
|
-
type: 'object',
|
|
789
|
-
properties: {
|
|
790
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
791
|
-
id: { type: 'string', description: 'Force a specific scope id instead of resolving from config.' },
|
|
792
|
-
},
|
|
793
|
-
},
|
|
794
|
-
},
|
|
795
|
-
{
|
|
796
|
-
name: 'scope_list',
|
|
797
|
-
description: 'List the curated org scope catalog (rnd, operations, creative, research) with role/department counts. Use to discover which scopes are available before suggesting `construct scope set`.',
|
|
798
|
-
inputSchema: { type: 'object', properties: {} },
|
|
799
|
-
},
|
|
800
|
-
{
|
|
801
|
-
name: 'scope_drafts',
|
|
802
|
-
description: 'List in-progress draft scopes under `.cx/scopes/draft-*` and any user-defined custom scope at `.cx/scope.json`. Use to see what scope work is pending before scaffolding another draft.',
|
|
803
|
-
inputSchema: {
|
|
804
|
-
type: 'object',
|
|
805
|
-
properties: { cwd: { type: 'string', description: 'Project root (default: server cwd).' } },
|
|
806
|
-
},
|
|
807
|
-
},
|
|
808
|
-
{
|
|
809
|
-
name: 'scope_health',
|
|
810
|
-
description: 'Per-scope health rollup over a window: observation count, per-role outcome runs and success rates. Use to check whether a scope is producing data before recommending changes or archive.',
|
|
811
|
-
inputSchema: {
|
|
812
|
-
type: 'object',
|
|
813
|
-
properties: {
|
|
814
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
815
|
-
id: { type: 'string', description: 'Scope id (default: active scope).' },
|
|
816
|
-
window_days: { type: 'number', description: 'Window in days (default 30).' },
|
|
817
|
-
},
|
|
818
|
-
},
|
|
819
|
-
},
|
|
820
|
-
{
|
|
821
|
-
name: 'outcomes_summary',
|
|
822
|
-
description: 'Read `.cx/outcomes/_summary.json` (per-role success rate, 30-day trend). Pass `aggregate=true` to rebuild the summary from JSONL outcome files first. Use to ground tiebreakers and improvement suggestions in real specialist performance.',
|
|
823
|
-
inputSchema: {
|
|
824
|
-
type: 'object',
|
|
825
|
-
properties: {
|
|
826
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
827
|
-
aggregate: { type: 'boolean', description: 'Rebuild `_summary.json` before reading (default false).' },
|
|
828
|
-
},
|
|
829
|
-
},
|
|
830
|
-
},
|
|
831
|
-
{
|
|
832
|
-
name: 'outcomes_record',
|
|
833
|
-
description: 'Append a specialist outcome line to `.cx/outcomes/<role>.jsonl` (writes durable state — requires `confirm=true`). Use when a specialist wants to self-report success/failure outside the automatic agent-tracker path.',
|
|
834
|
-
inputSchema: {
|
|
835
|
-
type: 'object',
|
|
836
|
-
required: ['confirm', 'role', 'success'],
|
|
837
|
-
properties: {
|
|
838
|
-
confirm: { type: 'boolean', description: 'Must be true.' },
|
|
839
|
-
cwd: { type: 'string' },
|
|
840
|
-
role: { type: 'string', description: 'Specialist id (e.g. cx-engineer, product-manager).' },
|
|
841
|
-
success: { type: 'boolean' },
|
|
842
|
-
intake_id: { type: 'string' },
|
|
843
|
-
profile: { type: 'string', description: 'Override active scope id stamp.' },
|
|
844
|
-
escalated: { type: 'boolean' },
|
|
845
|
-
duration_ms: { type: 'number' },
|
|
846
|
-
notes: { type: 'string', description: 'Trimmed to 500 chars.' },
|
|
847
|
-
source: { type: 'string', description: 'Origin tag (default: "mcp").' },
|
|
848
|
-
},
|
|
849
|
-
},
|
|
850
|
-
},
|
|
851
|
-
{
|
|
852
|
-
name: 'knowledge_add',
|
|
853
|
-
description: 'Persist a research finding as `.cx/knowledge/external/research/<slug>.md` with research-specific frontmatter (topic, confidence, sources, expiresAt, scope). Writes durable state — requires `confirm=true`. `confidence=confirmed` requires at least one source.',
|
|
854
|
-
inputSchema: {
|
|
855
|
-
type: 'object',
|
|
856
|
-
required: ['confirm', 'slug', 'topic', 'body'],
|
|
857
|
-
properties: {
|
|
858
|
-
confirm: { type: 'boolean', description: 'Must be true.' },
|
|
859
|
-
cwd: { type: 'string' },
|
|
860
|
-
slug: { type: 'string', description: 'Lowercase hyphenated, max 60 chars.' },
|
|
861
|
-
topic: { type: 'string' },
|
|
862
|
-
body: { type: 'string', description: 'Findings / inferences / gaps / recommendation block. Capped at 50KB total file.' },
|
|
863
|
-
confidence: { type: 'string', enum: ['confirmed', 'inferred', 'weak'], description: 'Default: inferred.' },
|
|
864
|
-
sources: {
|
|
865
|
-
type: 'array',
|
|
866
|
-
description: 'Required when confidence=confirmed.',
|
|
867
|
-
items: {
|
|
868
|
-
type: 'object',
|
|
869
|
-
required: ['url'],
|
|
870
|
-
properties: {
|
|
871
|
-
url: { type: 'string' },
|
|
872
|
-
accessedAt: { type: 'string', description: 'ISO timestamp; default now.' },
|
|
873
|
-
span: { type: 'string', description: 'Citation locator; trimmed to 200 chars.' },
|
|
874
|
-
},
|
|
875
|
-
},
|
|
876
|
-
},
|
|
877
|
-
ttl_days: { type: 'number', description: 'Default 90.' },
|
|
878
|
-
},
|
|
879
|
-
},
|
|
880
|
-
},
|
|
881
|
-
{
|
|
882
|
-
name: 'scope_create',
|
|
883
|
-
description: 'Scaffold a draft org scope under `.cx/scopes/draft-<id>/` (requirements.md + scope.json + persona stubs + department charters). Writes durable state — requires `confirm=true`. For curated catalog work, follow `docs/guides/concepts/scope-lifecycle.md` after creation.',
|
|
884
|
-
inputSchema: {
|
|
885
|
-
type: 'object',
|
|
886
|
-
required: ['confirm', 'id'],
|
|
887
|
-
properties: {
|
|
888
|
-
confirm: { type: 'boolean', description: 'Must be true.' },
|
|
889
|
-
cwd: { type: 'string' },
|
|
890
|
-
id: { type: 'string', description: 'Scope id (^[a-z][a-z0-9-]{1,30}$).' },
|
|
891
|
-
display_name: { type: 'string' },
|
|
892
|
-
seed_roles: {
|
|
893
|
-
type: 'array',
|
|
894
|
-
items: { type: 'string' },
|
|
895
|
-
description: 'Role ids to scaffold persona files for (cap 80).',
|
|
896
|
-
},
|
|
897
|
-
seed_departments: {
|
|
898
|
-
type: 'array',
|
|
899
|
-
items: {
|
|
900
|
-
type: 'object',
|
|
901
|
-
required: ['id'],
|
|
902
|
-
properties: {
|
|
903
|
-
id: { type: 'string' },
|
|
904
|
-
displayName: { type: 'string' },
|
|
905
|
-
},
|
|
906
|
-
},
|
|
907
|
-
description: 'Departments to scaffold charters for (cap 12).',
|
|
908
|
-
},
|
|
909
|
-
},
|
|
910
|
-
},
|
|
911
|
-
},
|
|
912
|
-
{
|
|
913
|
-
name: 'scope_archive',
|
|
914
|
-
description: 'Archive a curated scope: moves `specialists/org/scopes/<id>.json` and its intake table into `archive/scopes/<id>/` with an archive note. Destructive — requires `confirm=true` and a substantive `reason` (>=8 chars). Observations and outcomes are preserved.',
|
|
915
|
-
inputSchema: {
|
|
916
|
-
type: 'object',
|
|
917
|
-
required: ['confirm', 'id', 'reason'],
|
|
918
|
-
properties: {
|
|
919
|
-
confirm: { type: 'boolean', description: 'Must be true.' },
|
|
920
|
-
id: { type: 'string' },
|
|
921
|
-
reason: { type: 'string', description: 'Substantive reason (>= 8 chars).' },
|
|
922
|
-
},
|
|
923
|
-
},
|
|
924
|
-
},
|
|
925
|
-
{
|
|
926
|
-
name: 'sandbox_list',
|
|
927
|
-
description: 'List Construct sandboxes under `~/.cx/sandboxes/` (id, path, createdAt). Use to find an isolated environment for QA or dry-runs without polluting the active project.',
|
|
928
|
-
inputSchema: { type: 'object', properties: {} },
|
|
929
|
-
},
|
|
930
|
-
{
|
|
931
|
-
name: 'knowledge_graph_ask',
|
|
932
|
-
description: 'GraphRAG-style global query over the entity graph in `.cx/observations/`. Detects communities via label propagation, ranks them by BM25 against the query, and returns each top community with its central members and extractive summary. Use for "tell me about how X relates across the project" questions that pure semantic retrieval handles poorly.',
|
|
933
|
-
inputSchema: {
|
|
934
|
-
type: 'object',
|
|
935
|
-
required: ['query'],
|
|
936
|
-
properties: {
|
|
937
|
-
query: { type: 'string', description: 'Natural-language question.' },
|
|
938
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
939
|
-
top_k: { type: 'number', description: 'Max communities to return (default 5).' },
|
|
940
|
-
min_size: { type: 'number', description: 'Skip communities smaller than this (default 2).' },
|
|
941
|
-
tags: { type: 'array', items: { type: 'string' }, description: 'Restrict entity extraction to observations carrying these tags.' },
|
|
942
|
-
tag_match: { type: 'string', enum: ['any', 'all'], description: 'Tag match mode: any (default) or all.' },
|
|
943
|
-
},
|
|
944
|
-
},
|
|
945
|
-
},
|
|
946
|
-
{
|
|
947
|
-
name: 'learning_status',
|
|
948
|
-
description: 'One-shot mirror of `npm run learning:status`: active scope, observation counts (last 24h + total), research finding count, per-role outcome rollup. Use to answer "is Construct learning?" without spawning a shell.',
|
|
949
|
-
inputSchema: {
|
|
950
|
-
type: 'object',
|
|
951
|
-
properties: { cwd: { type: 'string', description: 'Project root (default: server cwd).' } },
|
|
952
|
-
},
|
|
953
|
-
},
|
|
954
|
-
{
|
|
955
|
-
name: 'document_export',
|
|
956
|
-
description: 'Convert a markdown file into a distributable document — PDF, DOCX, legacy DOC (LibreOffice), deck HTML, PPTX, HTML, RTF, ODT, EPUB, LaTeX, plain text, or Markdown — via Pandoc and Typst (PDF engine) plus optional pptxgenjs/LibreOffice, per ADR-0024. Engines are optional dependencies discovered at runtime — the tool returns a structured "install <binary>" error when tooling is absent, never crashes. Use `detect_only=true` to check availability without running an export.',
|
|
957
|
-
inputSchema: {
|
|
958
|
-
type: 'object',
|
|
959
|
-
required: ['format'],
|
|
960
|
-
properties: {
|
|
961
|
-
input_path: { type: 'string', description: 'Absolute path to the markdown source file (required unless detect_only=true).' },
|
|
962
|
-
output_path: { type: 'string', description: 'Optional absolute output path; defaults to <input>.<format> next to the source.' },
|
|
963
|
-
format: { type: 'string', enum: ['pdf', 'docx', 'doc', 'deck', 'pptx', 'html', 'rtf', 'odt', 'epub', 'tex', 'txt', 'md', 'mdx'], description: 'Target format.' },
|
|
964
|
-
detect_only: { type: 'boolean', description: 'When true, report binary availability without exporting. Default false.' },
|
|
965
|
-
figures: { type: 'boolean', description: 'When true, render d2/mermaid via pandoc-ext/diagram filter. Default false.' },
|
|
966
|
-
},
|
|
967
|
-
},
|
|
968
|
-
},
|
|
969
|
-
{
|
|
970
|
-
name: 'publish_detect',
|
|
971
|
-
description: 'Detect availability of publish pipeline tooling: Pandoc/Typst export, pandoc-ext/diagram figures, and VHS terminal demos.',
|
|
972
|
-
inputSchema: {
|
|
973
|
-
type: 'object',
|
|
974
|
-
properties: {
|
|
975
|
-
format: { type: 'string', enum: ['pdf', 'docx', 'doc', 'deck', 'pptx', 'html', 'rtf', 'odt', 'epub', 'tex', 'txt', 'md', 'mdx'], description: 'Export format to probe (default pdf).' },
|
|
976
|
-
figures: { type: 'boolean', description: 'Include figure binaries (default true).' },
|
|
977
|
-
demo: { type: 'string', description: 'When set, require VHS/asciinema for terminal demo.' },
|
|
978
|
-
},
|
|
979
|
-
},
|
|
980
|
-
},
|
|
981
|
-
{
|
|
982
|
-
name: 'publish_run',
|
|
983
|
-
description: 'Run the publish pipeline: export markdown with optional figure filter and optional demo recordings. Use dry_run=true to probe tooling only.',
|
|
984
|
-
inputSchema: {
|
|
985
|
-
type: 'object',
|
|
986
|
-
required: ['input_path'],
|
|
987
|
-
properties: {
|
|
988
|
-
input_path: { type: 'string', description: 'Absolute path to markdown research brief.' },
|
|
989
|
-
output_path: { type: 'string', description: 'Optional output path for export.' },
|
|
990
|
-
format: { type: 'string', enum: ['pdf', 'docx', 'doc', 'deck', 'pptx', 'html', 'rtf', 'odt', 'epub', 'tex', 'txt', 'md', 'mdx'], description: 'Target format (default pdf).' },
|
|
991
|
-
demo: { type: 'string', description: 'Terminal tape name to record.' },
|
|
992
|
-
figures: { type: 'boolean', description: 'Render diagrams (default true).' },
|
|
993
|
-
strict: { type: 'boolean', description: 'Fail when toolchain or release gate fails (default true).' },
|
|
994
|
-
source_only: { type: 'boolean', description: 'Write sources only (default false).' },
|
|
995
|
-
no_gate: { type: 'boolean', description: 'Skip artifact release gate (default false).' },
|
|
996
|
-
artifact_type: { type: 'string', description: 'Manifest doc type for release gate when path inference is ambiguous.' },
|
|
997
|
-
dry_run: { type: 'boolean', description: 'Detect tooling only (default false).' },
|
|
998
|
-
},
|
|
999
|
-
},
|
|
1000
|
-
},
|
|
1001
|
-
{
|
|
1002
|
-
name: 'knowledge_search',
|
|
1003
|
-
description: 'Search Construct\'s own documentation, knowledge base, and distilled embed observations. Call this immediately — no approval needed — when the user asks what Construct is, how a feature works, what commands exist, or anything about Construct\'s architecture or configuration. Also searches embed observations from GitHub, Jira, and other configured sources. Returns relevant excerpts with source file and heading.',
|
|
1004
|
-
inputSchema: {
|
|
1005
|
-
type: 'object',
|
|
1006
|
-
required: ['query'],
|
|
1007
|
-
properties: {
|
|
1008
|
-
query: { type: 'string', description: 'Natural-language question or keyword (e.g. "what is construct", "how does embed mode work", "provider authority guard", "slack configuration", "open Jira issues").' },
|
|
1009
|
-
top_k: { type: 'number', description: 'Max excerpts to return (default: 5).' },
|
|
1010
|
-
repo_root: { type: 'string', description: 'Repo root override (default: auto-detected from server location).' },
|
|
1011
|
-
root_dir: { type: 'string', description: 'Data directory where .cx/observations/ lives (default: home directory). Pass this to search embed observations from a custom data dir.' },
|
|
1012
|
-
},
|
|
1013
|
-
},
|
|
1014
|
-
},
|
|
1015
|
-
{
|
|
1016
|
-
name: 'workflow_init',
|
|
1017
|
-
description: 'Initialize a new workflow for the current project. Creates plan.md state if not already present and returns the initial workflow envelope.',
|
|
1018
|
-
inputSchema: {
|
|
1019
|
-
type: 'object',
|
|
1020
|
-
properties: {
|
|
1021
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
1022
|
-
title: { type: 'string', description: 'Workflow title shown in the plan header (default: "Untitled workflow").' },
|
|
1023
|
-
spec_ref: { type: 'string', description: 'Optional reference to a spec/PRD/ADR id this workflow implements.' },
|
|
1024
|
-
},
|
|
1025
|
-
},
|
|
1026
|
-
},
|
|
1027
|
-
{
|
|
1028
|
-
name: 'workflow_add_task',
|
|
1029
|
-
description: 'Add a task to the current workflow. Pass `request` for intent-based routing (the classifier picks track + specialist) or pass explicit task fields (`key`, `title`, etc.) for manual entry.',
|
|
1030
|
-
inputSchema: {
|
|
1031
|
-
type: 'object',
|
|
1032
|
-
properties: {
|
|
1033
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
1034
|
-
request: { type: 'string', description: 'Natural-language task request; when present, intent-based routing is used and the explicit fields below act as overrides.' },
|
|
1035
|
-
key: { type: 'string', description: 'Stable task key (e.g. T-001). Generated when omitted.' },
|
|
1036
|
-
title: { type: 'string', description: 'Short task title.' },
|
|
1037
|
-
phase: { type: 'string', description: 'Phase bucket (plan, build, validate, ship, etc.).' },
|
|
1038
|
-
owner: { type: 'string', description: 'Specialist or persona that owns the task.' },
|
|
1039
|
-
files: { type: 'array', items: { type: 'string' }, description: 'File paths this task touches.' },
|
|
1040
|
-
readFirst: { type: 'array', items: { type: 'string' }, description: 'Files the owner should read before editing.' },
|
|
1041
|
-
doNotChange: { type: 'array', items: { type: 'string' }, description: 'Files/regions the owner must not modify.' },
|
|
1042
|
-
acceptanceCriteria: { type: 'array', items: { type: 'string' }, description: 'Acceptance criteria as a checklist.' },
|
|
1043
|
-
verification: { type: 'string', description: 'Command(s) or description of how to verify the task is done.' },
|
|
1044
|
-
dependsOn: { type: 'array', items: { type: 'string' }, description: 'Task keys this task depends on.' },
|
|
1045
|
-
overlays: { type: 'array', items: { type: 'string' }, description: 'Role flavors that augment the owner persona for this task.' },
|
|
1046
|
-
challengeRequired: { type: 'boolean', description: 'Force a cx-devil-advocate challenge before the task can complete.' },
|
|
1047
|
-
challengeStatus: { type: 'string', description: 'Initial challenge status when seeded.' },
|
|
1048
|
-
tokenBudget: { type: 'number', description: 'Per-task token budget for cost tracking.' },
|
|
1049
|
-
status: { type: 'string', description: 'Initial status override.' },
|
|
1050
|
-
},
|
|
1051
|
-
},
|
|
1052
|
-
},
|
|
1053
|
-
{
|
|
1054
|
-
name: 'workflow_update_task',
|
|
1055
|
-
description: 'Update fields on an existing workflow task. Requires the task `key`. Only fields supplied are changed.',
|
|
1056
|
-
inputSchema: {
|
|
1057
|
-
type: 'object',
|
|
1058
|
-
required: ['key'],
|
|
1059
|
-
properties: {
|
|
1060
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
1061
|
-
key: { type: 'string', description: 'Task key to update.' },
|
|
1062
|
-
status: { type: 'string', description: 'New status (pending, in_progress, blocked_needs_user, blocked_by_dep, done, etc.).' },
|
|
1063
|
-
owner: { type: 'string', description: 'New owner persona.' },
|
|
1064
|
-
phase: { type: 'string', description: 'New phase bucket.' },
|
|
1065
|
-
note: { type: 'string', description: 'Append-only progress note.' },
|
|
1066
|
-
verification: { type: 'string', description: 'Updated verification description.' },
|
|
1067
|
-
overlays: { type: 'array', items: { type: 'string' }, description: 'Replace the overlay list.' },
|
|
1068
|
-
challengeRequired: { type: 'boolean', description: 'Toggle whether a challenge is required.' },
|
|
1069
|
-
challengeStatus: { type: 'string', description: 'Update the challenge status (proposed, accepted, refused, etc.).' },
|
|
1070
|
-
},
|
|
1071
|
-
},
|
|
1072
|
-
},
|
|
1073
|
-
{
|
|
1074
|
-
name: 'workflow_needs_main_input',
|
|
1075
|
-
description: 'Mark a workflow task as blocked pending user input. Sets status to blocked_needs_user and writes a packet describing the blocker for the orchestrator to surface.',
|
|
1076
|
-
inputSchema: {
|
|
1077
|
-
type: 'object',
|
|
1078
|
-
required: ['taskKey', 'blocker', 'question'],
|
|
1079
|
-
properties: {
|
|
1080
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
1081
|
-
taskKey: { type: 'string', description: 'Task key to mark blocked.' },
|
|
1082
|
-
worker: { type: 'string', description: 'Specialist that needs input (default: current owner).' },
|
|
1083
|
-
blocker: { type: 'string', description: 'One-line description of what is blocking progress.' },
|
|
1084
|
-
question: { type: 'string', description: 'The specific question to put to the user.' },
|
|
1085
|
-
},
|
|
1086
|
-
},
|
|
1087
|
-
},
|
|
1088
|
-
{
|
|
1089
|
-
name: 'workflow_validate',
|
|
1090
|
-
description: 'Validate the current workflow state against the schema and run consistency checks (no orphan tasks, no circular dependencies, every owner resolves to a known persona).',
|
|
1091
|
-
inputSchema: {
|
|
1092
|
-
type: 'object',
|
|
1093
|
-
properties: {
|
|
1094
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
1095
|
-
},
|
|
1096
|
-
},
|
|
1097
|
-
},
|
|
1098
|
-
{
|
|
1099
|
-
name: 'workflow_status',
|
|
1100
|
-
description: 'Return the full workflow snapshot for the current project: tasks, summary, alignment health, and the public-health surface used by the dashboard.',
|
|
1101
|
-
inputSchema: {
|
|
1102
|
-
type: 'object',
|
|
1103
|
-
properties: {
|
|
1104
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
1105
|
-
},
|
|
1106
|
-
},
|
|
1107
|
-
},
|
|
1108
|
-
{
|
|
1109
|
-
name: 'workflow_contract_validate',
|
|
1110
|
-
description: 'Validate a producer→consumer handoff against specialists/org. Required when a specialist hands off to another role: enforces input.mustContain, output schema, disk-artifact postconditions, and binary postconditions per producer (rubber-stamp prevention, post-hoc threat-model prevention, etc.). Self-enforcing: a producer with binary rules MUST pass `packet`, or the call itself is a contract violation.',
|
|
1111
|
-
inputSchema: {
|
|
1112
|
-
type: 'object',
|
|
1113
|
-
required: ['producer', 'consumer'],
|
|
1114
|
-
properties: {
|
|
1115
|
-
producer: { type: 'string', description: 'Producer agent or persona name (e.g. cx-reviewer, cx-security).' },
|
|
1116
|
-
consumer: { type: 'string', description: 'Consumer agent or persona name receiving the handoff.' },
|
|
1117
|
-
id: { type: 'string', description: 'Optional contract id; overrides producer/consumer lookup.' },
|
|
1118
|
-
artifact: { type: 'object', description: 'The handoff payload to validate against the contract schema and disk-artifact postconditions.' },
|
|
1119
|
-
packet: { type: 'object', description: 'The producer\'s in-memory output packet. REQUIRED when the producer has binary postconditions; omitting it is itself a contract violation.' },
|
|
1120
|
-
enforcement: { type: 'string', enum: ['block', 'warn'], description: 'Enforcement mode (default: block). Use warn only when explicitly advisory.' },
|
|
1121
|
-
},
|
|
1122
|
-
},
|
|
1123
|
-
},
|
|
1124
|
-
{
|
|
1125
|
-
name: 'workflow_import_plan',
|
|
1126
|
-
description: 'Bulk-add tasks from a markdown plan to the current workflow. Parses headings and bullet structure to extract task titles, owners, and acceptance criteria.',
|
|
1127
|
-
inputSchema: {
|
|
1128
|
-
type: 'object',
|
|
1129
|
-
required: ['markdown'],
|
|
1130
|
-
properties: {
|
|
1131
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
1132
|
-
markdown: { type: 'string', description: 'Plan markdown to parse.' },
|
|
1133
|
-
phase: { type: 'string', description: 'Phase bucket applied to all imported tasks.' },
|
|
1134
|
-
owner: { type: 'string', description: 'Default owner for tasks that do not specify one.' },
|
|
1135
|
-
readFirst: { type: 'array', items: { type: 'string' }, description: 'Default readFirst files applied to all imported tasks.' },
|
|
1136
|
-
doNotChange: { type: 'array', items: { type: 'string' }, description: 'Default doNotChange files applied to all imported tasks.' },
|
|
1137
|
-
acceptanceCriteria: { type: 'array', items: { type: 'string' }, description: 'Default acceptance criteria applied to all imported tasks.' },
|
|
1138
|
-
title: { type: 'string', description: 'Workflow title to set if the workflow is newly created.' },
|
|
1139
|
-
spec_ref: { type: 'string', description: 'Spec reference to associate with the workflow.' },
|
|
1140
|
-
},
|
|
1141
|
-
},
|
|
1142
|
-
},
|
|
1143
|
-
{
|
|
1144
|
-
name: 'cx_trace_telemetry',
|
|
1145
|
-
description: 'Record a single CX telemetry trace for an agent invocation. Use to log start/end, model used, token cost, and outcome verdict for performance review.',
|
|
1146
|
-
inputSchema: {
|
|
1147
|
-
type: 'object',
|
|
1148
|
-
required: ['agent', 'trace'],
|
|
1149
|
-
properties: {
|
|
1150
|
-
agent: { type: 'string', description: 'Agent or persona name being traced.' },
|
|
1151
|
-
trace: { type: 'object', description: 'Trace record: start_ts, end_ts, model, tokens, verdict, notes, etc.' },
|
|
1152
|
-
cwd: { type: 'string', description: 'Project root (default: server cwd).' },
|
|
1153
|
-
},
|
|
1154
|
-
},
|
|
1155
|
-
},
|
|
1156
|
-
{
|
|
1157
|
-
name: 'artifact_workflow',
|
|
1158
|
-
description: 'Plan a manifest-backed document artifact workflow and return a truthful provenance report. It separates planned steps from locally executed validation/export and never claims a host-planned specialist review or rewrite was completed. Durable local export requires approval_mode=allow-durable-write.',
|
|
1159
|
-
inputSchema: {
|
|
1160
|
-
type: 'object',
|
|
1161
|
-
properties: {
|
|
1162
|
-
input: { type: 'string', description: 'Natural-language artifact request.' },
|
|
1163
|
-
artifact_type: { type: 'string', description: 'Registered manifest document class.' },
|
|
1164
|
-
file_path: { type: 'string', description: 'Optional existing source document for local validation/export.' },
|
|
1165
|
-
format: { type: 'string', description: 'Distribution format such as pdf, docx, html, deck, or pptx.' },
|
|
1166
|
-
output_path: { type: 'string', description: 'Optional output destination when locally exporting.' },
|
|
1167
|
-
branding: { type: 'string', enum: ['construct', 'plain'], description: 'Construct is default; plain is an explicit opt-out.' },
|
|
1168
|
-
overrides: { type: 'object', description: 'Per-invocation manifest workflow overrides.' },
|
|
1169
|
-
approval_mode: { type: 'string', enum: ['proposal-only', 'requires-human-approval', 'allow-durable-write'], description: 'Only allow-durable-write performs local validation/export.' },
|
|
1170
|
-
},
|
|
1171
|
-
},
|
|
1172
|
-
},
|
|
1173
|
-
{
|
|
1174
|
-
name: 'author_artifact',
|
|
1175
|
-
description: 'Materialize a typed Construct artifact you have drafted (prd, prd-platform, prd-business, meta-prd, adr, rfc, research-brief, evidence-brief, runbook) to disk and run the release gate. YOU draft the full markdown — start with a single # title and include the type\'s required ## sections (call get_template first for the shape) — and pass it as draft_markdown; the canonical file is written and the gate verdict + errors are returned so you can fix and re-call. This is the Construct author→materialize→validate pass for supported hosts.',
|
|
1176
|
-
inputSchema: {
|
|
1177
|
-
type: 'object',
|
|
1178
|
-
properties: {
|
|
1179
|
-
draft_markdown: { type: 'string', description: 'The complete artifact markdown you authored. Must start with one # title line and contain the required ## sections for the type.' },
|
|
1180
|
-
artifact_type: { type: 'string', description: 'Artifact type (prd, meta-prd, adr, rfc, research-brief, evidence-brief, runbook, …). Defaults to prd; inferred from subject when omitted.' },
|
|
1181
|
-
subject: { type: 'string', description: 'Short subject/title hint (e.g. "OIDC integration") used for the filename and type inference.' },
|
|
1182
|
-
},
|
|
1183
|
-
required: ['draft_markdown'],
|
|
1184
|
-
},
|
|
1185
|
-
},
|
|
1186
|
-
{
|
|
1187
|
-
name: 'model_resolve',
|
|
1188
|
-
description: 'Resolve which model an embedded Construct workflow should use given the host/IDE provider context. Precedence: host model → same-provider-family fallback → Construct tier default → structured config error. Never reads or returns credential values (requiresCredential is a boolean) and never claims unverified provider health. Read-only; performs no writes.',
|
|
1189
|
-
inputSchema: {
|
|
1190
|
-
type: 'object',
|
|
1191
|
-
properties: {
|
|
1192
|
-
workflow_type: { type: 'string', description: 'Workflow type hint (e.g. evidence-ingest, prd-draft, architecture-review). Selects a tier when requested_tier is absent.' },
|
|
1193
|
-
requested_tier: { type: 'string', enum: ['reasoning', 'standard', 'fast'], description: 'Desired tier; overrides the workflow-type hint.' },
|
|
1194
|
-
host: { type: 'string', description: 'Host/IDE identifier (advisory).' },
|
|
1195
|
-
host_model: { type: 'string', description: 'Model the host is currently using (e.g. anthropic/claude-sonnet-4-6).' },
|
|
1196
|
-
host_provider: { type: 'string', description: 'Provider family the host uses, when no host_model is given.' },
|
|
1197
|
-
capabilities: { type: 'array', items: { type: 'string' }, description: 'Optional required capabilities; unverifiable ones are returned as warnings.' },
|
|
1198
|
-
allow_cross_provider_fallback: { type: 'boolean', description: 'Permit falling back outside the host provider family (default false).' },
|
|
1199
|
-
},
|
|
1200
|
-
},
|
|
1201
|
-
},
|
|
1202
|
-
{
|
|
1203
|
-
name: 'triage_recommend',
|
|
1204
|
-
description: 'Classify an artifact and return a role-aware plan (primary owner, role chain with rationale, suggested skills, evidence requirements, expected outputs, approval requirements, risks, next steps, canExecute) WITHOUT enqueuing or executing. Classification confidence is reported distinctly from any generation confidence. Read-only; performs no durable write.',
|
|
1205
|
-
inputSchema: {
|
|
1206
|
-
type: 'object',
|
|
1207
|
-
properties: {
|
|
1208
|
-
input: { type: 'string', description: 'Artifact text to classify (meeting notes, bug report, proposal, etc.). Provide this OR file_path.' },
|
|
1209
|
-
file_path: { type: 'string', description: 'Path to a file to extract and classify (PDF/Office via docling, audio/video via whisper, transcripts, plain text). Used when input is absent.' },
|
|
1210
|
-
source_path: { type: 'string', description: 'Optional filename/source hint to aid classification.' },
|
|
1211
|
-
artifact_type: { type: 'string', description: 'Optional artifact-type hint (advisory).' },
|
|
1212
|
-
domain: { type: 'string', description: 'Optional broad domain hint.' },
|
|
1213
|
-
desired_outcome: { type: 'string', description: 'Optional desired outcome (advisory).' },
|
|
1214
|
-
constraints: { type: 'array', items: { type: 'string' }, description: 'Optional constraints (advisory).' },
|
|
1215
|
-
available_roles: { type: 'array', items: { type: 'string' }, description: 'Restrict the plan to these role ids; dropped roles are reported as warnings.' },
|
|
1216
|
-
},
|
|
1217
|
-
},
|
|
1218
|
-
},
|
|
1219
|
-
{
|
|
1220
|
-
name: 'workflow_invoke',
|
|
1221
|
-
description: 'Invoke a named Construct workflow (roles/skills) non-interactively and return a provenanced execution plan: selected roles, rationale, applied skills, resolved model, evidence requirements, output contract, risks, and a traceId. Construct returns the orchestration plan; the host runtime performs specialist reasoning. Durable writes occur ONLY when approval_mode is allow-durable-write; proposal-only and requires-human-approval perform no durable writes.',
|
|
1222
|
-
inputSchema: {
|
|
1223
|
-
type: 'object',
|
|
1224
|
-
required: ['workflow_type'],
|
|
1225
|
-
properties: {
|
|
1226
|
-
workflow_type: { type: 'string', description: 'One of: evidence-ingest, proposal-review, prd-draft, architecture-review, risk-review, research-synthesis.' },
|
|
1227
|
-
input: { type: 'string', description: 'Artifact text the workflow operates on. Provide this OR file_path.' },
|
|
1228
|
-
file_path: { type: 'string', description: 'Path to a file to extract (docling/whisper/transcript) and operate on, used when input is absent.' },
|
|
1229
|
-
context: { type: 'object', description: 'Optional structured context; keys matching evidence requirements mark them satisfied.' },
|
|
1230
|
-
role_strategy: { type: 'string', enum: ['auto', 'explicit', 'constrained'], description: 'auto = default chain; explicit = use requested_roles; constrained = default chain intersected with requested_roles.' },
|
|
1231
|
-
requested_roles: { type: 'array', items: { type: 'string' }, description: 'Role ids for explicit/constrained strategies.' },
|
|
1232
|
-
approval_mode: { type: 'string', enum: ['proposal-only', 'requires-human-approval', 'allow-durable-write'], description: 'Gate for durable writes (default: the workflow type default).' },
|
|
1233
|
-
trace: { type: 'boolean', description: 'Emit a traceId for provenance correlation (default true).' },
|
|
1234
|
-
host: { type: 'string', description: 'Host/IDE identifier (advisory).' },
|
|
1235
|
-
host_model: { type: 'string', description: 'Model the host uses, for model resolution.' },
|
|
1236
|
-
host_provider: { type: 'string', description: 'Provider family the host uses, for model resolution.' },
|
|
1237
|
-
},
|
|
1238
|
-
},
|
|
1239
|
-
},
|
|
1240
|
-
{
|
|
1241
|
-
name: 'capability_describe',
|
|
1242
|
-
description: 'Describe what this Construct install can do: versions, contract interfaces (CLI/MCP/SDK), roles, skills, workflows, schemas, models/providers, policies, telemetry posture, and plugins. Read-only and secret-free — provider entries carry env-key names and a configured boolean only, never credential values. Reads live registries so the published contract cannot drift from reality.',
|
|
1243
|
-
inputSchema: {
|
|
1244
|
-
type: 'object',
|
|
1245
|
-
properties: {
|
|
1246
|
-
root_dir: { type: 'string', description: 'Optional Construct install root (default: server toolkit dir).' },
|
|
1247
|
-
},
|
|
1248
|
-
},
|
|
1249
|
-
},
|
|
1250
|
-
{
|
|
1251
|
-
name: 'construct_execution_resolve',
|
|
1252
|
-
description: 'Resolve the execution-capability contract for an embedded workflow BEFORE/at workflow start: returns executionMode (construct-orchestrated | construct-prompt-only | host-direct | same-family-fallback), constructCapabilitiesActive (subset of personas/skills/workflow-routing/prompt-envelope), degraded + machine-readable degradationReason, requestedStrategy vs effectiveStrategy, and the resolved provider/model. Descriptive, not enforced: reports what Construct planned and can resolve a model for, never an observation that the host ran personas (see the semantics field). Read-only and secret-free.',
|
|
1253
|
-
inputSchema: {
|
|
1254
|
-
type: 'object',
|
|
1255
|
-
properties: {
|
|
1256
|
-
workflow_type: { type: 'string', description: 'Workflow whose orchestration plan is weighed (e.g. evidence-ingest, architecture-review). Absent ⇒ generic orchestration availability.' },
|
|
1257
|
-
requested_strategy: { type: 'string', enum: ['orchestrated', 'prompt-only', 'auto'], description: 'Desired execution strategy (default auto).' },
|
|
1258
|
-
use_construct: { type: 'boolean', description: 'false ⇒ host-direct (host runs without Construct capabilities). Default true.' },
|
|
1259
|
-
host: { type: 'string', description: 'Host/IDE identifier (advisory).' },
|
|
1260
|
-
host_model: { type: 'string', description: 'Model the host is currently using, for model resolution.' },
|
|
1261
|
-
host_provider: { type: 'string', description: 'Provider family the host uses, when no host_model is given.' },
|
|
1262
|
-
requested_tier: { type: 'string', enum: ['reasoning', 'standard', 'fast'], description: 'Desired model tier; overrides the workflow-type hint.' },
|
|
1263
|
-
capabilities: { type: 'array', items: { type: 'string' }, description: 'Optional required capabilities; unverifiable ones are returned as warnings.' },
|
|
1264
|
-
allow_cross_provider_fallback: { type: 'boolean', description: 'Permit model fallback outside the host provider family (default false).' },
|
|
1265
|
-
},
|
|
1266
|
-
},
|
|
1267
|
-
},
|
|
1268
|
-
{
|
|
1269
|
-
name: 'orchestration_run',
|
|
1270
|
-
description: 'EXECUTE a real multi-specialist orchestration run and return per-specialist output — the executing counterpart to workflow_invoke (which only plans). For MCP hosts with no subagent primitive (VS Code/Copilot, Cursor), this is how you actually run a specialist chain: the engine owns orchestration, this tool is the thin client (ADR-0022). Solo runs execute in-process — no daemon, no port, no token; a remote/team orchestration service is opt-in via CONSTRUCT_ORCHESTRATION_URL. Real specialist output requires the `provider` worker backend (a provider key configured); the default `inline` backend prepares tasks only.',
|
|
1271
|
-
inputSchema: {
|
|
1272
|
-
type: 'object',
|
|
1273
|
-
required: ['request'],
|
|
1274
|
-
properties: {
|
|
1275
|
-
request: { type: 'string', description: 'Natural-language description of the work to orchestrate (e.g. "refactor the auth module and review it for security").' },
|
|
1276
|
-
workflow_type: { type: 'string', description: 'Optional workflow type to shape the plan (e.g. architecture-review, risk-review).' },
|
|
1277
|
-
requested_strategy: { type: 'string', enum: ['orchestrated', 'prompt-only', 'auto'], description: 'Execution strategy (default auto).' },
|
|
1278
|
-
worker_backend: { type: 'string', enum: ['inline', 'provider'], description: 'provider executes specialists (needs a provider key); inline prepares only. Default: daemon config.' },
|
|
1279
|
-
host: { type: 'string', description: 'Host/IDE identifier (advisory).' },
|
|
1280
|
-
host_model: { type: 'string', description: 'Model the host uses, for model resolution.' },
|
|
1281
|
-
host_provider: { type: 'string', description: 'Provider family the host uses, for model resolution.' },
|
|
1282
|
-
file_count: { type: 'number', description: 'Optional planning hint: number of files in scope.' },
|
|
1283
|
-
module_count: { type: 'number', description: 'Optional planning hint: number of modules in scope.' },
|
|
1284
|
-
wait: { type: 'boolean', description: 'Wait for the run to reach a terminal state and return task output (default true). false returns the runId immediately to poll with orchestration_status.' },
|
|
1285
|
-
timeout_ms: { type: 'number', description: 'Max time to wait when wait=true (default 120000). On timeout the runId is returned to poll.' },
|
|
1286
|
-
},
|
|
1287
|
-
},
|
|
1288
|
-
},
|
|
1289
|
-
{
|
|
1290
|
-
name: 'web_search',
|
|
1291
|
-
description: 'Search the PUBLIC WEB and return CITED results — the only search surface that reaches the open web, kept distinct from knowledge_search / provider_fetch / repo search so it is never conflated or faked. Requires a governed provider (WEB_SEARCH_URL); without one it returns a typed degradation (capability-unavailable) and zero results, never source/repo results dressed as web. Every result carries a verifiable URL, a claim-relative class, and an Admiralty grade with derived confidence (ADR-0017; high reserved for A1/A2/B1).',
|
|
1292
|
-
inputSchema: {
|
|
1293
|
-
type: 'object',
|
|
1294
|
-
required: ['query', 'claim'],
|
|
1295
|
-
properties: {
|
|
1296
|
-
query: { type: 'string', description: 'The search query string.' },
|
|
1297
|
-
claim: { type: 'string', description: 'The claim the results are meant to support — drives claim-relative source classification (ADR-0017).' },
|
|
1298
|
-
recency: { type: 'string', description: 'Optional freshness window hint (e.g. "30d").' },
|
|
1299
|
-
},
|
|
1300
|
-
},
|
|
1301
|
-
},
|
|
1302
|
-
{
|
|
1303
|
-
name: 'orchestration_status',
|
|
1304
|
-
description: 'Inspect orchestration runs on the local Construct daemon: pass run_id for the full record (status, per-task status/executor/output/error), or omit it for a list of recent runs. Fails fast if the daemon is unreachable.',
|
|
1305
|
-
inputSchema: {
|
|
1306
|
-
type: 'object',
|
|
1307
|
-
properties: {
|
|
1308
|
-
run_id: { type: 'string', description: 'Run id to fetch. Omit to list recent runs.' },
|
|
1309
|
-
limit: { type: 'number', description: 'Max runs to list when run_id is omitted (default 20).' },
|
|
1310
|
-
},
|
|
1311
|
-
},
|
|
1312
|
-
},
|
|
1313
|
-
{
|
|
1314
|
-
name: 'orchestration_readiness',
|
|
1315
|
-
description: 'Report whether this MCP session has the required Construct orchestration tools attached and reachable now. Returns a pass/fail verdict, typed reasonCode, one next step, required/observed/missing tools, and a redacted diagnostic bundle for support.',
|
|
1316
|
-
inputSchema: {
|
|
1317
|
-
type: 'object',
|
|
1318
|
-
properties: {
|
|
1319
|
-
host: { type: 'string', description: 'Host/IDE identifier, if known.' },
|
|
1320
|
-
session_id: { type: 'string', description: 'Host session/thread id, if known.' },
|
|
1321
|
-
observed_tools: { type: 'array', items: { type: 'string' }, description: 'Optional tool names the host observed in tools/list. Defaults to this server catalog.' },
|
|
1322
|
-
reachable_tools: { type: 'array', items: { type: 'string' }, description: 'Optional long-tail tools reachable through a gateway enum.' },
|
|
1323
|
-
required_tools: { type: 'array', items: { type: 'string' }, description: 'Tools required for orchestration. Defaults to orchestration_policy + orchestration_run.' },
|
|
1324
|
-
client_contract_version: { type: 'string', description: 'Client contract version for compatibility checks.' },
|
|
1325
|
-
observation_scope: { type: 'string', enum: ['host-session', 'local-config'], description: 'What was observed. MCP calls normally use host-session.' },
|
|
1326
|
-
},
|
|
1327
|
-
},
|
|
1328
|
-
},
|
|
1329
|
-
];
|
|
183
|
+
// Every tool def gains a declared outputSchema and a safety block (class, fs/
|
|
184
|
+
// network/process scope) from TOOL_SAFETY. A tool missing from that table throws
|
|
185
|
+
// here rather than shipping unclassified — see lib/mcp/tool-safety.mjs.
|
|
186
|
+
|
|
187
|
+
function withSafetyEnvelope(def) {
|
|
188
|
+
const safety = TOOL_SAFETY[def.name];
|
|
189
|
+
if (!safety) {
|
|
190
|
+
throw new Error(`tool-safety: "${def.name}" has no safety classification — add one to lib/mcp/tool-safety.mjs`);
|
|
191
|
+
}
|
|
192
|
+
return { ...def, outputSchema: def.outputSchema ?? DEFAULT_OUTPUT_SCHEMA, safety };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const HARDCODED_TOOL_DEFS = RAW_HARDCODED_TOOL_DEFS.map(withSafetyEnvelope);
|
|
196
|
+
|
|
197
|
+
// Self-registered tools (LMCP-B5): any `<name>.tool.mjs` file under
|
|
198
|
+
// lib/mcp/tools/ exporting TOOL_DEFS + TOOL_HANDLERS joins the catalog here
|
|
199
|
+
// without editing this file — see lib/mcp/tool-registry.mjs. Scan errors
|
|
200
|
+
// (a module that failed to import) are logged, not fatal; a module that
|
|
201
|
+
// imported but declared a tool with no safety classification throws, same
|
|
202
|
+
// fail-loud contract as withSafetyEnvelope above.
|
|
203
|
+
|
|
204
|
+
const { defs: SCANNED_TOOL_DEFS, handlers: SCANNED_TOOL_HANDLERS, errors: SCANNED_TOOL_ERRORS } = await scanToolModules();
|
|
205
|
+
for (const err of SCANNED_TOOL_ERRORS) console.error(`[construct-mcp] tool module scan: ${err}`);
|
|
206
|
+
|
|
207
|
+
const ALL_TOOL_DEFS = [...HARDCODED_TOOL_DEFS, ...SCANNED_TOOL_DEFS];
|
|
1330
208
|
|
|
1331
209
|
// Curated flat core: high-frequency, low-arg tools the orchestrator and the
|
|
1332
210
|
// built-in Build/Plan agents actually reach for. Everything else collapses
|
|
@@ -1340,15 +218,22 @@ const CORE_TOOL_NAMES = new Set([
|
|
|
1340
218
|
'workflow_invoke', 'triage_recommend', 'orchestration_readiness',
|
|
1341
219
|
]);
|
|
1342
220
|
|
|
1343
|
-
const LONG_TAIL_DEFS = ALL_TOOL_DEFS.filter((t) => !CORE_TOOL_NAMES.has(t.name));
|
|
1344
221
|
const KNOWN_TOOL_NAMES = new Set(ALL_TOOL_DEFS.map((t) => t.name));
|
|
1345
222
|
|
|
223
|
+
// The core/long-tail split is hand-maintained beside the catalog; a typo in a
|
|
224
|
+
// core name would silently drop a tool from both the flat surface and the gateway
|
|
225
|
+
// enum. Fail fast at module load against the catalog as the single source of truth.
|
|
226
|
+
|
|
227
|
+
assertCoreSubsetOfCatalog(CORE_TOOL_NAMES, KNOWN_TOOL_NAMES);
|
|
228
|
+
|
|
229
|
+
const LONG_TAIL_DEFS = ALL_TOOL_DEFS.filter((t) => !CORE_TOOL_NAMES.has(t.name));
|
|
230
|
+
|
|
1346
231
|
// One dispatcher for the long tail. `tool` is constrained to an enum of valid
|
|
1347
232
|
// names (≈1 token each — kills hallucinated names, the key small-model lever),
|
|
1348
233
|
// and the description carries a compact one-line catalog instead of ~10k of full
|
|
1349
234
|
// schemas. Dispatch reuses the same handlers via dispatchToolByName.
|
|
1350
235
|
|
|
1351
|
-
const CONSTRUCT_CALL_TOOL = {
|
|
236
|
+
const CONSTRUCT_CALL_TOOL = withSafetyEnvelope({
|
|
1352
237
|
name: 'call',
|
|
1353
238
|
description:
|
|
1354
239
|
'Invoke any non-core Construct tool by name: provide `tool` and `args`. '
|
|
@@ -1363,7 +248,7 @@ const CONSTRUCT_CALL_TOOL = {
|
|
|
1363
248
|
},
|
|
1364
249
|
required: ['tool'],
|
|
1365
250
|
},
|
|
1366
|
-
};
|
|
251
|
+
});
|
|
1367
252
|
|
|
1368
253
|
export function exposedTools() {
|
|
1369
254
|
return [...ALL_TOOL_DEFS.filter((t) => CORE_TOOL_NAMES.has(t.name)), CONSTRUCT_CALL_TOOL];
|
|
@@ -1437,6 +322,7 @@ export async function dispatchToolByName(name, args = {}) {
|
|
|
1437
322
|
const { demandFetch } = await import('../embed/demand-fetch.mjs');
|
|
1438
323
|
result = await demandFetch({ query: args.query, rootDir: args.root_dir, teamId: args.team_id, targetIds: args.target_ids });
|
|
1439
324
|
}
|
|
325
|
+
else if (name === 'provider_write') result = await providerWrite(args, { rootDir: opts.ROOT_DIR });
|
|
1440
326
|
else if (name === 'knowledge_search') {
|
|
1441
327
|
const { knowledgeSearch } = await import('../knowledge/search.mjs');
|
|
1442
328
|
result = knowledgeSearch({ query: args.query, topK: args.top_k, repoRoot: args.repo_root, rootDir: args.root_dir });
|
|
@@ -1508,14 +394,54 @@ export async function dispatchToolByName(name, args = {}) {
|
|
|
1508
394
|
else if (name === 'find_tool') result = await findTool(args, { toolDefs: ALL_TOOL_DEFS, env: process.env });
|
|
1509
395
|
else if (name === 'orchestration_readiness') {
|
|
1510
396
|
const catalog = currentMcpToolCatalog();
|
|
397
|
+
// Only the label 'host-session' when the caller actually reported what
|
|
398
|
+
// its session observed; falling back to this server's own catalog is a
|
|
399
|
+
// liveness-shaped self-report and must say so, never wear the
|
|
400
|
+
// serve-ability label it did not earn.
|
|
401
|
+
const callerObserved = Array.isArray(args.observed_tools) || Array.isArray(args.reachable_tools);
|
|
402
|
+
// Host provenance (construct-6y6w.7 pattern): default host from the MCP
|
|
403
|
+
// initialize handshake so hostExecutionViable reflects a real attached
|
|
404
|
+
// client, not just whatever an explicit args.host claims.
|
|
1511
405
|
result = buildOrchestrationReadiness({
|
|
406
|
+
host: server.getClientVersion()?.name,
|
|
1512
407
|
...args,
|
|
1513
408
|
observedTools: args.observed_tools ?? catalog.observedTools,
|
|
1514
409
|
reachableTools: args.reachable_tools ?? catalog.reachableTools,
|
|
1515
|
-
observationScope: args.observation_scope ?? 'host-session',
|
|
410
|
+
observationScope: args.observation_scope ?? (callerObserved ? 'host-session' : 'server-self-report'),
|
|
1516
411
|
}, { env: process.env, cwd: process.cwd() });
|
|
1517
412
|
}
|
|
1518
|
-
else if (name === 'orchestration_run') {
|
|
413
|
+
else if (name === 'orchestration_run') {
|
|
414
|
+
// Host provenance (construct-6y6w.7): default host from the MCP initialize
|
|
415
|
+
// handshake's clientInfo.name so run records reflect the real caller (VS
|
|
416
|
+
// Code, OpenCode, ...) instead of always falling through to cli-direct. An
|
|
417
|
+
// explicit args.host still wins — the spread after `host` overrides it.
|
|
418
|
+
const m = await import('./tools/orchestration-run.mjs');
|
|
419
|
+
const clientName = server.getClientVersion()?.name;
|
|
420
|
+
result = await m.orchestrationRun({ host: clientName, ...args });
|
|
421
|
+
|
|
422
|
+
// Phase 2 (LMCP host-execution): a run that materialized and stood at
|
|
423
|
+
// 'awaiting-host' is, by default, left for the calling agent to execute
|
|
424
|
+
// and submit back (Phase 1 pickup). When the connected client declared
|
|
425
|
+
// the MCP sampling capability at initialize time, construct-mcp instead
|
|
426
|
+
// drives that same loop itself via server.createMessage, so the run can
|
|
427
|
+
// finish in this same call rather than round-tripping through the
|
|
428
|
+
// caller's own turn. resolveHostExecutionMode degrades to pickup when
|
|
429
|
+
// the client never declared sampling, or when config forces pickup.
|
|
430
|
+
if (result && result.status === 'awaiting-host' && result.runId) {
|
|
431
|
+
const { resolveHostExecutionMode, driveHostSamplingLoop } = await import('../orchestration/host-sampling.mjs');
|
|
432
|
+
const { loadProjectConfig } = await import('../config/project-config.mjs');
|
|
433
|
+
const { getRun } = await import('../orchestration/runtime.mjs');
|
|
434
|
+
const config = (() => { try { return loadProjectConfig(process.cwd(), process.env).config || {}; } catch { return {}; } })();
|
|
435
|
+
const mode = resolveHostExecutionMode({ config, clientCapabilities: server.getClientCapabilities() });
|
|
436
|
+
if (mode === 'sampling') {
|
|
437
|
+
const freshRun = await getRun(process.cwd(), result.runId, { env: process.env });
|
|
438
|
+
if (freshRun) {
|
|
439
|
+
const driven = await driveHostSamplingLoop({ server, run: freshRun, cwd: process.cwd(), env: process.env });
|
|
440
|
+
result = m.shapeRun(driven);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
1519
445
|
else if (name === 'web_search') { const m = await import('./tools/web-search.mjs'); result = await m.webSearch(args); }
|
|
1520
446
|
else if (name === 'orchestration_status') { const m = await import('./tools/orchestration-run.mjs'); result = await m.orchestrationStatus(args); }
|
|
1521
447
|
else if (name === 'call') {
|
|
@@ -1523,6 +449,7 @@ export async function dispatchToolByName(name, args = {}) {
|
|
|
1523
449
|
if (!inner || isGatewayName(inner)) result = { error: "call requires a 'tool' name to invoke (e.g. { tool: 'document_export', args: {…} })" };
|
|
1524
450
|
else result = await dispatchToolByName(inner, args?.args || {});
|
|
1525
451
|
}
|
|
452
|
+
else if (SCANNED_TOOL_HANDLERS.has(name)) result = await SCANNED_TOOL_HANDLERS.get(name)(args, opts);
|
|
1526
453
|
else result = await resolveUnknownToolName(name, args);
|
|
1527
454
|
return result;
|
|
1528
455
|
}
|
|
@@ -1543,58 +470,15 @@ async function resolveUnknownToolName(name, args = {}) {
|
|
|
1543
470
|
return { error: `Unknown tool: ${name}. Core tools are flat; invoke any other tool via { name: 'call', arguments: { tool: '<name>', args: {…} } }.` };
|
|
1544
471
|
}
|
|
1545
472
|
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
// must never break dispatch — a malformed _meta should not fail the call.
|
|
1551
|
-
let parentCtx = {};
|
|
1552
|
-
try { parentCtx = await extractTraceContext(request.params?._meta || {}); } catch { /* tracing optional */ }
|
|
1553
|
-
void parentCtx;
|
|
1554
|
-
|
|
1555
|
-
// Bound every tool call. A tool that stalls (a stuck external extractor, a slow
|
|
1556
|
-
// model load, a wedged subprocess) must surface a clean timeout error to the
|
|
1557
|
-
// client rather than block the request until the client gives up and reports an
|
|
1558
|
-
// opaque failure. Override with CONSTRUCT_MCP_TOOL_TIMEOUT_MS (0 disables).
|
|
1559
|
-
const TOOL_TIMEOUT_MS = (() => {
|
|
1560
|
-
const raw = Number(process.env.CONSTRUCT_MCP_TOOL_TIMEOUT_MS);
|
|
1561
|
-
return Number.isFinite(raw) && raw >= 0 ? raw : 120_000;
|
|
1562
|
-
})();
|
|
1563
|
-
|
|
1564
|
-
const dispatch = (async () => {
|
|
1565
|
-
let result;
|
|
1566
|
-
try {
|
|
1567
|
-
result = await dispatchToolByName(name, args);
|
|
1568
|
-
} catch (err) {
|
|
1569
|
-
result = { error: err.message ?? String(err) };
|
|
1570
|
-
}
|
|
1571
|
-
return result;
|
|
1572
|
-
})();
|
|
1573
|
-
|
|
1574
|
-
let toolResult;
|
|
1575
|
-
if (!TOOL_TIMEOUT_MS) {
|
|
1576
|
-
toolResult = await dispatch;
|
|
1577
|
-
} else {
|
|
1578
|
-
let timer;
|
|
1579
|
-
const timeout = new Promise((_, reject) => {
|
|
1580
|
-
timer = setTimeout(
|
|
1581
|
-
() => reject(new Error(`tool ${name} timed out after ${Math.round(TOOL_TIMEOUT_MS / 1000)}s`)),
|
|
1582
|
-
TOOL_TIMEOUT_MS,
|
|
1583
|
-
);
|
|
1584
|
-
});
|
|
1585
|
-
try {
|
|
1586
|
-
toolResult = await Promise.race([dispatch, timeout]);
|
|
1587
|
-
} catch (err) {
|
|
1588
|
-
toolResult = { error: err.message ?? String(err) };
|
|
1589
|
-
} finally {
|
|
1590
|
-
clearTimeout(timer);
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
473
|
+
// Rate limiting, the destructive gate, tracing, timeout, and audit logging
|
|
474
|
+
// around every dispatch live in dispatch-envelope.mjs (construct-rf26.10);
|
|
475
|
+
// the factory call below wires them to server.mjs's own ROOT_DIR/
|
|
476
|
+
// DEPLOYMENT_MODE and the dispatchToolByName defined above.
|
|
1593
477
|
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
}
|
|
1597
|
-
|
|
478
|
+
server.setRequestHandler(
|
|
479
|
+
CallToolRequestSchema,
|
|
480
|
+
createToolCallHandler({ ROOT_DIR, DEPLOYMENT_MODE, dispatchToolByName }),
|
|
481
|
+
);
|
|
1598
482
|
|
|
1599
483
|
const cxTraceBound = (args) => cxTrace(args, opts);
|
|
1600
484
|
const projectContextBound = (args) => projectContext(args, opts);
|
|
@@ -1613,11 +497,23 @@ export {
|
|
|
1613
497
|
storageReset,
|
|
1614
498
|
deleteIngestedArtifactsTool,
|
|
1615
499
|
agentContract,
|
|
500
|
+
ALL_TOOL_DEFS,
|
|
1616
501
|
};
|
|
1617
502
|
|
|
1618
503
|
const argv1Real = (() => { try { return realpathSync(process.argv[1]); } catch { return process.argv[1]; } })();
|
|
1619
504
|
if (fileURLToPath(import.meta.url) === argv1Real) {
|
|
1620
|
-
|
|
505
|
+
// Orchestration tool calls that omit an explicit cwd default to this
|
|
506
|
+
// process's cwd, which is host-launch-dependent (construct-6y6w.9) — the
|
|
507
|
+
// same tool call can read/write a different project depending on which host
|
|
508
|
+
// launched the server and from where. Logging the resolved cwd at startup
|
|
509
|
+
// makes that binding diagnosable instead of silent.
|
|
510
|
+
console.error(`[construct-mcp] server started (cwd: ${process.cwd()})`);
|
|
511
|
+
|
|
512
|
+
// Orchestration and provider-backed tools resolve credentials in the server's
|
|
513
|
+
// own process; wiring the sink at the entry records those op reads on the same
|
|
514
|
+
// trail as the CLI. Scoped to the server entry so importing this module for a
|
|
515
|
+
// test never installs the process-global sink.
|
|
516
|
+
enableSecretAuditTrail();
|
|
1621
517
|
|
|
1622
518
|
// A long-running stdio server must survive a single malformed request: a
|
|
1623
519
|
// background rejection from one ingest (e.g. a broken docling sidecar that
|
|
@@ -1631,6 +527,27 @@ if (fileURLToPath(import.meta.url) === argv1Real) {
|
|
|
1631
527
|
console.error('[construct-mcp] uncaughtException (kept alive):', err?.stack || err);
|
|
1632
528
|
});
|
|
1633
529
|
|
|
1634
|
-
|
|
1635
|
-
|
|
530
|
+
// Transport is selected explicitly: stdio-local is the default and is byte-
|
|
531
|
+
// for-byte the original stdio path; http-remote is opt-in via
|
|
532
|
+
// CONSTRUCT_MCP_TRANSPORT and fails closed at startup when its auth config is
|
|
533
|
+
// absent, so a network surface never comes up unauthenticated.
|
|
534
|
+
|
|
535
|
+
// A startup auth-config failure in http-remote mode must exit non-zero, not be
|
|
536
|
+
// absorbed by the keep-alive handlers above — fail-closed means the process
|
|
537
|
+
// does not come up, not that it comes up degraded. The keep-alive guarantee
|
|
538
|
+
// is for in-flight request errors after a transport is already serving.
|
|
539
|
+
|
|
540
|
+
const mode = resolveTransportMode(process.env);
|
|
541
|
+
if (mode === TRANSPORT_HTTP) {
|
|
542
|
+
let config;
|
|
543
|
+
try {
|
|
544
|
+
({ config } = await startHttpTransport(server, { env: process.env }));
|
|
545
|
+
} catch (err) {
|
|
546
|
+
console.error('[construct-mcp] http-remote transport refused to start:', err?.message || err);
|
|
547
|
+
process.exit(1);
|
|
548
|
+
}
|
|
549
|
+
console.error(`[construct-mcp] http-remote transport listening on ${config.bindHost}:${config.bindPort}`);
|
|
550
|
+
} else {
|
|
551
|
+
await startStdioTransport(server);
|
|
552
|
+
}
|
|
1636
553
|
}
|