fa-mcp-sdk 0.4.10 → 0.4.13
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/cli-template/package.json +1 -1
- package/dist/core/agent-tester/services/TesterMcpClientService.js +11 -11
- package/dist/core/utils/testing/McpHttpClient.d.ts +2 -2
- package/dist/core/utils/testing/McpHttpClient.js +4 -4
- package/dist/core/utils/testing/McpSseClient.d.ts +2 -2
- package/dist/core/utils/testing/McpSseClient.js +6 -6
- package/dist/core/utils/testing/McpStreamableHttpClient.d.ts +2 -2
- package/dist/core/utils/testing/McpStreamableHttpClient.js +4 -4
- package/dist/core/web/static/agent-tester/index.html +2 -0
- package/package.json +1 -1
- package/src/tests/mcp/test-http.js +2 -2
- package/src/tests/mcp/test-sse.js +2 -2
|
@@ -108,27 +108,27 @@ export class TesterMcpClientService {
|
|
|
108
108
|
name: 'agent-tester',
|
|
109
109
|
version: '1.0.0',
|
|
110
110
|
});
|
|
111
|
-
const
|
|
111
|
+
const baseURL = new URL(mcpConfig.url);
|
|
112
112
|
if (mcpConfig.transport === 'http') {
|
|
113
|
-
logger.info(`Connecting via StreamableHTTPClientTransport to ${
|
|
113
|
+
logger.info(`Connecting via StreamableHTTPClientTransport to ${baseURL}`);
|
|
114
114
|
const safeHeaders = this.buildSafeHeaders(mcpConfig.headers);
|
|
115
115
|
const transportOpts = {};
|
|
116
116
|
if (safeHeaders) {
|
|
117
117
|
transportOpts.requestInit = { headers: safeHeaders };
|
|
118
118
|
}
|
|
119
|
-
const transport = new StreamableHTTPClientTransport(
|
|
119
|
+
const transport = new StreamableHTTPClientTransport(baseURL, transportOpts);
|
|
120
120
|
await client.connect(transport);
|
|
121
121
|
logger.info('Connected using Streamable HTTP transport');
|
|
122
122
|
}
|
|
123
123
|
else if (mcpConfig.transport === 'sse') {
|
|
124
|
-
logger.info(`Connecting via SSEClientTransport to ${
|
|
124
|
+
logger.info(`Connecting via SSEClientTransport to ${baseURL}`);
|
|
125
125
|
const safeHeaders = this.buildSafeHeaders(mcpConfig.headers);
|
|
126
126
|
const transportOpts = {};
|
|
127
127
|
if (safeHeaders) {
|
|
128
128
|
transportOpts.eventSourceInit = { headers: safeHeaders };
|
|
129
129
|
transportOpts.requestInit = { headers: safeHeaders };
|
|
130
130
|
}
|
|
131
|
-
const transport = new SSEClientTransport(
|
|
131
|
+
const transport = new SSEClientTransport(baseURL, transportOpts);
|
|
132
132
|
await client.connect(transport);
|
|
133
133
|
logger.info('Connected using SSE transport');
|
|
134
134
|
}
|
|
@@ -206,15 +206,15 @@ export class TesterMcpClientService {
|
|
|
206
206
|
async fetchRequiredHeadersUsing(client, serverUrl) {
|
|
207
207
|
// 1) Try HTTP endpoint /used-http-headers
|
|
208
208
|
try {
|
|
209
|
-
const
|
|
210
|
-
const headersUrl =
|
|
209
|
+
const baseURL = serverUrl.replace(/\/(mcp|sse)$/, '');
|
|
210
|
+
const headersUrl = baseURL + '/used-http-headers';
|
|
211
211
|
logger.info(`Fetching used headers from: ${headersUrl}`);
|
|
212
212
|
const response = await fetch(headersUrl, { method: 'GET', headers: { 'Accept': 'application/json' } });
|
|
213
213
|
if (response.ok) {
|
|
214
214
|
const headers = await response.json();
|
|
215
215
|
if (Array.isArray(headers)) {
|
|
216
216
|
if (headers.length > 0) {
|
|
217
|
-
logger.info(`Found ${headers.length} used headers from ${
|
|
217
|
+
logger.info(`Found ${headers.length} used headers from ${baseURL}`);
|
|
218
218
|
}
|
|
219
219
|
return headers;
|
|
220
220
|
}
|
|
@@ -377,14 +377,14 @@ export class TesterMcpClientService {
|
|
|
377
377
|
name: 'agent-tester',
|
|
378
378
|
version: '1.0.0',
|
|
379
379
|
});
|
|
380
|
-
const
|
|
380
|
+
const baseURL = new URL(request.url);
|
|
381
381
|
if (request.transport === 'http') {
|
|
382
382
|
const safeHeaders = this.buildSafeHeaders(request.headers);
|
|
383
383
|
const transportOpts = {};
|
|
384
384
|
if (safeHeaders) {
|
|
385
385
|
transportOpts.requestInit = { headers: safeHeaders };
|
|
386
386
|
}
|
|
387
|
-
const transport = new StreamableHTTPClientTransport(
|
|
387
|
+
const transport = new StreamableHTTPClientTransport(baseURL, transportOpts);
|
|
388
388
|
await client.connect(transport);
|
|
389
389
|
}
|
|
390
390
|
else if (request.transport === 'sse') {
|
|
@@ -394,7 +394,7 @@ export class TesterMcpClientService {
|
|
|
394
394
|
transportOpts.eventSourceInit = { headers: safeHeaders };
|
|
395
395
|
transportOpts.requestInit = { headers: safeHeaders };
|
|
396
396
|
}
|
|
397
|
-
const transport = new SSEClientTransport(
|
|
397
|
+
const transport = new SSEClientTransport(baseURL, transportOpts);
|
|
398
398
|
await client.connect(transport);
|
|
399
399
|
}
|
|
400
400
|
else {
|
|
@@ -7,7 +7,7 @@ type Json = any;
|
|
|
7
7
|
* with the current server implementation
|
|
8
8
|
*/
|
|
9
9
|
export declare class McpHttpClient extends BaseMcpClient {
|
|
10
|
-
private readonly
|
|
10
|
+
private readonly baseURL;
|
|
11
11
|
private readonly endpointPath;
|
|
12
12
|
serverInfo?: {
|
|
13
13
|
name: string;
|
|
@@ -15,7 +15,7 @@ export declare class McpHttpClient extends BaseMcpClient {
|
|
|
15
15
|
};
|
|
16
16
|
capabilities?: any;
|
|
17
17
|
protocolVersion?: string;
|
|
18
|
-
constructor(
|
|
18
|
+
constructor(baseURL: string, options?: {
|
|
19
19
|
endpointPath?: string;
|
|
20
20
|
headers?: Record<string, string>;
|
|
21
21
|
requestTimeoutMs?: number;
|
|
@@ -7,14 +7,14 @@ import { BaseMcpClient } from './BaseMcpClient.js';
|
|
|
7
7
|
* with the current server implementation
|
|
8
8
|
*/
|
|
9
9
|
export class McpHttpClient extends BaseMcpClient {
|
|
10
|
-
|
|
10
|
+
baseURL;
|
|
11
11
|
endpointPath;
|
|
12
12
|
serverInfo;
|
|
13
13
|
capabilities;
|
|
14
14
|
protocolVersion;
|
|
15
|
-
constructor(
|
|
15
|
+
constructor(baseURL, options) {
|
|
16
16
|
super(options?.headers ?? {});
|
|
17
|
-
this.
|
|
17
|
+
this.baseURL = baseURL.replace(/\/$/, '');
|
|
18
18
|
this.endpointPath = options?.endpointPath ?? '/mcp';
|
|
19
19
|
}
|
|
20
20
|
async initialize(params = {}) {
|
|
@@ -35,7 +35,7 @@ export class McpHttpClient extends BaseMcpClient {
|
|
|
35
35
|
'Accept': 'application/json',
|
|
36
36
|
...this.customHeaders,
|
|
37
37
|
};
|
|
38
|
-
const response = await fetch(`${this.
|
|
38
|
+
const response = await fetch(`${this.baseURL}${this.endpointPath}`, {
|
|
39
39
|
method: 'POST',
|
|
40
40
|
headers,
|
|
41
41
|
body: JSON.stringify(request),
|
|
@@ -7,13 +7,13 @@ import { BaseMcpClient } from './BaseMcpClient.js';
|
|
|
7
7
|
* Supports routing by id and per-operation timeouts.
|
|
8
8
|
*/
|
|
9
9
|
export declare class McpSseClient extends BaseMcpClient {
|
|
10
|
-
private readonly
|
|
10
|
+
private readonly baseURL;
|
|
11
11
|
private requestId;
|
|
12
12
|
private sseAbort?;
|
|
13
13
|
private sseReaderTask?;
|
|
14
14
|
private connected;
|
|
15
15
|
private pending;
|
|
16
|
-
constructor(
|
|
16
|
+
constructor(baseURL: string, customHeaders?: Record<string, string>);
|
|
17
17
|
/** Public API: close SSE and reject all pending */
|
|
18
18
|
close(): Promise<void>;
|
|
19
19
|
/** Ensure SSE stream established */
|
|
@@ -65,7 +65,7 @@ async function safeReadText(res) {
|
|
|
65
65
|
* Supports routing by id and per-operation timeouts.
|
|
66
66
|
*/
|
|
67
67
|
export class McpSseClient extends BaseMcpClient {
|
|
68
|
-
|
|
68
|
+
baseURL;
|
|
69
69
|
requestId;
|
|
70
70
|
// SSE connection state
|
|
71
71
|
sseAbort;
|
|
@@ -73,9 +73,9 @@ export class McpSseClient extends BaseMcpClient {
|
|
|
73
73
|
connected = false;
|
|
74
74
|
// pending requests awaiting response by id
|
|
75
75
|
pending = new Map();
|
|
76
|
-
constructor(
|
|
76
|
+
constructor(baseURL, customHeaders = {}) {
|
|
77
77
|
super(customHeaders);
|
|
78
|
-
this.
|
|
78
|
+
this.baseURL = baseURL.replace(/\/$/, '');
|
|
79
79
|
this.requestId = 1;
|
|
80
80
|
}
|
|
81
81
|
/** Public API: close SSE and reject all pending */
|
|
@@ -113,7 +113,7 @@ export class McpSseClient extends BaseMcpClient {
|
|
|
113
113
|
...this.customHeaders,
|
|
114
114
|
};
|
|
115
115
|
this.sseAbort = new AbortController();
|
|
116
|
-
const url = `${this.
|
|
116
|
+
const url = `${this.baseURL}/sse`;
|
|
117
117
|
const res = await fetch(url, {
|
|
118
118
|
method: 'GET',
|
|
119
119
|
headers,
|
|
@@ -266,7 +266,7 @@ export class McpSseClient extends BaseMcpClient {
|
|
|
266
266
|
...this.customHeaders,
|
|
267
267
|
};
|
|
268
268
|
try {
|
|
269
|
-
const res = await fetch(`${this.
|
|
269
|
+
const res = await fetch(`${this.baseURL}/sse`, {
|
|
270
270
|
method: 'POST',
|
|
271
271
|
headers,
|
|
272
272
|
body: JSON.stringify(request),
|
|
@@ -300,7 +300,7 @@ export class McpSseClient extends BaseMcpClient {
|
|
|
300
300
|
});
|
|
301
301
|
}
|
|
302
302
|
async health() {
|
|
303
|
-
const response = await fetch(`${this.
|
|
303
|
+
const response = await fetch(`${this.baseURL}/health`);
|
|
304
304
|
return response.json();
|
|
305
305
|
}
|
|
306
306
|
}
|
|
@@ -7,7 +7,7 @@ type Json = any;
|
|
|
7
7
|
* multiple requests/responses and incoming notifications.
|
|
8
8
|
*/
|
|
9
9
|
export declare class McpStreamableHttpClient extends BaseMcpClient {
|
|
10
|
-
private readonly
|
|
10
|
+
private readonly baseURL;
|
|
11
11
|
private readonly endpointPath;
|
|
12
12
|
private readonly requestTimeoutMs;
|
|
13
13
|
private encoder;
|
|
@@ -26,7 +26,7 @@ export declare class McpStreamableHttpClient extends BaseMcpClient {
|
|
|
26
26
|
};
|
|
27
27
|
capabilities?: any;
|
|
28
28
|
protocolVersion?: string;
|
|
29
|
-
constructor(
|
|
29
|
+
constructor(baseURL: string, options?: {
|
|
30
30
|
endpointPath?: string;
|
|
31
31
|
headers?: Record<string, string>;
|
|
32
32
|
requestTimeoutMs?: number;
|
|
@@ -6,7 +6,7 @@ import { BaseMcpClient } from './BaseMcpClient.js';
|
|
|
6
6
|
* multiple requests/responses and incoming notifications.
|
|
7
7
|
*/
|
|
8
8
|
export class McpStreamableHttpClient extends BaseMcpClient {
|
|
9
|
-
|
|
9
|
+
baseURL;
|
|
10
10
|
endpointPath;
|
|
11
11
|
requestTimeoutMs;
|
|
12
12
|
encoder = new TextEncoder();
|
|
@@ -22,9 +22,9 @@ export class McpStreamableHttpClient extends BaseMcpClient {
|
|
|
22
22
|
serverInfo;
|
|
23
23
|
capabilities;
|
|
24
24
|
protocolVersion;
|
|
25
|
-
constructor(
|
|
25
|
+
constructor(baseURL, options) {
|
|
26
26
|
super(options?.headers ?? {});
|
|
27
|
-
this.
|
|
27
|
+
this.baseURL = baseURL.replace(/\/$/, '');
|
|
28
28
|
this.endpointPath = options?.endpointPath ?? '/mcp';
|
|
29
29
|
this.requestTimeoutMs = options?.requestTimeoutMs ?? 120_000;
|
|
30
30
|
}
|
|
@@ -66,7 +66,7 @@ export class McpStreamableHttpClient extends BaseMcpClient {
|
|
|
66
66
|
'Accept': 'application/json',
|
|
67
67
|
...this.customHeaders,
|
|
68
68
|
};
|
|
69
|
-
this.response = await fetch(`${this.
|
|
69
|
+
this.response = await fetch(`${this.baseURL}${this.endpointPath}`, {
|
|
70
70
|
method: 'POST',
|
|
71
71
|
headers,
|
|
72
72
|
body: this.outgoing,
|
|
@@ -62,6 +62,8 @@
|
|
|
62
62
|
<div class="form-group model-select-group">
|
|
63
63
|
<label for="modelSelect">Model</label>
|
|
64
64
|
<select id="modelSelect" name="modelSelect" required>
|
|
65
|
+
<option value="gpt-5.4">gpt-5.4</option>
|
|
66
|
+
<option value="gpt-5.3-codex">gpt-5.3-codex</option>
|
|
65
67
|
<option value="gpt-5.2">gpt-5.2</option>
|
|
66
68
|
<option value="gpt-5.1">gpt-5.1</option>
|
|
67
69
|
<option value="gpt-5-nano">gpt-5-nano</option>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fa-mcp-sdk",
|
|
3
3
|
"productName": "FA MCP SDK",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.13",
|
|
5
5
|
"description": "Core infrastructure and templates for building Model Context Protocol (MCP) servers with TypeScript",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/core/index.js",
|
|
@@ -9,7 +9,7 @@ import { appConfig, McpHttpClient, getAuthHeadersForTests } from '../../../dist/
|
|
|
9
9
|
|
|
10
10
|
import TEMPLATE_TESTS from './test-cases.js';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const baseURL = (process.env.TEST_MCP_SERVER_URL || `http://localhost:${appConfig.webServer.port}`).replace(/\/+$/, '');
|
|
13
13
|
|
|
14
14
|
async function runTestGroup (title, tests, client) {
|
|
15
15
|
console.log(`\n${title}:`);
|
|
@@ -46,7 +46,7 @@ async function main () {
|
|
|
46
46
|
console.log('⚠️ Warning: Auth is enabled but no valid credentials found');
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const client = new McpHttpClient(
|
|
49
|
+
const client = new McpHttpClient(baseURL, { headers });
|
|
50
50
|
try {
|
|
51
51
|
await client.initialize({
|
|
52
52
|
protocolVersion: '2024-11-05',
|
|
@@ -9,7 +9,7 @@ import { appConfig, McpSseClient, getAuthHeadersForTests } from '../../../dist/c
|
|
|
9
9
|
|
|
10
10
|
import TEMPLATE_TESTS from './test-cases.js';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const baseURL = (process.env.TEST_MCP_SERVER_URL || `http://localhost:${appConfig.webServer.port}`).replace(/\/+$/, '');
|
|
13
13
|
|
|
14
14
|
async function runTestGroup (title, tests, client) {
|
|
15
15
|
console.log(`\n${title}:`);
|
|
@@ -46,7 +46,7 @@ async function main () {
|
|
|
46
46
|
console.log('⚠️ Warning: Auth is enabled but no valid credentials found');
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const client = new McpSseClient(
|
|
49
|
+
const client = new McpSseClient(baseURL, headers);
|
|
50
50
|
try {
|
|
51
51
|
// Health check (optional)
|
|
52
52
|
await client.health().catch(() => undefined);
|