@ismaelsoilet/synapsejs 1.1.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 (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +206 -0
  3. package/bin/synapse.ts +919 -0
  4. package/package.json +70 -0
  5. package/src/client/components.tsx +508 -0
  6. package/src/client/context.tsx +62 -0
  7. package/src/client/hooks.ts +152 -0
  8. package/src/client/i18n.ts +40 -0
  9. package/src/client.ts +66 -0
  10. package/src/compiler/agent-diagnostic-json.ts +113 -0
  11. package/src/compiler/ast-daemon-compressor.ts +190 -0
  12. package/src/compiler/client-bundler.ts +356 -0
  13. package/src/compiler/context-bench.ts +191 -0
  14. package/src/compiler/contract.ts +260 -0
  15. package/src/compiler/db-schema-generator.ts +306 -0
  16. package/src/compiler/fields-parser.ts +267 -0
  17. package/src/compiler/impact-analyzer.ts +279 -0
  18. package/src/compiler/migration-runner.ts +555 -0
  19. package/src/compiler/oracle-runner.ts +293 -0
  20. package/src/compiler/scaffolder.ts +528 -0
  21. package/src/compiler/schema-dag.ts +137 -0
  22. package/src/compiler/schema-drift.ts +184 -0
  23. package/src/compiler/slice-discovery.ts +154 -0
  24. package/src/compiler/slice-splitter.ts +838 -0
  25. package/src/compiler/slice-templates.ts +1527 -0
  26. package/src/compiler/standalone-builder.ts +117 -0
  27. package/src/core/action-context.ts +152 -0
  28. package/src/core/config.ts +77 -0
  29. package/src/core/database-client.ts +246 -0
  30. package/src/core/database-factory.ts +46 -0
  31. package/src/core/image-optimizer.ts +83 -0
  32. package/src/core/index.ts +14 -0
  33. package/src/core/jobs.ts +53 -0
  34. package/src/core/machine-types.ts +75 -0
  35. package/src/core/oracle.ts +20 -0
  36. package/src/core/postgres-client.ts +164 -0
  37. package/src/core/postgres-queue.ts +288 -0
  38. package/src/core/query-builder.ts +343 -0
  39. package/src/core/rpc-client.ts +70 -0
  40. package/src/core/session-context.ts +87 -0
  41. package/src/core/session-cookie.ts +81 -0
  42. package/src/core/session-token.ts +170 -0
  43. package/src/core/sqlite-client.ts +201 -0
  44. package/src/core/storage.ts +317 -0
  45. package/src/index.ts +133 -0
  46. package/src/mcp/server.ts +553 -0
  47. package/src/runtime/client-entry.ts +65 -0
  48. package/src/runtime/discovery-rules.ts +63 -0
  49. package/src/runtime/event-hub.ts +97 -0
  50. package/src/runtime/postgres-event-hub.ts +148 -0
  51. package/src/runtime/queue-engine.ts +255 -0
  52. package/src/runtime/rate-limiter.ts +152 -0
  53. package/src/runtime/server.ts +1550 -0
  54. package/src/runtime/uploads.ts +192 -0
  55. package/templates/starter/.dockerignore +7 -0
  56. package/templates/starter/Dockerfile +40 -0
  57. package/templates/starter/README.md +40 -0
  58. package/templates/starter/gitignore +6 -0
  59. package/templates/starter/package.json +34 -0
  60. package/templates/starter/src/slices/welcome/hello-world.slice.tsx +172 -0
  61. package/templates/starter/tsconfig.json +21 -0
package/src/index.ts ADDED
@@ -0,0 +1,133 @@
1
+ /**
2
+ * SynapseJS - The Machine-Centric AI-Native Fullstack Engine
3
+ *
4
+ * Official Public Package Entry Point
5
+ */
6
+
7
+ // 2. Convenience Re-exports for JIT Validation & PBT
8
+ export { type Static, type TSchema, Type } from '@sinclair/typebox';
9
+ export { Value } from '@sinclair/typebox/value';
10
+ // 1. Kernel Types & Functional Error Handling
11
+ export * from './core/index';
12
+ export { type RpcTransportError, rpcCall, rpcTransportFailure } from './core/rpc-client';
13
+
14
+ import * as fc from 'fast-check';
15
+
16
+ export * from './client';
17
+ export { type DiagnosticIssue, type DiagnosticReport, runMachineVerifications } from './compiler/agent-diagnostic-json';
18
+ export { compressRepositoryAST } from './compiler/ast-daemon-compressor';
19
+ export {
20
+ buildClientBundle,
21
+ buildVendorBundle,
22
+ VENDOR_BUNDLE_NAME,
23
+ VENDOR_BUNDLE_URL
24
+ } from './compiler/client-bundler';
25
+ export {
26
+ type MachineContract,
27
+ machineContract,
28
+ renderContractJson,
29
+ renderContractMarkdown
30
+ } from './compiler/contract';
31
+ export {
32
+ type ColumnDefinition,
33
+ type DatabaseCatalog,
34
+ generateDatabaseSchemaCatalog,
35
+ mapSqlTypeToTs,
36
+ parseDdlToCatalog,
37
+ type TableDefinition,
38
+ toPascalCase
39
+ } from './compiler/db-schema-generator';
40
+ export { type ParsedField, parseFields } from './compiler/fields-parser';
41
+ export {
42
+ analyzeImpact,
43
+ type ImpactAnalysisReport,
44
+ type ImpactedSlice,
45
+ type ImpactReason
46
+ } from './compiler/impact-analyzer';
47
+ export {
48
+ type BidirectionalDdl,
49
+ type MigrationReport,
50
+ type MigrationResult,
51
+ parseBidirectionalDdl,
52
+ type RollbackOptions,
53
+ type RollbackReport,
54
+ type RollbackResult,
55
+ rollbackSliceMigrations,
56
+ runSliceMigrations
57
+ } from './compiler/migration-runner';
58
+ export {
59
+ ORACLE_DIR_NAME,
60
+ type OracleCaseResult,
61
+ type OracleErrorCode,
62
+ type OracleReport,
63
+ type OracleSliceResult,
64
+ oracleWrapperSource,
65
+ parseOracleJunit,
66
+ runSliceOracles
67
+ } from './compiler/oracle-runner';
68
+ export { type ScaffoldError, type ScaffoldErrorCode, scaffoldCrud, scaffoldSlice } from './compiler/scaffolder';
69
+ export { orderSlicesByDag, parseTableDependencies } from './compiler/schema-dag';
70
+ export {
71
+ checkSchemaDrift,
72
+ type MissingColumnInfo,
73
+ type MissingTableInfo,
74
+ type SchemaDriftReport
75
+ } from './compiler/schema-drift';
76
+ export {
77
+ findSliceFiles,
78
+ resolveSlicesDir,
79
+ SLICE_EXTENSION,
80
+ type SlicesDirError,
81
+ type SlicesDirErrorCode,
82
+ type SlicesResolution
83
+ } from './compiler/slice-discovery';
84
+ export {
85
+ artifactDirectory,
86
+ type SplitArtifact,
87
+ type SplitDiagnostic,
88
+ type SplitResult,
89
+ type SplitVerification,
90
+ splitSlice,
91
+ verifySplit,
92
+ writeSplitArtifacts
93
+ } from './compiler/slice-splitter';
94
+ export { buildStandalone, type StandaloneBuildResult } from './compiler/standalone-builder';
95
+ export type { SliceOracle, SliceOracleCase } from './core/oracle';
96
+ export {
97
+ clearSession,
98
+ currentRoles,
99
+ DEFAULT_SESSION_MAX_AGE_SECONDS,
100
+ ROLES_COOKIE,
101
+ SESSION_COOKIE,
102
+ sessionCookie,
103
+ storeSession
104
+ } from './core/session-cookie';
105
+ // 5. Model Context Protocol (MCP) Server
106
+ export { SynapseMcpServer } from './mcp/server';
107
+ export * from './runtime/discovery-rules';
108
+ // 4. Runtime, Queue & Zero-Wiring HTTP Server
109
+ export {
110
+ EventHub,
111
+ type EventListener,
112
+ getEventHub,
113
+ resetEventHub,
114
+ type UnsubscribeFn
115
+ } from './runtime/event-hub';
116
+ export {
117
+ PostgresEventHub,
118
+ type PostgresEventHubOptions
119
+ } from './runtime/postgres-event-hub';
120
+ export { type JobRecord, QueueEngine } from './runtime/queue-engine';
121
+ export {
122
+ type RateLimitOptions,
123
+ type RateLimitResult,
124
+ TokenBucketRateLimiter
125
+ } from './runtime/rate-limiter';
126
+ export {
127
+ type DiscoveredSlice,
128
+ type SliceLoadError,
129
+ type SliceLoaderContext,
130
+ type SliceMetadata,
131
+ SynapseServer
132
+ } from './runtime/server';
133
+ export { fc };
@@ -0,0 +1,553 @@
1
+ /**
2
+ * SynapseJS - Native Model Context Protocol (MCP) Server
3
+ *
4
+ * Exposes SynapseJS machine capabilities (repo-map, db-schema, diagnostics,
5
+ * split verification, PBT, migrations, scaffolding, authoring contract)
6
+ * directly to AI Agents (Cursor, Claude Code, Windsurf, Antigravity) via JSON-RPC 2.0 over stdio.
7
+ */
8
+
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ import * as readline from 'readline';
12
+ import { runMachineVerifications } from '../compiler/agent-diagnostic-json';
13
+ import { machineContract } from '../compiler/contract';
14
+ import { analyzeImpact } from '../compiler/impact-analyzer';
15
+ import { rollbackSliceMigrations, runSliceMigrations } from '../compiler/migration-runner';
16
+ import { runSliceOracles } from '../compiler/oracle-runner';
17
+ import { type SliceTemplate, scaffoldCrud, scaffoldSlice } from '../compiler/scaffolder';
18
+ import { checkSchemaDrift } from '../compiler/schema-drift';
19
+ import { findSliceFiles, resolveSlicesDir } from '../compiler/slice-discovery';
20
+ import { artifactDirectory, splitSlice, verifySplit, writeSplitArtifacts } from '../compiler/slice-splitter';
21
+
22
+ interface JsonRpcRequest {
23
+ jsonrpc: string;
24
+ id?: string | number | null;
25
+ method: string;
26
+ // biome-ignore lint/suspicious/noExplicitAny: JSON-RPC parameter boundary
27
+ params?: any;
28
+ }
29
+
30
+ export class SynapseMcpServer {
31
+ private root: string;
32
+
33
+ constructor(root: string = process.cwd()) {
34
+ this.root = root;
35
+ }
36
+
37
+ start() {
38
+ const rl = readline.createInterface({
39
+ input: process.stdin,
40
+ output: process.stdout,
41
+ terminal: false
42
+ });
43
+
44
+ rl.on('line', async (line) => {
45
+ const trimmed = line.trim();
46
+ if (!trimmed) return;
47
+
48
+ try {
49
+ const request: JsonRpcRequest = JSON.parse(trimmed);
50
+ const response = await this.handleRequest(request);
51
+ if (response) {
52
+ process.stdout.write(`${JSON.stringify(response)}\n`);
53
+ }
54
+ // biome-ignore lint/suspicious/noExplicitAny: error message catch
55
+ } catch (err: any) {
56
+ process.stdout.write(
57
+ `${JSON.stringify({
58
+ jsonrpc: '2.0',
59
+ id: null,
60
+ error: { code: -32700, message: `Parse error: ${err.message}` }
61
+ })}\n`
62
+ );
63
+ }
64
+ });
65
+ }
66
+
67
+ // biome-ignore lint/suspicious/noExplicitAny: JSON-RPC response boundary
68
+ public async handleRequest(req: JsonRpcRequest): Promise<any> {
69
+ const { id, method, params } = req;
70
+
71
+ switch (method) {
72
+ case 'initialize': {
73
+ return {
74
+ jsonrpc: '2.0',
75
+ id,
76
+ result: {
77
+ protocolVersion: '2024-11-05',
78
+ capabilities: {
79
+ tools: {}
80
+ },
81
+ serverInfo: {
82
+ name: 'synapse-mcp',
83
+ version: '1.1.0'
84
+ }
85
+ }
86
+ };
87
+ }
88
+
89
+ case 'notifications/initialized': {
90
+ return null;
91
+ }
92
+
93
+ case 'tools/list': {
94
+ return {
95
+ jsonrpc: '2.0',
96
+ id,
97
+ result: {
98
+ tools: [
99
+ {
100
+ name: 'synapse_get_repo_map',
101
+ description:
102
+ 'Get compressed codebase skeleton map (.codebase/repo-map.d.ts) for AI context (<3000 tokens)',
103
+ inputSchema: { type: 'object', properties: {} }
104
+ },
105
+ {
106
+ name: 'synapse_get_db_schema',
107
+ description:
108
+ 'Get the centralized database schema catalog (.codebase/db-schema.d.ts) for AI context and type-safe relational queries',
109
+ inputSchema: { type: 'object', properties: {} }
110
+ },
111
+ {
112
+ name: 'synapse_check',
113
+ description:
114
+ 'Run machine-centric compiler diagnostics, returning exact JSON coordinates (file, line, col, message)',
115
+ inputSchema: {
116
+ type: 'object',
117
+ properties: {
118
+ targetFile: { type: 'string', description: 'Optional specific file to check' }
119
+ }
120
+ }
121
+ },
122
+ {
123
+ name: 'synapse_split',
124
+ description:
125
+ 'Run slice splitter and leak verification gates to enforce server/client isolation and zero leakage',
126
+ inputSchema: {
127
+ type: 'object',
128
+ properties: {
129
+ targetSlice: { type: 'string', description: 'Optional specific slice name to split' }
130
+ }
131
+ }
132
+ },
133
+ {
134
+ name: 'synapse_run_pbt',
135
+ description: 'Execute Fast-Check Property-Based Testing (PBT) invariant test suite across all slices',
136
+ inputSchema: { type: 'object', properties: {} }
137
+ },
138
+ {
139
+ name: 'synapse_scaffold_slice',
140
+ description:
141
+ 'Scaffold a new fullstack atomic vertical slice with TypeBox, Result, Action, React UI, and PBT oracles',
142
+ inputSchema: {
143
+ type: 'object',
144
+ required: ['domain', 'name'],
145
+ properties: {
146
+ domain: { type: 'string', description: 'Domain name (e.g. billing, customers, orders)' },
147
+ name: { type: 'string', description: 'Slice name in kebab-case (e.g. cancel-subscription)' },
148
+ template: {
149
+ type: 'string',
150
+ enum: ['create', 'list', 'update', 'delete', 'login', 'oauth-github', 'crud'],
151
+ description: 'Optional slice template shape (default: create)'
152
+ },
153
+ fields: {
154
+ type: 'string',
155
+ description:
156
+ 'Optional fields grammar, e.g. "name:string,email:string,status:enum(ACTIVE|INACTIVE),price:number"'
157
+ }
158
+ }
159
+ }
160
+ },
161
+ {
162
+ name: 'synapse_contract',
163
+ description:
164
+ 'Return the machine contract: slice exports and suffixes, Result and HTTP semantics, session rules, addressing, SSR behavior and the gates to run',
165
+ inputSchema: { type: 'object', properties: {} }
166
+ },
167
+ {
168
+ name: 'synapse_migrate',
169
+ description:
170
+ 'Auto-discover and apply sliceSchema DDL declarations across slices into the active database',
171
+ inputSchema: { type: 'object', properties: {} }
172
+ },
173
+ {
174
+ name: 'synapse_check_db_drift',
175
+ description:
176
+ 'Inspects live database catalog against sliceSchema DDL contracts, identifying missing tables, missing columns, and orphan tables',
177
+ inputSchema: { type: 'object', properties: {} }
178
+ },
179
+ {
180
+ name: 'synapse_diff_impact',
181
+ description:
182
+ 'Analyzes cross-slice dependencies (Foreign Keys, shared module imports, and table references) to report all slices impacted by a file or table change',
183
+ inputSchema: {
184
+ type: 'object',
185
+ required: ['target'],
186
+ properties: {
187
+ target: {
188
+ type: 'string',
189
+ description: 'Slice file path, slice name, shared module path, or table name'
190
+ }
191
+ }
192
+ }
193
+ },
194
+ {
195
+ name: 'synapse_rollback',
196
+ description: 'Roll back applied sliceSchema migrations by executing their -- down: statements',
197
+ inputSchema: {
198
+ type: 'object',
199
+ properties: {
200
+ targetSlice: { type: 'string', description: 'Optional target slice to rollback' },
201
+ steps: { type: 'number', description: 'Number of recent migrations to rollback (default: 1)' }
202
+ }
203
+ }
204
+ }
205
+ ]
206
+ }
207
+ };
208
+ }
209
+
210
+ case 'tools/call': {
211
+ const toolName = params?.name;
212
+ const args = params?.arguments || {};
213
+
214
+ let contentText = '';
215
+
216
+ try {
217
+ if (toolName === 'synapse_get_repo_map') {
218
+ const repoMapPath = path.join(this.root, '.codebase/repo-map.d.ts');
219
+
220
+ if (!fs.existsSync(repoMapPath)) {
221
+ return {
222
+ jsonrpc: '2.0',
223
+ id,
224
+ result: {
225
+ isError: true,
226
+ content: [
227
+ {
228
+ type: 'text',
229
+ text: JSON.stringify(
230
+ {
231
+ status: 'FAIL',
232
+ code: 'REPO_MAP_MISSING',
233
+ message: `repo-map.d.ts não encontrado. Gere com 'synapse skeleton'.`,
234
+ repoMapPath
235
+ },
236
+ null,
237
+ 2
238
+ )
239
+ }
240
+ ]
241
+ }
242
+ };
243
+ }
244
+
245
+ const content = fs.readFileSync(repoMapPath, 'utf-8');
246
+ contentText = JSON.stringify(
247
+ { status: 'PASS', repoMapPath: path.relative(this.root, repoMapPath), repoMap: content },
248
+ null,
249
+ 2
250
+ );
251
+ } else if (toolName === 'synapse_get_db_schema') {
252
+ const schemaPath = path.join(this.root, '.codebase/db-schema.d.ts');
253
+
254
+ if (!fs.existsSync(schemaPath)) {
255
+ return {
256
+ jsonrpc: '2.0',
257
+ id,
258
+ result: {
259
+ isError: true,
260
+ content: [
261
+ {
262
+ type: 'text',
263
+ text: JSON.stringify(
264
+ {
265
+ status: 'FAIL',
266
+ code: 'DB_SCHEMA_MISSING',
267
+ message: `db-schema.d.ts não encontrado. Gere com 'synapse skeleton'.`,
268
+ schemaPath
269
+ },
270
+ null,
271
+ 2
272
+ )
273
+ }
274
+ ]
275
+ }
276
+ };
277
+ }
278
+
279
+ const content = fs.readFileSync(schemaPath, 'utf-8');
280
+ contentText = JSON.stringify(
281
+ { status: 'PASS', schemaPath: path.relative(this.root, schemaPath), schema: content },
282
+ null,
283
+ 2
284
+ );
285
+ } else if (toolName === 'synapse_check') {
286
+ const report = runMachineVerifications(this.root, args.targetFile);
287
+ contentText = JSON.stringify(report, null, 2);
288
+ } else if (toolName === 'synapse_split') {
289
+ const resolution = resolveSlicesDir(this.root);
290
+ if (!resolution.ok) {
291
+ return {
292
+ jsonrpc: '2.0',
293
+ id,
294
+ result: {
295
+ isError: true,
296
+ content: [
297
+ {
298
+ type: 'text',
299
+ text: JSON.stringify(
300
+ {
301
+ status: 'FAIL',
302
+ operation: 'SLICE_SPLIT',
303
+ code: resolution.error.code,
304
+ message: resolution.error.message,
305
+ candidates: resolution.error.candidates
306
+ },
307
+ null,
308
+ 2
309
+ )
310
+ }
311
+ ]
312
+ }
313
+ };
314
+ }
315
+
316
+ let sliceFiles = findSliceFiles(resolution.value.slicesDir);
317
+ if (args.targetSlice) {
318
+ sliceFiles = sliceFiles.filter((f) => path.basename(f, '.slice.tsx') === args.targetSlice);
319
+ }
320
+
321
+ const slices = [];
322
+ let failed = false;
323
+
324
+ for (const file of sliceFiles) {
325
+ const split = splitSlice(file, this.root);
326
+
327
+ if (!split.ok) {
328
+ failed = true;
329
+ slices.push({
330
+ slice: path.basename(file, '.slice.tsx'),
331
+ status: 'FAIL',
332
+ code: split.error.code,
333
+ message: split.error.message
334
+ });
335
+ continue;
336
+ }
337
+
338
+ const outDir = artifactDirectory(this.root, split.value.sliceName);
339
+ const written = writeSplitArtifacts(split.value, outDir);
340
+ const verification = verifySplit(split.value, outDir);
341
+
342
+ if (verification.status === 'FAIL') {
343
+ failed = true;
344
+ }
345
+
346
+ slices.push({
347
+ slice: split.value.sliceName,
348
+ status: verification.status,
349
+ outDir: path.relative(this.root, outDir),
350
+ artifacts: written.map((target) => path.relative(this.root, target)),
351
+ diagnostics: verification.diagnostics,
352
+ leaks: verification.leaks
353
+ });
354
+ }
355
+
356
+ const splitStatus = failed || slices.length === 0 ? 'FAIL' : 'PASS';
357
+ contentText = JSON.stringify(
358
+ {
359
+ status: splitStatus,
360
+ operation: 'SLICE_SPLIT',
361
+ slicesDir: path.relative(this.root, resolution.value.slicesDir),
362
+ totalProcessed: slices.length,
363
+ slices
364
+ },
365
+ null,
366
+ 2
367
+ );
368
+ } else if (toolName === 'synapse_run_pbt') {
369
+ const report = await runSliceOracles(this.root);
370
+
371
+ if (
372
+ report.status === 'FAIL' &&
373
+ (report.code === 'NO_SLICES_DIR' || report.code === 'AMBIGUOUS_SLICES_DIR')
374
+ ) {
375
+ return {
376
+ jsonrpc: '2.0',
377
+ id,
378
+ result: {
379
+ isError: true,
380
+ content: [{ type: 'text', text: JSON.stringify(report, null, 2) }]
381
+ }
382
+ };
383
+ }
384
+
385
+ contentText = JSON.stringify(report, null, 2);
386
+ } else if (toolName === 'synapse_scaffold_slice') {
387
+ if (args.template === 'crud') {
388
+ const crud = scaffoldCrud(args.domain, args.name, this.root, args.fields);
389
+
390
+ if (!crud.ok) {
391
+ return {
392
+ jsonrpc: '2.0',
393
+ id,
394
+ result: {
395
+ isError: true,
396
+ content: [
397
+ {
398
+ type: 'text',
399
+ text: JSON.stringify(
400
+ {
401
+ status: 'FAIL',
402
+ code: crud.error.code,
403
+ message: crud.error.message,
404
+ candidates: crud.error.candidates
405
+ },
406
+ null,
407
+ 2
408
+ )
409
+ }
410
+ ]
411
+ }
412
+ };
413
+ }
414
+
415
+ contentText = JSON.stringify(
416
+ {
417
+ status: 'PASS',
418
+ operation: 'SCAFFOLD_CRUD',
419
+ domain: args.domain,
420
+ resource: args.name,
421
+ createdPaths: crud.value.map((file) => path.relative(this.root, file))
422
+ },
423
+ null,
424
+ 2
425
+ );
426
+ } else {
427
+ const created = scaffoldSlice(
428
+ args.domain,
429
+ args.name,
430
+ this.root,
431
+ (args.template || 'create') as SliceTemplate,
432
+ args.fields
433
+ );
434
+
435
+ if (!created.ok) {
436
+ return {
437
+ jsonrpc: '2.0',
438
+ id,
439
+ result: {
440
+ isError: true,
441
+ content: [
442
+ {
443
+ type: 'text',
444
+ text: JSON.stringify(
445
+ {
446
+ status: 'FAIL',
447
+ code: created.error.code,
448
+ message: created.error.message,
449
+ candidates: created.error.candidates
450
+ },
451
+ null,
452
+ 2
453
+ )
454
+ }
455
+ ]
456
+ }
457
+ };
458
+ }
459
+
460
+ contentText = JSON.stringify(
461
+ { status: 'PASS', createdPath: path.relative(this.root, created.value) },
462
+ null,
463
+ 2
464
+ );
465
+ }
466
+ } else if (toolName === 'synapse_contract') {
467
+ contentText = JSON.stringify(machineContract(), null, 2);
468
+ } else if (toolName === 'synapse_migrate') {
469
+ const report = await runSliceMigrations(this.root);
470
+ contentText = JSON.stringify(report, null, 2);
471
+ } else if (toolName === 'synapse_check_db_drift') {
472
+ const report = await checkSchemaDrift(this.root);
473
+ contentText = JSON.stringify(report, null, 2);
474
+ } else if (toolName === 'synapse_diff_impact') {
475
+ if (!args.target) {
476
+ return {
477
+ jsonrpc: '2.0',
478
+ id,
479
+ result: {
480
+ isError: true,
481
+ content: [
482
+ {
483
+ type: 'text',
484
+ text: JSON.stringify(
485
+ {
486
+ status: 'FAIL',
487
+ code: 'MISSING_TARGET',
488
+ message: 'Argumento target obrigatório'
489
+ },
490
+ null,
491
+ 2
492
+ )
493
+ }
494
+ ]
495
+ }
496
+ };
497
+ }
498
+ const report = analyzeImpact(args.target, this.root);
499
+ contentText = JSON.stringify(report, null, 2);
500
+ } else if (toolName === 'synapse_rollback') {
501
+ const report = await rollbackSliceMigrations(this.root, undefined, {
502
+ targetSlice: args.targetSlice,
503
+ steps: args.steps
504
+ });
505
+ contentText = JSON.stringify(report, null, 2);
506
+ } else {
507
+ return {
508
+ jsonrpc: '2.0',
509
+ id,
510
+ error: { code: -32601, message: `Unknown tool: ${toolName}` }
511
+ };
512
+ }
513
+
514
+ return {
515
+ jsonrpc: '2.0',
516
+ id,
517
+ result: {
518
+ content: [
519
+ {
520
+ type: 'text',
521
+ text: contentText
522
+ }
523
+ ]
524
+ }
525
+ };
526
+ } catch (err: unknown) {
527
+ const message = err instanceof Error ? err.message : String(err);
528
+ return {
529
+ jsonrpc: '2.0',
530
+ id,
531
+ result: {
532
+ isError: true,
533
+ content: [
534
+ {
535
+ type: 'text',
536
+ text: JSON.stringify({ status: 'ERROR', error: message }, null, 2)
537
+ }
538
+ ]
539
+ }
540
+ };
541
+ }
542
+ }
543
+
544
+ default: {
545
+ return {
546
+ jsonrpc: '2.0',
547
+ id,
548
+ error: { code: -32601, message: `Method not found: ${method}` }
549
+ };
550
+ }
551
+ }
552
+ }
553
+ }