@epicdm/flowstate-mcp-client 1.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/README.md +22 -0
- package/dist/index.d.mts +51 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +163 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +135 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# FlowState MCP Client
|
|
2
|
+
|
|
3
|
+
TypeScript client for connecting to FlowState MCP Gateway from web and Electron applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
yarn add @epic-flow/flowstate-mcp-client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { MCPClient } from '@epic-flow/flowstate-mcp-client';
|
|
15
|
+
|
|
16
|
+
const client = new MCPClient({
|
|
17
|
+
baseUrl: 'http://localhost:7081',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const tools = await client.listTools();
|
|
21
|
+
const result = await client.callTool('collection-query', { collection: 'tasks' });
|
|
22
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
interface MCPClientConfig {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
authToken?: string;
|
|
4
|
+
timeout?: number;
|
|
5
|
+
}
|
|
6
|
+
interface Tool {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
inputSchema: any;
|
|
10
|
+
}
|
|
11
|
+
interface ToolCallResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
result?: any;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
declare class MCPClientError extends Error {
|
|
17
|
+
statusCode?: number | undefined;
|
|
18
|
+
response?: any | undefined;
|
|
19
|
+
constructor(message: string, statusCode?: number | undefined, response?: any | undefined);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare class MCPClient {
|
|
23
|
+
private config;
|
|
24
|
+
constructor(config: MCPClientConfig);
|
|
25
|
+
/**
|
|
26
|
+
* List all available tools from MCP HTTP Server
|
|
27
|
+
*/
|
|
28
|
+
listTools(): Promise<Tool[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Call a specific tool with arguments
|
|
31
|
+
*/
|
|
32
|
+
callTool(toolName: string, args?: Record<string, any>): Promise<any>;
|
|
33
|
+
/**
|
|
34
|
+
* Check MCP HTTP server health
|
|
35
|
+
*/
|
|
36
|
+
health(): Promise<{
|
|
37
|
+
status: string;
|
|
38
|
+
initialized: boolean;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Update the auth token (useful when token is refreshed)
|
|
42
|
+
*/
|
|
43
|
+
updateAuthToken(authToken: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Update client configuration
|
|
46
|
+
*/
|
|
47
|
+
updateConfig(updates: Partial<MCPClientConfig>): void;
|
|
48
|
+
private fetch;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { MCPClient, type MCPClientConfig, MCPClientError, type Tool, type ToolCallResult };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
interface MCPClientConfig {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
authToken?: string;
|
|
4
|
+
timeout?: number;
|
|
5
|
+
}
|
|
6
|
+
interface Tool {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
inputSchema: any;
|
|
10
|
+
}
|
|
11
|
+
interface ToolCallResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
result?: any;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
declare class MCPClientError extends Error {
|
|
17
|
+
statusCode?: number | undefined;
|
|
18
|
+
response?: any | undefined;
|
|
19
|
+
constructor(message: string, statusCode?: number | undefined, response?: any | undefined);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare class MCPClient {
|
|
23
|
+
private config;
|
|
24
|
+
constructor(config: MCPClientConfig);
|
|
25
|
+
/**
|
|
26
|
+
* List all available tools from MCP HTTP Server
|
|
27
|
+
*/
|
|
28
|
+
listTools(): Promise<Tool[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Call a specific tool with arguments
|
|
31
|
+
*/
|
|
32
|
+
callTool(toolName: string, args?: Record<string, any>): Promise<any>;
|
|
33
|
+
/**
|
|
34
|
+
* Check MCP HTTP server health
|
|
35
|
+
*/
|
|
36
|
+
health(): Promise<{
|
|
37
|
+
status: string;
|
|
38
|
+
initialized: boolean;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Update the auth token (useful when token is refreshed)
|
|
42
|
+
*/
|
|
43
|
+
updateAuthToken(authToken: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Update client configuration
|
|
46
|
+
*/
|
|
47
|
+
updateConfig(updates: Partial<MCPClientConfig>): void;
|
|
48
|
+
private fetch;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { MCPClient, type MCPClientConfig, MCPClientError, type Tool, type ToolCallResult };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
MCPClient: () => MCPClient,
|
|
24
|
+
MCPClientError: () => MCPClientError
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/types.ts
|
|
29
|
+
var MCPClientError = class extends Error {
|
|
30
|
+
constructor(message, statusCode, response) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.statusCode = statusCode;
|
|
33
|
+
this.response = response;
|
|
34
|
+
this.name = "MCPClientError";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/client.ts
|
|
39
|
+
var MCPClient = class {
|
|
40
|
+
config;
|
|
41
|
+
constructor(config) {
|
|
42
|
+
this.config = {
|
|
43
|
+
timeout: 3e4,
|
|
44
|
+
...config
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* List all available tools from MCP HTTP Server
|
|
49
|
+
*/
|
|
50
|
+
async listTools() {
|
|
51
|
+
try {
|
|
52
|
+
const response = await this.fetch("/tools", {
|
|
53
|
+
method: "GET"
|
|
54
|
+
});
|
|
55
|
+
const data = await response.json();
|
|
56
|
+
return data.tools || [];
|
|
57
|
+
} catch (error) {
|
|
58
|
+
throw new MCPClientError(
|
|
59
|
+
`Failed to list tools: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
60
|
+
500
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Call a specific tool with arguments
|
|
66
|
+
*/
|
|
67
|
+
async callTool(toolName, args) {
|
|
68
|
+
try {
|
|
69
|
+
const response = await this.fetch(`/tools/${encodeURIComponent(toolName)}`, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
body: JSON.stringify(args || {})
|
|
72
|
+
});
|
|
73
|
+
const result = await response.json();
|
|
74
|
+
if (!result.success) {
|
|
75
|
+
throw new MCPClientError(
|
|
76
|
+
result.error || "Tool execution failed",
|
|
77
|
+
response.status
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return result.result;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (error instanceof MCPClientError) {
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
throw new MCPClientError(
|
|
86
|
+
`Failed to call tool ${toolName}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
87
|
+
500
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Check MCP HTTP server health
|
|
93
|
+
*/
|
|
94
|
+
async health() {
|
|
95
|
+
try {
|
|
96
|
+
const response = await this.fetch("/health", {
|
|
97
|
+
method: "GET"
|
|
98
|
+
});
|
|
99
|
+
return await response.json();
|
|
100
|
+
} catch (error) {
|
|
101
|
+
throw new MCPClientError(
|
|
102
|
+
`Health check failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
103
|
+
500
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Update the auth token (useful when token is refreshed)
|
|
109
|
+
*/
|
|
110
|
+
updateAuthToken(authToken) {
|
|
111
|
+
this.config.authToken = authToken;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Update client configuration
|
|
115
|
+
*/
|
|
116
|
+
updateConfig(updates) {
|
|
117
|
+
Object.assign(this.config, updates);
|
|
118
|
+
}
|
|
119
|
+
async fetch(path, options) {
|
|
120
|
+
const url = `${this.config.baseUrl}${path}`;
|
|
121
|
+
const hasAuthToken = !!this.config.authToken;
|
|
122
|
+
console.log(`[MCPClient] ${options.method || "GET"} ${url} (auth: ${hasAuthToken})`);
|
|
123
|
+
const headers = {
|
|
124
|
+
"Content-Type": "application/json",
|
|
125
|
+
...this.config.authToken && {
|
|
126
|
+
"Authorization": `Bearer ${this.config.authToken}`
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const controller = new AbortController();
|
|
130
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
131
|
+
try {
|
|
132
|
+
const response = await fetch(url, {
|
|
133
|
+
...options,
|
|
134
|
+
headers,
|
|
135
|
+
signal: controller.signal
|
|
136
|
+
});
|
|
137
|
+
clearTimeout(timeoutId);
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
throw new MCPClientError(
|
|
140
|
+
`HTTP ${response.status}: ${response.statusText}`,
|
|
141
|
+
response.status,
|
|
142
|
+
await response.json().catch(() => null)
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return response;
|
|
146
|
+
} catch (error) {
|
|
147
|
+
clearTimeout(timeoutId);
|
|
148
|
+
if (error instanceof MCPClientError) {
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
152
|
+
throw new MCPClientError("Request timeout", 408);
|
|
153
|
+
}
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
159
|
+
0 && (module.exports = {
|
|
160
|
+
MCPClient,
|
|
161
|
+
MCPClientError
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/client.ts"],"sourcesContent":["// Copyright 2026 Epic Digital Interactive Media LLC\n// SPDX-License-Identifier: Apache-2.0\n\nexport { MCPClient } from './client';\nexport type {\n MCPClientConfig,\n Tool,\n ToolCallResult,\n} from './types';\nexport { MCPClientError } from './types';\n","// Copyright 2026 Epic Digital Interactive Media LLC\n// SPDX-License-Identifier: Apache-2.0\n\nexport interface MCPClientConfig {\n baseUrl: string;\n authToken?: string;\n timeout?: number;\n}\n\nexport interface Tool {\n name: string;\n description: string;\n inputSchema: any;\n}\n\nexport interface ToolCallResult {\n success: boolean;\n result?: any;\n error?: string;\n}\n\nexport class MCPClientError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: any\n ) {\n super(message);\n this.name = 'MCPClientError';\n }\n}\n","// Copyright 2026 Epic Digital Interactive Media LLC\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { MCPClientConfig, Tool, ToolCallResult } from './types';\nimport { MCPClientError } from './types';\n\nexport class MCPClient {\n private config: MCPClientConfig;\n\n constructor(config: MCPClientConfig) {\n this.config = {\n timeout: 30000,\n ...config,\n };\n }\n\n /**\n * List all available tools from MCP HTTP Server\n */\n async listTools(): Promise<Tool[]> {\n try {\n const response = await this.fetch('/tools', {\n method: 'GET',\n });\n\n const data = await response.json();\n return data.tools || [];\n } catch (error) {\n throw new MCPClientError(\n `Failed to list tools: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 500\n );\n }\n }\n\n /**\n * Call a specific tool with arguments\n */\n async callTool(toolName: string, args?: Record<string, any>): Promise<any> {\n try {\n const response = await this.fetch(`/tools/${encodeURIComponent(toolName)}`, {\n method: 'POST',\n body: JSON.stringify(args || {}),\n });\n\n const result: ToolCallResult = await response.json();\n\n if (!result.success) {\n throw new MCPClientError(\n result.error || 'Tool execution failed',\n response.status\n );\n }\n\n return result.result;\n } catch (error) {\n if (error instanceof MCPClientError) {\n throw error;\n }\n throw new MCPClientError(\n `Failed to call tool ${toolName}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 500\n );\n }\n }\n\n /**\n * Check MCP HTTP server health\n */\n async health(): Promise<{ status: string; initialized: boolean }> {\n try {\n const response = await this.fetch('/health', {\n method: 'GET',\n });\n\n return await response.json();\n } catch (error) {\n throw new MCPClientError(\n `Health check failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 500\n );\n }\n }\n\n /**\n * Update the auth token (useful when token is refreshed)\n */\n updateAuthToken(authToken: string): void {\n this.config.authToken = authToken;\n }\n\n /**\n * Update client configuration\n */\n updateConfig(updates: Partial<MCPClientConfig>): void {\n Object.assign(this.config, updates);\n }\n\n private async fetch(path: string, options: RequestInit): Promise<Response> {\n const url = `${this.config.baseUrl}${path}`;\n const hasAuthToken = !!this.config.authToken;\n console.log(`[MCPClient] ${options.method || 'GET'} ${url} (auth: ${hasAuthToken})`);\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n ...(this.config.authToken && {\n 'Authorization': `Bearer ${this.config.authToken}`,\n }),\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new MCPClientError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n await response.json().catch(() => null)\n );\n }\n\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof MCPClientError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new MCPClientError('Request timeout', 408);\n }\n\n throw error;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var MCPClientError = class extends Error {
|
|
3
|
+
constructor(message, statusCode, response) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.statusCode = statusCode;
|
|
6
|
+
this.response = response;
|
|
7
|
+
this.name = "MCPClientError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/client.ts
|
|
12
|
+
var MCPClient = class {
|
|
13
|
+
config;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = {
|
|
16
|
+
timeout: 3e4,
|
|
17
|
+
...config
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* List all available tools from MCP HTTP Server
|
|
22
|
+
*/
|
|
23
|
+
async listTools() {
|
|
24
|
+
try {
|
|
25
|
+
const response = await this.fetch("/tools", {
|
|
26
|
+
method: "GET"
|
|
27
|
+
});
|
|
28
|
+
const data = await response.json();
|
|
29
|
+
return data.tools || [];
|
|
30
|
+
} catch (error) {
|
|
31
|
+
throw new MCPClientError(
|
|
32
|
+
`Failed to list tools: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
33
|
+
500
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Call a specific tool with arguments
|
|
39
|
+
*/
|
|
40
|
+
async callTool(toolName, args) {
|
|
41
|
+
try {
|
|
42
|
+
const response = await this.fetch(`/tools/${encodeURIComponent(toolName)}`, {
|
|
43
|
+
method: "POST",
|
|
44
|
+
body: JSON.stringify(args || {})
|
|
45
|
+
});
|
|
46
|
+
const result = await response.json();
|
|
47
|
+
if (!result.success) {
|
|
48
|
+
throw new MCPClientError(
|
|
49
|
+
result.error || "Tool execution failed",
|
|
50
|
+
response.status
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return result.result;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof MCPClientError) {
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
throw new MCPClientError(
|
|
59
|
+
`Failed to call tool ${toolName}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
60
|
+
500
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check MCP HTTP server health
|
|
66
|
+
*/
|
|
67
|
+
async health() {
|
|
68
|
+
try {
|
|
69
|
+
const response = await this.fetch("/health", {
|
|
70
|
+
method: "GET"
|
|
71
|
+
});
|
|
72
|
+
return await response.json();
|
|
73
|
+
} catch (error) {
|
|
74
|
+
throw new MCPClientError(
|
|
75
|
+
`Health check failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
76
|
+
500
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Update the auth token (useful when token is refreshed)
|
|
82
|
+
*/
|
|
83
|
+
updateAuthToken(authToken) {
|
|
84
|
+
this.config.authToken = authToken;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Update client configuration
|
|
88
|
+
*/
|
|
89
|
+
updateConfig(updates) {
|
|
90
|
+
Object.assign(this.config, updates);
|
|
91
|
+
}
|
|
92
|
+
async fetch(path, options) {
|
|
93
|
+
const url = `${this.config.baseUrl}${path}`;
|
|
94
|
+
const hasAuthToken = !!this.config.authToken;
|
|
95
|
+
console.log(`[MCPClient] ${options.method || "GET"} ${url} (auth: ${hasAuthToken})`);
|
|
96
|
+
const headers = {
|
|
97
|
+
"Content-Type": "application/json",
|
|
98
|
+
...this.config.authToken && {
|
|
99
|
+
"Authorization": `Bearer ${this.config.authToken}`
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const controller = new AbortController();
|
|
103
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
104
|
+
try {
|
|
105
|
+
const response = await fetch(url, {
|
|
106
|
+
...options,
|
|
107
|
+
headers,
|
|
108
|
+
signal: controller.signal
|
|
109
|
+
});
|
|
110
|
+
clearTimeout(timeoutId);
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
throw new MCPClientError(
|
|
113
|
+
`HTTP ${response.status}: ${response.statusText}`,
|
|
114
|
+
response.status,
|
|
115
|
+
await response.json().catch(() => null)
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return response;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
clearTimeout(timeoutId);
|
|
121
|
+
if (error instanceof MCPClientError) {
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
125
|
+
throw new MCPClientError("Request timeout", 408);
|
|
126
|
+
}
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
export {
|
|
132
|
+
MCPClient,
|
|
133
|
+
MCPClientError
|
|
134
|
+
};
|
|
135
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/client.ts"],"sourcesContent":["// Copyright 2026 Epic Digital Interactive Media LLC\n// SPDX-License-Identifier: Apache-2.0\n\nexport interface MCPClientConfig {\n baseUrl: string;\n authToken?: string;\n timeout?: number;\n}\n\nexport interface Tool {\n name: string;\n description: string;\n inputSchema: any;\n}\n\nexport interface ToolCallResult {\n success: boolean;\n result?: any;\n error?: string;\n}\n\nexport class MCPClientError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: any\n ) {\n super(message);\n this.name = 'MCPClientError';\n }\n}\n","// Copyright 2026 Epic Digital Interactive Media LLC\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { MCPClientConfig, Tool, ToolCallResult } from './types';\nimport { MCPClientError } from './types';\n\nexport class MCPClient {\n private config: MCPClientConfig;\n\n constructor(config: MCPClientConfig) {\n this.config = {\n timeout: 30000,\n ...config,\n };\n }\n\n /**\n * List all available tools from MCP HTTP Server\n */\n async listTools(): Promise<Tool[]> {\n try {\n const response = await this.fetch('/tools', {\n method: 'GET',\n });\n\n const data = await response.json();\n return data.tools || [];\n } catch (error) {\n throw new MCPClientError(\n `Failed to list tools: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 500\n );\n }\n }\n\n /**\n * Call a specific tool with arguments\n */\n async callTool(toolName: string, args?: Record<string, any>): Promise<any> {\n try {\n const response = await this.fetch(`/tools/${encodeURIComponent(toolName)}`, {\n method: 'POST',\n body: JSON.stringify(args || {}),\n });\n\n const result: ToolCallResult = await response.json();\n\n if (!result.success) {\n throw new MCPClientError(\n result.error || 'Tool execution failed',\n response.status\n );\n }\n\n return result.result;\n } catch (error) {\n if (error instanceof MCPClientError) {\n throw error;\n }\n throw new MCPClientError(\n `Failed to call tool ${toolName}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 500\n );\n }\n }\n\n /**\n * Check MCP HTTP server health\n */\n async health(): Promise<{ status: string; initialized: boolean }> {\n try {\n const response = await this.fetch('/health', {\n method: 'GET',\n });\n\n return await response.json();\n } catch (error) {\n throw new MCPClientError(\n `Health check failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 500\n );\n }\n }\n\n /**\n * Update the auth token (useful when token is refreshed)\n */\n updateAuthToken(authToken: string): void {\n this.config.authToken = authToken;\n }\n\n /**\n * Update client configuration\n */\n updateConfig(updates: Partial<MCPClientConfig>): void {\n Object.assign(this.config, updates);\n }\n\n private async fetch(path: string, options: RequestInit): Promise<Response> {\n const url = `${this.config.baseUrl}${path}`;\n const hasAuthToken = !!this.config.authToken;\n console.log(`[MCPClient] ${options.method || 'GET'} ${url} (auth: ${hasAuthToken})`);\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n ...(this.config.authToken && {\n 'Authorization': `Bearer ${this.config.authToken}`,\n }),\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(url, {\n ...options,\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new MCPClientError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n await response.json().catch(() => null)\n );\n }\n\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof MCPClientError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new MCPClientError('Request timeout', 408);\n }\n\n throw error;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@epicdm/flowstate-mcp-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript client for FlowState MCP Gateway",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"test": "jest",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"lint": "eslint src --ext .ts"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/jest": "^29.5.14",
|
|
27
|
+
"@types/node": "^20.14.11",
|
|
28
|
+
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
29
|
+
"@typescript-eslint/parser": "^7.18.0",
|
|
30
|
+
"eslint": "^8.57.1",
|
|
31
|
+
"jest": "^29.7.0",
|
|
32
|
+
"ts-jest": "^29.2.5",
|
|
33
|
+
"tsup": "^8.3.5",
|
|
34
|
+
"typescript": "^5.9.2"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"mcp",
|
|
38
|
+
"client",
|
|
39
|
+
"flowstate"
|
|
40
|
+
],
|
|
41
|
+
"author": "Epic Digital Interactive Media LLC",
|
|
42
|
+
"license": "Apache-2.0",
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "https://github.com/epicdm/epic-flowstate.git",
|
|
49
|
+
"directory": "packages/flowstate-mcp-client"
|
|
50
|
+
}
|
|
51
|
+
}
|