@marsnme/mcp-gateway 0.2.0 → 0.2.1

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 (2) hide show
  1. package/package.json +2 -2
  2. package/server.mjs +81 -80
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marsnme/mcp-gateway",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "mcpName": "io.github.Marsmanleo/marsnme",
5
5
  "private": false,
6
6
  "description": "Agent-agnostic, LLM-agnostic memory backend for MCP-compatible tools",
@@ -49,4 +49,4 @@
49
49
  "engines": {
50
50
  "node": ">=20"
51
51
  }
52
- }
52
+ }
package/server.mjs CHANGED
@@ -307,29 +307,29 @@ function buildTools() {
307
307
  return [
308
308
  {
309
309
  name: 'insert_memory',
310
- description: `Insert a short-term ${PROFILE.displayName} memory into ${DB_PROFILE}.memories (ephemeral context)`,
310
+ description: `Store a short-term ${PROFILE.displayName} memory into ${DB_PROFILE}.memories (ephemeral context that auto-expires). Use this to capture observations, decisions, session notes, or any context worth remembering temporarily. Memories last 7 days by default unless expires_at is set. For permanent knowledge, use memory_ingest instead.`,
311
311
  inputSchema: {
312
312
  type: 'object',
313
313
  properties: {
314
- body: { type: 'string', description: 'Memory content text' },
314
+ body: { type: 'string', description: 'The memory content to store. Be specific and include relevant context — this text is used for semantic search later.' },
315
315
  source: buildMemorySourceSchema(),
316
- session_id: { type: 'string', description: 'Session trace id' },
316
+ session_id: { type: 'string', description: 'Unique identifier for the current session/conversation. Used to group related memories together.' },
317
317
  tags: {
318
318
  type: 'array',
319
319
  items: { type: 'string' },
320
- description: 'Optional tags list'
320
+ description: 'Categorization labels for filtering (e.g. ["decision", "architecture", "bugfix"])'
321
321
  },
322
322
  expires_at: {
323
323
  type: 'string',
324
- description: 'Optional ISO timestamp override'
324
+ description: 'Custom expiration time in ISO 8601 format (e.g. "2026-06-17T00:00:00Z"). Defaults to 7 days from now if omitted.'
325
325
  },
326
326
  agent_body: {
327
327
  type: 'string',
328
- description: 'Optional body label (default inferred from source)'
328
+ description: 'Which persona/agent body this memory belongs to (e.g. "coco", "toto"). Defaults to the profile of this server.'
329
329
  },
330
330
  environment: {
331
331
  type: 'string',
332
- description: 'Optional environment label (default from MCP_ENVIRONMENT)'
332
+ description: 'Deployment environment label (e.g. "production", "staging"). Defaults to MCP_ENVIRONMENT if set.'
333
333
  }
334
334
  },
335
335
  required: ['body', 'source', 'session_id'],
@@ -338,36 +338,36 @@ function buildTools() {
338
338
  },
339
339
  {
340
340
  name: 'list_memories',
341
- description: `List recent memories from ${DB_PROFILE}.memories`,
341
+ description: `List recent short-term memories from ${DB_PROFILE}.memories in reverse chronological order — like a daily log or activity feed. Use this to review what was recently captured, check for duplicate memories before inserting, or browse recent activity. This is a time-ordered listing tool, not a search tool. For semantic search by meaning, use search_memories instead. For long-term knowledge retrieval, use recall. Returns memory body, source, creation time, and expiration status.`,
342
342
  inputSchema: {
343
343
  type: 'object',
344
344
  properties: {
345
- limit: { type: 'number', minimum: 1, maximum: 100, default: 20 },
345
+ limit: { type: 'number', minimum: 1, maximum: 100, default: 20, description: 'Maximum number of memories to return (default 20)' },
346
346
  source: buildMemorySourceSchema(),
347
- unexpired_only: { type: 'boolean', default: true }
347
+ unexpired_only: { type: 'boolean', default: true, description: 'When true (default), only return memories that have not yet expired. Set false to include expired entries.' }
348
348
  },
349
349
  additionalProperties: false
350
350
  }
351
351
  },
352
352
  {
353
353
  name: 'search_memories',
354
- description: `Semantic search memories from ${DB_PROFILE}.memories using Jina embeddings`,
354
+ description: `Semantic search across short-term memories in ${DB_PROFILE}.memories using Jina embeddings. Finds memories by meaning, not just keywords — ask a natural language question and get the most relevant matches. Use this to recall past decisions, find related context, or check if something was already discussed recently.`,
355
355
  inputSchema: {
356
356
  type: 'object',
357
357
  properties: {
358
- query: { type: 'string', description: 'Semantic search query text' },
359
- limit: { type: 'number', minimum: 1, maximum: 100, default: 20 },
358
+ query: { type: 'string', description: 'Natural language search query. Describe what you are looking for — semantic matching finds relevant results even without exact keywords.' },
359
+ limit: { type: 'number', minimum: 1, maximum: 100, default: 20, description: 'Maximum number of results to return' },
360
360
  source: buildMemorySourceSchema(),
361
- unexpired_only: { type: 'boolean', default: true },
362
- min_similarity: { type: 'number', minimum: -1, maximum: 1 },
363
- scope: { type: 'string', enum: ['this_body', 'all_bodies'], default: 'this_body' },
361
+ unexpired_only: { type: 'boolean', default: true, description: 'When true (default), exclude expired memories from results' },
362
+ min_similarity: { type: 'number', minimum: -1, maximum: 1, description: 'Minimum cosine similarity threshold for results (range -1 to 1). Higher values return fewer but more relevant matches.' },
363
+ scope: { type: 'string', enum: ['this_body', 'all_bodies'], default: 'this_body', description: 'Search scope: "this_body" searches only the current profile, "all_bodies" searches across all personas.' },
364
364
  agent_body: {
365
365
  type: 'string',
366
- description: 'Optional body scope key; defaults to source/body/env inference'
366
+ description: 'Filter results to a specific persona/body (e.g. "coco", "toto")'
367
367
  },
368
368
  environment: {
369
369
  type: 'string',
370
- description: 'Optional environment filter'
370
+ description: 'Filter results to a specific environment (e.g. "production", "staging")'
371
371
  }
372
372
  },
373
373
  required: ['query'],
@@ -377,7 +377,7 @@ function buildTools() {
377
377
  {
378
378
  name: 'reload_source_registry',
379
379
  description:
380
- `Reload enabled sources cache from ${DB_PROFILE}.${SOURCE_REGISTRY_TABLE} (effective when MCP_SOURCE_MODE=registry)`,
380
+ `Reload the source registry cache from ${DB_PROFILE}.${SOURCE_REGISTRY_TABLE}. Use this after adding or removing entries to refresh which sources are enabled for insert/search filtering. Only effective when running in registry mode (MCP_SOURCE_MODE=registry).`,
381
381
  inputSchema: {
382
382
  type: 'object',
383
383
  properties: {},
@@ -386,31 +386,31 @@ function buildTools() {
386
386
  },
387
387
  {
388
388
  name: 'recall',
389
- description: `Semantic recall from ${DB_PROFILE}.marsvault_chunks using Jina embeddings`,
389
+ description: `Semantic recall from long-term memory (${DB_PROFILE}.marsvault_chunks) using Jina embeddings. Searches across promoted insights, digests, and archived knowledge using vector similarity. Use this to retrieve established patterns, past decisions, documented workflows, or any knowledge that was previously promoted to long-term storage. This is the primary tool for accessing institutional memory.`,
390
390
  inputSchema: {
391
391
  type: 'object',
392
392
  properties: {
393
- query: { type: 'string', description: 'Semantic recall query text' },
394
- limit: { type: 'number', minimum: 1, maximum: 50, default: 5 },
395
- body: { type: 'string', enum: PROFILE.recallBodyEnum, default: DB_PROFILE },
396
- include_global: { type: 'boolean', default: true },
397
- include_shared: { type: 'boolean', default: true },
398
- include_private: { type: 'boolean', default: true },
399
- type: { type: 'string', description: 'Optional chunk type filter' },
400
- min_similarity: { type: 'number', minimum: -1, maximum: 1 },
401
- scope: { type: 'string', enum: ['this_body', 'all_bodies'], default: 'this_body' },
393
+ query: { type: 'string', description: 'Natural language query describing what knowledge you need. The system finds semantically similar chunks — describe the concept, not just keywords.' },
394
+ limit: { type: 'number', minimum: 1, maximum: 50, default: 5, description: 'Maximum number of chunks to return (default 5)' },
395
+ body: { type: 'string', enum: PROFILE.recallBodyEnum, default: DB_PROFILE, description: 'Which persona profile to search in (e.g. "coco", "toto", "system")' },
396
+ include_global: { type: 'boolean', default: true, description: 'Include globally visible chunks in results' },
397
+ include_shared: { type: 'boolean', default: true, description: 'Include shared-visibility chunks in results' },
398
+ include_private: { type: 'boolean', default: true, description: 'Include private chunks in results' },
399
+ type: { type: 'string', description: 'Filter by chunk type (e.g. "insight", "digest", "observation")' },
400
+ min_similarity: { type: 'number', minimum: -1, maximum: 1, description: 'Minimum cosine similarity threshold. Raise for higher precision, lower for broader recall.' },
401
+ scope: { type: 'string', enum: ['this_body', 'all_bodies'], default: 'this_body', description: 'Search scope: "this_body" for current profile only, "all_bodies" for cross-persona search' },
402
402
  agent_body: {
403
403
  type: 'string',
404
- description: 'Optional body scope key; defaults to MCP_AGENT_BODY when present'
404
+ description: 'Filter to a specific persona/body scope'
405
405
  },
406
406
  environment: {
407
407
  type: 'string',
408
- description: 'Optional environment filter'
408
+ description: 'Filter to a specific environment label'
409
409
  },
410
410
  debug_explain: {
411
411
  type: 'boolean',
412
412
  default: false,
413
- description: 'Include query/hit token overlap debug details'
413
+ description: 'When true, include token overlap details in each result for debugging relevance'
414
414
  }
415
415
  },
416
416
  required: ['query'],
@@ -419,7 +419,7 @@ function buildTools() {
419
419
  },
420
420
  {
421
421
  name: 'health_check',
422
- description: `Run ${PROFILE.displayName} memory health diagnostics (count_chunks, expiry_alert, coverage_map, detect_conflicts)`,
422
+ description: `Run comprehensive ${PROFILE.displayName} memory system diagnostics. Returns chunk counts by type and visibility, identifies expiring short-term memories that need promotion, detects timeline coverage gaps, and finds conflicting or redundant long-term chunks. Use this regularly to maintain memory hygiene and before batch promotion.`,
423
423
  inputSchema: {
424
424
  type: 'object',
425
425
  properties: {
@@ -514,11 +514,11 @@ function buildTools() {
514
514
  {
515
515
  name: 'session_boot',
516
516
  description:
517
- 'One-call session boot rhythm: always run identity/workflow/status recall + expiry-focused health snapshot + heartbeat sign-in',
517
+ `Initialize a new ${PROFILE.displayName} session by loading identity, workflow context, and recent status from long-term memory. Also runs an expiry-focused health snapshot and records a heartbeat sign-in. Call this once at the start of every new conversation to restore continuity and awareness of pending work.`,
518
518
  inputSchema: {
519
519
  type: 'object',
520
520
  properties: {
521
- source: { type: 'string', enum: PROFILE.sourceWhitelist },
521
+ source: { type: 'string', enum: PROFILE.sourceWhitelist, description: 'Source tool identifier (e.g. "warp", "cursor", "perplexity") for provenance tracking' },
522
522
  body_name: {
523
523
  type: 'string',
524
524
  description: 'Optional body/persona name (例如:大家姐、三哥、五妹、Toto)'
@@ -551,7 +551,8 @@ function buildTools() {
551
551
  type: 'number',
552
552
  minimum: 1,
553
553
  maximum: 10,
554
- default: 5
554
+ default: 5,
555
+ description: 'Maximum recall results per category (identity/workflow/status, default 5)'
555
556
  },
556
557
  alert_window_hours: {
557
558
  type: 'number',
@@ -579,7 +580,7 @@ function buildTools() {
579
580
  {
580
581
  name: 'session_close',
581
582
  description:
582
- 'Store session close summary with 7-day retention for CoCo/Toto rhythm closure',
583
+ `Save a ${PROFILE.displayName} session close summary before ending a conversation. The summary is stored as a short-term memory with 7-day retention, providing context for the next session boot. Include what was accomplished, what is still pending, and any important context for continuity.`,
583
584
  inputSchema: {
584
585
  type: 'object',
585
586
  properties: {
@@ -604,24 +605,24 @@ function buildTools() {
604
605
  },
605
606
  {
606
607
  name: 'dream_ingest',
607
- description: `Chunk and ingest Hermes digest text into ${DB_PROFILE}.marsvault_chunks as long-term insight data`,
608
+ description: `Ingest a Hermes digest (periodic summary report) into ${DB_PROFILE}.marsvault_chunks long-term memory. The content is automatically chunked into semantically meaningful segments and stored with vector embeddings for future recall. Use this for scheduled reports, daily digests, or any structured summary content that should be permanently available.`,
608
609
  inputSchema: {
609
610
  type: 'object',
610
611
  properties: {
611
- content: { type: 'string', description: 'Digest full text content' },
612
- source_file: { type: 'string', description: 'Logical source path for digest' },
613
- section: { type: 'string', description: 'Section label prefix' },
612
+ content: { type: 'string', description: 'The full text content of the digest to ingest. Will be automatically split into semantically coherent chunks.' },
613
+ source_file: { type: 'string', description: 'Logical file path or identifier for the source of this digest (e.g. "hermes/daily/2026-06-10")' },
614
+ section: { type: 'string', description: 'Optional section label prefix to tag all resulting chunks' },
614
615
  tags: {
615
616
  type: 'array',
616
617
  items: { type: 'string' },
617
- description: 'Optional tags list'
618
+ description: 'Tags for categorization (e.g. ["digest", "daily", "report"])'
618
619
  },
619
- type: { type: 'string', description: 'Chunk type', default: 'digest' },
620
- date: { type: 'string', description: 'Optional YYYY-MM-DD date override' },
621
- body: { type: 'string', enum: PROFILE.recallBodyEnum, default: DB_PROFILE },
622
- visibility: { type: 'string', enum: ['private', 'shared', 'global'], default: 'private' },
623
- origin: { type: 'string', description: 'Origin marker', default: PROFILE.digestDefaultOrigin },
624
- max_chunk_chars: { type: 'number', minimum: 300, maximum: 3000, default: 1200 }
620
+ type: { type: 'string', description: 'Chunk type label', default: 'digest' },
621
+ date: { type: 'string', description: 'Date for this digest in YYYY-MM-DD format. Defaults to today if omitted.' },
622
+ body: { type: 'string', enum: PROFILE.recallBodyEnum, default: DB_PROFILE, description: 'Target persona profile for storage' },
623
+ visibility: { type: 'string', enum: ['private', 'shared', 'global'], default: 'private', description: 'Access level: "private" = owner only, "shared" = cross-profile, "global" = system-wide' },
624
+ origin: { type: 'string', description: 'Origin marker identifying where this content came from', default: PROFILE.digestDefaultOrigin },
625
+ max_chunk_chars: { type: 'number', minimum: 300, maximum: 3000, default: 1200, description: 'Maximum character length per chunk (default 1200). Larger values = fewer, longer chunks.' }
625
626
  },
626
627
  required: ['content'],
627
628
  additionalProperties: false
@@ -629,48 +630,48 @@ function buildTools() {
629
630
  },
630
631
  {
631
632
  name: PROFILE.memoryIngestToolName,
632
- description: `Chunk and ingest ${PROFILE.displayName} long-term insight content into ${DB_PROFILE}.marsvault_chunks (not short-memory)`,
633
+ description: `Promote content into permanent long-term memory (${DB_PROFILE}.marsvault_chunks). Automatically chunks the input text, generates vector embeddings, and stores each segment for semantic recall. Use this to preserve important insights, decisions, patterns, or knowledge that should survive beyond the current session. This is the primary path from ephemeral to permanent memory.`,
633
634
  inputSchema: {
634
635
  type: 'object',
635
636
  properties: {
636
- content: { type: 'string', description: 'Insight full text content' },
637
- source_file: { type: 'string', description: 'Logical source path for insight content' },
638
- section: { type: 'string', description: 'Section label prefix' },
637
+ content: { type: 'string', description: 'The insight content to promote to long-term memory. Be specific and self-contained — future recall depends on the quality of this text.' },
638
+ source_file: { type: 'string', description: 'Logical file path or identifier for the source (e.g. "sessions/2026-06-10-session-notes")' },
639
+ section: { type: 'string', description: 'Optional section label prefix to organize chunks within the source' },
639
640
  tags: {
640
641
  type: 'array',
641
642
  items: { type: 'string' },
642
- description: 'Optional tags list'
643
+ description: 'Categorization tags (e.g. ["decision", "architecture"])'
643
644
  },
644
- type: { type: 'string', description: 'Chunk type', default: 'insight' },
645
- date: { type: 'string', description: 'Optional YYYY-MM-DD date override' },
646
- visibility: { type: 'string', enum: ['private', 'shared', 'global'], default: 'private' },
645
+ type: { type: 'string', description: 'Content type label (e.g. "insight", "observation", "decision")', default: 'insight' },
646
+ date: { type: 'string', description: 'Date for this content in YYYY-MM-DD format. Defaults to today if omitted.' },
647
+ visibility: { type: 'string', enum: ['private', 'shared', 'global'], default: 'private', description: 'Access level: "private" = this profile only, "shared" = cross-profile readable, "global" = system-wide' },
647
648
  origin: buildMemoryIngestOriginSchema(),
648
649
  source_memory_id: {
649
650
  type: 'string',
650
- description: 'Optional short-memory id to link promoted long-memory chunks'
651
+ description: 'Link this promotion to a specific short-term memory ID (for traceability)'
651
652
  },
652
653
  source_session_id: {
653
654
  type: 'string',
654
- description: 'Optional source session id for provenance'
655
+ description: 'Session ID where this insight originated (for provenance tracking)'
655
656
  },
656
657
  source_tool: {
657
658
  type: 'string',
658
659
  enum: PROFILE.sourceWhitelist,
659
- description: 'Optional source tool for provenance'
660
+ description: 'The tool/platform where this insight was originally captured'
660
661
  },
661
662
  source_user_note: {
662
663
  type: 'string',
663
- description: 'Optional user note describing why this memory was promoted'
664
+ description: 'Brief note explaining why this memory was selected for promotion'
664
665
  },
665
666
  agent_body: {
666
667
  type: 'string',
667
- description: 'Optional body label for memory boundary'
668
+ description: 'The persona/body this memory belongs to (e.g. "coco", "toto")'
668
669
  },
669
670
  environment: {
670
671
  type: 'string',
671
- description: 'Optional environment label'
672
+ description: 'Environment label (e.g. "production", "staging")'
672
673
  },
673
- max_chunk_chars: { type: 'number', minimum: 300, maximum: 3000, default: 1200 }
674
+ max_chunk_chars: { type: 'number', minimum: 300, maximum: 3000, default: 1200, description: 'Maximum characters per chunk (default 1200). Adjust for finer or coarser granularity.' }
674
675
  },
675
676
  required: ['content'],
676
677
  additionalProperties: false
@@ -678,19 +679,19 @@ function buildTools() {
678
679
  },
679
680
  {
680
681
  name: 'demote_memory',
681
- description: `Mark a long-memory chunk as deprecated/superseded in ${DB_PROFILE}.marsvault_chunks`,
682
+ description: `Deprecate a long-term memory chunk in ${DB_PROFILE}.marsvault_chunks, marking it as outdated or superseded. The chunk is not deleted — it is flagged so it no longer appears in recall results. Use this when information becomes incorrect, irrelevant, or is replaced by newer knowledge. Optionally link to the replacement chunk for traceability.`,
682
683
  inputSchema: {
683
684
  type: 'object',
684
685
  properties: {
685
- id: { type: 'string', description: 'Long-memory chunk id (UUID)' },
686
- deprecated_reason: { type: 'string', description: 'Reason for deprecation' },
686
+ id: { type: 'string', description: 'UUID of the long-term memory chunk to deprecate' },
687
+ deprecated_reason: { type: 'string', description: 'Why this memory is being deprecated (e.g. "superseded by newer architecture decision", "information confirmed incorrect")' },
687
688
  superseded_by: {
688
689
  type: 'string',
689
- description: 'Optional replacement chunk id (UUID) when this memory is superseded'
690
+ description: 'UUID of the replacement chunk, if this memory is being superseded by updated content'
690
691
  },
691
692
  deprecated_at: {
692
693
  type: 'string',
693
- description: 'Optional ISO timestamp override; defaults to now'
694
+ description: 'Custom deprecation timestamp in ISO 8601 format. Defaults to now if omitted.'
694
695
  }
695
696
  },
696
697
  required: ['id', 'deprecated_reason'],
@@ -699,7 +700,7 @@ function buildTools() {
699
700
  },
700
701
  {
701
702
  name: 'soft_forget',
702
- description: `Expire short-memory rows early in ${DB_PROFILE}.memories (manual cleanup without hard delete)`,
703
+ description: `Expire short-term memories in ${DB_PROFILE}.memories early without permanently deleting them. Marked memories become invisible to search and list operations but remain in the database for audit purposes. Use this to clean up irrelevant or incorrect short-term memories before their natural expiration.`,
703
704
  inputSchema: {
704
705
  type: 'object',
705
706
  properties: {
@@ -708,15 +709,15 @@ function buildTools() {
708
709
  items: { type: 'string' },
709
710
  minItems: 1,
710
711
  maxItems: 50,
711
- description: 'Short-memory IDs (UUID) to expire immediately'
712
+ description: 'Array of short-term memory UUIDs to expire. Up to 50 at a time.'
712
713
  },
713
714
  reason: {
714
715
  type: 'string',
715
- description: 'Optional note for why these memories are being soft-forgotten'
716
+ description: 'Brief explanation of why these memories are being forgotten (for audit trail)'
716
717
  },
717
718
  forgotten_at: {
718
719
  type: 'string',
719
- description: 'Optional ISO timestamp override; defaults to now'
720
+ description: 'Custom expiration timestamp in ISO 8601 format. Defaults to now if omitted.'
720
721
  }
721
722
  },
722
723
  required: ['ids'],
@@ -725,11 +726,11 @@ function buildTools() {
725
726
  },
726
727
  {
727
728
  name: 'explain_memory',
728
- description: `Explain provenance of a long-memory chunk in ${DB_PROFILE}.marsvault_chunks (source memory/session/tool/timeline)`,
729
+ description: `Trace the full provenance of a long-term memory chunk in ${DB_PROFILE}.marsvault_chunks — where it came from, how it was created, and what source material it was derived from. Returns the original source memory, session, tool, and timeline information. Use this to understand why a piece of knowledge exists or to verify its reliability.`,
729
730
  inputSchema: {
730
731
  type: 'object',
731
732
  properties: {
732
- id: { type: 'string', description: 'Long-memory chunk id (UUID)' }
733
+ id: { type: 'string', description: 'UUID of the long-term memory chunk to explain' }
733
734
  },
734
735
  required: ['id'],
735
736
  additionalProperties: false
@@ -737,7 +738,7 @@ function buildTools() {
737
738
  },
738
739
  {
739
740
  name: 'batch_promote',
740
- description: `Auto-promote expiring short memories to long-term ${DB_PROFILE}.marsvault_chunks. Finds candidates via health check scoring, ingests content, marks promoted.`,
741
+ description: `Automatically promote expiring short-term memories from ${DB_PROFILE}.memories to permanent long-term storage (${DB_PROFILE}.marsvault_chunks). Scans for memories that will expire within the alert window, then chunks and ingests each one with vector embeddings. Use this to prevent valuable context from being lost when short-term memories expire. Supports dry-run mode to preview candidates before committing.`,
741
742
  inputSchema: {
742
743
  type: 'object',
743
744
  properties: {
@@ -746,29 +747,29 @@ function buildTools() {
746
747
  minimum: 1,
747
748
  maximum: 720,
748
749
  default: 48,
749
- description: 'Look-ahead window for expiring memories (hours)'
750
+ description: 'Look-ahead window in hours. Memories expiring within this window are candidates for promotion (default 48).'
750
751
  },
751
752
  max_promote: {
752
753
  type: 'number',
753
754
  minimum: 1,
754
755
  maximum: 50,
755
756
  default: 10,
756
- description: 'Maximum memories to promote in one batch'
757
+ description: 'Maximum number of memories to promote in a single batch (default 10).'
757
758
  },
758
759
  dry_run: {
759
760
  type: 'boolean',
760
761
  default: false,
761
- description: 'If true, list candidates without promoting'
762
+ description: 'When true, list candidate memories without actually promoting them. Use to preview before committing.'
762
763
  },
763
764
  memory_ids: {
764
765
  type: 'array',
765
766
  items: { type: 'string' },
766
767
  maxItems: 50,
767
- description: 'Optional explicit memory IDs to promote (skips auto-detection)'
768
+ description: 'Explicit list of short-term memory UUIDs to promote. When provided, auto-detection is skipped and only these IDs are processed.'
768
769
  },
769
770
  origin: {
770
771
  type: 'string',
771
- description: 'Origin marker for promoted chunks',
772
+ description: 'Origin marker tagged on all promoted chunks for traceability',
772
773
  default: 'batch-promote'
773
774
  }
774
775
  },