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.
Files changed (45) hide show
  1. package/README.md +74 -7
  2. package/data/knowledge.json +1 -0
  3. package/dist/analyzers/memory.d.ts +12 -0
  4. package/dist/analyzers/memory.js +81 -0
  5. package/dist/analyzers/memory.js.map +1 -0
  6. package/dist/analyzers/performance.d.ts +10 -0
  7. package/dist/analyzers/performance.js +106 -0
  8. package/dist/analyzers/performance.js.map +1 -0
  9. package/dist/analyzers/security.d.ts +2 -0
  10. package/dist/analyzers/security.js +82 -0
  11. package/dist/analyzers/security.js.map +1 -0
  12. package/dist/analyzers/skill.d.ts +34 -0
  13. package/dist/analyzers/skill.js +483 -0
  14. package/dist/analyzers/skill.js.map +1 -0
  15. package/dist/analyzers/testing.d.ts +16 -0
  16. package/dist/analyzers/testing.js +135 -0
  17. package/dist/analyzers/testing.js.map +1 -0
  18. package/dist/analyzers/types.d.ts +19 -1
  19. package/dist/analyzers/types.js +65 -3
  20. package/dist/analyzers/types.js.map +1 -1
  21. package/dist/index.js +162 -5
  22. package/dist/index.js.map +1 -1
  23. package/dist/knowledge-server.d.ts +2 -0
  24. package/dist/knowledge-server.js +44 -0
  25. package/dist/knowledge-server.js.map +1 -0
  26. package/dist/knowledge.d.ts +78 -0
  27. package/dist/knowledge.js +69 -0
  28. package/dist/knowledge.js.map +1 -0
  29. package/dist/report.d.ts +10 -0
  30. package/dist/report.js +40 -0
  31. package/dist/report.js.map +1 -1
  32. package/dist/resources.d.ts +67 -0
  33. package/dist/resources.js +222 -0
  34. package/dist/resources.js.map +1 -0
  35. package/dist/result.d.ts +203 -0
  36. package/dist/result.js +135 -0
  37. package/dist/result.js.map +1 -0
  38. package/dist/scan.d.ts +9 -0
  39. package/dist/scan.js +110 -0
  40. package/dist/scan.js.map +1 -1
  41. package/dist/version.d.ts +1 -0
  42. package/dist/version.js +4 -0
  43. package/dist/version.js.map +1 -0
  44. package/mcp.json +76 -11
  45. package/package.json +19 -10
@@ -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":"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"}
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";
@@ -0,0 +1,4 @@
1
+ // GENERATED by scripts/sync-version.mjs — do not edit.
2
+ // The version lives in package.json. Run `npm run sync-version` after changing it.
3
+ export const VERSION = "2.2.0";
4
+ //# sourceMappingURL=version.js.map
@@ -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": "1.0.0",
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": ["ios", "swift", "swiftui", "xcode", "apple", "static-analysis", "code-review"],
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": ["-y", "ios-agent-mcp"]
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
- { "name": "analyze_swift_project", "summary": "Project overview plus a finding count for every rule category." },
29
- { "name": "review_swift_concurrency", "summary": "Swift 6 actor isolation and concurrency defects." },
30
- { "name": "review_swift_architecture", "summary": "Architecture boundaries, dependency injection, testability." },
31
- { "name": "review_swiftui", "summary": "SwiftUI view and state defects, Dynamic Type, design tokens." },
32
- { "name": "check_availability_guards", "summary": "Missing and over-restrictive @available guards." },
33
- { "name": "audit_app_store_readiness", "summary": "Purpose strings, privacy manifest, accessibility, localization." }
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
  }