@anastops/mcp-server 0.1.0 → 1.0.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.
Files changed (105) hide show
  1. package/dist/formatters.d.ts.map +1 -1
  2. package/dist/formatters.js +12 -3
  3. package/dist/formatters.js.map +1 -1
  4. package/dist/handlers/agent-handlers.d.ts +8 -0
  5. package/dist/handlers/agent-handlers.d.ts.map +1 -0
  6. package/dist/handlers/agent-handlers.js +184 -0
  7. package/dist/handlers/agent-handlers.js.map +1 -0
  8. package/dist/handlers/artifact-handlers.d.ts +8 -0
  9. package/dist/handlers/artifact-handlers.d.ts.map +1 -0
  10. package/dist/handlers/artifact-handlers.js +122 -0
  11. package/dist/handlers/artifact-handlers.js.map +1 -0
  12. package/dist/handlers/cost-handlers.d.ts +8 -0
  13. package/dist/handlers/cost-handlers.d.ts.map +1 -0
  14. package/dist/handlers/cost-handlers.js +140 -0
  15. package/dist/handlers/cost-handlers.js.map +1 -0
  16. package/dist/handlers/handlers.agent.d.ts +10 -0
  17. package/dist/handlers/handlers.agent.d.ts.map +1 -0
  18. package/dist/handlers/handlers.agent.js +99 -0
  19. package/dist/handlers/handlers.agent.js.map +1 -0
  20. package/dist/handlers/handlers.base.d.ts +82 -0
  21. package/dist/handlers/handlers.base.d.ts.map +1 -0
  22. package/dist/handlers/handlers.base.js +337 -0
  23. package/dist/handlers/handlers.base.js.map +1 -0
  24. package/dist/handlers/handlers.lock.d.ts +8 -0
  25. package/dist/handlers/handlers.lock.d.ts.map +1 -0
  26. package/dist/handlers/handlers.lock.js +111 -0
  27. package/dist/handlers/handlers.lock.js.map +1 -0
  28. package/dist/handlers/handlers.memory.d.ts +11 -0
  29. package/dist/handlers/handlers.memory.d.ts.map +1 -0
  30. package/dist/handlers/handlers.memory.js +122 -0
  31. package/dist/handlers/handlers.memory.js.map +1 -0
  32. package/dist/handlers/handlers.monitoring.d.ts +8 -0
  33. package/dist/handlers/handlers.monitoring.d.ts.map +1 -0
  34. package/dist/handlers/handlers.monitoring.js +99 -0
  35. package/dist/handlers/handlers.monitoring.js.map +1 -0
  36. package/dist/handlers/handlers.orchestration.d.ts +9 -0
  37. package/dist/handlers/handlers.orchestration.d.ts.map +1 -0
  38. package/dist/handlers/handlers.orchestration.js +128 -0
  39. package/dist/handlers/handlers.orchestration.js.map +1 -0
  40. package/dist/handlers/handlers.session.d.ts +18 -0
  41. package/dist/handlers/handlers.session.d.ts.map +1 -0
  42. package/dist/handlers/handlers.session.js +286 -0
  43. package/dist/handlers/handlers.session.js.map +1 -0
  44. package/dist/handlers/handlers.task.d.ts +15 -0
  45. package/dist/handlers/handlers.task.d.ts.map +1 -0
  46. package/dist/handlers/handlers.task.js +753 -0
  47. package/dist/handlers/handlers.task.js.map +1 -0
  48. package/dist/handlers/handlers.utility.d.ts +10 -0
  49. package/dist/handlers/handlers.utility.d.ts.map +1 -0
  50. package/dist/handlers/handlers.utility.js +59 -0
  51. package/dist/handlers/handlers.utility.js.map +1 -0
  52. package/dist/handlers/index.d.ts +18 -0
  53. package/dist/handlers/index.d.ts.map +1 -0
  54. package/dist/handlers/index.js +209 -0
  55. package/dist/handlers/index.js.map +1 -0
  56. package/dist/handlers/lock-handlers.d.ts +8 -0
  57. package/dist/handlers/lock-handlers.d.ts.map +1 -0
  58. package/dist/handlers/lock-handlers.js +154 -0
  59. package/dist/handlers/lock-handlers.js.map +1 -0
  60. package/dist/handlers/memory-handlers.d.ts +8 -0
  61. package/dist/handlers/memory-handlers.d.ts.map +1 -0
  62. package/dist/handlers/memory-handlers.js +76 -0
  63. package/dist/handlers/memory-handlers.js.map +1 -0
  64. package/dist/handlers/orchestration-handlers.d.ts +8 -0
  65. package/dist/handlers/orchestration-handlers.d.ts.map +1 -0
  66. package/dist/handlers/orchestration-handlers.js +113 -0
  67. package/dist/handlers/orchestration-handlers.js.map +1 -0
  68. package/dist/handlers/session-handlers.d.ts +8 -0
  69. package/dist/handlers/session-handlers.d.ts.map +1 -0
  70. package/dist/handlers/session-handlers.js +558 -0
  71. package/dist/handlers/session-handlers.js.map +1 -0
  72. package/dist/handlers/task-handlers.d.ts +8 -0
  73. package/dist/handlers/task-handlers.d.ts.map +1 -0
  74. package/dist/handlers/task-handlers.js +677 -0
  75. package/dist/handlers/task-handlers.js.map +1 -0
  76. package/dist/handlers/tool-definitions.d.ts +2626 -0
  77. package/dist/handlers/tool-definitions.d.ts.map +1 -0
  78. package/dist/handlers/tool-definitions.js +641 -0
  79. package/dist/handlers/tool-definitions.js.map +1 -0
  80. package/dist/handlers/types.d.ts +90 -0
  81. package/dist/handlers/types.d.ts.map +1 -0
  82. package/dist/handlers/types.js +5 -0
  83. package/dist/handlers/types.js.map +1 -0
  84. package/dist/handlers/utility-handlers.d.ts +8 -0
  85. package/dist/handlers/utility-handlers.d.ts.map +1 -0
  86. package/dist/handlers/utility-handlers.js +113 -0
  87. package/dist/handlers/utility-handlers.js.map +1 -0
  88. package/dist/handlers/utils.d.ts +30 -0
  89. package/dist/handlers/utils.d.ts.map +1 -0
  90. package/dist/handlers/utils.js +95 -0
  91. package/dist/handlers/utils.js.map +1 -0
  92. package/dist/handlers.d.ts +17 -2260
  93. package/dist/handlers.d.ts.map +1 -1
  94. package/dist/handlers.js +17 -1836
  95. package/dist/handlers.js.map +1 -1
  96. package/dist/index.js +41 -7
  97. package/dist/index.js.map +1 -1
  98. package/dist/persistence.d.ts.map +1 -1
  99. package/dist/persistence.js +84 -47
  100. package/dist/persistence.js.map +1 -1
  101. package/dist/schemas.d.ts +299 -0
  102. package/dist/schemas.d.ts.map +1 -0
  103. package/dist/schemas.js +334 -0
  104. package/dist/schemas.js.map +1 -0
  105. package/package.json +8 -5
@@ -0,0 +1,99 @@
1
+ /**
2
+ * MCP Tool Handlers - Agent Management
3
+ * Handles: agent_create, agent_deploy, agent_status, agent_list, agent_retire
4
+ */
5
+ import { nanoid } from 'nanoid';
6
+ import { getPersistence } from '../persistence.js';
7
+ import { safePersist, agents, getAgent } from './handlers.base.js';
8
+ export function handleAgentCreate(args) {
9
+ const agentId = nanoid(21);
10
+ const now = new Date();
11
+ const agent = {
12
+ id: agentId,
13
+ session_id: args['session_id'],
14
+ role: args['role'] ?? 'implementer',
15
+ name: args['name'] ?? `agent-${agentId.slice(0, 4)}`,
16
+ status: 'idle',
17
+ provider: args['provider'] ?? 'claude',
18
+ model: args['model'] ?? 'claude-sonnet',
19
+ current_task_id: null,
20
+ tasks_completed: 0,
21
+ tasks_failed: 0,
22
+ tokens_used: 0,
23
+ created_at: now,
24
+ last_activity_at: now,
25
+ config: {},
26
+ };
27
+ agents.set(agentId, agent);
28
+ // Persist to MongoDB
29
+ safePersist(getPersistence().saveAgent(agent));
30
+ return Promise.resolve({
31
+ agent_id: agent.id,
32
+ name: agent.name,
33
+ role: agent.role,
34
+ status: agent.status,
35
+ });
36
+ }
37
+ export async function handleAgentDeploy(args) {
38
+ const agent = await getAgent(args['agent_id']);
39
+ if (agent === null)
40
+ throw new Error('Agent not found');
41
+ agent.current_task_id = args['task_id'];
42
+ agent.status = 'working';
43
+ agent.last_activity_at = new Date();
44
+ agents.set(agent.id, agent);
45
+ safePersist(getPersistence().saveAgent(agent));
46
+ return { agent_id: agent.id, task_id: agent.current_task_id, status: agent.status };
47
+ }
48
+ export async function handleAgentStatus(args) {
49
+ const agent = await getAgent(args['agent_id']);
50
+ if (agent === null)
51
+ throw new Error('Agent not found');
52
+ return agent;
53
+ }
54
+ export async function handleAgentList(args) {
55
+ // Get from in-memory cache first
56
+ const inMemoryAgents = [];
57
+ for (const [, agent] of agents.entries()) {
58
+ if (args['session_id'] === undefined || agent.session_id === args['session_id']) {
59
+ inMemoryAgents.push(agent);
60
+ }
61
+ }
62
+ // Also get from MongoDB for persistence
63
+ const persistedAgents = await getPersistence().listAgents({
64
+ ...(args['session_id'] !== undefined && { session_id: args['session_id'] }),
65
+ });
66
+ // Merge: in-memory takes precedence
67
+ const inMemoryIds = new Set(inMemoryAgents.map((a) => a.id));
68
+ const sessionAgents = [
69
+ ...inMemoryAgents,
70
+ ...persistedAgents.filter((a) => !inMemoryIds.has(a.id)),
71
+ ];
72
+ return {
73
+ count: sessionAgents.length,
74
+ agents: sessionAgents.map((a) => ({ id: a.id, name: a.name, role: a.role, status: a.status })),
75
+ };
76
+ }
77
+ export async function handleAgentRetire(args) {
78
+ const agentId = args['agent_id'];
79
+ const agent = await getAgent(agentId);
80
+ if (agent === null) {
81
+ throw new Error(`Agent not found: ${agentId}`);
82
+ }
83
+ // Retire the agent
84
+ agent.status = 'completed';
85
+ agent.last_activity_at = new Date();
86
+ agent.current_task_id = null;
87
+ agents.set(agentId, agent);
88
+ // Persist to MongoDB
89
+ safePersist(getPersistence().saveAgent(agent));
90
+ return {
91
+ agent_id: agent.id,
92
+ name: agent.name,
93
+ role: agent.role,
94
+ status: agent.status,
95
+ tasks_completed: agent.tasks_completed,
96
+ retired: true,
97
+ };
98
+ }
99
+ //# sourceMappingURL=handlers.agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.agent.js","sourceRoot":"","sources":["../../src/handlers/handlers.agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Base utilities for MCP Tool Handlers
3
+ * Includes TOON encoding, response formatting, error handling, and cache management
4
+ */
5
+ import type { Task, Agent, Artifact } from '@anastops/core';
6
+ import { LRUCache } from 'lru-cache';
7
+ /**
8
+ * Safe fire-and-forget wrapper for persistence operations
9
+ * Catches errors to prevent uncaught promise rejections from crashing the server
10
+ */
11
+ export declare function safePersist<T>(operation: Promise<T>): void;
12
+ /**
13
+ * TOON-encoded response wrapper type
14
+ */
15
+ export interface TOONEncodedResponse {
16
+ data: unknown;
17
+ encoding?: 'toon' | 'json';
18
+ token_reduction?: {
19
+ original: number;
20
+ encoded: number;
21
+ savings_percent: number;
22
+ };
23
+ }
24
+ /**
25
+ * Apply TOON encoding to response if beneficial
26
+ * Returns original data if TOON doesn't provide savings
27
+ *
28
+ * TOON (Token-Optimized Object Notation) is most effective for:
29
+ * - Arrays of uniform objects (converted to tabular format)
30
+ * - Large structured responses (> 500 bytes)
31
+ */
32
+ export declare function applyTOONEncodingToResponse(data: unknown): TOONEncodedResponse;
33
+ /**
34
+ * Sanitize error message for external exposure
35
+ * SECURITY: Never expose internal details like stack traces, paths, or credentials
36
+ */
37
+ export declare function sanitizeErrorMessage(error: unknown): string;
38
+ export interface MemoryStoreValue {
39
+ value: Record<string, unknown>;
40
+ stored_at: Date;
41
+ }
42
+ export declare const agents: LRUCache<string, Agent, unknown>;
43
+ export declare const tasks: LRUCache<string, Task, unknown>;
44
+ export declare const artifacts: LRUCache<string, Artifact, unknown>;
45
+ export declare const memoryStore: LRUCache<string, MemoryStoreValue, unknown>;
46
+ /**
47
+ * Get task from memory or MongoDB
48
+ * Loads from MongoDB and caches in memory if not found
49
+ */
50
+ export declare function getTask(taskId: string): Promise<Task | null>;
51
+ /**
52
+ * Get agent from memory or MongoDB
53
+ */
54
+ export declare function getAgent(agentId: string): Promise<Agent | null>;
55
+ /**
56
+ * Get artifact from memory or MongoDB
57
+ */
58
+ export declare function getArtifact(artifactId: string): Promise<Artifact | null>;
59
+ /**
60
+ * Format a session report with all related data
61
+ */
62
+ export declare function formatSessionReport(report: {
63
+ session: {
64
+ id: string;
65
+ objective: string;
66
+ status: string;
67
+ created_at: Date;
68
+ updated_at: Date;
69
+ metadata: {
70
+ total_tokens: number;
71
+ total_cost: number;
72
+ agents_used: string[];
73
+ files_affected: string[];
74
+ tasks_completed: number;
75
+ tasks_failed: number;
76
+ };
77
+ };
78
+ tasks: Task[];
79
+ agents: Agent[];
80
+ artifacts: Artifact[];
81
+ }, includeOutput: boolean, includeArtifactContent: boolean): Record<string, unknown>;
82
+ //# sourceMappingURL=handlers.base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.base.d.ts","sourceRoot":"","sources":["../../src/handlers/handlers.base.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAKrC;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAO1D;AAKD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAwDD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,OAAO,GAAG,mBAAmB,CA8D9E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwB3D;AAGD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,IAAI,CAAC;CACjB;AAGD,eAAO,MAAM,MAAM,kCAAkE,CAAC;AACtF,eAAO,MAAM,KAAK,iCAAsE,CAAC;AACzF,eAAO,MAAM,SAAS,qCAA0E,CAAC;AACjG,eAAO,MAAM,WAAW,6CAGtB,CAAC;AAEH;;;GAGG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAgBlE;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAarE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAa9E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE;IACN,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,IAAI,CAAC;QACjB,UAAU,EAAE,IAAI,CAAC;QACjB,QAAQ,EAAE;YACR,YAAY,EAAE,MAAM,CAAC;YACrB,UAAU,EAAE,MAAM,CAAC;YACnB,WAAW,EAAE,MAAM,EAAE,CAAC;YACtB,cAAc,EAAE,MAAM,EAAE,CAAC;YACzB,eAAe,EAAE,MAAM,CAAC;YACxB,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;KACH,CAAC;IACF,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,SAAS,EAAE,QAAQ,EAAE,CAAC;CACvB,EACD,aAAa,EAAE,OAAO,EACtB,sBAAsB,EAAE,OAAO,GAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2HzB"}
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Base utilities for MCP Tool Handlers
3
+ * Includes TOON encoding, response formatting, error handling, and cache management
4
+ */
5
+ import { captureError } from '@anastops/core';
6
+ import { LRUCache } from 'lru-cache';
7
+ import { ZodError } from 'zod';
8
+ import { getPersistence } from '../persistence.js';
9
+ /**
10
+ * Safe fire-and-forget wrapper for persistence operations
11
+ * Catches errors to prevent uncaught promise rejections from crashing the server
12
+ */
13
+ export function safePersist(operation) {
14
+ operation.catch((error) => {
15
+ const message = error instanceof Error ? error.message : String(error);
16
+ console.error('[Persistence Error]', message);
17
+ // Capture persistence errors in Sentry
18
+ captureError(error, { type: 'persistence' });
19
+ });
20
+ }
21
+ // TOON encoding constants
22
+ const TOON_MIN_SIZE_BYTES = 500;
23
+ /**
24
+ * Estimate token count for text
25
+ * Rough approximation: ~4 characters per token for English
26
+ */
27
+ function estimateTokens(text) {
28
+ return Math.ceil(text.length / 4);
29
+ }
30
+ /**
31
+ * Convert array of uniform objects to TOON tabular format
32
+ * TOON format uses pipe-separated headers and values for compact representation
33
+ */
34
+ function toTOONTabular(arr, keys) {
35
+ if (arr.length === 0 || keys.length === 0)
36
+ return '';
37
+ const lines = [];
38
+ // Header row
39
+ lines.push(keys.join(' | '));
40
+ // Data rows
41
+ for (const item of arr) {
42
+ const values = keys.map((k) => {
43
+ const val = item[k];
44
+ if (val === null || val === undefined)
45
+ return '';
46
+ if (typeof val === 'string')
47
+ return val.slice(0, 50);
48
+ if (val instanceof Date)
49
+ return val.toISOString();
50
+ return String(val);
51
+ });
52
+ lines.push(values.join(' | '));
53
+ }
54
+ return lines.join('\n');
55
+ }
56
+ /**
57
+ * Check if array contains uniform objects (all objects have same keys)
58
+ */
59
+ function isUniformObjectArray(data) {
60
+ if (!Array.isArray(data) || data.length === 0)
61
+ return false;
62
+ if (typeof data[0] !== 'object' || data[0] === null)
63
+ return false;
64
+ const firstKeys = Object.keys(data[0])
65
+ .sort()
66
+ .join(',');
67
+ return data.every((item) => {
68
+ if (typeof item !== 'object' || item === null)
69
+ return false;
70
+ return (Object.keys(item)
71
+ .sort()
72
+ .join(',') === firstKeys);
73
+ });
74
+ }
75
+ /**
76
+ * Apply TOON encoding to response if beneficial
77
+ * Returns original data if TOON doesn't provide savings
78
+ *
79
+ * TOON (Token-Optimized Object Notation) is most effective for:
80
+ * - Arrays of uniform objects (converted to tabular format)
81
+ * - Large structured responses (> 500 bytes)
82
+ */
83
+ export function applyTOONEncodingToResponse(data) {
84
+ // Only apply TOON to arrays or large objects
85
+ const jsonStr = JSON.stringify(data);
86
+ if (jsonStr.length < TOON_MIN_SIZE_BYTES) {
87
+ return { data }; // Too small, not worth encoding
88
+ }
89
+ const originalTokens = estimateTokens(jsonStr);
90
+ // Check if data structure is TOON-eligible
91
+ // TOON works best with arrays of uniform objects
92
+ if (typeof data !== 'object' || data === null) {
93
+ return { data };
94
+ }
95
+ const dataObj = data;
96
+ // Look for arrays within the response that could be TOON-encoded
97
+ let hasEncodableArrays = false;
98
+ const toonParts = [];
99
+ const scalarParts = [];
100
+ for (const [key, value] of Object.entries(dataObj)) {
101
+ if (isUniformObjectArray(value)) {
102
+ hasEncodableArrays = true;
103
+ const keys = Object.keys(value[0]);
104
+ toonParts.push(`${key}:\n${toTOONTabular(value, keys)}`);
105
+ }
106
+ else if (Array.isArray(value)) {
107
+ // Non-uniform array, keep as JSON
108
+ scalarParts.push(`${key}: ${JSON.stringify(value)}`);
109
+ }
110
+ else if (typeof value === 'object' && value !== null) {
111
+ // Nested object, keep as compact JSON
112
+ scalarParts.push(`${key}: ${JSON.stringify(value)}`);
113
+ }
114
+ else {
115
+ // Scalar value
116
+ scalarParts.push(`${key}: ${String(value)}`);
117
+ }
118
+ }
119
+ if (!hasEncodableArrays) {
120
+ return { data }; // No benefit from TOON encoding
121
+ }
122
+ // Build TOON-encoded representation
123
+ const toonEncoded = [...scalarParts, ...toonParts].join('\n');
124
+ const encodedTokens = estimateTokens(toonEncoded);
125
+ // Only use TOON if we get meaningful savings (> 20%)
126
+ const savingsPercent = ((originalTokens - encodedTokens) / originalTokens) * 100;
127
+ if (savingsPercent < 20) {
128
+ return { data }; // Not enough savings to justify encoding change
129
+ }
130
+ return {
131
+ data: toonEncoded,
132
+ encoding: 'toon',
133
+ token_reduction: {
134
+ original: originalTokens,
135
+ encoded: encodedTokens,
136
+ savings_percent: Math.round(savingsPercent * 100) / 100,
137
+ },
138
+ };
139
+ }
140
+ /**
141
+ * Sanitize error message for external exposure
142
+ * SECURITY: Never expose internal details like stack traces, paths, or credentials
143
+ */
144
+ export function sanitizeErrorMessage(error) {
145
+ if (error instanceof ZodError) {
146
+ // Return validation errors with field details but no internal info
147
+ const issues = error.issues.map((issue) => ({
148
+ path: issue.path.join('.'),
149
+ message: issue.message,
150
+ }));
151
+ return `Validation error: ${JSON.stringify(issues)}`;
152
+ }
153
+ if (error instanceof Error) {
154
+ const message = error.message;
155
+ // Redact sensitive patterns
156
+ const sensitized = message
157
+ .replace(/mongodb:\/\/[^@]+@/gi, 'mongodb://***@') // MongoDB credentials
158
+ .replace(/redis:\/\/[^@]+@/gi, 'redis://***@') // Redis credentials
159
+ .replace(/password[=:]["']?[^"'\s]+["']?/gi, 'password=***') // Generic passwords
160
+ .replace(/\/Users\/[^/]+\//g, '/****/') // User paths
161
+ .replace(/\/home\/[^/]+\//g, '/****/') // User paths
162
+ .replace(/api[_-]?key[=:]["']?[^"'\s]+["']?/gi, 'api_key=***'); // API keys
163
+ return sensitized;
164
+ }
165
+ return 'An unexpected error occurred';
166
+ }
167
+ // LRU caches with size limits and TTL to prevent memory leaks
168
+ export const agents = new LRUCache({ max: 1000, ttl: 1000 * 60 * 60 }); // 1 hour TTL
169
+ export const tasks = new LRUCache({ max: 5000, ttl: 1000 * 60 * 60 * 24 }); // 24 hour TTL
170
+ export const artifacts = new LRUCache({ max: 1000, ttl: 1000 * 60 * 60 * 24 }); // 24 hour TTL
171
+ export const memoryStore = new LRUCache({
172
+ max: 10000,
173
+ ttl: 1000 * 60 * 60,
174
+ }); // 1 hour TTL
175
+ /**
176
+ * Get task from memory or MongoDB
177
+ * Loads from MongoDB and caches in memory if not found
178
+ */
179
+ export async function getTask(taskId) {
180
+ // Check in-memory first
181
+ const memTask = tasks.get(taskId);
182
+ if (memTask !== undefined) {
183
+ return memTask;
184
+ }
185
+ // Try to load from MongoDB
186
+ const dbTask = await getPersistence().getTask(taskId);
187
+ if (dbTask !== null) {
188
+ // Cache in memory for subsequent access
189
+ tasks.set(taskId, dbTask);
190
+ return dbTask;
191
+ }
192
+ return null;
193
+ }
194
+ /**
195
+ * Get agent from memory or MongoDB
196
+ */
197
+ export async function getAgent(agentId) {
198
+ const memAgent = agents.get(agentId);
199
+ if (memAgent !== undefined) {
200
+ return memAgent;
201
+ }
202
+ const dbAgent = await getPersistence().getAgent(agentId);
203
+ if (dbAgent !== null) {
204
+ agents.set(agentId, dbAgent);
205
+ return dbAgent;
206
+ }
207
+ return null;
208
+ }
209
+ /**
210
+ * Get artifact from memory or MongoDB
211
+ */
212
+ export async function getArtifact(artifactId) {
213
+ const memArtifact = artifacts.get(artifactId);
214
+ if (memArtifact !== undefined) {
215
+ return memArtifact;
216
+ }
217
+ const dbArtifact = await getPersistence().getArtifact(artifactId);
218
+ if (dbArtifact !== null) {
219
+ artifacts.set(artifactId, dbArtifact);
220
+ return dbArtifact;
221
+ }
222
+ return null;
223
+ }
224
+ /**
225
+ * Format a session report with all related data
226
+ */
227
+ export function formatSessionReport(report, includeOutput, includeArtifactContent) {
228
+ const { session, tasks: sessionTasks, agents: sessionAgents, artifacts: sessionArtifacts, } = report;
229
+ // Calculate statistics
230
+ const taskStats = {
231
+ total: sessionTasks.length,
232
+ pending: sessionTasks.filter((t) => t.status === 'pending').length,
233
+ queued: sessionTasks.filter((t) => t.status === 'queued').length,
234
+ running: sessionTasks.filter((t) => t.status === 'running').length,
235
+ completed: sessionTasks.filter((t) => t.status === 'completed').length,
236
+ failed: sessionTasks.filter((t) => t.status === 'failed').length,
237
+ cancelled: sessionTasks.filter((t) => t.status === 'cancelled').length,
238
+ };
239
+ const totalTokens = sessionTasks.reduce((sum, t) => sum + (t.token_usage?.total_tokens ?? 0), 0);
240
+ const totalCost = sessionTasks.reduce((sum, t) => sum + (t.token_usage?.cost ?? 0), 0);
241
+ // Format tasks with full details
242
+ const formattedTasks = sessionTasks.map((t) => {
243
+ const taskData = {
244
+ id: t.id,
245
+ type: t.type,
246
+ status: t.status,
247
+ description: t.description,
248
+ provider: t.provider,
249
+ model: t.model,
250
+ routing_tier: t.routing_tier,
251
+ complexity_score: t.complexity_score,
252
+ token_usage: t.token_usage,
253
+ created_at: t.created_at,
254
+ started_at: t.started_at,
255
+ completed_at: t.completed_at,
256
+ retry_count: t.retry_count,
257
+ input: {
258
+ prompt: t.input?.prompt?.slice(0, 500) ?? '',
259
+ context_files: t.input?.context_files ?? [],
260
+ agent: t.input?.agent,
261
+ skills: t.input?.skills,
262
+ },
263
+ };
264
+ if (t.error !== null && t.error !== undefined && t.error !== '') {
265
+ taskData.error = t.error;
266
+ }
267
+ if (includeOutput && t.output) {
268
+ taskData.output = {
269
+ content: t.output.content,
270
+ artifacts: t.output.artifacts,
271
+ files_modified: t.output.files_modified,
272
+ };
273
+ }
274
+ else if (t.output) {
275
+ taskData.output = {
276
+ content_length: t.output.content?.length ?? 0,
277
+ artifacts_count: t.output.artifacts?.length ?? 0,
278
+ files_modified: t.output.files_modified,
279
+ };
280
+ }
281
+ return taskData;
282
+ });
283
+ // Format agents
284
+ const formattedAgents = sessionAgents.map((a) => ({
285
+ id: a.id,
286
+ name: a.name,
287
+ role: a.role,
288
+ status: a.status,
289
+ provider: a.provider,
290
+ model: a.model,
291
+ tasks_completed: a.tasks_completed,
292
+ tasks_failed: a.tasks_failed,
293
+ tokens_used: a.tokens_used,
294
+ current_task_id: a.current_task_id,
295
+ created_at: a.created_at,
296
+ last_activity_at: a.last_activity_at,
297
+ }));
298
+ // Format artifacts
299
+ const formattedArtifacts = sessionArtifacts.map((a) => {
300
+ const artifactData = {
301
+ id: a.id,
302
+ name: a.name,
303
+ type: a.type,
304
+ size_bytes: a.size_bytes,
305
+ token_count: a.token_count,
306
+ created_at: a.created_at,
307
+ };
308
+ if (includeArtifactContent) {
309
+ artifactData.content = a.content;
310
+ }
311
+ else {
312
+ artifactData.summary = a.summary;
313
+ }
314
+ return artifactData;
315
+ });
316
+ return {
317
+ session: {
318
+ id: session.id,
319
+ objective: session.objective,
320
+ status: session.status,
321
+ created_at: session.created_at,
322
+ updated_at: session.updated_at,
323
+ metadata: session.metadata,
324
+ },
325
+ statistics: {
326
+ tasks: taskStats,
327
+ total_tokens: totalTokens,
328
+ total_cost_usd: totalCost,
329
+ agents_count: sessionAgents.length,
330
+ artifacts_count: sessionArtifacts.length,
331
+ },
332
+ tasks: formattedTasks,
333
+ agents: formattedAgents,
334
+ artifacts: formattedArtifacts,
335
+ };
336
+ }
337
+ //# sourceMappingURL=handlers.base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.base.js","sourceRoot":"","sources":["../../src/handlers/handlers.base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * MCP Tool Handlers - Lock Management
3
+ * Handles: lock_acquire, lock_release, lock_status
4
+ */
5
+ export declare function handleLockAcquire(args: Record<string, unknown>): Promise<unknown>;
6
+ export declare function handleLockRelease(args: Record<string, unknown>): Promise<unknown>;
7
+ export declare function handleLockStatus(args: Record<string, unknown>): Promise<unknown>;
8
+ //# sourceMappingURL=handlers.lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.lock.d.ts","sourceRoot":"","sources":["../../src/handlers/handlers.lock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAmCjF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CA+BjF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAkDhF"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * MCP Tool Handlers - Lock Management
3
+ * Handles: lock_acquire, lock_release, lock_status
4
+ */
5
+ import { memoryStore } from './handlers.base.js';
6
+ export function handleLockAcquire(args) {
7
+ const sessionId = args['session_id'];
8
+ const filePath = args['file_path'];
9
+ const ttl = args['ttl'] ?? 300000;
10
+ // In-memory lock implementation (Redis-based implementation would be used in production)
11
+ const lockKey = `lock:${filePath}`;
12
+ const existingLock = memoryStore.get(lockKey);
13
+ if (existingLock !== undefined) {
14
+ const lockData = existingLock.value;
15
+ // Check if lock is expired
16
+ if (lockData.expires_at > Date.now() && lockData.session_id !== sessionId) {
17
+ return Promise.resolve({
18
+ session_id: sessionId,
19
+ file_path: filePath,
20
+ acquired: false,
21
+ owner: lockData.session_id,
22
+ ttl,
23
+ });
24
+ }
25
+ }
26
+ // Acquire lock
27
+ memoryStore.set(lockKey, {
28
+ value: { session_id: sessionId, expires_at: Date.now() + ttl },
29
+ stored_at: new Date(),
30
+ });
31
+ return Promise.resolve({
32
+ session_id: sessionId,
33
+ file_path: filePath,
34
+ acquired: true,
35
+ ttl,
36
+ });
37
+ }
38
+ export function handleLockRelease(args) {
39
+ const sessionId = args['session_id'];
40
+ const filePath = args['file_path'];
41
+ const lockKey = `lock:${filePath}`;
42
+ const existingLock = memoryStore.get(lockKey);
43
+ if (existingLock !== undefined) {
44
+ const lockData = existingLock.value;
45
+ if (lockData.session_id === sessionId) {
46
+ memoryStore.delete(lockKey);
47
+ return Promise.resolve({
48
+ session_id: sessionId,
49
+ file_path: filePath,
50
+ released: true,
51
+ });
52
+ }
53
+ return Promise.resolve({
54
+ session_id: sessionId,
55
+ file_path: filePath,
56
+ released: false,
57
+ error: 'Lock is held by another session',
58
+ });
59
+ }
60
+ return Promise.resolve({
61
+ session_id: sessionId,
62
+ file_path: filePath,
63
+ released: true,
64
+ message: 'Lock did not exist',
65
+ });
66
+ }
67
+ export function handleLockStatus(args) {
68
+ const sessionId = args['session_id'];
69
+ const filePath = args['file_path'];
70
+ if (filePath !== undefined) {
71
+ const lockKey = `lock:${filePath}`;
72
+ const existingLock = memoryStore.get(lockKey);
73
+ if (existingLock !== undefined) {
74
+ const lockData = existingLock.value;
75
+ const isExpired = lockData.expires_at <= Date.now();
76
+ return Promise.resolve({
77
+ file_path: filePath,
78
+ is_locked: !isExpired,
79
+ owner: isExpired ? null : lockData.session_id,
80
+ expires_at: lockData.expires_at,
81
+ });
82
+ }
83
+ return Promise.resolve({
84
+ file_path: filePath,
85
+ is_locked: false,
86
+ owner: null,
87
+ });
88
+ }
89
+ if (sessionId !== undefined) {
90
+ // List all locks held by this session
91
+ const sessionLocks = [];
92
+ for (const [key, data] of memoryStore.entries()) {
93
+ if (key.startsWith('lock:')) {
94
+ const lockData = data.value;
95
+ if (lockData.session_id === sessionId && lockData.expires_at > Date.now()) {
96
+ sessionLocks.push({
97
+ file_path: key.replace('lock:', ''),
98
+ expires_at: lockData.expires_at,
99
+ });
100
+ }
101
+ }
102
+ }
103
+ return Promise.resolve({
104
+ session_id: sessionId,
105
+ lock_count: sessionLocks.length,
106
+ locks: sessionLocks,
107
+ });
108
+ }
109
+ return Promise.resolve({ error: 'Must provide either session_id or file_path' });
110
+ }
111
+ //# sourceMappingURL=handlers.lock.js.map