@kya-os/create-mcpi-app 1.9.32 → 1.9.34
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/.turbo/turbo-build.log +27 -2
- package/.turbo/turbo-test$colon$coverage.log +1829 -0
- package/.turbo/turbo-test.log +260 -220
- package/dist/bundles/blank.js +112104 -0
- package/dist/bundles/ecommerce.js +112178 -0
- package/dist/bundles/hardware-world.js +112576 -0
- package/dist/bundles/manifest.json +28 -0
- package/dist/bundles/mix-station.js +112480 -0
- package/dist/cli-runner.d.ts.map +1 -1
- package/dist/cli-runner.js +23 -0
- package/dist/cli-runner.js.map +1 -1
- package/dist/helpers/fetch-cloudflare-mcpi-template.js +1 -1
- package/dist/helpers/generate-cloudflare-files.d.ts +1 -1
- package/dist/helpers/generate-cloudflare-files.d.ts.map +1 -1
- package/dist/helpers/generate-cloudflare-files.js +457 -41
- package/dist/helpers/generate-cloudflare-files.js.map +1 -1
- package/dist/helpers/generate-openapi-project.d.ts +36 -0
- package/dist/helpers/generate-openapi-project.d.ts.map +1 -0
- package/dist/helpers/generate-openapi-project.js +114 -0
- package/dist/helpers/generate-openapi-project.js.map +1 -0
- package/dist/helpers/generate-openapi-tools.d.ts +43 -0
- package/dist/helpers/generate-openapi-tools.d.ts.map +1 -0
- package/dist/helpers/generate-openapi-tools.js +550 -0
- package/dist/helpers/generate-openapi-tools.js.map +1 -0
- package/dist/helpers/generate-runtime-config.d.ts +16 -0
- package/dist/helpers/generate-runtime-config.d.ts.map +1 -0
- package/dist/helpers/generate-runtime-config.js +49 -0
- package/dist/helpers/generate-runtime-config.js.map +1 -0
- package/dist/helpers/get-package-versions.js +8 -8
- package/dist/helpers/get-package-versions.js.map +1 -1
- package/dist/helpers/openapi-ingestion.d.ts +21 -0
- package/dist/helpers/openapi-ingestion.d.ts.map +1 -0
- package/dist/helpers/openapi-ingestion.js +433 -0
- package/dist/helpers/openapi-ingestion.js.map +1 -0
- package/dist/helpers/wrap/command.d.ts +12 -0
- package/dist/helpers/wrap/command.d.ts.map +1 -0
- package/dist/helpers/wrap/command.js +344 -0
- package/dist/helpers/wrap/command.js.map +1 -0
- package/dist/helpers/wrap/detect-server.d.ts +30 -0
- package/dist/helpers/wrap/detect-server.d.ts.map +1 -0
- package/dist/helpers/wrap/detect-server.js +207 -0
- package/dist/helpers/wrap/detect-server.js.map +1 -0
- package/dist/helpers/wrap/index.d.ts +13 -0
- package/dist/helpers/wrap/index.d.ts.map +1 -0
- package/dist/helpers/wrap/index.js +11 -0
- package/dist/helpers/wrap/index.js.map +1 -0
- package/dist/helpers/wrap/templates.d.ts +24 -0
- package/dist/helpers/wrap/templates.d.ts.map +1 -0
- package/dist/helpers/wrap/templates.js +221 -0
- package/dist/helpers/wrap/templates.js.map +1 -0
- package/dist/types/openapi-generator.d.ts +142 -0
- package/dist/types/openapi-generator.d.ts.map +1 -0
- package/dist/types/openapi-generator.js +8 -0
- package/dist/types/openapi-generator.js.map +1 -0
- package/package.json +35 -9
|
@@ -53,8 +53,8 @@ const UNIFIED_KV_BINDING = "MCPI_KV";
|
|
|
53
53
|
*/
|
|
54
54
|
export async function generateCloudflareProjectFiles(options) {
|
|
55
55
|
const { projectName, template = "blank", agentShieldProjectId, agentShieldApiUrl = "https://kya.vouched.id", agentShieldApiKey, skipIdentity = false, serverUrl, } = options;
|
|
56
|
-
|
|
57
|
-
const
|
|
56
|
+
// Standard DO class name for all templates (no more per-project PascalCase names)
|
|
57
|
+
const doClassName = "MCPIAgent";
|
|
58
58
|
// Get package versions from scaffolder's package.json (single source of truth)
|
|
59
59
|
// This ensures scaffolded projects use tested, consistent versions
|
|
60
60
|
const versions = await getPackageVersions();
|
|
@@ -98,7 +98,7 @@ export async function generateCloudflareProjectFiles(options) {
|
|
|
98
98
|
"@modelcontextprotocol/sdk": "1.25.2",
|
|
99
99
|
// agents@0.3.x removed 'ai' from direct deps, fixing Redis bundling issue
|
|
100
100
|
agents: "0.3.6",
|
|
101
|
-
hono: "4.
|
|
101
|
+
hono: "4.12.4",
|
|
102
102
|
},
|
|
103
103
|
devDependencies: {
|
|
104
104
|
"@cloudflare/vitest-pool-workers": "^0.5.41",
|
|
@@ -116,8 +116,7 @@ export async function generateCloudflareProjectFiles(options) {
|
|
|
116
116
|
path: "wrangler.toml",
|
|
117
117
|
content: generateWranglerToml({
|
|
118
118
|
projectName,
|
|
119
|
-
|
|
120
|
-
pascalCaseName,
|
|
119
|
+
doClassName,
|
|
121
120
|
agentDid: identity.did,
|
|
122
121
|
publicKey: identity.publicKey,
|
|
123
122
|
agentShieldProjectId,
|
|
@@ -180,13 +179,13 @@ dist/
|
|
|
180
179
|
// 6. src/index.ts
|
|
181
180
|
files.push({
|
|
182
181
|
path: "src/index.ts",
|
|
183
|
-
content: generateIndexTs(
|
|
182
|
+
content: generateIndexTs(doClassName),
|
|
184
183
|
encoding: "utf-8",
|
|
185
184
|
});
|
|
186
185
|
// 7. src/agent.ts
|
|
187
186
|
files.push({
|
|
188
187
|
path: "src/agent.ts",
|
|
189
|
-
content: generateAgentTs(projectName,
|
|
188
|
+
content: generateAgentTs(projectName, doClassName),
|
|
190
189
|
encoding: "utf-8",
|
|
191
190
|
});
|
|
192
191
|
// 8. src/mcpi-runtime-config.ts
|
|
@@ -195,12 +194,15 @@ dist/
|
|
|
195
194
|
content: generateRuntimeConfigTs(template),
|
|
196
195
|
encoding: "utf-8",
|
|
197
196
|
});
|
|
198
|
-
// 9. src/tools/greet.ts (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
197
|
+
// 9. src/tools/greet.ts (included for templates that use it)
|
|
198
|
+
// mix-station has its own tool set and doesn't use greet
|
|
199
|
+
if (template !== "mix-station") {
|
|
200
|
+
files.push({
|
|
201
|
+
path: "src/tools/greet.ts",
|
|
202
|
+
content: generateGreetToolTs(projectName),
|
|
203
|
+
encoding: "utf-8",
|
|
204
|
+
});
|
|
205
|
+
}
|
|
204
206
|
// 10. Add template-specific tools
|
|
205
207
|
if (template === "ecommerce") {
|
|
206
208
|
files.push(...generateEcommerceTools());
|
|
@@ -208,6 +210,9 @@ dist/
|
|
|
208
210
|
else if (template === "hardware-world") {
|
|
209
211
|
files.push(...generateHardwareWorldTools());
|
|
210
212
|
}
|
|
213
|
+
else if (template === "mix-station") {
|
|
214
|
+
files.push(...generateMixStationTools());
|
|
215
|
+
}
|
|
211
216
|
// 11. GitHub Actions workflow
|
|
212
217
|
files.push({
|
|
213
218
|
path: ".github/workflows/deploy.yml",
|
|
@@ -242,26 +247,20 @@ dist/
|
|
|
242
247
|
// ============================================================================
|
|
243
248
|
// Helper Functions
|
|
244
249
|
// ============================================================================
|
|
245
|
-
function toPascalCase(str) {
|
|
246
|
-
const result = str
|
|
247
|
-
.replace(/(?:^\w|[A-Z]|\b\w)/g, (word) => word.toUpperCase())
|
|
248
|
-
.replace(/\s+/g, "")
|
|
249
|
-
.replace(/-/g, "")
|
|
250
|
-
.replace(/[^a-zA-Z0-9]/g, "");
|
|
251
|
-
let className = result || "Project";
|
|
252
|
-
if (/^\d/.test(className)) {
|
|
253
|
-
className = "_" + className;
|
|
254
|
-
}
|
|
255
|
-
return className;
|
|
256
|
-
}
|
|
257
250
|
function generateWranglerToml(opts) {
|
|
258
|
-
const { projectName,
|
|
251
|
+
const { projectName, doClassName, agentDid, publicKey, agentShieldProjectId, agentShieldApiUrl, template, serverUrl, } = opts;
|
|
259
252
|
// Template-specific environment variables
|
|
260
253
|
let templateVars = "";
|
|
261
254
|
if (template === "hardware-world") {
|
|
262
255
|
templateVars = `
|
|
263
256
|
# Hardware World API Configuration
|
|
264
257
|
HARDWARE_WORLD_API_BASE_URL = "https://hardwareworld.com"
|
|
258
|
+
`;
|
|
259
|
+
}
|
|
260
|
+
else if (template === "mix-station") {
|
|
261
|
+
templateVars = `
|
|
262
|
+
# Mixer API Configuration
|
|
263
|
+
MIXER_API_URL = "https://mixer-vouched.vercel.app"
|
|
265
264
|
`;
|
|
266
265
|
}
|
|
267
266
|
return `#:schema node_modules/wrangler/config-schema.json
|
|
@@ -273,11 +272,11 @@ compatibility_flags = ["nodejs_compat"]
|
|
|
273
272
|
# Durable Object binding for MCP Agent state
|
|
274
273
|
[[durable_objects.bindings]]
|
|
275
274
|
name = "MCP_OBJECT"
|
|
276
|
-
class_name = "${
|
|
275
|
+
class_name = "${doClassName}"
|
|
277
276
|
|
|
278
277
|
[[migrations]]
|
|
279
278
|
tag = "v1"
|
|
280
|
-
new_sqlite_classes = ["${
|
|
279
|
+
new_sqlite_classes = ["${doClassName}"]
|
|
281
280
|
|
|
282
281
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
283
282
|
# KV NAMESPACE - Unified single namespace, auto-provisioned by Wrangler v4.45+
|
|
@@ -288,7 +287,7 @@ new_sqlite_classes = ["${pascalCaseName}MCP"]
|
|
|
288
287
|
# Just run: npm run deploy (KV namespace is created automatically!)
|
|
289
288
|
|
|
290
289
|
[[kv_namespaces]]
|
|
291
|
-
binding = "${
|
|
290
|
+
binding = "${UNIFIED_KV_BINDING}"
|
|
292
291
|
|
|
293
292
|
[vars]
|
|
294
293
|
# Agent DID (public identifier - safe to commit)
|
|
@@ -325,22 +324,21 @@ ${templateVars}
|
|
|
325
324
|
# For local development, copy .dev.vars.example to .dev.vars
|
|
326
325
|
`;
|
|
327
326
|
}
|
|
328
|
-
function generateIndexTs(
|
|
327
|
+
function generateIndexTs(doClassName) {
|
|
329
328
|
return `import { createMCPIApp } from "@kya-os/mcp-i-cloudflare";
|
|
330
|
-
import { ${
|
|
329
|
+
import { ${doClassName} } from "./agent";
|
|
331
330
|
import { getRuntimeConfig } from "./mcpi-runtime-config";
|
|
332
331
|
|
|
333
332
|
export default createMCPIApp({
|
|
334
|
-
AgentClass: ${
|
|
333
|
+
AgentClass: ${doClassName},
|
|
335
334
|
getRuntimeConfig,
|
|
336
|
-
envPrefix: "${projectNameUpper}", // Maps prefixed KV binding (e.g., ${projectNameUpper}_MCPI_KV) to standard names
|
|
337
335
|
});
|
|
338
336
|
|
|
339
337
|
// Export Durable Object class for Cloudflare Workers binding
|
|
340
|
-
export { ${
|
|
338
|
+
export { ${doClassName} };
|
|
341
339
|
`;
|
|
342
340
|
}
|
|
343
|
-
function generateAgentTs(projectName,
|
|
341
|
+
function generateAgentTs(projectName, doClassName) {
|
|
344
342
|
return `import { MCPICloudflareAgent, type CloudflareEnv } from "@kya-os/mcp-i-cloudflare";
|
|
345
343
|
import { getRuntimeConfig, getTools } from "./mcpi-runtime-config";
|
|
346
344
|
import type { CloudflareRuntimeConfig } from "@kya-os/mcp-i-cloudflare";
|
|
@@ -348,19 +346,15 @@ import type { CloudflareRuntimeConfig } from "@kya-os/mcp-i-cloudflare";
|
|
|
348
346
|
/**
|
|
349
347
|
* MCP-I Agent Implementation
|
|
350
348
|
*/
|
|
351
|
-
export class ${
|
|
349
|
+
export class ${doClassName} extends MCPICloudflareAgent {
|
|
352
350
|
protected getAgentName(): string {
|
|
353
|
-
return "${projectName}";
|
|
351
|
+
return (this.env as CloudflareEnv).MCP_SERVER_NAME || "${projectName}";
|
|
354
352
|
}
|
|
355
353
|
|
|
356
354
|
protected getAgentVersion(): string {
|
|
357
355
|
return "1.0.0";
|
|
358
356
|
}
|
|
359
357
|
|
|
360
|
-
protected getEnvPrefix(): string | undefined {
|
|
361
|
-
return "${projectNameUpper}";
|
|
362
|
-
}
|
|
363
|
-
|
|
364
358
|
protected getRuntimeConfigInternal(env: CloudflareEnv): CloudflareRuntimeConfig {
|
|
365
359
|
return getRuntimeConfig(env);
|
|
366
360
|
}
|
|
@@ -384,6 +378,10 @@ function generateRuntimeConfigTs(template) {
|
|
|
384
378
|
if (template === "hardware-world") {
|
|
385
379
|
return generateHardwareWorldRuntimeConfig();
|
|
386
380
|
}
|
|
381
|
+
// Mix Station has its own runtime config with Mixer API client
|
|
382
|
+
if (template === "mix-station") {
|
|
383
|
+
return generateMixStationRuntimeConfig();
|
|
384
|
+
}
|
|
387
385
|
const imports = [`import { greetTool } from "./tools/greet";`];
|
|
388
386
|
const tools = ["greetTool"];
|
|
389
387
|
if (template === "ecommerce") {
|
|
@@ -1421,6 +1419,424 @@ export const addToCartTool: ToolDefinition = {
|
|
|
1421
1419
|
},
|
|
1422
1420
|
];
|
|
1423
1421
|
}
|
|
1422
|
+
function generateMixStationRuntimeConfig() {
|
|
1423
|
+
return `import { defineConfig, type CloudflareRuntimeConfig, type ToolDefinition } from "@kya-os/mcp-i-cloudflare";
|
|
1424
|
+
import type { CloudflareEnv } from "@kya-os/mcp-i-cloudflare";
|
|
1425
|
+
import { createMixerClient } from "./lib/mixer-client";
|
|
1426
|
+
|
|
1427
|
+
// Cached env values for tool access (initialized by getRuntimeConfig)
|
|
1428
|
+
let cachedProjectId: string | null = null;
|
|
1429
|
+
let cachedMixerApiUrl: string | undefined = undefined;
|
|
1430
|
+
|
|
1431
|
+
/**
|
|
1432
|
+
* Get runtime configuration for MCP-I Cloudflare Worker
|
|
1433
|
+
*/
|
|
1434
|
+
export function getRuntimeConfig(env: CloudflareEnv): CloudflareRuntimeConfig {
|
|
1435
|
+
cachedProjectId = env.AGENTSHIELD_PROJECT_ID || null;
|
|
1436
|
+
cachedMixerApiUrl = env.MIXER_API_URL || undefined;
|
|
1437
|
+
|
|
1438
|
+
const environment = (env.MCPI_ENV || env.ENVIRONMENT || "development") as "development" | "production";
|
|
1439
|
+
|
|
1440
|
+
const proofingConfig = env.AGENTSHIELD_API_KEY ? {
|
|
1441
|
+
enabled: true,
|
|
1442
|
+
batchQueue: {
|
|
1443
|
+
destinations: [{
|
|
1444
|
+
type: "agentshield" as const,
|
|
1445
|
+
apiKey: env.AGENTSHIELD_API_KEY,
|
|
1446
|
+
apiUrl: env.AGENTSHIELD_API_URL || "https://kya.vouched.id",
|
|
1447
|
+
}],
|
|
1448
|
+
},
|
|
1449
|
+
} : undefined;
|
|
1450
|
+
|
|
1451
|
+
return defineConfig({
|
|
1452
|
+
environment,
|
|
1453
|
+
proofing: proofingConfig,
|
|
1454
|
+
vars: {
|
|
1455
|
+
ENVIRONMENT: environment,
|
|
1456
|
+
AGENTSHIELD_API_KEY: env.AGENTSHIELD_API_KEY,
|
|
1457
|
+
AGENTSHIELD_API_URL: env.AGENTSHIELD_API_URL,
|
|
1458
|
+
AGENTSHIELD_PROJECT_ID: env.AGENTSHIELD_PROJECT_ID,
|
|
1459
|
+
},
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
/**
|
|
1464
|
+
* Get mixer client lazily at execution time.
|
|
1465
|
+
* Uses cached env values set by getRuntimeConfig.
|
|
1466
|
+
*/
|
|
1467
|
+
function getMixerClientLazy(): { projectId: string; mixer: ReturnType<typeof createMixerClient> } | null {
|
|
1468
|
+
const projectId = cachedProjectId;
|
|
1469
|
+
if (!projectId) return null;
|
|
1470
|
+
return { projectId, mixer: createMixerClient(projectId, cachedMixerApiUrl) };
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/**
|
|
1474
|
+
* Get all tools for this agent
|
|
1475
|
+
*/
|
|
1476
|
+
export function getTools(): ToolDefinition[] {
|
|
1477
|
+
return [
|
|
1478
|
+
{
|
|
1479
|
+
name: "get_station_context",
|
|
1480
|
+
description: "Retrieve the curated context and documentation from this station. Returns combined content from all enabled station items.",
|
|
1481
|
+
inputSchema: {
|
|
1482
|
+
type: "object",
|
|
1483
|
+
properties: {
|
|
1484
|
+
query: { type: "string", description: "Optional search query to filter context" },
|
|
1485
|
+
maxTokens: { type: "number", description: "Maximum tokens to return (default: 8000)" },
|
|
1486
|
+
},
|
|
1487
|
+
},
|
|
1488
|
+
handler: async (args: { query?: string; maxTokens?: number }) => {
|
|
1489
|
+
const client = getMixerClientLazy();
|
|
1490
|
+
if (!client) {
|
|
1491
|
+
return { content: [{ type: "text", text: "Error: Station not configured. Missing project ID." }] };
|
|
1492
|
+
}
|
|
1493
|
+
try {
|
|
1494
|
+
const result = await client.mixer.getContext(args);
|
|
1495
|
+
if (!result.success) {
|
|
1496
|
+
return { content: [{ type: "text", text: \`Error: \${result.error}\` }] };
|
|
1497
|
+
}
|
|
1498
|
+
return { content: [{ type: "text", text: result.content || JSON.stringify(result, null, 2) }] };
|
|
1499
|
+
} catch (error) {
|
|
1500
|
+
return { content: [{ type: "text", text: \`Error fetching context: \${error}\` }] };
|
|
1501
|
+
}
|
|
1502
|
+
},
|
|
1503
|
+
},
|
|
1504
|
+
{
|
|
1505
|
+
name: "search_station",
|
|
1506
|
+
description: "Search through the station's indexed content using semantic search. Returns matching code nodes with relevance scores.",
|
|
1507
|
+
inputSchema: {
|
|
1508
|
+
type: "object",
|
|
1509
|
+
properties: {
|
|
1510
|
+
query: { type: "string", description: "Search query" },
|
|
1511
|
+
limit: { type: "number", description: "Maximum number of results (default: 10)" },
|
|
1512
|
+
},
|
|
1513
|
+
required: ["query"],
|
|
1514
|
+
},
|
|
1515
|
+
handler: async (args: { query: string; limit?: number }) => {
|
|
1516
|
+
const client = getMixerClientLazy();
|
|
1517
|
+
if (!client) {
|
|
1518
|
+
return { content: [{ type: "text", text: "Error: Station not configured. Missing project ID." }] };
|
|
1519
|
+
}
|
|
1520
|
+
try {
|
|
1521
|
+
const result = await client.mixer.search(args);
|
|
1522
|
+
if (!result.success) {
|
|
1523
|
+
return { content: [{ type: "text", text: \`Error: \${result.error}\` }] };
|
|
1524
|
+
}
|
|
1525
|
+
let output = \`Found \${result.resultCount} results for "\${result.query}":\\n\\n\`;
|
|
1526
|
+
for (const r of result.results || []) {
|
|
1527
|
+
output += \`## \${r.name || "Unknown"} (\${r.nodeType || "unknown"})\\n\`;
|
|
1528
|
+
output += \`File: \${r.filePath || "unknown"}:\${r.startLine ?? "?"}-\${r.endLine ?? "?"}\\n\`;
|
|
1529
|
+
output += \`Score: \${typeof r.score === "number" ? (r.score * 100).toFixed(1) : "?"}%\\n\\n\`;
|
|
1530
|
+
if (r.content) {
|
|
1531
|
+
output += \`\\\`\\\`\\\`\\n\${r.content.substring(0, 500)}\${r.content.length > 500 ? "..." : ""}\\n\\\`\\\`\\\`\\n\\n\`;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
return { content: [{ type: "text", text: output }] };
|
|
1535
|
+
} catch (error) {
|
|
1536
|
+
return { content: [{ type: "text", text: \`Error searching: \${error}\` }] };
|
|
1537
|
+
}
|
|
1538
|
+
},
|
|
1539
|
+
},
|
|
1540
|
+
{
|
|
1541
|
+
name: "get_station_info",
|
|
1542
|
+
description: "Get information about this station including available repositories, analysis status, and capabilities.",
|
|
1543
|
+
inputSchema: {
|
|
1544
|
+
type: "object",
|
|
1545
|
+
properties: {},
|
|
1546
|
+
},
|
|
1547
|
+
handler: async () => {
|
|
1548
|
+
const client = getMixerClientLazy();
|
|
1549
|
+
if (!client) {
|
|
1550
|
+
return { content: [{ type: "text", text: "Error: Station not configured. Missing project ID." }] };
|
|
1551
|
+
}
|
|
1552
|
+
try {
|
|
1553
|
+
const result = await client.mixer.getInfo();
|
|
1554
|
+
if (!result.success) {
|
|
1555
|
+
return { content: [{ type: "text", text: \`Error: \${result.error}\` }] };
|
|
1556
|
+
}
|
|
1557
|
+
let output = \`# \${result.station.name}\\n\\n\`;
|
|
1558
|
+
if (result.station.description) {
|
|
1559
|
+
output += \`\${result.station.description}\\n\\n\`;
|
|
1560
|
+
}
|
|
1561
|
+
output += \`## Content\\n\`;
|
|
1562
|
+
output += \`- Total items: \${result.content?.totalItems ?? 0}\\n\`;
|
|
1563
|
+
output += \`- Enabled items: \${result.content?.enabledItems ?? 0}\\n\`;
|
|
1564
|
+
output += \`- Repositories: \${result.content?.repositories?.join(", ") || "None"}\\n\\n\`;
|
|
1565
|
+
output += \`## Intelligence\\n\`;
|
|
1566
|
+
if (result.intelligence.available) {
|
|
1567
|
+
output += \`- Status: Ready\\n\`;
|
|
1568
|
+
output += \`- Code nodes: \${result.intelligence.totalNodes}\\n\`;
|
|
1569
|
+
output += \`- Relationships: \${result.intelligence.totalRelationships}\\n\`;
|
|
1570
|
+
output += \`- Communities: \${result.intelligence.totalCommunities}\\n\`;
|
|
1571
|
+
} else {
|
|
1572
|
+
output += \`- Status: \${result.intelligence.status}\\n\`;
|
|
1573
|
+
output += \`- Message: \${result.intelligence.message}\\n\`;
|
|
1574
|
+
}
|
|
1575
|
+
output += \`\\n## Capabilities\\n\`;
|
|
1576
|
+
output += \`- Semantic search: \${result.capabilities.semanticSearch ? "Yes" : "No"}\\n\`;
|
|
1577
|
+
output += \`- Graph queries: \${result.capabilities.graphQueries ? "Yes" : "No"}\\n\`;
|
|
1578
|
+
output += \`- Communities: \${result.capabilities.communities ? "Yes" : "No"}\\n\`;
|
|
1579
|
+
return { content: [{ type: "text", text: output }] };
|
|
1580
|
+
} catch (error) {
|
|
1581
|
+
return { content: [{ type: "text", text: \`Error getting info: \${error}\` }] };
|
|
1582
|
+
}
|
|
1583
|
+
},
|
|
1584
|
+
},
|
|
1585
|
+
{
|
|
1586
|
+
name: "read_file",
|
|
1587
|
+
description: "Read the content of a specific file from the station. Supports partial paths and optional line ranges.",
|
|
1588
|
+
inputSchema: {
|
|
1589
|
+
type: "object",
|
|
1590
|
+
properties: {
|
|
1591
|
+
filePath: { type: "string", description: "The file path to read (can be partial)" },
|
|
1592
|
+
startLine: { type: "number", description: "Optional: Start line (1-indexed)" },
|
|
1593
|
+
endLine: { type: "number", description: "Optional: End line (1-indexed)" },
|
|
1594
|
+
},
|
|
1595
|
+
required: ["filePath"],
|
|
1596
|
+
},
|
|
1597
|
+
handler: async (args: { filePath: string; startLine?: number; endLine?: number }) => {
|
|
1598
|
+
const client = getMixerClientLazy();
|
|
1599
|
+
if (!client) {
|
|
1600
|
+
return { content: [{ type: "text", text: "Error: Station not configured. Missing project ID." }] };
|
|
1601
|
+
}
|
|
1602
|
+
try {
|
|
1603
|
+
const result = await client.mixer.readFile(args);
|
|
1604
|
+
if (!result.success) {
|
|
1605
|
+
let output = \`Error: \${result.error}\\n\`;
|
|
1606
|
+
if (result.suggestions?.length) {
|
|
1607
|
+
output += \`\\nSimilar files found:\\n\`;
|
|
1608
|
+
for (const s of result.suggestions) {
|
|
1609
|
+
output += \`- \${s}\\n\`;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
return { content: [{ type: "text", text: output }] };
|
|
1613
|
+
}
|
|
1614
|
+
let output = \`# \${result.file.path}\\n\\n\`;
|
|
1615
|
+
output += \`Lines: \${result.file.lineCount}\`;
|
|
1616
|
+
if (result.file.startLine || result.file.endLine) {
|
|
1617
|
+
output += \` (showing \${result.file.startLine || 1}-\${result.file.endLine || result.file.lineCount})\`;
|
|
1618
|
+
}
|
|
1619
|
+
output += \`\\n\\n\\\`\\\`\\\`\\n\${result.file.content}\\n\\\`\\\`\\\`\`;
|
|
1620
|
+
if (result.alternateMatches?.length) {
|
|
1621
|
+
output += \`\\n\\nOther matching files: \${result.alternateMatches.join(", ")}\`;
|
|
1622
|
+
}
|
|
1623
|
+
return { content: [{ type: "text", text: output }] };
|
|
1624
|
+
} catch (error) {
|
|
1625
|
+
return { content: [{ type: "text", text: \`Error reading file: \${error}\` }] };
|
|
1626
|
+
}
|
|
1627
|
+
},
|
|
1628
|
+
},
|
|
1629
|
+
{
|
|
1630
|
+
name: "grep",
|
|
1631
|
+
description: "Search for text patterns using regex across all station content. Useful for finding TODOs, error messages, specific function calls, etc.",
|
|
1632
|
+
inputSchema: {
|
|
1633
|
+
type: "object",
|
|
1634
|
+
properties: {
|
|
1635
|
+
pattern: { type: "string", description: "Regex pattern to search for" },
|
|
1636
|
+
fileFilter: { type: "string", description: "Optional: Only search files containing this substring in their path" },
|
|
1637
|
+
caseSensitive: { type: "boolean", description: "Whether to match case (default: false)" },
|
|
1638
|
+
maxResults: { type: "number", description: "Maximum results to return (default: 100)" },
|
|
1639
|
+
},
|
|
1640
|
+
required: ["pattern"],
|
|
1641
|
+
},
|
|
1642
|
+
handler: async (args: { pattern: string; fileFilter?: string; caseSensitive?: boolean; maxResults?: number }) => {
|
|
1643
|
+
const client = getMixerClientLazy();
|
|
1644
|
+
if (!client) {
|
|
1645
|
+
return { content: [{ type: "text", text: "Error: Station not configured. Missing project ID." }] };
|
|
1646
|
+
}
|
|
1647
|
+
try {
|
|
1648
|
+
const result = await client.mixer.grep(args);
|
|
1649
|
+
if (!result.success) {
|
|
1650
|
+
return { content: [{ type: "text", text: \`Error: \${result.error}\` }] };
|
|
1651
|
+
}
|
|
1652
|
+
let output = \`Found \${result.totalMatches} matches for pattern "\${result.pattern}"\\n\`;
|
|
1653
|
+
output += \`Files searched: \${result.filesSearched}\`;
|
|
1654
|
+
if (result.truncated) output += \` (results truncated)\`;
|
|
1655
|
+
output += \`\\n\\n\`;
|
|
1656
|
+
for (const m of result.matches || []) {
|
|
1657
|
+
output += \`**\${m.file}:\${m.line}:\${m.column}**\\n\`;
|
|
1658
|
+
output += \`\\\`\\\`\\\`\\n\${m.context}\\n\\\`\\\`\\\`\\n\\n\`;
|
|
1659
|
+
}
|
|
1660
|
+
return { content: [{ type: "text", text: output }] };
|
|
1661
|
+
} catch (error) {
|
|
1662
|
+
return { content: [{ type: "text", text: \`Error searching: \${error}\` }] };
|
|
1663
|
+
}
|
|
1664
|
+
},
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
name: "graph_query",
|
|
1668
|
+
description: "Query the code graph for nodes, relationships, paths, and communities. The station must have been analyzed to build the graph.",
|
|
1669
|
+
inputSchema: {
|
|
1670
|
+
type: "object",
|
|
1671
|
+
properties: {
|
|
1672
|
+
action: { type: "string", description: "Query action: statistics, nodes, node, relationships, connected, path, communities, community, processes" },
|
|
1673
|
+
nodeId: { type: "string", description: "Node ID for node-specific queries" },
|
|
1674
|
+
targetNodeId: { type: "string", description: "Target node ID for path queries" },
|
|
1675
|
+
direction: { type: "string", description: "Relationship direction: in, out, or both (default: out)" },
|
|
1676
|
+
hops: { type: "number", description: "Traversal depth (default: 2)" },
|
|
1677
|
+
nodeTypes: { type: "string", description: "Comma-separated node types to filter" },
|
|
1678
|
+
limit: { type: "number", description: "Maximum results (default: 50)" },
|
|
1679
|
+
},
|
|
1680
|
+
required: ["action"],
|
|
1681
|
+
},
|
|
1682
|
+
handler: async (args: { action: string; nodeId?: string; targetNodeId?: string; direction?: string; hops?: number; nodeTypes?: string; limit?: number }) => {
|
|
1683
|
+
const client = getMixerClientLazy();
|
|
1684
|
+
if (!client) {
|
|
1685
|
+
return { content: [{ type: "text", text: "Error: Station not configured. Missing project ID." }] };
|
|
1686
|
+
}
|
|
1687
|
+
try {
|
|
1688
|
+
const result = await client.mixer.graph(args);
|
|
1689
|
+
if (!result.success) {
|
|
1690
|
+
return { content: [{ type: "text", text: \`Error: \${result.error}\` }] };
|
|
1691
|
+
}
|
|
1692
|
+
let output = \`## Graph Query: \${result.action}\\n\\n\`;
|
|
1693
|
+
if (result.statistics) {
|
|
1694
|
+
output += \`**Statistics:**\\n\`;
|
|
1695
|
+
output += JSON.stringify(result.statistics, null, 2);
|
|
1696
|
+
} else if (result.nodes) {
|
|
1697
|
+
output += \`Found \${result.count} nodes:\\n\\n\`;
|
|
1698
|
+
for (const n of result.nodes.slice(0, 20)) {
|
|
1699
|
+
output += \`- **\${n.name}** (\${n.nodeType}) - \${n.filePath || "unknown"}:\${n.startLine || "?"}\\n\`;
|
|
1700
|
+
}
|
|
1701
|
+
if (result.count > 20) output += \`\\n... and \${result.count - 20} more\\n\`;
|
|
1702
|
+
} else if (result.node) {
|
|
1703
|
+
output += \`**\${result.node.name}** (\${result.node.nodeType})\\n\`;
|
|
1704
|
+
output += \`- File: \${result.node.filePath}\\n\`;
|
|
1705
|
+
output += \`- Lines: \${result.node.startLine}-\${result.node.endLine}\\n\`;
|
|
1706
|
+
} else if (result.relationships) {
|
|
1707
|
+
output += \`Found \${result.count} relationships:\\n\\n\`;
|
|
1708
|
+
for (const r of result.relationships.slice(0, 20)) {
|
|
1709
|
+
output += \`- \${r.type}: \${r.sourceNodeId} → \${r.targetNodeId}\\n\`;
|
|
1710
|
+
}
|
|
1711
|
+
} else if (result.path) {
|
|
1712
|
+
if (result.found) {
|
|
1713
|
+
output += \`Path found (depth: \${result.path.depth}):\\n\\n\`;
|
|
1714
|
+
for (let i = 0; i < result.path.nodes.length; i++) {
|
|
1715
|
+
const n = result.path.nodes[i];
|
|
1716
|
+
output += \`\${i + 1}. **\${n.name}** (\${n.nodeType})\\n\`;
|
|
1717
|
+
}
|
|
1718
|
+
} else {
|
|
1719
|
+
output += result.message;
|
|
1720
|
+
}
|
|
1721
|
+
} else if (result.communities) {
|
|
1722
|
+
output += \`Found \${result.count} communities:\\n\\n\`;
|
|
1723
|
+
for (const c of result.communities) {
|
|
1724
|
+
output += \`- **\${c.label}**: \${c.memberCount} members (cohesion: \${(c.cohesionScore * 100).toFixed(0)}%)\\n\`;
|
|
1725
|
+
}
|
|
1726
|
+
} else {
|
|
1727
|
+
output += JSON.stringify(result, null, 2);
|
|
1728
|
+
}
|
|
1729
|
+
return { content: [{ type: "text", text: output }] };
|
|
1730
|
+
} catch (error) {
|
|
1731
|
+
return { content: [{ type: "text", text: \`Error querying graph: \${error}\` }] };
|
|
1732
|
+
}
|
|
1733
|
+
},
|
|
1734
|
+
},
|
|
1735
|
+
];
|
|
1736
|
+
}
|
|
1737
|
+
`;
|
|
1738
|
+
}
|
|
1739
|
+
function generateMixStationTools() {
|
|
1740
|
+
return [
|
|
1741
|
+
// Mixer API Client
|
|
1742
|
+
{
|
|
1743
|
+
path: "src/lib/mixer-client.ts",
|
|
1744
|
+
content: `/**
|
|
1745
|
+
* Mixer API Client
|
|
1746
|
+
*
|
|
1747
|
+
* Provides typed access to Mixer's MCP API endpoints.
|
|
1748
|
+
* The project ID is passed via X-AgentShield-Project-Id header,
|
|
1749
|
+
* which Mixer uses to look up the associated station.
|
|
1750
|
+
*/
|
|
1751
|
+
|
|
1752
|
+
const DEFAULT_MIXER_API_URL = "https://mixer-vouched.vercel.app";
|
|
1753
|
+
|
|
1754
|
+
export interface MixerApiClient {
|
|
1755
|
+
getContext: (args: { query?: string; maxTokens?: number }) => Promise<any>;
|
|
1756
|
+
search: (args: { query: string; limit?: number; mode?: string }) => Promise<any>;
|
|
1757
|
+
getInfo: () => Promise<any>;
|
|
1758
|
+
readFile: (args: { filePath: string; startLine?: number; endLine?: number }) => Promise<any>;
|
|
1759
|
+
grep: (args: { pattern: string; fileFilter?: string; caseSensitive?: boolean; maxResults?: number }) => Promise<any>;
|
|
1760
|
+
graph: (args: { action: string; nodeId?: string; targetNodeId?: string; direction?: string; hops?: number; nodeTypes?: string; limit?: number }) => Promise<any>;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
export function createMixerClient(projectId: string, apiUrl?: string): MixerApiClient {
|
|
1764
|
+
const mixerUrl = apiUrl || DEFAULT_MIXER_API_URL;
|
|
1765
|
+
const headers = {
|
|
1766
|
+
"Content-Type": "application/json",
|
|
1767
|
+
"X-AgentShield-Project-Id": projectId,
|
|
1768
|
+
};
|
|
1769
|
+
|
|
1770
|
+
return {
|
|
1771
|
+
async getContext(args) {
|
|
1772
|
+
const params = new URLSearchParams();
|
|
1773
|
+
if (args.query) params.set("query", args.query);
|
|
1774
|
+
if (args.maxTokens) params.set("maxTokens", args.maxTokens.toString());
|
|
1775
|
+
|
|
1776
|
+
const url = \`\${mixerUrl}/api/mcp/context\${params.toString() ? "?" + params.toString() : ""}\`;
|
|
1777
|
+
const response = await fetch(url, { headers });
|
|
1778
|
+
return response.json();
|
|
1779
|
+
},
|
|
1780
|
+
|
|
1781
|
+
async search(args) {
|
|
1782
|
+
const response = await fetch(\`\${mixerUrl}/api/mcp/search\`, {
|
|
1783
|
+
method: "POST",
|
|
1784
|
+
headers,
|
|
1785
|
+
body: JSON.stringify({
|
|
1786
|
+
query: args.query,
|
|
1787
|
+
limit: args.limit || 10,
|
|
1788
|
+
mode: args.mode || "hybrid",
|
|
1789
|
+
}),
|
|
1790
|
+
});
|
|
1791
|
+
return response.json();
|
|
1792
|
+
},
|
|
1793
|
+
|
|
1794
|
+
async getInfo() {
|
|
1795
|
+
const response = await fetch(\`\${mixerUrl}/api/mcp/info\`, { headers });
|
|
1796
|
+
return response.json();
|
|
1797
|
+
},
|
|
1798
|
+
|
|
1799
|
+
async readFile(args) {
|
|
1800
|
+
const params = new URLSearchParams();
|
|
1801
|
+
params.set("filePath", args.filePath);
|
|
1802
|
+
if (args.startLine) params.set("startLine", args.startLine.toString());
|
|
1803
|
+
if (args.endLine) params.set("endLine", args.endLine.toString());
|
|
1804
|
+
|
|
1805
|
+
const response = await fetch(\`\${mixerUrl}/api/mcp/read?\${params.toString()}\`, { headers });
|
|
1806
|
+
return response.json();
|
|
1807
|
+
},
|
|
1808
|
+
|
|
1809
|
+
async grep(args) {
|
|
1810
|
+
const params = new URLSearchParams();
|
|
1811
|
+
params.set("pattern", args.pattern);
|
|
1812
|
+
if (args.fileFilter) params.set("fileFilter", args.fileFilter);
|
|
1813
|
+
if (args.caseSensitive) params.set("caseSensitive", "true");
|
|
1814
|
+
if (args.maxResults) params.set("maxResults", args.maxResults.toString());
|
|
1815
|
+
|
|
1816
|
+
const response = await fetch(\`\${mixerUrl}/api/mcp/grep?\${params.toString()}\`, { headers });
|
|
1817
|
+
return response.json();
|
|
1818
|
+
},
|
|
1819
|
+
|
|
1820
|
+
async graph(args) {
|
|
1821
|
+
const params = new URLSearchParams();
|
|
1822
|
+
params.set("action", args.action);
|
|
1823
|
+
if (args.nodeId) params.set("nodeId", args.nodeId);
|
|
1824
|
+
if (args.targetNodeId) params.set("targetNodeId", args.targetNodeId);
|
|
1825
|
+
if (args.direction) params.set("direction", args.direction);
|
|
1826
|
+
if (args.hops) params.set("hops", args.hops.toString());
|
|
1827
|
+
if (args.nodeTypes) params.set("nodeTypes", args.nodeTypes);
|
|
1828
|
+
if (args.limit) params.set("limit", args.limit.toString());
|
|
1829
|
+
|
|
1830
|
+
const response = await fetch(\`\${mixerUrl}/api/mcp/graph?\${params.toString()}\`, { headers });
|
|
1831
|
+
return response.json();
|
|
1832
|
+
},
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
`,
|
|
1836
|
+
encoding: "utf-8",
|
|
1837
|
+
},
|
|
1838
|
+
];
|
|
1839
|
+
}
|
|
1424
1840
|
function generateDeployWorkflow() {
|
|
1425
1841
|
// Note: YAML values containing ${{ }} must be quoted to avoid parsing issues
|
|
1426
1842
|
return `name: Deploy to Cloudflare
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-cloudflare-files.js","sourceRoot":"","sources":["../../src/helpers/generate-cloudflare-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EACL,gBAAgB,GAEjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAkD/D;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAG,SAAkB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,OAA6B;IAE7B,MAAM,EACJ,WAAW,EACX,QAAQ,GAAG,OAAO,EAClB,oBAAoB,EACpB,iBAAiB,GAAG,wBAAwB,EAC5C,iBAAiB,EACjB,YAAY,GAAG,KAAK,EACpB,SAAS,GACV,GAAG,OAAO,CAAC;IAEZ,
|
|
1
|
+
{"version":3,"file":"generate-cloudflare-files.js","sourceRoot":"","sources":["../../src/helpers/generate-cloudflare-files.ts"],"names":[],"mappings":"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"}
|