@natomalabs/natoma-mcp-gateway 1.0.3 → 1.0.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.
@@ -1,131 +0,0 @@
1
- // nms-gateway.ts
2
- import EventSource from "eventsource";
3
- import { BaseMCPGateway } from "./base.js";
4
- // NMS Gateway (Non-Enterprise) - EventSource based
5
- export class NMSGateway extends BaseMCPGateway {
6
- eventSource = null;
7
- sessionId = null;
8
- sseUrl;
9
- messageUrl;
10
- constructor(config) {
11
- // Set isEnterprise to false for NMS Gateway
12
- super({ ...config, isEnterprise: false });
13
- const slug = config?.slug;
14
- this.sseUrl = slug ? `${this.baseUrl}/${slug}` : `${this.baseUrl}`;
15
- this.messageUrl = slug
16
- ? `${this.baseUrl}/${slug}/message`
17
- : `${this.baseUrl}/message`;
18
- // Debug the URLs
19
- console.error(`[NMSGateway] Base URL: ${this.baseUrl}`);
20
- console.error(`[NMSGateway] SSE URL: ${this.sseUrl}`);
21
- console.error(`[NMSGateway] Message URL: ${this.messageUrl}`);
22
- }
23
- async connect() {
24
- if (this.eventSource) {
25
- console.error("Closing existing connection");
26
- this.eventSource.close();
27
- }
28
- return new Promise((resolve, reject) => {
29
- const headers = {
30
- Accept: "text/event-stream",
31
- };
32
- if (this.apiKey) {
33
- headers["Authorization"] = `Bearer ${this.apiKey}`;
34
- }
35
- this.eventSource = new EventSource(this.sseUrl, { headers });
36
- this.eventSource.onopen = () => {
37
- console.error("--- SSE backend connected");
38
- this.reconnectAttempts = 0;
39
- resolve();
40
- };
41
- this.eventSource.onerror = (error) => {
42
- console.error(`--- SSE backend error: ${error?.message}`);
43
- this.handleConnectionError(error);
44
- reject(error);
45
- };
46
- this.setupEventListeners();
47
- });
48
- }
49
- setupEventListeners() {
50
- if (!this.eventSource)
51
- return;
52
- this.eventSource.addEventListener("endpoint", (event) => {
53
- const match = event.data.match(/sessionId=([^&]+)/);
54
- if (match) {
55
- this.sessionId = match[1];
56
- this.isReady = true;
57
- console.error(`Session established: ${this.sessionId}`);
58
- this.processQueuedMessages();
59
- }
60
- });
61
- this.eventSource.addEventListener("message", (event) => {
62
- try {
63
- console.error(`<-- ${event.data}`);
64
- console.log(event.data);
65
- }
66
- catch (error) {
67
- console.error(`Error handling message: ${error}`);
68
- }
69
- });
70
- }
71
- async handleConnectionError(error) {
72
- console.error(`Connection error: ${error.message}`);
73
- if (this.eventSource?.readyState === EventSource.CLOSED) {
74
- console.error("EventSource connection closed");
75
- await this.reconnect();
76
- }
77
- }
78
- async reconnect() {
79
- if (this.reconnectAttempts >= this.maxReconnectAttempts) {
80
- console.error(`Max reconnection attempts (${this.maxReconnectAttempts}) reached, exiting...`);
81
- process.exit(1);
82
- }
83
- this.reconnectAttempts++;
84
- this.isReady = false;
85
- try {
86
- await new Promise((resolve) => setTimeout(resolve, this.reconnectDelay));
87
- await this.connect();
88
- }
89
- catch (error) {
90
- console.error(`Reconnection failed: ${error}`);
91
- }
92
- }
93
- async processMessage(input) {
94
- if (!this.isReady || !this.sessionId) {
95
- this.messageQueue.push(input);
96
- return;
97
- }
98
- const message = input.toString().trim();
99
- console.error(`--> ${message}`);
100
- try {
101
- const url = `${this.messageUrl}?sessionId=${this.sessionId}`;
102
- const headers = {
103
- "Content-Type": "application/json",
104
- };
105
- if (this.apiKey) {
106
- headers["Authorization"] = `Bearer ${this.apiKey}`;
107
- }
108
- const response = await fetch(url, {
109
- method: "POST",
110
- headers,
111
- body: message,
112
- });
113
- if (!response.ok) {
114
- if (response.status === 503) {
115
- await this.reconnect();
116
- }
117
- else {
118
- console.error(`Error from server: ${response.status} ${response.statusText}`);
119
- }
120
- }
121
- }
122
- catch (error) {
123
- console.error(`Request error: ${error}`);
124
- }
125
- }
126
- cleanup() {
127
- if (this.eventSource) {
128
- this.eventSource.close();
129
- }
130
- }
131
- }
package/build/setup.js DELETED
@@ -1,186 +0,0 @@
1
- // setup.ts
2
- import fs from "fs";
3
- import path from "path";
4
- import os from "os";
5
- import chalk from "chalk";
6
- export const setupCommand = {
7
- command: "setup <url>",
8
- describe: "Setup command for Natoma MCP Gateway integration",
9
- builder: (yargs) => {
10
- return yargs
11
- .positional("url", {
12
- type: "string",
13
- describe: "The Natoma MCP URL to use",
14
- demandOption: true,
15
- })
16
- .option("client", {
17
- type: "string",
18
- describe: "Client to use (claude, windsurf, cursor)",
19
- default: "claude",
20
- choices: ["claude", "windsurf", "cursor"],
21
- })
22
- .option("apiKey", {
23
- type: "string",
24
- describe: "API key for authentication",
25
- demandOption: true,
26
- });
27
- },
28
- handler: async (argv) => {
29
- const { url, client, apiKey } = argv;
30
- try {
31
- console.log(chalk.cyan("šŸ“ Configuration Details:"));
32
- console.log(` URL: ${chalk.green(url)}`);
33
- console.log(` Client: ${chalk.green(client)}`);
34
- if (apiKey) {
35
- console.log(` API Key: ${chalk.green("****" + apiKey.slice(-4))}`);
36
- }
37
- console.log("");
38
- console.log(chalk.cyan("šŸ’¾ Saving configurations..."));
39
- saveMcpConfig(url, client, apiKey);
40
- console.log(chalk.cyan(`\nšŸš€ All done! Please restart ${client} for changes to take effect\n`));
41
- }
42
- catch (error) {
43
- console.log(chalk.red("\nāŒ Error occurred while setting up Natoma MCP:"));
44
- console.log(chalk.red(` ${error.message}`));
45
- console.log(chalk.yellow("\nPlease try again or contact support if the issue persists.\n"));
46
- }
47
- },
48
- };
49
- function saveMcpConfig(url, clientType, apiKey) {
50
- // Create config object for the gateway
51
- const config = {
52
- command: "npx",
53
- args: ["@natomalabs/natoma-mcp-gateway@latest", "start", "--url", url],
54
- env: {
55
- npm_config_yes: "true",
56
- },
57
- };
58
- // If API key is provided, add it to the environment variables
59
- if (apiKey) {
60
- config.env["NATOMA_MCP_API_KEY"] = apiKey;
61
- // Also add it to the args so it's passed to the start command
62
- config.args.push("--apiKey", apiKey);
63
- }
64
- // Extract installation ID from URL for Cursor
65
- const urlParts = url.split("/");
66
- const installationId = urlParts[urlParts.length - 1];
67
- const sseConfig = {
68
- url: url,
69
- apiKey: apiKey,
70
- slug: installationId,
71
- };
72
- const homeDir = os.homedir();
73
- // Define platform-specific paths
74
- const platformPaths = {
75
- win32: {
76
- baseDir: process.env.APPDATA || path.join(homeDir, "AppData", "Roaming"),
77
- vscodePath: path.join("Code", "User", "globalStorage"),
78
- },
79
- darwin: {
80
- baseDir: path.join(homeDir, "Library", "Application Support"),
81
- vscodePath: path.join("Code", "User", "globalStorage"),
82
- },
83
- linux: {
84
- baseDir: process.env.XDG_CONFIG_HOME || path.join(homeDir, ".config"),
85
- vscodePath: path.join("Code/User/globalStorage"),
86
- },
87
- };
88
- const platform = process.platform;
89
- // Check if platform is supported
90
- if (!platformPaths[platform]) {
91
- console.log(chalk.yellow(`\nāš ļø Platform ${platform} is not supported.`));
92
- return;
93
- }
94
- const { baseDir } = platformPaths[platform];
95
- // Define client-specific paths
96
- const clientPaths = {
97
- claude: {
98
- configDir: path.join(baseDir, "Claude"),
99
- configPath: path.join(baseDir, "Claude", "claude_desktop_config.json"),
100
- },
101
- windsurf: {
102
- configDir: path.join(homeDir, ".codeium", "windsurf"),
103
- configPath: path.join(homeDir, ".codeium", "windsurf", "mcp_config.json"),
104
- },
105
- cursor: {
106
- configDir: path.join(homeDir, ".cursor"),
107
- configPath: path.join(homeDir, ".cursor", "mcp.json"),
108
- },
109
- };
110
- if (!clientPaths[clientType]) {
111
- console.log(chalk.yellow(`\nāš ļø Client ${clientType} is not supported.`));
112
- return;
113
- }
114
- const { configDir, configPath } = clientPaths[clientType];
115
- // Create config directory if it doesn't exist
116
- if (!fs.existsSync(configDir)) {
117
- fs.mkdirSync(configDir, { recursive: true });
118
- }
119
- // Handle client-specific configuration format
120
- if (clientType === "claude") {
121
- let claudeConfig = { mcpServers: {} };
122
- if (fs.existsSync(configPath)) {
123
- try {
124
- claudeConfig = JSON.parse(fs.readFileSync(configPath, "utf8"));
125
- }
126
- catch (error) {
127
- console.log(chalk.yellow("āš ļø Creating new config file"));
128
- }
129
- }
130
- // Ensure mcpServers exists
131
- if (!claudeConfig.mcpServers)
132
- claudeConfig.mcpServers = {};
133
- // Update only the mcpServers entry
134
- claudeConfig.mcpServers[url] = config;
135
- fs.writeFileSync(configPath, JSON.stringify(claudeConfig, null, 2));
136
- console.log(chalk.green(`āœ… Configuration saved to: ${configPath}`));
137
- }
138
- else if (clientType === "windsurf") {
139
- let windsurfConfig = { mcpServers: {} };
140
- if (fs.existsSync(configPath)) {
141
- try {
142
- windsurfConfig = JSON.parse(fs.readFileSync(configPath, "utf8"));
143
- }
144
- catch (error) {
145
- console.log(chalk.yellow("āš ļø Creating new config file"));
146
- }
147
- }
148
- // Ensure mcpServers exists
149
- if (!windsurfConfig.mcpServers)
150
- windsurfConfig.mcpServers = {};
151
- // Now TypeScript knows mcpServers exists
152
- windsurfConfig.mcpServers[url] = config;
153
- fs.writeFileSync(configPath, JSON.stringify(windsurfConfig, null, 2));
154
- console.log(chalk.green(`āœ… Configuration saved to: ${configPath}`));
155
- }
156
- else if (clientType === "cursor") {
157
- let cursorConfig = { mcpServers: {} };
158
- if (fs.existsSync(configPath)) {
159
- try {
160
- cursorConfig = JSON.parse(fs.readFileSync(configPath, "utf8"));
161
- }
162
- catch (error) {
163
- console.log(chalk.yellow("āš ļø Creating new config file"));
164
- }
165
- }
166
- // Ensure mcpServers exists
167
- if (!cursorConfig.mcpServers)
168
- cursorConfig.mcpServers = {};
169
- // Remove existing config if it exists
170
- if (cursorConfig.mcpServers[url]) {
171
- delete cursorConfig.mcpServers[url];
172
- }
173
- try {
174
- // Create a unique key for Cursor's configuration
175
- const newKey = `natoma_${installationId}`;
176
- cursorConfig.mcpServers[newKey] = sseConfig;
177
- fs.writeFileSync(configPath, JSON.stringify(cursorConfig, null, 2));
178
- console.log(chalk.green(`āœ… Configuration saved to: ${configPath}`));
179
- }
180
- catch (error) {
181
- console.log(chalk.red("āŒ Error occurred while setting up MCP:"));
182
- console.log(chalk.red(` ${error.message}`));
183
- console.log(chalk.yellow("\nPlease try again or contact support if the issue persists.\n"));
184
- }
185
- }
186
- }