@yourgpt/copilot-sdk 2.0.1 → 2.0.2-beta.2
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 +42 -0
- package/dist/{ThreadManager-JT0sqSSD.d.ts → ThreadManager-Dkp_eLty.d.ts} +1 -1
- package/dist/{ThreadManager-CUq5Ocu2.d.cts → ThreadManager-LfFRhr4e.d.cts} +1 -1
- package/dist/anthropic-6F5GRE3B.js +4 -0
- package/dist/anthropic-6F5GRE3B.js.map +1 -0
- package/dist/anthropic-DGalr_Fw.d.cts +17 -0
- package/dist/anthropic-DkCEDYOt.d.ts +17 -0
- package/dist/anthropic-NMTRABEH.cjs +21 -0
- package/dist/anthropic-NMTRABEH.cjs.map +1 -0
- package/dist/brave-DdnWb7Gb.d.cts +17 -0
- package/dist/brave-DsI9n7Wr.d.ts +17 -0
- package/dist/brave-OYKCOZEM.cjs +21 -0
- package/dist/brave-OYKCOZEM.cjs.map +1 -0
- package/dist/brave-XSASGGH2.js +4 -0
- package/dist/brave-XSASGGH2.js.map +1 -0
- package/dist/chunk-2FAWEBZS.cjs +88 -0
- package/dist/chunk-2FAWEBZS.cjs.map +1 -0
- package/dist/chunk-53UGJNHN.js +92 -0
- package/dist/chunk-53UGJNHN.js.map +1 -0
- package/dist/chunk-6T5XXJEP.cjs +80 -0
- package/dist/chunk-6T5XXJEP.cjs.map +1 -0
- package/dist/chunk-7K7HZMP4.cjs +1170 -0
- package/dist/chunk-7K7HZMP4.cjs.map +1 -0
- package/dist/chunk-7W7QLZNC.js +72 -0
- package/dist/chunk-7W7QLZNC.js.map +1 -0
- package/dist/{chunk-JM7PB2LP.js → chunk-7XFFRV7D.js} +10 -66
- package/dist/chunk-7XFFRV7D.js.map +1 -0
- package/dist/chunk-ASV6JLYG.cjs +99 -0
- package/dist/chunk-ASV6JLYG.cjs.map +1 -0
- package/dist/chunk-BH7MNDWW.js +1152 -0
- package/dist/chunk-BH7MNDWW.js.map +1 -0
- package/dist/chunk-BKO7DSPU.js +67 -0
- package/dist/chunk-BKO7DSPU.js.map +1 -0
- package/dist/chunk-CBAHCI4R.cjs +76 -0
- package/dist/chunk-CBAHCI4R.cjs.map +1 -0
- package/dist/chunk-CEKAYA2Q.cjs +74 -0
- package/dist/chunk-CEKAYA2Q.cjs.map +1 -0
- package/dist/chunk-CEOMTQTP.js +85 -0
- package/dist/chunk-CEOMTQTP.js.map +1 -0
- package/dist/chunk-DABZYCVX.js +84 -0
- package/dist/chunk-DABZYCVX.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-G4SF2PNQ.js +33 -0
- package/dist/chunk-G4SF2PNQ.js.map +1 -0
- package/dist/chunk-GANCV72Z.cjs +110 -0
- package/dist/chunk-GANCV72Z.cjs.map +1 -0
- package/dist/{chunk-BLSI67J6.cjs → chunk-H5XMKBBA.cjs} +425 -30
- package/dist/chunk-H5XMKBBA.cjs.map +1 -0
- package/dist/{chunk-CJ7UWN2Y.js → chunk-IXFV6AW6.js} +397 -7
- package/dist/chunk-IXFV6AW6.js.map +1 -0
- package/dist/chunk-JEQ2X3Z6.cjs +12 -0
- package/dist/chunk-JEQ2X3Z6.cjs.map +1 -0
- package/dist/chunk-JO4BHPAD.cjs +40 -0
- package/dist/chunk-JO4BHPAD.cjs.map +1 -0
- package/dist/chunk-MEBXW75C.cjs +89 -0
- package/dist/chunk-MEBXW75C.cjs.map +1 -0
- package/dist/chunk-MNDGIW47.js +76 -0
- package/dist/chunk-MNDGIW47.js.map +1 -0
- package/dist/chunk-PPFHA6IL.js +83 -0
- package/dist/chunk-PPFHA6IL.js.map +1 -0
- package/dist/chunk-RQ74USYU.js +128 -0
- package/dist/chunk-RQ74USYU.js.map +1 -0
- package/dist/chunk-TXLIY7GF.cjs +132 -0
- package/dist/chunk-TXLIY7GF.cjs.map +1 -0
- package/dist/chunk-UIWFYMAO.cjs +82 -0
- package/dist/chunk-UIWFYMAO.cjs.map +1 -0
- package/dist/{chunk-4PRWNAXQ.cjs → chunk-UOWLKFXK.cjs} +27 -89
- package/dist/chunk-UOWLKFXK.cjs.map +1 -0
- package/dist/chunk-VD74IPKB.js +106 -0
- package/dist/chunk-VD74IPKB.js.map +1 -0
- package/dist/chunk-W73FBYIH.cjs +87 -0
- package/dist/chunk-W73FBYIH.cjs.map +1 -0
- package/dist/chunk-XGITAEXU.js +93 -0
- package/dist/chunk-XGITAEXU.js.map +1 -0
- package/dist/chunk-XWOHNY3F.cjs +96 -0
- package/dist/chunk-XWOHNY3F.cjs.map +1 -0
- package/dist/chunk-ZPYQDMUX.js +79 -0
- package/dist/chunk-ZPYQDMUX.js.map +1 -0
- package/dist/core/index.cjs +156 -84
- package/dist/core/index.d.cts +16 -4
- package/dist/core/index.d.ts +16 -4
- package/dist/core/index.js +13 -1
- package/dist/exa-72KFY5A7.cjs +21 -0
- package/dist/exa-72KFY5A7.cjs.map +1 -0
- package/dist/exa-Dp9U-WTc.d.ts +17 -0
- package/dist/exa-NNVPBC2M.js +4 -0
- package/dist/exa-NNVPBC2M.js.map +1 -0
- package/dist/exa-jJSPhyUW.d.cts +17 -0
- package/dist/google-CHU2yycE.d.cts +17 -0
- package/dist/google-CTEK6SV2.js +4 -0
- package/dist/google-CTEK6SV2.js.map +1 -0
- package/dist/google-Da8IQxaI.d.ts +17 -0
- package/dist/google-IIUXFFVF.cjs +21 -0
- package/dist/google-IIUXFFVF.cjs.map +1 -0
- package/dist/index-2VtgKM8S.d.cts +206 -0
- package/dist/index-pWEH7pUE.d.ts +206 -0
- package/dist/mcp/index.cjs +670 -0
- package/dist/mcp/index.cjs.map +1 -0
- package/dist/mcp/index.d.cts +779 -0
- package/dist/mcp/index.d.ts +779 -0
- package/dist/mcp/index.js +574 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/openai-6KTCQ7PZ.cjs +21 -0
- package/dist/openai-6KTCQ7PZ.cjs.map +1 -0
- package/dist/openai-7W2PCNW5.js +4 -0
- package/dist/openai-7W2PCNW5.js.map +1 -0
- package/dist/openai-Cam8hF4f.d.ts +17 -0
- package/dist/openai-HVSCuXgO.d.cts +17 -0
- package/dist/react/index.cjs +75 -42
- package/dist/react/index.d.cts +270 -45
- package/dist/react/index.d.ts +270 -45
- package/dist/react/index.js +15 -2
- package/dist/searxng-AXLVGY7Z.js +4 -0
- package/dist/searxng-AXLVGY7Z.js.map +1 -0
- package/dist/searxng-EJKNY236.cjs +21 -0
- package/dist/searxng-EJKNY236.cjs.map +1 -0
- package/dist/searxng-K0qtY9vp.d.ts +17 -0
- package/dist/searxng-QGOte_Gq.d.cts +17 -0
- package/dist/serper-3JYJHJX6.js +4 -0
- package/dist/serper-3JYJHJX6.js.map +1 -0
- package/dist/serper-63FT4AOL.cjs +21 -0
- package/dist/serper-63FT4AOL.cjs.map +1 -0
- package/dist/serper-7Czya3PW.d.ts +17 -0
- package/dist/serper-JzdaSnS9.d.cts +17 -0
- package/dist/styles.css +38 -0
- package/dist/tavily-AWFP4RM7.cjs +21 -0
- package/dist/tavily-AWFP4RM7.cjs.map +1 -0
- package/dist/tavily-C8cXXojE.d.cts +17 -0
- package/dist/tavily-CIWAAZPH.js +4 -0
- package/dist/tavily-CIWAAZPH.js.map +1 -0
- package/dist/tavily-DdSGVgkE.d.ts +17 -0
- package/dist/themes/catppuccin.css +2 -0
- package/dist/themes/claude.css +2 -0
- package/dist/themes/linear.css +2 -0
- package/dist/themes/modern-minimal.css +2 -0
- package/dist/themes/posthog.css +2 -0
- package/dist/themes/supabase.css +2 -0
- package/dist/themes/twitter.css +2 -0
- package/dist/themes/vercel.css +2 -0
- package/dist/tools/anthropic/index.cjs +61 -0
- package/dist/tools/anthropic/index.cjs.map +1 -0
- package/dist/tools/anthropic/index.d.cts +67 -0
- package/dist/tools/anthropic/index.d.ts +67 -0
- package/dist/tools/anthropic/index.js +56 -0
- package/dist/tools/anthropic/index.js.map +1 -0
- package/dist/tools/brave/index.cjs +85 -0
- package/dist/tools/brave/index.cjs.map +1 -0
- package/dist/tools/brave/index.d.cts +91 -0
- package/dist/tools/brave/index.d.ts +91 -0
- package/dist/tools/brave/index.js +80 -0
- package/dist/tools/brave/index.js.map +1 -0
- package/dist/tools/exa/index.cjs +90 -0
- package/dist/tools/exa/index.cjs.map +1 -0
- package/dist/tools/exa/index.d.cts +92 -0
- package/dist/tools/exa/index.d.ts +92 -0
- package/dist/tools/exa/index.js +85 -0
- package/dist/tools/exa/index.js.map +1 -0
- package/dist/tools/google/index.cjs +81 -0
- package/dist/tools/google/index.cjs.map +1 -0
- package/dist/tools/google/index.d.cts +81 -0
- package/dist/tools/google/index.d.ts +81 -0
- package/dist/tools/google/index.js +76 -0
- package/dist/tools/google/index.js.map +1 -0
- package/dist/tools/openai/index.cjs +83 -0
- package/dist/tools/openai/index.cjs.map +1 -0
- package/dist/tools/openai/index.d.cts +84 -0
- package/dist/tools/openai/index.d.ts +84 -0
- package/dist/tools/openai/index.js +78 -0
- package/dist/tools/openai/index.js.map +1 -0
- package/dist/tools/searxng/index.cjs +85 -0
- package/dist/tools/searxng/index.cjs.map +1 -0
- package/dist/tools/searxng/index.d.cts +91 -0
- package/dist/tools/searxng/index.d.ts +91 -0
- package/dist/tools/searxng/index.js +80 -0
- package/dist/tools/searxng/index.js.map +1 -0
- package/dist/tools/serper/index.cjs +85 -0
- package/dist/tools/serper/index.cjs.map +1 -0
- package/dist/tools/serper/index.d.cts +91 -0
- package/dist/tools/serper/index.d.ts +91 -0
- package/dist/tools/serper/index.js +80 -0
- package/dist/tools/serper/index.js.map +1 -0
- package/dist/tools/tavily/index.cjs +91 -0
- package/dist/tools/tavily/index.cjs.map +1 -0
- package/dist/tools/tavily/index.d.cts +95 -0
- package/dist/tools/tavily/index.d.ts +95 -0
- package/dist/tools/tavily/index.js +86 -0
- package/dist/tools/tavily/index.js.map +1 -0
- package/dist/tools/web-search/index.cjs +31 -0
- package/dist/tools/web-search/index.cjs.map +1 -0
- package/dist/tools/web-search/index.d.cts +3 -0
- package/dist/tools/web-search/index.d.ts +3 -0
- package/dist/tools/web-search/index.js +14 -0
- package/dist/tools/web-search/index.js.map +1 -0
- package/dist/{types-BtAaOV07.d.cts → tools-DDWrco4h.d.cts} +43 -367
- package/dist/{types-BtAaOV07.d.ts → tools-DDWrco4h.d.ts} +43 -367
- package/dist/types-B20VCJXL.d.cts +347 -0
- package/dist/types-B20VCJXL.d.ts +347 -0
- package/dist/types-Cizh9K_f.d.ts +441 -0
- package/dist/types-DG2ya08y.d.cts +367 -0
- package/dist/types-DG2ya08y.d.ts +367 -0
- package/dist/types-DjSfYNKj.d.cts +441 -0
- package/dist/types-ZguuKEs_.d.cts +127 -0
- package/dist/types-ZguuKEs_.d.ts +127 -0
- package/dist/ui/index.cjs +1075 -148
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +410 -4
- package/dist/ui/index.d.ts +410 -4
- package/dist/ui/index.js +1007 -96
- package/dist/ui/index.js.map +1 -1
- package/package.json +52 -2
- package/dist/chunk-4PRWNAXQ.cjs.map +0 -1
- package/dist/chunk-BLSI67J6.cjs.map +0 -1
- package/dist/chunk-CJ7UWN2Y.js.map +0 -1
- package/dist/chunk-JM7PB2LP.js.map +0 -1
|
@@ -0,0 +1,1170 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/mcp/types.ts
|
|
4
|
+
var JSON_RPC_ERROR_CODES = {
|
|
5
|
+
PARSE_ERROR: -32700,
|
|
6
|
+
INVALID_REQUEST: -32600,
|
|
7
|
+
METHOD_NOT_FOUND: -32601,
|
|
8
|
+
INVALID_PARAMS: -32602,
|
|
9
|
+
INTERNAL_ERROR: -32603
|
|
10
|
+
};
|
|
11
|
+
var MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
12
|
+
var MCPError = class _MCPError extends Error {
|
|
13
|
+
constructor(message, code, data) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.code = code;
|
|
16
|
+
this.data = data;
|
|
17
|
+
this.name = "MCPError";
|
|
18
|
+
}
|
|
19
|
+
static fromJsonRpcError(error) {
|
|
20
|
+
return new _MCPError(error.message, error.code, error.data);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// src/mcp/protocol/JsonRpcHandler.ts
|
|
25
|
+
var JsonRpcHandler = class {
|
|
26
|
+
constructor(options) {
|
|
27
|
+
this.requestId = 0;
|
|
28
|
+
this.pendingRequests = /* @__PURE__ */ new Map();
|
|
29
|
+
this.defaultTimeout = options?.timeout ?? 3e4;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate a unique request ID
|
|
33
|
+
*/
|
|
34
|
+
generateId() {
|
|
35
|
+
return `req_${++this.requestId}_${Date.now()}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create a JSON-RPC request
|
|
39
|
+
*/
|
|
40
|
+
createRequest(method, params) {
|
|
41
|
+
const request = {
|
|
42
|
+
jsonrpc: "2.0",
|
|
43
|
+
id: this.generateId(),
|
|
44
|
+
method
|
|
45
|
+
};
|
|
46
|
+
if (params !== void 0) {
|
|
47
|
+
request.params = params;
|
|
48
|
+
}
|
|
49
|
+
return request;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a JSON-RPC notification (no response expected)
|
|
53
|
+
*/
|
|
54
|
+
createNotification(method, params) {
|
|
55
|
+
const notification = {
|
|
56
|
+
jsonrpc: "2.0",
|
|
57
|
+
method
|
|
58
|
+
};
|
|
59
|
+
if (params !== void 0) {
|
|
60
|
+
notification.params = params;
|
|
61
|
+
}
|
|
62
|
+
return notification;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Register a pending request and return a promise that resolves when response is received
|
|
66
|
+
*/
|
|
67
|
+
registerRequest(request, timeout) {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
const timeoutMs = timeout ?? this.defaultTimeout;
|
|
70
|
+
const timeoutHandle = setTimeout(() => {
|
|
71
|
+
this.pendingRequests.delete(request.id);
|
|
72
|
+
reject(
|
|
73
|
+
new MCPError(
|
|
74
|
+
`Request timed out after ${timeoutMs}ms: ${request.method}`,
|
|
75
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
76
|
+
)
|
|
77
|
+
);
|
|
78
|
+
}, timeoutMs);
|
|
79
|
+
this.pendingRequests.set(request.id, {
|
|
80
|
+
resolve,
|
|
81
|
+
reject,
|
|
82
|
+
timeout: timeoutHandle
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Handle an incoming JSON-RPC response
|
|
88
|
+
*/
|
|
89
|
+
handleResponse(response) {
|
|
90
|
+
if (response.id === null) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const pending = this.pendingRequests.get(response.id);
|
|
94
|
+
if (!pending) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
this.pendingRequests.delete(response.id);
|
|
98
|
+
clearTimeout(pending.timeout);
|
|
99
|
+
if (isErrorResponse(response)) {
|
|
100
|
+
pending.reject(MCPError.fromJsonRpcError(response.error));
|
|
101
|
+
} else {
|
|
102
|
+
pending.resolve(response.result);
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Parse a JSON-RPC message from string
|
|
108
|
+
*/
|
|
109
|
+
parse(data) {
|
|
110
|
+
try {
|
|
111
|
+
const parsed = JSON.parse(data);
|
|
112
|
+
if (!this.isValidMessage(parsed)) {
|
|
113
|
+
throw new MCPError(
|
|
114
|
+
"Invalid JSON-RPC message",
|
|
115
|
+
JSON_RPC_ERROR_CODES.INVALID_REQUEST
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return parsed;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (error instanceof MCPError) {
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
throw new MCPError(
|
|
124
|
+
"Failed to parse JSON-RPC message",
|
|
125
|
+
JSON_RPC_ERROR_CODES.PARSE_ERROR,
|
|
126
|
+
error
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Serialize a JSON-RPC message to string
|
|
132
|
+
*/
|
|
133
|
+
serialize(message) {
|
|
134
|
+
return JSON.stringify(message);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Validate a JSON-RPC message
|
|
138
|
+
*/
|
|
139
|
+
isValidMessage(message) {
|
|
140
|
+
if (!message || typeof message !== "object") {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const msg = message;
|
|
144
|
+
if (msg.jsonrpc !== "2.0") {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if ("method" in msg && typeof msg.method === "string") {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if ("id" in msg) {
|
|
151
|
+
return "result" in msg || "error" in msg;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Check if message is a request
|
|
157
|
+
*/
|
|
158
|
+
isRequest(message) {
|
|
159
|
+
return "method" in message && "id" in message;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if message is a notification
|
|
163
|
+
*/
|
|
164
|
+
isNotification(message) {
|
|
165
|
+
return "method" in message && !("id" in message);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check if message is a response
|
|
169
|
+
*/
|
|
170
|
+
isResponse(message) {
|
|
171
|
+
return "id" in message && ("result" in message || "error" in message);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Cancel all pending requests
|
|
175
|
+
*/
|
|
176
|
+
cancelAllPending(reason) {
|
|
177
|
+
const error = new MCPError(
|
|
178
|
+
reason ?? "All pending requests cancelled",
|
|
179
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
180
|
+
);
|
|
181
|
+
for (const [id, pending] of this.pendingRequests) {
|
|
182
|
+
clearTimeout(pending.timeout);
|
|
183
|
+
pending.reject(error);
|
|
184
|
+
}
|
|
185
|
+
this.pendingRequests.clear();
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get number of pending requests
|
|
189
|
+
*/
|
|
190
|
+
getPendingCount() {
|
|
191
|
+
return this.pendingRequests.size;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Check if a specific request is pending
|
|
195
|
+
*/
|
|
196
|
+
isPending(id) {
|
|
197
|
+
return this.pendingRequests.has(id);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
function isErrorResponse(response) {
|
|
201
|
+
return "error" in response;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// src/mcp/protocol/messages.ts
|
|
205
|
+
var MCP_METHODS = {
|
|
206
|
+
// Lifecycle
|
|
207
|
+
INITIALIZE: "initialize",
|
|
208
|
+
INITIALIZED: "notifications/initialized",
|
|
209
|
+
PING: "ping",
|
|
210
|
+
// Tools
|
|
211
|
+
TOOLS_LIST: "tools/list",
|
|
212
|
+
TOOLS_CALL: "tools/call",
|
|
213
|
+
// Resources (for future use)
|
|
214
|
+
RESOURCES_LIST: "resources/list",
|
|
215
|
+
RESOURCES_READ: "resources/read",
|
|
216
|
+
RESOURCES_SUBSCRIBE: "resources/subscribe",
|
|
217
|
+
RESOURCES_UNSUBSCRIBE: "resources/unsubscribe",
|
|
218
|
+
// Prompts (for future use)
|
|
219
|
+
PROMPTS_LIST: "prompts/list",
|
|
220
|
+
PROMPTS_GET: "prompts/get",
|
|
221
|
+
// Notifications
|
|
222
|
+
TOOLS_LIST_CHANGED: "notifications/tools/list_changed",
|
|
223
|
+
RESOURCES_LIST_CHANGED: "notifications/resources/list_changed",
|
|
224
|
+
RESOURCES_UPDATED: "notifications/resources/updated",
|
|
225
|
+
PROMPTS_LIST_CHANGED: "notifications/prompts/list_changed",
|
|
226
|
+
// Elicitation
|
|
227
|
+
ELICITATION_REQUEST: "elicitation/request",
|
|
228
|
+
ELICITATION_RESPONSE: "elicitation/response",
|
|
229
|
+
// Logging
|
|
230
|
+
LOGGING_SET_LEVEL: "logging/setLevel",
|
|
231
|
+
LOGGING_MESSAGE: "notifications/message",
|
|
232
|
+
// Cancellation
|
|
233
|
+
CANCEL: "notifications/cancelled"
|
|
234
|
+
};
|
|
235
|
+
var DEFAULT_CLIENT_INFO = {
|
|
236
|
+
name: "yourgpt-copilot-sdk",
|
|
237
|
+
version: "2.2.0"
|
|
238
|
+
};
|
|
239
|
+
var DEFAULT_CLIENT_CAPABILITIES = {
|
|
240
|
+
roots: {
|
|
241
|
+
listChanged: true
|
|
242
|
+
},
|
|
243
|
+
sampling: {}
|
|
244
|
+
};
|
|
245
|
+
function createInitializeParams(clientInfo, capabilities) {
|
|
246
|
+
return {
|
|
247
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
248
|
+
clientInfo: {
|
|
249
|
+
...DEFAULT_CLIENT_INFO,
|
|
250
|
+
...clientInfo
|
|
251
|
+
},
|
|
252
|
+
capabilities: capabilities ?? DEFAULT_CLIENT_CAPABILITIES
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function createToolsListParams(cursor) {
|
|
256
|
+
if (cursor) {
|
|
257
|
+
return { cursor };
|
|
258
|
+
}
|
|
259
|
+
return {};
|
|
260
|
+
}
|
|
261
|
+
function createToolCallParams(name, args) {
|
|
262
|
+
return {
|
|
263
|
+
name,
|
|
264
|
+
arguments: args
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function createPingParams() {
|
|
268
|
+
return {};
|
|
269
|
+
}
|
|
270
|
+
function isInitializeResult(value) {
|
|
271
|
+
if (!value || typeof value !== "object") return false;
|
|
272
|
+
const v = value;
|
|
273
|
+
return typeof v.protocolVersion === "string" && v.capabilities !== null && typeof v.capabilities === "object" && v.serverInfo !== null && typeof v.serverInfo === "object";
|
|
274
|
+
}
|
|
275
|
+
function isToolsListResult(value) {
|
|
276
|
+
if (!value || typeof value !== "object") return false;
|
|
277
|
+
const v = value;
|
|
278
|
+
return Array.isArray(v.tools);
|
|
279
|
+
}
|
|
280
|
+
function isToolCallResult(value) {
|
|
281
|
+
if (!value || typeof value !== "object") return false;
|
|
282
|
+
const v = value;
|
|
283
|
+
return Array.isArray(v.content);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// src/mcp/transports/types.ts
|
|
287
|
+
var BaseTransport = class {
|
|
288
|
+
constructor() {
|
|
289
|
+
this.connected = false;
|
|
290
|
+
}
|
|
291
|
+
onMessage(handler) {
|
|
292
|
+
this.messageHandler = handler;
|
|
293
|
+
}
|
|
294
|
+
onError(handler) {
|
|
295
|
+
this.errorHandler = handler;
|
|
296
|
+
}
|
|
297
|
+
onClose(handler) {
|
|
298
|
+
this.closeHandler = handler;
|
|
299
|
+
}
|
|
300
|
+
isConnected() {
|
|
301
|
+
return this.connected;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Emit a message to the handler
|
|
305
|
+
*/
|
|
306
|
+
emitMessage(message) {
|
|
307
|
+
if (this.messageHandler) {
|
|
308
|
+
this.messageHandler(message);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Emit an error to the handler
|
|
313
|
+
*/
|
|
314
|
+
emitError(error) {
|
|
315
|
+
if (this.errorHandler) {
|
|
316
|
+
this.errorHandler(error);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Emit close event
|
|
321
|
+
*/
|
|
322
|
+
emitClose() {
|
|
323
|
+
this.connected = false;
|
|
324
|
+
if (this.closeHandler) {
|
|
325
|
+
this.closeHandler();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
// src/mcp/transports/HttpTransport.ts
|
|
331
|
+
var HttpTransport = class extends BaseTransport {
|
|
332
|
+
constructor(options) {
|
|
333
|
+
super();
|
|
334
|
+
this.url = options.url;
|
|
335
|
+
this.headers = options.headers ?? {};
|
|
336
|
+
this.timeout = options.timeout ?? 3e4;
|
|
337
|
+
this.sessionId = options.sessionId;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Connect the HTTP transport
|
|
341
|
+
*
|
|
342
|
+
* For HTTP transport, "connecting" means verifying the endpoint is reachable.
|
|
343
|
+
* The actual session is established during the initialize handshake.
|
|
344
|
+
*/
|
|
345
|
+
async connect() {
|
|
346
|
+
if (this.connected) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
this.abortController = new AbortController();
|
|
350
|
+
this.connected = true;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Disconnect the HTTP transport
|
|
354
|
+
*/
|
|
355
|
+
async disconnect() {
|
|
356
|
+
if (!this.connected) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (this.eventSource) {
|
|
360
|
+
this.eventSource.close();
|
|
361
|
+
this.eventSource = void 0;
|
|
362
|
+
}
|
|
363
|
+
if (this.abortController) {
|
|
364
|
+
this.abortController.abort();
|
|
365
|
+
this.abortController = void 0;
|
|
366
|
+
}
|
|
367
|
+
this.sessionId = void 0;
|
|
368
|
+
this.connected = false;
|
|
369
|
+
this.emitClose();
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Send a JSON-RPC message and handle the response
|
|
373
|
+
*/
|
|
374
|
+
async send(message) {
|
|
375
|
+
if (!this.connected) {
|
|
376
|
+
throw new MCPError(
|
|
377
|
+
"Transport not connected",
|
|
378
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
const response = await this.sendRequest(message);
|
|
383
|
+
const contentType = response.headers.get("content-type") || "";
|
|
384
|
+
const newSessionId = response.headers.get("mcp-session-id");
|
|
385
|
+
if (newSessionId) {
|
|
386
|
+
this.sessionId = newSessionId;
|
|
387
|
+
}
|
|
388
|
+
if (contentType.includes("text/event-stream")) {
|
|
389
|
+
await this.handleSSEResponse(response);
|
|
390
|
+
} else if (contentType.includes("application/json")) {
|
|
391
|
+
const text = await response.text();
|
|
392
|
+
if (text.trim()) {
|
|
393
|
+
const messages = this.parseResponseText(text);
|
|
394
|
+
for (const msg of messages) {
|
|
395
|
+
this.emitMessage(msg);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
} else if (!response.ok) {
|
|
399
|
+
throw new MCPError(
|
|
400
|
+
`HTTP error: ${response.status} ${response.statusText}`,
|
|
401
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
} catch (error) {
|
|
405
|
+
if (error instanceof MCPError) {
|
|
406
|
+
throw error;
|
|
407
|
+
}
|
|
408
|
+
if (error instanceof Error) {
|
|
409
|
+
if (error.name === "AbortError") {
|
|
410
|
+
throw new MCPError(
|
|
411
|
+
"Request aborted",
|
|
412
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
throw new MCPError(
|
|
416
|
+
`Transport error: ${error.message}`,
|
|
417
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR,
|
|
418
|
+
error
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
throw new MCPError(
|
|
422
|
+
"Unknown transport error",
|
|
423
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Send an HTTP request
|
|
429
|
+
*/
|
|
430
|
+
async sendRequest(message) {
|
|
431
|
+
const headers = {
|
|
432
|
+
"Content-Type": "application/json",
|
|
433
|
+
Accept: "application/json, text/event-stream",
|
|
434
|
+
...this.headers
|
|
435
|
+
};
|
|
436
|
+
if (this.sessionId) {
|
|
437
|
+
headers["Mcp-Session-Id"] = this.sessionId;
|
|
438
|
+
}
|
|
439
|
+
const controller = new AbortController();
|
|
440
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
441
|
+
try {
|
|
442
|
+
const response = await fetch(this.url, {
|
|
443
|
+
method: "POST",
|
|
444
|
+
headers,
|
|
445
|
+
body: JSON.stringify(message),
|
|
446
|
+
signal: controller.signal
|
|
447
|
+
});
|
|
448
|
+
return response;
|
|
449
|
+
} finally {
|
|
450
|
+
clearTimeout(timeoutId);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Handle an SSE response stream
|
|
455
|
+
*/
|
|
456
|
+
async handleSSEResponse(response) {
|
|
457
|
+
const reader = response.body?.getReader();
|
|
458
|
+
if (!reader) {
|
|
459
|
+
throw new MCPError(
|
|
460
|
+
"No response body for SSE stream",
|
|
461
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
const decoder = new TextDecoder();
|
|
465
|
+
let buffer = "";
|
|
466
|
+
try {
|
|
467
|
+
while (true) {
|
|
468
|
+
const { done, value } = await reader.read();
|
|
469
|
+
if (done) {
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
buffer += decoder.decode(value, { stream: true });
|
|
473
|
+
const events = buffer.split("\n\n");
|
|
474
|
+
buffer = events.pop() || "";
|
|
475
|
+
for (const event of events) {
|
|
476
|
+
if (!event.trim()) continue;
|
|
477
|
+
const lines = event.split("\n");
|
|
478
|
+
let data = "";
|
|
479
|
+
for (const line of lines) {
|
|
480
|
+
if (line.startsWith("data: ")) {
|
|
481
|
+
data += line.slice(6);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (data) {
|
|
485
|
+
try {
|
|
486
|
+
const messages = this.parseResponseText(data);
|
|
487
|
+
for (const msg of messages) {
|
|
488
|
+
this.emitMessage(msg);
|
|
489
|
+
}
|
|
490
|
+
} catch {
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
} finally {
|
|
496
|
+
reader.releaseLock();
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Parse response text into JSON-RPC messages
|
|
501
|
+
*/
|
|
502
|
+
parseResponseText(text) {
|
|
503
|
+
const trimmed = text.trim();
|
|
504
|
+
if (!trimmed) {
|
|
505
|
+
return [];
|
|
506
|
+
}
|
|
507
|
+
try {
|
|
508
|
+
const parsed = JSON.parse(trimmed);
|
|
509
|
+
if (Array.isArray(parsed)) {
|
|
510
|
+
return parsed.filter(
|
|
511
|
+
(msg) => this.isValidJsonRpcMessage(msg)
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
if (this.isValidJsonRpcMessage(parsed)) {
|
|
515
|
+
return [parsed];
|
|
516
|
+
}
|
|
517
|
+
return [];
|
|
518
|
+
} catch {
|
|
519
|
+
throw new MCPError(
|
|
520
|
+
"Failed to parse JSON-RPC response",
|
|
521
|
+
JSON_RPC_ERROR_CODES.PARSE_ERROR
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Validate a JSON-RPC message
|
|
527
|
+
*/
|
|
528
|
+
isValidJsonRpcMessage(msg) {
|
|
529
|
+
if (!msg || typeof msg !== "object") {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
const m = msg;
|
|
533
|
+
if (m.jsonrpc !== "2.0") {
|
|
534
|
+
return false;
|
|
535
|
+
}
|
|
536
|
+
if ("method" in m && typeof m.method === "string") {
|
|
537
|
+
return true;
|
|
538
|
+
}
|
|
539
|
+
if ("id" in m && ("result" in m || "error" in m)) {
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Start listening for server-initiated events via SSE
|
|
546
|
+
*
|
|
547
|
+
* This is optional and used when the server supports server-initiated
|
|
548
|
+
* notifications (e.g., tools/list_changed).
|
|
549
|
+
*/
|
|
550
|
+
startEventStream() {
|
|
551
|
+
if (this.eventSource || typeof EventSource === "undefined") {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
const url = new URL(this.url);
|
|
555
|
+
if (this.sessionId) {
|
|
556
|
+
url.searchParams.set("sessionId", this.sessionId);
|
|
557
|
+
}
|
|
558
|
+
this.eventSource = new EventSource(url.toString());
|
|
559
|
+
this.eventSource.onmessage = (event) => {
|
|
560
|
+
try {
|
|
561
|
+
const messages = this.parseResponseText(event.data);
|
|
562
|
+
for (const msg of messages) {
|
|
563
|
+
this.emitMessage(msg);
|
|
564
|
+
}
|
|
565
|
+
} catch {
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
this.eventSource.onerror = () => {
|
|
569
|
+
this.emitError(new MCPError("SSE connection error"));
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Stop the event stream
|
|
574
|
+
*/
|
|
575
|
+
stopEventStream() {
|
|
576
|
+
if (this.eventSource) {
|
|
577
|
+
this.eventSource.close();
|
|
578
|
+
this.eventSource = void 0;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Get the current session ID
|
|
583
|
+
*/
|
|
584
|
+
getSessionId() {
|
|
585
|
+
return this.sessionId;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Set the session ID (used after initialization)
|
|
589
|
+
*/
|
|
590
|
+
setSessionId(sessionId) {
|
|
591
|
+
this.sessionId = sessionId;
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
// src/mcp/tools/MCPToolAdapter.ts
|
|
596
|
+
var MCPToolAdapter = class {
|
|
597
|
+
constructor(clientName) {
|
|
598
|
+
this.clientName = clientName;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Convert an MCP tool to a ToolDefinition
|
|
602
|
+
*/
|
|
603
|
+
toToolDefinition(mcpTool, options) {
|
|
604
|
+
const { prefix = true, asServerTool = true, callTool } = options;
|
|
605
|
+
const toolName = prefix ? `${this.clientName}_${mcpTool.name}` : mcpTool.name;
|
|
606
|
+
const originalName = mcpTool.name;
|
|
607
|
+
return {
|
|
608
|
+
name: toolName,
|
|
609
|
+
description: mcpTool.description ?? `MCP tool: ${mcpTool.name}`,
|
|
610
|
+
location: asServerTool ? "server" : "client",
|
|
611
|
+
inputSchema: this.convertInputSchema(mcpTool.inputSchema),
|
|
612
|
+
handler: async (params, context) => {
|
|
613
|
+
try {
|
|
614
|
+
if (context?.signal?.aborted) {
|
|
615
|
+
return {
|
|
616
|
+
success: false,
|
|
617
|
+
error: "Tool execution cancelled"
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
const result = await callTool(originalName, params);
|
|
621
|
+
return this.convertResult(result);
|
|
622
|
+
} catch (error) {
|
|
623
|
+
return {
|
|
624
|
+
success: false,
|
|
625
|
+
error: error instanceof Error ? error.message : "Unknown error calling MCP tool"
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
// MCP tools display their name as title
|
|
630
|
+
title: this.formatToolTitle(mcpTool.name),
|
|
631
|
+
executingTitle: `Calling ${this.formatToolTitle(mcpTool.name)}...`,
|
|
632
|
+
completedTitle: `${this.formatToolTitle(mcpTool.name)} completed`
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Convert multiple MCP tools to ToolDefinitions
|
|
637
|
+
*/
|
|
638
|
+
toToolDefinitions(mcpTools, options) {
|
|
639
|
+
return mcpTools.map((tool) => this.toToolDefinition(tool, options));
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Convert MCP input schema to SDK ToolInputSchema
|
|
643
|
+
*/
|
|
644
|
+
convertInputSchema(mcpSchema) {
|
|
645
|
+
return {
|
|
646
|
+
type: "object",
|
|
647
|
+
properties: mcpSchema.properties ? this.convertProperties(mcpSchema.properties) : {},
|
|
648
|
+
required: mcpSchema.required,
|
|
649
|
+
additionalProperties: mcpSchema.additionalProperties
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Convert MCP schema properties to SDK JSONSchemaProperty format
|
|
654
|
+
*/
|
|
655
|
+
convertProperties(properties) {
|
|
656
|
+
const converted = {};
|
|
657
|
+
for (const [key, prop] of Object.entries(properties)) {
|
|
658
|
+
converted[key] = this.convertProperty(prop);
|
|
659
|
+
}
|
|
660
|
+
return converted;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Convert a single MCP property to SDK format
|
|
664
|
+
*/
|
|
665
|
+
convertProperty(prop) {
|
|
666
|
+
let type = "string";
|
|
667
|
+
if (prop.type) {
|
|
668
|
+
if (Array.isArray(prop.type)) {
|
|
669
|
+
const nonNull = prop.type.find((t) => t !== "null");
|
|
670
|
+
type = nonNull || "string";
|
|
671
|
+
} else {
|
|
672
|
+
type = prop.type;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
const converted = {
|
|
676
|
+
type,
|
|
677
|
+
description: prop.description
|
|
678
|
+
};
|
|
679
|
+
if (prop.enum) {
|
|
680
|
+
converted.enum = prop.enum;
|
|
681
|
+
}
|
|
682
|
+
if (prop.default !== void 0) {
|
|
683
|
+
converted.default = prop.default;
|
|
684
|
+
}
|
|
685
|
+
if (prop.minLength !== void 0) {
|
|
686
|
+
converted.minLength = prop.minLength;
|
|
687
|
+
}
|
|
688
|
+
if (prop.maxLength !== void 0) {
|
|
689
|
+
converted.maxLength = prop.maxLength;
|
|
690
|
+
}
|
|
691
|
+
if (prop.minimum !== void 0) {
|
|
692
|
+
converted.minimum = prop.minimum;
|
|
693
|
+
}
|
|
694
|
+
if (prop.maximum !== void 0) {
|
|
695
|
+
converted.maximum = prop.maximum;
|
|
696
|
+
}
|
|
697
|
+
if (prop.pattern !== void 0) {
|
|
698
|
+
converted.pattern = prop.pattern;
|
|
699
|
+
}
|
|
700
|
+
if (prop.properties) {
|
|
701
|
+
converted.properties = this.convertProperties(prop.properties);
|
|
702
|
+
}
|
|
703
|
+
if (prop.required) {
|
|
704
|
+
converted.required = prop.required;
|
|
705
|
+
}
|
|
706
|
+
if (prop.items) {
|
|
707
|
+
converted.items = this.convertProperty(prop.items);
|
|
708
|
+
}
|
|
709
|
+
return converted;
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Convert MCP tool result to SDK ToolResponse
|
|
713
|
+
*/
|
|
714
|
+
convertResult(result) {
|
|
715
|
+
const response = {
|
|
716
|
+
success: !result.isError
|
|
717
|
+
};
|
|
718
|
+
const textParts = [];
|
|
719
|
+
const aiContent = [];
|
|
720
|
+
const uiResources = [];
|
|
721
|
+
for (const content of result.content) {
|
|
722
|
+
switch (content.type) {
|
|
723
|
+
case "text":
|
|
724
|
+
textParts.push(content.text);
|
|
725
|
+
break;
|
|
726
|
+
case "image": {
|
|
727
|
+
const img = content;
|
|
728
|
+
aiContent.push({
|
|
729
|
+
type: "image",
|
|
730
|
+
data: img.data,
|
|
731
|
+
mediaType: img.mimeType
|
|
732
|
+
});
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
case "resource": {
|
|
736
|
+
const res = content.resource;
|
|
737
|
+
if (res.uri?.startsWith("ui://")) {
|
|
738
|
+
uiResources.push({
|
|
739
|
+
uri: res.uri,
|
|
740
|
+
mimeType: res.mimeType || "text/html",
|
|
741
|
+
content: res.text,
|
|
742
|
+
// MCP uses "text" field, normalize to "content"
|
|
743
|
+
blob: res.blob
|
|
744
|
+
});
|
|
745
|
+
} else if (res.text) {
|
|
746
|
+
textParts.push(res.text);
|
|
747
|
+
}
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
case "ui": {
|
|
751
|
+
const uiContent = content;
|
|
752
|
+
uiResources.push({
|
|
753
|
+
uri: uiContent.resource.uri,
|
|
754
|
+
mimeType: uiContent.resource.mimeType,
|
|
755
|
+
content: uiContent.resource.content,
|
|
756
|
+
blob: uiContent.resource.blob,
|
|
757
|
+
metadata: uiContent.resource.metadata
|
|
758
|
+
});
|
|
759
|
+
break;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (textParts.length > 0) {
|
|
764
|
+
response.message = textParts.join("\n");
|
|
765
|
+
if (textParts.length === 1) {
|
|
766
|
+
try {
|
|
767
|
+
response.data = JSON.parse(textParts[0]);
|
|
768
|
+
} catch {
|
|
769
|
+
response.data = textParts[0];
|
|
770
|
+
}
|
|
771
|
+
} else {
|
|
772
|
+
response.data = textParts;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
if (aiContent.length > 0) {
|
|
776
|
+
response._aiContent = aiContent;
|
|
777
|
+
}
|
|
778
|
+
if (uiResources.length > 0) {
|
|
779
|
+
response._uiResources = uiResources;
|
|
780
|
+
}
|
|
781
|
+
if (result.isError) {
|
|
782
|
+
response.error = textParts.join("\n") || "Tool execution failed";
|
|
783
|
+
}
|
|
784
|
+
return response;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Format tool name as a readable title
|
|
788
|
+
*/
|
|
789
|
+
formatToolTitle(name) {
|
|
790
|
+
return name.replace(/[-_]/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
function mcpToolToDefinition(clientName, mcpTool, options) {
|
|
794
|
+
const adapter = new MCPToolAdapter(clientName);
|
|
795
|
+
return adapter.toToolDefinition(mcpTool, options);
|
|
796
|
+
}
|
|
797
|
+
function mcpToolsToDefinitions(clientName, mcpTools, options) {
|
|
798
|
+
const adapter = new MCPToolAdapter(clientName);
|
|
799
|
+
return adapter.toToolDefinitions(mcpTools, options);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// src/mcp/client/MCPClient.ts
|
|
803
|
+
var MCPClient = class {
|
|
804
|
+
constructor(config, events) {
|
|
805
|
+
this.config = config;
|
|
806
|
+
this.events = events ?? {};
|
|
807
|
+
this.rpcHandler = new JsonRpcHandler({ timeout: config.timeout ?? 3e4 });
|
|
808
|
+
this.toolAdapter = new MCPToolAdapter(config.name);
|
|
809
|
+
this.state = {
|
|
810
|
+
connectionState: "disconnected",
|
|
811
|
+
tools: []
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Get the current client state
|
|
816
|
+
*/
|
|
817
|
+
getState() {
|
|
818
|
+
return { ...this.state };
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Get the client name
|
|
822
|
+
*/
|
|
823
|
+
getName() {
|
|
824
|
+
return this.config.name;
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Check if client is connected
|
|
828
|
+
*/
|
|
829
|
+
isConnected() {
|
|
830
|
+
return this.state.connectionState === "connected";
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Connect to the MCP server
|
|
834
|
+
*/
|
|
835
|
+
async connect() {
|
|
836
|
+
if (this.state.connectionState === "connected") {
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
if (this.state.connectionState === "connecting") {
|
|
840
|
+
throw new MCPError("Connection already in progress");
|
|
841
|
+
}
|
|
842
|
+
this.setConnectionState("connecting");
|
|
843
|
+
try {
|
|
844
|
+
this.transport = this.createTransport();
|
|
845
|
+
this.transport.onMessage(this.handleMessage.bind(this));
|
|
846
|
+
this.transport.onError(this.handleError.bind(this));
|
|
847
|
+
this.transport.onClose(this.handleClose.bind(this));
|
|
848
|
+
await this.transport.connect();
|
|
849
|
+
await this.initialize();
|
|
850
|
+
this.setConnectionState("connected");
|
|
851
|
+
await this.refreshTools();
|
|
852
|
+
} catch (error) {
|
|
853
|
+
this.setConnectionState(
|
|
854
|
+
"error",
|
|
855
|
+
error instanceof Error ? error.message : "Connection failed"
|
|
856
|
+
);
|
|
857
|
+
throw error;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Disconnect from the MCP server
|
|
862
|
+
*/
|
|
863
|
+
async disconnect() {
|
|
864
|
+
if (this.state.connectionState === "disconnected") {
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
this.rpcHandler.cancelAllPending("Client disconnecting");
|
|
868
|
+
if (this.transport) {
|
|
869
|
+
await this.transport.disconnect();
|
|
870
|
+
this.transport = void 0;
|
|
871
|
+
}
|
|
872
|
+
this.state = {
|
|
873
|
+
connectionState: "disconnected",
|
|
874
|
+
tools: []
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Call an MCP tool
|
|
879
|
+
*/
|
|
880
|
+
async callTool(name, args) {
|
|
881
|
+
this.ensureConnected();
|
|
882
|
+
const result = await this.request(
|
|
883
|
+
MCP_METHODS.TOOLS_CALL,
|
|
884
|
+
createToolCallParams(name, args)
|
|
885
|
+
);
|
|
886
|
+
if (!isToolCallResult(result)) {
|
|
887
|
+
throw new MCPError(
|
|
888
|
+
"Invalid tool call result from server",
|
|
889
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
return result;
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* Refresh the list of available tools
|
|
896
|
+
*/
|
|
897
|
+
async refreshTools() {
|
|
898
|
+
this.ensureConnected();
|
|
899
|
+
const allTools = [];
|
|
900
|
+
let cursor;
|
|
901
|
+
do {
|
|
902
|
+
const result = await this.request(
|
|
903
|
+
MCP_METHODS.TOOLS_LIST,
|
|
904
|
+
createToolsListParams(cursor)
|
|
905
|
+
);
|
|
906
|
+
if (!isToolsListResult(result)) {
|
|
907
|
+
throw new MCPError(
|
|
908
|
+
"Invalid tools list result from server",
|
|
909
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
allTools.push(...result.tools);
|
|
913
|
+
cursor = result.nextCursor;
|
|
914
|
+
} while (cursor);
|
|
915
|
+
this.state.tools = allTools;
|
|
916
|
+
this.state.lastActivity = Date.now();
|
|
917
|
+
this.events.onToolsChange?.(allTools);
|
|
918
|
+
return allTools;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Convert MCP tools to ToolDefinition format for use with CopilotProvider
|
|
922
|
+
*/
|
|
923
|
+
toToolDefinitions(options) {
|
|
924
|
+
const prefix = options?.prefixToolNames !== false;
|
|
925
|
+
const asServer = options?.serverLocation ?? false;
|
|
926
|
+
return this.state.tools.map(
|
|
927
|
+
(tool) => this.toolAdapter.toToolDefinition(tool, {
|
|
928
|
+
prefix,
|
|
929
|
+
asServerTool: asServer,
|
|
930
|
+
callTool: this.callTool.bind(this)
|
|
931
|
+
})
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Get the list of MCP tools
|
|
936
|
+
*/
|
|
937
|
+
getTools() {
|
|
938
|
+
return [...this.state.tools];
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Get server info
|
|
942
|
+
*/
|
|
943
|
+
getServerInfo() {
|
|
944
|
+
return this.state.serverInfo;
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Get server capabilities
|
|
948
|
+
*/
|
|
949
|
+
getServerCapabilities() {
|
|
950
|
+
return this.state.serverCapabilities;
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* Ping the server to check connectivity
|
|
954
|
+
*/
|
|
955
|
+
async ping() {
|
|
956
|
+
try {
|
|
957
|
+
await this.request(MCP_METHODS.PING, createPingParams());
|
|
958
|
+
return true;
|
|
959
|
+
} catch {
|
|
960
|
+
return false;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
// ============================================
|
|
964
|
+
// Private Methods
|
|
965
|
+
// ============================================
|
|
966
|
+
/**
|
|
967
|
+
* Create transport based on config
|
|
968
|
+
*/
|
|
969
|
+
createTransport() {
|
|
970
|
+
switch (this.config.transport) {
|
|
971
|
+
case "http":
|
|
972
|
+
if (!this.config.url) {
|
|
973
|
+
throw new MCPError(
|
|
974
|
+
"URL is required for HTTP transport",
|
|
975
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
return new HttpTransport({
|
|
979
|
+
url: this.config.url,
|
|
980
|
+
headers: this.config.headers,
|
|
981
|
+
timeout: this.config.timeout
|
|
982
|
+
});
|
|
983
|
+
case "sse":
|
|
984
|
+
if (!this.config.url) {
|
|
985
|
+
throw new MCPError(
|
|
986
|
+
"URL is required for SSE transport",
|
|
987
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
return new HttpTransport({
|
|
991
|
+
url: this.config.url,
|
|
992
|
+
headers: this.config.headers,
|
|
993
|
+
timeout: this.config.timeout
|
|
994
|
+
});
|
|
995
|
+
case "stdio":
|
|
996
|
+
throw new MCPError(
|
|
997
|
+
"Stdio transport not yet implemented. Use HTTP or SSE transport.",
|
|
998
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
999
|
+
);
|
|
1000
|
+
default:
|
|
1001
|
+
throw new MCPError(
|
|
1002
|
+
`Unknown transport type: ${this.config.transport}`,
|
|
1003
|
+
JSON_RPC_ERROR_CODES.INVALID_PARAMS
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Perform MCP initialization handshake
|
|
1009
|
+
*/
|
|
1010
|
+
async initialize() {
|
|
1011
|
+
const params = createInitializeParams(
|
|
1012
|
+
this.config.clientInfo,
|
|
1013
|
+
this.config.capabilities
|
|
1014
|
+
);
|
|
1015
|
+
const result = await this.request(
|
|
1016
|
+
MCP_METHODS.INITIALIZE,
|
|
1017
|
+
params
|
|
1018
|
+
);
|
|
1019
|
+
if (!isInitializeResult(result)) {
|
|
1020
|
+
throw new MCPError(
|
|
1021
|
+
"Invalid initialization result from server",
|
|
1022
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
this.state.serverInfo = result.serverInfo;
|
|
1026
|
+
this.state.serverCapabilities = result.capabilities;
|
|
1027
|
+
await this.notify(MCP_METHODS.INITIALIZED);
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* Send a JSON-RPC request and wait for response
|
|
1031
|
+
*/
|
|
1032
|
+
async request(method, params) {
|
|
1033
|
+
if (!this.transport) {
|
|
1034
|
+
throw new MCPError(
|
|
1035
|
+
"Transport not initialized",
|
|
1036
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
const request = this.rpcHandler.createRequest(method, params);
|
|
1040
|
+
const responsePromise = this.rpcHandler.registerRequest(
|
|
1041
|
+
request,
|
|
1042
|
+
this.config.timeout
|
|
1043
|
+
);
|
|
1044
|
+
await this.transport.send(request);
|
|
1045
|
+
return responsePromise;
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Send a JSON-RPC notification (no response expected)
|
|
1049
|
+
*/
|
|
1050
|
+
async notify(method, params) {
|
|
1051
|
+
if (!this.transport) {
|
|
1052
|
+
throw new MCPError(
|
|
1053
|
+
"Transport not initialized",
|
|
1054
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
const notification = this.rpcHandler.createNotification(method, params);
|
|
1058
|
+
await this.transport.send(notification);
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Handle incoming JSON-RPC message
|
|
1062
|
+
*/
|
|
1063
|
+
handleMessage(message) {
|
|
1064
|
+
if (this.rpcHandler.isResponse(message)) {
|
|
1065
|
+
this.rpcHandler.handleResponse(message);
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
if (this.rpcHandler.isNotification(message)) {
|
|
1069
|
+
const notification = message;
|
|
1070
|
+
this.handleNotification(notification.method, notification.params);
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
if (this.rpcHandler.isRequest(message)) {
|
|
1074
|
+
const request = message;
|
|
1075
|
+
this.handleServerRequest(request.id, request.method, request.params);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Handle server notification
|
|
1080
|
+
*/
|
|
1081
|
+
handleNotification(method, params) {
|
|
1082
|
+
switch (method) {
|
|
1083
|
+
case MCP_METHODS.TOOLS_LIST_CHANGED:
|
|
1084
|
+
this.refreshTools().catch((error) => {
|
|
1085
|
+
this.events.onError?.(error);
|
|
1086
|
+
});
|
|
1087
|
+
break;
|
|
1088
|
+
default:
|
|
1089
|
+
this.events.onNotification?.(method, params);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Handle server-initiated request (e.g., elicitation)
|
|
1094
|
+
*/
|
|
1095
|
+
async handleServerRequest(_id, method, params) {
|
|
1096
|
+
if (method === MCP_METHODS.ELICITATION_REQUEST && this.events.onElicitationRequest) {
|
|
1097
|
+
try {
|
|
1098
|
+
const elicitationRequest = params;
|
|
1099
|
+
const response = await this.events.onElicitationRequest(elicitationRequest);
|
|
1100
|
+
await this.notify(
|
|
1101
|
+
MCP_METHODS.ELICITATION_RESPONSE,
|
|
1102
|
+
response
|
|
1103
|
+
);
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
await this.notify(MCP_METHODS.ELICITATION_RESPONSE, {
|
|
1106
|
+
requestId: params?.requestId,
|
|
1107
|
+
accepted: false,
|
|
1108
|
+
reason: error instanceof Error ? error.message : "User rejected"
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Handle transport error
|
|
1115
|
+
*/
|
|
1116
|
+
handleError(error) {
|
|
1117
|
+
this.setConnectionState("error", error.message);
|
|
1118
|
+
this.events.onError?.(error);
|
|
1119
|
+
}
|
|
1120
|
+
/**
|
|
1121
|
+
* Handle transport close
|
|
1122
|
+
*/
|
|
1123
|
+
handleClose() {
|
|
1124
|
+
if (this.state.connectionState === "connected") {
|
|
1125
|
+
this.setConnectionState("disconnected");
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Update connection state
|
|
1130
|
+
*/
|
|
1131
|
+
setConnectionState(state, error) {
|
|
1132
|
+
this.state.connectionState = state;
|
|
1133
|
+
this.state.error = error;
|
|
1134
|
+
this.events.onConnectionStateChange?.(state);
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Ensure client is connected
|
|
1138
|
+
*/
|
|
1139
|
+
ensureConnected() {
|
|
1140
|
+
if (!this.isConnected()) {
|
|
1141
|
+
throw new MCPError(
|
|
1142
|
+
"Client not connected. Call connect() first.",
|
|
1143
|
+
JSON_RPC_ERROR_CODES.INTERNAL_ERROR
|
|
1144
|
+
);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
function createMCPClient(config, events) {
|
|
1149
|
+
return new MCPClient(config, events);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
exports.BaseTransport = BaseTransport;
|
|
1153
|
+
exports.DEFAULT_CLIENT_CAPABILITIES = DEFAULT_CLIENT_CAPABILITIES;
|
|
1154
|
+
exports.DEFAULT_CLIENT_INFO = DEFAULT_CLIENT_INFO;
|
|
1155
|
+
exports.HttpTransport = HttpTransport;
|
|
1156
|
+
exports.JSON_RPC_ERROR_CODES = JSON_RPC_ERROR_CODES;
|
|
1157
|
+
exports.JsonRpcHandler = JsonRpcHandler;
|
|
1158
|
+
exports.MCPClient = MCPClient;
|
|
1159
|
+
exports.MCPError = MCPError;
|
|
1160
|
+
exports.MCPToolAdapter = MCPToolAdapter;
|
|
1161
|
+
exports.MCP_METHODS = MCP_METHODS;
|
|
1162
|
+
exports.MCP_PROTOCOL_VERSION = MCP_PROTOCOL_VERSION;
|
|
1163
|
+
exports.createInitializeParams = createInitializeParams;
|
|
1164
|
+
exports.createMCPClient = createMCPClient;
|
|
1165
|
+
exports.createToolCallParams = createToolCallParams;
|
|
1166
|
+
exports.createToolsListParams = createToolsListParams;
|
|
1167
|
+
exports.mcpToolToDefinition = mcpToolToDefinition;
|
|
1168
|
+
exports.mcpToolsToDefinitions = mcpToolsToDefinitions;
|
|
1169
|
+
//# sourceMappingURL=chunk-7K7HZMP4.cjs.map
|
|
1170
|
+
//# sourceMappingURL=chunk-7K7HZMP4.cjs.map
|