@echoes-io/mcp-server 4.1.0 → 4.1.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 (47) hide show
  1. package/cli/index.d.ts +2 -0
  2. package/cli/index.js +186 -0
  3. package/package.json +2 -1
  4. package/src/database/index.d.ts +6 -0
  5. package/src/database/index.js +26 -0
  6. package/src/database/relations.d.ts +744 -0
  7. package/src/database/relations.js +52 -0
  8. package/src/database/schema.d.ts +733 -0
  9. package/src/database/schema.js +69 -0
  10. package/src/database/vector.d.ts +25 -0
  11. package/src/database/vector.js +98 -0
  12. package/src/index.d.ts +5 -0
  13. package/src/index.js +5 -0
  14. package/src/rag/character-ner.d.ts +36 -0
  15. package/src/rag/character-ner.js +416 -0
  16. package/src/rag/database-sync.d.ts +38 -0
  17. package/src/rag/database-sync.js +158 -0
  18. package/src/rag/embeddings.d.ts +74 -0
  19. package/src/rag/embeddings.js +164 -0
  20. package/src/rag/graph-rag.d.ts +69 -0
  21. package/src/rag/graph-rag.js +311 -0
  22. package/src/rag/hybrid-rag.d.ts +109 -0
  23. package/src/rag/hybrid-rag.js +255 -0
  24. package/src/rag/index.d.ts +16 -0
  25. package/src/rag/index.js +33 -0
  26. package/src/server.d.ts +43 -0
  27. package/src/server.js +177 -0
  28. package/src/tools/index-rag.d.ts +19 -0
  29. package/src/tools/index-rag.js +85 -0
  30. package/src/tools/index-tracker.d.ts +17 -0
  31. package/src/tools/index-tracker.js +89 -0
  32. package/src/tools/index.d.ts +5 -0
  33. package/src/tools/index.js +5 -0
  34. package/src/tools/rag-context.d.ts +34 -0
  35. package/src/tools/rag-context.js +51 -0
  36. package/src/tools/rag-search.d.ts +35 -0
  37. package/src/tools/rag-search.js +60 -0
  38. package/src/tools/words-count.d.ts +15 -0
  39. package/src/tools/words-count.js +28 -0
  40. package/src/types/frontmatter.d.ts +35 -0
  41. package/src/types/frontmatter.js +1 -0
  42. package/src/utils/index.d.ts +1 -0
  43. package/src/utils/index.js +1 -0
  44. package/src/utils/markdown.d.ts +6 -0
  45. package/src/utils/markdown.js +36 -0
  46. package/src/utils/timeline-detection.d.ts +13 -0
  47. package/src/utils/timeline-detection.js +76 -0
package/cli/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/cli/index.js ADDED
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+ import { runServer } from '../src/server.js';
3
+ import { indexRag } from '../src/tools/index-rag.js';
4
+ import { indexTracker } from '../src/tools/index-tracker.js';
5
+ import { ragContext } from '../src/tools/rag-context.js';
6
+ import { ragSearch } from '../src/tools/rag-search.js';
7
+ import { wordsCount } from '../src/tools/words-count.js';
8
+ import { getTimelineContext } from '../src/utils/timeline-detection.js';
9
+ const [, , command, ...args] = process.argv;
10
+ async function main() {
11
+ if (!command) {
12
+ // No command = run MCP server
13
+ await runServer();
14
+ return;
15
+ }
16
+ // CLI commands
17
+ switch (command) {
18
+ case 'words-count': {
19
+ const filePath = args[0];
20
+ const detailed = args.includes('--detailed');
21
+ if (!filePath) {
22
+ console.error('Usage: echoes-mcp-server words-count <file> [--detailed]');
23
+ process.exit(1);
24
+ }
25
+ try {
26
+ const result = await wordsCount({ filePath, detailed });
27
+ console.log(JSON.stringify(result, null, 2));
28
+ }
29
+ catch (error) {
30
+ console.error('Error:', error instanceof Error ? error.message : error);
31
+ process.exit(1);
32
+ }
33
+ break;
34
+ }
35
+ case 'index-tracker': {
36
+ const timelineArg = args[0];
37
+ const contentPathArg = args[1];
38
+ try {
39
+ const { timeline, contentPath } = getTimelineContext(timelineArg, contentPathArg);
40
+ const result = await indexTracker({ timeline, contentPath });
41
+ console.log(JSON.stringify(result, null, 2));
42
+ }
43
+ catch (error) {
44
+ console.error('Error:', error instanceof Error ? error.message : error);
45
+ process.exit(1);
46
+ }
47
+ break;
48
+ }
49
+ case 'index-rag': {
50
+ const timelineArg = args[0];
51
+ const contentPathArg = args[1];
52
+ const arcFlag = args.indexOf('--arc');
53
+ const episodeFlag = args.indexOf('--episode');
54
+ try {
55
+ const { timeline, contentPath } = getTimelineContext(timelineArg, contentPathArg);
56
+ const arc = arcFlag !== -1 ? args[arcFlag + 1] : undefined;
57
+ const episode = episodeFlag !== -1 ? parseInt(args[episodeFlag + 1], 10) : undefined;
58
+ const result = await indexRag({ timeline, contentPath, arc, episode });
59
+ console.log(JSON.stringify(result, null, 2));
60
+ }
61
+ catch (error) {
62
+ console.error('Error:', error instanceof Error ? error.message : error);
63
+ process.exit(1);
64
+ }
65
+ break;
66
+ }
67
+ case 'rag-search': {
68
+ const timelineArg = args[0];
69
+ const query = args[1] || args[0]; // If no timeline provided, first arg is query
70
+ try {
71
+ const { timeline } = getTimelineContext(timelineArg && args[1] ? timelineArg : undefined);
72
+ const actualQuery = args[1] ? query : timelineArg; // Adjust query based on args
73
+ if (!actualQuery) {
74
+ console.error('Usage: echoes-mcp-server rag-search "<query>" [options]');
75
+ console.error(' or: echoes-mcp-server rag-search <timeline> "<query>" [options]');
76
+ process.exit(1);
77
+ }
78
+ // Parse optional flags
79
+ const topKFlag = args.indexOf('--top-k');
80
+ const charactersFlag = args.indexOf('--characters');
81
+ const arcFlag = args.indexOf('--arc');
82
+ const povFlag = args.indexOf('--pov');
83
+ const allCharacters = args.includes('--all-characters');
84
+ const vectorOnly = args.includes('--vector-only');
85
+ const topK = topKFlag !== -1 ? parseInt(args[topKFlag + 1], 10) : 10;
86
+ const characters = charactersFlag !== -1 ? args[charactersFlag + 1].split(',') : undefined;
87
+ const arc = arcFlag !== -1 ? args[arcFlag + 1] : undefined;
88
+ const pov = povFlag !== -1 ? args[povFlag + 1] : undefined;
89
+ const result = await ragSearch({
90
+ timeline,
91
+ query: actualQuery,
92
+ topK,
93
+ characters,
94
+ allCharacters,
95
+ arc,
96
+ pov,
97
+ useGraphRAG: !vectorOnly,
98
+ });
99
+ console.log(JSON.stringify(result, null, 2));
100
+ }
101
+ catch (error) {
102
+ console.error('Error:', error instanceof Error ? error.message : error);
103
+ process.exit(1);
104
+ }
105
+ break;
106
+ }
107
+ case 'rag-context': {
108
+ const timelineArg = args[0];
109
+ const query = args[1] || args[0]; // If no timeline provided, first arg is query
110
+ try {
111
+ const { timeline } = getTimelineContext(timelineArg && args[1] ? timelineArg : undefined);
112
+ const actualQuery = args[1] ? query : timelineArg; // Adjust query based on args
113
+ if (!actualQuery) {
114
+ console.error('Usage: echoes-mcp-server rag-context "<query>" [options]');
115
+ console.error(' or: echoes-mcp-server rag-context <timeline> "<query>" [options]');
116
+ process.exit(1);
117
+ }
118
+ // Parse optional flags
119
+ const maxChaptersFlag = args.indexOf('--max-chapters');
120
+ const charactersFlag = args.indexOf('--characters');
121
+ const arcFlag = args.indexOf('--arc');
122
+ const povFlag = args.indexOf('--pov');
123
+ const allCharacters = args.includes('--all-characters');
124
+ const maxChapters = maxChaptersFlag !== -1 ? parseInt(args[maxChaptersFlag + 1], 10) : 5;
125
+ const characters = charactersFlag !== -1 ? args[charactersFlag + 1].split(',') : undefined;
126
+ const arc = arcFlag !== -1 ? args[arcFlag + 1] : undefined;
127
+ const pov = povFlag !== -1 ? args[povFlag + 1] : undefined;
128
+ const result = await ragContext({
129
+ timeline,
130
+ query: actualQuery,
131
+ maxChapters,
132
+ characters,
133
+ allCharacters,
134
+ arc,
135
+ pov,
136
+ });
137
+ console.log(JSON.stringify(result, null, 2));
138
+ }
139
+ catch (error) {
140
+ console.error('Error:', error instanceof Error ? error.message : error);
141
+ process.exit(1);
142
+ }
143
+ break;
144
+ }
145
+ case 'help':
146
+ console.log(`
147
+ Echoes MCP Server v3.0.0
148
+
149
+ Usage:
150
+ echoes-mcp-server # Run MCP server
151
+ echoes-mcp-server words-count <file> # Count words in file
152
+ echoes-mcp-server index-tracker [timeline] [path] # Sync filesystem to database (auto-detects from cwd)
153
+ echoes-mcp-server index-rag [timeline] [path] # Index chapters into GraphRAG (auto-detects from cwd)
154
+ echoes-mcp-server rag-search "<query>" # Search chapters semantically (auto-detects timeline)
155
+ echoes-mcp-server rag-context "<query>" # Get full chapter context for AI (auto-detects timeline)
156
+ echoes-mcp-server help # Show this help
157
+
158
+ Auto-Detection:
159
+ Run from timeline-* directory: auto-detects timeline and content path
160
+ Run from .github directory: multi-timeline mode (requires explicit timeline)
161
+ Run from mcp-server directory: test mode
162
+
163
+ Examples:
164
+ cd timeline-pulse && echoes-mcp-server index-tracker # Auto-detects "pulse" timeline
165
+ cd timeline-pulse && echoes-mcp-server rag-search "romantic scene"
166
+ echoes-mcp-server rag-search pulse "romantic scene" # Explicit timeline
167
+
168
+ Options:
169
+ --detailed # Include detailed statistics (words-count)
170
+ --arc <name> # Filter by arc (index-rag, rag-search, rag-context)
171
+ --episode <num> # Filter by episode (index-rag)
172
+ --top-k <num> # Max results (rag-search, default: 10)
173
+ --max-chapters <num> # Max chapters (rag-context, default: 5)
174
+ --characters <name1,name2> # Filter by characters (rag-search, rag-context)
175
+ --all-characters # Require all characters (rag-search, rag-context)
176
+ --pov <name> # Filter by POV (rag-search, rag-context)
177
+ --vector-only # Use vector search only (rag-search)
178
+ `);
179
+ break;
180
+ default:
181
+ console.error(`Unknown command: ${command}`);
182
+ console.error('Run "echoes-mcp-server help" for usage information');
183
+ process.exit(1);
184
+ }
185
+ }
186
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@echoes-io/mcp-server",
3
3
  "type": "module",
4
- "version": "4.1.0",
4
+ "version": "4.1.1",
5
5
  "description": "Model Context Protocol server for AI integration with Echoes storytelling platform",
6
6
  "scripts": {
7
7
  "dev": "tsx cli/index.ts",
@@ -24,6 +24,7 @@
24
24
  "clean": "rimraf --glob ./{cli,src,test}/**/*.{d.ts,js} ./{drizzle,vitest}*.{d.ts,js}",
25
25
  "prebuild": "npm run clean",
26
26
  "build": "tsc",
27
+ "prerelease": "npm run build",
27
28
  "release": "semantic-release"
28
29
  },
29
30
  "bin": {
@@ -0,0 +1,6 @@
1
+ import { drizzle } from 'drizzle-orm/better-sqlite3';
2
+ import * as schema from './schema.js';
3
+ export type DatabaseType = ReturnType<typeof drizzle<typeof schema>>;
4
+ export declare function initDatabase(dbPath: string): Promise<DatabaseType>;
5
+ export { relations } from './relations.js';
6
+ export * from './schema.js';
@@ -0,0 +1,26 @@
1
+ import Database from 'better-sqlite3';
2
+ import { drizzle } from 'drizzle-orm/better-sqlite3';
3
+ import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
4
+ import * as sqliteVec from 'sqlite-vec';
5
+ import { relations } from './relations.js';
6
+ import * as schema from './schema.js';
7
+ export async function initDatabase(dbPath) {
8
+ const client = new Database(dbPath);
9
+ // Enable WAL mode for better concurrency
10
+ client.pragma('journal_mode = WAL');
11
+ // Load sqlite-vec extension
12
+ sqliteVec.load(client);
13
+ const db = drizzle({ client, relations, schema });
14
+ // Auto-migrate on startup
15
+ try {
16
+ await migrate(db, { migrationsFolder: './db' });
17
+ }
18
+ catch (error) {
19
+ console.error('❌ Database migration failed:', error);
20
+ throw error;
21
+ }
22
+ return db;
23
+ }
24
+ export { relations } from './relations.js';
25
+ // Re-export all schema
26
+ export * from './schema.js';