smart-context-mcp 1.16.2 → 1.16.5

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 CHANGED
@@ -56,7 +56,7 @@ Restart your AI client. Done.
56
56
  # Check installed version
57
57
  npm list -g smart-context-mcp
58
58
 
59
- # Should show: smart-context-mcp@1.16.2 (or later)
59
+ # Should show: smart-context-mcp@1.16.5 (or later)
60
60
 
61
61
  # Update to latest version
62
62
  npm update -g smart-context-mcp
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "smart-context-mcp",
3
3
  "mcpName": "io.github.Arrayo/smart-context-mcp",
4
- "version": "1.16.2",
4
+ "version": "1.16.5",
5
5
  "description": "MCP server that reduces agent token usage by 90% with intelligent context compression, task checkpoint persistence, and workflow-aware agent guidance.",
6
6
  "author": "Francisco Caballero Portero <fcp1978@hotmail.com>",
7
7
  "type": "module",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/Arrayo/smart-context-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "1.16.2",
9
+ "version": "1.16.5",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "smart-context-mcp",
14
- "version": "1.16.2",
14
+ "version": "1.16.5",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },
@@ -74,11 +74,17 @@ export const buildOperationalContextLines = (
74
74
  const summary = result?.summary;
75
75
  const continuityState = result?.continuity?.state;
76
76
  const storageIssue = result?.storageHealth?.issue;
77
+ const task = result?.task ?? null;
78
+ const handoff = result?.handoff ?? null;
77
79
 
78
80
  if (result?.found && summary) {
79
81
  const label = sessionStart ? 'resume' : continuityState ?? 'resume';
80
82
  lines.push(`devctx ${label}: session ${result.sessionId}`);
81
83
 
84
+ if (task?.taskId) {
85
+ lines.push(`task: ${truncate(task.taskId, maxLineLength)}`);
86
+ }
87
+
82
88
  if (summary.goal) {
83
89
  lines.push(`goal: ${truncate(summary.goal, maxLineLength)}`);
84
90
  }
@@ -106,10 +112,20 @@ export const buildOperationalContextLines = (
106
112
  lines.push(`devctx new task session: ${truncate(summary.goal, maxLineLength)}`);
107
113
  }
108
114
 
109
- if (result?.continuity?.reason) {
115
+ if (!mutationSafety?.blocked && result?.continuity?.reason) {
110
116
  lines.push(`context status: ${truncate(result.continuity.reason, maxLineLength)}`);
111
117
  }
112
118
 
119
+ if (handoff?.fromAgentId || handoff?.summary?.nextStep || handoff?.summary?.pending?.length > 0) {
120
+ lines.push(`handoff: ${truncate(`from ${handoff?.fromAgentId ?? 'previous agent'} via ${handoff?.trigger ?? 'handoff'}`, maxLineLength)}`);
121
+ if (handoff?.summary?.pending?.[0]) {
122
+ lines.push(`pending: ${truncate(handoff.summary.pending[0], maxLineLength)}`);
123
+ }
124
+ if (handoff?.summary?.nextStep) {
125
+ lines.push(`handoff next: ${truncate(handoff.summary.nextStep, maxLineLength)}`);
126
+ }
127
+ }
128
+
113
129
  if (mutationSafety?.blocked) {
114
130
  const reasons = mutationSafety.blockedBy?.join(' and ') || 'blocked';
115
131
  lines.push(`repo safety: ${mutationSafety.stateDbPath} is ${reasons}; context writes are blocked.`);
@@ -7,7 +7,9 @@ import { smartTurn } from '../../tools/smart-turn.js';
7
7
  import {
8
8
  deleteHookTurnState,
9
9
  getHookTurnState,
10
+ persistTaskHandoff,
10
11
  setHookTurnState,
12
+ upsertAgentRun,
11
13
  } from '../../storage/sqlite.js';
12
14
  import { DEFAULT_START_MAX_TOKENS, resolveManagedStart } from '../base-orchestrator.js';
13
15
  import { extractNextStep, normalizeWhitespace, truncate } from '../policy/event-policy.js';
@@ -25,8 +27,20 @@ export const WRITE_TOOLS = new Set(['Write', 'Edit', 'MultiEdit']);
25
27
 
26
28
  const uniq = (values) => [...new Set(values.filter((value) => typeof value === 'string' && value.trim().length > 0))];
27
29
 
30
+ const resolveAgentId = (input = {}) => {
31
+ const value = input.agent_id ?? input.agentId ?? input.assistant_id ?? input.worker_id ?? null;
32
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : 'main';
33
+ };
34
+
35
+ const resolveParentAgentId = (input = {}) => {
36
+ const value = input.parent_agent_id ?? input.parentAgentId ?? null;
37
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;
38
+ };
39
+
28
40
  export const buildClaudeHookKey = ({ sessionId, agentId = null }) =>
29
- agentId ? `${HOOK_CLIENT}:subagent:${sessionId}:${agentId}` : `${HOOK_CLIENT}:main:${sessionId}`;
41
+ agentId && agentId !== 'main'
42
+ ? `${HOOK_CLIENT}:subagent:${sessionId}:${agentId}`
43
+ : `${HOOK_CLIENT}:main:${sessionId}`;
30
44
 
31
45
  const countPromptTerms = (value) =>
32
46
  normalizeWhitespace(value)
@@ -148,6 +162,8 @@ export const createClaudeAdapter = ({
148
162
  summaryTool = smartSummary,
149
163
  resolveStart = resolveManagedStart,
150
164
  persistMetric = persistMetrics,
165
+ writeAgentRun = upsertAgentRun,
166
+ writeTaskHandoff = persistTaskHandoff,
151
167
  getMutationSafety = getRepoMutationSafety,
152
168
  readHookState = null,
153
169
  writeHookState = ({ hookKey, state }) => setHookTurnState({ hookKey, state }),
@@ -215,7 +231,11 @@ export const createClaudeAdapter = ({
215
231
  const maybeTrackTurn = async ({
216
232
  hookKey,
217
233
  claudeSessionId,
234
+ conversationId,
218
235
  projectSessionId,
236
+ taskId,
237
+ agentId,
238
+ parentAgentId,
219
239
  prompt,
220
240
  continuityState,
221
241
  }) => {
@@ -232,7 +252,11 @@ export const createClaudeAdapter = ({
232
252
  state: {
233
253
  client: HOOK_CLIENT,
234
254
  claudeSessionId,
255
+ conversationId,
235
256
  projectSessionId,
257
+ taskId,
258
+ agentId,
259
+ parentAgentId,
236
260
  turnId: `${claudeSessionId}:${Date.now()}`,
237
261
  promptPreview: truncate(prompt, MAX_PROMPT_PREVIEW),
238
262
  continuityState,
@@ -246,6 +270,45 @@ export const createClaudeAdapter = ({
246
270
  });
247
271
  };
248
272
 
273
+ const maybeAutoCheckpointFromState = async (state, { trigger = 'post_tool_use' } = {}) => {
274
+ if (!state?.projectSessionId || getMutationSafety().shouldBlock) {
275
+ return false;
276
+ }
277
+
278
+ const update = {
279
+ ...(state.promptPreview ? { currentFocus: state.promptPreview } : {}),
280
+ ...(state.touchedFiles.length > 0 ? { touchedFiles: state.touchedFiles } : {}),
281
+ };
282
+
283
+ await summaryTool({
284
+ action: 'checkpoint',
285
+ sessionId: state.projectSessionId,
286
+ event: 'milestone',
287
+ update,
288
+ maxTokens: STOP_MAX_TOKENS,
289
+ force: true,
290
+ });
291
+
292
+ if (state.taskId) {
293
+ await writeTaskHandoff({
294
+ taskId: state.taskId,
295
+ sessionId: state.projectSessionId,
296
+ fromAgentId: state.agentId ?? null,
297
+ toAgentId: null,
298
+ trigger,
299
+ summary: {
300
+ currentFocus: state.promptPreview,
301
+ touchedFiles: state.touchedFiles,
302
+ pending: [],
303
+ nextStep: null,
304
+ evidence: state.touchedFiles.length > 0 ? [`Touched files: ${state.touchedFiles.join(', ')}`] : [],
305
+ },
306
+ });
307
+ }
308
+
309
+ return true;
310
+ };
311
+
249
312
  const handleSessionStart = async () => {
250
313
  const result = await startTurn({
251
314
  phase: 'start',
@@ -262,6 +325,8 @@ export const createClaudeAdapter = ({
262
325
  };
263
326
 
264
327
  const handleUserPromptSubmit = async (input) => {
328
+ const agentId = resolveAgentId(input);
329
+ const parentAgentId = resolveParentAgentId(input);
265
330
  const startResolution = await resolveStart({
266
331
  prompt: input.prompt,
267
332
  ensureSession: true,
@@ -272,10 +337,27 @@ export const createClaudeAdapter = ({
272
337
  });
273
338
  const result = startResolution.startResult;
274
339
 
340
+ if (!getMutationSafety().shouldBlock) {
341
+ await writeAgentRun({
342
+ runId: buildClaudeHookKey({ sessionId: input.session_id, agentId }),
343
+ taskId: result.task?.taskId ?? null,
344
+ agentId,
345
+ parentAgentId,
346
+ client: HOOK_CLIENT,
347
+ conversationId: input.session_id,
348
+ sessionId: result.sessionId ?? null,
349
+ role: agentId === 'main' ? 'main' : 'subagent',
350
+ });
351
+ }
352
+
275
353
  const trackedState = await maybeTrackTurn({
276
- hookKey: buildClaudeHookKey({ sessionId: input.session_id }),
354
+ hookKey: buildClaudeHookKey({ sessionId: input.session_id, agentId }),
277
355
  claudeSessionId: input.session_id,
356
+ conversationId: input.session_id,
278
357
  projectSessionId: result.sessionId ?? null,
358
+ taskId: result.task?.taskId ?? null,
359
+ agentId,
360
+ parentAgentId,
279
361
  prompt: input.prompt,
280
362
  continuityState: result.continuity?.state ?? '',
281
363
  });
@@ -291,7 +373,7 @@ export const createClaudeAdapter = ({
291
373
  };
292
374
 
293
375
  const handlePostToolUse = async (input) => {
294
- const hookKey = buildClaudeHookKey({ sessionId: input.session_id });
376
+ const hookKey = buildClaudeHookKey({ sessionId: input.session_id, agentId: resolveAgentId(input) });
295
377
  const existing = await readTrackedState(hookKey);
296
378
  if (!existing) {
297
379
  return null;
@@ -307,7 +389,7 @@ export const createClaudeAdapter = ({
307
389
  toolResponse: input.tool_response,
308
390
  });
309
391
 
310
- const nextState = {
392
+ let nextState = {
311
393
  ...existing,
312
394
  checkpointed: checkpoint.matched ? true : existing.checkpointed,
313
395
  checkpointEvent: checkpoint.matched ? checkpoint.event : existing.checkpointEvent,
@@ -316,6 +398,17 @@ export const createClaudeAdapter = ({
316
398
  updatedAt: new Date().toISOString(),
317
399
  };
318
400
 
401
+ if (!checkpoint.matched && touchedFiles.length > 0) {
402
+ const autoCheckpointed = await maybeAutoCheckpointFromState(nextState, { trigger: 'post_tool_use' });
403
+ if (autoCheckpointed) {
404
+ nextState = {
405
+ ...nextState,
406
+ checkpointed: true,
407
+ checkpointEvent: 'milestone',
408
+ };
409
+ }
410
+ }
411
+
319
412
  await maybeSetTrackedTurnState({ hookKey, state: nextState });
320
413
  if (checkpoint.matched || touchedFiles.length > 0) {
321
414
  await recordHookMetrics({
@@ -329,7 +422,7 @@ export const createClaudeAdapter = ({
329
422
  };
330
423
 
331
424
  const handleStop = async (input) => {
332
- const hookKey = buildClaudeHookKey({ sessionId: input.session_id });
425
+ const hookKey = buildClaudeHookKey({ sessionId: input.session_id, agentId: resolveAgentId(input) });
333
426
  const state = await readTrackedState(hookKey);
334
427
  if (!state) {
335
428
  return null;
@@ -371,6 +464,23 @@ export const createClaudeAdapter = ({
371
464
  });
372
465
  }
373
466
 
467
+ if (state.taskId) {
468
+ await writeTaskHandoff({
469
+ taskId: state.taskId,
470
+ sessionId: state.projectSessionId,
471
+ fromAgentId: state.agentId ?? null,
472
+ toAgentId: null,
473
+ trigger: state.agentId && state.agentId !== 'main' ? 'subagent_delegate' : 'stop',
474
+ summary: {
475
+ currentFocus: update.currentFocus ?? state.promptPreview,
476
+ touchedFiles: state.touchedFiles,
477
+ pending: update.nextStep ? [update.nextStep] : [],
478
+ nextStep: update.nextStep ?? null,
479
+ evidence: state.touchedFiles.length > 0 ? [`Touched files: ${state.touchedFiles.join(', ')}`] : [],
480
+ },
481
+ });
482
+ }
483
+
374
484
  await recordHookMetrics({
375
485
  action: 'Stop',
376
486
  sessionId: state.projectSessionId,
@@ -7,7 +7,9 @@ import { smartTurn } from '../../tools/smart-turn.js';
7
7
  import {
8
8
  deleteHookTurnState,
9
9
  getHookTurnState,
10
+ persistTaskHandoff,
10
11
  setHookTurnState,
12
+ upsertAgentRun,
11
13
  } from '../../storage/sqlite.js';
12
14
  import { DEFAULT_START_MAX_TOKENS, resolveManagedStart } from '../base-orchestrator.js';
13
15
  import { extractNextStep, normalizeWhitespace, truncate } from '../policy/event-policy.js';
@@ -25,8 +27,20 @@ export const WRITE_TOOLS = new Set(['Write', 'StrReplace', 'Delete', 'EditNotebo
25
27
 
26
28
  const uniq = (values) => [...new Set(values.filter((value) => typeof value === 'string' && value.trim().length > 0))];
27
29
 
30
+ const resolveAgentId = (input = {}) => {
31
+ const value = input.agent_id ?? input.agentId ?? input.worker_id ?? null;
32
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : 'main';
33
+ };
34
+
35
+ const resolveParentAgentId = (input = {}) => {
36
+ const value = input.parent_agent_id ?? input.parentAgentId ?? null;
37
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;
38
+ };
39
+
28
40
  export const buildCursorHookKey = ({ conversationId, agentId = null }) =>
29
- agentId ? `${HOOK_CLIENT}:subagent:${conversationId}:${agentId}` : `${HOOK_CLIENT}:main:${conversationId}`;
41
+ agentId && agentId !== 'main'
42
+ ? `${HOOK_CLIENT}:subagent:${conversationId}:${agentId}`
43
+ : `${HOOK_CLIENT}:main:${conversationId}`;
30
44
 
31
45
  const countPromptTerms = (value) =>
32
46
  normalizeWhitespace(value)
@@ -151,6 +165,8 @@ export const createCursorAdapter = ({
151
165
  summaryTool = smartSummary,
152
166
  resolveStart = resolveManagedStart,
153
167
  persistMetric = persistMetrics,
168
+ writeAgentRun = upsertAgentRun,
169
+ writeTaskHandoff = persistTaskHandoff,
154
170
  getMutationSafety = getRepoMutationSafety,
155
171
  readHookState = null,
156
172
  writeHookState = ({ hookKey, state }) => setHookTurnState({ hookKey, state }),
@@ -218,7 +234,11 @@ export const createCursorAdapter = ({
218
234
  const maybeTrackTurn = async ({
219
235
  hookKey,
220
236
  cursorConversationId,
237
+ conversationId,
221
238
  projectSessionId,
239
+ taskId,
240
+ agentId,
241
+ parentAgentId,
222
242
  prompt,
223
243
  continuityState,
224
244
  }) => {
@@ -235,7 +255,11 @@ export const createCursorAdapter = ({
235
255
  state: {
236
256
  client: HOOK_CLIENT,
237
257
  cursorConversationId,
258
+ conversationId,
238
259
  projectSessionId,
260
+ taskId,
261
+ agentId,
262
+ parentAgentId,
239
263
  turnId: `${cursorConversationId}:${Date.now()}`,
240
264
  promptPreview: truncate(prompt, MAX_PROMPT_PREVIEW),
241
265
  continuityState,
@@ -249,6 +273,45 @@ export const createCursorAdapter = ({
249
273
  });
250
274
  };
251
275
 
276
+ const maybeAutoCheckpointFromState = async (state, { trigger = 'post_tool_use' } = {}) => {
277
+ if (!state?.projectSessionId || getMutationSafety().shouldBlock) {
278
+ return false;
279
+ }
280
+
281
+ const update = {
282
+ ...(state.promptPreview ? { currentFocus: state.promptPreview } : {}),
283
+ ...(state.touchedFiles.length > 0 ? { touchedFiles: state.touchedFiles } : {}),
284
+ };
285
+
286
+ await summaryTool({
287
+ action: 'checkpoint',
288
+ sessionId: state.projectSessionId,
289
+ event: 'milestone',
290
+ update,
291
+ maxTokens: STOP_MAX_TOKENS,
292
+ force: true,
293
+ });
294
+
295
+ if (state.taskId) {
296
+ await writeTaskHandoff({
297
+ taskId: state.taskId,
298
+ sessionId: state.projectSessionId,
299
+ fromAgentId: state.agentId ?? null,
300
+ toAgentId: null,
301
+ trigger,
302
+ summary: {
303
+ currentFocus: state.promptPreview,
304
+ touchedFiles: state.touchedFiles,
305
+ pending: [],
306
+ nextStep: null,
307
+ evidence: state.touchedFiles.length > 0 ? [`Touched files: ${state.touchedFiles.join(', ')}`] : [],
308
+ },
309
+ });
310
+ }
311
+
312
+ return true;
313
+ };
314
+
252
315
  const handleConversationStart = async () => {
253
316
  const result = await startTurn({
254
317
  phase: 'start',
@@ -265,6 +328,8 @@ export const createCursorAdapter = ({
265
328
  };
266
329
 
267
330
  const handleUserMessageSubmit = async (input) => {
331
+ const agentId = resolveAgentId(input);
332
+ const parentAgentId = resolveParentAgentId(input);
268
333
  const startResolution = await resolveStart({
269
334
  prompt: input.user_message,
270
335
  ensureSession: true,
@@ -275,10 +340,27 @@ export const createCursorAdapter = ({
275
340
  });
276
341
  const result = startResolution.startResult;
277
342
 
343
+ if (!getMutationSafety().shouldBlock) {
344
+ await writeAgentRun({
345
+ runId: buildCursorHookKey({ conversationId: input.conversation_id, agentId }),
346
+ taskId: result.task?.taskId ?? null,
347
+ agentId,
348
+ parentAgentId,
349
+ client: HOOK_CLIENT,
350
+ conversationId: input.conversation_id,
351
+ sessionId: result.sessionId ?? null,
352
+ role: agentId === 'main' ? 'main' : 'subagent',
353
+ });
354
+ }
355
+
278
356
  const trackedState = await maybeTrackTurn({
279
- hookKey: buildCursorHookKey({ conversationId: input.conversation_id }),
357
+ hookKey: buildCursorHookKey({ conversationId: input.conversation_id, agentId }),
280
358
  cursorConversationId: input.conversation_id,
359
+ conversationId: input.conversation_id,
281
360
  projectSessionId: result.sessionId ?? null,
361
+ taskId: result.task?.taskId ?? null,
362
+ agentId,
363
+ parentAgentId,
282
364
  prompt: input.user_message,
283
365
  continuityState: result.continuity?.state ?? '',
284
366
  });
@@ -294,7 +376,7 @@ export const createCursorAdapter = ({
294
376
  };
295
377
 
296
378
  const handlePostToolUse = async (input) => {
297
- const hookKey = buildCursorHookKey({ conversationId: input.conversation_id });
379
+ const hookKey = buildCursorHookKey({ conversationId: input.conversation_id, agentId: resolveAgentId(input) });
298
380
  const existing = await readTrackedState(hookKey);
299
381
  if (!existing) {
300
382
  return null;
@@ -310,7 +392,7 @@ export const createCursorAdapter = ({
310
392
  toolResponse: input.tool_response,
311
393
  });
312
394
 
313
- const nextState = {
395
+ let nextState = {
314
396
  ...existing,
315
397
  checkpointed: checkpoint.matched ? true : existing.checkpointed,
316
398
  checkpointEvent: checkpoint.matched ? checkpoint.event : existing.checkpointEvent,
@@ -319,6 +401,17 @@ export const createCursorAdapter = ({
319
401
  updatedAt: new Date().toISOString(),
320
402
  };
321
403
 
404
+ if (!checkpoint.matched && touchedFiles.length > 0) {
405
+ const autoCheckpointed = await maybeAutoCheckpointFromState(nextState, { trigger: 'post_tool_use' });
406
+ if (autoCheckpointed) {
407
+ nextState = {
408
+ ...nextState,
409
+ checkpointed: true,
410
+ checkpointEvent: 'milestone',
411
+ };
412
+ }
413
+ }
414
+
322
415
  await maybeSetTrackedTurnState({ hookKey, state: nextState });
323
416
  if (checkpoint.matched || touchedFiles.length > 0) {
324
417
  await recordHookMetrics({
@@ -332,7 +425,7 @@ export const createCursorAdapter = ({
332
425
  };
333
426
 
334
427
  const handleConversationEnd = async (input) => {
335
- const hookKey = buildCursorHookKey({ conversationId: input.conversation_id });
428
+ const hookKey = buildCursorHookKey({ conversationId: input.conversation_id, agentId: resolveAgentId(input) });
336
429
  const state = await readTrackedState(hookKey);
337
430
  if (!state) {
338
431
  return null;
@@ -374,6 +467,23 @@ export const createCursorAdapter = ({
374
467
  });
375
468
  }
376
469
 
470
+ if (state.taskId) {
471
+ await writeTaskHandoff({
472
+ taskId: state.taskId,
473
+ sessionId: state.projectSessionId,
474
+ fromAgentId: state.agentId ?? null,
475
+ toAgentId: null,
476
+ trigger: state.agentId && state.agentId !== 'main' ? 'subagent_delegate' : 'session_end',
477
+ summary: {
478
+ currentFocus: update.currentFocus ?? state.promptPreview,
479
+ touchedFiles: state.touchedFiles,
480
+ pending: update.nextStep ? [update.nextStep] : [],
481
+ nextStep: update.nextStep ?? null,
482
+ evidence: state.touchedFiles.length > 0 ? [`Touched files: ${state.touchedFiles.join(', ')}`] : [],
483
+ },
484
+ });
485
+ }
486
+
377
487
  await recordHookMetrics({
378
488
  action: 'ConversationEnd',
379
489
  sessionId: state.projectSessionId,
package/src/server.js CHANGED
@@ -35,6 +35,17 @@ import {
35
35
  const require = createRequire(import.meta.url);
36
36
  const { version } = require('../package.json');
37
37
 
38
+ const SERVER_INSTRUCTIONS = `devctx — compressed context, search, and session handoff for long work (migrations, multi-file refactors, multi-session tasks).
39
+
40
+ smart_turn (session continuity — read this before calling):
41
+ - START: phase "start". Pass userPrompt (current goal). ensureSession true recommended when you want persistence. Use at the beginning of substantial work or when resuming after a break — not for one-line fixes or single-shot questions.
42
+ - END: phase "end". Pass event: milestone | blocker | task_complete. Pass sessionId if you have it; include update (nextStep, completed, etc.) when checkpointing progress. Call after a meaningful slice of work (close a phase), not after every trivial edit.
43
+ - SKIP smart_turn entirely for trivial or same-session point tasks (the tool schema also warns about this).
44
+
45
+ Source of truth: devctx does not replace git history, PRs, or repo docs (e.g. MIGRATION.md). If end was not called or work was not committed, those remain authoritative.
46
+
47
+ Other entry points: smart_context for curated multi-file context; smart_search with intent for exploration; smart_read in outline|signatures|symbol before full reads; smart_shell for safe git/npm diagnostics.`;
48
+
38
49
  export const asTextResult = (result) => ({
39
50
  content: [
40
51
  {
@@ -52,10 +63,10 @@ export const createDevctxServer = () => {
52
63
  process.exit(1);
53
64
  }
54
65
 
55
- const server = new McpServer({
56
- name: 'devctx',
57
- version,
58
- });
66
+ const server = new McpServer(
67
+ { name: 'devctx', version },
68
+ { instructions: SERVER_INSTRUCTIONS },
69
+ );
59
70
 
60
71
  setServerForStreaming(server);
61
72