@felan-ai/ext-mcp 0.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.
- package/LICENSE +24 -0
- package/NOTICE +16 -0
- package/README.md +60 -0
- package/dist/boundary.d.ts +24 -0
- package/dist/boundary.d.ts.map +1 -0
- package/dist/boundary.js +224 -0
- package/dist/boundary.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +129 -0
- package/dist/config.js.map +1 -0
- package/dist/contracts.d.ts +61 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +2 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +515 -0
- package/dist/index.js.map +1 -0
- package/dist/manager.d.ts +32 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +282 -0
- package/dist/manager.js.map +1 -0
- package/package.json +46 -0
package/dist/manager.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { Client, SdkHttpError, SSEClientTransport, StreamableHTTPClientTransport, UnauthorizedError, } from '@modelcontextprotocol/client';
|
|
2
|
+
const MAX_TOOL_PAGES = 100;
|
|
3
|
+
const MAX_TOOLS_PER_SERVER = 1_000;
|
|
4
|
+
export class McpAuthenticationRequiredError extends Error {
|
|
5
|
+
serverName;
|
|
6
|
+
constructor(serverName) {
|
|
7
|
+
super(`MCP server ${serverName} requires OAuth authentication`);
|
|
8
|
+
this.serverName = serverName;
|
|
9
|
+
this.name = 'McpAuthenticationRequiredError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class McpManager {
|
|
13
|
+
#servers;
|
|
14
|
+
#states = new Map();
|
|
15
|
+
#sessionSignal;
|
|
16
|
+
#oauth;
|
|
17
|
+
#connectionFactory;
|
|
18
|
+
#fetch;
|
|
19
|
+
#closed = false;
|
|
20
|
+
constructor(servers, oauth, sessionSignal, connectionFactory = connectMcpServer, fetchFn) {
|
|
21
|
+
this.#servers = new Map(servers.map((server) => [server.name, server]));
|
|
22
|
+
this.#oauth = oauth;
|
|
23
|
+
this.#sessionSignal = sessionSignal;
|
|
24
|
+
this.#connectionFactory = connectionFactory;
|
|
25
|
+
this.#fetch = fetchFn;
|
|
26
|
+
for (const server of servers) {
|
|
27
|
+
this.#states.set(server.name, {
|
|
28
|
+
status: 'disconnected',
|
|
29
|
+
generation: 0,
|
|
30
|
+
tools: [],
|
|
31
|
+
connection: undefined,
|
|
32
|
+
connecting: undefined,
|
|
33
|
+
connectController: undefined,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
server(name) {
|
|
38
|
+
const server = this.#servers.get(name);
|
|
39
|
+
if (!server)
|
|
40
|
+
throw new Error(`Unknown MCP server: ${name}`);
|
|
41
|
+
return server;
|
|
42
|
+
}
|
|
43
|
+
statuses() {
|
|
44
|
+
return [...this.#servers.keys()].map((server) => {
|
|
45
|
+
const state = this.#states.get(server);
|
|
46
|
+
return { server, status: state.status, toolCount: state.tools.length };
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async listTools(serverName, signal) {
|
|
50
|
+
const connection = await this.connect(serverName, signal);
|
|
51
|
+
return this.#states.get(serverName)?.connection === connection
|
|
52
|
+
? [...this.#states.get(serverName).tools]
|
|
53
|
+
: [];
|
|
54
|
+
}
|
|
55
|
+
async callTool(serverName, toolName, args, signal) {
|
|
56
|
+
const server = this.server(serverName);
|
|
57
|
+
const connection = await this.connect(serverName, signal);
|
|
58
|
+
const tool = this.#states.get(serverName).tools.find((candidate) => candidate.name === toolName);
|
|
59
|
+
if (!tool)
|
|
60
|
+
throw new Error(`Unknown tool ${JSON.stringify(toolName)} on MCP server ${serverName}`);
|
|
61
|
+
try {
|
|
62
|
+
return await connection.client.callTool({ name: tool.name, arguments: args }, requestOptions(server, combineSignals(this.#sessionSignal, signal)));
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (isUnauthorized(error)) {
|
|
66
|
+
await this.closeServer(serverName);
|
|
67
|
+
this.#states.get(serverName).status = 'needs-auth';
|
|
68
|
+
throw new McpAuthenticationRequiredError(serverName);
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
await this.closeServer(serverName);
|
|
72
|
+
}
|
|
73
|
+
catch (cleanupError) {
|
|
74
|
+
throw new AggregateError([error, cleanupError], `Failed to clean up MCP server ${serverName}`);
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async connect(serverName, signal) {
|
|
80
|
+
this.#assertOpen();
|
|
81
|
+
const server = this.server(serverName);
|
|
82
|
+
const state = this.#states.get(serverName);
|
|
83
|
+
if (state.connection)
|
|
84
|
+
return state.connection;
|
|
85
|
+
if (state.connecting)
|
|
86
|
+
return abortable(state.connecting, signal);
|
|
87
|
+
const generation = state.generation;
|
|
88
|
+
const controller = new AbortController();
|
|
89
|
+
const connectSignal = combineSignals(this.#sessionSignal, controller.signal, signal);
|
|
90
|
+
state.connectController = controller;
|
|
91
|
+
state.status = 'connecting';
|
|
92
|
+
let connecting;
|
|
93
|
+
connecting = (async () => {
|
|
94
|
+
let connection;
|
|
95
|
+
try {
|
|
96
|
+
const provider = await this.#oauth.providerFor(server, connectSignal);
|
|
97
|
+
connection = await this.#connectionFactory(server, provider, connectSignal, this.#fetch);
|
|
98
|
+
const tools = await fetchAllTools(connection.client, requestOptions(server, connectSignal));
|
|
99
|
+
if (this.#closed
|
|
100
|
+
|| state.generation !== generation
|
|
101
|
+
|| controller.signal.aborted
|
|
102
|
+
|| this.#sessionSignal.aborted) {
|
|
103
|
+
throw abortReason(connectSignal);
|
|
104
|
+
}
|
|
105
|
+
state.connection = connection;
|
|
106
|
+
state.tools = tools;
|
|
107
|
+
state.status = 'connected';
|
|
108
|
+
return connection;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
let reportedError = error;
|
|
112
|
+
if (connection && state.connection !== connection) {
|
|
113
|
+
try {
|
|
114
|
+
await closeConnection(connection);
|
|
115
|
+
}
|
|
116
|
+
catch (cleanupError) {
|
|
117
|
+
reportedError = new AggregateError([error, cleanupError], 'Failed to clean up MCP connection attempt');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (state.generation === generation && !this.#closed) {
|
|
121
|
+
state.status = connectSignal.aborted
|
|
122
|
+
? 'disconnected'
|
|
123
|
+
: isUnauthorized(reportedError) ? 'needs-auth' : 'failed';
|
|
124
|
+
}
|
|
125
|
+
if (isUnauthorized(reportedError))
|
|
126
|
+
throw new McpAuthenticationRequiredError(serverName);
|
|
127
|
+
throw reportedError;
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
if (state.connectController === controller)
|
|
131
|
+
state.connectController = undefined;
|
|
132
|
+
if (state.connecting === connecting)
|
|
133
|
+
state.connecting = undefined;
|
|
134
|
+
}
|
|
135
|
+
})();
|
|
136
|
+
state.connecting = connecting;
|
|
137
|
+
return abortable(connecting, signal);
|
|
138
|
+
}
|
|
139
|
+
async closeServer(serverName) {
|
|
140
|
+
const state = this.#states.get(serverName);
|
|
141
|
+
if (!state)
|
|
142
|
+
return;
|
|
143
|
+
state.generation += 1;
|
|
144
|
+
const connecting = state.connecting;
|
|
145
|
+
state.connectController?.abort(new Error(`MCP server ${serverName} connection closed`));
|
|
146
|
+
const connection = state.connection;
|
|
147
|
+
state.connection = undefined;
|
|
148
|
+
state.connecting = undefined;
|
|
149
|
+
state.tools = [];
|
|
150
|
+
state.status = 'disconnected';
|
|
151
|
+
if (connection)
|
|
152
|
+
await closeConnection(connection);
|
|
153
|
+
if (connecting)
|
|
154
|
+
await connecting.catch(() => { });
|
|
155
|
+
}
|
|
156
|
+
async close() {
|
|
157
|
+
if (this.#closed)
|
|
158
|
+
return;
|
|
159
|
+
this.#closed = true;
|
|
160
|
+
const closings = [...this.#servers.keys()].map((name) => this.closeServer(name));
|
|
161
|
+
const results = await Promise.allSettled(closings);
|
|
162
|
+
const failures = results.flatMap((result) => result.status === 'rejected' ? [result.reason] : []);
|
|
163
|
+
if (failures.length > 0)
|
|
164
|
+
throw new AggregateError(failures, 'Failed to close MCP connections');
|
|
165
|
+
}
|
|
166
|
+
#assertOpen() {
|
|
167
|
+
if (this.#closed || this.#sessionSignal.aborted)
|
|
168
|
+
throw abortReason(this.#sessionSignal);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export async function connectMcpServer(server, provider, signal, fetchFn) {
|
|
172
|
+
const kinds = server.transport === 'auto'
|
|
173
|
+
? ['streamable-http', 'sse']
|
|
174
|
+
: [server.transport];
|
|
175
|
+
let previousError;
|
|
176
|
+
for (const kind of kinds) {
|
|
177
|
+
signal.throwIfAborted();
|
|
178
|
+
const client = new Client({ name: 'felan-mcp', version: '0.1.0' });
|
|
179
|
+
const transport = kind === 'streamable-http'
|
|
180
|
+
? new StreamableHTTPClientTransport(new URL(server.url), {
|
|
181
|
+
authProvider: provider,
|
|
182
|
+
...(fetchFn === undefined ? {} : { fetch: fetchFn }),
|
|
183
|
+
})
|
|
184
|
+
: new SSEClientTransport(new URL(server.url), {
|
|
185
|
+
authProvider: provider,
|
|
186
|
+
...(fetchFn === undefined ? {} : { fetch: fetchFn }),
|
|
187
|
+
});
|
|
188
|
+
try {
|
|
189
|
+
await client.connect(transport, requestOptions(server, signal));
|
|
190
|
+
return { client, transport, transportKind: kind };
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
try {
|
|
194
|
+
await closeConnection({ client, transport, transportKind: kind });
|
|
195
|
+
}
|
|
196
|
+
catch (cleanupError) {
|
|
197
|
+
throw new AggregateError([error, cleanupError], `Failed to clean up MCP ${kind} connection`);
|
|
198
|
+
}
|
|
199
|
+
previousError = error;
|
|
200
|
+
if (kind !== 'streamable-http' || !shouldFallbackToSse(error))
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
throw previousError instanceof Error ? previousError : new Error(String(previousError));
|
|
205
|
+
}
|
|
206
|
+
async function fetchAllTools(client, options) {
|
|
207
|
+
const tools = [];
|
|
208
|
+
let cursor;
|
|
209
|
+
let pages = 0;
|
|
210
|
+
do {
|
|
211
|
+
if (++pages > MAX_TOOL_PAGES)
|
|
212
|
+
throw new Error('MCP tool listing exceeded the page limit');
|
|
213
|
+
const result = await client.listTools(cursor ? { cursor } : undefined, options);
|
|
214
|
+
tools.push(...result.tools);
|
|
215
|
+
if (tools.length > MAX_TOOLS_PER_SERVER) {
|
|
216
|
+
throw new Error(`MCP server exposed more than ${MAX_TOOLS_PER_SERVER} tools`);
|
|
217
|
+
}
|
|
218
|
+
cursor = result.nextCursor;
|
|
219
|
+
} while (cursor);
|
|
220
|
+
return tools;
|
|
221
|
+
}
|
|
222
|
+
function requestOptions(server, signal) {
|
|
223
|
+
if (!signal && server.requestTimeoutMs === undefined)
|
|
224
|
+
return undefined;
|
|
225
|
+
return {
|
|
226
|
+
...(signal ? { signal } : {}),
|
|
227
|
+
...(server.requestTimeoutMs === undefined ? {} : { timeout: server.requestTimeoutMs }),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function shouldFallbackToSse(error) {
|
|
231
|
+
return error instanceof SdkHttpError && [404, 405, 406, 415].includes(error.status);
|
|
232
|
+
}
|
|
233
|
+
function isUnauthorized(error) {
|
|
234
|
+
if (error instanceof McpAuthenticationRequiredError || error instanceof UnauthorizedError)
|
|
235
|
+
return true;
|
|
236
|
+
if (error instanceof SdkHttpError && error.status === 401)
|
|
237
|
+
return true;
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
function combineSignals(...signals) {
|
|
241
|
+
const present = signals.filter((signal) => signal !== undefined);
|
|
242
|
+
if (present.length === 0)
|
|
243
|
+
return new AbortController().signal;
|
|
244
|
+
if (present.length === 1)
|
|
245
|
+
return present[0];
|
|
246
|
+
return AbortSignal.any(present);
|
|
247
|
+
}
|
|
248
|
+
function abortable(promise, signal) {
|
|
249
|
+
if (!signal)
|
|
250
|
+
return promise;
|
|
251
|
+
signal.throwIfAborted();
|
|
252
|
+
return new Promise((resolve, reject) => {
|
|
253
|
+
const onAbort = () => reject(abortReason(signal));
|
|
254
|
+
const cleanup = () => signal.removeEventListener('abort', onAbort);
|
|
255
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
256
|
+
promise.then((value) => {
|
|
257
|
+
cleanup();
|
|
258
|
+
resolve(value);
|
|
259
|
+
}, (error) => {
|
|
260
|
+
cleanup();
|
|
261
|
+
reject(error);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
function abortReason(signal) {
|
|
266
|
+
return signal.reason instanceof Error ? signal.reason : new Error('MCP operation aborted');
|
|
267
|
+
}
|
|
268
|
+
async function closeConnection(connection) {
|
|
269
|
+
try {
|
|
270
|
+
await connection.client.close();
|
|
271
|
+
}
|
|
272
|
+
catch (clientError) {
|
|
273
|
+
try {
|
|
274
|
+
await connection.transport.close();
|
|
275
|
+
}
|
|
276
|
+
catch (transportError) {
|
|
277
|
+
throw new AggregateError([clientError, transportError], 'Failed to close MCP client and transport');
|
|
278
|
+
}
|
|
279
|
+
throw clientError;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@felan-ai/ext-mcp",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Portable OAuth-only MCP gateway for Felan",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/felan-ai/felan.git",
|
|
10
|
+
"directory": "packages/ext-mcp"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=22.19.0"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"LICENSE",
|
|
18
|
+
"NOTICE",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@modelcontextprotocol/client": "2.0.0",
|
|
29
|
+
"typebox": "1.1.38"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@felan-ai/agent-core": "^0.4.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@felan-ai/agent-core": "0.4.3"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public",
|
|
39
|
+
"provenance": true
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
43
|
+
"type-check": "tsc -p tsconfig.json --noEmit",
|
|
44
|
+
"test": "vitest run"
|
|
45
|
+
}
|
|
46
|
+
}
|