@dsiloed/silo-link 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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +350 -0
  3. package/dist/api/dsiloed-client.d.ts +32 -0
  4. package/dist/api/dsiloed-client.d.ts.map +1 -0
  5. package/dist/api/dsiloed-client.js +240 -0
  6. package/dist/api/dsiloed-client.js.map +1 -0
  7. package/dist/cable/action-cable-client.d.ts +28 -0
  8. package/dist/cable/action-cable-client.d.ts.map +1 -0
  9. package/dist/cable/action-cable-client.js +194 -0
  10. package/dist/cable/action-cable-client.js.map +1 -0
  11. package/dist/cable/subscription-manager.d.ts +29 -0
  12. package/dist/cable/subscription-manager.d.ts.map +1 -0
  13. package/dist/cable/subscription-manager.js +125 -0
  14. package/dist/cable/subscription-manager.js.map +1 -0
  15. package/dist/cli/commands.d.ts +4 -0
  16. package/dist/cli/commands.d.ts.map +1 -0
  17. package/dist/cli/commands.js +144 -0
  18. package/dist/cli/commands.js.map +1 -0
  19. package/dist/cli/daemon.d.ts +5 -0
  20. package/dist/cli/daemon.d.ts.map +1 -0
  21. package/dist/cli/daemon.js +35 -0
  22. package/dist/cli/daemon.js.map +1 -0
  23. package/dist/config/config-manager.d.ts +7 -0
  24. package/dist/config/config-manager.d.ts.map +1 -0
  25. package/dist/config/config-manager.js +76 -0
  26. package/dist/config/config-manager.js.map +1 -0
  27. package/dist/config/jwt-generator.d.ts +15 -0
  28. package/dist/config/jwt-generator.d.ts.map +1 -0
  29. package/dist/config/jwt-generator.js +54 -0
  30. package/dist/config/jwt-generator.js.map +1 -0
  31. package/dist/core/bridge.d.ts +37 -0
  32. package/dist/core/bridge.d.ts.map +1 -0
  33. package/dist/core/bridge.js +247 -0
  34. package/dist/core/bridge.js.map +1 -0
  35. package/dist/core/claude-launcher.d.ts +78 -0
  36. package/dist/core/claude-launcher.d.ts.map +1 -0
  37. package/dist/core/claude-launcher.js +352 -0
  38. package/dist/core/claude-launcher.js.map +1 -0
  39. package/dist/core/message-queue.d.ts +47 -0
  40. package/dist/core/message-queue.d.ts.map +1 -0
  41. package/dist/core/message-queue.js +139 -0
  42. package/dist/core/message-queue.js.map +1 -0
  43. package/dist/core/session-manager.d.ts +24 -0
  44. package/dist/core/session-manager.d.ts.map +1 -0
  45. package/dist/core/session-manager.js +111 -0
  46. package/dist/core/session-manager.js.map +1 -0
  47. package/dist/index.d.ts +3 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +4 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/mcp/server.d.ts +27 -0
  52. package/dist/mcp/server.d.ts.map +1 -0
  53. package/dist/mcp/server.js +109 -0
  54. package/dist/mcp/server.js.map +1 -0
  55. package/dist/mcp/tools/register-tools.d.ts +19 -0
  56. package/dist/mcp/tools/register-tools.d.ts.map +1 -0
  57. package/dist/mcp/tools/register-tools.js +385 -0
  58. package/dist/mcp/tools/register-tools.js.map +1 -0
  59. package/dist/types/index.d.ts +74 -0
  60. package/dist/types/index.d.ts.map +1 -0
  61. package/dist/types/index.js +2 -0
  62. package/dist/types/index.js.map +1 -0
  63. package/package.json +57 -0
@@ -0,0 +1,111 @@
1
+ const IDLE_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour
2
+ export class SessionManager {
3
+ sessions = new Map();
4
+ mcpToSession = new Map();
5
+ conversationToSession = new Map();
6
+ cleanupTimer = null;
7
+ onSessionCleaned;
8
+ constructor(onSessionCleaned) {
9
+ this.onSessionCleaned = onSessionCleaned;
10
+ this.cleanupTimer = setInterval(() => this.cleanupIdle(), 5 * 60 * 1000);
11
+ }
12
+ register(session) {
13
+ this.sessions.set(session.sessionId, session);
14
+ this.mcpToSession.set(session.mcpSessionId, session.sessionId);
15
+ this.conversationToSession.set(session.conversationId, session.sessionId);
16
+ }
17
+ unregister(sessionId) {
18
+ const session = this.sessions.get(sessionId);
19
+ if (session) {
20
+ this.mcpToSession.delete(session.mcpSessionId);
21
+ this.conversationToSession.delete(session.conversationId);
22
+ this.sessions.delete(sessionId);
23
+ }
24
+ return session;
25
+ }
26
+ get(sessionId) {
27
+ return this.sessions.get(sessionId);
28
+ }
29
+ getByMcpSessionId(mcpSessionId) {
30
+ const sessionId = this.mcpToSession.get(mcpSessionId);
31
+ return sessionId ? this.sessions.get(sessionId) : undefined;
32
+ }
33
+ getByConversationId(conversationId) {
34
+ const sessionId = this.conversationToSession.get(conversationId);
35
+ return sessionId ? this.sessions.get(sessionId) : undefined;
36
+ }
37
+ getAll() {
38
+ return Array.from(this.sessions.values());
39
+ }
40
+ touchActivity(sessionId) {
41
+ const session = this.sessions.get(sessionId);
42
+ if (session) {
43
+ session.lastActivity = new Date();
44
+ }
45
+ }
46
+ /**
47
+ * Checks that the 3 internal maps are consistent with each other.
48
+ * Returns true if everything is in sync, false otherwise.
49
+ */
50
+ validate() {
51
+ const errors = [];
52
+ // Every entry in mcpToSession should point to an existing session,
53
+ // and that session's mcpSessionId should match the key.
54
+ for (const [mcpSessionId, sessionId] of this.mcpToSession) {
55
+ const session = this.sessions.get(sessionId);
56
+ if (!session) {
57
+ errors.push(`mcpToSession has entry ${mcpSessionId} -> ${sessionId}, but session does not exist`);
58
+ }
59
+ else if (session.mcpSessionId !== mcpSessionId) {
60
+ errors.push(`mcpToSession maps ${mcpSessionId} -> ${sessionId}, but session.mcpSessionId is ${session.mcpSessionId}`);
61
+ }
62
+ }
63
+ // Every entry in conversationToSession should point to an existing session,
64
+ // and that session's conversationId should match the key.
65
+ for (const [conversationId, sessionId] of this.conversationToSession) {
66
+ const session = this.sessions.get(sessionId);
67
+ if (!session) {
68
+ errors.push(`conversationToSession has entry ${conversationId} -> ${sessionId}, but session does not exist`);
69
+ }
70
+ else if (session.conversationId !== conversationId) {
71
+ errors.push(`conversationToSession maps ${conversationId} -> ${sessionId}, but session.conversationId is ${session.conversationId}`);
72
+ }
73
+ }
74
+ // Every session should have corresponding entries in both lookup maps.
75
+ for (const [sessionId, session] of this.sessions) {
76
+ if (this.mcpToSession.get(session.mcpSessionId) !== sessionId) {
77
+ errors.push(`session ${sessionId} has mcpSessionId ${session.mcpSessionId}, but mcpToSession does not map back to it`);
78
+ }
79
+ if (this.conversationToSession.get(session.conversationId) !== sessionId) {
80
+ errors.push(`session ${sessionId} has conversationId ${session.conversationId}, but conversationToSession does not map back to it`);
81
+ }
82
+ }
83
+ if (errors.length > 0) {
84
+ console.warn(`[SessionManager] validation failed (${errors.length} issue${errors.length > 1 ? 's' : ''}):\n - ${errors.join('\n - ')}`);
85
+ return false;
86
+ }
87
+ return true;
88
+ }
89
+ cleanupIdle() {
90
+ const now = Date.now();
91
+ for (const [id, session] of this.sessions) {
92
+ if (now - session.lastActivity.getTime() > IDLE_TIMEOUT_MS) {
93
+ const cleaned = this.unregister(id);
94
+ if (cleaned && this.onSessionCleaned) {
95
+ this.onSessionCleaned(cleaned);
96
+ }
97
+ }
98
+ }
99
+ this.validate();
100
+ }
101
+ destroy() {
102
+ if (this.cleanupTimer) {
103
+ clearInterval(this.cleanupTimer);
104
+ this.cleanupTimer = null;
105
+ }
106
+ this.sessions.clear();
107
+ this.mcpToSession.clear();
108
+ this.conversationToSession.clear();
109
+ }
110
+ }
111
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/core/session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { program } from './cli/commands.js';
3
+ program.parse(process.argv);
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { SessionManager } from '../core/session-manager.js';
2
+ import type { MessageQueue } from '../core/message-queue.js';
3
+ import type { DSiloedClient } from '../api/dsiloed-client.js';
4
+ import type { SubscriptionManager } from '../cable/subscription-manager.js';
5
+ import type { ActionCableClient } from '../cable/action-cable-client.js';
6
+ import type { SiloLinkConfig } from '../types/index.js';
7
+ interface McpServerDeps {
8
+ config: SiloLinkConfig;
9
+ sessionManager: SessionManager;
10
+ messageQueue: MessageQueue;
11
+ dsiloedClient: DSiloedClient;
12
+ subscriptionManager: SubscriptionManager;
13
+ cableClient: ActionCableClient;
14
+ }
15
+ export declare class SiloLinkMcpServer {
16
+ private app;
17
+ private server;
18
+ private transports;
19
+ private deps;
20
+ constructor(deps: McpServerDeps);
21
+ private createServerForSession;
22
+ private setupRoutes;
23
+ start(port: number): Promise<void>;
24
+ stop(): Promise<void>;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,UAAU,aAAa;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,aAAa,CAAC;IAC7B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,WAAW,EAAE,iBAAiB,CAAC;CAChC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,UAAU,CAAyD;IAC3E,OAAO,CAAC,IAAI,CAAgB;gBAEhB,IAAI,EAAE,aAAa;IAO/B,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,WAAW;IAoEnB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAe5B"}
@@ -0,0 +1,109 @@
1
+ import express from 'express';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
5
+ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
6
+ import { registerTools } from './tools/register-tools.js';
7
+ export class SiloLinkMcpServer {
8
+ app;
9
+ server = null;
10
+ transports = new Map();
11
+ deps;
12
+ constructor(deps) {
13
+ this.deps = deps;
14
+ this.app = express();
15
+ this.app.use(express.json());
16
+ this.setupRoutes();
17
+ }
18
+ createServerForSession(transport) {
19
+ const server = new McpServer({
20
+ name: 'silolink',
21
+ version: '0.1.0',
22
+ });
23
+ registerTools(server, transport, this.deps);
24
+ return server;
25
+ }
26
+ setupRoutes() {
27
+ // POST: client-to-server messages + initialization
28
+ this.app.post('/mcp', async (req, res) => {
29
+ const sessionId = req.headers['mcp-session-id'];
30
+ if (sessionId && this.transports.has(sessionId)) {
31
+ const transport = this.transports.get(sessionId);
32
+ await transport.handleRequest(req, res, req.body);
33
+ return;
34
+ }
35
+ if (!sessionId && isInitializeRequest(req.body)) {
36
+ const transport = new StreamableHTTPServerTransport({
37
+ sessionIdGenerator: () => randomUUID(),
38
+ onsessioninitialized: (newSessionId) => {
39
+ this.transports.set(newSessionId, transport);
40
+ },
41
+ });
42
+ transport.onclose = () => {
43
+ if (transport.sessionId) {
44
+ this.transports.delete(transport.sessionId);
45
+ }
46
+ };
47
+ const server = this.createServerForSession(transport);
48
+ await server.connect(transport);
49
+ await transport.handleRequest(req, res, req.body);
50
+ return;
51
+ }
52
+ res.status(400).json({
53
+ jsonrpc: '2.0',
54
+ error: { code: -32000, message: 'Bad Request: No valid session ID' },
55
+ id: null,
56
+ });
57
+ });
58
+ // GET: SSE stream for server-to-client notifications
59
+ this.app.get('/mcp', async (req, res) => {
60
+ const sessionId = req.headers['mcp-session-id'];
61
+ if (!sessionId || !this.transports.has(sessionId)) {
62
+ res.status(400).send('Invalid or missing session ID');
63
+ return;
64
+ }
65
+ await this.transports.get(sessionId).handleRequest(req, res);
66
+ });
67
+ // DELETE: terminate session
68
+ this.app.delete('/mcp', async (req, res) => {
69
+ const sessionId = req.headers['mcp-session-id'];
70
+ if (!sessionId || !this.transports.has(sessionId)) {
71
+ res.status(400).send('Invalid or missing session ID');
72
+ return;
73
+ }
74
+ await this.transports.get(sessionId).handleRequest(req, res);
75
+ });
76
+ // Health check
77
+ this.app.get('/health', (_req, res) => {
78
+ res.json({
79
+ status: 'ok',
80
+ sessions: this.deps.sessionManager.getAll().length,
81
+ cable: this.deps.cableClient.getState(),
82
+ });
83
+ });
84
+ }
85
+ start(port) {
86
+ return new Promise((resolve) => {
87
+ this.server = this.app.listen(port, () => {
88
+ console.log(`MCP server listening on http://localhost:${port}/mcp`);
89
+ resolve();
90
+ });
91
+ });
92
+ }
93
+ async stop() {
94
+ // Close all transports
95
+ for (const transport of this.transports.values()) {
96
+ await transport.close();
97
+ }
98
+ this.transports.clear();
99
+ return new Promise((resolve) => {
100
+ if (this.server) {
101
+ this.server.close(() => resolve());
102
+ }
103
+ else {
104
+ resolve();
105
+ }
106
+ });
107
+ }
108
+ }
109
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
+ import type { SessionManager } from '../../core/session-manager.js';
4
+ import type { MessageQueue } from '../../core/message-queue.js';
5
+ import type { DSiloedClient } from '../../api/dsiloed-client.js';
6
+ import type { SubscriptionManager } from '../../cable/subscription-manager.js';
7
+ import type { ActionCableClient } from '../../cable/action-cable-client.js';
8
+ import type { SiloLinkConfig } from '../../types/index.js';
9
+ interface ToolDeps {
10
+ config: SiloLinkConfig;
11
+ sessionManager: SessionManager;
12
+ messageQueue: MessageQueue;
13
+ dsiloedClient: DSiloedClient;
14
+ subscriptionManager: SubscriptionManager;
15
+ cableClient: ActionCableClient;
16
+ }
17
+ export declare function registerTools(server: McpServer, transport: StreamableHTTPServerTransport, deps: ToolDeps): void;
18
+ export {};
19
+ //# sourceMappingURL=register-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-tools.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/register-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACxG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAW,MAAM,sBAAsB,CAAC;AAGpE,UAAU,QAAQ;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,aAAa,CAAC;IAC7B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,WAAW,EAAE,iBAAiB,CAAC;CAChC;AAqBD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,6BAA6B,EACxC,IAAI,EAAE,QAAQ,GACb,IAAI,CAscN"}