create-walle 0.9.13 → 0.9.14
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/README.md +6 -1
- package/bin/create-walle.js +195 -30
- package/bin/mcp-inject.js +18 -53
- package/package.json +3 -1
- package/template/claude-task-manager/approval-agent.js +7 -0
- package/template/claude-task-manager/docs/session-standup-command-center-design.md +242 -0
- package/template/claude-task-manager/git-utils.js +111 -3
- package/template/claude-task-manager/lib/session-history.js +144 -16
- package/template/claude-task-manager/lib/session-standup.js +409 -0
- package/template/claude-task-manager/lib/standup-attention.js +200 -0
- package/template/claude-task-manager/lib/status-hooks.js +8 -2
- package/template/claude-task-manager/lib/update-telemetry.js +114 -0
- package/template/claude-task-manager/lib/walle-default-model.js +55 -0
- package/template/claude-task-manager/lib/walle-mcp-auto-config.js +62 -0
- package/template/claude-task-manager/lib/walle-supervisor.js +83 -19
- package/template/claude-task-manager/lib/worktree-cwd.js +82 -0
- package/template/claude-task-manager/providers/codex-mcp.js +104 -0
- package/template/claude-task-manager/providers/index.js +2 -0
- package/template/claude-task-manager/public/css/setup.css +2 -1
- package/template/claude-task-manager/public/css/walle.css +5 -0
- package/template/claude-task-manager/public/index.html +1596 -283
- package/template/claude-task-manager/public/js/session-search-utils.js +171 -1
- package/template/claude-task-manager/public/js/setup.js +62 -19
- package/template/claude-task-manager/public/js/stream-view.js +55 -6
- package/template/claude-task-manager/public/js/walle-session.js +73 -16
- package/template/claude-task-manager/public/js/walle.js +34 -2
- package/template/claude-task-manager/server.js +780 -177
- package/template/claude-task-manager/session-integrity.js +58 -15
- package/template/claude-task-manager/workers/approval-widget-validator.js +15 -5
- package/template/claude-task-manager/workers/state-detectors/codex.js +6 -0
- package/template/package.json +1 -1
- package/template/wall-e/agent.js +36 -7
- package/template/wall-e/api-walle.js +72 -20
- package/template/wall-e/coding/stream-processor.js +22 -2
- package/template/wall-e/coding-orchestrator.js +26 -6
- package/template/wall-e/eval/agent-runner.js +16 -4
- package/template/wall-e/eval/benchmark-generator.js +21 -1
- package/template/wall-e/eval/benchmarks/coding-agent.json +0 -596
- package/template/wall-e/eval/codex-cli-baseline.js +633 -0
- package/template/wall-e/eval/eval-orchestrator.js +3 -3
- package/template/wall-e/eval/run-agent-benchmarks.js +11 -3
- package/template/wall-e/eval/run-codex-cli-baseline.js +177 -0
- package/template/wall-e/lib/mcp-integration.js +220 -0
- package/template/wall-e/llm/ollama.js +47 -8
- package/template/wall-e/llm/ollama.plugin.json +1 -1
- package/template/wall-e/llm/tool-adapter.js +1 -0
- package/template/wall-e/loops/ingest.js +42 -8
- package/template/wall-e/mcp-server.js +272 -10
- package/template/wall-e/memory/ctm-session-context.js +910 -0
- package/template/wall-e/server.js +26 -1
- package/template/wall-e/skills/_bundled/scan-ctm-sessions/SKILL.md +20 -0
- package/template/wall-e/skills/_bundled/scan-ctm-sessions/run.js +43 -0
- package/template/wall-e/skills/skill-planner.js +52 -3
- package/template/wall-e/tools/builtin-middleware.js +55 -2
- package/template/wall-e/tools/shell-policy.js +1 -1
- package/template/wall-e/tools/slack-owner.js +104 -0
- package/template/website/index.html +2 -2
- package/template/builder-journal.md +0 -17
|
@@ -4,6 +4,7 @@ const path = require('node:path');
|
|
|
4
4
|
const { v4: uuidv4 } = require('uuid');
|
|
5
5
|
const brain = require('./brain');
|
|
6
6
|
const { createSessionIngestService } = require('./memory/session-ingest-service');
|
|
7
|
+
const ctmSessionContext = require('./memory/ctm-session-context');
|
|
7
8
|
const { collectIngestRecords } = require('./sources/base');
|
|
8
9
|
const { ensureBuiltinSourceAdapters } = require('./sources/builtin');
|
|
9
10
|
const sourceRegistry = require('./sources/registry');
|
|
@@ -13,6 +14,36 @@ try { _embeddings = require('./embeddings'); } catch { _embeddings = null; }
|
|
|
13
14
|
|
|
14
15
|
const PROTOCOL_VERSION = '2025-03-26';
|
|
15
16
|
|
|
17
|
+
const MCP_RESOURCES = [
|
|
18
|
+
{
|
|
19
|
+
uri: 'walle://status/session-memory',
|
|
20
|
+
name: 'Wall-E session memory status',
|
|
21
|
+
description: 'Operational status for Wall-E brain memory and CTM cached session-context access.',
|
|
22
|
+
mimeType: 'application/json',
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const MCP_RESOURCE_TEMPLATES = [
|
|
27
|
+
{
|
|
28
|
+
uriTemplate: 'walle-session://ctm/{session_id}/full',
|
|
29
|
+
name: 'CTM session full context',
|
|
30
|
+
description: 'Full cached CTM session context from session_conversations/session_messages. Use for explicit session transfer.',
|
|
31
|
+
mimeType: 'application/json',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
uriTemplate: 'walle-session://ctm/{session_id}/compact',
|
|
35
|
+
name: 'CTM session compact context',
|
|
36
|
+
description: 'Prompt-friendly markdown view of cached CTM session context.',
|
|
37
|
+
mimeType: 'text/markdown',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
uriTemplate: 'walle-context://task/{query}',
|
|
41
|
+
name: 'Task-scoped CTM context pack',
|
|
42
|
+
description: 'Search cached CTM sessions for a task prompt and return a deduplicated context pack.',
|
|
43
|
+
mimeType: 'text/markdown',
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
|
|
16
47
|
const MCP_TOOLS = [
|
|
17
48
|
{
|
|
18
49
|
name: 'search_memories',
|
|
@@ -199,30 +230,54 @@ const MCP_TOOLS = [
|
|
|
199
230
|
},
|
|
200
231
|
{
|
|
201
232
|
name: 'walle_search_sessions',
|
|
202
|
-
description: 'Search
|
|
233
|
+
description: 'Search coding-session history. Tries cached CTM DB session messages first, then ingested Wall-E memories/diary entries. Returns deduplicated attributed snippets plus session pointers.',
|
|
203
234
|
inputSchema: {
|
|
204
235
|
type: 'object',
|
|
205
236
|
properties: {
|
|
206
237
|
query: { type: 'string', description: 'Search query' },
|
|
207
238
|
limit: { type: 'number', description: 'Max session snippets (default 10, max 50)' },
|
|
239
|
+
prefer_db: { type: 'boolean', description: 'Try cached CTM DB tables before Wall-E memory (default true)' },
|
|
240
|
+
include_memory: { type: 'boolean', description: 'Also search Wall-E ingested memories and diary entries (default true)' },
|
|
208
241
|
},
|
|
209
242
|
required: ['query'],
|
|
210
243
|
},
|
|
211
244
|
},
|
|
212
245
|
{
|
|
213
246
|
name: 'walle_get_session',
|
|
214
|
-
description: 'Retrieve session
|
|
247
|
+
description: 'Retrieve cached CTM session context by session id/source id, or parse a JSONL session directly when adapter_id and uri are provided. DB tables are preferred for full context transfer.',
|
|
215
248
|
inputSchema: {
|
|
216
249
|
type: 'object',
|
|
217
250
|
properties: {
|
|
251
|
+
session_id: { type: 'string', description: 'CTM session id or agent session id to retrieve from cached DB tables' },
|
|
252
|
+
session_ids: { type: 'array', items: { type: 'string' }, description: 'Several CTM/agent session ids to retrieve together' },
|
|
218
253
|
source_id: { type: 'string', description: 'Stable source/session id to retrieve from memory' },
|
|
219
254
|
adapter_id: { type: 'string', description: 'Optional adapter id for direct JSONL parse' },
|
|
220
255
|
uri: { type: 'string', description: 'Optional JSONL path for direct parse' },
|
|
221
|
-
limit: { type: 'number', description: 'Max records (default 50,
|
|
256
|
+
limit: { type: 'number', description: 'Max records/messages (default 50 for memory, 200 for CTM DB; use 0/full/all for all cached DB messages)' },
|
|
257
|
+
cursor: { type: 'number', description: 'Message offset for cached DB pagination' },
|
|
258
|
+
format: { type: 'string', description: 'Cached DB output format: messages, markdown, or compact' },
|
|
259
|
+
dedupe: { type: 'boolean', description: 'Deduplicate repeated message content (default true)' },
|
|
260
|
+
prefer_db: { type: 'boolean', description: 'Use cached CTM DB tables before Wall-E memory fallback (default true)' },
|
|
222
261
|
include_raw: { type: 'boolean', description: 'Include raw content when available' },
|
|
223
262
|
},
|
|
224
263
|
},
|
|
225
264
|
},
|
|
265
|
+
{
|
|
266
|
+
name: 'walle_context_pack',
|
|
267
|
+
description: 'Build a deduplicated task-scoped context pack from cached CTM session history. Use before starting a coding task to discover prior attempts and relevant implementation context.',
|
|
268
|
+
inputSchema: {
|
|
269
|
+
type: 'object',
|
|
270
|
+
properties: {
|
|
271
|
+
task: { type: 'string', description: 'Current user prompt or task description' },
|
|
272
|
+
query: { type: 'string', description: 'Optional explicit search query; defaults to task' },
|
|
273
|
+
session_ids: { type: 'array', items: { type: 'string' }, description: 'Optional CTM/agent session ids to force include' },
|
|
274
|
+
limit: { type: 'number', description: 'Max sessions to include (default 5, max 50)' },
|
|
275
|
+
token_budget: { type: 'number', description: 'Approximate context-pack token budget (default 12000)' },
|
|
276
|
+
mode: { type: 'string', description: 'auto, compact, or full' },
|
|
277
|
+
include_raw: { type: 'boolean', description: 'Include raw cached messages when mode/full transfer needs exact source payloads' },
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
226
281
|
{
|
|
227
282
|
name: 'walle_diary_write',
|
|
228
283
|
description: 'Write an idempotent agent diary entry for a coding session stop, handoff, or compaction boundary.',
|
|
@@ -412,6 +467,11 @@ async function executeTool(name, args) {
|
|
|
412
467
|
return {
|
|
413
468
|
ok: true,
|
|
414
469
|
stats,
|
|
470
|
+
ctm_db: getCtmDbStatus(),
|
|
471
|
+
resources: {
|
|
472
|
+
static: MCP_RESOURCES.map((resource) => resource.uri),
|
|
473
|
+
templates: MCP_RESOURCE_TEMPLATES.map((template) => template.uriTemplate),
|
|
474
|
+
},
|
|
415
475
|
source_adapters: sourceRegistry.list().map(formatSourceAdapter),
|
|
416
476
|
diary_count: countDiaryEntries(),
|
|
417
477
|
tools: MCP_TOOLS.filter((tool) => tool.name.startsWith('walle_')).map((tool) => tool.name),
|
|
@@ -446,11 +506,45 @@ async function executeTool(name, args) {
|
|
|
446
506
|
}
|
|
447
507
|
case 'walle_search_sessions': {
|
|
448
508
|
const limit = clampLimit(args.limit, 10, 50);
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
.
|
|
452
|
-
|
|
453
|
-
|
|
509
|
+
const ctmResults = args.prefer_db === false
|
|
510
|
+
? { ok: false, results: [], skipped: true, reason: 'prefer_db_false' }
|
|
511
|
+
: safeCtmSearchSessions({ query: args.query, limit });
|
|
512
|
+
const memoryResults = args.include_memory === false
|
|
513
|
+
? []
|
|
514
|
+
: brain.searchMemories({ query: args.query, limit: limit * 4 })
|
|
515
|
+
.filter(isSessionMemory)
|
|
516
|
+
.slice(0, limit * 2)
|
|
517
|
+
.map((memory, index) => ({
|
|
518
|
+
...formatSessionMemory(memory),
|
|
519
|
+
source_layer: 'wall-e-memory',
|
|
520
|
+
rank: 10000 + index,
|
|
521
|
+
}));
|
|
522
|
+
const dbResults = (ctmResults.results || []).map((result, index) => ({
|
|
523
|
+
...result,
|
|
524
|
+
source_layer: 'ctm-db',
|
|
525
|
+
rank: Number.isFinite(result.rank) ? result.rank : index,
|
|
526
|
+
}));
|
|
527
|
+
const results = ctmSessionContext.dedupeItems([...dbResults, ...memoryResults], {
|
|
528
|
+
limit,
|
|
529
|
+
contentFields: ['snippet', 'content'],
|
|
530
|
+
keyPrefix: (item) => `${item.session_id || item.source_id || ''}:${item.role || item.memory_type || ''}`,
|
|
531
|
+
}).map(stripRank);
|
|
532
|
+
return {
|
|
533
|
+
results,
|
|
534
|
+
sources: {
|
|
535
|
+
ctm_db: {
|
|
536
|
+
ok: Boolean(ctmResults.ok),
|
|
537
|
+
unavailable: Boolean(ctmResults.unavailable),
|
|
538
|
+
reason: ctmResults.reason || '',
|
|
539
|
+
count: (ctmResults.results || []).length,
|
|
540
|
+
},
|
|
541
|
+
wall_e_memory: {
|
|
542
|
+
searched: args.include_memory !== false,
|
|
543
|
+
count: memoryResults.length,
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
deduped: true,
|
|
547
|
+
};
|
|
454
548
|
}
|
|
455
549
|
case 'walle_get_session': {
|
|
456
550
|
const limit = clampLimit(args.limit, 50, 200);
|
|
@@ -475,12 +569,47 @@ async function executeTool(name, args) {
|
|
|
475
569
|
.map((record) => formatSourceRecord(record, { includeRaw: Boolean(args.include_raw) })),
|
|
476
570
|
};
|
|
477
571
|
}
|
|
572
|
+
const wantsDb = args.prefer_db !== false;
|
|
573
|
+
const dbSessionIds = args.session_ids || args.session_id || args.source_id;
|
|
574
|
+
if (wantsDb && dbSessionIds) {
|
|
575
|
+
const dbContext = safeCtmSessionContext({
|
|
576
|
+
session_ids: args.session_ids,
|
|
577
|
+
session_id: args.session_id,
|
|
578
|
+
source_id: args.source_id,
|
|
579
|
+
limit: args.limit ?? 200,
|
|
580
|
+
cursor: args.cursor || 0,
|
|
581
|
+
include_raw: Boolean(args.include_raw),
|
|
582
|
+
dedupe: args.dedupe !== false,
|
|
583
|
+
format: args.format || 'messages',
|
|
584
|
+
});
|
|
585
|
+
if (dbContext.ok && (dbContext.sessions.length > 0 || dbContext.messages.length > 0)) {
|
|
586
|
+
return dbContext;
|
|
587
|
+
}
|
|
588
|
+
if (args.session_id || args.session_ids) return dbContext;
|
|
589
|
+
}
|
|
478
590
|
if (!args.source_id) throw new Error('source_id is required when adapter_id and uri are not provided');
|
|
479
591
|
return {
|
|
480
592
|
source_id: args.source_id,
|
|
593
|
+
transfer: {
|
|
594
|
+
full_context_supported: false,
|
|
595
|
+
served_from: 'wall-e-memory',
|
|
596
|
+
jsonl_fallback_used: false,
|
|
597
|
+
ctm_db_preferred: wantsDb,
|
|
598
|
+
},
|
|
481
599
|
records: getSessionMemories(args.source_id, { limit }).map(formatSessionMemory),
|
|
482
600
|
};
|
|
483
601
|
}
|
|
602
|
+
case 'walle_context_pack': {
|
|
603
|
+
return safeCtmContextPack({
|
|
604
|
+
task: args.task || '',
|
|
605
|
+
query: args.query || '',
|
|
606
|
+
session_ids: args.session_ids,
|
|
607
|
+
limit: args.limit || 5,
|
|
608
|
+
token_budget: args.token_budget || 12000,
|
|
609
|
+
mode: args.mode || 'auto',
|
|
610
|
+
include_raw: Boolean(args.include_raw),
|
|
611
|
+
});
|
|
612
|
+
}
|
|
484
613
|
case 'walle_diary_write': {
|
|
485
614
|
return writeDiaryEntry(args);
|
|
486
615
|
}
|
|
@@ -514,6 +643,46 @@ function clampLimit(value, fallback, max) {
|
|
|
514
643
|
return Math.min(Math.max(Math.trunc(n), 1), max);
|
|
515
644
|
}
|
|
516
645
|
|
|
646
|
+
function stripRank(item) {
|
|
647
|
+
if (!item || typeof item !== 'object') return item;
|
|
648
|
+
const { rank, ...rest } = item;
|
|
649
|
+
return rest;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function getCtmDbStatus() {
|
|
653
|
+
const dbPath = ctmSessionContext.resolveCtmDbPath();
|
|
654
|
+
return {
|
|
655
|
+
available: fs.existsSync(dbPath),
|
|
656
|
+
db_path: dbPath,
|
|
657
|
+
serving_priority: 'ctm-db-first',
|
|
658
|
+
cached_tables: ['session_conversations', 'session_messages', 'session_messages_fts', 'ctm_sessions', 'agent_sessions'],
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function safeCtmSearchSessions(args) {
|
|
663
|
+
try {
|
|
664
|
+
return ctmSessionContext.searchCtmSessions(args);
|
|
665
|
+
} catch (err) {
|
|
666
|
+
return { ok: false, source: 'ctm-db', results: [], reason: err.message };
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function safeCtmSessionContext(args) {
|
|
671
|
+
try {
|
|
672
|
+
return ctmSessionContext.getCtmSessionContext(args);
|
|
673
|
+
} catch (err) {
|
|
674
|
+
return { ok: false, source: 'ctm-db', sessions: [], messages: [], reason: err.message };
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
function safeCtmContextPack(args) {
|
|
679
|
+
try {
|
|
680
|
+
return ctmSessionContext.buildContextPack(args);
|
|
681
|
+
} catch (err) {
|
|
682
|
+
return { ok: false, source: 'ctm-db', sessions: [], messages: [], reason: err.message };
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
517
686
|
function assertJsonlPath(filePath) {
|
|
518
687
|
if (!filePath || typeof filePath !== 'string') throw new Error('uri must be a JSONL file path');
|
|
519
688
|
if (filePath.split(/[\\/]+/).includes('..')) throw new Error('uri cannot contain traversal segments');
|
|
@@ -748,6 +917,63 @@ function jsonResponse(res, data, status = 200) {
|
|
|
748
917
|
res.end(body);
|
|
749
918
|
}
|
|
750
919
|
|
|
920
|
+
async function readMcpResource(uri) {
|
|
921
|
+
if (!uri || typeof uri !== 'string') throw new Error('resource uri is required');
|
|
922
|
+
|
|
923
|
+
if (uri === 'walle://status/session-memory') {
|
|
924
|
+
return {
|
|
925
|
+
uri,
|
|
926
|
+
mimeType: 'application/json',
|
|
927
|
+
text: JSON.stringify(await executeTool('walle_memory_status', {})),
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
let parsed;
|
|
932
|
+
try {
|
|
933
|
+
parsed = new URL(uri);
|
|
934
|
+
} catch {
|
|
935
|
+
throw new Error(`Invalid resource uri: ${uri}`);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
if (parsed.protocol === 'walle-session:' && parsed.hostname === 'ctm') {
|
|
939
|
+
const [rawSessionId, rawMode] = parsed.pathname.split('/').filter(Boolean);
|
|
940
|
+
if (!rawSessionId) throw new Error('walle-session resource requires a session id');
|
|
941
|
+
const sessionId = decodeURIComponent(rawSessionId);
|
|
942
|
+
const mode = rawMode || 'full';
|
|
943
|
+
const context = ctmSessionContext.getCtmSessionContext({
|
|
944
|
+
session_id: sessionId,
|
|
945
|
+
limit: mode === 'full' || mode === 'messages' ? 0 : 200,
|
|
946
|
+
format: mode === 'compact' || mode === 'summary' ? 'compact' : 'messages',
|
|
947
|
+
dedupe: true,
|
|
948
|
+
});
|
|
949
|
+
if (mode === 'compact' || mode === 'summary') {
|
|
950
|
+
return {
|
|
951
|
+
uri,
|
|
952
|
+
mimeType: 'text/markdown',
|
|
953
|
+
text: context.text || ctmSessionContext.renderContextMarkdown(context, { compact: true }),
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
return {
|
|
957
|
+
uri,
|
|
958
|
+
mimeType: 'application/json',
|
|
959
|
+
text: JSON.stringify(context),
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
if (parsed.protocol === 'walle-context:' && parsed.hostname === 'task') {
|
|
964
|
+
const task = decodeURIComponent(parsed.pathname.replace(/^\/+/, ''));
|
|
965
|
+
if (!task) throw new Error('walle-context task resource requires an encoded task query');
|
|
966
|
+
const pack = ctmSessionContext.buildContextPack({ task, mode: 'compact' });
|
|
967
|
+
return {
|
|
968
|
+
uri,
|
|
969
|
+
mimeType: 'text/markdown',
|
|
970
|
+
text: pack.text || ctmSessionContext.renderContextMarkdown(pack, { compact: true }),
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
throw new Error(`Unknown resource uri: ${uri}`);
|
|
975
|
+
}
|
|
976
|
+
|
|
751
977
|
async function handleMcp(req, res) {
|
|
752
978
|
let msg;
|
|
753
979
|
try {
|
|
@@ -775,7 +1001,7 @@ async function handleMcp(req, res) {
|
|
|
775
1001
|
jsonrpc: '2.0', id,
|
|
776
1002
|
result: {
|
|
777
1003
|
protocolVersion: PROTOCOL_VERSION,
|
|
778
|
-
capabilities: { tools: {} },
|
|
1004
|
+
capabilities: { tools: {}, resources: {} },
|
|
779
1005
|
serverInfo: { name: 'wall-e', version: (() => { try { return require('./package.json').version; } catch { return '0.0.0'; } })() },
|
|
780
1006
|
},
|
|
781
1007
|
});
|
|
@@ -788,6 +1014,35 @@ async function handleMcp(req, res) {
|
|
|
788
1014
|
});
|
|
789
1015
|
}
|
|
790
1016
|
|
|
1017
|
+
case 'resources/list': {
|
|
1018
|
+
return jsonResponse(res, {
|
|
1019
|
+
jsonrpc: '2.0', id,
|
|
1020
|
+
result: { resources: MCP_RESOURCES },
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
case 'resources/templates/list': {
|
|
1025
|
+
return jsonResponse(res, {
|
|
1026
|
+
jsonrpc: '2.0', id,
|
|
1027
|
+
result: { resourceTemplates: MCP_RESOURCE_TEMPLATES },
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
case 'resources/read': {
|
|
1032
|
+
try {
|
|
1033
|
+
const content = await readMcpResource(params?.uri);
|
|
1034
|
+
return jsonResponse(res, {
|
|
1035
|
+
jsonrpc: '2.0', id,
|
|
1036
|
+
result: { contents: [{ uri: content.uri, mimeType: content.mimeType, text: content.text }] },
|
|
1037
|
+
});
|
|
1038
|
+
} catch (err) {
|
|
1039
|
+
return jsonResponse(res, {
|
|
1040
|
+
jsonrpc: '2.0', id,
|
|
1041
|
+
result: { contents: [{ uri: params?.uri || '', mimeType: 'text/plain', text: `Error: ${err.message}` }], isError: true },
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
791
1046
|
case 'tools/call': {
|
|
792
1047
|
const toolName = params?.name;
|
|
793
1048
|
const toolArgs = params?.arguments || {};
|
|
@@ -819,4 +1074,11 @@ async function handleMcp(req, res) {
|
|
|
819
1074
|
}
|
|
820
1075
|
}
|
|
821
1076
|
|
|
822
|
-
module.exports = {
|
|
1077
|
+
module.exports = {
|
|
1078
|
+
handleMcp,
|
|
1079
|
+
MCP_TOOLS,
|
|
1080
|
+
MCP_RESOURCES,
|
|
1081
|
+
MCP_RESOURCE_TEMPLATES,
|
|
1082
|
+
executeTool,
|
|
1083
|
+
readMcpResource,
|
|
1084
|
+
};
|