ios-agent-mcp 2.0.1 → 2.2.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 +74 -7
- package/data/knowledge.json +1 -0
- package/dist/analyzers/memory.d.ts +12 -0
- package/dist/analyzers/memory.js +81 -0
- package/dist/analyzers/memory.js.map +1 -0
- package/dist/analyzers/performance.d.ts +10 -0
- package/dist/analyzers/performance.js +106 -0
- package/dist/analyzers/performance.js.map +1 -0
- package/dist/analyzers/security.d.ts +2 -0
- package/dist/analyzers/security.js +82 -0
- package/dist/analyzers/security.js.map +1 -0
- package/dist/analyzers/skill.d.ts +34 -0
- package/dist/analyzers/skill.js +483 -0
- package/dist/analyzers/skill.js.map +1 -0
- package/dist/analyzers/testing.d.ts +16 -0
- package/dist/analyzers/testing.js +135 -0
- package/dist/analyzers/testing.js.map +1 -0
- package/dist/analyzers/types.d.ts +19 -1
- package/dist/analyzers/types.js +65 -3
- package/dist/analyzers/types.js.map +1 -1
- package/dist/index.js +162 -5
- package/dist/index.js.map +1 -1
- package/dist/knowledge-server.d.ts +2 -0
- package/dist/knowledge-server.js +44 -0
- package/dist/knowledge-server.js.map +1 -0
- package/dist/knowledge.d.ts +78 -0
- package/dist/knowledge.js +69 -0
- package/dist/knowledge.js.map +1 -0
- package/dist/report.d.ts +10 -0
- package/dist/report.js +40 -0
- package/dist/report.js.map +1 -1
- package/dist/resources.d.ts +67 -0
- package/dist/resources.js +222 -0
- package/dist/resources.js.map +1 -0
- package/dist/result.d.ts +203 -0
- package/dist/result.js +135 -0
- package/dist/result.js.map +1 -0
- package/dist/scan.d.ts +9 -0
- package/dist/scan.js +110 -0
- package/dist/scan.js.map +1 -1
- package/dist/version.d.ts +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/mcp.json +76 -11
- package/package.json +19 -10
package/dist/result.d.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Finding } from "./analyzers/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* A 0–100 defect-density score.
|
|
5
|
+
*
|
|
6
|
+
* penalty = 10·blockers + 3·serious + 1·minor
|
|
7
|
+
* capacity = filesChecked × 10
|
|
8
|
+
* score = clamp(0, 100, round(100 × (1 − penalty / capacity)))
|
|
9
|
+
*
|
|
10
|
+
* 100 means no findings. The denominator is file count, so the score is a
|
|
11
|
+
* *density*: adding clean files raises it, which is the intended behaviour for
|
|
12
|
+
* tracking one project over time.
|
|
13
|
+
*
|
|
14
|
+
* It is deliberately NOT comparable between projects — a UI-heavy target and a
|
|
15
|
+
* networking library have different rule surfaces. Use it as a direction of
|
|
16
|
+
* travel, and use the counts for anything that matters.
|
|
17
|
+
*/
|
|
18
|
+
export declare function scoreFor(findings: Finding[], filesChecked: number): number;
|
|
19
|
+
export declare const issueSchema: z.ZodObject<{
|
|
20
|
+
file: z.ZodString;
|
|
21
|
+
line: z.ZodNumber;
|
|
22
|
+
severity: z.ZodEnum<["blocker", "serious", "minor"]>;
|
|
23
|
+
rule: z.ZodString;
|
|
24
|
+
message: z.ZodString;
|
|
25
|
+
consequence: z.ZodString;
|
|
26
|
+
fix: z.ZodString;
|
|
27
|
+
doc: z.ZodString;
|
|
28
|
+
excerpt: z.ZodString;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
severity: "blocker" | "serious" | "minor";
|
|
31
|
+
file: string;
|
|
32
|
+
line: number;
|
|
33
|
+
message: string;
|
|
34
|
+
rule: string;
|
|
35
|
+
consequence: string;
|
|
36
|
+
fix: string;
|
|
37
|
+
doc: string;
|
|
38
|
+
excerpt: string;
|
|
39
|
+
}, {
|
|
40
|
+
severity: "blocker" | "serious" | "minor";
|
|
41
|
+
file: string;
|
|
42
|
+
line: number;
|
|
43
|
+
message: string;
|
|
44
|
+
rule: string;
|
|
45
|
+
consequence: string;
|
|
46
|
+
fix: string;
|
|
47
|
+
doc: string;
|
|
48
|
+
excerpt: string;
|
|
49
|
+
}>;
|
|
50
|
+
/** The shape every review tool declares as its `outputSchema`. */
|
|
51
|
+
export declare const reviewOutputShape: {
|
|
52
|
+
summary: z.ZodString;
|
|
53
|
+
score: z.ZodNumber;
|
|
54
|
+
counts: z.ZodObject<{
|
|
55
|
+
blocker: z.ZodNumber;
|
|
56
|
+
serious: z.ZodNumber;
|
|
57
|
+
minor: z.ZodNumber;
|
|
58
|
+
total: z.ZodNumber;
|
|
59
|
+
}, "strip", z.ZodTypeAny, {
|
|
60
|
+
blocker: number;
|
|
61
|
+
serious: number;
|
|
62
|
+
minor: number;
|
|
63
|
+
total: number;
|
|
64
|
+
}, {
|
|
65
|
+
blocker: number;
|
|
66
|
+
serious: number;
|
|
67
|
+
minor: number;
|
|
68
|
+
total: number;
|
|
69
|
+
}>;
|
|
70
|
+
files_checked: z.ZodNumber;
|
|
71
|
+
issues: z.ZodArray<z.ZodObject<{
|
|
72
|
+
file: z.ZodString;
|
|
73
|
+
line: z.ZodNumber;
|
|
74
|
+
severity: z.ZodEnum<["blocker", "serious", "minor"]>;
|
|
75
|
+
rule: z.ZodString;
|
|
76
|
+
message: z.ZodString;
|
|
77
|
+
consequence: z.ZodString;
|
|
78
|
+
fix: z.ZodString;
|
|
79
|
+
doc: z.ZodString;
|
|
80
|
+
excerpt: z.ZodString;
|
|
81
|
+
}, "strip", z.ZodTypeAny, {
|
|
82
|
+
severity: "blocker" | "serious" | "minor";
|
|
83
|
+
file: string;
|
|
84
|
+
line: number;
|
|
85
|
+
message: string;
|
|
86
|
+
rule: string;
|
|
87
|
+
consequence: string;
|
|
88
|
+
fix: string;
|
|
89
|
+
doc: string;
|
|
90
|
+
excerpt: string;
|
|
91
|
+
}, {
|
|
92
|
+
severity: "blocker" | "serious" | "minor";
|
|
93
|
+
file: string;
|
|
94
|
+
line: number;
|
|
95
|
+
message: string;
|
|
96
|
+
rule: string;
|
|
97
|
+
consequence: string;
|
|
98
|
+
fix: string;
|
|
99
|
+
doc: string;
|
|
100
|
+
excerpt: string;
|
|
101
|
+
}>, "many">;
|
|
102
|
+
suggestions: z.ZodArray<z.ZodString, "many">;
|
|
103
|
+
};
|
|
104
|
+
export declare const reviewOutputSchema: z.ZodObject<{
|
|
105
|
+
summary: z.ZodString;
|
|
106
|
+
score: z.ZodNumber;
|
|
107
|
+
counts: z.ZodObject<{
|
|
108
|
+
blocker: z.ZodNumber;
|
|
109
|
+
serious: z.ZodNumber;
|
|
110
|
+
minor: z.ZodNumber;
|
|
111
|
+
total: z.ZodNumber;
|
|
112
|
+
}, "strip", z.ZodTypeAny, {
|
|
113
|
+
blocker: number;
|
|
114
|
+
serious: number;
|
|
115
|
+
minor: number;
|
|
116
|
+
total: number;
|
|
117
|
+
}, {
|
|
118
|
+
blocker: number;
|
|
119
|
+
serious: number;
|
|
120
|
+
minor: number;
|
|
121
|
+
total: number;
|
|
122
|
+
}>;
|
|
123
|
+
files_checked: z.ZodNumber;
|
|
124
|
+
issues: z.ZodArray<z.ZodObject<{
|
|
125
|
+
file: z.ZodString;
|
|
126
|
+
line: z.ZodNumber;
|
|
127
|
+
severity: z.ZodEnum<["blocker", "serious", "minor"]>;
|
|
128
|
+
rule: z.ZodString;
|
|
129
|
+
message: z.ZodString;
|
|
130
|
+
consequence: z.ZodString;
|
|
131
|
+
fix: z.ZodString;
|
|
132
|
+
doc: z.ZodString;
|
|
133
|
+
excerpt: z.ZodString;
|
|
134
|
+
}, "strip", z.ZodTypeAny, {
|
|
135
|
+
severity: "blocker" | "serious" | "minor";
|
|
136
|
+
file: string;
|
|
137
|
+
line: number;
|
|
138
|
+
message: string;
|
|
139
|
+
rule: string;
|
|
140
|
+
consequence: string;
|
|
141
|
+
fix: string;
|
|
142
|
+
doc: string;
|
|
143
|
+
excerpt: string;
|
|
144
|
+
}, {
|
|
145
|
+
severity: "blocker" | "serious" | "minor";
|
|
146
|
+
file: string;
|
|
147
|
+
line: number;
|
|
148
|
+
message: string;
|
|
149
|
+
rule: string;
|
|
150
|
+
consequence: string;
|
|
151
|
+
fix: string;
|
|
152
|
+
doc: string;
|
|
153
|
+
excerpt: string;
|
|
154
|
+
}>, "many">;
|
|
155
|
+
suggestions: z.ZodArray<z.ZodString, "many">;
|
|
156
|
+
}, "strip", z.ZodTypeAny, {
|
|
157
|
+
issues: {
|
|
158
|
+
severity: "blocker" | "serious" | "minor";
|
|
159
|
+
file: string;
|
|
160
|
+
line: number;
|
|
161
|
+
message: string;
|
|
162
|
+
rule: string;
|
|
163
|
+
consequence: string;
|
|
164
|
+
fix: string;
|
|
165
|
+
doc: string;
|
|
166
|
+
excerpt: string;
|
|
167
|
+
}[];
|
|
168
|
+
summary: string;
|
|
169
|
+
score: number;
|
|
170
|
+
counts: {
|
|
171
|
+
blocker: number;
|
|
172
|
+
serious: number;
|
|
173
|
+
minor: number;
|
|
174
|
+
total: number;
|
|
175
|
+
};
|
|
176
|
+
files_checked: number;
|
|
177
|
+
suggestions: string[];
|
|
178
|
+
}, {
|
|
179
|
+
issues: {
|
|
180
|
+
severity: "blocker" | "serious" | "minor";
|
|
181
|
+
file: string;
|
|
182
|
+
line: number;
|
|
183
|
+
message: string;
|
|
184
|
+
rule: string;
|
|
185
|
+
consequence: string;
|
|
186
|
+
fix: string;
|
|
187
|
+
doc: string;
|
|
188
|
+
excerpt: string;
|
|
189
|
+
}[];
|
|
190
|
+
summary: string;
|
|
191
|
+
score: number;
|
|
192
|
+
counts: {
|
|
193
|
+
blocker: number;
|
|
194
|
+
serious: number;
|
|
195
|
+
minor: number;
|
|
196
|
+
total: number;
|
|
197
|
+
};
|
|
198
|
+
files_checked: number;
|
|
199
|
+
suggestions: string[];
|
|
200
|
+
}>;
|
|
201
|
+
export type ReviewOutput = z.infer<typeof reviewOutputSchema>;
|
|
202
|
+
/** Build the structured half of a tool result. */
|
|
203
|
+
export declare function buildReviewOutput(title: string, findings: Finding[], filesChecked: number): ReviewOutput;
|
package/dist/result.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { sortFindings } from "./analyzers/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Structured tool output.
|
|
5
|
+
*
|
|
6
|
+
* Every review tool returns BOTH a markdown `content` block and this object as
|
|
7
|
+
* `structuredContent`. The markdown is for a human reading the transcript; the
|
|
8
|
+
* object is for a workflow that needs to branch on the result without parsing
|
|
9
|
+
* prose. Returning only JSON would make the transcript unreadable; returning
|
|
10
|
+
* only prose forces every consumer to regex it.
|
|
11
|
+
*
|
|
12
|
+
* Field names are snake_case because this is a wire contract, not internal API.
|
|
13
|
+
*/
|
|
14
|
+
/** Weights behind `score`. Stated here because a score nobody can reproduce is a vibe. */
|
|
15
|
+
const SEVERITY_WEIGHT = {
|
|
16
|
+
blocker: 10,
|
|
17
|
+
serious: 3,
|
|
18
|
+
minor: 1,
|
|
19
|
+
};
|
|
20
|
+
/** One blocker per file scanned is the notional floor. */
|
|
21
|
+
const CAPACITY_PER_FILE = 10;
|
|
22
|
+
/**
|
|
23
|
+
* A 0–100 defect-density score.
|
|
24
|
+
*
|
|
25
|
+
* penalty = 10·blockers + 3·serious + 1·minor
|
|
26
|
+
* capacity = filesChecked × 10
|
|
27
|
+
* score = clamp(0, 100, round(100 × (1 − penalty / capacity)))
|
|
28
|
+
*
|
|
29
|
+
* 100 means no findings. The denominator is file count, so the score is a
|
|
30
|
+
* *density*: adding clean files raises it, which is the intended behaviour for
|
|
31
|
+
* tracking one project over time.
|
|
32
|
+
*
|
|
33
|
+
* It is deliberately NOT comparable between projects — a UI-heavy target and a
|
|
34
|
+
* networking library have different rule surfaces. Use it as a direction of
|
|
35
|
+
* travel, and use the counts for anything that matters.
|
|
36
|
+
*/
|
|
37
|
+
export function scoreFor(findings, filesChecked) {
|
|
38
|
+
if (filesChecked <= 0)
|
|
39
|
+
return 100;
|
|
40
|
+
const penalty = findings.reduce((total, finding) => total + SEVERITY_WEIGHT[finding.severity], 0);
|
|
41
|
+
const capacity = filesChecked * CAPACITY_PER_FILE;
|
|
42
|
+
const score = Math.round(100 * (1 - penalty / capacity));
|
|
43
|
+
return Math.max(0, Math.min(100, score));
|
|
44
|
+
}
|
|
45
|
+
export const issueSchema = z.object({
|
|
46
|
+
file: z.string(),
|
|
47
|
+
line: z.number().int(),
|
|
48
|
+
severity: z.enum(["blocker", "serious", "minor"]),
|
|
49
|
+
rule: z.string(),
|
|
50
|
+
message: z.string(),
|
|
51
|
+
consequence: z.string(),
|
|
52
|
+
fix: z.string(),
|
|
53
|
+
doc: z.string(),
|
|
54
|
+
excerpt: z.string(),
|
|
55
|
+
});
|
|
56
|
+
/** The shape every review tool declares as its `outputSchema`. */
|
|
57
|
+
export const reviewOutputShape = {
|
|
58
|
+
summary: z.string().describe("One-line plain-language result."),
|
|
59
|
+
score: z
|
|
60
|
+
.number()
|
|
61
|
+
.int()
|
|
62
|
+
.describe("0-100 defect density. 100 = no findings. penalty = 10*blockers + 3*serious + 1*minor; capacity = files*10. Comparable across runs on ONE project, not between projects."),
|
|
63
|
+
counts: z.object({
|
|
64
|
+
blocker: z.number().int(),
|
|
65
|
+
serious: z.number().int(),
|
|
66
|
+
minor: z.number().int(),
|
|
67
|
+
total: z.number().int(),
|
|
68
|
+
}),
|
|
69
|
+
files_checked: z.number().int().describe("Swift files actually scanned."),
|
|
70
|
+
issues: z.array(issueSchema).describe("Every finding, most severe first."),
|
|
71
|
+
suggestions: z
|
|
72
|
+
.array(z.string())
|
|
73
|
+
.describe("Prioritized next actions, deduplicated by rule — not a restatement of every issue's fix."),
|
|
74
|
+
};
|
|
75
|
+
export const reviewOutputSchema = z.object(reviewOutputShape);
|
|
76
|
+
/**
|
|
77
|
+
* Collapse findings into a handful of actions.
|
|
78
|
+
*
|
|
79
|
+
* A `suggestions` array that simply repeats every issue's `fix` is noise — the
|
|
80
|
+
* issues already carry those. This groups by rule so a file with forty
|
|
81
|
+
* literal-spacing findings produces one instruction, ordered by total weight.
|
|
82
|
+
*/
|
|
83
|
+
function suggestionsFor(findings) {
|
|
84
|
+
if (findings.length === 0)
|
|
85
|
+
return [];
|
|
86
|
+
const byRule = new Map();
|
|
87
|
+
for (const finding of findings) {
|
|
88
|
+
const entry = byRule.get(finding.rule) ?? {
|
|
89
|
+
count: 0,
|
|
90
|
+
weight: 0,
|
|
91
|
+
fix: finding.fix,
|
|
92
|
+
};
|
|
93
|
+
entry.count += 1;
|
|
94
|
+
entry.weight += SEVERITY_WEIGHT[finding.severity];
|
|
95
|
+
byRule.set(finding.rule, entry);
|
|
96
|
+
}
|
|
97
|
+
return [...byRule.entries()]
|
|
98
|
+
.sort((a, b) => b[1].weight - a[1].weight)
|
|
99
|
+
.slice(0, 5)
|
|
100
|
+
.map(([rule, entry]) => entry.count === 1
|
|
101
|
+
? `${rule}: ${entry.fix}`
|
|
102
|
+
: `${rule} (${entry.count} occurrences): ${entry.fix}`);
|
|
103
|
+
}
|
|
104
|
+
function summarize(title, counts, files) {
|
|
105
|
+
if (counts.total === 0) {
|
|
106
|
+
return `${title}: no findings across ${files} file${files === 1 ? "" : "s"}.`;
|
|
107
|
+
}
|
|
108
|
+
const parts = [];
|
|
109
|
+
if (counts.blocker > 0)
|
|
110
|
+
parts.push(`${counts.blocker} blocker`);
|
|
111
|
+
if (counts.serious > 0)
|
|
112
|
+
parts.push(`${counts.serious} serious`);
|
|
113
|
+
if (counts.minor > 0)
|
|
114
|
+
parts.push(`${counts.minor} minor`);
|
|
115
|
+
return `${title}: ${parts.join(", ")} across ${files} file${files === 1 ? "" : "s"}.`;
|
|
116
|
+
}
|
|
117
|
+
/** Build the structured half of a tool result. */
|
|
118
|
+
export function buildReviewOutput(title, findings, filesChecked) {
|
|
119
|
+
const sorted = sortFindings(findings);
|
|
120
|
+
const counts = {
|
|
121
|
+
blocker: sorted.filter((f) => f.severity === "blocker").length,
|
|
122
|
+
serious: sorted.filter((f) => f.severity === "serious").length,
|
|
123
|
+
minor: sorted.filter((f) => f.severity === "minor").length,
|
|
124
|
+
total: sorted.length,
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
summary: summarize(title, counts, filesChecked),
|
|
128
|
+
score: scoreFor(sorted, filesChecked),
|
|
129
|
+
counts,
|
|
130
|
+
files_checked: filesChecked,
|
|
131
|
+
issues: sorted,
|
|
132
|
+
suggestions: suggestionsFor(sorted),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAqB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEvE;;;;;;;;;;GAUG;AAEH,0FAA0F;AAC1F,MAAM,eAAe,GAA6B;IAChD,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,CAAC;IACV,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,0DAA0D;AAC1D,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAmB,EAAE,YAAoB;IAChE,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAElC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAC7B,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,EAC7D,CAAC,CACF,CAAC;IACF,MAAM,QAAQ,GAAG,YAAY,GAAG,iBAAiB,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC;IAEzD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACtB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACjD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAEH,kEAAkE;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC/D,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,CACP,yKAAyK,CAC1K;IACH,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;QACzB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;QACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;QACvB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;KACxB,CAAC;IACF,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IACzE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IAC1E,WAAW,EAAE,CAAC;SACX,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,CACP,0FAA0F,CAC3F;CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAG9D;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,QAAmB;IACzC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA0D,CAAC;IAEjF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI;YACxC,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC;QACF,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACjB,KAAK,CAAC,MAAM,IAAI,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACzB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;SACzC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CACrB,KAAK,CAAC,KAAK,KAAK,CAAC;QACf,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,GAAG,EAAE;QACzB,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,KAAK,kBAAkB,KAAK,CAAC,GAAG,EAAE,CACzD,CAAC;AACN,CAAC;AAED,SAAS,SAAS,CAAC,KAAa,EAAE,MAA8B,EAAE,KAAa;IAC7E,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,KAAK,wBAAwB,KAAK,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAChF,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,OAAO,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;IAChE,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC;IAC1D,OAAO,GAAG,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,KAAK,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACxF,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,QAAmB,EACnB,YAAoB;IAEpB,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;QAC9D,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;QAC9D,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM;QAC1D,KAAK,EAAE,MAAM,CAAC,MAAM;KACrB,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC;QAC/C,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;QACrC,MAAM;QACN,aAAa,EAAE,YAAY;QAC3B,MAAM,EAAE,MAAM;QACd,WAAW,EAAE,cAAc,CAAC,MAAM,CAAC;KACpC,CAAC;AACJ,CAAC"}
|
package/dist/scan.d.ts
CHANGED
|
@@ -20,6 +20,15 @@ export interface ProjectSummary {
|
|
|
20
20
|
hasTests: boolean;
|
|
21
21
|
hasPackageSwift: boolean;
|
|
22
22
|
hasXcodeProject: boolean;
|
|
23
|
+
/** SwiftUI, UIKit, both, or neither — inferred from imports. */
|
|
24
|
+
uiFramework: "SwiftUI" | "UIKit" | "SwiftUI + UIKit" | "unknown";
|
|
25
|
+
/** Best-effort architecture read. Evidence is reported alongside it. */
|
|
26
|
+
architecture: string;
|
|
27
|
+
architectureEvidence: string[];
|
|
28
|
+
/** Third-party packages, from Package.swift / Podfile / project.pbxproj. */
|
|
29
|
+
dependencies: string[];
|
|
30
|
+
/** True when at least one dependency crosses an injected protocol boundary. */
|
|
31
|
+
usesDependencyInjection: boolean;
|
|
23
32
|
}
|
|
24
33
|
/** A structural overview of the project, independent of rule violations. */
|
|
25
34
|
export declare function summarizeProject(root: string, files: SourceFile[]): Promise<ProjectSummary>;
|
package/dist/scan.js
CHANGED
|
@@ -103,6 +103,97 @@ export async function readProjectContext(root) {
|
|
|
103
103
|
const isApp = plists.length > 0 || xcodeprojs.length > 0;
|
|
104
104
|
return { infoPlist, hasPrivacyManifest: manifests.length > 0, isApp };
|
|
105
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Infer the architecture from file naming and type shape.
|
|
108
|
+
*
|
|
109
|
+
* Deliberately reports EVIDENCE rather than a bare verdict. "MVVM" with nothing
|
|
110
|
+
* behind it is a guess presented as a fact; "MVVM — 12 *ViewModel/*Model types,
|
|
111
|
+
* Views/ and ViewModels/ directories" is a claim the reader can check. When the
|
|
112
|
+
* signals are weak it says so instead of picking the most popular answer.
|
|
113
|
+
*/
|
|
114
|
+
function inferArchitecture(files) {
|
|
115
|
+
const paths = files.map((f) => f.path);
|
|
116
|
+
const evidence = [];
|
|
117
|
+
const count = (test) => paths.filter((p) => test.test(p)).length;
|
|
118
|
+
const typeCount = (test) => files.filter((f) => test.test(f.content)).length;
|
|
119
|
+
const viewModels = typeCount(/\b(?:final\s+)?class\s+\w*(?:ViewModel|Model)\b/);
|
|
120
|
+
const useCases = count(/UseCases?\//i) + typeCount(/protocol\s+\w*UseCase\b/);
|
|
121
|
+
const repositories = typeCount(/protocol\s+\w*Repository\b/);
|
|
122
|
+
const coordinators = typeCount(/\bclass\s+\w*Coordinator\b/);
|
|
123
|
+
const stores = typeCount(/\b(?:struct|enum)\s+\w*(?:Reducer|Feature)\b/) +
|
|
124
|
+
typeCount(/import\s+ComposableArchitecture/);
|
|
125
|
+
const hasLayerDirs = count(/(^|\/)(Domain|Data|Presentation)\//i) >= 2;
|
|
126
|
+
const hasMVVMDirs = count(/(^|\/)ViewModels?\//i) > 0 && count(/(^|\/)Views?\//i) > 0;
|
|
127
|
+
if (stores > 0) {
|
|
128
|
+
evidence.push(`${stores} Reducer/Feature type(s) or a ComposableArchitecture import`);
|
|
129
|
+
return { architecture: "The Composable Architecture", evidence };
|
|
130
|
+
}
|
|
131
|
+
if (hasLayerDirs || (useCases > 0 && repositories > 0)) {
|
|
132
|
+
if (hasLayerDirs)
|
|
133
|
+
evidence.push("Domain/, Data/, and Presentation/ directories");
|
|
134
|
+
if (useCases > 0)
|
|
135
|
+
evidence.push(`${useCases} use-case protocol(s) or a UseCases/ directory`);
|
|
136
|
+
if (repositories > 0)
|
|
137
|
+
evidence.push(`${repositories} repository protocol(s)`);
|
|
138
|
+
return { architecture: "Clean Architecture", evidence };
|
|
139
|
+
}
|
|
140
|
+
if (coordinators > 0) {
|
|
141
|
+
evidence.push(`${coordinators} Coordinator type(s)`);
|
|
142
|
+
if (viewModels > 0)
|
|
143
|
+
evidence.push(`${viewModels} view-model type(s)`);
|
|
144
|
+
return { architecture: "MVVM + Coordinator", evidence };
|
|
145
|
+
}
|
|
146
|
+
if (viewModels > 0 || hasMVVMDirs) {
|
|
147
|
+
if (viewModels > 0)
|
|
148
|
+
evidence.push(`${viewModels} ViewModel/Model type(s)`);
|
|
149
|
+
if (hasMVVMDirs)
|
|
150
|
+
evidence.push("Views/ and ViewModels/ directories");
|
|
151
|
+
return { architecture: "MVVM", evidence };
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
architecture: "not determined",
|
|
155
|
+
evidence: ["no view-model, use-case, repository, or coordinator types found"],
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/** Third-party package names from whichever manifest the project uses. */
|
|
159
|
+
async function readDependencies(root) {
|
|
160
|
+
const found = new Set();
|
|
161
|
+
for (const path of await walk(root, (p) => p.endsWith("Package.swift"), 5)) {
|
|
162
|
+
try {
|
|
163
|
+
const content = await readFile(path, "utf8");
|
|
164
|
+
for (const match of content.matchAll(/url:\s*"https?:\/\/[^"]*\/([\w.-]+?)(?:\.git)?"/g)) {
|
|
165
|
+
found.add(match[1]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// ignore
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// SwiftPM through Xcode records resolved packages here.
|
|
173
|
+
for (const path of await walk(root, (p) => p.endsWith("Package.resolved"), 5)) {
|
|
174
|
+
try {
|
|
175
|
+
const content = await readFile(path, "utf8");
|
|
176
|
+
for (const match of content.matchAll(/"(?:identity|package)"\s*:\s*"([^"]+)"/g)) {
|
|
177
|
+
found.add(match[1]);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// ignore
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
for (const path of await walk(root, (p) => /(^|\/)Podfile$/.test(p), 3)) {
|
|
185
|
+
try {
|
|
186
|
+
const content = await readFile(path, "utf8");
|
|
187
|
+
for (const match of content.matchAll(/^\s*pod\s+['"]([^'"\/]+)/gm)) {
|
|
188
|
+
found.add(match[1]);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// ignore
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return [...found].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
196
|
+
}
|
|
106
197
|
/** A structural overview of the project, independent of rule violations. */
|
|
107
198
|
export async function summarizeProject(root, files) {
|
|
108
199
|
const frameworks = new Set();
|
|
@@ -139,6 +230,20 @@ export async function summarizeProject(root, files) {
|
|
|
139
230
|
}
|
|
140
231
|
}
|
|
141
232
|
const xcodeprojs = await walk(root, (p) => p.endsWith(".pbxproj"), 3);
|
|
233
|
+
const { architecture, evidence } = inferArchitecture(files);
|
|
234
|
+
const dependencies = await readDependencies(root);
|
|
235
|
+
const usesSwiftUI = frameworks.has("SwiftUI");
|
|
236
|
+
const usesUIKit = frameworks.has("UIKit");
|
|
237
|
+
const uiFramework = usesSwiftUI && usesUIKit
|
|
238
|
+
? "SwiftUI + UIKit"
|
|
239
|
+
: usesSwiftUI
|
|
240
|
+
? "SwiftUI"
|
|
241
|
+
: usesUIKit
|
|
242
|
+
? "UIKit"
|
|
243
|
+
: "unknown";
|
|
244
|
+
// An injected protocol existential in an initializer is the signal. A project
|
|
245
|
+
// that only ever constructs concrete types has no seam, whatever it is called.
|
|
246
|
+
const usesDependencyInjection = files.some((file) => /init\s*\([^)]*:\s*any\s+\w+/.test(file.content));
|
|
142
247
|
return {
|
|
143
248
|
swiftFileCount: files.length,
|
|
144
249
|
lineCount,
|
|
@@ -148,6 +253,11 @@ export async function summarizeProject(root, files) {
|
|
|
148
253
|
hasTests: files.some((f) => /Tests?\.swift$/.test(f.path)),
|
|
149
254
|
hasPackageSwift: packages.length > 0,
|
|
150
255
|
hasXcodeProject: xcodeprojs.length > 0,
|
|
256
|
+
uiFramework,
|
|
257
|
+
architecture,
|
|
258
|
+
architectureEvidence: evidence,
|
|
259
|
+
dependencies,
|
|
260
|
+
usesDependencyInjection,
|
|
151
261
|
};
|
|
152
262
|
}
|
|
153
263
|
//# sourceMappingURL=scan.js.map
|
package/dist/scan.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION = "2.2.0";
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,mFAAmF;AACnF,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
package/mcp.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ios-agent-mcp",
|
|
3
3
|
"displayName": "iOS Agent",
|
|
4
|
-
"version": "
|
|
5
|
-
"description": "Static analysis for modern iOS/Swift projects — Swift 6 actor isolation, architecture boundaries, SwiftUI, availability guards, and App Store readiness.",
|
|
4
|
+
"version": "2.2.0",
|
|
5
|
+
"description": "Static analysis for modern iOS/Swift projects — Swift 6 actor isolation, architecture boundaries, SwiftUI, availability guards, and App Store readiness — plus a linter for Agent Skill repositories.",
|
|
6
6
|
"author": "Nagarjuna Reddy",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"homepage": "https://github.com/Nagarjuna2997/ios-agent-skill",
|
|
@@ -11,13 +11,25 @@
|
|
|
11
11
|
"url": "https://github.com/Nagarjuna2997/ios-agent-skill.git",
|
|
12
12
|
"directory": "mcp-server"
|
|
13
13
|
},
|
|
14
|
-
"keywords": [
|
|
14
|
+
"keywords": [
|
|
15
|
+
"ios",
|
|
16
|
+
"swift",
|
|
17
|
+
"swiftui",
|
|
18
|
+
"xcode",
|
|
19
|
+
"apple",
|
|
20
|
+
"static-analysis",
|
|
21
|
+
"code-review",
|
|
22
|
+
"agent-skills"
|
|
23
|
+
],
|
|
15
24
|
"runtime": {
|
|
16
25
|
"type": "node",
|
|
17
26
|
"minimumVersion": "18",
|
|
18
27
|
"transport": "stdio",
|
|
19
28
|
"command": "npx",
|
|
20
|
-
"args": [
|
|
29
|
+
"args": [
|
|
30
|
+
"-y",
|
|
31
|
+
"ios-agent-mcp"
|
|
32
|
+
]
|
|
21
33
|
},
|
|
22
34
|
"permissions": {
|
|
23
35
|
"filesystem": "read",
|
|
@@ -25,11 +37,64 @@
|
|
|
25
37
|
"notes": "Reads .swift, Info.plist, Package.swift, and project.pbxproj files under the path you pass to a tool. Makes no network requests and writes nothing."
|
|
26
38
|
},
|
|
27
39
|
"tools": [
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
{
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
{
|
|
41
|
+
"name": "analyze_swift_project",
|
|
42
|
+
"summary": "Project overview plus a finding count for every rule category."
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "review_swift_concurrency",
|
|
46
|
+
"summary": "Swift 6 actor isolation and concurrency defects."
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "review_swift_architecture",
|
|
50
|
+
"summary": "Architecture boundaries, dependency injection, testability."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "review_swiftui",
|
|
54
|
+
"summary": "SwiftUI view and state defects, Dynamic Type, design tokens."
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "check_availability_guards",
|
|
58
|
+
"summary": "Missing and over-restrictive @available guards."
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "audit_app_store_readiness",
|
|
62
|
+
"summary": "Purpose strings, privacy manifest, accessibility, localization."
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "review_swift_memory",
|
|
66
|
+
"summary": "Retain cycles, weak/unowned usage, closure and Task lifetime."
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "review_swift_security",
|
|
70
|
+
"summary": "Hardcoded secrets, insecure storage, ATS, TLS, weak crypto, Keychain accessibility."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "review_swift_testing",
|
|
74
|
+
"summary": "Flaky patterns, vacuous tests, live network in tests, missing coverage."
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "review_swift_performance",
|
|
78
|
+
"summary": "Work inside body, eager stacks, unstable ForEach identity, blocking I/O."
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "lint_skill",
|
|
82
|
+
"summary": "Agent Skill metadata: frontmatter, subagent tool grants, mirror sync, doc references."
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"resources": [
|
|
86
|
+
{
|
|
87
|
+
"uri": "ios://project/info",
|
|
88
|
+
"summary": "Structure, architecture with evidence, DI, frameworks."
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"uri": "ios://project/dependencies",
|
|
92
|
+
"summary": "Third-party packages and Apple frameworks."
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"uri": "ios://project/issues",
|
|
96
|
+
"summary": "Every finding across all nine categories."
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"notes": "Resources require a project root: pass --project PATH or set IOS_AGENT_PROJECT. Tools take an explicit path argument and need no configuration."
|
|
35
100
|
}
|