@1mcp/agent 0.4.0 → 0.8.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.
- package/README.md +57 -2
- package/build/capabilities/capabilityManager.d.ts +34 -0
- package/build/capabilities/capabilityManager.d.ts.map +1 -0
- package/build/capabilities/capabilityManager.js +13 -5
- package/build/capabilities/capabilityManager.js.map +1 -0
- package/build/client.d.ts +25 -0
- package/build/client.d.ts.map +1 -0
- package/build/client.js +3 -10
- package/build/client.js.map +1 -0
- package/build/clients/clientManager.d.ts +40 -0
- package/build/clients/clientManager.d.ts.map +1 -0
- package/build/clients/clientManager.js +45 -21
- package/build/clients/clientManager.js.map +1 -0
- package/build/config/configManager.d.ts +54 -0
- package/build/config/configManager.d.ts.map +1 -0
- package/build/config/configManager.js +1 -0
- package/build/config/configManager.js.map +1 -0
- package/build/config/transportConfig.d.ts +7 -0
- package/build/config/transportConfig.d.ts.map +1 -0
- package/build/config/transportConfig.js +1 -0
- package/build/config/transportConfig.js.map +1 -0
- package/build/constants.d.ts +43 -0
- package/build/constants.d.ts.map +1 -0
- package/build/constants.js +19 -4
- package/build/constants.js.map +1 -0
- package/build/handlers/notificationHandlers.d.ts +14 -0
- package/build/handlers/notificationHandlers.d.ts.map +1 -0
- package/build/handlers/notificationHandlers.js +1 -0
- package/build/handlers/notificationHandlers.js.map +1 -0
- package/build/handlers/requestHandlers.d.ts +10 -0
- package/build/handlers/requestHandlers.d.ts.map +1 -0
- package/build/handlers/requestHandlers.js +45 -30
- package/build/handlers/requestHandlers.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +6 -1
- package/build/index.js.map +1 -0
- package/build/logger/logger.d.ts +13 -0
- package/build/logger/logger.d.ts.map +1 -0
- package/build/logger/logger.js +7 -33
- package/build/logger/logger.js.map +1 -0
- package/build/middleware/loggingMiddleware.d.ts +6 -0
- package/build/middleware/loggingMiddleware.d.ts.map +1 -0
- package/build/middleware/loggingMiddleware.js +1 -0
- package/build/middleware/loggingMiddleware.js.map +1 -0
- package/build/server/expressServer.d.ts +10 -0
- package/build/server/expressServer.d.ts.map +1 -0
- package/build/server/expressServer.js +2 -11
- package/build/server/expressServer.js.map +1 -0
- package/build/server.d.ts +7 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +1 -0
- package/build/server.js.map +1 -0
- package/build/serverManager.d.ts +25 -0
- package/build/serverManager.d.ts.map +1 -0
- package/build/serverManager.js +4 -2
- package/build/serverManager.js.map +1 -0
- package/build/services/configReloadService.d.ts +37 -0
- package/build/services/configReloadService.d.ts.map +1 -0
- package/build/services/configReloadService.js +1 -0
- package/build/services/configReloadService.js.map +1 -0
- package/build/types.d.ts +129 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +1 -0
- package/build/types.js.map +1 -0
- package/build/utils/clientFiltering.d.ts +37 -0
- package/build/utils/clientFiltering.d.ts.map +1 -0
- package/build/utils/clientFiltering.js +73 -0
- package/build/utils/clientFiltering.js.map +1 -0
- package/build/utils/errorHandling.d.ts +62 -0
- package/build/utils/errorHandling.d.ts.map +1 -0
- package/build/utils/errorHandling.js +1 -0
- package/build/utils/errorHandling.js.map +1 -0
- package/build/utils/errorTypes.d.ts +25 -0
- package/build/utils/errorTypes.d.ts.map +1 -0
- package/build/utils/errorTypes.js +1 -0
- package/build/utils/errorTypes.js.map +1 -0
- package/package.json +28 -11
- package/build/config/configManager.test.js +0 -106
- package/build/logger/mcpTransport.js +0 -150
- package/build/serverManager.test.js +0 -158
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import Transport from 'winston-transport';
|
|
2
|
-
// Map Winston log levels to MCP log levels
|
|
3
|
-
const LOG_LEVEL_MAP = {
|
|
4
|
-
error: 'error',
|
|
5
|
-
warn: 'warning',
|
|
6
|
-
info: 'info',
|
|
7
|
-
verbose: 'debug',
|
|
8
|
-
debug: 'debug',
|
|
9
|
-
silly: 'debug',
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Winston transport for sending logs to MCP clients
|
|
13
|
-
*/
|
|
14
|
-
export class MCPTransport extends Transport {
|
|
15
|
-
server;
|
|
16
|
-
loggerName;
|
|
17
|
-
connected = false;
|
|
18
|
-
constructor(options) {
|
|
19
|
-
super(options);
|
|
20
|
-
this.server = options.server;
|
|
21
|
-
this.loggerName = options.loggerName || '1mcp';
|
|
22
|
-
// Set up connection status handlers
|
|
23
|
-
this.setupConnectionHandlers();
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Set up handlers for connection status changes
|
|
27
|
-
*/
|
|
28
|
-
setupConnectionHandlers() {
|
|
29
|
-
// Handle connection close
|
|
30
|
-
this.server.onclose = () => {
|
|
31
|
-
this.setConnected(false);
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Set the connection status of the transport
|
|
36
|
-
* @param connected Whether the server is connected
|
|
37
|
-
*/
|
|
38
|
-
setConnected(connected) {
|
|
39
|
-
const previousState = this.connected;
|
|
40
|
-
this.connected = connected;
|
|
41
|
-
// Log connection state changes
|
|
42
|
-
if (previousState !== connected) {
|
|
43
|
-
console.debug(`MCP Transport connection state changed to: ${connected ? 'connected' : 'disconnected'}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Send a log notification to the MCP client
|
|
48
|
-
* @param info The log info object
|
|
49
|
-
* @returns true if the notification was sent, false otherwise
|
|
50
|
-
*/
|
|
51
|
-
sendLogNotification(info) {
|
|
52
|
-
if (!this.server || !this.connected) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
// Map Winston log level to MCP log level
|
|
56
|
-
const level = LOG_LEVEL_MAP[info.level] || 'info';
|
|
57
|
-
const sanitizedData = this.sanitizeData(info);
|
|
58
|
-
// Extract message and metadata
|
|
59
|
-
const { message, level: _, ...meta } = sanitizedData;
|
|
60
|
-
// Create MCP logging notification
|
|
61
|
-
const notification = {
|
|
62
|
-
method: 'notifications/message',
|
|
63
|
-
params: {
|
|
64
|
-
level,
|
|
65
|
-
message: typeof message === 'string' ? message : JSON.stringify(message),
|
|
66
|
-
logger: this.loggerName,
|
|
67
|
-
data: Object.keys(meta).length > 0 ? meta : undefined,
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
// Send notification to MCP clients
|
|
71
|
-
try {
|
|
72
|
-
this.server.notification(notification);
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
console.error('Failed to send log notification to MCP client:', error);
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Sanitize log data to remove sensitive information
|
|
82
|
-
* @param data The data to sanitize
|
|
83
|
-
* @returns Sanitized data
|
|
84
|
-
*/
|
|
85
|
-
sanitizeData(data) {
|
|
86
|
-
if (typeof data !== 'object' || data === null) {
|
|
87
|
-
return data;
|
|
88
|
-
}
|
|
89
|
-
// List of potentially sensitive field names
|
|
90
|
-
const sensitiveFields = [
|
|
91
|
-
'password',
|
|
92
|
-
'token',
|
|
93
|
-
'secret',
|
|
94
|
-
'key',
|
|
95
|
-
'credential',
|
|
96
|
-
'auth',
|
|
97
|
-
'apiKey',
|
|
98
|
-
'api_key',
|
|
99
|
-
'accessToken',
|
|
100
|
-
'access_token',
|
|
101
|
-
'jwt',
|
|
102
|
-
'ssn',
|
|
103
|
-
'creditCard',
|
|
104
|
-
'credit_card',
|
|
105
|
-
'cvv',
|
|
106
|
-
'pin',
|
|
107
|
-
];
|
|
108
|
-
if (Array.isArray(data)) {
|
|
109
|
-
return data.map((item) => this.sanitizeData(item));
|
|
110
|
-
}
|
|
111
|
-
const sanitized = {};
|
|
112
|
-
for (const [key, value] of Object.entries(data)) {
|
|
113
|
-
// Check if this is a sensitive field
|
|
114
|
-
const isSensitive = sensitiveFields.some((field) => key.toLowerCase().includes(field.toLowerCase()));
|
|
115
|
-
if (isSensitive) {
|
|
116
|
-
sanitized[key] = '[REDACTED]';
|
|
117
|
-
}
|
|
118
|
-
else if (typeof value === 'object' && value !== null) {
|
|
119
|
-
sanitized[key] = this.sanitizeData(value);
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
sanitized[key] = value;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return sanitized;
|
|
126
|
-
}
|
|
127
|
-
log(info, callback) {
|
|
128
|
-
setImmediate(() => {
|
|
129
|
-
this.emit('logged', info);
|
|
130
|
-
});
|
|
131
|
-
// Only try to send if connected
|
|
132
|
-
if (this.connected) {
|
|
133
|
-
try {
|
|
134
|
-
this.sendLogNotification(info);
|
|
135
|
-
}
|
|
136
|
-
catch (_) {
|
|
137
|
-
// Ignore any errors during log sending
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// Always call the callback to prevent blocking
|
|
141
|
-
callback();
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Clean up resources when the transport is closed
|
|
145
|
-
*/
|
|
146
|
-
close() {
|
|
147
|
-
this.setConnected(false);
|
|
148
|
-
this.server.onclose = undefined;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
-
import { ServerManager } from './serverManager.js';
|
|
3
|
-
import logger from './logger/logger.js';
|
|
4
|
-
import configReloadService from './services/configReloadService.js';
|
|
5
|
-
import { setupCapabilities } from './capabilities/capabilityManager.js';
|
|
6
|
-
import { enhanceServerWithLogging } from './middleware/loggingMiddleware.js';
|
|
7
|
-
// Mock dependencies
|
|
8
|
-
jest.mock('@modelcontextprotocol/sdk/server/index.js', () => ({
|
|
9
|
-
Server: jest.fn(),
|
|
10
|
-
}));
|
|
11
|
-
jest.mock('@modelcontextprotocol/sdk/shared/transport.js', () => ({
|
|
12
|
-
Transport: jest.fn(),
|
|
13
|
-
}));
|
|
14
|
-
jest.mock('./logger/logger.js', () => {
|
|
15
|
-
const mockLogger = {
|
|
16
|
-
info: jest.fn(),
|
|
17
|
-
error: jest.fn(),
|
|
18
|
-
};
|
|
19
|
-
return {
|
|
20
|
-
__esModule: true,
|
|
21
|
-
default: mockLogger,
|
|
22
|
-
};
|
|
23
|
-
});
|
|
24
|
-
jest.mock('./services/configReloadService.js', () => ({
|
|
25
|
-
__esModule: true,
|
|
26
|
-
default: {
|
|
27
|
-
initialize: jest.fn(),
|
|
28
|
-
},
|
|
29
|
-
}));
|
|
30
|
-
jest.mock('./capabilities/capabilityManager.js', () => ({
|
|
31
|
-
setupCapabilities: jest.fn(),
|
|
32
|
-
}));
|
|
33
|
-
jest.mock('./middleware/loggingMiddleware.js', () => ({
|
|
34
|
-
enhanceServerWithLogging: jest.fn(),
|
|
35
|
-
}));
|
|
36
|
-
describe('ServerManager', () => {
|
|
37
|
-
let mockConfig;
|
|
38
|
-
let mockCapabilities;
|
|
39
|
-
let mockClients;
|
|
40
|
-
let mockTransports;
|
|
41
|
-
let mockTransport;
|
|
42
|
-
let mockServer;
|
|
43
|
-
beforeEach(() => {
|
|
44
|
-
// Reset all mocks
|
|
45
|
-
jest.clearAllMocks();
|
|
46
|
-
// Setup test data
|
|
47
|
-
mockConfig = { name: 'test-server', version: '1.0.0' };
|
|
48
|
-
mockCapabilities = { capabilities: { test: true } };
|
|
49
|
-
mockClients = {};
|
|
50
|
-
mockTransports = {};
|
|
51
|
-
mockTransport = {
|
|
52
|
-
// Add any required Transport properties here
|
|
53
|
-
};
|
|
54
|
-
mockServer = {
|
|
55
|
-
connect: jest.fn().mockResolvedValue(undefined),
|
|
56
|
-
transport: mockTransport,
|
|
57
|
-
};
|
|
58
|
-
// Setup mocks
|
|
59
|
-
Server.mockImplementation(() => mockServer);
|
|
60
|
-
setupCapabilities.mockResolvedValue(undefined);
|
|
61
|
-
enhanceServerWithLogging.mockReturnValue(undefined);
|
|
62
|
-
configReloadService.initialize.mockImplementation(() => undefined);
|
|
63
|
-
});
|
|
64
|
-
describe('getInstance', () => {
|
|
65
|
-
it('should create a singleton instance', () => {
|
|
66
|
-
const instance1 = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports);
|
|
67
|
-
const instance2 = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports);
|
|
68
|
-
expect(instance1).toBe(instance2);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
describe('connectTransport', () => {
|
|
72
|
-
let serverManager;
|
|
73
|
-
const sessionId = 'test-session';
|
|
74
|
-
const tags = ['tag1', 'tag2'];
|
|
75
|
-
beforeEach(() => {
|
|
76
|
-
serverManager = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports);
|
|
77
|
-
});
|
|
78
|
-
it('should successfully connect a transport', async () => {
|
|
79
|
-
await serverManager.connectTransport(mockTransport, sessionId, tags);
|
|
80
|
-
expect(Server).toHaveBeenCalledWith(mockConfig, mockCapabilities);
|
|
81
|
-
expect(enhanceServerWithLogging).toHaveBeenCalledWith(mockServer);
|
|
82
|
-
expect(setupCapabilities).toHaveBeenCalled();
|
|
83
|
-
expect(configReloadService.initialize).toHaveBeenCalled();
|
|
84
|
-
expect(mockServer.connect).toHaveBeenCalledWith(mockTransport);
|
|
85
|
-
expect(logger.info).toHaveBeenCalledWith(`Connected transport for session ${sessionId}`);
|
|
86
|
-
});
|
|
87
|
-
it('should handle connection errors', async () => {
|
|
88
|
-
const error = new Error('Connection failed');
|
|
89
|
-
mockServer.connect.mockRejectedValueOnce(error);
|
|
90
|
-
await expect(serverManager.connectTransport(mockTransport, sessionId, tags)).rejects.toThrow('Connection failed');
|
|
91
|
-
expect(logger.error).toHaveBeenCalled();
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
describe('disconnectTransport', () => {
|
|
95
|
-
let serverManager;
|
|
96
|
-
const sessionId = 'test-session';
|
|
97
|
-
beforeEach(() => {
|
|
98
|
-
serverManager = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports);
|
|
99
|
-
});
|
|
100
|
-
it('should successfully disconnect a transport', async () => {
|
|
101
|
-
await serverManager.connectTransport(mockTransport, sessionId);
|
|
102
|
-
jest.clearAllMocks(); // Clear the logs from connectTransport
|
|
103
|
-
serverManager.disconnectTransport(sessionId);
|
|
104
|
-
expect(logger.info).toHaveBeenCalledWith(`Disconnected transport for session ${sessionId}`);
|
|
105
|
-
});
|
|
106
|
-
it('should handle non-existent session gracefully', () => {
|
|
107
|
-
serverManager.disconnectTransport('non-existent');
|
|
108
|
-
expect(logger.info).not.toHaveBeenCalled();
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
describe('transport management methods', () => {
|
|
112
|
-
let serverManager;
|
|
113
|
-
const sessionId = 'test-session';
|
|
114
|
-
beforeEach(async () => {
|
|
115
|
-
serverManager = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports);
|
|
116
|
-
await serverManager.connectTransport(mockTransport, sessionId);
|
|
117
|
-
});
|
|
118
|
-
it('should get transport by session id', () => {
|
|
119
|
-
const transport = serverManager.getTransport(sessionId);
|
|
120
|
-
expect(transport).toBe(mockTransport);
|
|
121
|
-
});
|
|
122
|
-
it('should return undefined for non-existent session', () => {
|
|
123
|
-
const transport = serverManager.getTransport('non-existent');
|
|
124
|
-
expect(transport).toBeUndefined();
|
|
125
|
-
});
|
|
126
|
-
it('should get all transports', () => {
|
|
127
|
-
const transports = serverManager.getTransports();
|
|
128
|
-
expect(transports.size).toBe(1);
|
|
129
|
-
expect(transports.get(sessionId)).toBe(mockTransport);
|
|
130
|
-
});
|
|
131
|
-
it('should get client transports', () => {
|
|
132
|
-
const clientTransports = serverManager.getClientTransports();
|
|
133
|
-
expect(clientTransports).toEqual(mockTransports);
|
|
134
|
-
});
|
|
135
|
-
it('should get active transports count', () => {
|
|
136
|
-
expect(serverManager.getActiveTransportsCount()).toBe(1);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
describe('getServer', () => {
|
|
140
|
-
let serverManager;
|
|
141
|
-
const sessionId = 'test-session';
|
|
142
|
-
const tags = ['tag1', 'tag2'];
|
|
143
|
-
beforeEach(async () => {
|
|
144
|
-
serverManager = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports);
|
|
145
|
-
await serverManager.connectTransport(mockTransport, sessionId, tags);
|
|
146
|
-
});
|
|
147
|
-
it('should return server info for existing session', () => {
|
|
148
|
-
const serverInfo = serverManager.getServer(sessionId);
|
|
149
|
-
expect(serverInfo).toBeDefined();
|
|
150
|
-
expect(serverInfo?.server).toBe(mockServer);
|
|
151
|
-
expect(serverInfo?.tags).toEqual(tags);
|
|
152
|
-
});
|
|
153
|
-
it('should return undefined for non-existent session', () => {
|
|
154
|
-
const serverInfo = serverManager.getServer('non-existent');
|
|
155
|
-
expect(serverInfo).toBeUndefined();
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
});
|