safety-agent-mcp 0.1.0 → 0.1.2
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/index.js +94 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +110 -1
- package/tests/scan.test.ts +30 -0
package/dist/index.js
CHANGED
|
@@ -49,6 +49,22 @@ const RedactInputSchema = z
|
|
|
49
49
|
.describe("When true, naturally rewrite content to remove sensitive information instead of using placeholders. For example, 'Contact me at john@example.com' becomes 'Contact me via email' instead of 'Contact me at <EMAIL_REDACTED>'."),
|
|
50
50
|
})
|
|
51
51
|
.strict();
|
|
52
|
+
const ScanInputSchema = z
|
|
53
|
+
.object({
|
|
54
|
+
repo: z
|
|
55
|
+
.string()
|
|
56
|
+
.min(1, "Repository URL cannot be empty")
|
|
57
|
+
.describe("The Git repository URL to scan for AI agent-targeted attacks. Must start with https:// or git@. Examples: 'https://github.com/user/repo', 'git@github.com:user/repo.git'"),
|
|
58
|
+
branch: z
|
|
59
|
+
.string()
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Optional branch, tag, or commit SHA to checkout. If not provided, defaults to the repository's default branch."),
|
|
62
|
+
model: z
|
|
63
|
+
.string()
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("Optional model to use for analysis in 'provider/model' format. Default: 'anthropic/claude-sonnet-4-5'. Examples: 'openai/gpt-4o', 'anthropic/claude-3-opus'"),
|
|
66
|
+
})
|
|
67
|
+
.strict();
|
|
52
68
|
// ============================================================================
|
|
53
69
|
// MCP Server Setup
|
|
54
70
|
// ============================================================================
|
|
@@ -198,6 +214,83 @@ Common Entity Types:
|
|
|
198
214
|
}
|
|
199
215
|
});
|
|
200
216
|
// ============================================================================
|
|
217
|
+
// Tool: superagent_scan
|
|
218
|
+
// ============================================================================
|
|
219
|
+
server.registerTool("superagent_scan", {
|
|
220
|
+
title: "Superagent Repository Scanner",
|
|
221
|
+
description: `Scan a Git repository for AI agent-targeted attacks like repo poisoning, prompt injection, and malicious instructions using Superagent's security scanning.
|
|
222
|
+
|
|
223
|
+
This tool clones a repository into a secure sandbox and uses AI to analyze its contents for security threats that could exploit AI agents or coding assistants.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
- repo (string): The Git repository URL to scan. Must start with https:// or git@.
|
|
227
|
+
- branch (string, optional): Branch, tag, or commit to checkout. Defaults to the repository's default branch.
|
|
228
|
+
- model (string, optional): Model to use for analysis (provider/model format). Default: 'anthropic/claude-sonnet-4-5'.
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
A security report containing findings about potential threats in the repository, along with usage metrics.
|
|
232
|
+
|
|
233
|
+
Examples:
|
|
234
|
+
- Use when: Evaluating a third-party repository before integrating it
|
|
235
|
+
- Use when: "Scan https://github.com/user/repo for security issues"
|
|
236
|
+
- Use when: Checking for malicious code that could poison AI training or exploit AI agents
|
|
237
|
+
- Use when: Auditing dependencies for prompt injection attacks
|
|
238
|
+
- Don't use when: You need real-time input validation (use superagent_guard instead)
|
|
239
|
+
|
|
240
|
+
Threat Types Detected:
|
|
241
|
+
- repo_poisoning: Malicious code designed to exploit AI agents or training data
|
|
242
|
+
- prompt_injection: Hidden instructions that could manipulate AI behavior
|
|
243
|
+
- data_exfiltration: Code that attempts to steal data through AI interactions
|
|
244
|
+
- malicious_instructions: Concealed commands in comments, docs, or configuration`,
|
|
245
|
+
inputSchema: ScanInputSchema.shape,
|
|
246
|
+
annotations: {
|
|
247
|
+
readOnlyHint: true,
|
|
248
|
+
destructiveHint: false,
|
|
249
|
+
idempotentHint: true,
|
|
250
|
+
openWorldHint: true,
|
|
251
|
+
},
|
|
252
|
+
}, async (params) => {
|
|
253
|
+
try {
|
|
254
|
+
// Check for DAYTONA_API_KEY
|
|
255
|
+
if (!process.env.DAYTONA_API_KEY) {
|
|
256
|
+
return {
|
|
257
|
+
content: [
|
|
258
|
+
{
|
|
259
|
+
type: "text",
|
|
260
|
+
text: "Error: DAYTONA_API_KEY environment variable is required for repository scanning. Get your API key at https://daytona.io",
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
// Call Superagent Scan API using SDK
|
|
266
|
+
const result = await client.scan({
|
|
267
|
+
repo: params.repo,
|
|
268
|
+
branch: params.branch,
|
|
269
|
+
model: params.model,
|
|
270
|
+
});
|
|
271
|
+
// Return the scan result as JSON
|
|
272
|
+
return {
|
|
273
|
+
content: [
|
|
274
|
+
{
|
|
275
|
+
type: "text",
|
|
276
|
+
text: JSON.stringify(result, null, 2),
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
283
|
+
return {
|
|
284
|
+
content: [
|
|
285
|
+
{
|
|
286
|
+
type: "text",
|
|
287
|
+
text: `Error: ${errorMessage}`,
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
// ============================================================================
|
|
201
294
|
// Main Function
|
|
202
295
|
// ============================================================================
|
|
203
296
|
async function main() {
|
|
@@ -216,7 +309,7 @@ async function main() {
|
|
|
216
309
|
await server.connect(transport);
|
|
217
310
|
// Log to stderr (stdout is reserved for MCP protocol)
|
|
218
311
|
console.error("Superagent MCP server running via stdio");
|
|
219
|
-
console.error("Tools available: superagent_guard, superagent_redact");
|
|
312
|
+
console.error("Tools available: superagent_guard, superagent_redact, superagent_scan");
|
|
220
313
|
}
|
|
221
314
|
// Run the server
|
|
222
315
|
main().catch((error) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+EAA+E;AAC/E,+BAA+B;AAC/B,+EAA+E;AAE/E,MAAM,MAAM,GAAG,YAAY,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAmB;CACxC,CAAC,CAAC;AAEH,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E,MAAM,gBAAgB,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,EAAE,sBAAsB,CAAC;SAC9B,GAAG,CAAC,KAAK,EAAE,kDAAkD,CAAC;SAC9D,QAAQ,CACP,sPAAsP,CACvP;IACH,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,kOAAkO,CACnO;CACJ,CAAC;KACD,MAAM,EAAE,CAAC;AAIZ,MAAM,iBAAiB,GAAG,CAAC;KACxB,MAAM,CAAC;IACN,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,EAAE,sBAAsB,CAAC;SAC9B,GAAG,CAAC,KAAK,EAAE,kDAAkD,CAAC;SAC9D,QAAQ,CACP,kFAAkF,CACnF;IACH,QAAQ,EAAE,CAAC;SACR,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CACP,qOAAqO,CACtO;IACH,OAAO,EAAE,CAAC;SACP,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,+NAA+N,CAChO;CACJ,CAAC;KACD,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "safety-agent-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "MCP server for Superagent.sh API integration - security guardrails, PII redaction, and claim verification",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.6.1",
|
|
36
|
-
"safety-agent": "^0.1.
|
|
36
|
+
"safety-agent": "^0.1.3",
|
|
37
37
|
"zod": "^3.23.8"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -70,6 +70,30 @@ const RedactInputSchema = z
|
|
|
70
70
|
|
|
71
71
|
type RedactInput = z.infer<typeof RedactInputSchema>;
|
|
72
72
|
|
|
73
|
+
const ScanInputSchema = z
|
|
74
|
+
.object({
|
|
75
|
+
repo: z
|
|
76
|
+
.string()
|
|
77
|
+
.min(1, "Repository URL cannot be empty")
|
|
78
|
+
.describe(
|
|
79
|
+
"The Git repository URL to scan for AI agent-targeted attacks. Must start with https:// or git@. Examples: 'https://github.com/user/repo', 'git@github.com:user/repo.git'"
|
|
80
|
+
),
|
|
81
|
+
branch: z
|
|
82
|
+
.string()
|
|
83
|
+
.optional()
|
|
84
|
+
.describe(
|
|
85
|
+
"Optional branch, tag, or commit SHA to checkout. If not provided, defaults to the repository's default branch."
|
|
86
|
+
),
|
|
87
|
+
model: z
|
|
88
|
+
.string()
|
|
89
|
+
.optional()
|
|
90
|
+
.describe(
|
|
91
|
+
"Optional model to use for analysis in 'provider/model' format. Default: 'anthropic/claude-sonnet-4-5'. Examples: 'openai/gpt-4o', 'anthropic/claude-3-opus'"
|
|
92
|
+
),
|
|
93
|
+
})
|
|
94
|
+
.strict();
|
|
95
|
+
|
|
96
|
+
type ScanInput = z.infer<typeof ScanInputSchema>;
|
|
73
97
|
|
|
74
98
|
// ============================================================================
|
|
75
99
|
// MCP Server Setup
|
|
@@ -235,6 +259,91 @@ Common Entity Types:
|
|
|
235
259
|
}
|
|
236
260
|
);
|
|
237
261
|
|
|
262
|
+
// ============================================================================
|
|
263
|
+
// Tool: superagent_scan
|
|
264
|
+
// ============================================================================
|
|
265
|
+
|
|
266
|
+
server.registerTool(
|
|
267
|
+
"superagent_scan",
|
|
268
|
+
{
|
|
269
|
+
title: "Superagent Repository Scanner",
|
|
270
|
+
description: `Scan a Git repository for AI agent-targeted attacks like repo poisoning, prompt injection, and malicious instructions using Superagent's security scanning.
|
|
271
|
+
|
|
272
|
+
This tool clones a repository into a secure sandbox and uses AI to analyze its contents for security threats that could exploit AI agents or coding assistants.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
- repo (string): The Git repository URL to scan. Must start with https:// or git@.
|
|
276
|
+
- branch (string, optional): Branch, tag, or commit to checkout. Defaults to the repository's default branch.
|
|
277
|
+
- model (string, optional): Model to use for analysis (provider/model format). Default: 'anthropic/claude-sonnet-4-5'.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
A security report containing findings about potential threats in the repository, along with usage metrics.
|
|
281
|
+
|
|
282
|
+
Examples:
|
|
283
|
+
- Use when: Evaluating a third-party repository before integrating it
|
|
284
|
+
- Use when: "Scan https://github.com/user/repo for security issues"
|
|
285
|
+
- Use when: Checking for malicious code that could poison AI training or exploit AI agents
|
|
286
|
+
- Use when: Auditing dependencies for prompt injection attacks
|
|
287
|
+
- Don't use when: You need real-time input validation (use superagent_guard instead)
|
|
288
|
+
|
|
289
|
+
Threat Types Detected:
|
|
290
|
+
- repo_poisoning: Malicious code designed to exploit AI agents or training data
|
|
291
|
+
- prompt_injection: Hidden instructions that could manipulate AI behavior
|
|
292
|
+
- data_exfiltration: Code that attempts to steal data through AI interactions
|
|
293
|
+
- malicious_instructions: Concealed commands in comments, docs, or configuration`,
|
|
294
|
+
inputSchema: ScanInputSchema.shape,
|
|
295
|
+
annotations: {
|
|
296
|
+
readOnlyHint: true,
|
|
297
|
+
destructiveHint: false,
|
|
298
|
+
idempotentHint: true,
|
|
299
|
+
openWorldHint: true,
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
async (params: ScanInput) => {
|
|
303
|
+
try {
|
|
304
|
+
// Check for DAYTONA_API_KEY
|
|
305
|
+
if (!process.env.DAYTONA_API_KEY) {
|
|
306
|
+
return {
|
|
307
|
+
content: [
|
|
308
|
+
{
|
|
309
|
+
type: "text",
|
|
310
|
+
text: "Error: DAYTONA_API_KEY environment variable is required for repository scanning. Get your API key at https://daytona.io",
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Call Superagent Scan API using SDK
|
|
317
|
+
const result = await client.scan({
|
|
318
|
+
repo: params.repo,
|
|
319
|
+
branch: params.branch,
|
|
320
|
+
model: params.model as any,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// Return the scan result as JSON
|
|
324
|
+
return {
|
|
325
|
+
content: [
|
|
326
|
+
{
|
|
327
|
+
type: "text",
|
|
328
|
+
text: JSON.stringify(result, null, 2),
|
|
329
|
+
},
|
|
330
|
+
],
|
|
331
|
+
};
|
|
332
|
+
} catch (error) {
|
|
333
|
+
const errorMessage =
|
|
334
|
+
error instanceof Error ? error.message : String(error);
|
|
335
|
+
return {
|
|
336
|
+
content: [
|
|
337
|
+
{
|
|
338
|
+
type: "text",
|
|
339
|
+
text: `Error: ${errorMessage}`,
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
);
|
|
346
|
+
|
|
238
347
|
// ============================================================================
|
|
239
348
|
// Main Function
|
|
240
349
|
// ============================================================================
|
|
@@ -261,7 +370,7 @@ async function main() {
|
|
|
261
370
|
// Log to stderr (stdout is reserved for MCP protocol)
|
|
262
371
|
console.error("Superagent MCP server running via stdio");
|
|
263
372
|
console.error(
|
|
264
|
-
"Tools available: superagent_guard, superagent_redact"
|
|
373
|
+
"Tools available: superagent_guard, superagent_redact, superagent_scan"
|
|
265
374
|
);
|
|
266
375
|
}
|
|
267
376
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { createClient } from "safety-agent";
|
|
3
|
+
|
|
4
|
+
const DAYTONA_API_KEY = process.env.DAYTONA_API_KEY;
|
|
5
|
+
const SUPERAGENT_API_KEY = process.env.SUPERAGENT_API_KEY;
|
|
6
|
+
|
|
7
|
+
const skipIfNoCredentials = !DAYTONA_API_KEY || !SUPERAGENT_API_KEY;
|
|
8
|
+
|
|
9
|
+
describe.skipIf(skipIfNoCredentials)("scan", () => {
|
|
10
|
+
const client = createClient();
|
|
11
|
+
|
|
12
|
+
it("returns valid response structure for repository scan", { timeout: 300000 }, async () => {
|
|
13
|
+
const result = await client.scan({
|
|
14
|
+
repo: "https://github.com/superagent-ai/superagent-starter",
|
|
15
|
+
branch: "main",
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Verify response structure
|
|
19
|
+
expect(result).toHaveProperty("result");
|
|
20
|
+
expect(result).toHaveProperty("usage");
|
|
21
|
+
expect(typeof result.result).toBe("string");
|
|
22
|
+
expect(result.result.length).toBeGreaterThan(0);
|
|
23
|
+
|
|
24
|
+
// Verify usage structure
|
|
25
|
+
expect(typeof result.usage.inputTokens).toBe("number");
|
|
26
|
+
expect(typeof result.usage.outputTokens).toBe("number");
|
|
27
|
+
expect(typeof result.usage.reasoningTokens).toBe("number");
|
|
28
|
+
expect(typeof result.usage.cost).toBe("number");
|
|
29
|
+
});
|
|
30
|
+
});
|