@zivis/mcp 0.1.12 → 0.1.17
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/dist/api-client.js +18 -9
- package/dist/pattern-packs/zivis-public-0.2.0/manifest.json +1 -1
- package/dist/project-binding.d.ts +1 -0
- package/dist/project-binding.js +50 -6
- package/dist/prompts/audit-dependencies.js +9 -21
- package/dist/server.js +0 -10
- package/dist/tools/check-project.js +7 -12
- package/dist/tools/devx-run.d.ts +1 -1
- package/dist/tools/devx-run.js +1 -1
- package/dist/tools/discover-local-infra.d.ts +1 -1
- package/dist/tools/discover-local-infra.js +9 -16
- package/dist/tools/get-started.d.ts +1 -1
- package/dist/tools/get-started.js +110 -94
- package/dist/tools/get-trust-keys.d.ts +1 -1
- package/dist/tools/get-trust-keys.js +1 -1
- package/dist/tools/inspect-zat.d.ts +1 -1
- package/dist/tools/inspect-zat.js +2 -2
- package/dist/tools/security-review.d.ts +2 -7
- package/dist/tools/security-review.js +12 -91
- package/package.json +2 -1
- package/dist/tools/check-repo-trust.d.ts +0 -18
- package/dist/tools/check-repo-trust.js +0 -221
- package/dist/tools/get-oss-zat.d.ts +0 -22
- package/dist/tools/get-oss-zat.js +0 -98
package/dist/api-client.js
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
1
4
|
import { resolveAuth } from "./auth/index.js";
|
|
2
|
-
import { detectProjectBinding, resolveConfigFromBinding, resolveMcpSessionForWorkspace, } from "./project-binding.js";
|
|
5
|
+
import { detectProjectBinding, resolveConfigFromBinding, resolveMcpSessionForWorkspace, sanitizeBindingOverrides, } from "./project-binding.js";
|
|
3
6
|
import { DEFAULT_CONFIG } from "./types.js";
|
|
7
|
+
const USER_AGENT = (() => {
|
|
8
|
+
try {
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"), "utf-8"));
|
|
11
|
+
return `@zivis/mcp/${pkg.version ?? "0.0.0"}`;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return "@zivis/mcp/0.0.0";
|
|
15
|
+
}
|
|
16
|
+
})();
|
|
4
17
|
export class ApiClient {
|
|
5
18
|
config;
|
|
6
19
|
constructor(config = DEFAULT_CONFIG) {
|
|
@@ -12,16 +25,12 @@ export class ApiClient {
|
|
|
12
25
|
if (!detected) {
|
|
13
26
|
return this.config;
|
|
14
27
|
}
|
|
15
|
-
const { binding } = detected;
|
|
28
|
+
const { binding, filePath } = detected;
|
|
16
29
|
const fromBinding = resolveConfigFromBinding(ws);
|
|
17
30
|
return {
|
|
18
31
|
...this.config,
|
|
19
32
|
session: resolveMcpSessionForWorkspace(this.config, ws, detected, fromBinding),
|
|
20
|
-
...(binding
|
|
21
|
-
...(binding.oauthApiUrl ? { oauthApiUrl: binding.oauthApiUrl } : {}),
|
|
22
|
-
...(binding.oauthClientId ? { oauthClientId: binding.oauthClientId } : {}),
|
|
23
|
-
...(binding.keychainPrefix ? { keychainPrefix: binding.keychainPrefix } : {}),
|
|
24
|
-
...(binding.configDir ? { configDir: binding.configDir } : {}),
|
|
33
|
+
...sanitizeBindingOverrides(binding, filePath),
|
|
25
34
|
};
|
|
26
35
|
}
|
|
27
36
|
buildAuthHeaders(creds) {
|
|
@@ -50,7 +59,7 @@ export class ApiClient {
|
|
|
50
59
|
const url = `${apiBaseUrl}${path}`;
|
|
51
60
|
const headers = {
|
|
52
61
|
"Content-Type": "application/json",
|
|
53
|
-
"User-Agent":
|
|
62
|
+
"User-Agent": USER_AGENT,
|
|
54
63
|
...this.buildAuthHeaders(creds),
|
|
55
64
|
};
|
|
56
65
|
const fetchOptions = { method, headers };
|
|
@@ -88,7 +97,7 @@ export class ApiClient {
|
|
|
88
97
|
}
|
|
89
98
|
const url = `${effectiveConfig.apiBaseUrl}${path}`;
|
|
90
99
|
const headers = {
|
|
91
|
-
"User-Agent":
|
|
100
|
+
"User-Agent": USER_AGENT,
|
|
92
101
|
...this.buildAuthHeaders(creds),
|
|
93
102
|
};
|
|
94
103
|
const response = await fetch(url, { method: "GET", headers });
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"pack_id": "zivis-public",
|
|
4
4
|
"pack_name": "ZIVIS Public Pattern Pack",
|
|
5
5
|
"version": "0.2.0",
|
|
6
|
-
"built_at": "2026-09-
|
|
6
|
+
"built_at": "2026-09-08T13:37:26.490Z",
|
|
7
7
|
"tier": "customer_safe",
|
|
8
8
|
"description": "ZIVIS-curated public pattern pack — capsules + inference prompts evaluated locally on the user's machine.",
|
|
9
9
|
"capsules": [
|
|
@@ -3,6 +3,7 @@ export declare function detectProjectBinding(cwd: string): {
|
|
|
3
3
|
binding: ProjectBinding;
|
|
4
4
|
filePath: string;
|
|
5
5
|
} | null;
|
|
6
|
+
export declare function sanitizeBindingOverrides(binding: ProjectBinding, filePath: string): Partial<Pick<ZivisConfig, "apiBaseUrl" | "oauthApiUrl" | "oauthClientId">>;
|
|
6
7
|
export declare function resolveConfigFromBinding(cwd?: string): ZivisConfig;
|
|
7
8
|
export declare function resolveMcpSessionForWorkspace(incoming: ZivisConfig, workspacePath: string, detected: ReturnType<typeof detectProjectBinding>, fromBinding: ZivisConfig): string;
|
|
8
9
|
export declare function validateProjectBinding(binding: ProjectBinding, filePath: string, config: ZivisConfig): void;
|
package/dist/project-binding.js
CHANGED
|
@@ -27,19 +27,63 @@ export function detectProjectBinding(cwd) {
|
|
|
27
27
|
}
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
|
+
const TRUSTED_BINDING_HOST = "zivis.ai";
|
|
31
|
+
const TRUSTED_BINDING_HOST_SUFFIX = ".zivis.ai";
|
|
32
|
+
const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
|
|
33
|
+
function isTrustedBindingUrl(raw, envAnchor) {
|
|
34
|
+
if (envAnchor && raw === envAnchor)
|
|
35
|
+
return true;
|
|
36
|
+
let parsed;
|
|
37
|
+
try {
|
|
38
|
+
parsed = new URL(raw);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const host = parsed.hostname.toLowerCase();
|
|
44
|
+
if (LOOPBACK_HOSTS.has(host))
|
|
45
|
+
return true;
|
|
46
|
+
if (parsed.protocol !== "https:")
|
|
47
|
+
return false;
|
|
48
|
+
return host === TRUSTED_BINDING_HOST || host.endsWith(TRUSTED_BINDING_HOST_SUFFIX);
|
|
49
|
+
}
|
|
50
|
+
function describeHost(raw) {
|
|
51
|
+
try {
|
|
52
|
+
return new URL(raw).host;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return "<unparseable url>";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function sanitizeBindingOverrides(binding, filePath) {
|
|
59
|
+
const out = {};
|
|
60
|
+
const gate = (field, value, envName) => {
|
|
61
|
+
if (!value)
|
|
62
|
+
return;
|
|
63
|
+
if (isTrustedBindingUrl(value, process.env[envName])) {
|
|
64
|
+
out[field] = value;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
console.error(`[zivis] WARNING: ignoring untrusted "${field}" in ${filePath} ` +
|
|
68
|
+
`(host: ${describeHost(value)}). A repo binding may only point at ` +
|
|
69
|
+
`https://*.zivis.ai, localhost, or the exact value of ${envName}. ` +
|
|
70
|
+
`Falling back to the configured/default host.`);
|
|
71
|
+
};
|
|
72
|
+
gate("apiBaseUrl", binding.apiBaseUrl, "ZIVIS_API_URL");
|
|
73
|
+
gate("oauthApiUrl", binding.oauthApiUrl, "ZIVIS_OAUTH_API_URL");
|
|
74
|
+
if (binding.oauthClientId)
|
|
75
|
+
out.oauthClientId = binding.oauthClientId;
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
30
78
|
export function resolveConfigFromBinding(cwd) {
|
|
31
79
|
const detected = detectProjectBinding(cwd ?? process.cwd());
|
|
32
80
|
if (!detected)
|
|
33
81
|
return DEFAULT_CONFIG;
|
|
34
|
-
const { binding } = detected;
|
|
82
|
+
const { binding, filePath } = detected;
|
|
35
83
|
return {
|
|
36
84
|
...DEFAULT_CONFIG,
|
|
37
85
|
...(binding.session ? { session: binding.session } : {}),
|
|
38
|
-
...(binding
|
|
39
|
-
...(binding.oauthApiUrl ? { oauthApiUrl: binding.oauthApiUrl } : {}),
|
|
40
|
-
...(binding.oauthClientId ? { oauthClientId: binding.oauthClientId } : {}),
|
|
41
|
-
...(binding.keychainPrefix ? { keychainPrefix: binding.keychainPrefix } : {}),
|
|
42
|
-
...(binding.configDir ? { configDir: binding.configDir } : {}),
|
|
86
|
+
...sanitizeBindingOverrides(binding, filePath),
|
|
43
87
|
};
|
|
44
88
|
}
|
|
45
89
|
export function resolveMcpSessionForWorkspace(incoming, workspacePath, detected, fromBinding) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export function registerAuditDependenciesPrompt(server) {
|
|
2
2
|
server.registerPrompt("audit-dependencies", {
|
|
3
|
-
description: "Check the open source libraries this project depends on for security risks
|
|
3
|
+
description: "Check the open source libraries this project depends on for security risks (requires a connected ZIVIS project — run `zivis init` first if needed).",
|
|
4
4
|
argsSchema: {},
|
|
5
5
|
}, async () => ({
|
|
6
6
|
messages: [
|
|
@@ -12,33 +12,21 @@ export function registerAuditDependenciesPrompt(server) {
|
|
|
12
12
|
|
|
13
13
|
Please do the following:
|
|
14
14
|
|
|
15
|
-
1.
|
|
16
|
-
- package.json (look for the "dependencies" and "devDependencies" keys)
|
|
17
|
-
- requirements.txt or pyproject.toml
|
|
18
|
-
- go.mod
|
|
19
|
-
- Any other manifest files you can see
|
|
15
|
+
1. Check whether this repo is connected to ZIVIS: look for \`.zivis/project.json\`. If it's missing, run \`zivis init\` in the terminal first (interactive login + one-time setup) and only continue once that succeeds.
|
|
20
16
|
|
|
21
|
-
2.
|
|
22
|
-
- Skip internal packages (those starting with "@my-company/" or similar private namespaces).
|
|
23
|
-
- Skip built-in packages (e.g. node built-ins like "fs", "path").
|
|
17
|
+
2. Run \`zivis test dependencies\` in the terminal. This loads the ZIVIS dependency-risk methodology (reachability triage against the resolved lockfile — not just a CVE list) plus this project's prior ZIVIS security context, and hands you the grounding to do the actual analysis yourself.
|
|
24
18
|
|
|
25
|
-
3.
|
|
26
|
-
with the owner/repo string (e.g. "openai/openai-node").
|
|
19
|
+
3. Follow the methodology it prints: build the dependency worklist from your lockfile, trace direct-runtime dependencies for reachability (is the vulnerable function actually imported, called, and fed attacker-controlled input?), and classify each as reachable-confirmed / reachable-but-contingent / not-imported / not-applicable / indeterminate.
|
|
27
20
|
|
|
28
|
-
4.
|
|
29
|
-
- Package name
|
|
30
|
-
- Trust grade (A+ through F)
|
|
31
|
-
- Risk level (Safe / Low risk / Moderate / High / Critical)
|
|
32
|
-
- Any critical or high findings (one line each)
|
|
21
|
+
4. Give me a summary table with columns: package, installed version, CVE(s), reachability verdict, and one-line reasoning.
|
|
33
22
|
|
|
34
|
-
5.
|
|
23
|
+
5. For anything reachable-confirmed, record it as a finding through the run's normal reporting flow so it's durable ZIVIS history, not just terminal output.
|
|
35
24
|
|
|
36
|
-
6. At the end, suggest the two highest-priority actions
|
|
25
|
+
6. At the end, name any transitive-only dependencies you didn't trace this pass (an explicit coverage gap, not a silent pass) and suggest the two highest-priority actions.
|
|
37
26
|
|
|
38
27
|
Ground rules:
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
- Don't make up trust data — only use what zivis_check_repo_trust returns.
|
|
28
|
+
- This requires a connected ZIVIS project — do not fabricate a trust score or skip straight to a verdict if \`zivis init\`/\`zivis test dependencies\` fails; report what went wrong instead.
|
|
29
|
+
- A CVE with no confirmed reachable call site is not the same as a confirmed vulnerability — say so explicitly rather than flattening the distinction.
|
|
42
30
|
- Speak in plain English. "High risk" is better than "critical severity threat vector".`,
|
|
43
31
|
},
|
|
44
32
|
},
|
package/dist/server.js
CHANGED
|
@@ -55,8 +55,6 @@ import { THREAT_LIST_RELEVANT_CAPSULES_NAME, THREAT_LIST_RELEVANT_CAPSULES_DESCR
|
|
|
55
55
|
import { THREAT_GET_CAPSULE_NAME, THREAT_GET_CAPSULE_DESCRIPTION, THREAT_GET_CAPSULE_SCHEMA, createThreatGetCapsuleHandler, } from "./tools/threat-get-capsule.js";
|
|
56
56
|
import { THREAT_GET_INFERENCE_PROMPT_NAME, THREAT_GET_INFERENCE_PROMPT_DESCRIPTION, THREAT_GET_INFERENCE_PROMPT_SCHEMA, createThreatGetInferencePromptHandler, } from "./tools/threat-get-inference-prompt.js";
|
|
57
57
|
import { THREAT_RUN_MATCHER_NAME, THREAT_RUN_MATCHER_DESCRIPTION, THREAT_RUN_MATCHER_SCHEMA, createThreatRunMatcherHandler, } from "./tools/threat-run-matcher.js";
|
|
58
|
-
import { CHECK_REPO_TRUST_NAME, CHECK_REPO_TRUST_DESCRIPTION, CHECK_REPO_TRUST_SCHEMA, createCheckRepoTrustHandler, } from "./tools/check-repo-trust.js";
|
|
59
|
-
import { GET_OSS_ZAT_NAME, GET_OSS_ZAT_DESCRIPTION, GET_OSS_ZAT_SCHEMA, createGetOssZatHandler, } from "./tools/get-oss-zat.js";
|
|
60
58
|
import { VERIFY_TRUST_MARK_NAME, VERIFY_TRUST_MARK_DESCRIPTION, VERIFY_TRUST_MARK_SCHEMA, createVerifyTrustMarkHandler, } from "./tools/verify-trust-mark.js";
|
|
61
59
|
import { GET_TRUST_KEYS_NAME, GET_TRUST_KEYS_DESCRIPTION, GET_TRUST_KEYS_SCHEMA, createGetTrustKeysHandler, } from "./tools/get-trust-keys.js";
|
|
62
60
|
import { INSPECT_ZAT_NAME, INSPECT_ZAT_DESCRIPTION, INSPECT_ZAT_SCHEMA, createInspectZatHandler, } from "./tools/inspect-zat.js";
|
|
@@ -142,14 +140,6 @@ export async function startServer(incoming = DEFAULT_CONFIG) {
|
|
|
142
140
|
description: THREAT_RUN_MATCHER_DESCRIPTION,
|
|
143
141
|
inputSchema: THREAT_RUN_MATCHER_SCHEMA,
|
|
144
142
|
}, createThreatRunMatcherHandler());
|
|
145
|
-
server.registerTool(CHECK_REPO_TRUST_NAME, {
|
|
146
|
-
description: CHECK_REPO_TRUST_DESCRIPTION,
|
|
147
|
-
inputSchema: CHECK_REPO_TRUST_SCHEMA,
|
|
148
|
-
}, createCheckRepoTrustHandler(config));
|
|
149
|
-
server.registerTool(GET_OSS_ZAT_NAME, {
|
|
150
|
-
description: GET_OSS_ZAT_DESCRIPTION,
|
|
151
|
-
inputSchema: GET_OSS_ZAT_SCHEMA,
|
|
152
|
-
}, createGetOssZatHandler(config));
|
|
153
143
|
server.registerTool(VERIFY_TRUST_MARK_NAME, {
|
|
154
144
|
description: VERIFY_TRUST_MARK_DESCRIPTION,
|
|
155
145
|
inputSchema: VERIFY_TRUST_MARK_SCHEMA,
|
|
@@ -44,18 +44,12 @@ export function createCheckProjectHandler(apiClient, _config) {
|
|
|
44
44
|
{
|
|
45
45
|
id: "run_auth_init",
|
|
46
46
|
label: "Connect this project to your ZIVIS org",
|
|
47
|
-
tool: "
|
|
48
|
-
|
|
47
|
+
tool: "cli_command",
|
|
48
|
+
args_hint: { command: "zivis init" },
|
|
49
|
+
why: "Every ZIVIS command requires a bound Application — this creates the binding, then re-check.",
|
|
49
50
|
requires_tier: "free",
|
|
50
51
|
},
|
|
51
|
-
|
|
52
|
-
id: "check_deps_no_auth",
|
|
53
|
-
label: "Check dependencies without a binding (no auth needed)",
|
|
54
|
-
tool: "zivis_check_repo_trust",
|
|
55
|
-
why: "You can check any GitHub repo for security issues right now — no binding required.",
|
|
56
|
-
requires_tier: "free",
|
|
57
|
-
},
|
|
58
|
-
], "Project is not bound to a ZIVIS org. Run 'zivis auth init' in your terminal to fix this.");
|
|
52
|
+
], "Project is not bound to a ZIVIS org. Run 'zivis init' in your terminal to fix this.");
|
|
59
53
|
}
|
|
60
54
|
const { binding, filePath } = detected;
|
|
61
55
|
const sessionMatches = currentSession === binding.session;
|
|
@@ -161,8 +155,9 @@ export function createCheckProjectHandler(apiClient, _config) {
|
|
|
161
155
|
{
|
|
162
156
|
id: "check_deps",
|
|
163
157
|
label: "Check the open source libraries you depend on",
|
|
164
|
-
tool: "
|
|
165
|
-
|
|
158
|
+
tool: "cli_command",
|
|
159
|
+
args_hint: { command: "zivis test dependencies" },
|
|
160
|
+
why: "Runs the ZIVIS dependency-risk methodology against your resolved lockfile — reachability triage, not just a CVE list.",
|
|
166
161
|
requires_tier: "free",
|
|
167
162
|
},
|
|
168
163
|
], `Project is correctly connected to ${binding.orgName ?? "your ZIVIS org"}.`);
|
package/dist/tools/devx-run.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export declare function createRunReportHandler(apiClient: ApiClient): (params: R
|
|
|
54
54
|
}[];
|
|
55
55
|
}>;
|
|
56
56
|
export declare const RUN_COMPLETE_NAME = "zivis_run_complete";
|
|
57
|
-
export declare const RUN_COMPLETE_DESCRIPTION = "Complete a pending run with its final result envelope (ZIV-219 + ZIV-32) \u2014 the run's immutable close-out.\n\n`result` is the SAME envelope shape `zivis run complete --input` accepts: { summary?, coverage[]?, findings[]?, retests[]?, evidence[]?, observations[]?, generatedArtifacts?, risk_candidates? } \u2014 validated server-side, not here. It may safely repeat items already posted via zivis_run_report; the shared fingerprint/content-hash/observation-key upserts converge instead of duplicating. The response reports what was created/updated/matched, plus
|
|
57
|
+
export declare const RUN_COMPLETE_DESCRIPTION = "Complete a pending run with its final result envelope (ZIV-219 + ZIV-32) \u2014 the run's immutable close-out.\n\n`result` is the SAME envelope shape `zivis run complete --input` accepts: { summary?, coverage[]?, findings[]?, retests[]?, evidence[]?, observations[]?, generatedArtifacts?, risk_candidates? } \u2014 validated server-side, not here. It may safely repeat items already posted via zivis_run_report; the shared fingerprint/content-hash/observation-key upserts converge instead of duplicating. The response reports what was created/updated/matched, plus the Application's stable Assurance Overview URL (`applicationAssuranceUrl`).";
|
|
58
58
|
export declare const RUN_COMPLETE_SCHEMA: {
|
|
59
59
|
run_id: z.ZodString;
|
|
60
60
|
result: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
package/dist/tools/devx-run.js
CHANGED
|
@@ -124,7 +124,7 @@ export function createRunReportHandler(apiClient) {
|
|
|
124
124
|
export const RUN_COMPLETE_NAME = "zivis_run_complete";
|
|
125
125
|
export const RUN_COMPLETE_DESCRIPTION = `Complete a pending run with its final result envelope (ZIV-219 + ZIV-32) — the run's immutable close-out.
|
|
126
126
|
|
|
127
|
-
\`result\` is the SAME envelope shape \`zivis run complete --input\` accepts: { summary?, coverage[]?, findings[]?, retests[]?, evidence[]?, observations[]?, generatedArtifacts?, risk_candidates? } — validated server-side, not here. It may safely repeat items already posted via zivis_run_report; the shared fingerprint/content-hash/observation-key upserts converge instead of duplicating. The response reports what was created/updated/matched, plus
|
|
127
|
+
\`result\` is the SAME envelope shape \`zivis run complete --input\` accepts: { summary?, coverage[]?, findings[]?, retests[]?, evidence[]?, observations[]?, generatedArtifacts?, risk_candidates? } — validated server-side, not here. It may safely repeat items already posted via zivis_run_report; the shared fingerprint/content-hash/observation-key upserts converge instead of duplicating. The response reports what was created/updated/matched, plus the Application's stable Assurance Overview URL (\`applicationAssuranceUrl\`).`;
|
|
128
128
|
export const RUN_COMPLETE_SCHEMA = {
|
|
129
129
|
run_id: z.string().min(1).describe("The runId returned by zivis_run_start. Must be pending — completing an already-completed run replays idempotently."),
|
|
130
130
|
result: z
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const DISCOVER_LOCAL_INFRA_NAME = "zivis_discover_local_infra";
|
|
3
|
-
export declare const DISCOVER_LOCAL_INFRA_DESCRIPTION = "Discover AI infrastructure in a local project directory by reading Docker, compose, and dependency files.\n\nAnalyzes the project to understand what services are defined, which are running, and what AI/LLM frameworks are in use. Returns
|
|
3
|
+
export declare const DISCOVER_LOCAL_INFRA_DESCRIPTION = "Discover AI infrastructure in a local project directory by reading Docker, compose, and dependency files.\n\nAnalyzes the project to understand what services are defined, which are running, and what AI/LLM frameworks are in use. Returns a suggested target shape (URL, chat endpoint) for the coding agent to use as grounding context before running `zivis test ai`.\n\nWhat it reads:\n- docker-compose.yml / docker-compose.yaml / compose.yml / compose.yaml\n- Dockerfile(s) in the project root and subdirectories\n- .env files (structure only \u2014 values are redacted for safety)\n- package.json, requirements.txt, pyproject.toml, go.mod (to detect AI frameworks)\n\nWhat it checks:\n- Docker daemon status\n- Currently running containers (docker compose ps)\n- Port mappings and exposed services\n\nWhat it returns:\n- List of services with ports and images\n- Running vs stopped status per service\n- Detected AI/LLM patterns (OpenAI, Anthropic, LangChain, etc.)\n- Suggested target_url/target_type/chat_endpoint \u2014 informational context, not a tool call to make\n- Whether the zivis-local-runner Docker image is available\n\nFor actually testing the discovered AI system, run `zivis test ai` in the terminal \u2014 this tool only maps what's running locally.\n\nThis tool makes NO network requests and requires NO authentication. It only reads local files and queries the Docker daemon.";
|
|
4
4
|
export declare const DISCOVER_LOCAL_INFRA_SCHEMA: {
|
|
5
5
|
project_dir: z.ZodOptional<z.ZodString>;
|
|
6
6
|
};
|
|
@@ -7,7 +7,7 @@ const execAsync = promisify(exec);
|
|
|
7
7
|
export const DISCOVER_LOCAL_INFRA_NAME = "zivis_discover_local_infra";
|
|
8
8
|
export const DISCOVER_LOCAL_INFRA_DESCRIPTION = `Discover AI infrastructure in a local project directory by reading Docker, compose, and dependency files.
|
|
9
9
|
|
|
10
|
-
Analyzes the project to understand what services are defined, which are running, and what AI/LLM frameworks are in use. Returns
|
|
10
|
+
Analyzes the project to understand what services are defined, which are running, and what AI/LLM frameworks are in use. Returns a suggested target shape (URL, chat endpoint) for the coding agent to use as grounding context before running \`zivis test ai\`.
|
|
11
11
|
|
|
12
12
|
What it reads:
|
|
13
13
|
- docker-compose.yml / docker-compose.yaml / compose.yml / compose.yaml
|
|
@@ -24,9 +24,11 @@ What it returns:
|
|
|
24
24
|
- List of services with ports and images
|
|
25
25
|
- Running vs stopped status per service
|
|
26
26
|
- Detected AI/LLM patterns (OpenAI, Anthropic, LangChain, etc.)
|
|
27
|
-
- Suggested target_url
|
|
27
|
+
- Suggested target_url/target_type/chat_endpoint — informational context, not a tool call to make
|
|
28
28
|
- Whether the zivis-local-runner Docker image is available
|
|
29
29
|
|
|
30
|
+
For actually testing the discovered AI system, run \`zivis test ai\` in the terminal — this tool only maps what's running locally.
|
|
31
|
+
|
|
30
32
|
This tool makes NO network requests and requires NO authentication. It only reads local files and queries the Docker daemon.`;
|
|
31
33
|
export const DISCOVER_LOCAL_INFRA_SCHEMA = {
|
|
32
34
|
project_dir: z
|
|
@@ -127,7 +129,7 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
127
129
|
aiFrameworks: { detected: [], envHints: [] },
|
|
128
130
|
runnerImage: { available: false },
|
|
129
131
|
suggestion: null,
|
|
130
|
-
|
|
132
|
+
nextStep: null,
|
|
131
133
|
};
|
|
132
134
|
try {
|
|
133
135
|
const { stdout } = await execAsync("docker version --format '{{.Server.Version}}'", {
|
|
@@ -344,19 +346,10 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
344
346
|
}
|
|
345
347
|
result.suggestion = generateSuggestion(result.compose.services, result.aiFrameworks.detected, result.aiFrameworks.envHints, result.dockerfiles);
|
|
346
348
|
if (result.suggestion) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
352
|
-
if (result.suggestion.request_template) {
|
|
353
|
-
parts.push(`request_template='${result.suggestion.request_template}'`);
|
|
354
|
-
}
|
|
355
|
-
if (result.suggestion.response_path) {
|
|
356
|
-
parts.push(`response_path="${result.suggestion.response_path}"`);
|
|
357
|
-
}
|
|
358
|
-
parts.push(`scan_depth="standard"`);
|
|
359
|
-
result.localScanCommand = `zivis_local_scan(${parts.join(", ")})`;
|
|
349
|
+
result.nextStep =
|
|
350
|
+
`Detected ${result.suggestion.target_type} target at ${result.suggestion.target_url}` +
|
|
351
|
+
(result.suggestion.chat_endpoint ? ` (chat endpoint: ${result.suggestion.chat_endpoint})` : "") +
|
|
352
|
+
`. Run \`zivis test ai\` to test it.`;
|
|
360
353
|
}
|
|
361
354
|
return {
|
|
362
355
|
content: [
|
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import type { ApiClient } from "../api-client.js";
|
|
3
3
|
import type { ZivisConfig } from "../types.js";
|
|
4
4
|
export declare const GET_STARTED_NAME = "zivis_get_started";
|
|
5
|
-
export declare const GET_STARTED_DESCRIPTION = "Call this FIRST on any turn where the user asks about security, vulnerabilities, code review, deployment readiness, threat modeling, dependencies, or \"what should I do next.\" Idempotent and safe to call repeatedly \u2014 detects prior inspect runs and never re-inspects unnecessarily. Prefer this over calling zivis_inspect directly.\n\nUse this when the user says any of:\n- \"what should I do for security on this app\"\n- \"uhh, where do I start\"\n- \"is my app safe\" / \"is my chatbot safe\"\n- \"I need to do security stuff before launch\"\n- \"I have an audit / pen test / customer asking about security\"\n- \"check my dependencies / libraries / repos\"\n- \"how do I use ZIVIS\"\n- \"what can ZIVIS do for me\"\n\nThis tool inspects the current project state \u2014 binding, application, scans, findings \u2014\nAND if a recent 'zivis inspect' artifact exists for this repo, evaluates the local\nthreat library against it to surface architectural patterns ZIVIS thinks may apply\n(self-consistency without context isolation, late org filter, privilege separation, etc.).\nThe 'relevant_threats' field in the response is what makes this tool different from a\ngeneric security menu: ZIVIS is reading the user's actual codebase via the graph\nartifact and naming threats by their architectural shape.\n\
|
|
5
|
+
export declare const GET_STARTED_DESCRIPTION = "Call this FIRST on any turn where the user asks about security, vulnerabilities, code review, deployment readiness, threat modeling, dependencies, or \"what should I do next.\" Idempotent and safe to call repeatedly \u2014 detects prior inspect runs and never re-inspects unnecessarily. Prefer this over calling zivis_inspect directly.\n\nUse this when the user says any of:\n- \"what should I do for security on this app\"\n- \"uhh, where do I start\"\n- \"is my app safe\" / \"is my chatbot safe\"\n- \"I need to do security stuff before launch\"\n- \"I have an audit / pen test / customer asking about security\"\n- \"check my dependencies / libraries / repos\"\n- \"how do I use ZIVIS\"\n- \"what can ZIVIS do for me\"\n\nThis tool inspects the current project state \u2014 binding, application, scans, findings \u2014\nAND if a recent 'zivis inspect' artifact exists for this repo, evaluates the local\nthreat library against it to surface architectural patterns ZIVIS thinks may apply\n(self-consistency without context isolation, late org filter, privilege separation, etc.).\nThe 'relevant_threats' field in the response is what makes this tool different from a\ngeneric security menu: ZIVIS is reading the user's actual codebase via the graph\nartifact and naming threats by their architectural shape.\n\nSpeak in plain developer language by default \u2014 do not introduce jargon (actor, STRIDE,\nkill chain, TTPs) unless the user already used it. Naming the actual product concepts\n(\"your threat model\", `zivis threatmodel`) is fine when they are the literal thing being\ndiscussed; that is a product noun, not jargon to avoid.\n\nOutput is a structured JSON object. Present recommended_next_steps as a numbered list\nto the user, in order, and ask them to pick one. If relevant_threats is non-empty, lead\nwith that \u2014 it's the most concrete thing ZIVIS knows about their repo. Use the label\nand why fields verbatim; do not invent new steps. If the user is unsure which to pick,\nrecommend the item flagged in if_user_unsure.";
|
|
6
6
|
export declare const GET_STARTED_SCHEMA: {
|
|
7
7
|
concern: z.ZodOptional<z.ZodString>;
|
|
8
8
|
cwd: z.ZodOptional<z.ZodString>;
|