@contextstream/mcp-server 0.3.72 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1468 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7662,6 +7662,13 @@ ${options.workspaceId ? `# Workspace ID: ${options.workspaceId}` : ""}
|
|
|
7662
7662
|
content: content.trim() + "\n"
|
|
7663
7663
|
};
|
|
7664
7664
|
}
|
|
7665
|
+
function generateAllRuleFiles(options) {
|
|
7666
|
+
return getAvailableEditors().map((editor) => {
|
|
7667
|
+
const result = generateRuleContent(editor, options);
|
|
7668
|
+
if (!result) return null;
|
|
7669
|
+
return { editor, ...result };
|
|
7670
|
+
}).filter((r) => r !== null);
|
|
7671
|
+
}
|
|
7665
7672
|
|
|
7666
7673
|
// src/tool-catalog.ts
|
|
7667
7674
|
var TOOL_CATALOG = [
|
|
@@ -8431,6 +8438,111 @@ function getBundleInfo() {
|
|
|
8431
8438
|
}));
|
|
8432
8439
|
}
|
|
8433
8440
|
var deferredTools = /* @__PURE__ */ new Map();
|
|
8441
|
+
var ROUTER_MODE = process.env.CONTEXTSTREAM_ROUTER_MODE === "true";
|
|
8442
|
+
var operationsRegistry = /* @__PURE__ */ new Map();
|
|
8443
|
+
function inferOperationCategory(name) {
|
|
8444
|
+
if (name.startsWith("session_") || name.startsWith("context_")) return "Session";
|
|
8445
|
+
if (name.startsWith("memory_")) return "Memory";
|
|
8446
|
+
if (name.startsWith("search_")) return "Search";
|
|
8447
|
+
if (name.startsWith("graph_")) return "Graph";
|
|
8448
|
+
if (name.startsWith("workspace")) return "Workspace";
|
|
8449
|
+
if (name.startsWith("project")) return "Project";
|
|
8450
|
+
if (name.startsWith("reminder")) return "Reminders";
|
|
8451
|
+
if (name.startsWith("slack_") || name.startsWith("github_") || name.startsWith("integration")) return "Integrations";
|
|
8452
|
+
if (name.startsWith("ai_")) return "AI";
|
|
8453
|
+
if (name === "auth_me" || name === "mcp_server_version" || name === "generate_editor_rules") return "Utility";
|
|
8454
|
+
if (name === "tools_enable_bundle" || name === "contextstream" || name === "contextstream_help") return "Meta";
|
|
8455
|
+
return "Other";
|
|
8456
|
+
}
|
|
8457
|
+
function getOperationCatalog(category) {
|
|
8458
|
+
const ops = {};
|
|
8459
|
+
for (const [name, config] of operationsRegistry) {
|
|
8460
|
+
const cat = config.category;
|
|
8461
|
+
if (category && cat.toLowerCase() !== category.toLowerCase()) continue;
|
|
8462
|
+
if (!ops[cat]) ops[cat] = [];
|
|
8463
|
+
ops[cat].push(name);
|
|
8464
|
+
}
|
|
8465
|
+
const lines = [];
|
|
8466
|
+
for (const [cat, names] of Object.entries(ops).sort()) {
|
|
8467
|
+
lines.push(`${cat}: ${names.join(", ")}`);
|
|
8468
|
+
}
|
|
8469
|
+
return lines.join("\n");
|
|
8470
|
+
}
|
|
8471
|
+
function getOperationSchema(name) {
|
|
8472
|
+
const op = operationsRegistry.get(name);
|
|
8473
|
+
if (!op) return null;
|
|
8474
|
+
const zodSchema = op.inputSchema;
|
|
8475
|
+
try {
|
|
8476
|
+
const shape = zodSchema?._def?.shape?.() || zodSchema?.shape || {};
|
|
8477
|
+
const properties = {};
|
|
8478
|
+
const required = [];
|
|
8479
|
+
for (const [key, field] of Object.entries(shape)) {
|
|
8480
|
+
const f = field;
|
|
8481
|
+
const isOptional = f?._def?.typeName === "ZodOptional" || f?.isOptional?.();
|
|
8482
|
+
const innerType = isOptional ? f?._def?.innerType : f;
|
|
8483
|
+
const typeName = innerType?._def?.typeName || "unknown";
|
|
8484
|
+
const description = f?._def?.description || innerType?._def?.description;
|
|
8485
|
+
let type = "string";
|
|
8486
|
+
if (typeName === "ZodNumber") type = "number";
|
|
8487
|
+
else if (typeName === "ZodBoolean") type = "boolean";
|
|
8488
|
+
else if (typeName === "ZodArray") type = "array";
|
|
8489
|
+
else if (typeName === "ZodObject") type = "object";
|
|
8490
|
+
else if (typeName === "ZodEnum") type = "enum";
|
|
8491
|
+
properties[key] = { type };
|
|
8492
|
+
if (description) properties[key].description = description;
|
|
8493
|
+
if (typeName === "ZodEnum") {
|
|
8494
|
+
properties[key].enum = innerType?._def?.values;
|
|
8495
|
+
}
|
|
8496
|
+
if (!isOptional) required.push(key);
|
|
8497
|
+
}
|
|
8498
|
+
return {
|
|
8499
|
+
name: op.name,
|
|
8500
|
+
title: op.title,
|
|
8501
|
+
description: op.description,
|
|
8502
|
+
category: op.category,
|
|
8503
|
+
schema: {
|
|
8504
|
+
type: "object",
|
|
8505
|
+
properties,
|
|
8506
|
+
required: required.length > 0 ? required : void 0
|
|
8507
|
+
}
|
|
8508
|
+
};
|
|
8509
|
+
} catch {
|
|
8510
|
+
return {
|
|
8511
|
+
name: op.name,
|
|
8512
|
+
title: op.title,
|
|
8513
|
+
description: op.description,
|
|
8514
|
+
category: op.category,
|
|
8515
|
+
schema: { type: "object" }
|
|
8516
|
+
};
|
|
8517
|
+
}
|
|
8518
|
+
}
|
|
8519
|
+
var OUTPUT_FORMAT = process.env.CONTEXTSTREAM_OUTPUT_FORMAT || "compact";
|
|
8520
|
+
var COMPACT_OUTPUT = OUTPUT_FORMAT === "compact";
|
|
8521
|
+
var CONSOLIDATED_MODE = process.env.CONTEXTSTREAM_CONSOLIDATED !== "false";
|
|
8522
|
+
var CONSOLIDATED_TOOLS = /* @__PURE__ */ new Set([
|
|
8523
|
+
"session_init",
|
|
8524
|
+
// Standalone - complex initialization
|
|
8525
|
+
"context_smart",
|
|
8526
|
+
// Standalone - called every message
|
|
8527
|
+
"search",
|
|
8528
|
+
// Consolidates search_semantic, search_hybrid, search_keyword, search_pattern
|
|
8529
|
+
"session",
|
|
8530
|
+
// Consolidates session_capture, session_recall, etc.
|
|
8531
|
+
"memory",
|
|
8532
|
+
// Consolidates memory_create_event, memory_get_event, etc.
|
|
8533
|
+
"graph",
|
|
8534
|
+
// Consolidates graph_dependencies, graph_impact, etc.
|
|
8535
|
+
"project",
|
|
8536
|
+
// Consolidates projects_list, projects_create, etc.
|
|
8537
|
+
"workspace",
|
|
8538
|
+
// Consolidates workspaces_list, workspace_associate, etc.
|
|
8539
|
+
"reminder",
|
|
8540
|
+
// Consolidates reminders_list, reminders_create, etc.
|
|
8541
|
+
"integration",
|
|
8542
|
+
// Consolidates slack_*, github_*, integrations_*
|
|
8543
|
+
"help"
|
|
8544
|
+
// Consolidates session_tools, auth_me, mcp_server_version, etc.
|
|
8545
|
+
]);
|
|
8434
8546
|
var TOOLSET_ALIASES = {
|
|
8435
8547
|
// Light mode - minimal, fastest
|
|
8436
8548
|
light: LIGHT_TOOLSET,
|
|
@@ -8493,8 +8605,9 @@ function resolveToolFilter() {
|
|
|
8493
8605
|
console.error(`[ContextStream] Unknown CONTEXTSTREAM_TOOLSET "${toolsetRaw}". Using standard toolset.`);
|
|
8494
8606
|
return { allowlist: STANDARD_TOOLSET, source: "standard", autoDetected: false };
|
|
8495
8607
|
}
|
|
8496
|
-
function formatContent(data) {
|
|
8497
|
-
|
|
8608
|
+
function formatContent(data, forceFormat) {
|
|
8609
|
+
const usePretty = forceFormat === "pretty" || !forceFormat && !COMPACT_OUTPUT;
|
|
8610
|
+
return usePretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
8498
8611
|
}
|
|
8499
8612
|
function toStructured(data) {
|
|
8500
8613
|
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
@@ -8632,6 +8745,21 @@ function registerTools(server, client, sessionManager) {
|
|
|
8632
8745
|
console.error(`[ContextStream] Progressive mode: ENABLED (starting with ${coreBundle.size} core tools)`);
|
|
8633
8746
|
console.error("[ContextStream] Use tools_enable_bundle to unlock additional tool bundles dynamically.");
|
|
8634
8747
|
}
|
|
8748
|
+
if (ROUTER_MODE) {
|
|
8749
|
+
console.error("[ContextStream] Router mode: ENABLED (all operations accessed via contextstream/contextstream_help)");
|
|
8750
|
+
console.error("[ContextStream] Only 2 tools registered. Use contextstream_help to see available operations.");
|
|
8751
|
+
}
|
|
8752
|
+
if (COMPACT_OUTPUT) {
|
|
8753
|
+
console.error("[ContextStream] Output format: COMPACT (minified JSON, ~30% fewer tokens per response)");
|
|
8754
|
+
} else {
|
|
8755
|
+
console.error("[ContextStream] Output format: pretty (set CONTEXTSTREAM_OUTPUT_FORMAT=compact for fewer tokens)");
|
|
8756
|
+
}
|
|
8757
|
+
if (CONSOLIDATED_MODE) {
|
|
8758
|
+
console.error(`[ContextStream] Consolidated mode: ENABLED (~${CONSOLIDATED_TOOLS.size} domain tools, ~75% token reduction)`);
|
|
8759
|
+
console.error("[ContextStream] Set CONTEXTSTREAM_CONSOLIDATED=false to use individual tools.");
|
|
8760
|
+
} else {
|
|
8761
|
+
console.error("[ContextStream] Consolidated mode: disabled (using individual tools)");
|
|
8762
|
+
}
|
|
8635
8763
|
let serverRef = server;
|
|
8636
8764
|
const defaultProTools = /* @__PURE__ */ new Set([
|
|
8637
8765
|
// AI endpoints (typically paid/credit-metered)
|
|
@@ -9015,11 +9143,44 @@ Upgrade: ${upgradeUrl2}` : "";
|
|
|
9015
9143
|
console.error(`[ContextStream] Bundle '${bundleName}' enabled with ${toolsEnabled} tools.`);
|
|
9016
9144
|
return { success: true, message: `Enabled bundle '${bundleName}' with ${toolsEnabled} tools.`, toolsEnabled };
|
|
9017
9145
|
}
|
|
9146
|
+
const ROUTER_DIRECT_TOOLS = /* @__PURE__ */ new Set(["contextstream", "contextstream_help"]);
|
|
9018
9147
|
function registerTool(name, config, handler) {
|
|
9019
|
-
if (
|
|
9148
|
+
if (CONSOLIDATED_MODE && !CONSOLIDATED_TOOLS.has(name)) {
|
|
9149
|
+
operationsRegistry.set(name, {
|
|
9150
|
+
name,
|
|
9151
|
+
title: config.title,
|
|
9152
|
+
description: config.description,
|
|
9153
|
+
inputSchema: config.inputSchema,
|
|
9154
|
+
handler,
|
|
9155
|
+
category: inferOperationCategory(name)
|
|
9156
|
+
});
|
|
9157
|
+
return;
|
|
9158
|
+
}
|
|
9159
|
+
if (!CONSOLIDATED_MODE && toolAllowlist && !toolAllowlist.has(name)) {
|
|
9160
|
+
if (ROUTER_MODE && !ROUTER_DIRECT_TOOLS.has(name)) {
|
|
9161
|
+
operationsRegistry.set(name, {
|
|
9162
|
+
name,
|
|
9163
|
+
title: config.title,
|
|
9164
|
+
description: config.description,
|
|
9165
|
+
inputSchema: config.inputSchema,
|
|
9166
|
+
handler,
|
|
9167
|
+
category: inferOperationCategory(name)
|
|
9168
|
+
});
|
|
9169
|
+
}
|
|
9170
|
+
return;
|
|
9171
|
+
}
|
|
9172
|
+
if (!CONSOLIDATED_MODE && !shouldRegisterIntegrationTool(name)) {
|
|
9020
9173
|
return;
|
|
9021
9174
|
}
|
|
9022
|
-
if (!
|
|
9175
|
+
if (ROUTER_MODE && !ROUTER_DIRECT_TOOLS.has(name)) {
|
|
9176
|
+
operationsRegistry.set(name, {
|
|
9177
|
+
name,
|
|
9178
|
+
title: config.title,
|
|
9179
|
+
description: config.description,
|
|
9180
|
+
inputSchema: config.inputSchema,
|
|
9181
|
+
handler,
|
|
9182
|
+
category: inferOperationCategory(name)
|
|
9183
|
+
});
|
|
9023
9184
|
return;
|
|
9024
9185
|
}
|
|
9025
9186
|
if (PROGRESSIVE_MODE && !isToolInEnabledBundles(name)) {
|
|
@@ -9147,6 +9308,137 @@ Example: Enable memory tools before using memory_create_event.`,
|
|
|
9147
9308
|
return { content: [{ type: "text", text: formatContent(response) }], structuredContent: toStructured(response) };
|
|
9148
9309
|
}
|
|
9149
9310
|
);
|
|
9311
|
+
if (ROUTER_MODE) {
|
|
9312
|
+
serverRef.registerTool(
|
|
9313
|
+
"contextstream",
|
|
9314
|
+
{
|
|
9315
|
+
title: "ContextStream Operation",
|
|
9316
|
+
description: `Execute any ContextStream operation. Use contextstream_help to see available operations.
|
|
9317
|
+
|
|
9318
|
+
Example: contextstream({ op: "session_init", args: { folder_path: "/path/to/project" } })
|
|
9319
|
+
|
|
9320
|
+
This single tool replaces 50+ individual tools, dramatically reducing token overhead.
|
|
9321
|
+
All ContextStream functionality is accessible through this dispatcher.`,
|
|
9322
|
+
inputSchema: {
|
|
9323
|
+
type: "object",
|
|
9324
|
+
properties: {
|
|
9325
|
+
op: { type: "string", description: "Operation name (e.g., session_init, memory_create_event)" },
|
|
9326
|
+
args: { type: "object", description: "Operation arguments (varies by operation)" }
|
|
9327
|
+
},
|
|
9328
|
+
required: ["op"]
|
|
9329
|
+
},
|
|
9330
|
+
annotations: {
|
|
9331
|
+
readOnlyHint: false,
|
|
9332
|
+
destructiveHint: false,
|
|
9333
|
+
idempotentHint: false,
|
|
9334
|
+
openWorldHint: false
|
|
9335
|
+
}
|
|
9336
|
+
},
|
|
9337
|
+
async (input) => {
|
|
9338
|
+
const opName = input.op;
|
|
9339
|
+
const operation = operationsRegistry.get(opName);
|
|
9340
|
+
if (!operation) {
|
|
9341
|
+
const available = getOperationCatalog();
|
|
9342
|
+
return {
|
|
9343
|
+
content: [{
|
|
9344
|
+
type: "text",
|
|
9345
|
+
text: `Unknown operation: ${opName}
|
|
9346
|
+
|
|
9347
|
+
Available operations:
|
|
9348
|
+
${available}
|
|
9349
|
+
|
|
9350
|
+
Use contextstream_help({ op: "operation_name" }) for details.`
|
|
9351
|
+
}],
|
|
9352
|
+
isError: true
|
|
9353
|
+
};
|
|
9354
|
+
}
|
|
9355
|
+
const args = input.args || {};
|
|
9356
|
+
const parsed = operation.inputSchema.safeParse(args);
|
|
9357
|
+
if (!parsed.success) {
|
|
9358
|
+
const schema = getOperationSchema(opName);
|
|
9359
|
+
return {
|
|
9360
|
+
content: [{
|
|
9361
|
+
type: "text",
|
|
9362
|
+
text: `Invalid arguments for ${opName}: ${parsed.error.message}
|
|
9363
|
+
|
|
9364
|
+
Expected schema:
|
|
9365
|
+
${JSON.stringify(schema?.schema || {}, null, 2)}`
|
|
9366
|
+
}],
|
|
9367
|
+
isError: true
|
|
9368
|
+
};
|
|
9369
|
+
}
|
|
9370
|
+
try {
|
|
9371
|
+
return await operation.handler(parsed.data);
|
|
9372
|
+
} catch (error) {
|
|
9373
|
+
return {
|
|
9374
|
+
content: [{
|
|
9375
|
+
type: "text",
|
|
9376
|
+
text: `Error executing ${opName}: ${error?.message || String(error)}`
|
|
9377
|
+
}],
|
|
9378
|
+
isError: true
|
|
9379
|
+
};
|
|
9380
|
+
}
|
|
9381
|
+
}
|
|
9382
|
+
);
|
|
9383
|
+
serverRef.registerTool(
|
|
9384
|
+
"contextstream_help",
|
|
9385
|
+
{
|
|
9386
|
+
title: "ContextStream Help",
|
|
9387
|
+
description: `Get help on available ContextStream operations or schema for a specific operation.
|
|
9388
|
+
|
|
9389
|
+
Examples:
|
|
9390
|
+
- contextstream_help({}) - List all operations by category
|
|
9391
|
+
- contextstream_help({ op: "session_init" }) - Get schema for session_init
|
|
9392
|
+
- contextstream_help({ category: "Memory" }) - List memory operations only`,
|
|
9393
|
+
inputSchema: {
|
|
9394
|
+
type: "object",
|
|
9395
|
+
properties: {
|
|
9396
|
+
op: { type: "string", description: "Operation name to get schema for" },
|
|
9397
|
+
category: { type: "string", description: "Category to filter (Session, Memory, Search, Graph, etc.)" }
|
|
9398
|
+
}
|
|
9399
|
+
},
|
|
9400
|
+
annotations: {
|
|
9401
|
+
readOnlyHint: true,
|
|
9402
|
+
destructiveHint: false,
|
|
9403
|
+
idempotentHint: true,
|
|
9404
|
+
openWorldHint: false
|
|
9405
|
+
}
|
|
9406
|
+
},
|
|
9407
|
+
async (input) => {
|
|
9408
|
+
if (input.op) {
|
|
9409
|
+
const schema = getOperationSchema(input.op);
|
|
9410
|
+
if (!schema) {
|
|
9411
|
+
return {
|
|
9412
|
+
content: [{
|
|
9413
|
+
type: "text",
|
|
9414
|
+
text: `Unknown operation: ${input.op}
|
|
9415
|
+
|
|
9416
|
+
Use contextstream_help({}) to see available operations.`
|
|
9417
|
+
}],
|
|
9418
|
+
isError: true
|
|
9419
|
+
};
|
|
9420
|
+
}
|
|
9421
|
+
return {
|
|
9422
|
+
content: [{ type: "text", text: JSON.stringify(schema, null, 2) }],
|
|
9423
|
+
structuredContent: schema
|
|
9424
|
+
};
|
|
9425
|
+
}
|
|
9426
|
+
const catalog = getOperationCatalog(input.category);
|
|
9427
|
+
const result = {
|
|
9428
|
+
router_mode: true,
|
|
9429
|
+
total_operations: operationsRegistry.size,
|
|
9430
|
+
categories: catalog,
|
|
9431
|
+
usage: 'Call contextstream({ op: "operation_name", args: {...} }) to execute an operation.',
|
|
9432
|
+
hint: 'Use contextstream_help({ op: "operation_name" }) to see the schema for a specific operation.'
|
|
9433
|
+
};
|
|
9434
|
+
return {
|
|
9435
|
+
content: [{ type: "text", text: formatContent(result) }],
|
|
9436
|
+
structuredContent: toStructured(result)
|
|
9437
|
+
};
|
|
9438
|
+
}
|
|
9439
|
+
);
|
|
9440
|
+
console.error(`[ContextStream] Router mode: Registered 2 meta-tools, ${operationsRegistry.size} operations available via dispatcher.`);
|
|
9441
|
+
}
|
|
9150
9442
|
registerTool(
|
|
9151
9443
|
"workspaces_list",
|
|
9152
9444
|
{
|
|
@@ -12053,6 +12345,1175 @@ Use this to remove a reminder that is no longer relevant.`,
|
|
|
12053
12345
|
};
|
|
12054
12346
|
}
|
|
12055
12347
|
);
|
|
12348
|
+
if (CONSOLIDATED_MODE) {
|
|
12349
|
+
registerTool(
|
|
12350
|
+
"search",
|
|
12351
|
+
{
|
|
12352
|
+
title: "Search",
|
|
12353
|
+
description: `Search workspace memory and knowledge. Modes: semantic (meaning-based), hybrid (semantic + keyword), keyword (exact match), pattern (regex).`,
|
|
12354
|
+
inputSchema: external_exports.object({
|
|
12355
|
+
mode: external_exports.enum(["semantic", "hybrid", "keyword", "pattern"]).describe("Search mode"),
|
|
12356
|
+
query: external_exports.string().describe("Search query"),
|
|
12357
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
12358
|
+
project_id: external_exports.string().uuid().optional(),
|
|
12359
|
+
limit: external_exports.number().optional()
|
|
12360
|
+
})
|
|
12361
|
+
},
|
|
12362
|
+
async (input) => {
|
|
12363
|
+
const params = {
|
|
12364
|
+
query: input.query,
|
|
12365
|
+
workspace_id: resolveWorkspaceId(input.workspace_id),
|
|
12366
|
+
project_id: resolveProjectId(input.project_id),
|
|
12367
|
+
limit: input.limit
|
|
12368
|
+
};
|
|
12369
|
+
let result;
|
|
12370
|
+
switch (input.mode) {
|
|
12371
|
+
case "semantic":
|
|
12372
|
+
result = await client.searchSemantic(params);
|
|
12373
|
+
break;
|
|
12374
|
+
case "hybrid":
|
|
12375
|
+
result = await client.searchHybrid(params);
|
|
12376
|
+
break;
|
|
12377
|
+
case "keyword":
|
|
12378
|
+
result = await client.searchKeyword(params);
|
|
12379
|
+
break;
|
|
12380
|
+
case "pattern":
|
|
12381
|
+
result = await client.searchPattern(params);
|
|
12382
|
+
break;
|
|
12383
|
+
}
|
|
12384
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12385
|
+
}
|
|
12386
|
+
);
|
|
12387
|
+
registerTool(
|
|
12388
|
+
"session",
|
|
12389
|
+
{
|
|
12390
|
+
title: "Session",
|
|
12391
|
+
description: `Session management operations. Actions: capture (save decision/insight), capture_lesson (save lesson from mistake), get_lessons (retrieve lessons), recall (natural language recall), remember (quick save), user_context (get preferences), summary (workspace summary), compress (compress chat), delta (changes since timestamp), smart_search (context-enriched search), decision_trace (trace decision provenance).`,
|
|
12392
|
+
inputSchema: external_exports.object({
|
|
12393
|
+
action: external_exports.enum([
|
|
12394
|
+
"capture",
|
|
12395
|
+
"capture_lesson",
|
|
12396
|
+
"get_lessons",
|
|
12397
|
+
"recall",
|
|
12398
|
+
"remember",
|
|
12399
|
+
"user_context",
|
|
12400
|
+
"summary",
|
|
12401
|
+
"compress",
|
|
12402
|
+
"delta",
|
|
12403
|
+
"smart_search",
|
|
12404
|
+
"decision_trace"
|
|
12405
|
+
]).describe("Action to perform"),
|
|
12406
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
12407
|
+
project_id: external_exports.string().uuid().optional(),
|
|
12408
|
+
// Content params
|
|
12409
|
+
query: external_exports.string().optional().describe("Query for recall/search/lessons/decision_trace"),
|
|
12410
|
+
content: external_exports.string().optional().describe("Content for capture/remember/compress"),
|
|
12411
|
+
title: external_exports.string().optional().describe("Title for capture/capture_lesson"),
|
|
12412
|
+
event_type: external_exports.enum(["decision", "preference", "insight", "task", "bug", "feature", "correction", "lesson", "warning", "frustration", "conversation"]).optional().describe("Event type for capture"),
|
|
12413
|
+
importance: external_exports.enum(["low", "medium", "high", "critical"]).optional(),
|
|
12414
|
+
tags: external_exports.array(external_exports.string()).optional(),
|
|
12415
|
+
// Lesson-specific
|
|
12416
|
+
category: external_exports.enum(["workflow", "code_quality", "verification", "communication", "project_specific"]).optional(),
|
|
12417
|
+
trigger: external_exports.string().optional().describe("What caused the problem"),
|
|
12418
|
+
impact: external_exports.string().optional().describe("What went wrong"),
|
|
12419
|
+
prevention: external_exports.string().optional().describe("How to prevent in future"),
|
|
12420
|
+
severity: external_exports.enum(["low", "medium", "high", "critical"]).optional(),
|
|
12421
|
+
keywords: external_exports.array(external_exports.string()).optional(),
|
|
12422
|
+
// Other params
|
|
12423
|
+
since: external_exports.string().optional().describe("ISO timestamp for delta"),
|
|
12424
|
+
limit: external_exports.number().optional(),
|
|
12425
|
+
max_tokens: external_exports.number().optional().describe("Max tokens for summary"),
|
|
12426
|
+
include_decisions: external_exports.boolean().optional(),
|
|
12427
|
+
include_related: external_exports.boolean().optional(),
|
|
12428
|
+
include_impact: external_exports.boolean().optional(),
|
|
12429
|
+
session_id: external_exports.string().optional(),
|
|
12430
|
+
code_refs: external_exports.array(external_exports.object({
|
|
12431
|
+
file_path: external_exports.string(),
|
|
12432
|
+
symbol_id: external_exports.string().optional(),
|
|
12433
|
+
symbol_name: external_exports.string().optional()
|
|
12434
|
+
})).optional(),
|
|
12435
|
+
provenance: external_exports.object({
|
|
12436
|
+
repo: external_exports.string().optional(),
|
|
12437
|
+
branch: external_exports.string().optional(),
|
|
12438
|
+
commit_sha: external_exports.string().optional(),
|
|
12439
|
+
pr_url: external_exports.string().url().optional(),
|
|
12440
|
+
issue_url: external_exports.string().url().optional(),
|
|
12441
|
+
slack_thread_url: external_exports.string().url().optional()
|
|
12442
|
+
}).optional()
|
|
12443
|
+
})
|
|
12444
|
+
},
|
|
12445
|
+
async (input) => {
|
|
12446
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
12447
|
+
const projectId = resolveProjectId(input.project_id);
|
|
12448
|
+
switch (input.action) {
|
|
12449
|
+
case "capture": {
|
|
12450
|
+
if (!input.event_type || !input.title || !input.content) {
|
|
12451
|
+
return errorResult("capture requires: event_type, title, content");
|
|
12452
|
+
}
|
|
12453
|
+
const result = await client.captureContext({
|
|
12454
|
+
workspace_id: workspaceId,
|
|
12455
|
+
project_id: projectId,
|
|
12456
|
+
event_type: input.event_type,
|
|
12457
|
+
title: input.title,
|
|
12458
|
+
content: input.content,
|
|
12459
|
+
importance: input.importance,
|
|
12460
|
+
tags: input.tags,
|
|
12461
|
+
session_id: input.session_id,
|
|
12462
|
+
code_refs: input.code_refs,
|
|
12463
|
+
provenance: input.provenance
|
|
12464
|
+
});
|
|
12465
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12466
|
+
}
|
|
12467
|
+
case "capture_lesson": {
|
|
12468
|
+
if (!input.title || !input.category || !input.trigger || !input.impact || !input.prevention) {
|
|
12469
|
+
return errorResult("capture_lesson requires: title, category, trigger, impact, prevention");
|
|
12470
|
+
}
|
|
12471
|
+
const lessonInput = {
|
|
12472
|
+
title: input.title,
|
|
12473
|
+
category: input.category,
|
|
12474
|
+
trigger: input.trigger,
|
|
12475
|
+
impact: input.impact,
|
|
12476
|
+
prevention: input.prevention,
|
|
12477
|
+
severity: input.severity || "medium",
|
|
12478
|
+
keywords: input.keywords,
|
|
12479
|
+
workspace_id: workspaceId,
|
|
12480
|
+
project_id: projectId
|
|
12481
|
+
};
|
|
12482
|
+
const signature = buildLessonSignature(lessonInput, workspaceId || "global", projectId);
|
|
12483
|
+
if (isDuplicateLessonCapture(signature)) {
|
|
12484
|
+
return { content: [{ type: "text", text: formatContent({ deduplicated: true, message: "Lesson already captured recently" }) }] };
|
|
12485
|
+
}
|
|
12486
|
+
const result = await client.captureLesson(lessonInput);
|
|
12487
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12488
|
+
}
|
|
12489
|
+
case "get_lessons": {
|
|
12490
|
+
const result = await client.getLessons({
|
|
12491
|
+
workspace_id: workspaceId,
|
|
12492
|
+
project_id: projectId,
|
|
12493
|
+
query: input.query,
|
|
12494
|
+
category: input.category,
|
|
12495
|
+
severity: input.severity,
|
|
12496
|
+
limit: input.limit
|
|
12497
|
+
});
|
|
12498
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12499
|
+
}
|
|
12500
|
+
case "recall": {
|
|
12501
|
+
if (!input.query) {
|
|
12502
|
+
return errorResult("recall requires: query");
|
|
12503
|
+
}
|
|
12504
|
+
const result = await client.recallContext({
|
|
12505
|
+
workspace_id: workspaceId,
|
|
12506
|
+
project_id: projectId,
|
|
12507
|
+
query: input.query
|
|
12508
|
+
});
|
|
12509
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12510
|
+
}
|
|
12511
|
+
case "remember": {
|
|
12512
|
+
if (!input.content) {
|
|
12513
|
+
return errorResult("remember requires: content");
|
|
12514
|
+
}
|
|
12515
|
+
const result = await client.rememberContext({
|
|
12516
|
+
workspace_id: workspaceId,
|
|
12517
|
+
project_id: projectId,
|
|
12518
|
+
content: input.content,
|
|
12519
|
+
importance: input.importance
|
|
12520
|
+
});
|
|
12521
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12522
|
+
}
|
|
12523
|
+
case "user_context": {
|
|
12524
|
+
const result = await client.getUserContext({ workspace_id: workspaceId });
|
|
12525
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12526
|
+
}
|
|
12527
|
+
case "summary": {
|
|
12528
|
+
const result = await client.getSessionSummary({
|
|
12529
|
+
workspace_id: workspaceId,
|
|
12530
|
+
project_id: projectId,
|
|
12531
|
+
max_tokens: input.max_tokens
|
|
12532
|
+
});
|
|
12533
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12534
|
+
}
|
|
12535
|
+
case "compress": {
|
|
12536
|
+
if (!input.content) {
|
|
12537
|
+
return errorResult("compress requires: content (the chat history to compress)");
|
|
12538
|
+
}
|
|
12539
|
+
const result = await client.compressSession({
|
|
12540
|
+
workspace_id: workspaceId,
|
|
12541
|
+
project_id: projectId,
|
|
12542
|
+
chat_history: input.content
|
|
12543
|
+
});
|
|
12544
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12545
|
+
}
|
|
12546
|
+
case "delta": {
|
|
12547
|
+
if (!input.since) {
|
|
12548
|
+
return errorResult("delta requires: since (ISO timestamp)");
|
|
12549
|
+
}
|
|
12550
|
+
const result = await client.getSessionDelta({
|
|
12551
|
+
workspace_id: workspaceId,
|
|
12552
|
+
project_id: projectId,
|
|
12553
|
+
since: input.since,
|
|
12554
|
+
limit: input.limit
|
|
12555
|
+
});
|
|
12556
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12557
|
+
}
|
|
12558
|
+
case "smart_search": {
|
|
12559
|
+
if (!input.query) {
|
|
12560
|
+
return errorResult("smart_search requires: query");
|
|
12561
|
+
}
|
|
12562
|
+
const result = await client.smartSearch({
|
|
12563
|
+
workspace_id: workspaceId,
|
|
12564
|
+
project_id: projectId,
|
|
12565
|
+
query: input.query,
|
|
12566
|
+
include_decisions: input.include_decisions,
|
|
12567
|
+
include_related: input.include_related
|
|
12568
|
+
});
|
|
12569
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12570
|
+
}
|
|
12571
|
+
case "decision_trace": {
|
|
12572
|
+
if (!input.query) {
|
|
12573
|
+
return errorResult("decision_trace requires: query");
|
|
12574
|
+
}
|
|
12575
|
+
const result = await client.decisionTrace({
|
|
12576
|
+
workspace_id: workspaceId,
|
|
12577
|
+
project_id: projectId,
|
|
12578
|
+
query: input.query,
|
|
12579
|
+
include_impact: input.include_impact,
|
|
12580
|
+
limit: input.limit
|
|
12581
|
+
});
|
|
12582
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12583
|
+
}
|
|
12584
|
+
default:
|
|
12585
|
+
return errorResult(`Unknown action: ${input.action}`);
|
|
12586
|
+
}
|
|
12587
|
+
}
|
|
12588
|
+
);
|
|
12589
|
+
registerTool(
|
|
12590
|
+
"memory",
|
|
12591
|
+
{
|
|
12592
|
+
title: "Memory",
|
|
12593
|
+
description: `Memory operations for events and nodes. Event actions: create_event, get_event, update_event, delete_event, list_events, distill_event. Node actions: create_node, get_node, update_node, delete_node, list_nodes, supersede_node. Query actions: search, decisions, timeline, summary.`,
|
|
12594
|
+
inputSchema: external_exports.object({
|
|
12595
|
+
action: external_exports.enum([
|
|
12596
|
+
"create_event",
|
|
12597
|
+
"get_event",
|
|
12598
|
+
"update_event",
|
|
12599
|
+
"delete_event",
|
|
12600
|
+
"list_events",
|
|
12601
|
+
"distill_event",
|
|
12602
|
+
"create_node",
|
|
12603
|
+
"get_node",
|
|
12604
|
+
"update_node",
|
|
12605
|
+
"delete_node",
|
|
12606
|
+
"list_nodes",
|
|
12607
|
+
"supersede_node",
|
|
12608
|
+
"search",
|
|
12609
|
+
"decisions",
|
|
12610
|
+
"timeline",
|
|
12611
|
+
"summary"
|
|
12612
|
+
]).describe("Action to perform"),
|
|
12613
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
12614
|
+
project_id: external_exports.string().uuid().optional(),
|
|
12615
|
+
// ID params
|
|
12616
|
+
event_id: external_exports.string().uuid().optional(),
|
|
12617
|
+
node_id: external_exports.string().uuid().optional(),
|
|
12618
|
+
// Content params
|
|
12619
|
+
title: external_exports.string().optional(),
|
|
12620
|
+
content: external_exports.string().optional(),
|
|
12621
|
+
event_type: external_exports.string().optional(),
|
|
12622
|
+
node_type: external_exports.string().optional(),
|
|
12623
|
+
metadata: external_exports.record(external_exports.any()).optional(),
|
|
12624
|
+
// Query params
|
|
12625
|
+
query: external_exports.string().optional(),
|
|
12626
|
+
category: external_exports.string().optional(),
|
|
12627
|
+
limit: external_exports.number().optional(),
|
|
12628
|
+
// Node relations
|
|
12629
|
+
relations: external_exports.array(external_exports.object({
|
|
12630
|
+
type: external_exports.string(),
|
|
12631
|
+
target_id: external_exports.string().uuid()
|
|
12632
|
+
})).optional(),
|
|
12633
|
+
new_node_id: external_exports.string().uuid().optional().describe("For supersede: the new node ID"),
|
|
12634
|
+
// Provenance
|
|
12635
|
+
provenance: external_exports.object({
|
|
12636
|
+
repo: external_exports.string().optional(),
|
|
12637
|
+
branch: external_exports.string().optional(),
|
|
12638
|
+
commit_sha: external_exports.string().optional(),
|
|
12639
|
+
pr_url: external_exports.string().url().optional(),
|
|
12640
|
+
issue_url: external_exports.string().url().optional(),
|
|
12641
|
+
slack_thread_url: external_exports.string().url().optional()
|
|
12642
|
+
}).optional(),
|
|
12643
|
+
code_refs: external_exports.array(external_exports.object({
|
|
12644
|
+
file_path: external_exports.string(),
|
|
12645
|
+
symbol_id: external_exports.string().optional(),
|
|
12646
|
+
symbol_name: external_exports.string().optional()
|
|
12647
|
+
})).optional()
|
|
12648
|
+
})
|
|
12649
|
+
},
|
|
12650
|
+
async (input) => {
|
|
12651
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
12652
|
+
const projectId = resolveProjectId(input.project_id);
|
|
12653
|
+
switch (input.action) {
|
|
12654
|
+
case "create_event": {
|
|
12655
|
+
if (!input.event_type || !input.title || !input.content) {
|
|
12656
|
+
return errorResult("create_event requires: event_type, title, content");
|
|
12657
|
+
}
|
|
12658
|
+
const result = await client.createMemoryEvent({
|
|
12659
|
+
workspace_id: workspaceId,
|
|
12660
|
+
project_id: projectId,
|
|
12661
|
+
event_type: input.event_type,
|
|
12662
|
+
title: input.title,
|
|
12663
|
+
content: input.content,
|
|
12664
|
+
metadata: input.metadata,
|
|
12665
|
+
provenance: input.provenance,
|
|
12666
|
+
code_refs: input.code_refs
|
|
12667
|
+
});
|
|
12668
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12669
|
+
}
|
|
12670
|
+
case "get_event": {
|
|
12671
|
+
if (!input.event_id) {
|
|
12672
|
+
return errorResult("get_event requires: event_id");
|
|
12673
|
+
}
|
|
12674
|
+
const result = await client.getMemoryEvent(input.event_id);
|
|
12675
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12676
|
+
}
|
|
12677
|
+
case "update_event": {
|
|
12678
|
+
if (!input.event_id) {
|
|
12679
|
+
return errorResult("update_event requires: event_id");
|
|
12680
|
+
}
|
|
12681
|
+
const result = await client.updateMemoryEvent({
|
|
12682
|
+
event_id: input.event_id,
|
|
12683
|
+
title: input.title,
|
|
12684
|
+
content: input.content,
|
|
12685
|
+
metadata: input.metadata
|
|
12686
|
+
});
|
|
12687
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12688
|
+
}
|
|
12689
|
+
case "delete_event": {
|
|
12690
|
+
if (!input.event_id) {
|
|
12691
|
+
return errorResult("delete_event requires: event_id");
|
|
12692
|
+
}
|
|
12693
|
+
const result = await client.deleteMemoryEvent(input.event_id);
|
|
12694
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12695
|
+
}
|
|
12696
|
+
case "list_events": {
|
|
12697
|
+
const result = await client.listMemoryEvents({
|
|
12698
|
+
workspace_id: workspaceId,
|
|
12699
|
+
project_id: projectId,
|
|
12700
|
+
limit: input.limit
|
|
12701
|
+
});
|
|
12702
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12703
|
+
}
|
|
12704
|
+
case "distill_event": {
|
|
12705
|
+
if (!input.event_id) {
|
|
12706
|
+
return errorResult("distill_event requires: event_id");
|
|
12707
|
+
}
|
|
12708
|
+
const result = await client.distillEvent(input.event_id);
|
|
12709
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12710
|
+
}
|
|
12711
|
+
case "create_node": {
|
|
12712
|
+
if (!input.node_type || !input.title || !input.content) {
|
|
12713
|
+
return errorResult("create_node requires: node_type, title, content");
|
|
12714
|
+
}
|
|
12715
|
+
const result = await client.createKnowledgeNode({
|
|
12716
|
+
workspace_id: workspaceId,
|
|
12717
|
+
project_id: projectId,
|
|
12718
|
+
node_type: input.node_type,
|
|
12719
|
+
title: input.title,
|
|
12720
|
+
content: input.content,
|
|
12721
|
+
relations: input.relations
|
|
12722
|
+
});
|
|
12723
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12724
|
+
}
|
|
12725
|
+
case "get_node": {
|
|
12726
|
+
if (!input.node_id) {
|
|
12727
|
+
return errorResult("get_node requires: node_id");
|
|
12728
|
+
}
|
|
12729
|
+
const result = await client.getKnowledgeNode(input.node_id);
|
|
12730
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12731
|
+
}
|
|
12732
|
+
case "update_node": {
|
|
12733
|
+
if (!input.node_id) {
|
|
12734
|
+
return errorResult("update_node requires: node_id");
|
|
12735
|
+
}
|
|
12736
|
+
const result = await client.updateKnowledgeNode({
|
|
12737
|
+
node_id: input.node_id,
|
|
12738
|
+
title: input.title,
|
|
12739
|
+
content: input.content
|
|
12740
|
+
});
|
|
12741
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12742
|
+
}
|
|
12743
|
+
case "delete_node": {
|
|
12744
|
+
if (!input.node_id) {
|
|
12745
|
+
return errorResult("delete_node requires: node_id");
|
|
12746
|
+
}
|
|
12747
|
+
const result = await client.deleteKnowledgeNode(input.node_id);
|
|
12748
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12749
|
+
}
|
|
12750
|
+
case "list_nodes": {
|
|
12751
|
+
const result = await client.listKnowledgeNodes({
|
|
12752
|
+
workspace_id: workspaceId,
|
|
12753
|
+
project_id: projectId,
|
|
12754
|
+
limit: input.limit
|
|
12755
|
+
});
|
|
12756
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12757
|
+
}
|
|
12758
|
+
case "supersede_node": {
|
|
12759
|
+
if (!input.node_id || !input.new_node_id) {
|
|
12760
|
+
return errorResult("supersede_node requires: node_id, new_node_id");
|
|
12761
|
+
}
|
|
12762
|
+
const result = await client.supersedeKnowledgeNode({
|
|
12763
|
+
node_id: input.node_id,
|
|
12764
|
+
new_node_id: input.new_node_id
|
|
12765
|
+
});
|
|
12766
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12767
|
+
}
|
|
12768
|
+
case "search": {
|
|
12769
|
+
if (!input.query) {
|
|
12770
|
+
return errorResult("search requires: query");
|
|
12771
|
+
}
|
|
12772
|
+
const result = await client.searchMemory({
|
|
12773
|
+
workspace_id: workspaceId,
|
|
12774
|
+
project_id: projectId,
|
|
12775
|
+
query: input.query,
|
|
12776
|
+
limit: input.limit
|
|
12777
|
+
});
|
|
12778
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12779
|
+
}
|
|
12780
|
+
case "decisions": {
|
|
12781
|
+
const result = await client.memoryDecisions({
|
|
12782
|
+
workspace_id: workspaceId,
|
|
12783
|
+
project_id: projectId,
|
|
12784
|
+
category: input.category,
|
|
12785
|
+
limit: input.limit
|
|
12786
|
+
});
|
|
12787
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12788
|
+
}
|
|
12789
|
+
case "timeline": {
|
|
12790
|
+
const result = await client.memoryTimeline({
|
|
12791
|
+
workspace_id: workspaceId
|
|
12792
|
+
});
|
|
12793
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12794
|
+
}
|
|
12795
|
+
case "summary": {
|
|
12796
|
+
const result = await client.memorySummary({
|
|
12797
|
+
workspace_id: workspaceId
|
|
12798
|
+
});
|
|
12799
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12800
|
+
}
|
|
12801
|
+
default:
|
|
12802
|
+
return errorResult(`Unknown action: ${input.action}`);
|
|
12803
|
+
}
|
|
12804
|
+
}
|
|
12805
|
+
);
|
|
12806
|
+
registerTool(
|
|
12807
|
+
"graph",
|
|
12808
|
+
{
|
|
12809
|
+
title: "Graph",
|
|
12810
|
+
description: `Code graph analysis. Actions: dependencies (module deps), impact (change impact), call_path (function call path), related (related nodes), path (path between nodes), decisions (decision history), ingest (build graph), circular_dependencies, unused_code, contradictions.`,
|
|
12811
|
+
inputSchema: external_exports.object({
|
|
12812
|
+
action: external_exports.enum([
|
|
12813
|
+
"dependencies",
|
|
12814
|
+
"impact",
|
|
12815
|
+
"call_path",
|
|
12816
|
+
"related",
|
|
12817
|
+
"path",
|
|
12818
|
+
"decisions",
|
|
12819
|
+
"ingest",
|
|
12820
|
+
"circular_dependencies",
|
|
12821
|
+
"unused_code",
|
|
12822
|
+
"contradictions"
|
|
12823
|
+
]).describe("Action to perform"),
|
|
12824
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
12825
|
+
project_id: external_exports.string().uuid().optional(),
|
|
12826
|
+
// ID params
|
|
12827
|
+
node_id: external_exports.string().uuid().optional().describe("For related/contradictions"),
|
|
12828
|
+
source_id: external_exports.string().uuid().optional().describe("For path"),
|
|
12829
|
+
target_id: external_exports.string().uuid().optional().describe("For path"),
|
|
12830
|
+
// Target specification
|
|
12831
|
+
target: external_exports.object({
|
|
12832
|
+
type: external_exports.string().describe("module|function|type|variable"),
|
|
12833
|
+
id: external_exports.string().describe("Element identifier")
|
|
12834
|
+
}).optional().describe("For dependencies/impact"),
|
|
12835
|
+
source: external_exports.object({
|
|
12836
|
+
type: external_exports.string().describe("function"),
|
|
12837
|
+
id: external_exports.string().describe("Function identifier")
|
|
12838
|
+
}).optional().describe("For call_path"),
|
|
12839
|
+
// Options
|
|
12840
|
+
max_depth: external_exports.number().optional(),
|
|
12841
|
+
include_transitive: external_exports.boolean().optional(),
|
|
12842
|
+
limit: external_exports.number().optional(),
|
|
12843
|
+
wait: external_exports.boolean().optional().describe("For ingest: wait for completion")
|
|
12844
|
+
})
|
|
12845
|
+
},
|
|
12846
|
+
async (input) => {
|
|
12847
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
12848
|
+
const projectId = resolveProjectId(input.project_id);
|
|
12849
|
+
const gatedActions = ["related", "path", "decisions", "call_path", "circular_dependencies", "unused_code", "ingest", "contradictions"];
|
|
12850
|
+
if (gatedActions.includes(input.action)) {
|
|
12851
|
+
const gate = await gateIfGraphTool(`graph_${input.action}`, input);
|
|
12852
|
+
if (gate) return gate;
|
|
12853
|
+
}
|
|
12854
|
+
switch (input.action) {
|
|
12855
|
+
case "dependencies": {
|
|
12856
|
+
if (!input.target) {
|
|
12857
|
+
return errorResult("dependencies requires: target { type, id }");
|
|
12858
|
+
}
|
|
12859
|
+
const result = await client.graphDependencies({
|
|
12860
|
+
target: input.target,
|
|
12861
|
+
max_depth: input.max_depth,
|
|
12862
|
+
include_transitive: input.include_transitive
|
|
12863
|
+
});
|
|
12864
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12865
|
+
}
|
|
12866
|
+
case "impact": {
|
|
12867
|
+
if (!input.target) {
|
|
12868
|
+
return errorResult("impact requires: target { type, id }");
|
|
12869
|
+
}
|
|
12870
|
+
const result = await client.graphImpact({
|
|
12871
|
+
target: input.target,
|
|
12872
|
+
max_depth: input.max_depth
|
|
12873
|
+
});
|
|
12874
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12875
|
+
}
|
|
12876
|
+
case "call_path": {
|
|
12877
|
+
if (!input.source || !input.target) {
|
|
12878
|
+
return errorResult("call_path requires: source { type, id }, target { type, id }");
|
|
12879
|
+
}
|
|
12880
|
+
const result = await client.graphCallPath({
|
|
12881
|
+
source: input.source,
|
|
12882
|
+
target: input.target,
|
|
12883
|
+
max_depth: input.max_depth
|
|
12884
|
+
});
|
|
12885
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12886
|
+
}
|
|
12887
|
+
case "related": {
|
|
12888
|
+
if (!input.node_id) {
|
|
12889
|
+
return errorResult("related requires: node_id");
|
|
12890
|
+
}
|
|
12891
|
+
const result = await client.graphRelated({
|
|
12892
|
+
node_id: input.node_id,
|
|
12893
|
+
workspace_id: workspaceId,
|
|
12894
|
+
project_id: projectId,
|
|
12895
|
+
limit: input.limit
|
|
12896
|
+
});
|
|
12897
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12898
|
+
}
|
|
12899
|
+
case "path": {
|
|
12900
|
+
if (!input.source_id || !input.target_id) {
|
|
12901
|
+
return errorResult("path requires: source_id, target_id");
|
|
12902
|
+
}
|
|
12903
|
+
const result = await client.graphPath({
|
|
12904
|
+
source_id: input.source_id,
|
|
12905
|
+
target_id: input.target_id,
|
|
12906
|
+
workspace_id: workspaceId,
|
|
12907
|
+
project_id: projectId
|
|
12908
|
+
});
|
|
12909
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12910
|
+
}
|
|
12911
|
+
case "decisions": {
|
|
12912
|
+
const result = await client.graphDecisions({
|
|
12913
|
+
workspace_id: workspaceId,
|
|
12914
|
+
project_id: projectId,
|
|
12915
|
+
limit: input.limit
|
|
12916
|
+
});
|
|
12917
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12918
|
+
}
|
|
12919
|
+
case "ingest": {
|
|
12920
|
+
if (!projectId) {
|
|
12921
|
+
return errorResult("ingest requires: project_id");
|
|
12922
|
+
}
|
|
12923
|
+
const result = await client.graphIngest({
|
|
12924
|
+
project_id: projectId,
|
|
12925
|
+
wait: input.wait
|
|
12926
|
+
});
|
|
12927
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12928
|
+
}
|
|
12929
|
+
case "circular_dependencies": {
|
|
12930
|
+
if (!projectId) {
|
|
12931
|
+
return errorResult("circular_dependencies requires: project_id");
|
|
12932
|
+
}
|
|
12933
|
+
const result = await client.findCircularDependencies(projectId);
|
|
12934
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12935
|
+
}
|
|
12936
|
+
case "unused_code": {
|
|
12937
|
+
if (!projectId) {
|
|
12938
|
+
return errorResult("unused_code requires: project_id");
|
|
12939
|
+
}
|
|
12940
|
+
const result = await client.findUnusedCode(projectId);
|
|
12941
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12942
|
+
}
|
|
12943
|
+
case "contradictions": {
|
|
12944
|
+
if (!input.node_id) {
|
|
12945
|
+
return errorResult("contradictions requires: node_id");
|
|
12946
|
+
}
|
|
12947
|
+
const result = await client.findContradictions(input.node_id);
|
|
12948
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
12949
|
+
}
|
|
12950
|
+
default:
|
|
12951
|
+
return errorResult(`Unknown action: ${input.action}`);
|
|
12952
|
+
}
|
|
12953
|
+
}
|
|
12954
|
+
);
|
|
12955
|
+
registerTool(
|
|
12956
|
+
"project",
|
|
12957
|
+
{
|
|
12958
|
+
title: "Project",
|
|
12959
|
+
description: `Project management. Actions: list, get, create, update, index (trigger indexing), overview, statistics, files, index_status, ingest_local (index local folder).`,
|
|
12960
|
+
inputSchema: external_exports.object({
|
|
12961
|
+
action: external_exports.enum([
|
|
12962
|
+
"list",
|
|
12963
|
+
"get",
|
|
12964
|
+
"create",
|
|
12965
|
+
"update",
|
|
12966
|
+
"index",
|
|
12967
|
+
"overview",
|
|
12968
|
+
"statistics",
|
|
12969
|
+
"files",
|
|
12970
|
+
"index_status",
|
|
12971
|
+
"ingest_local"
|
|
12972
|
+
]).describe("Action to perform"),
|
|
12973
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
12974
|
+
project_id: external_exports.string().uuid().optional(),
|
|
12975
|
+
// Create/update params
|
|
12976
|
+
name: external_exports.string().optional(),
|
|
12977
|
+
description: external_exports.string().optional(),
|
|
12978
|
+
folder_path: external_exports.string().optional(),
|
|
12979
|
+
generate_editor_rules: external_exports.boolean().optional(),
|
|
12980
|
+
// Ingest params
|
|
12981
|
+
path: external_exports.string().optional().describe("Local path to ingest"),
|
|
12982
|
+
overwrite: external_exports.boolean().optional(),
|
|
12983
|
+
write_to_disk: external_exports.boolean().optional(),
|
|
12984
|
+
// Pagination
|
|
12985
|
+
page: external_exports.number().optional(),
|
|
12986
|
+
page_size: external_exports.number().optional()
|
|
12987
|
+
})
|
|
12988
|
+
},
|
|
12989
|
+
async (input) => {
|
|
12990
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
12991
|
+
const projectId = resolveProjectId(input.project_id);
|
|
12992
|
+
switch (input.action) {
|
|
12993
|
+
case "list": {
|
|
12994
|
+
const result = await client.listProjects({
|
|
12995
|
+
workspace_id: workspaceId,
|
|
12996
|
+
page: input.page,
|
|
12997
|
+
page_size: input.page_size
|
|
12998
|
+
});
|
|
12999
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13000
|
+
}
|
|
13001
|
+
case "get": {
|
|
13002
|
+
if (!projectId) {
|
|
13003
|
+
return errorResult("get requires: project_id");
|
|
13004
|
+
}
|
|
13005
|
+
const result = await client.getProject(projectId);
|
|
13006
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13007
|
+
}
|
|
13008
|
+
case "create": {
|
|
13009
|
+
if (!input.name) {
|
|
13010
|
+
return errorResult("create requires: name");
|
|
13011
|
+
}
|
|
13012
|
+
const result = await client.createProject({
|
|
13013
|
+
workspace_id: workspaceId,
|
|
13014
|
+
name: input.name,
|
|
13015
|
+
description: input.description,
|
|
13016
|
+
folder_path: input.folder_path,
|
|
13017
|
+
generate_editor_rules: input.generate_editor_rules
|
|
13018
|
+
});
|
|
13019
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13020
|
+
}
|
|
13021
|
+
case "update": {
|
|
13022
|
+
if (!projectId) {
|
|
13023
|
+
return errorResult("update requires: project_id");
|
|
13024
|
+
}
|
|
13025
|
+
const result = await client.updateProject({
|
|
13026
|
+
project_id: projectId,
|
|
13027
|
+
name: input.name,
|
|
13028
|
+
description: input.description
|
|
13029
|
+
});
|
|
13030
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13031
|
+
}
|
|
13032
|
+
case "index": {
|
|
13033
|
+
if (!projectId) {
|
|
13034
|
+
return errorResult("index requires: project_id");
|
|
13035
|
+
}
|
|
13036
|
+
const result = await client.indexProject(projectId);
|
|
13037
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13038
|
+
}
|
|
13039
|
+
case "overview": {
|
|
13040
|
+
if (!projectId) {
|
|
13041
|
+
return errorResult("overview requires: project_id");
|
|
13042
|
+
}
|
|
13043
|
+
const result = await client.projectOverview(projectId);
|
|
13044
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13045
|
+
}
|
|
13046
|
+
case "statistics": {
|
|
13047
|
+
if (!projectId) {
|
|
13048
|
+
return errorResult("statistics requires: project_id");
|
|
13049
|
+
}
|
|
13050
|
+
const result = await client.projectStatistics(projectId);
|
|
13051
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13052
|
+
}
|
|
13053
|
+
case "files": {
|
|
13054
|
+
if (!projectId) {
|
|
13055
|
+
return errorResult("files requires: project_id");
|
|
13056
|
+
}
|
|
13057
|
+
const result = await client.projectFiles(projectId);
|
|
13058
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13059
|
+
}
|
|
13060
|
+
case "index_status": {
|
|
13061
|
+
if (!projectId) {
|
|
13062
|
+
return errorResult("index_status requires: project_id");
|
|
13063
|
+
}
|
|
13064
|
+
const result = await client.projectIndexStatus(projectId);
|
|
13065
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13066
|
+
}
|
|
13067
|
+
case "ingest_local": {
|
|
13068
|
+
if (!input.path) {
|
|
13069
|
+
return errorResult("ingest_local requires: path");
|
|
13070
|
+
}
|
|
13071
|
+
const validPath = await validateReadableDirectory(input.path);
|
|
13072
|
+
if (!validPath.ok) {
|
|
13073
|
+
return errorResult(validPath.error);
|
|
13074
|
+
}
|
|
13075
|
+
const files = await readAllFilesInBatches(validPath.resolvedPath, async (batch) => {
|
|
13076
|
+
await client.ingestLocalFiles({
|
|
13077
|
+
project_id: projectId,
|
|
13078
|
+
files: batch,
|
|
13079
|
+
overwrite: input.overwrite,
|
|
13080
|
+
write_to_disk: input.write_to_disk
|
|
13081
|
+
});
|
|
13082
|
+
});
|
|
13083
|
+
const result = { files_ingested: files, project_id: projectId };
|
|
13084
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13085
|
+
}
|
|
13086
|
+
default:
|
|
13087
|
+
return errorResult(`Unknown action: ${input.action}`);
|
|
13088
|
+
}
|
|
13089
|
+
}
|
|
13090
|
+
);
|
|
13091
|
+
registerTool(
|
|
13092
|
+
"workspace",
|
|
13093
|
+
{
|
|
13094
|
+
title: "Workspace",
|
|
13095
|
+
description: `Workspace management. Actions: list, get, associate (link folder to workspace), bootstrap (create workspace and initialize).`,
|
|
13096
|
+
inputSchema: external_exports.object({
|
|
13097
|
+
action: external_exports.enum(["list", "get", "associate", "bootstrap"]).describe("Action to perform"),
|
|
13098
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
13099
|
+
// Associate/bootstrap params
|
|
13100
|
+
folder_path: external_exports.string().optional(),
|
|
13101
|
+
workspace_name: external_exports.string().optional(),
|
|
13102
|
+
create_parent_mapping: external_exports.boolean().optional(),
|
|
13103
|
+
generate_editor_rules: external_exports.boolean().optional(),
|
|
13104
|
+
// Bootstrap-specific
|
|
13105
|
+
description: external_exports.string().optional(),
|
|
13106
|
+
visibility: external_exports.enum(["private", "public"]).optional(),
|
|
13107
|
+
auto_index: external_exports.boolean().optional(),
|
|
13108
|
+
context_hint: external_exports.string().optional(),
|
|
13109
|
+
// Pagination
|
|
13110
|
+
page: external_exports.number().optional(),
|
|
13111
|
+
page_size: external_exports.number().optional()
|
|
13112
|
+
})
|
|
13113
|
+
},
|
|
13114
|
+
async (input) => {
|
|
13115
|
+
switch (input.action) {
|
|
13116
|
+
case "list": {
|
|
13117
|
+
const result = await client.listWorkspaces({
|
|
13118
|
+
page: input.page,
|
|
13119
|
+
page_size: input.page_size
|
|
13120
|
+
});
|
|
13121
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13122
|
+
}
|
|
13123
|
+
case "get": {
|
|
13124
|
+
if (!input.workspace_id) {
|
|
13125
|
+
return errorResult("get requires: workspace_id");
|
|
13126
|
+
}
|
|
13127
|
+
const result = await client.getWorkspace(input.workspace_id);
|
|
13128
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13129
|
+
}
|
|
13130
|
+
case "associate": {
|
|
13131
|
+
if (!input.folder_path || !input.workspace_id) {
|
|
13132
|
+
return errorResult("associate requires: folder_path, workspace_id");
|
|
13133
|
+
}
|
|
13134
|
+
const result = await client.associateWorkspace({
|
|
13135
|
+
folder_path: input.folder_path,
|
|
13136
|
+
workspace_id: input.workspace_id,
|
|
13137
|
+
workspace_name: input.workspace_name,
|
|
13138
|
+
create_parent_mapping: input.create_parent_mapping,
|
|
13139
|
+
generate_editor_rules: input.generate_editor_rules
|
|
13140
|
+
});
|
|
13141
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13142
|
+
}
|
|
13143
|
+
case "bootstrap": {
|
|
13144
|
+
if (!input.workspace_name) {
|
|
13145
|
+
return errorResult("bootstrap requires: workspace_name");
|
|
13146
|
+
}
|
|
13147
|
+
const result = await client.bootstrapWorkspace({
|
|
13148
|
+
workspace_name: input.workspace_name,
|
|
13149
|
+
folder_path: input.folder_path,
|
|
13150
|
+
description: input.description,
|
|
13151
|
+
visibility: input.visibility,
|
|
13152
|
+
create_parent_mapping: input.create_parent_mapping,
|
|
13153
|
+
generate_editor_rules: input.generate_editor_rules,
|
|
13154
|
+
auto_index: input.auto_index,
|
|
13155
|
+
context_hint: input.context_hint
|
|
13156
|
+
});
|
|
13157
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13158
|
+
}
|
|
13159
|
+
default:
|
|
13160
|
+
return errorResult(`Unknown action: ${input.action}`);
|
|
13161
|
+
}
|
|
13162
|
+
}
|
|
13163
|
+
);
|
|
13164
|
+
registerTool(
|
|
13165
|
+
"reminder",
|
|
13166
|
+
{
|
|
13167
|
+
title: "Reminder",
|
|
13168
|
+
description: `Reminder management. Actions: list, active (pending/overdue), create, snooze, complete, dismiss.`,
|
|
13169
|
+
inputSchema: external_exports.object({
|
|
13170
|
+
action: external_exports.enum(["list", "active", "create", "snooze", "complete", "dismiss"]).describe("Action to perform"),
|
|
13171
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
13172
|
+
project_id: external_exports.string().uuid().optional(),
|
|
13173
|
+
reminder_id: external_exports.string().uuid().optional(),
|
|
13174
|
+
// Create params
|
|
13175
|
+
title: external_exports.string().optional(),
|
|
13176
|
+
content: external_exports.string().optional(),
|
|
13177
|
+
remind_at: external_exports.string().optional().describe("ISO 8601 datetime"),
|
|
13178
|
+
priority: external_exports.enum(["low", "normal", "high", "urgent"]).optional(),
|
|
13179
|
+
recurrence: external_exports.enum(["daily", "weekly", "monthly"]).optional(),
|
|
13180
|
+
keywords: external_exports.array(external_exports.string()).optional(),
|
|
13181
|
+
// Snooze params
|
|
13182
|
+
until: external_exports.string().optional().describe("ISO 8601 datetime"),
|
|
13183
|
+
// Filter params
|
|
13184
|
+
status: external_exports.enum(["pending", "completed", "dismissed", "snoozed"]).optional(),
|
|
13185
|
+
context: external_exports.string().optional(),
|
|
13186
|
+
limit: external_exports.number().optional()
|
|
13187
|
+
})
|
|
13188
|
+
},
|
|
13189
|
+
async (input) => {
|
|
13190
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
13191
|
+
const projectId = resolveProjectId(input.project_id);
|
|
13192
|
+
switch (input.action) {
|
|
13193
|
+
case "list": {
|
|
13194
|
+
const result = await client.remindersList({
|
|
13195
|
+
workspace_id: workspaceId,
|
|
13196
|
+
project_id: projectId,
|
|
13197
|
+
status: input.status,
|
|
13198
|
+
priority: input.priority,
|
|
13199
|
+
limit: input.limit
|
|
13200
|
+
});
|
|
13201
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13202
|
+
}
|
|
13203
|
+
case "active": {
|
|
13204
|
+
const result = await client.remindersActive({
|
|
13205
|
+
workspace_id: workspaceId,
|
|
13206
|
+
project_id: projectId,
|
|
13207
|
+
context: input.context,
|
|
13208
|
+
limit: input.limit
|
|
13209
|
+
});
|
|
13210
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13211
|
+
}
|
|
13212
|
+
case "create": {
|
|
13213
|
+
if (!input.title || !input.content || !input.remind_at) {
|
|
13214
|
+
return errorResult("create requires: title, content, remind_at");
|
|
13215
|
+
}
|
|
13216
|
+
const result = await client.remindersCreate({
|
|
13217
|
+
workspace_id: workspaceId,
|
|
13218
|
+
project_id: projectId,
|
|
13219
|
+
title: input.title,
|
|
13220
|
+
content: input.content,
|
|
13221
|
+
remind_at: input.remind_at,
|
|
13222
|
+
priority: input.priority,
|
|
13223
|
+
recurrence: input.recurrence,
|
|
13224
|
+
keywords: input.keywords
|
|
13225
|
+
});
|
|
13226
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13227
|
+
}
|
|
13228
|
+
case "snooze": {
|
|
13229
|
+
if (!input.reminder_id || !input.until) {
|
|
13230
|
+
return errorResult("snooze requires: reminder_id, until");
|
|
13231
|
+
}
|
|
13232
|
+
const result = await client.remindersSnooze({
|
|
13233
|
+
reminder_id: input.reminder_id,
|
|
13234
|
+
until: input.until
|
|
13235
|
+
});
|
|
13236
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13237
|
+
}
|
|
13238
|
+
case "complete": {
|
|
13239
|
+
if (!input.reminder_id) {
|
|
13240
|
+
return errorResult("complete requires: reminder_id");
|
|
13241
|
+
}
|
|
13242
|
+
const result = await client.remindersComplete({
|
|
13243
|
+
reminder_id: input.reminder_id
|
|
13244
|
+
});
|
|
13245
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13246
|
+
}
|
|
13247
|
+
case "dismiss": {
|
|
13248
|
+
if (!input.reminder_id) {
|
|
13249
|
+
return errorResult("dismiss requires: reminder_id");
|
|
13250
|
+
}
|
|
13251
|
+
const result = await client.remindersDismiss({
|
|
13252
|
+
reminder_id: input.reminder_id
|
|
13253
|
+
});
|
|
13254
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13255
|
+
}
|
|
13256
|
+
default:
|
|
13257
|
+
return errorResult(`Unknown action: ${input.action}`);
|
|
13258
|
+
}
|
|
13259
|
+
}
|
|
13260
|
+
);
|
|
13261
|
+
registerTool(
|
|
13262
|
+
"integration",
|
|
13263
|
+
{
|
|
13264
|
+
title: "Integration",
|
|
13265
|
+
description: `Integration operations for Slack and GitHub. Provider: slack, github, all. Actions: status, search, stats, activity, contributors, knowledge, summary, channels (slack), discussions (slack), repos (github), issues (github).`,
|
|
13266
|
+
inputSchema: external_exports.object({
|
|
13267
|
+
provider: external_exports.enum(["slack", "github", "all"]).describe("Integration provider"),
|
|
13268
|
+
action: external_exports.enum([
|
|
13269
|
+
"status",
|
|
13270
|
+
"search",
|
|
13271
|
+
"stats",
|
|
13272
|
+
"activity",
|
|
13273
|
+
"contributors",
|
|
13274
|
+
"knowledge",
|
|
13275
|
+
"summary",
|
|
13276
|
+
"channels",
|
|
13277
|
+
"discussions",
|
|
13278
|
+
"sync_users",
|
|
13279
|
+
"repos",
|
|
13280
|
+
"issues"
|
|
13281
|
+
]).describe("Action to perform"),
|
|
13282
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
13283
|
+
project_id: external_exports.string().uuid().optional(),
|
|
13284
|
+
query: external_exports.string().optional(),
|
|
13285
|
+
limit: external_exports.number().optional(),
|
|
13286
|
+
since: external_exports.string().optional(),
|
|
13287
|
+
until: external_exports.string().optional()
|
|
13288
|
+
})
|
|
13289
|
+
},
|
|
13290
|
+
async (input) => {
|
|
13291
|
+
const workspaceId = resolveWorkspaceId(input.workspace_id);
|
|
13292
|
+
const projectId = resolveProjectId(input.project_id);
|
|
13293
|
+
const integrationGated = await gateIfIntegrationTool(
|
|
13294
|
+
input.provider === "slack" ? "slack_search" : input.provider === "github" ? "github_search" : "integrations_status"
|
|
13295
|
+
);
|
|
13296
|
+
if (integrationGated) return integrationGated;
|
|
13297
|
+
const params = {
|
|
13298
|
+
workspace_id: workspaceId,
|
|
13299
|
+
project_id: projectId,
|
|
13300
|
+
query: input.query,
|
|
13301
|
+
limit: input.limit,
|
|
13302
|
+
since: input.since,
|
|
13303
|
+
until: input.until
|
|
13304
|
+
};
|
|
13305
|
+
switch (input.action) {
|
|
13306
|
+
case "status": {
|
|
13307
|
+
const result = await client.integrationsStatus(params);
|
|
13308
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13309
|
+
}
|
|
13310
|
+
case "search": {
|
|
13311
|
+
if (input.provider === "slack") {
|
|
13312
|
+
const result = await client.slackSearch(params);
|
|
13313
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13314
|
+
} else if (input.provider === "github") {
|
|
13315
|
+
const result = await client.githubSearch(params);
|
|
13316
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13317
|
+
} else {
|
|
13318
|
+
const result = await client.integrationsSearch(params);
|
|
13319
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13320
|
+
}
|
|
13321
|
+
}
|
|
13322
|
+
case "stats": {
|
|
13323
|
+
if (input.provider === "slack") {
|
|
13324
|
+
const result = await client.slackStats(params);
|
|
13325
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13326
|
+
} else if (input.provider === "github") {
|
|
13327
|
+
const result = await client.githubStats(params);
|
|
13328
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13329
|
+
}
|
|
13330
|
+
return errorResult("stats requires provider: slack or github");
|
|
13331
|
+
}
|
|
13332
|
+
case "activity": {
|
|
13333
|
+
if (input.provider === "slack") {
|
|
13334
|
+
const result = await client.slackActivity(params);
|
|
13335
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13336
|
+
} else if (input.provider === "github") {
|
|
13337
|
+
const result = await client.githubActivity(params);
|
|
13338
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13339
|
+
}
|
|
13340
|
+
return errorResult("activity requires provider: slack or github");
|
|
13341
|
+
}
|
|
13342
|
+
case "contributors": {
|
|
13343
|
+
if (input.provider === "slack") {
|
|
13344
|
+
const result = await client.slackContributors(params);
|
|
13345
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13346
|
+
} else if (input.provider === "github") {
|
|
13347
|
+
const result = await client.githubContributors(params);
|
|
13348
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13349
|
+
}
|
|
13350
|
+
return errorResult("contributors requires provider: slack or github");
|
|
13351
|
+
}
|
|
13352
|
+
case "knowledge": {
|
|
13353
|
+
if (input.provider === "slack") {
|
|
13354
|
+
const result = await client.slackKnowledge(params);
|
|
13355
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13356
|
+
} else if (input.provider === "github") {
|
|
13357
|
+
const result = await client.githubKnowledge(params);
|
|
13358
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13359
|
+
} else {
|
|
13360
|
+
const result = await client.integrationsKnowledge(params);
|
|
13361
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13362
|
+
}
|
|
13363
|
+
}
|
|
13364
|
+
case "summary": {
|
|
13365
|
+
if (input.provider === "slack") {
|
|
13366
|
+
const result = await client.slackSummary(params);
|
|
13367
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13368
|
+
} else if (input.provider === "github") {
|
|
13369
|
+
const result = await client.githubSummary(params);
|
|
13370
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13371
|
+
} else {
|
|
13372
|
+
const result = await client.integrationsSummary(params);
|
|
13373
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13374
|
+
}
|
|
13375
|
+
}
|
|
13376
|
+
case "channels": {
|
|
13377
|
+
if (input.provider !== "slack") {
|
|
13378
|
+
return errorResult("channels is only available for slack provider");
|
|
13379
|
+
}
|
|
13380
|
+
const result = await client.slackChannels(params);
|
|
13381
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13382
|
+
}
|
|
13383
|
+
case "discussions": {
|
|
13384
|
+
if (input.provider !== "slack") {
|
|
13385
|
+
return errorResult("discussions is only available for slack provider");
|
|
13386
|
+
}
|
|
13387
|
+
const result = await client.slackDiscussions(params);
|
|
13388
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13389
|
+
}
|
|
13390
|
+
case "sync_users": {
|
|
13391
|
+
if (input.provider !== "slack") {
|
|
13392
|
+
return errorResult("sync_users is only available for slack provider");
|
|
13393
|
+
}
|
|
13394
|
+
const result = await client.slackSyncUsers(params);
|
|
13395
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13396
|
+
}
|
|
13397
|
+
case "repos": {
|
|
13398
|
+
if (input.provider !== "github") {
|
|
13399
|
+
return errorResult("repos is only available for github provider");
|
|
13400
|
+
}
|
|
13401
|
+
const result = await client.githubRepos(params);
|
|
13402
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13403
|
+
}
|
|
13404
|
+
case "issues": {
|
|
13405
|
+
if (input.provider !== "github") {
|
|
13406
|
+
return errorResult("issues is only available for github provider");
|
|
13407
|
+
}
|
|
13408
|
+
const result = await client.githubIssues(params);
|
|
13409
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13410
|
+
}
|
|
13411
|
+
default:
|
|
13412
|
+
return errorResult(`Unknown action: ${input.action}`);
|
|
13413
|
+
}
|
|
13414
|
+
}
|
|
13415
|
+
);
|
|
13416
|
+
registerTool(
|
|
13417
|
+
"help",
|
|
13418
|
+
{
|
|
13419
|
+
title: "Help",
|
|
13420
|
+
description: `Utility and help. Actions: tools (list available tools), auth (current user), version (server version), editor_rules (generate AI editor rules), enable_bundle (enable tool bundle in progressive mode).`,
|
|
13421
|
+
inputSchema: external_exports.object({
|
|
13422
|
+
action: external_exports.enum(["tools", "auth", "version", "editor_rules", "enable_bundle"]).describe("Action to perform"),
|
|
13423
|
+
// For tools
|
|
13424
|
+
format: external_exports.enum(["grouped", "minimal", "full"]).optional(),
|
|
13425
|
+
category: external_exports.string().optional(),
|
|
13426
|
+
// For editor_rules
|
|
13427
|
+
folder_path: external_exports.string().optional(),
|
|
13428
|
+
editors: external_exports.array(external_exports.string()).optional(),
|
|
13429
|
+
mode: external_exports.enum(["minimal", "full"]).optional(),
|
|
13430
|
+
dry_run: external_exports.boolean().optional(),
|
|
13431
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
13432
|
+
workspace_name: external_exports.string().optional(),
|
|
13433
|
+
project_name: external_exports.string().optional(),
|
|
13434
|
+
additional_rules: external_exports.string().optional(),
|
|
13435
|
+
// For enable_bundle
|
|
13436
|
+
bundle: external_exports.enum(["session", "memory", "search", "graph", "workspace", "project", "reminders", "integrations"]).optional(),
|
|
13437
|
+
list_bundles: external_exports.boolean().optional()
|
|
13438
|
+
})
|
|
13439
|
+
},
|
|
13440
|
+
async (input) => {
|
|
13441
|
+
switch (input.action) {
|
|
13442
|
+
case "tools": {
|
|
13443
|
+
const format = input.format || "grouped";
|
|
13444
|
+
const catalog = generateToolCatalog(format, input.category);
|
|
13445
|
+
const consolidatedInfo = CONSOLIDATED_MODE ? `
|
|
13446
|
+
|
|
13447
|
+
[Consolidated Mode]
|
|
13448
|
+
Domain tools: ${Array.from(CONSOLIDATED_TOOLS).join(", ")}
|
|
13449
|
+
Each domain tool has an 'action' parameter for specific operations.` : "";
|
|
13450
|
+
return {
|
|
13451
|
+
content: [{ type: "text", text: catalog + consolidatedInfo }],
|
|
13452
|
+
structuredContent: {
|
|
13453
|
+
format,
|
|
13454
|
+
catalog,
|
|
13455
|
+
consolidated_mode: CONSOLIDATED_MODE,
|
|
13456
|
+
domain_tools: CONSOLIDATED_MODE ? Array.from(CONSOLIDATED_TOOLS) : void 0
|
|
13457
|
+
}
|
|
13458
|
+
};
|
|
13459
|
+
}
|
|
13460
|
+
case "auth": {
|
|
13461
|
+
const result = await client.me();
|
|
13462
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13463
|
+
}
|
|
13464
|
+
case "version": {
|
|
13465
|
+
const result = { name: "contextstream-mcp", version: VERSION };
|
|
13466
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13467
|
+
}
|
|
13468
|
+
case "editor_rules": {
|
|
13469
|
+
if (!input.folder_path) {
|
|
13470
|
+
return errorResult("editor_rules requires: folder_path");
|
|
13471
|
+
}
|
|
13472
|
+
const result = await generateAllRuleFiles(input.folder_path, {
|
|
13473
|
+
editors: input.editors,
|
|
13474
|
+
mode: input.mode,
|
|
13475
|
+
dryRun: input.dry_run,
|
|
13476
|
+
workspaceId: input.workspace_id,
|
|
13477
|
+
workspaceName: input.workspace_name,
|
|
13478
|
+
projectName: input.project_name,
|
|
13479
|
+
additionalRules: input.additional_rules
|
|
13480
|
+
});
|
|
13481
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13482
|
+
}
|
|
13483
|
+
case "enable_bundle": {
|
|
13484
|
+
if (input.list_bundles) {
|
|
13485
|
+
const bundles = getBundleInfo();
|
|
13486
|
+
const result2 = {
|
|
13487
|
+
progressive_mode: PROGRESSIVE_MODE,
|
|
13488
|
+
consolidated_mode: CONSOLIDATED_MODE,
|
|
13489
|
+
bundles,
|
|
13490
|
+
hint: CONSOLIDATED_MODE ? "Consolidated mode is enabled. All operations are available via domain tools." : PROGRESSIVE_MODE ? "Progressive mode is enabled. Use enable_bundle to unlock additional tools." : "Neither progressive nor consolidated mode is enabled."
|
|
13491
|
+
};
|
|
13492
|
+
return { content: [{ type: "text", text: formatContent(result2) }], structuredContent: toStructured(result2) };
|
|
13493
|
+
}
|
|
13494
|
+
if (!input.bundle) {
|
|
13495
|
+
return errorResult("enable_bundle requires: bundle (or use list_bundles: true)");
|
|
13496
|
+
}
|
|
13497
|
+
if (CONSOLIDATED_MODE) {
|
|
13498
|
+
return {
|
|
13499
|
+
content: [{ type: "text", text: "Consolidated mode is enabled. All operations are available via domain tools (search, session, memory, graph, project, workspace, reminder, integration, help)." }]
|
|
13500
|
+
};
|
|
13501
|
+
}
|
|
13502
|
+
if (!PROGRESSIVE_MODE) {
|
|
13503
|
+
return {
|
|
13504
|
+
content: [{ type: "text", text: "Progressive mode is not enabled. All tools from your toolset are already available." }]
|
|
13505
|
+
};
|
|
13506
|
+
}
|
|
13507
|
+
const result = enableBundle(input.bundle);
|
|
13508
|
+
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
13509
|
+
}
|
|
13510
|
+
default:
|
|
13511
|
+
return errorResult(`Unknown action: ${input.action}`);
|
|
13512
|
+
}
|
|
13513
|
+
}
|
|
13514
|
+
);
|
|
13515
|
+
console.error(`[ContextStream] Consolidated mode: Registered ${CONSOLIDATED_TOOLS.size} domain tools.`);
|
|
13516
|
+
}
|
|
12056
13517
|
}
|
|
12057
13518
|
|
|
12058
13519
|
// src/resources.ts
|
|
@@ -14534,6 +15995,9 @@ Environment variables:
|
|
|
14534
15995
|
CONTEXTSTREAM_AUTO_HIDE_INTEGRATIONS Auto-hide Slack/GitHub tools when not connected (default: true)
|
|
14535
15996
|
CONTEXTSTREAM_SCHEMA_MODE Schema verbosity: compact|full (default: full, compact reduces tokens)
|
|
14536
15997
|
CONTEXTSTREAM_PROGRESSIVE_MODE Progressive disclosure: true|false (default: false, starts with ~13 core tools)
|
|
15998
|
+
CONTEXTSTREAM_ROUTER_MODE Router pattern: true|false (default: false, exposes only 2 meta-tools)
|
|
15999
|
+
CONTEXTSTREAM_OUTPUT_FORMAT Output verbosity: compact|pretty (default: compact, ~30% fewer tokens)
|
|
16000
|
+
CONTEXTSTREAM_CONSOLIDATED Consolidated domain tools: true|false (default: true in v0.4.x, ~75% token reduction)
|
|
14537
16001
|
CONTEXTSTREAM_PRO_TOOLS Optional comma-separated PRO tool names (default: AI tools)
|
|
14538
16002
|
CONTEXTSTREAM_UPGRADE_URL Optional upgrade URL shown for PRO tools on Free plan
|
|
14539
16003
|
CONTEXTSTREAM_ENABLE_PROMPTS Enable MCP prompts list (default: true)
|