@zivis/mcp 0.1.12 → 0.1.18

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.
@@ -1,4 +1,5 @@
1
1
  import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
2
3
  import { z } from "zod";
3
4
  import { detectProjectBinding } from "../project-binding.js";
4
5
  import { loadActivePack, findRelevantCapsules, } from "../pattern-pack/index.js";
@@ -24,8 +25,10 @@ The 'relevant_threats' field in the response is what makes this tool different f
24
25
  generic security menu: ZIVIS is reading the user's actual codebase via the graph
25
26
  artifact and naming threats by their architectural shape.
26
27
 
27
- Always speak to the user in threat-model language: components, flows, trust boundaries,
28
- attack scenarios. Even when they don't yet know those terms that's how they learn.
28
+ Speak in plain developer language by default do not introduce jargon (actor, STRIDE,
29
+ kill chain, TTPs) unless the user already used it. Naming the actual product concepts
30
+ ("your threat model", \`zivis threatmodel\`) is fine when they are the literal thing being
31
+ discussed; that is a product noun, not jargon to avoid.
29
32
 
30
33
  Output is a structured JSON object. Present recommended_next_steps as a numbered list
31
34
  to the user, in order, and ask them to pick one. If relevant_threats is non-empty, lead
@@ -80,42 +83,44 @@ function stepCheckDeps() {
80
83
  return {
81
84
  id: "check_dependencies",
82
85
  label: "Check the open source libraries you depend on",
83
- tool: "zivis_check_repo_trust",
84
- why: "Free, no setup. Catches risky AI SDKs and known-bad dependencies before they cause problems.",
85
- estimated_time: "1 minute per repo",
86
- requires_auth: false,
86
+ tool: "cli_command",
87
+ args_hint: { command: "zivis test dependencies" },
88
+ why: "Runs the ZIVIS dependency-risk methodology (reachability triage) against your resolved lockfile.",
89
+ estimated_time: "a few minutes — the coding agent does the reasoning",
90
+ requires_auth: true,
87
91
  };
88
92
  }
89
- function stepSetupAiTarget(hint) {
93
+ function stepTestScope(scopeId, label, why) {
90
94
  return {
91
- id: "setup_ai_target",
92
- label: "Tell ZIVIS about your chatbot or AI system so it can test it",
93
- tool: "zivis_setup_red_team_target",
94
- args_hint: { target_type: "ai_chat", ...hint },
95
- why: "ZIVIS needs to know your endpoint to run prompt-injection, jailbreak, and PII-leakage tests.",
96
- estimated_time: "2 minutes",
95
+ id: `test_${scopeId}`,
96
+ label,
97
+ tool: "cli_command",
98
+ args_hint: { command: `zivis test ${scopeId}` },
99
+ why,
100
+ estimated_time: "a few minutes — the coding agent does the reasoning",
97
101
  requires_auth: true,
98
102
  };
99
103
  }
100
- function stepSetupWebTarget(hint) {
104
+ function stepBareTest() {
101
105
  return {
102
- id: "setup_web_target",
103
- label: "Register your web app or API with ZIVIS for testing",
104
- tool: "zivis_setup_red_team_target",
105
- args_hint: { target_type: "web_app", ...hint },
106
- why: "ZIVIS needs to know your app URL to run security tests against it.",
107
- estimated_time: "2 minutes",
106
+ id: "run_test",
107
+ label: "Run a ZIVIS security review of what changed",
108
+ tool: "cli_command",
109
+ args_hint: { command: "zivis test" },
110
+ why: "Change-aware by default: recommends only the scopes your recent changes touch, using ZIVIS's memory of what was last tested.",
111
+ estimated_time: "a few minutes — the coding agent does the reasoning",
108
112
  requires_auth: true,
109
113
  };
110
114
  }
111
- function stepBrowseTests() {
115
+ function stepListScopes() {
112
116
  return {
113
- id: "browse_test_library",
114
- label: "Browse what ZIVIS can test for",
115
- tool: "zivis_list_test_scenarios",
116
- why: "See the menu of attack categories (prompt injection, auth bypass, data leakage, etc.) before committing to a scan.",
117
- estimated_time: "30 seconds",
118
- requires_auth: true,
117
+ id: "list_scopes",
118
+ label: "See the security areas ZIVIS can test",
119
+ tool: "cli_command",
120
+ args_hint: { command: "zivis test --list" },
121
+ why: "Lists the scopes defined by the verified ZIVIS AppSec methodology pack — pick one instead of guessing a scope name.",
122
+ estimated_time: "a few seconds",
123
+ requires_auth: false,
119
124
  };
120
125
  }
121
126
  function stepViewFindings(count) {
@@ -124,8 +129,7 @@ function stepViewFindings(count) {
124
129
  label: count
125
130
  ? `Review the ${count} open security issue${count === 1 ? "" : "s"} ZIVIS found`
126
131
  : "Review open security issues ZIVIS found",
127
- tool: "zivis_get_findings",
128
- args_hint: { status: "open" },
132
+ tool: "zivis_security_review",
129
133
  why: "Look at what's been found already before starting new scans — no point duplicating work.",
130
134
  estimated_time: "5 minutes",
131
135
  requires_auth: true,
@@ -136,18 +140,52 @@ function stepRunSecurityReview() {
136
140
  id: "run_security_review",
137
141
  label: "Get a security readiness summary before launch or audit",
138
142
  tool: "zivis_security_review",
139
- why: "Pulls together all open findings, past fixes, and known attack scenarios into one pre-launch checklist.",
143
+ why: "Pulls together open findings and regression history from prior ZIVIS work into one pre-launch checklist.",
140
144
  estimated_time: "3 minutes",
141
145
  requires_auth: true,
142
146
  };
143
147
  }
148
+ function stepThreatModel() {
149
+ return {
150
+ id: "threat_model",
151
+ label: "Start or continue this Application's living threat model",
152
+ tool: "cli_command",
153
+ args_hint: { command: "zivis threatmodel" },
154
+ why: "Captures components, data flows, and trust boundaries as a durable, versioned artifact.",
155
+ estimated_time: "a few minutes — the coding agent does the reasoning",
156
+ requires_auth: true,
157
+ };
158
+ }
159
+ function stepGateShip() {
160
+ return {
161
+ id: "gate_ship",
162
+ label: "Get a deterministic ship/no-ship verdict against your committed policy",
163
+ tool: "cli_command",
164
+ args_hint: { command: "zivis gate ship" },
165
+ why: "Deterministic — reads your committed .zivis/policy.yaml against live Zivis state. Never an invented verdict.",
166
+ estimated_time: "a few seconds",
167
+ requires_auth: true,
168
+ };
169
+ }
170
+ function stepGateInit() {
171
+ return {
172
+ id: "gate_init",
173
+ label: "Create a committed ship policy so 'can we ship?' has a real answer",
174
+ tool: "cli_command",
175
+ args_hint: { command: "zivis gate --init" },
176
+ why: "No .zivis/policy.yaml exists yet, so zivis gate has nothing to evaluate — this scaffolds a starter policy to review and commit.",
177
+ estimated_time: "a minute to review and adjust the generated thresholds",
178
+ requires_auth: true,
179
+ };
180
+ }
144
181
  function stepSetupProject() {
145
182
  return {
146
183
  id: "setup_project",
147
184
  label: "Connect this project to your ZIVIS org",
148
- tool: "zivis_check_project",
149
- why: "ZIVIS needs to know which org this project belongs to before it can run tests or store results.",
150
- estimated_time: "2 minutes (run 'zivis auth init' in your terminal)",
185
+ tool: "cli_command",
186
+ args_hint: { command: "zivis init" },
187
+ why: "Every ZIVIS command needs a bound Application before it can run tests or store results this is the one thing that has to happen first.",
188
+ estimated_time: "2 minutes",
151
189
  requires_auth: false,
152
190
  };
153
191
  }
@@ -163,6 +201,10 @@ function stepInstallGitHubApp(installUrl) {
163
201
  };
164
202
  }
165
203
  async function fetchState(apiClient, cwd) {
204
+ const hasGatePolicy = await fs
205
+ .access(path.join(cwd, ".zivis", "policy.yaml"))
206
+ .then(() => true)
207
+ .catch(() => false);
166
208
  const detected = detectProjectBinding(cwd);
167
209
  if (!detected) {
168
210
  return {
@@ -171,6 +213,7 @@ async function fetchState(apiClient, cwd) {
171
213
  has_scans: false,
172
214
  has_findings: false,
173
215
  open_findings_count: 0,
216
+ has_gate_policy: hasGatePolicy,
174
217
  };
175
218
  }
176
219
  const state = {
@@ -180,6 +223,7 @@ async function fetchState(apiClient, cwd) {
180
223
  has_scans: false,
181
224
  has_findings: false,
182
225
  open_findings_count: 0,
226
+ has_gate_policy: hasGatePolicy,
183
227
  };
184
228
  try {
185
229
  const appsResp = await apiClient.get("/api/rt/applications?limit=1");
@@ -221,28 +265,19 @@ function buildMenu(intent, state, concern) {
221
265
  if (!state.bound) {
222
266
  return {
223
267
  headline: "Welcome to ZIVIS! First, let's connect this project to your organization so results are stored and tracked.",
224
- recommended_next_steps: [
225
- stepSetupProject(),
226
- stepCheckDeps(),
227
- stepBrowseTests(),
228
- ],
229
- guidance_for_assistant: "Present these as a numbered list. The user should run 'zivis auth init' in their terminal to complete step 1. " +
230
- "Step 2 (check_dependencies) requires no auth and can be done immediately. " +
231
- "If they ask 'why' something matters, expand on the 'why' field — do not make new claims.",
232
- if_user_unsure: "Recommend option 2 (check_dependencies) — it requires no setup and gives immediate results.",
268
+ recommended_next_steps: [stepSetupProject()],
269
+ guidance_for_assistant: "Present this as a single step. The user should run 'zivis init' in their terminal — it handles login and " +
270
+ "Application binding together. Every other ZIVIS command needs this to succeed first; there is nothing " +
271
+ "useful to offer in parallel. If they ask 'why' something matters, expand on the 'why' field — do not make new claims.",
272
+ if_user_unsure: "Run 'zivis init' — it's the only step available until this project is connected.",
233
273
  };
234
274
  }
235
275
  if (state.has_findings && intent !== "dep_audit") {
236
276
  const steps = [
237
277
  stepViewFindings(state.open_findings_count),
278
+ stepBareTest(),
238
279
  stepCheckDeps(),
239
280
  ];
240
- if (!state.has_application) {
241
- steps.push(stepSetupWebTarget());
242
- }
243
- else {
244
- steps.push(stepBrowseTests());
245
- }
246
281
  return {
247
282
  headline: `ZIVIS sees your project (${state.org_name ?? "connected"}) and has found ${state.open_findings_count} open security issue${state.open_findings_count === 1 ? "" : "s"}.`,
248
283
  recommended_next_steps: steps,
@@ -253,46 +288,28 @@ function buildMenu(intent, state, concern) {
253
288
  }
254
289
  if (intent === "ai_red_team") {
255
290
  const steps = [
256
- stepSetupAiTarget(),
291
+ stepTestScope("ai", "Test your AI system for prompt injection, jailbreaks, and data leakage", "Runs the ZIVIS 'ai' scope methodology, grounded in your actual code — not a generic checklist."),
257
292
  stepCheckDeps(),
258
- stepBrowseTests(),
259
293
  ];
260
294
  return {
261
- headline: state.has_application
262
- ? `ZIVIS sees your project (${state.org_name ?? "connected"}) and has a target configured. Ready to test your AI system.`
263
- : `ZIVIS sees your project (${state.org_name ?? "connected"}) but no security testing has run yet.`,
295
+ headline: `ZIVIS sees your project (${state.org_name ?? "connected"}). Let's test the AI-specific surface.`,
264
296
  recommended_next_steps: steps,
265
297
  guidance_for_assistant: "The user wants to test an AI/chatbot system. Present these as a numbered list. " +
266
- "If they already have a target URL, include it in args_hint. " +
267
298
  "If they ask 'why' something matters, expand on the 'why' field — do not make new claims.",
268
- if_user_unsure: "Recommend option 1 (setup_ai_target) — setting up the chatbot as a test target is the fastest path to finding real issues.",
299
+ if_user_unsure: "Recommend option 1 (test_ai) — it's the scope built for exactly this.",
269
300
  };
270
301
  }
271
302
  if (intent === "dep_audit") {
272
303
  return {
273
- headline: "Checking your dependencies is a great place to start — it's free, needs no setup, and often finds the most impactful issues.",
274
- recommended_next_steps: [
275
- stepCheckDeps(),
276
- stepSetupWebTarget(),
277
- stepBrowseTests(),
278
- ],
279
- guidance_for_assistant: "Present these as a numbered list. For step 1, ask the user to share which packages they want to check " +
280
- "(the GitHub org/repo of the dependency, e.g. openai/openai-python). " +
281
- "If they ask 'why' something matters, expand on the 'why' field — do not make new claims.",
282
- if_user_unsure: "Recommend option 1 (check_dependencies) — it works right now with no setup.",
304
+ headline: "Checking your dependencies is a great place to start — it often finds the most impactful issues fastest.",
305
+ recommended_next_steps: [stepCheckDeps(), stepBareTest()],
306
+ guidance_for_assistant: "Present these as a numbered list. If they ask 'why' something matters, expand on the 'why' field — do not make new claims.",
307
+ if_user_unsure: "Recommend option 1 (check_dependencies).",
283
308
  };
284
309
  }
285
310
  if (intent === "pre_audit" || intent === "pre_launch") {
286
- const steps = [
287
- stepRunSecurityReview(),
288
- stepCheckDeps(),
289
- ];
290
- if (!state.has_application) {
291
- steps.push(stepSetupWebTarget());
292
- }
293
- else {
294
- steps.push(stepBrowseTests());
295
- }
311
+ const gateStep = state.has_gate_policy ? stepGateShip() : stepGateInit();
312
+ const steps = [stepRunSecurityReview(), gateStep, stepBareTest(), stepCheckDeps()];
296
313
  const headline = intent === "pre_audit"
297
314
  ? `ZIVIS can help you prepare for an audit. Let's get a security readiness picture first.`
298
315
  : `ZIVIS can help you check security before you go live.`;
@@ -300,47 +317,46 @@ function buildMenu(intent, state, concern) {
300
317
  headline,
301
318
  recommended_next_steps: steps,
302
319
  guidance_for_assistant: "The user has a deadline (audit or launch). Start with a security review to understand the current state, " +
303
- "then address the highest-severity issues first. " +
304
- "If they ask 'why' something matters, expand on the 'why' field do not make new claims.",
305
- if_user_unsure: "Recommend option 1 (run_security_review) it gives the fastest complete picture and shows what needs to be fixed before the deadline.",
320
+ "then address the highest-severity issues first. The security review reflects known findings, not a " +
321
+ "deterministic ship verdict. If the user actually asks 'can we ship?' / 'go or no-go?', route to " +
322
+ "'zivis gate'NEVER answer that question yourself from the review or from general judgment. " +
323
+ (state.has_gate_policy
324
+ ? "A committed policy already exists here, so 'zivis gate ship' (or the relevant gate name) gives a real deterministic answer."
325
+ : "No committed policy exists yet, so gate has nothing to evaluate — offer 'zivis gate --init' to scaffold one first, then run the real evaluation. Do not substitute your own opinion in the meantime.") +
326
+ " If they ask 'why' something matters, expand on the 'why' field — do not make new claims.",
327
+ if_user_unsure: "Recommend option 1 (run_security_review) — it gives the fastest complete picture of what's already known.",
306
328
  };
307
329
  }
308
330
  if (intent === "view_findings") {
309
331
  return {
310
332
  headline: state.has_findings
311
333
  ? `ZIVIS has ${state.open_findings_count} open finding${state.open_findings_count === 1 ? "" : "s"} for this project.`
312
- : `No open findings found yet — ZIVIS may not have run a scan, or all issues are resolved.`,
334
+ : `No open findings on record yet — that means no test has found one, not that the project is clean.`,
313
335
  recommended_next_steps: [
314
336
  stepViewFindings(state.open_findings_count > 0 ? state.open_findings_count : undefined),
315
- state.has_application ? stepBrowseTests() : stepSetupWebTarget(),
316
- stepCheckDeps(),
337
+ stepBareTest(),
317
338
  ],
318
- guidance_for_assistant: "Present these as a numbered list. If the user wants to see findings, call zivis_get_findings directly. " +
339
+ guidance_for_assistant: "Present these as a numbered list. If the user wants to see findings, call zivis_security_review directly. " +
340
+ "No open findings does not mean the project passed a test — say so explicitly if the count is zero. " +
319
341
  "If they ask 'why' something matters, expand on the 'why' field — do not make new claims.",
320
342
  if_user_unsure: "Recommend option 1 (view_open_findings) — let's see what ZIVIS already knows.",
321
343
  };
322
344
  }
323
- const steps = [];
324
- if (!state.has_application) {
325
- steps.push(stepSetupWebTarget());
326
- }
327
- steps.push(stepCheckDeps());
345
+ const steps = [stepBareTest(), stepCheckDeps()];
328
346
  if (state.has_findings) {
329
347
  steps.push(stepViewFindings(state.open_findings_count));
330
348
  }
331
349
  else {
332
- steps.push(stepBrowseTests());
350
+ steps.push(stepListScopes());
333
351
  }
334
- if (steps.length < 3)
335
- steps.push(stepBrowseTests());
352
+ if (!state.has_application)
353
+ steps.push(stepThreatModel());
336
354
  return {
337
- headline: state.has_application
338
- ? `ZIVIS is connected to your project (${state.org_name ?? "org"}). Here are the most useful things to do next.`
339
- : `ZIVIS is connected to your project (${state.org_name ?? "org"}) but no app has been registered for testing yet.`,
355
+ headline: `ZIVIS is connected to your project (${state.org_name ?? "org"}). Here are the most useful things to do next.`,
340
356
  recommended_next_steps: steps.slice(0, 4),
341
357
  guidance_for_assistant: "Present these as a numbered list. Ask the user to pick one before taking any action. " +
342
358
  "If they ask 'why' something matters, expand on the 'why' field — do not make new claims.",
343
- if_user_unsure: "Recommend option 2 (check_dependencies) — it's free, fast, and shows value without setup.",
359
+ if_user_unsure: "Recommend option 1 (run_test) — bare 'zivis test' is change-aware and the natural default entry point.",
344
360
  };
345
361
  }
346
362
  async function findRelevantThreats(cwd) {
@@ -1,6 +1,6 @@
1
1
  import type { ZivisConfig } from "../types.js";
2
2
  export declare const GET_TRUST_KEYS_NAME = "zivis_get_trust_keys";
3
- export declare const GET_TRUST_KEYS_DESCRIPTION = "Retrieve the ZIVIS public signing keys (JWKS) for independent cryptographic verification of trust marks and ZATs.\n\nReturns a JWKS (JSON Web Key Set) containing two keys:\n\n1. **ML-DSA-65 key** (post-quantum, FIPS-204):\n - Algorithm: CRYSTALS-Dilithium Level 3\n - NIST Security Category 3 (128-bit quantum security)\n - Used to verify the full digital signature on ZATs and trust marks\n - Key type: \"PQ-LWE\" (proposed post-quantum JWK key type)\n - The \"x\" field is the base64url-encoded public key bytes\n\n2. **Ed25519 key** (RFC 8032):\n - Used to verify compact trust tokens (shorter, URL-safe format)\n - Standard JWK format (kty: \"OKP\", crv: \"Ed25519\")\n\nThese keys enable third-party, offline verification without trusting ZIVIS infrastructure.\nThis is critical for ATNP (Agent Trust Negotiation Protocol) where agents must independently verify trust marks.\n\nVerification workflow:\n1. Get a ZAT (from zivis_get_oss_zat or zivis_get_org_zat)\n2. Get the public keys (this tool)\n3. Verify the signature using ML-DSA-65 or Ed25519 library of your choice\n4. Check expiration and claims\n\nNo parameters required. No authentication required.";
3
+ export declare const GET_TRUST_KEYS_DESCRIPTION = "Retrieve the ZIVIS public signing keys (JWKS) for independent cryptographic verification of trust marks and ZATs.\n\nReturns a JWKS (JSON Web Key Set) containing two keys:\n\n1. **ML-DSA-65 key** (post-quantum, FIPS-204):\n - Algorithm: CRYSTALS-Dilithium Level 3\n - NIST Security Category 3 (128-bit quantum security)\n - Used to verify the full digital signature on ZATs and trust marks\n - Key type: \"PQ-LWE\" (proposed post-quantum JWK key type)\n - The \"x\" field is the base64url-encoded public key bytes\n\n2. **Ed25519 key** (RFC 8032):\n - Used to verify compact trust tokens (shorter, URL-safe format)\n - Standard JWK format (kty: \"OKP\", crv: \"Ed25519\")\n\nThese keys enable third-party, offline verification without trusting ZIVIS infrastructure.\nThis is critical for ATNP (Agent Trust Negotiation Protocol) where agents must independently verify trust marks.\n\nVerification workflow:\n1. Get a ZAT (from zivis_get_org_zat)\n2. Get the public keys (this tool)\n3. Verify the signature using ML-DSA-65 or Ed25519 library of your choice\n4. Check expiration and claims\n\nNo parameters required. No authentication required.";
4
4
  export declare const GET_TRUST_KEYS_SCHEMA: {};
5
5
  export declare function createGetTrustKeysHandler(config: ZivisConfig): () => Promise<{
6
6
  content: {
@@ -18,7 +18,7 @@ These keys enable third-party, offline verification without trusting ZIVIS infra
18
18
  This is critical for ATNP (Agent Trust Negotiation Protocol) where agents must independently verify trust marks.
19
19
 
20
20
  Verification workflow:
21
- 1. Get a ZAT (from zivis_get_oss_zat or zivis_get_org_zat)
21
+ 1. Get a ZAT (from zivis_get_org_zat)
22
22
  2. Get the public keys (this tool)
23
23
  3. Verify the signature using ML-DSA-65 or Ed25519 library of your choice
24
24
  4. Check expiration and claims
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  export declare const INSPECT_ZAT_NAME = "zivis_inspect_zat";
3
- export declare const INSPECT_ZAT_DESCRIPTION = "Parse a ZIVIS Attestation Token (ZAT) JSON and produce a human-readable explanation of all fields.\n\nThis tool does NOT make any API calls \u2014 it parses the ZAT locally and explains what each field means.\n\nUse this after retrieving a ZAT from zivis_get_oss_zat or zivis_get_org_zat to understand:\n- What the claims mean (Z-Score, trust tiers, coverage, findings)\n- Whether signatures are present and which algorithms were used\n- Token validity and expiration\n- Evidence manifest integrity\n- Framework and methodology details\n- Lens-level scores (for OSS ZATs)\n\nAccepts either:\n- A JSON string (the raw ZAT output)\n- A JSON object with a \"zat\" field (the wrapper returned by the API)\n\nZAT Field Reference:\n- **iss**: Issuer (always \"zivis.ai\")\n- **sub**: Subject \u2014 \"org:<slug>\" for enterprise, \"github:<owner>/<repo>\" for OSS\n- **mark_id**: Unique identifier (ztm_...) \u2014 references the trust mark\n- **issued_at / expires_at**: ISO 8601 timestamps \u2014 ZATs are short-lived (48h)\n- **frameworks[]**: Which security frameworks were assessed (NIST IR 8596, ISO 42001, OWASP LLM Top 10, etc.)\n - basis: \"tested\" | \"mapped\" | \"self-attested\" | \"third-party\" \u2014 how the assessment was performed\n - csf_version: Present if framework is NIST CSF 2.0 derived (enables cross-framework comparison)\n- **claims**: The actual trust posture\n - For enterprise: z_score_raw (0-1), z_score_display (0-1000), tier (0-3), tier_label, coverage_pct, mapped_outcomes\n - For OSS: score (0-100), grade (A+ to F), check_types, findings by severity, commit SHA\n - Tier meanings: 0=Commitment, 1=Foundational Trust (600+), 2=Operational Trust (700+), 3=Systemic Trust (800+)\n- **evidence_manifest**: SHA-256 hash of the evidence bundle \u2014 proves the assessment data hasn't been tampered with\n- **methodology**: How the assessment was performed (model version, scoring algorithm, evaluator type)\n- **sig**: Cryptographic signatures\n - alg: \"ML-DSA-65\" (FIPS-204, post-quantum CRYSTALS-Dilithium Level 3)\n - compact: Ed25519 (RFC 8032) compact token for lightweight verification\n- **ver**: ZAT spec version (e.g., \"0.3.0\")";
3
+ export declare const INSPECT_ZAT_DESCRIPTION = "Parse a ZIVIS Attestation Token (ZAT) JSON and produce a human-readable explanation of all fields.\n\nThis tool does NOT make any API calls \u2014 it parses the ZAT locally and explains what each field means.\n\nUse this after retrieving a ZAT from zivis_get_org_zat to understand:\n- What the claims mean (Z-Score, trust tiers, coverage, findings)\n- Whether signatures are present and which algorithms were used\n- Token validity and expiration\n- Evidence manifest integrity\n- Framework and methodology details\n- Lens-level scores (for OSS ZATs)\n\nAccepts either:\n- A JSON string (the raw ZAT output)\n- A JSON object with a \"zat\" field (the wrapper returned by the API)\n\nZAT Field Reference:\n- **iss**: Issuer (always \"zivis.ai\")\n- **sub**: Subject \u2014 \"org:<slug>\" for enterprise, \"github:<owner>/<repo>\" for OSS\n- **mark_id**: Unique identifier (ztm_...) \u2014 references the trust mark\n- **issued_at / expires_at**: ISO 8601 timestamps \u2014 ZATs are short-lived (48h)\n- **frameworks[]**: Which security frameworks were assessed (NIST IR 8596, ISO 42001, OWASP LLM Top 10, etc.)\n - basis: \"tested\" | \"mapped\" | \"self-attested\" | \"third-party\" \u2014 how the assessment was performed\n - csf_version: Present if framework is NIST CSF 2.0 derived (enables cross-framework comparison)\n- **claims**: The actual trust posture\n - For enterprise: z_score_raw (0-1), z_score_display (0-1000), tier (0-3), tier_label, coverage_pct, mapped_outcomes\n - For OSS: score (0-100), grade (A+ to F), check_types, findings by severity, commit SHA\n - Tier meanings: 0=Commitment, 1=Foundational Trust (600+), 2=Operational Trust (700+), 3=Systemic Trust (800+)\n- **evidence_manifest**: SHA-256 hash of the evidence bundle \u2014 proves the assessment data hasn't been tampered with\n- **methodology**: How the assessment was performed (model version, scoring algorithm, evaluator type)\n- **sig**: Cryptographic signatures\n - alg: \"ML-DSA-65\" (FIPS-204, post-quantum CRYSTALS-Dilithium Level 3)\n - compact: Ed25519 (RFC 8032) compact token for lightweight verification\n- **ver**: ZAT spec version (e.g., \"0.3.0\")";
4
4
  export declare const INSPECT_ZAT_SCHEMA: {
5
5
  zat_json: z.ZodString;
6
6
  };
@@ -4,7 +4,7 @@ export const INSPECT_ZAT_DESCRIPTION = `Parse a ZIVIS Attestation Token (ZAT) JS
4
4
 
5
5
  This tool does NOT make any API calls — it parses the ZAT locally and explains what each field means.
6
6
 
7
- Use this after retrieving a ZAT from zivis_get_oss_zat or zivis_get_org_zat to understand:
7
+ Use this after retrieving a ZAT from zivis_get_org_zat to understand:
8
8
  - What the claims mean (Z-Score, trust tiers, coverage, findings)
9
9
  - Whether signatures are present and which algorithms were used
10
10
  - Token validity and expiration
@@ -37,7 +37,7 @@ ZAT Field Reference:
37
37
  export const INSPECT_ZAT_SCHEMA = {
38
38
  zat_json: z
39
39
  .string()
40
- .describe("The ZAT JSON string to inspect (from zivis_get_oss_zat or zivis_get_org_zat output)"),
40
+ .describe("The ZAT JSON string to inspect (from zivis_get_org_zat output)"),
41
41
  };
42
42
  export function createInspectZatHandler() {
43
43
  return async (params) => {
@@ -2,14 +2,12 @@ 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 SECURITY_REVIEW_NAME = "zivis_security_review";
5
- export declare const SECURITY_REVIEW_DESCRIPTION = "Gather ZIVIS security intelligence for an AI-powered code review.\n\nPulls historical findings and open vulnerabilities to give you comprehensive security context. Use this BEFORE reviewing code to understand:\n\n1. **Regression risks** \u2014 Previously fixed vulnerabilities that could be reintroduced\n2. **Known vulnerabilities** \u2014 Open findings that may be relevant to the code being reviewed\n3. **Dependency risks** \u2014 OSS trust scores for dependencies in the code\n\nReturns structured security context that you should reference during code review. Focus on:\n- Code that touches areas where historical findings were fixed (regression check)\n- Use of low-trust dependencies\n\nProvide at least one of: repo, application_id, or campaign_id.";
5
+ export declare const SECURITY_REVIEW_DESCRIPTION = "Gather ZIVIS security intelligence for an AI-powered code review.\n\nPulls historical findings and open vulnerabilities to give you comprehensive security context. Use this BEFORE reviewing code to understand:\n\n1. **Regression risks** \u2014 Previously fixed vulnerabilities that could be reintroduced\n2. **Known vulnerabilities** \u2014 Open findings that may be relevant to the code being reviewed\n\nReturns structured security context that you should reference during code review. Focus on:\n- Code that touches areas where historical findings were fixed (regression check)\n\nFor dependency risk, use `zivis test dependencies` instead \u2014 this tool no longer checks dependencies.\n\nProvide at least one of: repo or application_id.";
6
6
  export declare const SECURITY_REVIEW_SCHEMA: {
7
7
  repo: z.ZodOptional<z.ZodString>;
8
8
  application_id: z.ZodOptional<z.ZodString>;
9
- campaign_id: z.ZodOptional<z.ZodString>;
10
9
  focus_areas: z.ZodOptional<z.ZodArray<z.ZodEnum<{
11
10
  regression: "regression";
12
- dependencies: "dependencies";
13
11
  all: "all";
14
12
  }>>>;
15
13
  severity_threshold: z.ZodOptional<z.ZodEnum<{
@@ -20,16 +18,13 @@ export declare const SECURITY_REVIEW_SCHEMA: {
20
18
  info: "info";
21
19
  }>>;
22
20
  include_resolved: z.ZodDefault<z.ZodBoolean>;
23
- dependency_list: z.ZodOptional<z.ZodArray<z.ZodString>>;
24
21
  };
25
- export declare function createSecurityReviewHandler(apiClient: ApiClient, config: ZivisConfig): (params: {
22
+ export declare function createSecurityReviewHandler(apiClient: ApiClient, _config: ZivisConfig): (params: {
26
23
  repo?: string;
27
24
  application_id?: string;
28
- campaign_id?: string;
29
25
  focus_areas?: string[];
30
26
  severity_threshold?: string;
31
27
  include_resolved?: boolean;
32
- dependency_list?: string[];
33
28
  }) => Promise<{
34
29
  content: {
35
30
  type: "text";
@@ -8,22 +8,21 @@ Pulls historical findings and open vulnerabilities to give you comprehensive sec
8
8
 
9
9
  1. **Regression risks** — Previously fixed vulnerabilities that could be reintroduced
10
10
  2. **Known vulnerabilities** — Open findings that may be relevant to the code being reviewed
11
- 3. **Dependency risks** — OSS trust scores for dependencies in the code
12
11
 
13
12
  Returns structured security context that you should reference during code review. Focus on:
14
13
  - Code that touches areas where historical findings were fixed (regression check)
15
- - Use of low-trust dependencies
16
14
 
17
- Provide at least one of: repo, application_id, or campaign_id.`;
15
+ For dependency risk, use \`zivis test dependencies\` instead — this tool no longer checks dependencies.
16
+
17
+ Provide at least one of: repo or application_id.`;
18
18
  export const SECURITY_REVIEW_SCHEMA = {
19
- repo: z.string().optional().describe("Repository name (owner/repo) — pulls findings and OSS trust data"),
19
+ repo: z.string().optional().describe("Repository name (owner/repo) — pulls findings scoped to this repo"),
20
20
  application_id: z
21
21
  .string()
22
22
  .optional()
23
23
  .describe("Application UUID — pulls findings scoped to this app. If omitted, uses applicationId from .zivis/project.json when set."),
24
- campaign_id: z.string().optional().describe("Campaign UUID — pulls campaign-specific findings"),
25
24
  focus_areas: z
26
- .array(z.enum(["regression", "dependencies", "all"]))
25
+ .array(z.enum(["regression", "all"]))
27
26
  .optional()
28
27
  .describe("Which intelligence to gather (default: all)"),
29
28
  severity_threshold: z
@@ -34,10 +33,6 @@ export const SECURITY_REVIEW_SCHEMA = {
34
33
  .boolean()
35
34
  .default(true)
36
35
  .describe("Include resolved findings for regression checking (default: true)"),
37
- dependency_list: z
38
- .array(z.string())
39
- .optional()
40
- .describe("Specific dependencies to check trust scores for (owner/repo format)"),
41
36
  };
42
37
  const SEVERITY_ORDER = {
43
38
  critical: 5,
@@ -46,16 +41,17 @@ const SEVERITY_ORDER = {
46
41
  low: 2,
47
42
  info: 1,
48
43
  };
49
- export function createSecurityReviewHandler(apiClient, config) {
44
+ export function createSecurityReviewHandler(apiClient, _config) {
50
45
  return async (params) => {
51
- const { repo, application_id: application_idParam, campaign_id, focus_areas = ["all"], severity_threshold = "low", include_resolved = true, dependency_list, } = params;
46
+ const { repo, application_id: application_idParam, focus_areas = ["all"], severity_threshold = "low", include_resolved = true, } = params;
52
47
  const application_id = resolveApplicationId(application_idParam);
53
- if (!repo && !application_id && !campaign_id) {
48
+ if (!repo && !application_id) {
54
49
  return {
55
50
  content: [{
56
51
  type: "text",
57
- text: "Error: Provide at least one of: repo, application_id, or campaign_id " +
58
- "(or set applicationId in .zivis/project.json for default app scope)",
52
+ text: "Error: Provide at least one of: repo or application_id " +
53
+ "or run `zivis init` to connect this repository to a ZIVIS Application " +
54
+ "so application_id resolves automatically.",
59
55
  }],
60
56
  isError: true,
61
57
  };
@@ -64,7 +60,7 @@ export function createSecurityReviewHandler(apiClient, config) {
64
60
  const context = {
65
61
  _description: "ZIVIS Security Review Context — use this intelligence during code review",
66
62
  generatedAt: new Date().toISOString(),
67
- parameters: { repo, application_id, campaign_id },
63
+ parameters: { repo, application_id },
68
64
  };
69
65
  const errors = [];
70
66
  if (shouldInclude("regression") && (repo || application_id)) {
@@ -112,65 +108,6 @@ export function createSecurityReviewHandler(apiClient, config) {
112
108
  errors.push(`Open findings: ${err instanceof Error ? err.message : "failed"}`);
113
109
  }
114
110
  }
115
- if (shouldInclude("dependencies") && dependency_list && dependency_list.length > 0) {
116
- const depResults = [];
117
- const baseUrl = config.apiBaseUrl;
118
- for (const dep of dependency_list.slice(0, 10)) {
119
- try {
120
- const parsed = parseRepo(dep);
121
- if (!parsed) {
122
- depResults.push({ repo: dep, error: "Invalid format" });
123
- continue;
124
- }
125
- const res = await fetch(`${baseUrl}/api/oss-trust/repos/${parsed.owner}/${parsed.repo}`);
126
- if (res.ok) {
127
- const entry = await res.json();
128
- depResults.push({
129
- repo: dep,
130
- trustGrade: entry.trustGrade,
131
- trustScore: entry.trustScore,
132
- findings: {
133
- critical: entry.findingsCritical ?? 0,
134
- high: entry.findingsHigh ?? 0,
135
- medium: entry.findingsMedium ?? 0,
136
- low: entry.findingsLow ?? 0,
137
- },
138
- lastScanned: entry.lastScannedAt,
139
- });
140
- }
141
- else {
142
- depResults.push({ repo: dep, trustGrade: "unscanned", trustScore: null });
143
- }
144
- }
145
- catch {
146
- depResults.push({ repo: dep, error: "Failed to fetch" });
147
- }
148
- }
149
- const risky = depResults.filter((d) => d.trustScore != null && d.trustScore < 70);
150
- context.dependencyRisks = {
151
- _instruction: "Flag usage of low-trust dependencies. Consider alternatives for dependencies with grade C or below.",
152
- checked: depResults.length,
153
- riskyCount: risky.length,
154
- dependencies: depResults,
155
- };
156
- }
157
- if (campaign_id) {
158
- try {
159
- const campaignFindings = await apiClient.get(`/api/campaigns/${campaign_id}/findings?limit=50`);
160
- const findings = campaignFindings.findings || [];
161
- const minSeverity = SEVERITY_ORDER[severity_threshold] || 2;
162
- const filtered = findings.filter((f) => (SEVERITY_ORDER[f.severity] || 1) >= minSeverity);
163
- context.campaignFindings = {
164
- _instruction: "These findings are from active security testing campaigns. Check if code changes address or affect these.",
165
- count: filtered.length,
166
- bySeverity: countBySeverity(filtered),
167
- findings: filtered.slice(0, 20).map(summarizeFinding),
168
- };
169
- }
170
- catch (err) {
171
- errors.push(`Campaign findings: ${err instanceof Error ? err.message : "failed"}`);
172
- }
173
- }
174
111
  context.reviewGuidance = buildReviewGuidance(context);
175
112
  if (errors.length > 0) {
176
113
  context.warnings = errors;
@@ -255,24 +192,8 @@ function buildReviewGuidance(context) {
255
192
  if (open?.count > 0) {
256
193
  guidance.push(`OPEN VULNS: ${open.count} known vulnerabilities (${open.bySeverity?.critical || 0} critical, ${open.bySeverity?.high || 0} high). Verify changes don't worsen these.`);
257
194
  }
258
- const deps = context.dependencyRisks;
259
- if (deps?.riskyCount > 0) {
260
- guidance.push(`RISKY DEPS: ${deps.riskyCount} dependencies with low trust scores. Consider alternatives.`);
261
- }
262
195
  if (guidance.length === 0) {
263
196
  guidance.push("No significant security context found. Perform standard code review best practices.");
264
197
  }
265
198
  return guidance;
266
199
  }
267
- function parseRepo(input) {
268
- const trimmed = input.trim();
269
- const urlMatch = trimmed.match(/^https?:\/\/(?:www\.)?github\.com\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)/);
270
- if (urlMatch) {
271
- return { owner: urlMatch[1], repo: urlMatch[2].replace(/\.git$/, "") };
272
- }
273
- const slashMatch = trimmed.match(/^([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)$/);
274
- if (slashMatch) {
275
- return { owner: slashMatch[1], repo: slashMatch[2] };
276
- }
277
- return null;
278
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zivis/mcp",
3
- "version": "0.1.12",
3
+ "version": "0.1.18",
4
4
  "description": "ZIVIS MCP server — threat modeling, security scans, and AI red team tools for IDE integration",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://zivis.ai",
@@ -43,12 +43,12 @@
43
43
  "build:pattern-pack": "tsx ../scripts/build-pattern-pack.ts",
44
44
  "build": "tsc -p tsconfig.build.json && pnpm run build:pattern-pack && node scripts/ensure-symlink.cjs",
45
45
  "prepublishOnly": "rm -rf dist && pnpm run build",
46
- "postpublish": "node -e \"const p=require('./package.json'); require('child_process').execSync('npm dist-tag add '+p.name+'@'+p.version+' latest',{stdio:'inherit'});\"",
47
46
  "dev": "tsc --watch",
48
47
  "start": "node dist/index.js",
49
48
  "test": "vitest run",
50
49
  "test:watch": "vitest",
51
50
  "lint": "tsc --noEmit",
51
+ "check:drift": "tsx scripts/check-drift.ts",
52
52
  "build:installer": "bash scripts/build-installer.sh"
53
53
  },
54
54
  "engines": {