@meldocio/mcp-stdio-proxy 1.0.22 → 1.0.24
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/bin/cli.js +33 -1088
- package/bin/meldoc-mcp-proxy.js +134 -1264
- package/lib/cli/commands.js +277 -0
- package/lib/cli/formatters.js +137 -0
- package/lib/core/constants.js +98 -0
- package/lib/http/client.js +61 -0
- package/lib/http/error-handler.js +195 -0
- package/lib/install/config-manager.js +203 -0
- package/lib/install/config-paths.js +198 -0
- package/lib/install/installers.js +328 -0
- package/lib/install/templates.js +266 -0
- package/lib/mcp/handlers.js +185 -0
- package/lib/mcp/tools-call.js +179 -0
- package/lib/protocol/error-codes.js +143 -0
- package/lib/protocol/json-rpc.js +183 -0
- package/lib/protocol/tools-schema.js +239 -0
- package/package.json +1 -1
- package/lib/constants.js +0 -31
- /package/lib/{auth.js → core/auth.js} +0 -0
- /package/lib/{config.js → core/config.js} +0 -0
- /package/lib/{credentials.js → core/credentials.js} +0 -0
- /package/lib/{device-flow.js → core/device-flow.js} +0 -0
- /package/lib/{logger.js → core/logger.js} +0 -0
- /package/lib/{workspace.js → core/workspace.js} +0 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles all CLI commands for auth, config, and installation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { interactiveLogin } = require('../core/device-flow');
|
|
8
|
+
const { deleteCredentials } = require('../core/credentials');
|
|
9
|
+
const { getAuthStatus, getAccessToken } = require('../core/auth');
|
|
10
|
+
const { setWorkspaceAlias, getWorkspaceAlias } = require('../core/config');
|
|
11
|
+
const { getApiUrl, getAppUrl } = require('../core/constants');
|
|
12
|
+
const { createInstaller } = require('../install/installers');
|
|
13
|
+
const axios = require('axios');
|
|
14
|
+
const https = require('https');
|
|
15
|
+
const chalk = require('chalk');
|
|
16
|
+
const logger = require('../core/logger');
|
|
17
|
+
|
|
18
|
+
const API_URL = getApiUrl();
|
|
19
|
+
const APP_URL = getAppUrl();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Authentication Commands
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Handle auth login command
|
|
27
|
+
*/
|
|
28
|
+
async function handleAuthLogin() {
|
|
29
|
+
try {
|
|
30
|
+
await interactiveLogin({
|
|
31
|
+
autoOpen: true,
|
|
32
|
+
showQR: false,
|
|
33
|
+
timeout: 120000,
|
|
34
|
+
apiBaseUrl: API_URL,
|
|
35
|
+
appUrl: APP_URL
|
|
36
|
+
});
|
|
37
|
+
process.exit(0);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Handle auth status command
|
|
45
|
+
*/
|
|
46
|
+
async function handleAuthStatus() {
|
|
47
|
+
const status = await getAuthStatus();
|
|
48
|
+
if (!status || !status.authenticated) {
|
|
49
|
+
logger.error('Not authenticated');
|
|
50
|
+
console.log('\n' + logger.label('To authenticate, run:'));
|
|
51
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login') + '\n');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
logger.section('🔑 Authentication Status');
|
|
56
|
+
|
|
57
|
+
if (status.type === 'user_session' && status.user) {
|
|
58
|
+
logger.item('Email', logger.value(status.user.email));
|
|
59
|
+
if (status.expiresAt) {
|
|
60
|
+
logger.item('Token expires', logger.value(new Date(status.expiresAt).toLocaleString()));
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
logger.item('Type', logger.value(status.type));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log();
|
|
67
|
+
process.exit(0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Handle auth logout command
|
|
72
|
+
*/
|
|
73
|
+
async function handleAuthLogout() {
|
|
74
|
+
deleteCredentials();
|
|
75
|
+
logger.success('Logged out successfully');
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Configuration Commands
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Handle config set-workspace command
|
|
85
|
+
*/
|
|
86
|
+
function handleConfigSetWorkspace(alias) {
|
|
87
|
+
if (!alias) {
|
|
88
|
+
logger.error('Workspace alias is required');
|
|
89
|
+
console.log('\n' + logger.label('Usage:'));
|
|
90
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy config set-workspace <alias>') + '\n');
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
setWorkspaceAlias(alias);
|
|
96
|
+
logger.success(`Workspace set to: ${logger.highlight(alias)}`);
|
|
97
|
+
process.exit(0);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
logger.error(`Failed to set workspace: ${error.message}`);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Handle config get-workspace command
|
|
106
|
+
*/
|
|
107
|
+
function handleConfigGetWorkspace() {
|
|
108
|
+
const alias = getWorkspaceAlias();
|
|
109
|
+
if (alias) {
|
|
110
|
+
console.log(logger.highlight(alias));
|
|
111
|
+
}
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Handle config list-workspaces command
|
|
117
|
+
*/
|
|
118
|
+
async function handleConfigListWorkspaces() {
|
|
119
|
+
try {
|
|
120
|
+
const tokenInfo = await getAccessToken();
|
|
121
|
+
if (!tokenInfo) {
|
|
122
|
+
logger.error('Not authenticated');
|
|
123
|
+
console.log('\n' + logger.label('To authenticate, run:'));
|
|
124
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login') + '\n');
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Call MCP tool meldoc.list_workspaces via POST /mcp/v1/rpc
|
|
129
|
+
const response = await axios.post(`${API_URL}/mcp/v1/rpc`, {
|
|
130
|
+
jsonrpc: '2.0',
|
|
131
|
+
id: 1,
|
|
132
|
+
method: 'tools/call',
|
|
133
|
+
params: {
|
|
134
|
+
name: 'meldoc.list_workspaces',
|
|
135
|
+
arguments: {}
|
|
136
|
+
}
|
|
137
|
+
}, {
|
|
138
|
+
headers: {
|
|
139
|
+
'Authorization': `Bearer ${tokenInfo.token}`,
|
|
140
|
+
'Content-Type': 'application/json'
|
|
141
|
+
},
|
|
142
|
+
timeout: 10000,
|
|
143
|
+
httpsAgent: new https.Agent({ keepAlive: true })
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
if (response.data.error) {
|
|
147
|
+
logger.error(`Error: ${response.data.error.message}`);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const workspaces = response.data.result?.workspaces || [];
|
|
152
|
+
if (workspaces.length === 0) {
|
|
153
|
+
logger.info('No workspaces available');
|
|
154
|
+
process.exit(0);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
logger.section('📁 Available Workspaces');
|
|
158
|
+
for (const ws of workspaces) {
|
|
159
|
+
const role = ws.role || 'member';
|
|
160
|
+
const roleColor = role === 'owner' ? chalk.red : role === 'admin' ? chalk.yellow : chalk.gray;
|
|
161
|
+
logger.item(
|
|
162
|
+
`${logger.highlight(ws.alias)} ${chalk.gray('(' + ws.name + ')')}`,
|
|
163
|
+
roleColor(`[${role}]`)
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
console.log();
|
|
167
|
+
|
|
168
|
+
process.exit(0);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
if (error.response?.data?.error) {
|
|
171
|
+
const errorData = error.response.data.error;
|
|
172
|
+
if (errorData.code === 'AUTH_REQUIRED' || errorData.data?.code === 'AUTH_REQUIRED') {
|
|
173
|
+
logger.error('Not authenticated');
|
|
174
|
+
console.log('\n' + logger.label('To authenticate, run:'));
|
|
175
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login') + '\n');
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
logger.error(`Error: ${errorData.message || error.message}`);
|
|
179
|
+
} else {
|
|
180
|
+
logger.error(`Error: ${error.message}`);
|
|
181
|
+
}
|
|
182
|
+
process.exit(1);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Installation Commands
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Handle install command - automatically configure MCP client
|
|
192
|
+
*/
|
|
193
|
+
function handleInstall(consumer, isLocal) {
|
|
194
|
+
if (isLocal) {
|
|
195
|
+
const installer = createInstaller('local');
|
|
196
|
+
const result = installer.install();
|
|
197
|
+
process.exit(result.result === 'error' ? 1 : 0);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const consumerLower = (consumer || 'claude-desktop').toLowerCase();
|
|
202
|
+
let client, scope;
|
|
203
|
+
|
|
204
|
+
switch (consumerLower) {
|
|
205
|
+
case 'claude-desktop':
|
|
206
|
+
case 'claude':
|
|
207
|
+
client = 'claude-desktop';
|
|
208
|
+
scope = 'project';
|
|
209
|
+
break;
|
|
210
|
+
case 'cursor':
|
|
211
|
+
client = 'cursor';
|
|
212
|
+
scope = 'project';
|
|
213
|
+
break;
|
|
214
|
+
case 'cursor-global':
|
|
215
|
+
client = 'cursor';
|
|
216
|
+
scope = 'global';
|
|
217
|
+
break;
|
|
218
|
+
case 'claude-code':
|
|
219
|
+
client = 'claude-code';
|
|
220
|
+
scope = 'project';
|
|
221
|
+
break;
|
|
222
|
+
case 'claude-code-user':
|
|
223
|
+
client = 'claude-code';
|
|
224
|
+
scope = 'user';
|
|
225
|
+
break;
|
|
226
|
+
case 'claude-code-local':
|
|
227
|
+
client = 'claude-code';
|
|
228
|
+
scope = 'local';
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
logger.error(`Unknown consumer: ${consumer}`);
|
|
232
|
+
console.log();
|
|
233
|
+
logger.info('Supported consumers:');
|
|
234
|
+
console.log(' ' + logger.highlight('claude-desktop') + ' (or claude) - Claude Desktop');
|
|
235
|
+
console.log(' ' + logger.highlight('cursor') + ' - Cursor IDE (project-specific)');
|
|
236
|
+
console.log(' ' + logger.highlight('cursor-global') + ' - Cursor IDE (global)');
|
|
237
|
+
console.log(' ' + logger.highlight('claude-code') + ' - Claude Code (project scope)');
|
|
238
|
+
console.log(' ' + logger.highlight('claude-code-user') + ' - Claude Code (user scope)');
|
|
239
|
+
console.log(' ' + logger.highlight('claude-code-local') + ' - Claude Code (local scope)');
|
|
240
|
+
console.log();
|
|
241
|
+
logger.info('Or use ' + logger.highlight('--local') + ' flag to create local mcp.json');
|
|
242
|
+
console.log();
|
|
243
|
+
process.exit(1);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Use new unified installer
|
|
248
|
+
const installer = createInstaller(client, scope);
|
|
249
|
+
const result = installer.install();
|
|
250
|
+
process.exit(result.result === 'error' ? 1 : 0);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Handle uninstall command - remove Meldoc MCP configuration
|
|
255
|
+
*/
|
|
256
|
+
function handleUninstall() {
|
|
257
|
+
// Default to Claude Desktop for backward compatibility
|
|
258
|
+
const installer = createInstaller('claude-desktop');
|
|
259
|
+
const result = installer.uninstall();
|
|
260
|
+
process.exit(result.result === 'error' ? 1 : 0);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
module.exports = {
|
|
264
|
+
// Auth commands
|
|
265
|
+
handleAuthLogin,
|
|
266
|
+
handleAuthStatus,
|
|
267
|
+
handleAuthLogout,
|
|
268
|
+
|
|
269
|
+
// Config commands
|
|
270
|
+
handleConfigSetWorkspace,
|
|
271
|
+
handleConfigGetWorkspace,
|
|
272
|
+
handleConfigListWorkspaces,
|
|
273
|
+
|
|
274
|
+
// Installation commands
|
|
275
|
+
handleInstall,
|
|
276
|
+
handleUninstall
|
|
277
|
+
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Output Formatters
|
|
3
|
+
*
|
|
4
|
+
* Handles help text, usage hints, and other formatted CLI output.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const logger = require('../core/logger');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Show detailed help message with all commands and examples
|
|
11
|
+
*/
|
|
12
|
+
function handleHelp() {
|
|
13
|
+
console.log('\n' + logger.section('📖 Meldoc MCP CLI Help'));
|
|
14
|
+
console.log();
|
|
15
|
+
|
|
16
|
+
console.log(logger.label('Available Commands:'));
|
|
17
|
+
console.log();
|
|
18
|
+
|
|
19
|
+
console.log(' ' + logger.highlight('auth login'));
|
|
20
|
+
console.log(' Authenticate with Meldoc using device flow');
|
|
21
|
+
console.log();
|
|
22
|
+
|
|
23
|
+
console.log(' ' + logger.highlight('auth status'));
|
|
24
|
+
console.log(' Check authentication status');
|
|
25
|
+
console.log();
|
|
26
|
+
|
|
27
|
+
console.log(' ' + logger.highlight('auth logout'));
|
|
28
|
+
console.log(' Log out and clear credentials');
|
|
29
|
+
console.log();
|
|
30
|
+
|
|
31
|
+
console.log(' ' + logger.highlight('config set-workspace <alias>'));
|
|
32
|
+
console.log(' Set the active workspace alias');
|
|
33
|
+
console.log();
|
|
34
|
+
|
|
35
|
+
console.log(' ' + logger.highlight('config get-workspace'));
|
|
36
|
+
console.log(' Get the current workspace alias');
|
|
37
|
+
console.log();
|
|
38
|
+
|
|
39
|
+
console.log(' ' + logger.highlight('config list-workspaces'));
|
|
40
|
+
console.log(' List all available workspaces');
|
|
41
|
+
console.log();
|
|
42
|
+
|
|
43
|
+
console.log(' ' + logger.highlight('install [consumer] [--local]'));
|
|
44
|
+
console.log(' Automatically configure MCP client for Meldoc MCP');
|
|
45
|
+
console.log(' Consumers: claude-desktop (default), cursor, cursor-global, claude-code');
|
|
46
|
+
console.log(' Use --local flag to create local mcp.json file');
|
|
47
|
+
console.log();
|
|
48
|
+
|
|
49
|
+
console.log(' ' + logger.highlight('uninstall'));
|
|
50
|
+
console.log(' Remove Meldoc MCP configuration from Claude Desktop');
|
|
51
|
+
console.log();
|
|
52
|
+
|
|
53
|
+
console.log(' ' + logger.highlight('help'));
|
|
54
|
+
console.log(' Show this help message');
|
|
55
|
+
console.log();
|
|
56
|
+
|
|
57
|
+
console.log(logger.label('Examples:'));
|
|
58
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install'));
|
|
59
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install claude-desktop'));
|
|
60
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install cursor'));
|
|
61
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install claude-code'));
|
|
62
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy install --local'));
|
|
63
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy uninstall'));
|
|
64
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth login'));
|
|
65
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy config set-workspace my-workspace'));
|
|
66
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy config list-workspaces'));
|
|
67
|
+
console.log();
|
|
68
|
+
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Show brief usage hints when no arguments provided
|
|
74
|
+
*/
|
|
75
|
+
function showUsageHints() {
|
|
76
|
+
console.log('\n' + logger.section('🔧 Meldoc MCP CLI'));
|
|
77
|
+
console.log();
|
|
78
|
+
console.log(logger.label('Available commands:'));
|
|
79
|
+
console.log(' ' + logger.highlight('auth login') + ' - Authenticate with Meldoc');
|
|
80
|
+
console.log(' ' + logger.highlight('auth status') + ' - Check authentication status');
|
|
81
|
+
console.log(' ' + logger.highlight('auth logout') + ' - Log out');
|
|
82
|
+
console.log(' ' + logger.highlight('config set-workspace') + ' - Set workspace alias');
|
|
83
|
+
console.log(' ' + logger.highlight('config get-workspace') + ' - Get current workspace');
|
|
84
|
+
console.log(' ' + logger.highlight('config list-workspaces') + ' - List workspaces');
|
|
85
|
+
console.log(' ' + logger.highlight('install [consumer]') + ' - Configure MCP client');
|
|
86
|
+
console.log(' ' + logger.highlight('uninstall') + ' - Remove configuration');
|
|
87
|
+
console.log(' ' + logger.highlight('help') + ' - Show detailed help');
|
|
88
|
+
console.log();
|
|
89
|
+
console.log(logger.label('For more information, run:'));
|
|
90
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy help') + '\n');
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Show unknown command error with available commands
|
|
96
|
+
*/
|
|
97
|
+
function showUnknownCommandError(command) {
|
|
98
|
+
logger.error(`Unknown command: ${command}`);
|
|
99
|
+
console.log('\n' + logger.label('Available commands:'));
|
|
100
|
+
console.log(' ' + logger.highlight('install') + ' - Configure Claude Desktop');
|
|
101
|
+
console.log(' ' + logger.highlight('uninstall') + ' - Remove configuration');
|
|
102
|
+
console.log(' ' + logger.highlight('auth') + ' <cmd> - Authentication commands');
|
|
103
|
+
console.log(' ' + logger.highlight('config') + ' <cmd> - Configuration commands');
|
|
104
|
+
console.log(' ' + logger.highlight('help') + ' - Show help');
|
|
105
|
+
console.log();
|
|
106
|
+
console.log(logger.label('Run') + ' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy help') + ' ' + logger.label('for more information'));
|
|
107
|
+
console.log();
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Show unknown auth subcommand error
|
|
113
|
+
*/
|
|
114
|
+
function showUnknownAuthCommandError(subcommand) {
|
|
115
|
+
logger.error(`Unknown auth command: ${subcommand}`);
|
|
116
|
+
console.log('\n' + logger.label('Usage:'));
|
|
117
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy auth <login|status|logout>') + '\n');
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Show unknown config subcommand error
|
|
123
|
+
*/
|
|
124
|
+
function showUnknownConfigCommandError(subcommand) {
|
|
125
|
+
logger.error(`Unknown config command: ${subcommand}`);
|
|
126
|
+
console.log('\n' + logger.label('Usage:'));
|
|
127
|
+
console.log(' ' + logger.highlight('npx @meldocio/mcp-stdio-proxy config <set-workspace|get-workspace|list-workspaces>') + '\n');
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = {
|
|
132
|
+
handleHelp,
|
|
133
|
+
showUsageHints,
|
|
134
|
+
showUnknownCommandError,
|
|
135
|
+
showUnknownAuthCommandError,
|
|
136
|
+
showUnknownConfigCommandError
|
|
137
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default configuration constants
|
|
3
|
+
* Production values used when environment variables are not set
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Production API URL
|
|
7
|
+
const DEFAULT_API_URL = 'https://api.meldoc.io';
|
|
8
|
+
|
|
9
|
+
// Production App URL (frontend)
|
|
10
|
+
const DEFAULT_APP_URL = 'https://app.meldoc.io';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Request timeout configuration
|
|
14
|
+
* 25 seconds - less than Claude Desktop's 30s timeout to allow for proper error handling
|
|
15
|
+
*/
|
|
16
|
+
const REQUEST_TIMEOUT = 25000;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Log levels for severity filtering
|
|
20
|
+
*/
|
|
21
|
+
const LOG_LEVELS = {
|
|
22
|
+
ERROR: 0,
|
|
23
|
+
WARN: 1,
|
|
24
|
+
INFO: 2,
|
|
25
|
+
DEBUG: 3
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Default log level names mapped to numeric values
|
|
30
|
+
*/
|
|
31
|
+
const LOG_LEVEL_NAMES = {
|
|
32
|
+
0: 'ERROR',
|
|
33
|
+
1: 'WARN',
|
|
34
|
+
2: 'INFO',
|
|
35
|
+
3: 'DEBUG'
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* MCP protocol version
|
|
40
|
+
*/
|
|
41
|
+
const MCP_PROTOCOL_VERSION = '2025-06-18';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Server capability flags
|
|
45
|
+
*/
|
|
46
|
+
const SERVER_CAPABILITIES = {
|
|
47
|
+
TOOLS: true,
|
|
48
|
+
PROMPTS: false,
|
|
49
|
+
RESOURCES: false,
|
|
50
|
+
LOGGING: false
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get API URL from environment or use production default
|
|
55
|
+
*/
|
|
56
|
+
function getApiUrl() {
|
|
57
|
+
return process.env.MELDOC_API_URL || DEFAULT_API_URL;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get App URL from environment or use production default
|
|
62
|
+
*/
|
|
63
|
+
function getAppUrl() {
|
|
64
|
+
return process.env.MELDOC_APP_URL || DEFAULT_APP_URL;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get log level from environment variable
|
|
69
|
+
* @param {string} [level] - Log level string (ERROR, WARN, INFO, DEBUG)
|
|
70
|
+
* @returns {number} Numeric log level
|
|
71
|
+
*/
|
|
72
|
+
function getLogLevel(level) {
|
|
73
|
+
const upper = (level || '').toUpperCase();
|
|
74
|
+
return LOG_LEVELS[upper] !== undefined ? LOG_LEVELS[upper] : LOG_LEVELS.ERROR;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get log level name from numeric value
|
|
79
|
+
* @param {number} level - Numeric log level
|
|
80
|
+
* @returns {string} Log level name
|
|
81
|
+
*/
|
|
82
|
+
function getLogLevelName(level) {
|
|
83
|
+
return LOG_LEVEL_NAMES[level] || 'UNKNOWN';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = {
|
|
87
|
+
DEFAULT_API_URL,
|
|
88
|
+
DEFAULT_APP_URL,
|
|
89
|
+
REQUEST_TIMEOUT,
|
|
90
|
+
LOG_LEVELS,
|
|
91
|
+
LOG_LEVEL_NAMES,
|
|
92
|
+
MCP_PROTOCOL_VERSION,
|
|
93
|
+
SERVER_CAPABILITIES,
|
|
94
|
+
getApiUrl,
|
|
95
|
+
getAppUrl,
|
|
96
|
+
getLogLevel,
|
|
97
|
+
getLogLevelName
|
|
98
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Client for MCP Backend Communication
|
|
3
|
+
*
|
|
4
|
+
* Handles HTTP requests to the Meldoc API backend.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const axios = require('axios');
|
|
8
|
+
const https = require('https');
|
|
9
|
+
const { getApiUrl, REQUEST_TIMEOUT } = require('../core/constants');
|
|
10
|
+
const { getAccessToken } = require('../core/auth');
|
|
11
|
+
const { resolveWorkspaceAlias } = require('../core/workspace');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Make an authenticated JSON-RPC request to the backend
|
|
15
|
+
* @param {Object} request - JSON-RPC request object
|
|
16
|
+
* @returns {Promise<Object>} Response data
|
|
17
|
+
*/
|
|
18
|
+
async function makeBackendRequest(request) {
|
|
19
|
+
const apiUrl = getApiUrl();
|
|
20
|
+
const rpcEndpoint = `${apiUrl}/mcp/v1/rpc`;
|
|
21
|
+
|
|
22
|
+
// Get access token
|
|
23
|
+
const tokenInfo = await getAccessToken();
|
|
24
|
+
if (!tokenInfo) {
|
|
25
|
+
throw new Error('Not authenticated');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Ensure request has jsonrpc field
|
|
29
|
+
const requestWithJsonRpc = {
|
|
30
|
+
...request,
|
|
31
|
+
jsonrpc: request.jsonrpc || '2.0'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Resolve workspace if not provided
|
|
35
|
+
const workspaceAlias = await resolveWorkspaceAlias();
|
|
36
|
+
|
|
37
|
+
// Build headers
|
|
38
|
+
const headers = {
|
|
39
|
+
'Authorization': `Bearer ${tokenInfo.token}`,
|
|
40
|
+
'Content-Type': 'application/json'
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Add workspace header if available
|
|
44
|
+
if (workspaceAlias) {
|
|
45
|
+
headers['X-Workspace-Alias'] = workspaceAlias;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Make request
|
|
49
|
+
const response = await axios.post(rpcEndpoint, requestWithJsonRpc, {
|
|
50
|
+
headers,
|
|
51
|
+
timeout: REQUEST_TIMEOUT,
|
|
52
|
+
httpsAgent: new https.Agent({ keepAlive: true }),
|
|
53
|
+
validateStatus: () => true // Accept all status codes
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return response;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
makeBackendRequest
|
|
61
|
+
};
|