contract-driven-delivery 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.1.1] - 2026-05-29
|
|
4
|
+
|
|
5
|
+
MCP tool access for graph/code-map exploration.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **`cdd-kit mcp`**: runs a stdio MCP server exposing graph and code-map tools
|
|
10
|
+
(`cdd_graph_status`, `cdd_graph_context`, `cdd_graph_query`,
|
|
11
|
+
`cdd_graph_impact`, `cdd_index_query`, `cdd_index_impact`) so AI agents can
|
|
12
|
+
use project exploration as native tools instead of shell-only commands.
|
|
13
|
+
|
|
3
14
|
## [2.1.0] - 2026-05-27
|
|
4
15
|
|
|
5
16
|
Native code graph and symptom-driven bug-fix workflow.
|
package/README.md
CHANGED
|
@@ -713,6 +713,31 @@ Use `--engine native` for the built-in graph, `--engine codemap` for the older
|
|
|
713
713
|
code-map-only fallback, `--engine codegraph` to require external CodeGraph, or
|
|
714
714
|
`CDD_CODEGRAPH_BIN=/path/to/codegraph` to point at a custom binary.
|
|
715
715
|
|
|
716
|
+
### `cdd-kit mcp`
|
|
717
|
+
|
|
718
|
+
`cdd-kit mcp` runs a stdio MCP server so agents can call the graph/index layer
|
|
719
|
+
as tools instead of shelling out manually.
|
|
720
|
+
|
|
721
|
+
```json
|
|
722
|
+
{
|
|
723
|
+
"mcpServers": {
|
|
724
|
+
"cdd-kit": {
|
|
725
|
+
"command": "cdd-kit",
|
|
726
|
+
"args": ["mcp"]
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
Exposed tools:
|
|
733
|
+
|
|
734
|
+
- `cdd_graph_status`
|
|
735
|
+
- `cdd_graph_context`
|
|
736
|
+
- `cdd_graph_query`
|
|
737
|
+
- `cdd_graph_impact`
|
|
738
|
+
- `cdd_index_query`
|
|
739
|
+
- `cdd_index_impact`
|
|
740
|
+
|
|
716
741
|
Large Python repos are scanned in chunks (`CDD_CODE_MAP_BATCH_SIZE`, default 400)
|
|
717
742
|
so one slow batch cannot drop the whole language. Raise
|
|
718
743
|
`CDD_CODE_MAP_TIMEOUT_MS` (default 30000) if a single batch still times out.
|
|
@@ -9,7 +9,16 @@ auto-refreshing `cdd-kit index ...` commands for that job.
|
|
|
9
9
|
|
|
10
10
|
## Preferred workflow: graph/query before reading
|
|
11
11
|
|
|
12
|
-
Before reading source, use the graph layer when available
|
|
12
|
+
Before reading source, use the graph layer when available. If the `cdd-kit`
|
|
13
|
+
MCP server is configured, prefer these tools:
|
|
14
|
+
|
|
15
|
+
- `cdd_graph_context`
|
|
16
|
+
- `cdd_graph_query`
|
|
17
|
+
- `cdd_graph_impact`
|
|
18
|
+
- `cdd_index_query`
|
|
19
|
+
- `cdd_index_impact`
|
|
20
|
+
|
|
21
|
+
If MCP tools are not available, use the equivalent CLI commands:
|
|
13
22
|
|
|
14
23
|
```bash
|
|
15
24
|
cdd-kit graph context "fix login redirect bug"
|
package/dist/cli/index.js
CHANGED
|
@@ -11816,6 +11816,315 @@ var init_graph = __esm({
|
|
|
11816
11816
|
}
|
|
11817
11817
|
});
|
|
11818
11818
|
|
|
11819
|
+
// src/mcp/server.ts
|
|
11820
|
+
var server_exports = {};
|
|
11821
|
+
__export(server_exports, {
|
|
11822
|
+
runMcpServer: () => runMcpServer
|
|
11823
|
+
});
|
|
11824
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
11825
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
11826
|
+
import { createInterface } from "readline";
|
|
11827
|
+
async function runMcpServer(opts) {
|
|
11828
|
+
const rl = createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
11829
|
+
for await (const line of rl) {
|
|
11830
|
+
if (!line.trim())
|
|
11831
|
+
continue;
|
|
11832
|
+
let request;
|
|
11833
|
+
try {
|
|
11834
|
+
request = JSON.parse(line);
|
|
11835
|
+
} catch (err) {
|
|
11836
|
+
writeError(null, -32700, `Parse error: ${err.message}`);
|
|
11837
|
+
continue;
|
|
11838
|
+
}
|
|
11839
|
+
if (!request.method) {
|
|
11840
|
+
if ("id" in request)
|
|
11841
|
+
writeError(request.id ?? null, -32600, "Invalid Request: missing method");
|
|
11842
|
+
continue;
|
|
11843
|
+
}
|
|
11844
|
+
try {
|
|
11845
|
+
const result = await handleRequest(request, opts);
|
|
11846
|
+
if ("id" in request)
|
|
11847
|
+
writeResult(request.id ?? null, result);
|
|
11848
|
+
} catch (err) {
|
|
11849
|
+
if ("id" in request)
|
|
11850
|
+
writeError(request.id ?? null, -32e3, err.message);
|
|
11851
|
+
}
|
|
11852
|
+
}
|
|
11853
|
+
}
|
|
11854
|
+
async function handleRequest(request, opts) {
|
|
11855
|
+
switch (request.method) {
|
|
11856
|
+
case "initialize": {
|
|
11857
|
+
const params = asObject(request.params);
|
|
11858
|
+
return {
|
|
11859
|
+
protocolVersion: typeof params.protocolVersion === "string" ? params.protocolVersion : "2024-11-05",
|
|
11860
|
+
capabilities: {
|
|
11861
|
+
tools: { listChanged: false },
|
|
11862
|
+
resources: {},
|
|
11863
|
+
prompts: {}
|
|
11864
|
+
},
|
|
11865
|
+
serverInfo: {
|
|
11866
|
+
name: "cdd-kit",
|
|
11867
|
+
version: opts.version
|
|
11868
|
+
}
|
|
11869
|
+
};
|
|
11870
|
+
}
|
|
11871
|
+
case "ping":
|
|
11872
|
+
return {};
|
|
11873
|
+
case "tools/list":
|
|
11874
|
+
return { tools };
|
|
11875
|
+
case "tools/call": {
|
|
11876
|
+
const params = asObject(request.params);
|
|
11877
|
+
const name = requireString(params, "name");
|
|
11878
|
+
const args = asObject(params.arguments);
|
|
11879
|
+
return callTool(name, args);
|
|
11880
|
+
}
|
|
11881
|
+
case "resources/list":
|
|
11882
|
+
return { resources: [] };
|
|
11883
|
+
case "prompts/list":
|
|
11884
|
+
return { prompts: [] };
|
|
11885
|
+
case "notifications/initialized":
|
|
11886
|
+
return {};
|
|
11887
|
+
default:
|
|
11888
|
+
throw new Error(`Method not found: ${request.method}`);
|
|
11889
|
+
}
|
|
11890
|
+
}
|
|
11891
|
+
function callTool(name, args) {
|
|
11892
|
+
switch (name) {
|
|
11893
|
+
case "cdd_graph_status":
|
|
11894
|
+
return runCddJson([
|
|
11895
|
+
"graph",
|
|
11896
|
+
"status",
|
|
11897
|
+
"--engine",
|
|
11898
|
+
optionalString(args.engine, "auto"),
|
|
11899
|
+
"--map",
|
|
11900
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11901
|
+
"--json"
|
|
11902
|
+
]);
|
|
11903
|
+
case "cdd_graph_query":
|
|
11904
|
+
return runCddJson([
|
|
11905
|
+
"graph",
|
|
11906
|
+
"query",
|
|
11907
|
+
requireString(args, "query"),
|
|
11908
|
+
"--engine",
|
|
11909
|
+
optionalString(args.engine, "auto"),
|
|
11910
|
+
"--map",
|
|
11911
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11912
|
+
"--limit",
|
|
11913
|
+
String(optionalInt(args.limit, 10)),
|
|
11914
|
+
"--json",
|
|
11915
|
+
...refreshArgs(args)
|
|
11916
|
+
]);
|
|
11917
|
+
case "cdd_graph_context":
|
|
11918
|
+
return runCddJson([
|
|
11919
|
+
"graph",
|
|
11920
|
+
"context",
|
|
11921
|
+
requireString(args, "task"),
|
|
11922
|
+
"--engine",
|
|
11923
|
+
optionalString(args.engine, "auto"),
|
|
11924
|
+
"--map",
|
|
11925
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11926
|
+
"--max-nodes",
|
|
11927
|
+
String(optionalInt(args.maxNodes, 20)),
|
|
11928
|
+
"--json",
|
|
11929
|
+
...refreshArgs(args)
|
|
11930
|
+
]);
|
|
11931
|
+
case "cdd_graph_impact":
|
|
11932
|
+
return runCddJson([
|
|
11933
|
+
"graph",
|
|
11934
|
+
"impact",
|
|
11935
|
+
requireString(args, "target"),
|
|
11936
|
+
"--engine",
|
|
11937
|
+
optionalString(args.engine, "auto"),
|
|
11938
|
+
"--map",
|
|
11939
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11940
|
+
"--limit",
|
|
11941
|
+
String(optionalInt(args.limit, 20)),
|
|
11942
|
+
"--depth",
|
|
11943
|
+
String(optionalInt(args.depth, 2)),
|
|
11944
|
+
"--json",
|
|
11945
|
+
...refreshArgs(args)
|
|
11946
|
+
]);
|
|
11947
|
+
case "cdd_index_query":
|
|
11948
|
+
return runCddJson([
|
|
11949
|
+
"index",
|
|
11950
|
+
"query",
|
|
11951
|
+
requireString(args, "query"),
|
|
11952
|
+
"--map",
|
|
11953
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11954
|
+
"--limit",
|
|
11955
|
+
String(optionalInt(args.limit, 10)),
|
|
11956
|
+
"--json",
|
|
11957
|
+
...refreshArgs(args)
|
|
11958
|
+
]);
|
|
11959
|
+
case "cdd_index_impact":
|
|
11960
|
+
return runCddJson([
|
|
11961
|
+
"index",
|
|
11962
|
+
"impact",
|
|
11963
|
+
requireString(args, "target"),
|
|
11964
|
+
"--map",
|
|
11965
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11966
|
+
"--limit",
|
|
11967
|
+
String(optionalInt(args.limit, 20)),
|
|
11968
|
+
"--json",
|
|
11969
|
+
...refreshArgs(args)
|
|
11970
|
+
]);
|
|
11971
|
+
default:
|
|
11972
|
+
return {
|
|
11973
|
+
isError: true,
|
|
11974
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }]
|
|
11975
|
+
};
|
|
11976
|
+
}
|
|
11977
|
+
}
|
|
11978
|
+
function runCddJson(args) {
|
|
11979
|
+
const cliPath = process.argv[1] || fileURLToPath3(import.meta.url);
|
|
11980
|
+
const result = spawnSync4(process.execPath, [cliPath, ...args], {
|
|
11981
|
+
cwd: process.cwd(),
|
|
11982
|
+
env: process.env,
|
|
11983
|
+
encoding: "utf8"
|
|
11984
|
+
});
|
|
11985
|
+
const stdout = result.stdout?.trim() ?? "";
|
|
11986
|
+
const stderr = result.stderr?.trim() ?? "";
|
|
11987
|
+
const isError = !!result.error || (result.status ?? 1) !== 0;
|
|
11988
|
+
if (stdout) {
|
|
11989
|
+
return {
|
|
11990
|
+
isError: isError || void 0,
|
|
11991
|
+
content: [{ type: "text", text: stdout }]
|
|
11992
|
+
};
|
|
11993
|
+
}
|
|
11994
|
+
return {
|
|
11995
|
+
isError: true,
|
|
11996
|
+
content: [{ type: "text", text: result.error?.message || stderr || `cdd-kit exited with status ${result.status}` }]
|
|
11997
|
+
};
|
|
11998
|
+
}
|
|
11999
|
+
function refreshArgs(args) {
|
|
12000
|
+
return args.refresh === false ? ["--no-refresh"] : [];
|
|
12001
|
+
}
|
|
12002
|
+
function asObject(value) {
|
|
12003
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
12004
|
+
}
|
|
12005
|
+
function requireString(args, key) {
|
|
12006
|
+
const value = args[key];
|
|
12007
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
12008
|
+
throw new Error(`Missing required string argument: ${key}`);
|
|
12009
|
+
}
|
|
12010
|
+
return value;
|
|
12011
|
+
}
|
|
12012
|
+
function optionalString(value, fallback) {
|
|
12013
|
+
return typeof value === "string" && value.trim() ? value : fallback;
|
|
12014
|
+
}
|
|
12015
|
+
function optionalInt(value, fallback) {
|
|
12016
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number.parseInt(value, 10) : fallback;
|
|
12017
|
+
return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : fallback;
|
|
12018
|
+
}
|
|
12019
|
+
function writeResult(id, result) {
|
|
12020
|
+
process.stdout.write(`${JSON.stringify({ jsonrpc: "2.0", id, result })}
|
|
12021
|
+
`);
|
|
12022
|
+
}
|
|
12023
|
+
function writeError(id, code, message) {
|
|
12024
|
+
process.stdout.write(`${JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } })}
|
|
12025
|
+
`);
|
|
12026
|
+
}
|
|
12027
|
+
var DEFAULT_MAP, tools;
|
|
12028
|
+
var init_server = __esm({
|
|
12029
|
+
"src/mcp/server.ts"() {
|
|
12030
|
+
"use strict";
|
|
12031
|
+
DEFAULT_MAP = ".cdd/code-map.yml";
|
|
12032
|
+
tools = [
|
|
12033
|
+
{
|
|
12034
|
+
name: "cdd_graph_status",
|
|
12035
|
+
description: "Show the active cdd-kit graph engine and code-map/code-graph freshness for the current workspace.",
|
|
12036
|
+
inputSchema: {
|
|
12037
|
+
type: "object",
|
|
12038
|
+
properties: {
|
|
12039
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12040
|
+
engine: { type: "string", enum: ["auto", "native", "codegraph", "codemap"], default: "auto" }
|
|
12041
|
+
},
|
|
12042
|
+
additionalProperties: false
|
|
12043
|
+
}
|
|
12044
|
+
},
|
|
12045
|
+
{
|
|
12046
|
+
name: "cdd_graph_query",
|
|
12047
|
+
description: "Search native graph symbols/files and return candidate nodes with line ranges.",
|
|
12048
|
+
inputSchema: {
|
|
12049
|
+
type: "object",
|
|
12050
|
+
properties: {
|
|
12051
|
+
query: { type: "string", description: "Symbol, file path, file stem, class, function, component, or route term." },
|
|
12052
|
+
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
|
|
12053
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12054
|
+
engine: { type: "string", enum: ["auto", "native", "codegraph", "codemap"], default: "auto" },
|
|
12055
|
+
refresh: { type: "boolean", default: true }
|
|
12056
|
+
},
|
|
12057
|
+
required: ["query"],
|
|
12058
|
+
additionalProperties: false
|
|
12059
|
+
}
|
|
12060
|
+
},
|
|
12061
|
+
{
|
|
12062
|
+
name: "cdd_graph_context",
|
|
12063
|
+
description: "Build graph-first task context from a task, symptom, or known feature term.",
|
|
12064
|
+
inputSchema: {
|
|
12065
|
+
type: "object",
|
|
12066
|
+
properties: {
|
|
12067
|
+
task: { type: "string", description: "Task, bug symptom, feature name, screen name, or domain term." },
|
|
12068
|
+
maxNodes: { type: "integer", minimum: 1, maximum: 100, default: 20 },
|
|
12069
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12070
|
+
engine: { type: "string", enum: ["auto", "native", "codegraph", "codemap"], default: "auto" },
|
|
12071
|
+
refresh: { type: "boolean", default: true }
|
|
12072
|
+
},
|
|
12073
|
+
required: ["task"],
|
|
12074
|
+
additionalProperties: false
|
|
12075
|
+
}
|
|
12076
|
+
},
|
|
12077
|
+
{
|
|
12078
|
+
name: "cdd_graph_impact",
|
|
12079
|
+
description: "Analyze callers, callees, imports, references, and dependents for a file or symbol before editing.",
|
|
12080
|
+
inputSchema: {
|
|
12081
|
+
type: "object",
|
|
12082
|
+
properties: {
|
|
12083
|
+
target: { type: "string", description: "Candidate file path, symbol, graph node id, or qualified name." },
|
|
12084
|
+
depth: { type: "integer", minimum: 1, maximum: 10, default: 2 },
|
|
12085
|
+
limit: { type: "integer", minimum: 1, maximum: 200, default: 20 },
|
|
12086
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12087
|
+
engine: { type: "string", enum: ["auto", "native", "codegraph", "codemap"], default: "auto" },
|
|
12088
|
+
refresh: { type: "boolean", default: true }
|
|
12089
|
+
},
|
|
12090
|
+
required: ["target"],
|
|
12091
|
+
additionalProperties: false
|
|
12092
|
+
}
|
|
12093
|
+
},
|
|
12094
|
+
{
|
|
12095
|
+
name: "cdd_index_query",
|
|
12096
|
+
description: "Fallback code-map query for files, symbols, imports, and line ranges.",
|
|
12097
|
+
inputSchema: {
|
|
12098
|
+
type: "object",
|
|
12099
|
+
properties: {
|
|
12100
|
+
query: { type: "string", description: "Symbol, file path, import module, enum member, or substring." },
|
|
12101
|
+
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
|
|
12102
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12103
|
+
refresh: { type: "boolean", default: true }
|
|
12104
|
+
},
|
|
12105
|
+
required: ["query"],
|
|
12106
|
+
additionalProperties: false
|
|
12107
|
+
}
|
|
12108
|
+
},
|
|
12109
|
+
{
|
|
12110
|
+
name: "cdd_index_impact",
|
|
12111
|
+
description: "Fallback code-map impact query for local imports and direct dependents.",
|
|
12112
|
+
inputSchema: {
|
|
12113
|
+
type: "object",
|
|
12114
|
+
properties: {
|
|
12115
|
+
target: { type: "string", description: "File path or unique symbol." },
|
|
12116
|
+
limit: { type: "integer", minimum: 1, maximum: 200, default: 20 },
|
|
12117
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12118
|
+
refresh: { type: "boolean", default: true }
|
|
12119
|
+
},
|
|
12120
|
+
required: ["target"],
|
|
12121
|
+
additionalProperties: false
|
|
12122
|
+
}
|
|
12123
|
+
}
|
|
12124
|
+
];
|
|
12125
|
+
}
|
|
12126
|
+
});
|
|
12127
|
+
|
|
11819
12128
|
// src/commands/archive.ts
|
|
11820
12129
|
var archive_exports = {};
|
|
11821
12130
|
__export(archive_exports, {
|
|
@@ -12358,7 +12667,7 @@ var init_context = __esm({
|
|
|
12358
12667
|
// src/cli/index.ts
|
|
12359
12668
|
import { readFileSync as readFileSync31 } from "fs";
|
|
12360
12669
|
import os from "os";
|
|
12361
|
-
import { fileURLToPath as
|
|
12670
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
12362
12671
|
import { dirname as dirname7, join as join30 } from "path";
|
|
12363
12672
|
import { Command } from "commander";
|
|
12364
12673
|
|
|
@@ -13464,7 +13773,7 @@ async function installHooks() {
|
|
|
13464
13773
|
}
|
|
13465
13774
|
|
|
13466
13775
|
// src/cli/index.ts
|
|
13467
|
-
var __dirname2 = dirname7(
|
|
13776
|
+
var __dirname2 = dirname7(fileURLToPath4(import.meta.url));
|
|
13468
13777
|
var pkg = JSON.parse(readFileSync31(join30(__dirname2, "..", "..", "package.json"), "utf8"));
|
|
13469
13778
|
var program = new Command();
|
|
13470
13779
|
program.name("cdd-kit").description("Contract-Driven Delivery Kit CLI").version(pkg.version);
|
|
@@ -13622,6 +13931,10 @@ graph.command("context <task>").description("Build task context with native grap
|
|
|
13622
13931
|
});
|
|
13623
13932
|
process.exit(exit);
|
|
13624
13933
|
});
|
|
13934
|
+
program.command("mcp").description("Run the cdd-kit MCP stdio server exposing graph and code-map tools").action(async () => {
|
|
13935
|
+
const { runMcpServer: runMcpServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
13936
|
+
await runMcpServer2({ version: pkg.version });
|
|
13937
|
+
});
|
|
13625
13938
|
program.command("gate <change-id>").description("Run delivery-quality gate for a change (required artifacts, tasks, tier, contracts)").option("--strict", "Treat pending tasks (except section 7) as errors", false).action(async (id, opts) => {
|
|
13626
13939
|
await gate(id, { strict: opts.strict });
|
|
13627
13940
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contract-driven-delivery",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Contract-driven delivery kit for AI coding agents with deterministic context indexes, manifest-backed read-scope governance, and orchestrated contracts-first delivery.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"contract-driven",
|