@structured-vibe-coding/core 0.14.3 → 0.16.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.
@@ -0,0 +1,53 @@
1
+ # External MCP *sources* that sdd will *call* (sdd = client).
2
+ # Not the same as `sdd mcp serve` (that exposes sdd tools *to* agents).
3
+ #
4
+ # Use cases:
5
+ # - Org UI/UX / design-system MCP
6
+ # - Internal API catalog MCP
7
+ # - Third-party or custom AST / code-search MCP
8
+ #
9
+ # sdd matches sources by stage / workflow / keywords / intents, then invokes
10
+ # the configured tool and can embed results in agent handoff.
11
+ #
12
+ # Add via CLI:
13
+ # sdd mcp sources add --id design-system --command npx --arg -y --arg @acme/ds-mcp \
14
+ # --stages design,implement --intents ui,design --tool search_components \
15
+ # --tool-arg query={{query}}
16
+ #
17
+ version: 1
18
+ auto_fetch_on_handoff: true
19
+ max_chars_per_source: 6000
20
+ sources: []
21
+
22
+ # Example (uncomment and edit):
23
+ #
24
+ # sources:
25
+ # - id: design-system
26
+ # description: Acme design system components and tokens
27
+ # command: npx
28
+ # args: ["-y", "@acme/design-system-mcp"]
29
+ # priority: 20
30
+ # when:
31
+ # stages: [design, implement, stories]
32
+ # workflows: [feature, enterprise-feature]
33
+ # intents: [ui, design, component]
34
+ # keywords: [button, token, theme, component]
35
+ # invoke:
36
+ # tool: search_components
37
+ # args:
38
+ # query: "{{query}}"
39
+ #
40
+ # - id: code-ast
41
+ # description: AST / symbol search for this monorepo (external engine)
42
+ # command: npx
43
+ # args: ["-y", "@example/ast-search-mcp"]
44
+ # cwd: "{{projectRoot}}"
45
+ # priority: 30
46
+ # when:
47
+ # stages: [implement, code_research, local_verify]
48
+ # intents: [code, implement]
49
+ # invoke:
50
+ # tool: search
51
+ # args:
52
+ # query: "{{query}}"
53
+ # root: "{{projectRoot}}"
@@ -19,9 +19,9 @@ import {
19
19
  removeOtherAgentHosts,
20
20
  renderThinAgent,
21
21
  writeAgentHandoff
22
- } from "./chunk-S7SHVKG4.js";
22
+ } from "./chunk-GR7KIAR2.js";
23
+ import "./chunk-RRBKQ76B.js";
23
24
  import "./chunk-OJFMJHNL.js";
24
- import "./chunk-C725DWSB.js";
25
25
  import "./chunk-A752UVPF.js";
26
26
  import "./chunk-67AUAGNV.js";
27
27
  import "./chunk-7MJYPJMR.js";
@@ -245,7 +245,7 @@ async function createChange(input) {
245
245
  await materializeStageArtifacts(projectRoot, config, id, workflow, meta, firstStage);
246
246
  await setActiveChange(projectRoot, config, id);
247
247
  try {
248
- const { refreshActiveAgentContext } = await import("./agents-WL3PNTJL.js");
248
+ const { refreshActiveAgentContext } = await import("./agents-7NS5LFEZ.js");
249
249
  await refreshActiveAgentContext(projectRoot);
250
250
  } catch {
251
251
  }
@@ -333,7 +333,7 @@ async function advanceStage(projectRoot, config, changeId, opts) {
333
333
  stage2
334
334
  );
335
335
  try {
336
- const { refreshActiveAgentContext } = await import("./agents-WL3PNTJL.js");
336
+ const { refreshActiveAgentContext } = await import("./agents-7NS5LFEZ.js");
337
337
  await refreshActiveAgentContext(projectRoot);
338
338
  } catch {
339
339
  }
@@ -380,7 +380,7 @@ async function advanceStage(projectRoot, config, changeId, opts) {
380
380
  stage
381
381
  );
382
382
  try {
383
- const { refreshActiveAgentContext } = await import("./agents-WL3PNTJL.js");
383
+ const { refreshActiveAgentContext } = await import("./agents-7NS5LFEZ.js");
384
384
  await refreshActiveAgentContext(projectRoot);
385
385
  } catch {
386
386
  }
@@ -484,7 +484,7 @@ async function completeChange(projectRoot, config, changeId) {
484
484
  let promoted;
485
485
  if (ctx.meta.workflow === "greenfield" || ctx.meta.flags?.greenfield === true) {
486
486
  try {
487
- const { promoteGreenfieldToMemory: promoteGreenfieldToMemory2 } = await import("./greenfield-SY3SB5OT.js");
487
+ const { promoteGreenfieldToMemory: promoteGreenfieldToMemory2 } = await import("./greenfield-3ZH5OASX.js");
488
488
  promoted = await promoteGreenfieldToMemory2(projectRoot, config, changeId);
489
489
  } catch {
490
490
  }
@@ -1,10 +1,10 @@
1
- import {
2
- loadConfig
3
- } from "./chunk-OJFMJHNL.js";
4
1
  import {
5
2
  buildAgentPrompt,
6
3
  formatStatus
7
- } from "./chunk-C725DWSB.js";
4
+ } from "./chunk-RRBKQ76B.js";
5
+ import {
6
+ loadConfig
7
+ } from "./chunk-OJFMJHNL.js";
8
8
  import {
9
9
  buildContext,
10
10
  getActiveChangeId
@@ -0,0 +1,147 @@
1
+ import {
2
+ sddRoot
3
+ } from "./chunk-7MJYPJMR.js";
4
+ import {
5
+ ensureDir,
6
+ pathExists,
7
+ readYaml,
8
+ writeYaml
9
+ } from "./chunk-EPFURATC.js";
10
+
11
+ // src/mcp/sources.ts
12
+ import { join } from "pathe";
13
+
14
+ // src/mcp/types.ts
15
+ import { z } from "zod";
16
+ var McpWhenSchema = z.object({
17
+ /** Empty = all stages */
18
+ stages: z.array(z.string()).default([]),
19
+ /** Empty = all workflows */
20
+ workflows: z.array(z.string()).default([]),
21
+ /** Match title/query (case-insensitive substring) */
22
+ keywords: z.array(z.string()).default([]),
23
+ /**
24
+ * High-level intent tags the operator or tool may pass:
25
+ * code | ui | design | api | docs | data
26
+ */
27
+ intents: z.array(z.string()).default([])
28
+ });
29
+ var McpInvokeSchema = z.object({
30
+ /** Tool name on the remote MCP server */
31
+ tool: z.string(),
32
+ /**
33
+ * Static args + templates:
34
+ * {{query}} {{title}} {{stage}} {{workflow}} {{projectRoot}}
35
+ */
36
+ args: z.record(z.unknown()).default({})
37
+ });
38
+ var McpSourceSchema = z.object({
39
+ id: z.string().min(1),
40
+ description: z.string().default(""),
41
+ /** stdio only in v1 */
42
+ transport: z.enum(["stdio"]).default("stdio"),
43
+ command: z.string().min(1),
44
+ args: z.array(z.string()).default([]),
45
+ env: z.record(z.string()).default({}),
46
+ /** Working directory (default: project root). Supports {{projectRoot}} */
47
+ cwd: z.string().optional(),
48
+ enabled: z.boolean().default(true),
49
+ /** Higher runs first when gathering */
50
+ priority: z.number().default(0),
51
+ when: McpWhenSchema.default({}),
52
+ /**
53
+ * How sdd calls this source when auto-gathering for a stage.
54
+ * If omitted, `sdd mcp fetch` still works with an explicit --tool.
55
+ */
56
+ invoke: McpInvokeSchema.optional(),
57
+ /** Optional allowlist of tool names (documentation / validation) */
58
+ tools: z.array(z.string()).optional()
59
+ });
60
+ var McpConfigSchema = z.object({
61
+ version: z.number().default(1),
62
+ /**
63
+ * When true, handoff generation calls matching sources with `invoke` and
64
+ * embeds results under "External MCP context".
65
+ */
66
+ auto_fetch_on_handoff: z.boolean().default(true),
67
+ /** Max chars of MCP output embedded into handoff per source */
68
+ max_chars_per_source: z.number().default(6e3),
69
+ sources: z.array(McpSourceSchema).default([])
70
+ });
71
+
72
+ // src/mcp/sources.ts
73
+ function mcpConfigPath(projectRoot) {
74
+ return join(sddRoot(projectRoot), "mcp.yaml");
75
+ }
76
+ function defaultMcpConfig() {
77
+ return McpConfigSchema.parse({
78
+ version: 1,
79
+ auto_fetch_on_handoff: true,
80
+ max_chars_per_source: 6e3,
81
+ sources: []
82
+ });
83
+ }
84
+ async function loadMcpConfig(projectRoot) {
85
+ const path = mcpConfigPath(projectRoot);
86
+ if (!await pathExists(path)) {
87
+ return defaultMcpConfig();
88
+ }
89
+ const raw = await readYaml(path);
90
+ return McpConfigSchema.parse(raw ?? {});
91
+ }
92
+ async function saveMcpConfig(projectRoot, config) {
93
+ await ensureDir(sddRoot(projectRoot));
94
+ const path = mcpConfigPath(projectRoot);
95
+ await writeYaml(path, McpConfigSchema.parse(config));
96
+ return path;
97
+ }
98
+ async function ensureMcpConfig(projectRoot) {
99
+ const path = mcpConfigPath(projectRoot);
100
+ if (!await pathExists(path)) {
101
+ const cfg = defaultMcpConfig();
102
+ await saveMcpConfig(projectRoot, cfg);
103
+ return cfg;
104
+ }
105
+ return loadMcpConfig(projectRoot);
106
+ }
107
+ async function addMcpSource(projectRoot, source) {
108
+ const cfg = await ensureMcpConfig(projectRoot);
109
+ const parsed = McpSourceSchema.parse(source);
110
+ const rest = cfg.sources.filter((s) => s.id !== parsed.id);
111
+ cfg.sources = [...rest, parsed].sort((a, b) => b.priority - a.priority);
112
+ await saveMcpConfig(projectRoot, cfg);
113
+ return cfg;
114
+ }
115
+ async function removeMcpSource(projectRoot, id) {
116
+ const cfg = await ensureMcpConfig(projectRoot);
117
+ cfg.sources = cfg.sources.filter((s) => s.id !== id);
118
+ await saveMcpConfig(projectRoot, cfg);
119
+ return cfg;
120
+ }
121
+ function interpolate(value, vars) {
122
+ return value.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? "");
123
+ }
124
+ function interpolateArgs(args, vars) {
125
+ const out = {};
126
+ for (const [k, v] of Object.entries(args)) {
127
+ if (typeof v === "string") out[k] = interpolate(v, vars);
128
+ else out[k] = v;
129
+ }
130
+ return out;
131
+ }
132
+
133
+ export {
134
+ McpWhenSchema,
135
+ McpInvokeSchema,
136
+ McpSourceSchema,
137
+ McpConfigSchema,
138
+ mcpConfigPath,
139
+ defaultMcpConfig,
140
+ loadMcpConfig,
141
+ saveMcpConfig,
142
+ ensureMcpConfig,
143
+ addMcpSource,
144
+ removeMcpSource,
145
+ interpolate,
146
+ interpolateArgs
147
+ };
@@ -106,10 +106,41 @@ async function buildAgentPrompt(ctx, config, projectRoot) {
106
106
  `2. If present, read: \`changes/${ctx.id}/code-context.md\` (regenerate if stale)`
107
107
  );
108
108
  parts.push(
109
- `Do not dump unbounded source into the prompt; prefer the sliced output.`
109
+ `3. Org libraries / remote AST: configure \`.sdd/mcp.yaml\` and \`sdd mcp fetch\` (see External MCP context below)`
110
+ );
111
+ parts.push(
112
+ `Do not dump unbounded source into the prompt; prefer sliced / MCP output.`
110
113
  );
111
114
  parts.push("");
112
115
  }
116
+ try {
117
+ const { loadMcpConfig } = await import("./sources-PF45EUH2.js");
118
+ const {
119
+ gatherMcpContextForChange,
120
+ formatMcpContextForHandoff
121
+ } = await import("./gather-74DQ35QX.js");
122
+ const mcpCfg = await loadMcpConfig(projectRoot);
123
+ if (mcpCfg.auto_fetch_on_handoff && mcpCfg.sources.length) {
124
+ const fetched = await gatherMcpContextForChange(projectRoot, ctx);
125
+ const block = formatMcpContextForHandoff(
126
+ fetched.filter((r) => r.ok || r.error)
127
+ );
128
+ if (block) {
129
+ parts.push(block);
130
+ }
131
+ } else if (mcpCfg.sources.length === 0) {
132
+ parts.push(`## External MCP sources`);
133
+ parts.push("");
134
+ parts.push(
135
+ `No sources in \`.sdd/mcp.yaml\` yet. To attach org libraries / AST engines:`
136
+ );
137
+ parts.push(
138
+ `\`sdd mcp sources add --help\` \xB7 docs: Configure MCP sources`
139
+ );
140
+ parts.push("");
141
+ }
142
+ } catch {
143
+ }
113
144
  parts.push(
114
145
  `When done with this stage, the human will run \`sdd next\` or \`sdd verify\` / \`sdd complete\`.`
115
146
  );
@@ -0,0 +1,236 @@
1
+ import {
2
+ interpolate,
3
+ interpolateArgs,
4
+ loadMcpConfig
5
+ } from "./chunk-KYWETNFU.js";
6
+
7
+ // src/mcp/client.ts
8
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
9
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
10
+ function contentToText(result) {
11
+ const parts = result.content ?? [];
12
+ return parts.map((p) => p.type === "text" ? p.text ?? "" : JSON.stringify(p)).join("\n").trim();
13
+ }
14
+ async function withMcpSource(source, projectRoot, fn) {
15
+ const vars = { projectRoot };
16
+ const cwd = source.cwd ? interpolate(source.cwd, vars) : projectRoot;
17
+ const env = {
18
+ ...process.env,
19
+ ...source.env,
20
+ SDD_PROJECT_ROOT: projectRoot
21
+ };
22
+ const transport = new StdioClientTransport({
23
+ command: source.command,
24
+ args: source.args,
25
+ cwd,
26
+ env
27
+ });
28
+ const client = new Client({
29
+ name: "sdd-mcp-client",
30
+ version: "0.14.0"
31
+ });
32
+ await client.connect(transport);
33
+ try {
34
+ return await fn(client);
35
+ } finally {
36
+ try {
37
+ await client.close();
38
+ } catch {
39
+ }
40
+ }
41
+ }
42
+ async function listMcpSourceTools(source, projectRoot) {
43
+ return withMcpSource(source, projectRoot, async (client) => {
44
+ const listed = await client.listTools();
45
+ return listed.tools.map((t) => ({
46
+ name: t.name,
47
+ description: t.description
48
+ }));
49
+ });
50
+ }
51
+ async function callMcpSourceTool(source, projectRoot, tool, args) {
52
+ try {
53
+ if (source.tools?.length && !source.tools.includes(tool)) {
54
+ return {
55
+ ok: false,
56
+ text: "",
57
+ error: `Tool "${tool}" not in allowlist for source ${source.id}: ${source.tools.join(", ")}`
58
+ };
59
+ }
60
+ return await withMcpSource(source, projectRoot, async (client) => {
61
+ const result = await client.callTool({ name: tool, arguments: args });
62
+ const text = contentToText(result);
63
+ const isError = Boolean(result.isError);
64
+ return {
65
+ ok: !isError,
66
+ text: text || (isError ? "(empty error result)" : "(empty)"),
67
+ error: isError ? text || "tool returned isError" : void 0
68
+ };
69
+ });
70
+ } catch (err) {
71
+ return {
72
+ ok: false,
73
+ text: "",
74
+ error: err instanceof Error ? err.message : String(err)
75
+ };
76
+ }
77
+ }
78
+
79
+ // src/mcp/match.ts
80
+ function includesCI(list, value) {
81
+ const v = value.toLowerCase();
82
+ return list.some((x) => x.toLowerCase() === v);
83
+ }
84
+ function matchMcpSources(sources, ctx) {
85
+ const stage = ctx.stage ?? "";
86
+ const workflow = ctx.workflow ?? "";
87
+ const query = (ctx.query ?? "").toLowerCase();
88
+ const intents = (ctx.intents ?? []).map((i) => i.toLowerCase());
89
+ const matched = sources.filter((s) => {
90
+ if (!s.enabled) return false;
91
+ const w = s.when;
92
+ if (w.stages.length && stage && !includesCI(w.stages, stage)) {
93
+ return false;
94
+ }
95
+ if (w.workflows.length && workflow && !includesCI(w.workflows, workflow)) {
96
+ return false;
97
+ }
98
+ if (w.intents.length && intents.length) {
99
+ const hit = w.intents.some((i) => intents.includes(i.toLowerCase()));
100
+ if (!hit) return false;
101
+ }
102
+ if (w.keywords.length && query) {
103
+ const hit = w.keywords.some((k) => query.includes(k.toLowerCase()));
104
+ if (!hit) return false;
105
+ }
106
+ return true;
107
+ });
108
+ return matched.sort((a, b) => b.priority - a.priority);
109
+ }
110
+ function explainMatch(source, ctx) {
111
+ const bits = [];
112
+ if (source.when.stages.length) {
113
+ bits.push(`stages=[${source.when.stages.join(",")}]`);
114
+ } else bits.push("stages=*");
115
+ if (source.when.workflows.length) {
116
+ bits.push(`workflows=[${source.when.workflows.join(",")}]`);
117
+ }
118
+ if (source.when.intents.length) {
119
+ bits.push(`intents=[${source.when.intents.join(",")}]`);
120
+ }
121
+ if (source.when.keywords.length) {
122
+ bits.push(`keywords=[${source.when.keywords.join(",")}]`);
123
+ }
124
+ const ok = matchMcpSources([source], ctx).length > 0;
125
+ return `${ok ? "MATCH" : "skip"} ${source.id} (${bits.join(" ")}) stage=${ctx.stage ?? "?"} workflow=${ctx.workflow ?? "?"}`;
126
+ }
127
+
128
+ // src/mcp/gather.ts
129
+ async function gatherMcpContext(opts) {
130
+ const cfg = await loadMcpConfig(opts.projectRoot);
131
+ let sources = matchMcpSources(cfg.sources, opts.match);
132
+ if (opts.sourceIds?.length) {
133
+ const allow = new Set(opts.sourceIds);
134
+ sources = sources.filter((s) => allow.has(s.id));
135
+ }
136
+ const vars = {
137
+ projectRoot: opts.projectRoot,
138
+ query: opts.match.query ?? "",
139
+ title: opts.match.query ?? "",
140
+ stage: opts.match.stage ?? "",
141
+ workflow: opts.match.workflow ?? ""
142
+ };
143
+ const results = [];
144
+ for (const source of sources) {
145
+ const tool = opts.tool ?? source.invoke?.tool;
146
+ if (!tool) {
147
+ if (opts.requireInvoke !== false && !opts.tool) {
148
+ results.push({
149
+ sourceId: source.id,
150
+ tool: "(none)",
151
+ ok: false,
152
+ text: "",
153
+ error: "No invoke.tool configured. Set invoke in .sdd/mcp.yaml or pass --tool."
154
+ });
155
+ }
156
+ continue;
157
+ }
158
+ const baseArgs = opts.args ?? source.invoke?.args ?? {};
159
+ const args = interpolateArgs(
160
+ baseArgs,
161
+ vars
162
+ );
163
+ const called = await callMcpSourceTool(
164
+ source,
165
+ opts.projectRoot,
166
+ tool,
167
+ args
168
+ );
169
+ const max = cfg.max_chars_per_source ?? 6e3;
170
+ let text = called.text;
171
+ if (text.length > max) {
172
+ text = `${text.slice(0, max)}
173
+
174
+ \u2026(truncated at max_chars_per_source=${max})`;
175
+ }
176
+ results.push({
177
+ sourceId: source.id,
178
+ tool,
179
+ ok: called.ok,
180
+ text,
181
+ error: called.error
182
+ });
183
+ }
184
+ return results;
185
+ }
186
+ async function gatherMcpContextForChange(projectRoot, ctx, extra) {
187
+ const cfg = await loadMcpConfig(projectRoot);
188
+ if (!cfg.auto_fetch_on_handoff && !extra?.query) {
189
+ }
190
+ return gatherMcpContext({
191
+ projectRoot,
192
+ match: {
193
+ stage: ctx.meta.stage,
194
+ workflow: ctx.meta.workflow,
195
+ query: extra?.query ?? ctx.meta.title,
196
+ intents: extra?.intents
197
+ },
198
+ requireInvoke: true
199
+ });
200
+ }
201
+ function formatMcpContextForHandoff(results) {
202
+ if (!results.length) return "";
203
+ const parts = [
204
+ "## External MCP context",
205
+ "",
206
+ "Pulled from project-configured MCP *sources* (`.sdd/mcp.yaml`).",
207
+ "Use this instead of guessing org libraries / design systems / remote AST indexes.",
208
+ ""
209
+ ];
210
+ for (const r of results) {
211
+ parts.push(`### Source \`${r.sourceId}\` (tool: \`${r.tool}\`)`);
212
+ parts.push("");
213
+ if (!r.ok) {
214
+ parts.push(`_Error: ${r.error ?? "failed"}_`);
215
+ } else {
216
+ parts.push(r.text || "_(empty)_");
217
+ }
218
+ parts.push("");
219
+ }
220
+ return parts.join("\n");
221
+ }
222
+ function listMatchingSourceIds(sources, match) {
223
+ return matchMcpSources(sources, match).map((s) => s.id);
224
+ }
225
+
226
+ export {
227
+ withMcpSource,
228
+ listMcpSourceTools,
229
+ callMcpSourceTool,
230
+ matchMcpSources,
231
+ explainMatch,
232
+ gatherMcpContext,
233
+ gatherMcpContextForChange,
234
+ formatMcpContextForHandoff,
235
+ listMatchingSourceIds
236
+ };
@@ -0,0 +1,15 @@
1
+ import {
2
+ formatMcpContextForHandoff,
3
+ gatherMcpContext,
4
+ gatherMcpContextForChange,
5
+ listMatchingSourceIds
6
+ } from "./chunk-VD3CPFAI.js";
7
+ import "./chunk-KYWETNFU.js";
8
+ import "./chunk-7MJYPJMR.js";
9
+ import "./chunk-EPFURATC.js";
10
+ export {
11
+ formatMcpContextForHandoff,
12
+ gatherMcpContext,
13
+ gatherMcpContextForChange,
14
+ listMatchingSourceIds
15
+ };
@@ -6,8 +6,8 @@ import {
6
6
  startFeatureFromBacklog,
7
7
  startGreenfield,
8
8
  updateFeatureStatus
9
- } from "./chunk-HOH43IQ2.js";
10
- import "./chunk-C725DWSB.js";
9
+ } from "./chunk-24EXBX7P.js";
10
+ import "./chunk-RRBKQ76B.js";
11
11
  import "./chunk-A752UVPF.js";
12
12
  import "./chunk-67AUAGNV.js";
13
13
  import "./chunk-7MJYPJMR.js";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
3
 
3
4
  declare const GateSchema: z.ZodObject<{
4
5
  type: z.ZodDefault<z.ZodEnum<["none", "soft", "hard"]>>;
@@ -1410,6 +1411,7 @@ declare function defaultsRoot(): string;
1410
1411
  declare function defaultWorkflowsDir(): string;
1411
1412
  declare function defaultTemplatesDir(): string;
1412
1413
  declare function defaultMemoryDir(): string;
1414
+ declare function defaultMcpYamlPath(): string;
1413
1415
 
1414
1416
  declare function pathExists(path: string): Promise<boolean>;
1415
1417
  declare function ensureDir(path: string): Promise<void>;
@@ -1762,4 +1764,399 @@ declare function updateFeatureStatus(backlogPath: string, featureId: string, sta
1762
1764
  */
1763
1765
  declare function promoteGreenfieldToMemory(projectRoot: string, config: Config, changeId: string): Promise<string[]>;
1764
1766
 
1765
- export { AGENT_INTEGRATIONS, AGENT_TARGET_OPTIONS, ALL_AGENT_TARGETS, type AdapterExtractResult, AdapterRegistry, type AdvanceResult, type AgentIntegration, type AgentTarget, type AgentTargetOption, type ArtifactDef, ArtifactDefSchema, type BuildRefinePlanOptions, type ChangeContext, type ChangeMeta, ChangeMetaSchema, type CodeContextCaps, type CodeContextGap, type CodeContextGapCode, type CodeContextRequest, type CodeContextResult, type CodeContextSummary, type CodeSlice, type Complexity, type Config, ConfigSchema, type CreateChangeInput, DEFAULT_CODE_CONTEXT_CAPS, DEFAULT_INIT_INTEGRATION, type FocusPlan, type Gate, GateSchema, type GenerateCodeContextDeps, type GreenfieldFeature, type InitOptions, type InitResult, type InstallAgentOptions, type InstallAgentResult, type InstallAgentsOptions, type InstallAgentsResult, type InstalledAgentSnapshot, type LanguageAdapter, PROTOCOL_MD, type RefineArtifactRef, type RefineMode, type RefinePlan, SDD_AGENT_ROLES, SDD_DIR, type SddAgentRole, type SddAgentRoleId, type Stage, StageSchema, type StartFeatureInput, type StartGreenfieldInput, type StartGreenfieldResult, type SymbolInfo, type SymbolKind, VerifyCommandSchema, type VerifyResult, type Workflow, WorkflowSchema, activePointerPath, activeStages, advanceStage, agentHostPaths, agentKickoffMessage, approveGate, archiveDir, buildAgentPrompt, buildContext, buildRefinePlan, canLeaveStage, changeDirName, changeMetaPath, changePath, changesDir, classifyPath, clearActiveIf, completeChange, configPath, copyDir, copyDirSkipExisting, createChange, defaultConfig, defaultMemoryDir, defaultTemplatesDir, defaultWorkflowsDir, defaultsRoot, domainsDir, ensureDir, fallbackAdapter, fallbackIncompleteStageId, findFeaturesBacklogPath, firstActiveStageId, formatJsonSummary, formatStatus, generateCodeContext, getActiveChangeId, getIntegration, getStage, incompletePriorStageErrors, inferComplexity, initProject, installAgentIntegration, installAgentIntegrations, integrationKeyFor, isIgnoredPath, isInitialized, isSecretPath, isStageSkipped, isSubstantiveArtifactContent, listBacklogFeatures, listChanges, listDirs, listFiles, listWorkflowNames, loadChangeMeta, loadConfig, loadInstalledAgent, loadWorkflow, memoryDir, mergeCaps, nextStageId, nowIso, optionForTarget, parseAgentTargets, parseFeaturesBacklog, parseIntegration, pathExists, promoteGreenfieldToMemory, readText, readYaml, recommendWorkflow, refreshActiveAgentContext, removeOtherAgentHosts, removePath, renderThinAgent, resolveChangeId, resolveFocus, resolveStages, runLocalVerify, saveChangeMeta, saveConfig, sddRoot, setActiveChange, shouldAutoSkip, skipStage, slugify, startFeatureFromBacklog, startGreenfield, switchWorkflow, templatesDir, todayIsoDate, tokenizeKeywords, typescriptAdapter, uniqueChangeDirName, updateFeatureStatus, workflowsDir, writeAgentHandoff, writeRefineBrief, writeText, writeTextIfMissing, writeYaml };
1767
+ /**
1768
+ * External MCP *sources* that sdd consumes (sdd = MCP client).
1769
+ * Distinct from `sdd mcp serve` (sdd as MCP server for agents).
1770
+ */
1771
+ declare const McpWhenSchema: z.ZodObject<{
1772
+ /** Empty = all stages */
1773
+ stages: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1774
+ /** Empty = all workflows */
1775
+ workflows: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1776
+ /** Match title/query (case-insensitive substring) */
1777
+ keywords: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1778
+ /**
1779
+ * High-level intent tags the operator or tool may pass:
1780
+ * code | ui | design | api | docs | data
1781
+ */
1782
+ intents: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1783
+ }, "strip", z.ZodTypeAny, {
1784
+ stages: string[];
1785
+ keywords: string[];
1786
+ workflows: string[];
1787
+ intents: string[];
1788
+ }, {
1789
+ stages?: string[] | undefined;
1790
+ keywords?: string[] | undefined;
1791
+ workflows?: string[] | undefined;
1792
+ intents?: string[] | undefined;
1793
+ }>;
1794
+ declare const McpInvokeSchema: z.ZodObject<{
1795
+ /** Tool name on the remote MCP server */
1796
+ tool: z.ZodString;
1797
+ /**
1798
+ * Static args + templates:
1799
+ * {{query}} {{title}} {{stage}} {{workflow}} {{projectRoot}}
1800
+ */
1801
+ args: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1802
+ }, "strip", z.ZodTypeAny, {
1803
+ tool: string;
1804
+ args: Record<string, unknown>;
1805
+ }, {
1806
+ tool: string;
1807
+ args?: Record<string, unknown> | undefined;
1808
+ }>;
1809
+ declare const McpSourceSchema: z.ZodObject<{
1810
+ id: z.ZodString;
1811
+ description: z.ZodDefault<z.ZodString>;
1812
+ /** stdio only in v1 */
1813
+ transport: z.ZodDefault<z.ZodEnum<["stdio"]>>;
1814
+ command: z.ZodString;
1815
+ args: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1816
+ env: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
1817
+ /** Working directory (default: project root). Supports {{projectRoot}} */
1818
+ cwd: z.ZodOptional<z.ZodString>;
1819
+ enabled: z.ZodDefault<z.ZodBoolean>;
1820
+ /** Higher runs first when gathering */
1821
+ priority: z.ZodDefault<z.ZodNumber>;
1822
+ when: z.ZodDefault<z.ZodObject<{
1823
+ /** Empty = all stages */
1824
+ stages: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1825
+ /** Empty = all workflows */
1826
+ workflows: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1827
+ /** Match title/query (case-insensitive substring) */
1828
+ keywords: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1829
+ /**
1830
+ * High-level intent tags the operator or tool may pass:
1831
+ * code | ui | design | api | docs | data
1832
+ */
1833
+ intents: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1834
+ }, "strip", z.ZodTypeAny, {
1835
+ stages: string[];
1836
+ keywords: string[];
1837
+ workflows: string[];
1838
+ intents: string[];
1839
+ }, {
1840
+ stages?: string[] | undefined;
1841
+ keywords?: string[] | undefined;
1842
+ workflows?: string[] | undefined;
1843
+ intents?: string[] | undefined;
1844
+ }>>;
1845
+ /**
1846
+ * How sdd calls this source when auto-gathering for a stage.
1847
+ * If omitted, `sdd mcp fetch` still works with an explicit --tool.
1848
+ */
1849
+ invoke: z.ZodOptional<z.ZodObject<{
1850
+ /** Tool name on the remote MCP server */
1851
+ tool: z.ZodString;
1852
+ /**
1853
+ * Static args + templates:
1854
+ * {{query}} {{title}} {{stage}} {{workflow}} {{projectRoot}}
1855
+ */
1856
+ args: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1857
+ }, "strip", z.ZodTypeAny, {
1858
+ tool: string;
1859
+ args: Record<string, unknown>;
1860
+ }, {
1861
+ tool: string;
1862
+ args?: Record<string, unknown> | undefined;
1863
+ }>>;
1864
+ /** Optional allowlist of tool names (documentation / validation) */
1865
+ tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1866
+ }, "strip", z.ZodTypeAny, {
1867
+ id: string;
1868
+ description: string;
1869
+ when: {
1870
+ stages: string[];
1871
+ keywords: string[];
1872
+ workflows: string[];
1873
+ intents: string[];
1874
+ };
1875
+ priority: number;
1876
+ args: string[];
1877
+ transport: "stdio";
1878
+ command: string;
1879
+ env: Record<string, string>;
1880
+ enabled: boolean;
1881
+ cwd?: string | undefined;
1882
+ invoke?: {
1883
+ tool: string;
1884
+ args: Record<string, unknown>;
1885
+ } | undefined;
1886
+ tools?: string[] | undefined;
1887
+ }, {
1888
+ id: string;
1889
+ command: string;
1890
+ description?: string | undefined;
1891
+ when?: {
1892
+ stages?: string[] | undefined;
1893
+ keywords?: string[] | undefined;
1894
+ workflows?: string[] | undefined;
1895
+ intents?: string[] | undefined;
1896
+ } | undefined;
1897
+ priority?: number | undefined;
1898
+ args?: string[] | undefined;
1899
+ transport?: "stdio" | undefined;
1900
+ env?: Record<string, string> | undefined;
1901
+ cwd?: string | undefined;
1902
+ enabled?: boolean | undefined;
1903
+ invoke?: {
1904
+ tool: string;
1905
+ args?: Record<string, unknown> | undefined;
1906
+ } | undefined;
1907
+ tools?: string[] | undefined;
1908
+ }>;
1909
+ declare const McpConfigSchema: z.ZodObject<{
1910
+ version: z.ZodDefault<z.ZodNumber>;
1911
+ /**
1912
+ * When true, handoff generation calls matching sources with `invoke` and
1913
+ * embeds results under "External MCP context".
1914
+ */
1915
+ auto_fetch_on_handoff: z.ZodDefault<z.ZodBoolean>;
1916
+ /** Max chars of MCP output embedded into handoff per source */
1917
+ max_chars_per_source: z.ZodDefault<z.ZodNumber>;
1918
+ sources: z.ZodDefault<z.ZodArray<z.ZodObject<{
1919
+ id: z.ZodString;
1920
+ description: z.ZodDefault<z.ZodString>;
1921
+ /** stdio only in v1 */
1922
+ transport: z.ZodDefault<z.ZodEnum<["stdio"]>>;
1923
+ command: z.ZodString;
1924
+ args: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1925
+ env: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
1926
+ /** Working directory (default: project root). Supports {{projectRoot}} */
1927
+ cwd: z.ZodOptional<z.ZodString>;
1928
+ enabled: z.ZodDefault<z.ZodBoolean>;
1929
+ /** Higher runs first when gathering */
1930
+ priority: z.ZodDefault<z.ZodNumber>;
1931
+ when: z.ZodDefault<z.ZodObject<{
1932
+ /** Empty = all stages */
1933
+ stages: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1934
+ /** Empty = all workflows */
1935
+ workflows: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1936
+ /** Match title/query (case-insensitive substring) */
1937
+ keywords: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1938
+ /**
1939
+ * High-level intent tags the operator or tool may pass:
1940
+ * code | ui | design | api | docs | data
1941
+ */
1942
+ intents: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1943
+ }, "strip", z.ZodTypeAny, {
1944
+ stages: string[];
1945
+ keywords: string[];
1946
+ workflows: string[];
1947
+ intents: string[];
1948
+ }, {
1949
+ stages?: string[] | undefined;
1950
+ keywords?: string[] | undefined;
1951
+ workflows?: string[] | undefined;
1952
+ intents?: string[] | undefined;
1953
+ }>>;
1954
+ /**
1955
+ * How sdd calls this source when auto-gathering for a stage.
1956
+ * If omitted, `sdd mcp fetch` still works with an explicit --tool.
1957
+ */
1958
+ invoke: z.ZodOptional<z.ZodObject<{
1959
+ /** Tool name on the remote MCP server */
1960
+ tool: z.ZodString;
1961
+ /**
1962
+ * Static args + templates:
1963
+ * {{query}} {{title}} {{stage}} {{workflow}} {{projectRoot}}
1964
+ */
1965
+ args: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1966
+ }, "strip", z.ZodTypeAny, {
1967
+ tool: string;
1968
+ args: Record<string, unknown>;
1969
+ }, {
1970
+ tool: string;
1971
+ args?: Record<string, unknown> | undefined;
1972
+ }>>;
1973
+ /** Optional allowlist of tool names (documentation / validation) */
1974
+ tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1975
+ }, "strip", z.ZodTypeAny, {
1976
+ id: string;
1977
+ description: string;
1978
+ when: {
1979
+ stages: string[];
1980
+ keywords: string[];
1981
+ workflows: string[];
1982
+ intents: string[];
1983
+ };
1984
+ priority: number;
1985
+ args: string[];
1986
+ transport: "stdio";
1987
+ command: string;
1988
+ env: Record<string, string>;
1989
+ enabled: boolean;
1990
+ cwd?: string | undefined;
1991
+ invoke?: {
1992
+ tool: string;
1993
+ args: Record<string, unknown>;
1994
+ } | undefined;
1995
+ tools?: string[] | undefined;
1996
+ }, {
1997
+ id: string;
1998
+ command: string;
1999
+ description?: string | undefined;
2000
+ when?: {
2001
+ stages?: string[] | undefined;
2002
+ keywords?: string[] | undefined;
2003
+ workflows?: string[] | undefined;
2004
+ intents?: string[] | undefined;
2005
+ } | undefined;
2006
+ priority?: number | undefined;
2007
+ args?: string[] | undefined;
2008
+ transport?: "stdio" | undefined;
2009
+ env?: Record<string, string> | undefined;
2010
+ cwd?: string | undefined;
2011
+ enabled?: boolean | undefined;
2012
+ invoke?: {
2013
+ tool: string;
2014
+ args?: Record<string, unknown> | undefined;
2015
+ } | undefined;
2016
+ tools?: string[] | undefined;
2017
+ }>, "many">>;
2018
+ }, "strip", z.ZodTypeAny, {
2019
+ version: number;
2020
+ auto_fetch_on_handoff: boolean;
2021
+ max_chars_per_source: number;
2022
+ sources: {
2023
+ id: string;
2024
+ description: string;
2025
+ when: {
2026
+ stages: string[];
2027
+ keywords: string[];
2028
+ workflows: string[];
2029
+ intents: string[];
2030
+ };
2031
+ priority: number;
2032
+ args: string[];
2033
+ transport: "stdio";
2034
+ command: string;
2035
+ env: Record<string, string>;
2036
+ enabled: boolean;
2037
+ cwd?: string | undefined;
2038
+ invoke?: {
2039
+ tool: string;
2040
+ args: Record<string, unknown>;
2041
+ } | undefined;
2042
+ tools?: string[] | undefined;
2043
+ }[];
2044
+ }, {
2045
+ version?: number | undefined;
2046
+ auto_fetch_on_handoff?: boolean | undefined;
2047
+ max_chars_per_source?: number | undefined;
2048
+ sources?: {
2049
+ id: string;
2050
+ command: string;
2051
+ description?: string | undefined;
2052
+ when?: {
2053
+ stages?: string[] | undefined;
2054
+ keywords?: string[] | undefined;
2055
+ workflows?: string[] | undefined;
2056
+ intents?: string[] | undefined;
2057
+ } | undefined;
2058
+ priority?: number | undefined;
2059
+ args?: string[] | undefined;
2060
+ transport?: "stdio" | undefined;
2061
+ env?: Record<string, string> | undefined;
2062
+ cwd?: string | undefined;
2063
+ enabled?: boolean | undefined;
2064
+ invoke?: {
2065
+ tool: string;
2066
+ args?: Record<string, unknown> | undefined;
2067
+ } | undefined;
2068
+ tools?: string[] | undefined;
2069
+ }[] | undefined;
2070
+ }>;
2071
+ type McpWhen = z.infer<typeof McpWhenSchema>;
2072
+ type McpInvoke = z.infer<typeof McpInvokeSchema>;
2073
+ type McpSource = z.infer<typeof McpSourceSchema>;
2074
+ type McpConfig = z.infer<typeof McpConfigSchema>;
2075
+ interface McpMatchContext {
2076
+ stage?: string;
2077
+ workflow?: string;
2078
+ /** Free text: change title, user query, task line */
2079
+ query?: string;
2080
+ /** Explicit intent tags from CLI/agent */
2081
+ intents?: string[];
2082
+ }
2083
+ interface McpFetchResult {
2084
+ sourceId: string;
2085
+ tool: string;
2086
+ ok: boolean;
2087
+ text: string;
2088
+ error?: string;
2089
+ }
2090
+
2091
+ declare function mcpConfigPath(projectRoot: string): string;
2092
+ declare function defaultMcpConfig(): McpConfig;
2093
+ /**
2094
+ * Example sources (commented in written file via description only —
2095
+ * we write a real empty config + README-style top comment is hard in YAML;
2096
+ * document examples in docs).
2097
+ */
2098
+ declare function loadMcpConfig(projectRoot: string): Promise<McpConfig>;
2099
+ declare function saveMcpConfig(projectRoot: string, config: McpConfig): Promise<string>;
2100
+ declare function ensureMcpConfig(projectRoot: string): Promise<McpConfig>;
2101
+ declare function addMcpSource(projectRoot: string, source: McpSource): Promise<McpConfig>;
2102
+ declare function removeMcpSource(projectRoot: string, id: string): Promise<McpConfig>;
2103
+ declare function interpolate(value: string, vars: Record<string, string>): string;
2104
+ declare function interpolateArgs(args: Record<string, unknown>, vars: Record<string, string>): Record<string, unknown>;
2105
+
2106
+ /**
2107
+ * Decide which configured MCP sources apply for this stage / workflow / query.
2108
+ *
2109
+ * 1. enabled
2110
+ * 2. when.stages → stage must match (if stage known)
2111
+ * 3. when.workflows → workflow must match (if workflow known)
2112
+ * 4. when.intents + caller passed intents → require intersection
2113
+ * 5. when.keywords + query present → require a keyword substring hit
2114
+ *
2115
+ * So: stage routing always; intents/keywords refine when the caller provides signals.
2116
+ */
2117
+ declare function matchMcpSources(sources: McpSource[], ctx: McpMatchContext): McpSource[];
2118
+ /** Human explanation of match for CLI */
2119
+ declare function explainMatch(source: McpSource, ctx: McpMatchContext): string;
2120
+
2121
+ /**
2122
+ * sdd as MCP *client* — connect to external stdio MCP servers and call tools.
2123
+ */
2124
+
2125
+ interface CallMcpToolResult {
2126
+ ok: boolean;
2127
+ text: string;
2128
+ error?: string;
2129
+ }
2130
+ /**
2131
+ * One-shot: spawn source, list tools or call tool, then close.
2132
+ */
2133
+ declare function withMcpSource<T>(source: McpSource, projectRoot: string, fn: (client: Client) => Promise<T>): Promise<T>;
2134
+ declare function listMcpSourceTools(source: McpSource, projectRoot: string): Promise<{
2135
+ name: string;
2136
+ description?: string;
2137
+ }[]>;
2138
+ declare function callMcpSourceTool(source: McpSource, projectRoot: string, tool: string, args: Record<string, unknown>): Promise<CallMcpToolResult>;
2139
+
2140
+ interface GatherMcpOptions {
2141
+ projectRoot: string;
2142
+ match: McpMatchContext;
2143
+ /** Only these source ids (default: all matching) */
2144
+ sourceIds?: string[];
2145
+ /** Force tool/args instead of source.invoke */
2146
+ tool?: string;
2147
+ args?: Record<string, unknown>;
2148
+ /** Skip sources without invoke unless tool override */
2149
+ requireInvoke?: boolean;
2150
+ }
2151
+ /**
2152
+ * Call matching external MCP sources and collect text for agents / handoff.
2153
+ */
2154
+ declare function gatherMcpContext(opts: GatherMcpOptions): Promise<McpFetchResult[]>;
2155
+ declare function gatherMcpContextForChange(projectRoot: string, ctx: ChangeContext, extra?: {
2156
+ query?: string;
2157
+ intents?: string[];
2158
+ }): Promise<McpFetchResult[]>;
2159
+ declare function formatMcpContextForHandoff(results: McpFetchResult[]): string;
2160
+ declare function listMatchingSourceIds(sources: McpSource[], match: McpMatchContext): string[];
2161
+
2162
+ export { AGENT_INTEGRATIONS, AGENT_TARGET_OPTIONS, ALL_AGENT_TARGETS, type AdapterExtractResult, AdapterRegistry, type AdvanceResult, type AgentIntegration, type AgentTarget, type AgentTargetOption, type ArtifactDef, ArtifactDefSchema, type BuildRefinePlanOptions, type CallMcpToolResult, type ChangeContext, type ChangeMeta, ChangeMetaSchema, type CodeContextCaps, type CodeContextGap, type CodeContextGapCode, type CodeContextRequest, type CodeContextResult, type CodeContextSummary, type CodeSlice, type Complexity, type Config, ConfigSchema, type CreateChangeInput, DEFAULT_CODE_CONTEXT_CAPS, DEFAULT_INIT_INTEGRATION, type FocusPlan, type Gate, GateSchema, type GatherMcpOptions, type GenerateCodeContextDeps, type GreenfieldFeature, type InitOptions, type InitResult, type InstallAgentOptions, type InstallAgentResult, type InstallAgentsOptions, type InstallAgentsResult, type InstalledAgentSnapshot, type LanguageAdapter, type McpConfig, McpConfigSchema, type McpFetchResult, type McpInvoke, McpInvokeSchema, type McpMatchContext, type McpSource, McpSourceSchema, type McpWhen, McpWhenSchema, PROTOCOL_MD, type RefineArtifactRef, type RefineMode, type RefinePlan, SDD_AGENT_ROLES, SDD_DIR, type SddAgentRole, type SddAgentRoleId, type Stage, StageSchema, type StartFeatureInput, type StartGreenfieldInput, type StartGreenfieldResult, type SymbolInfo, type SymbolKind, VerifyCommandSchema, type VerifyResult, type Workflow, WorkflowSchema, activePointerPath, activeStages, addMcpSource, advanceStage, agentHostPaths, agentKickoffMessage, approveGate, archiveDir, buildAgentPrompt, buildContext, buildRefinePlan, callMcpSourceTool, canLeaveStage, changeDirName, changeMetaPath, changePath, changesDir, classifyPath, clearActiveIf, completeChange, configPath, copyDir, copyDirSkipExisting, createChange, defaultConfig, defaultMcpConfig, defaultMcpYamlPath, defaultMemoryDir, defaultTemplatesDir, defaultWorkflowsDir, defaultsRoot, domainsDir, ensureDir, ensureMcpConfig, explainMatch, fallbackAdapter, fallbackIncompleteStageId, findFeaturesBacklogPath, firstActiveStageId, formatJsonSummary, formatMcpContextForHandoff, formatStatus, gatherMcpContext, gatherMcpContextForChange, generateCodeContext, getActiveChangeId, getIntegration, getStage, incompletePriorStageErrors, inferComplexity, initProject, installAgentIntegration, installAgentIntegrations, integrationKeyFor, interpolate, interpolateArgs, isIgnoredPath, isInitialized, isSecretPath, isStageSkipped, isSubstantiveArtifactContent, listBacklogFeatures, listChanges, listDirs, listFiles, listMatchingSourceIds, listMcpSourceTools, listWorkflowNames, loadChangeMeta, loadConfig, loadInstalledAgent, loadMcpConfig, loadWorkflow, matchMcpSources, mcpConfigPath, memoryDir, mergeCaps, nextStageId, nowIso, optionForTarget, parseAgentTargets, parseFeaturesBacklog, parseIntegration, pathExists, promoteGreenfieldToMemory, readText, readYaml, recommendWorkflow, refreshActiveAgentContext, removeMcpSource, removeOtherAgentHosts, removePath, renderThinAgent, resolveChangeId, resolveFocus, resolveStages, runLocalVerify, saveChangeMeta, saveConfig, saveMcpConfig, sddRoot, setActiveChange, shouldAutoSkip, skipStage, slugify, startFeatureFromBacklog, startGreenfield, switchWorkflow, templatesDir, todayIsoDate, tokenizeKeywords, typescriptAdapter, uniqueChangeDirName, updateFeatureStatus, withMcpSource, workflowsDir, writeAgentHandoff, writeRefineBrief, writeText, writeTextIfMissing, writeYaml };
package/dist/index.js CHANGED
@@ -1,3 +1,48 @@
1
+ import {
2
+ advanceStage,
3
+ approveGate,
4
+ canLeaveStage,
5
+ completeChange,
6
+ createChange,
7
+ fallbackIncompleteStageId,
8
+ findFeaturesBacklogPath,
9
+ incompletePriorStageErrors,
10
+ isSubstantiveArtifactContent,
11
+ listBacklogFeatures,
12
+ parseFeaturesBacklog,
13
+ promoteGreenfieldToMemory,
14
+ skipStage,
15
+ startFeatureFromBacklog,
16
+ startGreenfield,
17
+ switchWorkflow,
18
+ updateFeatureStatus
19
+ } from "./chunk-24EXBX7P.js";
20
+ import {
21
+ callMcpSourceTool,
22
+ explainMatch,
23
+ formatMcpContextForHandoff,
24
+ gatherMcpContext,
25
+ gatherMcpContextForChange,
26
+ listMatchingSourceIds,
27
+ listMcpSourceTools,
28
+ matchMcpSources,
29
+ withMcpSource
30
+ } from "./chunk-VD3CPFAI.js";
31
+ import {
32
+ McpConfigSchema,
33
+ McpInvokeSchema,
34
+ McpSourceSchema,
35
+ McpWhenSchema,
36
+ addMcpSource,
37
+ defaultMcpConfig,
38
+ ensureMcpConfig,
39
+ interpolate,
40
+ interpolateArgs,
41
+ loadMcpConfig,
42
+ mcpConfigPath,
43
+ removeMcpSource,
44
+ saveMcpConfig
45
+ } from "./chunk-KYWETNFU.js";
1
46
  import {
2
47
  AGENT_INTEGRATIONS,
3
48
  AGENT_TARGET_OPTIONS,
@@ -19,36 +64,17 @@ import {
19
64
  removeOtherAgentHosts,
20
65
  renderThinAgent,
21
66
  writeAgentHandoff
22
- } from "./chunk-S7SHVKG4.js";
67
+ } from "./chunk-GR7KIAR2.js";
68
+ import {
69
+ buildAgentPrompt,
70
+ formatStatus
71
+ } from "./chunk-RRBKQ76B.js";
23
72
  import {
24
73
  defaultConfig,
25
74
  isInitialized,
26
75
  loadConfig,
27
76
  saveConfig
28
77
  } from "./chunk-OJFMJHNL.js";
29
- import {
30
- advanceStage,
31
- approveGate,
32
- canLeaveStage,
33
- completeChange,
34
- createChange,
35
- fallbackIncompleteStageId,
36
- findFeaturesBacklogPath,
37
- incompletePriorStageErrors,
38
- isSubstantiveArtifactContent,
39
- listBacklogFeatures,
40
- parseFeaturesBacklog,
41
- promoteGreenfieldToMemory,
42
- skipStage,
43
- startFeatureFromBacklog,
44
- startGreenfield,
45
- switchWorkflow,
46
- updateFeatureStatus
47
- } from "./chunk-HOH43IQ2.js";
48
- import {
49
- buildAgentPrompt,
50
- formatStatus
51
- } from "./chunk-C725DWSB.js";
52
78
  import {
53
79
  activeStages,
54
80
  buildContext,
@@ -144,6 +170,9 @@ function defaultTemplatesDir() {
144
170
  function defaultMemoryDir() {
145
171
  return join(defaultsRoot(), "memory");
146
172
  }
173
+ function defaultMcpYamlPath() {
174
+ return join(defaultsRoot(), "mcp.yaml");
175
+ }
147
176
 
148
177
  // src/init.ts
149
178
  async function initProject(opts) {
@@ -173,6 +202,12 @@ async function initProject(opts) {
173
202
  await copyDir(tSrc, tDest);
174
203
  created.push(tDest);
175
204
  }
205
+ const mcpSrc = defaultMcpYamlPath();
206
+ const mcpDest = mcpConfigPath(projectRoot);
207
+ if (await pathExists(mcpSrc)) {
208
+ const wrote = await writeTextIfMissing(mcpDest, await readText(mcpSrc));
209
+ if (wrote) created.push(mcpDest);
210
+ }
176
211
  const mDest = memoryDir(projectRoot, config);
177
212
  await ensureDir(mDest);
178
213
  const mSrc = defaultMemoryDir();
@@ -2098,6 +2133,10 @@ export {
2098
2133
  DEFAULT_CODE_CONTEXT_CAPS,
2099
2134
  DEFAULT_INIT_INTEGRATION,
2100
2135
  GateSchema,
2136
+ McpConfigSchema,
2137
+ McpInvokeSchema,
2138
+ McpSourceSchema,
2139
+ McpWhenSchema,
2101
2140
  PROTOCOL_MD,
2102
2141
  SDD_AGENT_ROLES,
2103
2142
  SDD_DIR,
@@ -2106,6 +2145,7 @@ export {
2106
2145
  WorkflowSchema,
2107
2146
  activePointerPath,
2108
2147
  activeStages,
2148
+ addMcpSource,
2109
2149
  advanceStage,
2110
2150
  agentHostPaths,
2111
2151
  agentKickoffMessage,
@@ -2114,6 +2154,7 @@ export {
2114
2154
  buildAgentPrompt,
2115
2155
  buildContext,
2116
2156
  buildRefinePlan,
2157
+ callMcpSourceTool,
2117
2158
  canLeaveStage,
2118
2159
  changeDirName,
2119
2160
  changeMetaPath,
@@ -2127,18 +2168,25 @@ export {
2127
2168
  copyDirSkipExisting,
2128
2169
  createChange,
2129
2170
  defaultConfig,
2171
+ defaultMcpConfig,
2172
+ defaultMcpYamlPath,
2130
2173
  defaultMemoryDir,
2131
2174
  defaultTemplatesDir,
2132
2175
  defaultWorkflowsDir,
2133
2176
  defaultsRoot,
2134
2177
  domainsDir,
2135
2178
  ensureDir,
2179
+ ensureMcpConfig,
2180
+ explainMatch,
2136
2181
  fallbackAdapter,
2137
2182
  fallbackIncompleteStageId,
2138
2183
  findFeaturesBacklogPath,
2139
2184
  firstActiveStageId,
2140
2185
  formatJsonSummary,
2186
+ formatMcpContextForHandoff,
2141
2187
  formatStatus,
2188
+ gatherMcpContext,
2189
+ gatherMcpContextForChange,
2142
2190
  generateCodeContext,
2143
2191
  getActiveChangeId,
2144
2192
  getIntegration,
@@ -2149,6 +2197,8 @@ export {
2149
2197
  installAgentIntegration,
2150
2198
  installAgentIntegrations,
2151
2199
  integrationKeyFor,
2200
+ interpolate,
2201
+ interpolateArgs,
2152
2202
  isIgnoredPath,
2153
2203
  isInitialized,
2154
2204
  isSecretPath,
@@ -2158,11 +2208,16 @@ export {
2158
2208
  listChanges,
2159
2209
  listDirs,
2160
2210
  listFiles,
2211
+ listMatchingSourceIds,
2212
+ listMcpSourceTools,
2161
2213
  listWorkflowNames,
2162
2214
  loadChangeMeta,
2163
2215
  loadConfig,
2164
2216
  loadInstalledAgent,
2217
+ loadMcpConfig,
2165
2218
  loadWorkflow,
2219
+ matchMcpSources,
2220
+ mcpConfigPath,
2166
2221
  memoryDir,
2167
2222
  mergeCaps,
2168
2223
  nextStageId,
@@ -2177,6 +2232,7 @@ export {
2177
2232
  readYaml,
2178
2233
  recommendWorkflow,
2179
2234
  refreshActiveAgentContext,
2235
+ removeMcpSource,
2180
2236
  removeOtherAgentHosts,
2181
2237
  removePath,
2182
2238
  renderThinAgent,
@@ -2186,6 +2242,7 @@ export {
2186
2242
  runLocalVerify,
2187
2243
  saveChangeMeta,
2188
2244
  saveConfig,
2245
+ saveMcpConfig,
2189
2246
  sddRoot,
2190
2247
  setActiveChange,
2191
2248
  shouldAutoSkip,
@@ -2200,6 +2257,7 @@ export {
2200
2257
  typescriptAdapter,
2201
2258
  uniqueChangeDirName,
2202
2259
  updateFeatureStatus,
2260
+ withMcpSource,
2203
2261
  workflowsDir,
2204
2262
  writeAgentHandoff,
2205
2263
  writeRefineBrief,
@@ -0,0 +1,24 @@
1
+ import {
2
+ addMcpSource,
3
+ defaultMcpConfig,
4
+ ensureMcpConfig,
5
+ interpolate,
6
+ interpolateArgs,
7
+ loadMcpConfig,
8
+ mcpConfigPath,
9
+ removeMcpSource,
10
+ saveMcpConfig
11
+ } from "./chunk-KYWETNFU.js";
12
+ import "./chunk-7MJYPJMR.js";
13
+ import "./chunk-EPFURATC.js";
14
+ export {
15
+ addMcpSource,
16
+ defaultMcpConfig,
17
+ ensureMcpConfig,
18
+ interpolate,
19
+ interpolateArgs,
20
+ loadMcpConfig,
21
+ mcpConfigPath,
22
+ removeMcpSource,
23
+ saveMcpConfig
24
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@structured-vibe-coding/core",
3
- "version": "0.14.3",
3
+ "version": "0.16.0",
4
4
  "description": "Core engine for sdd — local Spec-Driven Development workflows, change packs, greenfield, and agent handoff",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,6 +17,7 @@
17
17
  "README.md"
18
18
  ],
19
19
  "dependencies": {
20
+ "@modelcontextprotocol/sdk": "^1.30.0",
20
21
  "pathe": "^2.0.3",
21
22
  "typescript": "^5.8.2",
22
23
  "yaml": "^2.7.0",