@loose-ends/mcp 0.0.0-stage → 1.1.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/README.md CHANGED
@@ -1,3 +1,17 @@
1
- # Temporary Holding Version
1
+ # @loose-ends/mcp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ MCP server for [Loose Ends](https://github.com/sid732/loose-ends). It lets coding agents check whether the code they wrote is reachable before they finish.
4
+
5
+ ```json
6
+ { "mcpServers": { "loose-ends": { "command": "npx", "args": ["-y", "@loose-ends/mcp"] } } }
7
+ ```
8
+
9
+ Pass `--root <dir>` or set `LOOSE_ENDS_ROOT` to analyze a directory other than the working directory.
10
+
11
+ | Tool | Purpose |
12
+ |---|---|
13
+ | `check_changes` | Compare the working tree or a head ref with its base and report new loose ends. |
14
+ | `scan_project` | Report all unreachable code in the project. |
15
+ | `explain` | Explain why a file, symbol, or dependency is or is not reachable. |
16
+ | `list_roots` | List discovered entry points. |
17
+ | `plan_cleanup` | Return a removal patch, optionally verified against the project's checks. It never writes files. |
package/dist/bin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
package/dist/bin.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "./index.js";
4
+ const rootFlag = process.argv.indexOf("--root");
5
+ const root = rootFlag !== -1 ? process.argv[rootFlag + 1] : undefined;
6
+ const server = createServer({ root });
7
+ await server.connect(new StdioServerTransport());
8
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAChD,MAAM,IAAI,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAEtE,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACtC,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export interface ServerOptions {
3
+ /** Default project root when a tool call does not pass one. */
4
+ root?: string;
5
+ }
6
+ export declare function createServer(options?: ServerOptions): McpServer;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAoCD,wBAAgB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,SAAS,CAuInE"}
package/dist/index.js ADDED
@@ -0,0 +1,143 @@
1
+ import { resolve } from "node:path";
2
+ import { VERSION, analyze, check, cleanupPatch, explain, formatExplanation, formatText, label, loadConfig, planCleanup, scan, toJsonReport, verifyCleanup, } from "@loose-ends/core";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { z } from "zod";
5
+ const rootArg = z.string().optional().describe("Project root. Defaults to the server's working directory.");
6
+ /** Compact view of a result for agents: findings with the evidence needed to act on them. */
7
+ function compact(result) {
8
+ const report = toJsonReport(result);
9
+ return {
10
+ passed: report.passed,
11
+ mode: report.mode,
12
+ base: report.base,
13
+ head: report.head,
14
+ blocking: result.failing.length,
15
+ findings: report.findings.map((f) => ({
16
+ kind: f.kind,
17
+ severity: f.severity,
18
+ blocking: f.failing,
19
+ target: f.target,
20
+ location: f.file ? `${f.file}${f.line ? `:${f.line}` : ""}` : undefined,
21
+ message: f.message,
22
+ evidence: f.evidence,
23
+ suppressed: f.suppressed,
24
+ })),
25
+ };
26
+ }
27
+ function ok(...texts) {
28
+ return { content: texts.map((text) => ({ type: "text", text })) };
29
+ }
30
+ function fail(error) {
31
+ return { content: [{ type: "text", text: `loose-ends error: ${error instanceof Error ? error.message : String(error)}` }], isError: true };
32
+ }
33
+ export function createServer(options = {}) {
34
+ const defaultRoot = resolve(options.root ?? process.env.LOOSE_ENDS_ROOT ?? process.cwd());
35
+ const rootOf = (root) => (root ? resolve(defaultRoot, root) : defaultRoot);
36
+ const server = new McpServer({ name: "loose-ends", version: VERSION }, {
37
+ instructions: "Loose Ends checks whether code you added or changed is reachable from a real entry point. " +
38
+ "Run check_changes before you finish a task. Blocking findings mean you left orphaned, superseded, or unconnected code: " +
39
+ "wire it in, delete it, or ask the user whether it should be marked dormant. Never mark code dormant or suppress a finding on your own. " +
40
+ "Use explain to see why something is or is not reachable.",
41
+ });
42
+ server.registerTool("check_changes", {
43
+ title: "Check changes for loose ends",
44
+ description: "Compare the working tree (or a head ref) with its base branch. Reports added code nothing reaches, code the change orphaned, replaced implementations that were not removed, and unused dependencies.",
45
+ inputSchema: {
46
+ root: rootArg,
47
+ base: z.string().optional().describe("Base revision. Defaults to the merge base with origin/HEAD, main, or master."),
48
+ head: z.string().optional().describe("Head revision. Defaults to the working tree, including uncommitted changes."),
49
+ },
50
+ annotations: { readOnlyHint: true, idempotentHint: true },
51
+ }, async ({ root, base, head }) => {
52
+ try {
53
+ const result = check({ root: rootOf(root), base, head });
54
+ return ok(formatText(result), JSON.stringify(compact(result), null, 2));
55
+ }
56
+ catch (error) {
57
+ return fail(error);
58
+ }
59
+ });
60
+ server.registerTool("scan_project", {
61
+ title: "Scan project for unreachable code",
62
+ description: "Report every unreachable file, symbol, and dependency in the project, independent of any change. Use it to understand existing debt, not to judge a change.",
63
+ inputSchema: { root: rootArg, limit: z.number().int().positive().max(500).optional().describe("Maximum findings to return (default 100).") },
64
+ annotations: { readOnlyHint: true, idempotentHint: true },
65
+ }, async ({ root, limit }) => {
66
+ try {
67
+ const result = scan({ root: rootOf(root) });
68
+ const view = compact(result);
69
+ const max = limit ?? 100;
70
+ const truncated = view.findings.length > max;
71
+ view.findings = view.findings.slice(0, max);
72
+ return ok(JSON.stringify({ ...view, truncated, total: result.findings.length }, null, 2));
73
+ }
74
+ catch (error) {
75
+ return fail(error);
76
+ }
77
+ });
78
+ server.registerTool("explain", {
79
+ title: "Explain liveness",
80
+ description: "Explain why a file, symbol (path#name), or dependency is live, test-only, uncertain, dormant, or orphaned, including the path from its root and what references it.",
81
+ inputSchema: { target: z.string().describe("A path like src/a.ts or app/views.py, a symbol like src/a.ts#run, or a package name."), root: rootArg },
82
+ annotations: { readOnlyHint: true, idempotentHint: true },
83
+ }, async ({ target, root }) => {
84
+ try {
85
+ const analysis = analyze(loadConfig(rootOf(root)));
86
+ const e = explain(analysis, target);
87
+ if (!e)
88
+ return fail(new Error(`"${target}" is not a known file, symbol, or dependency`));
89
+ return ok(formatExplanation(e), JSON.stringify(e, null, 2));
90
+ }
91
+ catch (error) {
92
+ return fail(error);
93
+ }
94
+ });
95
+ server.registerTool("list_roots", {
96
+ title: "List entry points",
97
+ description: "List the entry points (package exports, bins, scripts, framework routes, config entries, tests) that liveness is measured from.",
98
+ inputSchema: { root: rootArg, kind: z.enum(["production", "tooling", "test"]).optional() },
99
+ annotations: { readOnlyHint: true, idempotentHint: true },
100
+ }, async ({ root, kind }) => {
101
+ try {
102
+ const analysis = analyze(loadConfig(rootOf(root)));
103
+ const roots = analysis.roots
104
+ .filter((r) => r.node.startsWith("file:") && (!kind || r.kind === kind))
105
+ .map((r) => ({ target: label(analysis.graph.nodes.get(r.node), r.node), kind: r.kind, source: r.source, reason: r.reason }));
106
+ return ok(JSON.stringify(roots, null, 2));
107
+ }
108
+ catch (error) {
109
+ return fail(error);
110
+ }
111
+ });
112
+ server.registerTool("plan_cleanup", {
113
+ title: "Plan cleanup",
114
+ description: "Build a removal plan for blocking loose ends and return it as a unified diff. With verify=true the plan is applied in a scratch copy and the project's configured checks run there. Never modifies the working tree: apply the patch yourself after reviewing it.",
115
+ inputSchema: {
116
+ root: rootArg,
117
+ base: z.string().optional(),
118
+ scope: z.enum(["change", "project"]).optional().describe("change (default) cleans up this change; project cleans up everything."),
119
+ verify: z.boolean().optional().describe("Run the configured checks against the cleaned-up copy."),
120
+ },
121
+ annotations: { readOnlyHint: true },
122
+ }, async ({ root, base, scope, verify }) => {
123
+ try {
124
+ const dir = rootOf(root);
125
+ const result = scope === "project" ? scan({ root: dir, keepAnalyses: true }) : check({ root: dir, base, keepAnalyses: true });
126
+ const plan = planCleanup(result.analyses.head, result.findings);
127
+ if (plan.actions.length === 0)
128
+ return ok(JSON.stringify({ actions: [], skipped: plan.skipped }, null, 2));
129
+ if (verify) {
130
+ const v = verifyCleanup(dir, plan, result.config.checks);
131
+ const summary = { actions: plan.actions, skipped: plan.skipped, verified: v.passed, checks: v.checks, configuredChecks: result.config.checks.length };
132
+ return ok(JSON.stringify(summary, null, 2), v.patch);
133
+ }
134
+ const { patch } = cleanupPatch(dir, plan);
135
+ return ok(JSON.stringify({ actions: plan.actions, skipped: plan.skipped, verified: false }, null, 2), patch);
136
+ }
137
+ catch (error) {
138
+ return fail(error);
139
+ }
140
+ });
141
+ return server;
142
+ }
143
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,41 @@
1
1
  {
2
2
  "name": "@loose-ends/mcp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.1.0",
4
+ "description": "MCP server that lets coding agents check their changes for loose ends.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "loose-ends-mcp": "dist/bin.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc -b"
24
+ },
25
+ "dependencies": {
26
+ "@loose-ends/core": "1.1.0",
27
+ "@modelcontextprotocol/sdk": "^1.32.0",
28
+ "zod": "^4.0.0"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/sid732/loose-ends.git",
33
+ "directory": "packages/mcp"
34
+ },
35
+ "engines": {
36
+ "node": ">=20"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ }
41
+ }