poe-code 3.0.73 → 3.0.74
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/dist/cli/commands/ralph.js +1 -3
- package/dist/cli/commands/ralph.js.map +1 -1
- package/dist/cli/commands/spawn.js +3 -3
- package/dist/cli/commands/spawn.js.map +1 -1
- package/dist/cli/service-registry.d.ts +1 -0
- package/dist/cli/service-registry.js.map +1 -1
- package/dist/index.js +2026 -102
- package/dist/index.js.map +4 -4
- package/dist/providers/claude-code.js +1 -0
- package/dist/providers/claude-code.js.map +2 -2
- package/dist/providers/codex.js +1 -0
- package/dist/providers/codex.js.map +2 -2
- package/dist/providers/create-provider.d.ts +1 -0
- package/dist/providers/create-provider.js +1 -0
- package/dist/providers/create-provider.js.map +1 -1
- package/dist/providers/kimi.js +1 -0
- package/dist/providers/kimi.js.map +2 -2
- package/dist/providers/opencode.js +1 -0
- package/dist/providers/opencode.js.map +2 -2
- package/dist/providers/poe-agent.d.ts +3 -1
- package/dist/providers/poe-agent.js +1510 -15
- package/dist/providers/poe-agent.js.map +4 -4
- package/dist/sdk/spawn.js +6 -1
- package/dist/sdk/spawn.js.map +1 -1
- package/package.json +1 -1
|
@@ -668,17 +668,1433 @@ var init_chat = __esm({
|
|
|
668
668
|
}
|
|
669
669
|
});
|
|
670
670
|
|
|
671
|
+
// packages/tiny-mcp-client/src/internal.ts
|
|
672
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
673
|
+
import { PassThrough } from "node:stream";
|
|
674
|
+
function defaultStdioSpawn(command, args, options) {
|
|
675
|
+
return spawn2(command, args, options);
|
|
676
|
+
}
|
|
677
|
+
function defaultHttpTransportFetch(input, init) {
|
|
678
|
+
return fetch(input, init);
|
|
679
|
+
}
|
|
680
|
+
function serializeJsonRpcMessage2(message) {
|
|
681
|
+
return `${JSON.stringify(message)}
|
|
682
|
+
`;
|
|
683
|
+
}
|
|
684
|
+
function chunkToString2(chunk) {
|
|
685
|
+
if (typeof chunk === "string") {
|
|
686
|
+
return chunk;
|
|
687
|
+
}
|
|
688
|
+
if (chunk instanceof Uint8Array) {
|
|
689
|
+
return Buffer.from(chunk).toString("utf8");
|
|
690
|
+
}
|
|
691
|
+
return String(chunk);
|
|
692
|
+
}
|
|
693
|
+
function normalizeLine2(line) {
|
|
694
|
+
return line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
695
|
+
}
|
|
696
|
+
async function* readLines2(stream) {
|
|
697
|
+
let buffer = "";
|
|
698
|
+
for await (const chunk of stream) {
|
|
699
|
+
buffer += chunkToString2(chunk);
|
|
700
|
+
while (true) {
|
|
701
|
+
const newlineIndex = buffer.indexOf("\n");
|
|
702
|
+
if (newlineIndex === -1) {
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
const line = buffer.slice(0, newlineIndex);
|
|
706
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
707
|
+
yield normalizeLine2(line);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
if (buffer.length > 0) {
|
|
711
|
+
yield normalizeLine2(buffer);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
function isObjectRecord3(value) {
|
|
715
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
716
|
+
}
|
|
717
|
+
function hasOwn2(value, property) {
|
|
718
|
+
return Object.prototype.hasOwnProperty.call(value, property);
|
|
719
|
+
}
|
|
720
|
+
function isRequestId2(value) {
|
|
721
|
+
return typeof value === "string" || typeof value === "number";
|
|
722
|
+
}
|
|
723
|
+
function isLogLevel(value) {
|
|
724
|
+
return value === "debug" || value === "info" || value === "notice" || value === "warning" || value === "error" || value === "critical" || value === "alert" || value === "emergency";
|
|
725
|
+
}
|
|
726
|
+
function toRequestId2(value) {
|
|
727
|
+
return isRequestId2(value) ? value : null;
|
|
728
|
+
}
|
|
729
|
+
function parseError2() {
|
|
730
|
+
return new McpError(ERROR_PARSE, "Parse error");
|
|
731
|
+
}
|
|
732
|
+
function invalidRequest2() {
|
|
733
|
+
return new McpError(ERROR_INVALID_REQUEST, "Invalid Request");
|
|
734
|
+
}
|
|
735
|
+
function isJsonRpcErrorObject2(value) {
|
|
736
|
+
if (!isObjectRecord3(value)) {
|
|
737
|
+
return false;
|
|
738
|
+
}
|
|
739
|
+
if (typeof value.code !== "number" || typeof value.message !== "string") {
|
|
740
|
+
return false;
|
|
741
|
+
}
|
|
742
|
+
return value.data === void 0 || hasOwn2(value, "data");
|
|
743
|
+
}
|
|
744
|
+
function parseJsonRpcPayload(parsed) {
|
|
745
|
+
if (!isObjectRecord3(parsed)) {
|
|
746
|
+
return {
|
|
747
|
+
type: "invalid",
|
|
748
|
+
id: null,
|
|
749
|
+
error: invalidRequest2()
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
const id = toRequestId2(parsed.id);
|
|
753
|
+
if (parsed.jsonrpc !== "2.0") {
|
|
754
|
+
return {
|
|
755
|
+
type: "invalid",
|
|
756
|
+
id,
|
|
757
|
+
error: invalidRequest2()
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
const hasMethod = hasOwn2(parsed, "method");
|
|
761
|
+
const hasId = hasOwn2(parsed, "id");
|
|
762
|
+
if (hasMethod) {
|
|
763
|
+
if (typeof parsed.method !== "string") {
|
|
764
|
+
return {
|
|
765
|
+
type: "invalid",
|
|
766
|
+
id,
|
|
767
|
+
error: invalidRequest2()
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
if (hasId) {
|
|
771
|
+
if (!isRequestId2(parsed.id)) {
|
|
772
|
+
return {
|
|
773
|
+
type: "invalid",
|
|
774
|
+
id: null,
|
|
775
|
+
error: invalidRequest2()
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
const request = {
|
|
779
|
+
jsonrpc: "2.0",
|
|
780
|
+
id: parsed.id,
|
|
781
|
+
method: parsed.method
|
|
782
|
+
};
|
|
783
|
+
if (hasOwn2(parsed, "params")) {
|
|
784
|
+
request.params = parsed.params;
|
|
785
|
+
}
|
|
786
|
+
return {
|
|
787
|
+
type: "request",
|
|
788
|
+
message: request
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
const notification = {
|
|
792
|
+
jsonrpc: "2.0",
|
|
793
|
+
method: parsed.method
|
|
794
|
+
};
|
|
795
|
+
if (hasOwn2(parsed, "params")) {
|
|
796
|
+
notification.params = parsed.params;
|
|
797
|
+
}
|
|
798
|
+
return {
|
|
799
|
+
type: "notification",
|
|
800
|
+
message: notification
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
if (!hasId || !isRequestId2(parsed.id)) {
|
|
804
|
+
return {
|
|
805
|
+
type: "invalid",
|
|
806
|
+
id,
|
|
807
|
+
error: invalidRequest2()
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
const hasResult = hasOwn2(parsed, "result");
|
|
811
|
+
const hasError = hasOwn2(parsed, "error");
|
|
812
|
+
if (hasResult === hasError) {
|
|
813
|
+
return {
|
|
814
|
+
type: "invalid",
|
|
815
|
+
id: parsed.id,
|
|
816
|
+
error: invalidRequest2()
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
if (hasResult) {
|
|
820
|
+
return {
|
|
821
|
+
type: "response",
|
|
822
|
+
message: {
|
|
823
|
+
jsonrpc: "2.0",
|
|
824
|
+
id: parsed.id,
|
|
825
|
+
result: parsed.result
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
if (!isJsonRpcErrorObject2(parsed.error)) {
|
|
830
|
+
return {
|
|
831
|
+
type: "invalid",
|
|
832
|
+
id: parsed.id,
|
|
833
|
+
error: invalidRequest2()
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
return {
|
|
837
|
+
type: "response",
|
|
838
|
+
message: {
|
|
839
|
+
jsonrpc: "2.0",
|
|
840
|
+
id: parsed.id,
|
|
841
|
+
error: parsed.error
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
var MCP_PROTOCOL_VERSION, McpClient, ERROR_PARSE, ERROR_INVALID_REQUEST, ERROR_METHOD_NOT_FOUND, ERROR_INTERNAL, StdioTransport, HttpTransport, HttpTransportGetSseNotSupportedError, McpError, SseParser, JsonRpcMessageLayer2;
|
|
846
|
+
var init_internal = __esm({
|
|
847
|
+
"packages/tiny-mcp-client/src/internal.ts"() {
|
|
848
|
+
"use strict";
|
|
849
|
+
MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
850
|
+
McpClient = class {
|
|
851
|
+
currentState = "disconnected";
|
|
852
|
+
currentServerCapabilities = null;
|
|
853
|
+
currentServerInfo = null;
|
|
854
|
+
currentInstructions;
|
|
855
|
+
options;
|
|
856
|
+
transport = null;
|
|
857
|
+
messageLayer = null;
|
|
858
|
+
constructor(options) {
|
|
859
|
+
this.options = options;
|
|
860
|
+
}
|
|
861
|
+
get state() {
|
|
862
|
+
return this.currentState;
|
|
863
|
+
}
|
|
864
|
+
get serverCapabilities() {
|
|
865
|
+
return this.currentServerCapabilities;
|
|
866
|
+
}
|
|
867
|
+
get serverInfo() {
|
|
868
|
+
return this.currentServerInfo;
|
|
869
|
+
}
|
|
870
|
+
get instructions() {
|
|
871
|
+
return this.currentInstructions;
|
|
872
|
+
}
|
|
873
|
+
getMessageLayerOrThrow() {
|
|
874
|
+
if (this.currentState === "disconnected") {
|
|
875
|
+
throw new Error("MCP client is disconnected");
|
|
876
|
+
}
|
|
877
|
+
if (this.currentState === "closed") {
|
|
878
|
+
throw new Error("MCP client is closed");
|
|
879
|
+
}
|
|
880
|
+
if (this.messageLayer === null) {
|
|
881
|
+
throw new Error("MCP client is disconnected");
|
|
882
|
+
}
|
|
883
|
+
return this.messageLayer;
|
|
884
|
+
}
|
|
885
|
+
async connect(transport) {
|
|
886
|
+
if (this.currentState !== "disconnected" && this.currentState !== "closed") {
|
|
887
|
+
throw new Error("MCP client is already connected");
|
|
888
|
+
}
|
|
889
|
+
const transportClosedReason = transport.closed.then((closedEvent) => closedEvent.reason).catch(
|
|
890
|
+
(error) => error instanceof Error ? error : new Error(String(error))
|
|
891
|
+
);
|
|
892
|
+
const messageLayer = new JsonRpcMessageLayer2(
|
|
893
|
+
transport.readable,
|
|
894
|
+
transport.writable,
|
|
895
|
+
3e4,
|
|
896
|
+
transportClosedReason
|
|
897
|
+
);
|
|
898
|
+
const {
|
|
899
|
+
onSamplingRequest,
|
|
900
|
+
onRootsList,
|
|
901
|
+
onToolsChanged,
|
|
902
|
+
onResourcesChanged,
|
|
903
|
+
onResourceUpdated,
|
|
904
|
+
onPromptsChanged,
|
|
905
|
+
onLog,
|
|
906
|
+
onProgress
|
|
907
|
+
} = this.options;
|
|
908
|
+
messageLayer.onRequest("ping", () => ({}));
|
|
909
|
+
if (onSamplingRequest !== void 0) {
|
|
910
|
+
messageLayer.onRequest(
|
|
911
|
+
"sampling/createMessage",
|
|
912
|
+
(params) => onSamplingRequest(params)
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
if (onRootsList !== void 0) {
|
|
916
|
+
messageLayer.onRequest("roots/list", async () => ({
|
|
917
|
+
roots: await onRootsList()
|
|
918
|
+
}));
|
|
919
|
+
}
|
|
920
|
+
messageLayer.onNotification("notifications/tools/list_changed", async () => {
|
|
921
|
+
if (onToolsChanged === void 0) {
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
await onToolsChanged();
|
|
925
|
+
});
|
|
926
|
+
messageLayer.onNotification("notifications/resources/list_changed", async () => {
|
|
927
|
+
if (onResourcesChanged === void 0) {
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
await onResourcesChanged();
|
|
931
|
+
});
|
|
932
|
+
messageLayer.onNotification("notifications/resources/updated", async (params) => {
|
|
933
|
+
if (onResourceUpdated === void 0) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
if (typeof params !== "object" || params === null || Array.isArray(params)) {
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
const { uri } = params;
|
|
940
|
+
if (typeof uri !== "string") {
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
await onResourceUpdated(uri);
|
|
944
|
+
});
|
|
945
|
+
messageLayer.onNotification("notifications/prompts/list_changed", async () => {
|
|
946
|
+
if (onPromptsChanged === void 0) {
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
await onPromptsChanged();
|
|
950
|
+
});
|
|
951
|
+
messageLayer.onNotification("notifications/message", async (params) => {
|
|
952
|
+
if (onLog === void 0 || !isObjectRecord3(params) || !isLogLevel(params.level)) {
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
if (!hasOwn2(params, "data")) {
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
const message = {
|
|
959
|
+
level: params.level,
|
|
960
|
+
data: params.data
|
|
961
|
+
};
|
|
962
|
+
if (params.logger !== void 0) {
|
|
963
|
+
if (typeof params.logger !== "string") {
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
message.logger = params.logger;
|
|
967
|
+
}
|
|
968
|
+
await onLog(message);
|
|
969
|
+
});
|
|
970
|
+
messageLayer.onNotification("notifications/progress", async (params) => {
|
|
971
|
+
if (onProgress === void 0 || !isObjectRecord3(params)) {
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
const { progressToken, progress } = params;
|
|
975
|
+
if (!isRequestId2(progressToken) || typeof progress !== "number") {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
const progressParams = {
|
|
979
|
+
progressToken,
|
|
980
|
+
progress
|
|
981
|
+
};
|
|
982
|
+
if (params.total !== void 0) {
|
|
983
|
+
if (typeof params.total !== "number") {
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
progressParams.total = params.total;
|
|
987
|
+
}
|
|
988
|
+
if (params.message !== void 0) {
|
|
989
|
+
if (typeof params.message !== "string") {
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
progressParams.message = params.message;
|
|
993
|
+
}
|
|
994
|
+
await onProgress(progressParams);
|
|
995
|
+
});
|
|
996
|
+
messageLayer.onNotification("notifications/cancelled", () => void 0);
|
|
997
|
+
this.transport = transport;
|
|
998
|
+
this.messageLayer = messageLayer;
|
|
999
|
+
this.currentState = "initializing";
|
|
1000
|
+
transport.closed.then((closedEvent) => {
|
|
1001
|
+
if (this.transport !== transport) {
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
this.messageLayer?.dispose(closedEvent.reason);
|
|
1005
|
+
this.messageLayer = null;
|
|
1006
|
+
this.transport = null;
|
|
1007
|
+
this.currentState = "closed";
|
|
1008
|
+
}).catch((error) => {
|
|
1009
|
+
if (this.transport !== transport) {
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
const reason = error instanceof Error ? error : new Error(String(error));
|
|
1013
|
+
this.messageLayer?.dispose(reason);
|
|
1014
|
+
this.messageLayer = null;
|
|
1015
|
+
this.transport = null;
|
|
1016
|
+
this.currentState = "closed";
|
|
1017
|
+
});
|
|
1018
|
+
const capabilities = {
|
|
1019
|
+
...this.options.capabilities ?? {}
|
|
1020
|
+
};
|
|
1021
|
+
if (onSamplingRequest !== void 0 && capabilities.sampling === void 0) {
|
|
1022
|
+
capabilities.sampling = {};
|
|
1023
|
+
}
|
|
1024
|
+
if (onRootsList !== void 0) {
|
|
1025
|
+
capabilities.roots = {
|
|
1026
|
+
...capabilities.roots ?? {}
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
const initializeResult = await messageLayer.sendRequest("initialize", {
|
|
1030
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
1031
|
+
clientInfo: this.options.clientInfo,
|
|
1032
|
+
capabilities
|
|
1033
|
+
});
|
|
1034
|
+
if (initializeResult.protocolVersion !== MCP_PROTOCOL_VERSION) {
|
|
1035
|
+
throw new McpError(
|
|
1036
|
+
ERROR_INVALID_REQUEST,
|
|
1037
|
+
`Unsupported protocol version: ${initializeResult.protocolVersion}`
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
this.currentServerCapabilities = initializeResult.capabilities;
|
|
1041
|
+
this.currentServerInfo = initializeResult.serverInfo;
|
|
1042
|
+
this.currentInstructions = initializeResult.instructions;
|
|
1043
|
+
messageLayer.sendNotification("notifications/initialized");
|
|
1044
|
+
this.currentState = "ready";
|
|
1045
|
+
return initializeResult;
|
|
1046
|
+
}
|
|
1047
|
+
getServerCapabilitiesOrThrow() {
|
|
1048
|
+
if (this.currentServerCapabilities === null) {
|
|
1049
|
+
throw new Error("MCP client has not completed initialization");
|
|
1050
|
+
}
|
|
1051
|
+
return this.currentServerCapabilities;
|
|
1052
|
+
}
|
|
1053
|
+
async listTools(params = {}) {
|
|
1054
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1055
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1056
|
+
if (serverCapabilities.tools === void 0) {
|
|
1057
|
+
throw new Error("Server does not support tools");
|
|
1058
|
+
}
|
|
1059
|
+
const requestParams = params.cursor === void 0 ? void 0 : { cursor: params.cursor };
|
|
1060
|
+
return await messageLayer.sendRequest("tools/list", requestParams);
|
|
1061
|
+
}
|
|
1062
|
+
async callTool(params, options = {}) {
|
|
1063
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1064
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1065
|
+
if (serverCapabilities.tools === void 0) {
|
|
1066
|
+
throw new Error("Server does not support tools");
|
|
1067
|
+
}
|
|
1068
|
+
const requestParams = options.progressToken === void 0 ? params : {
|
|
1069
|
+
...params,
|
|
1070
|
+
_meta: {
|
|
1071
|
+
progressToken: options.progressToken
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
let requestId;
|
|
1075
|
+
const requestPromise = messageLayer.sendRequest("tools/call", requestParams, {
|
|
1076
|
+
onRequestId: (nextRequestId) => {
|
|
1077
|
+
requestId = nextRequestId;
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
if (options.signal === void 0) {
|
|
1081
|
+
return await requestPromise;
|
|
1082
|
+
}
|
|
1083
|
+
const signal = options.signal;
|
|
1084
|
+
let abortListener;
|
|
1085
|
+
const abortPromise = new Promise((_, reject) => {
|
|
1086
|
+
const rejectWithAbortReason = () => {
|
|
1087
|
+
if (requestId !== void 0) {
|
|
1088
|
+
messageLayer.sendNotification("notifications/cancelled", { requestId });
|
|
1089
|
+
}
|
|
1090
|
+
reject(signal.reason);
|
|
1091
|
+
};
|
|
1092
|
+
abortListener = rejectWithAbortReason;
|
|
1093
|
+
signal.addEventListener("abort", abortListener, { once: true });
|
|
1094
|
+
if (signal.aborted) {
|
|
1095
|
+
signal.removeEventListener("abort", abortListener);
|
|
1096
|
+
rejectWithAbortReason();
|
|
1097
|
+
}
|
|
1098
|
+
});
|
|
1099
|
+
try {
|
|
1100
|
+
return await Promise.race([requestPromise, abortPromise]);
|
|
1101
|
+
} finally {
|
|
1102
|
+
if (abortListener !== void 0) {
|
|
1103
|
+
signal.removeEventListener("abort", abortListener);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
async listResources(params = {}) {
|
|
1108
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1109
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1110
|
+
if (serverCapabilities.resources === void 0) {
|
|
1111
|
+
throw new Error("Server does not support resources");
|
|
1112
|
+
}
|
|
1113
|
+
const requestParams = params.cursor === void 0 ? void 0 : { cursor: params.cursor };
|
|
1114
|
+
return await messageLayer.sendRequest("resources/list", requestParams);
|
|
1115
|
+
}
|
|
1116
|
+
async listResourceTemplates(params = {}) {
|
|
1117
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1118
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1119
|
+
if (serverCapabilities.resources === void 0) {
|
|
1120
|
+
throw new Error("Server does not support resources");
|
|
1121
|
+
}
|
|
1122
|
+
const requestParams = params.cursor === void 0 ? void 0 : { cursor: params.cursor };
|
|
1123
|
+
return await messageLayer.sendRequest("resources/templates/list", requestParams);
|
|
1124
|
+
}
|
|
1125
|
+
async readResource(params) {
|
|
1126
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1127
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1128
|
+
if (serverCapabilities.resources === void 0) {
|
|
1129
|
+
throw new Error("Server does not support resources");
|
|
1130
|
+
}
|
|
1131
|
+
return await messageLayer.sendRequest("resources/read", params);
|
|
1132
|
+
}
|
|
1133
|
+
async subscribe(uri) {
|
|
1134
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1135
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1136
|
+
if (serverCapabilities.resources?.subscribe !== true) {
|
|
1137
|
+
throw new Error("Server does not support resource subscriptions");
|
|
1138
|
+
}
|
|
1139
|
+
await messageLayer.sendRequest("resources/subscribe", { uri });
|
|
1140
|
+
}
|
|
1141
|
+
async unsubscribe(uri) {
|
|
1142
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1143
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1144
|
+
if (serverCapabilities.resources?.subscribe !== true) {
|
|
1145
|
+
throw new Error("Server does not support resource subscriptions");
|
|
1146
|
+
}
|
|
1147
|
+
await messageLayer.sendRequest("resources/unsubscribe", { uri });
|
|
1148
|
+
}
|
|
1149
|
+
async listPrompts(params = {}) {
|
|
1150
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1151
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1152
|
+
if (serverCapabilities.prompts === void 0) {
|
|
1153
|
+
throw new Error("Server does not support prompts");
|
|
1154
|
+
}
|
|
1155
|
+
const requestParams = params.cursor === void 0 ? void 0 : { cursor: params.cursor };
|
|
1156
|
+
return await messageLayer.sendRequest("prompts/list", requestParams);
|
|
1157
|
+
}
|
|
1158
|
+
async getPrompt(params) {
|
|
1159
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1160
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1161
|
+
if (serverCapabilities.prompts === void 0) {
|
|
1162
|
+
throw new Error("Server does not support prompts");
|
|
1163
|
+
}
|
|
1164
|
+
return await messageLayer.sendRequest("prompts/get", params);
|
|
1165
|
+
}
|
|
1166
|
+
async complete(params) {
|
|
1167
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1168
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1169
|
+
if (serverCapabilities.completions === void 0) {
|
|
1170
|
+
throw new Error("Server does not support completions");
|
|
1171
|
+
}
|
|
1172
|
+
return await messageLayer.sendRequest("completion/complete", params);
|
|
1173
|
+
}
|
|
1174
|
+
async setLogLevel(level) {
|
|
1175
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1176
|
+
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
1177
|
+
if (serverCapabilities.logging === void 0) {
|
|
1178
|
+
throw new Error("Server does not support logging");
|
|
1179
|
+
}
|
|
1180
|
+
await messageLayer.sendRequest("logging/setLevel", { level });
|
|
1181
|
+
}
|
|
1182
|
+
async cancel(requestId, reason) {
|
|
1183
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1184
|
+
const params = { requestId };
|
|
1185
|
+
if (reason !== void 0) {
|
|
1186
|
+
params.reason = reason;
|
|
1187
|
+
}
|
|
1188
|
+
messageLayer.sendNotification("notifications/cancelled", params);
|
|
1189
|
+
}
|
|
1190
|
+
async sendRootsChanged() {
|
|
1191
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1192
|
+
messageLayer.sendNotification("notifications/roots/list_changed");
|
|
1193
|
+
}
|
|
1194
|
+
async ping() {
|
|
1195
|
+
const messageLayer = this.getMessageLayerOrThrow();
|
|
1196
|
+
await messageLayer.sendRequest("ping");
|
|
1197
|
+
}
|
|
1198
|
+
async close() {
|
|
1199
|
+
if (this.currentState === "closed") {
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
const closeError = new Error("MCP client closed");
|
|
1203
|
+
this.messageLayer?.dispose(closeError);
|
|
1204
|
+
this.transport?.dispose(closeError);
|
|
1205
|
+
this.messageLayer = null;
|
|
1206
|
+
this.transport = null;
|
|
1207
|
+
this.currentState = "closed";
|
|
1208
|
+
}
|
|
1209
|
+
};
|
|
1210
|
+
ERROR_PARSE = -32700;
|
|
1211
|
+
ERROR_INVALID_REQUEST = -32600;
|
|
1212
|
+
ERROR_METHOD_NOT_FOUND = -32601;
|
|
1213
|
+
ERROR_INTERNAL = -32603;
|
|
1214
|
+
StdioTransport = class _StdioTransport {
|
|
1215
|
+
readable;
|
|
1216
|
+
writable;
|
|
1217
|
+
closed;
|
|
1218
|
+
child;
|
|
1219
|
+
disposed = false;
|
|
1220
|
+
stderrOutput = "";
|
|
1221
|
+
static STDERR_MAX_LENGTH = 65536;
|
|
1222
|
+
constructor({
|
|
1223
|
+
command,
|
|
1224
|
+
args = [],
|
|
1225
|
+
cwd,
|
|
1226
|
+
env,
|
|
1227
|
+
spawn: spawnProcess = defaultStdioSpawn
|
|
1228
|
+
}) {
|
|
1229
|
+
this.child = spawnProcess(command, args, {
|
|
1230
|
+
cwd,
|
|
1231
|
+
env,
|
|
1232
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1233
|
+
});
|
|
1234
|
+
const child = this.child;
|
|
1235
|
+
this.readable = child.stdout;
|
|
1236
|
+
this.writable = child.stdin;
|
|
1237
|
+
child.stderr.on("data", (chunk) => {
|
|
1238
|
+
this.stderrOutput += chunkToString2(chunk);
|
|
1239
|
+
if (this.stderrOutput.length > _StdioTransport.STDERR_MAX_LENGTH) {
|
|
1240
|
+
this.stderrOutput = this.stderrOutput.slice(-_StdioTransport.STDERR_MAX_LENGTH);
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
this.closed = new Promise((resolve) => {
|
|
1244
|
+
let settled = false;
|
|
1245
|
+
const resolveClosed = (event) => {
|
|
1246
|
+
if (settled) {
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
settled = true;
|
|
1250
|
+
resolve(event);
|
|
1251
|
+
};
|
|
1252
|
+
child.once("exit", (code, signal) => {
|
|
1253
|
+
const closedEvent = {
|
|
1254
|
+
reason: new Error("Stdio transport process exited")
|
|
1255
|
+
};
|
|
1256
|
+
if (code !== null) {
|
|
1257
|
+
closedEvent.code = code;
|
|
1258
|
+
}
|
|
1259
|
+
if (signal !== null) {
|
|
1260
|
+
closedEvent.signal = signal;
|
|
1261
|
+
}
|
|
1262
|
+
resolveClosed(closedEvent);
|
|
1263
|
+
});
|
|
1264
|
+
child.once("error", (error) => {
|
|
1265
|
+
const closedEvent = {
|
|
1266
|
+
reason: error instanceof Error ? error : new Error(String(error))
|
|
1267
|
+
};
|
|
1268
|
+
if (child.exitCode !== null) {
|
|
1269
|
+
closedEvent.code = child.exitCode;
|
|
1270
|
+
}
|
|
1271
|
+
if (child.signalCode !== null) {
|
|
1272
|
+
closedEvent.signal = child.signalCode;
|
|
1273
|
+
}
|
|
1274
|
+
resolveClosed(closedEvent);
|
|
1275
|
+
});
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
getStderrOutput() {
|
|
1279
|
+
return this.stderrOutput;
|
|
1280
|
+
}
|
|
1281
|
+
dispose(reason = new Error("Stdio transport disposed")) {
|
|
1282
|
+
void reason;
|
|
1283
|
+
if (this.disposed) {
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
this.disposed = true;
|
|
1287
|
+
if (!this.child.stdin.destroyed && !this.child.stdin.writableEnded) {
|
|
1288
|
+
this.child.stdin.end();
|
|
1289
|
+
}
|
|
1290
|
+
if (this.child.exitCode === null && this.child.signalCode === null && !this.child.killed) {
|
|
1291
|
+
this.child.kill("SIGTERM");
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
HttpTransport = class {
|
|
1296
|
+
readable;
|
|
1297
|
+
writable;
|
|
1298
|
+
closed;
|
|
1299
|
+
url;
|
|
1300
|
+
headers;
|
|
1301
|
+
fetchImpl;
|
|
1302
|
+
readStream = new PassThrough();
|
|
1303
|
+
writeStream = new PassThrough();
|
|
1304
|
+
resolveClosed;
|
|
1305
|
+
sessionId;
|
|
1306
|
+
lastEventId;
|
|
1307
|
+
getSseStreamStarted = false;
|
|
1308
|
+
disposed = false;
|
|
1309
|
+
inFlightFetchAbortControllers = /* @__PURE__ */ new Set();
|
|
1310
|
+
openSseReaders = /* @__PURE__ */ new Set();
|
|
1311
|
+
constructor({
|
|
1312
|
+
url,
|
|
1313
|
+
headers = {},
|
|
1314
|
+
fetch: fetchImpl = defaultHttpTransportFetch
|
|
1315
|
+
}) {
|
|
1316
|
+
this.url = url;
|
|
1317
|
+
this.headers = headers;
|
|
1318
|
+
this.fetchImpl = fetchImpl;
|
|
1319
|
+
this.readable = this.readStream;
|
|
1320
|
+
this.writable = this.writeStream;
|
|
1321
|
+
this.closed = new Promise((resolve) => {
|
|
1322
|
+
this.resolveClosed = resolve;
|
|
1323
|
+
});
|
|
1324
|
+
this.readStream.once("error", (error) => {
|
|
1325
|
+
this.dispose(error instanceof Error ? error : new Error(String(error)));
|
|
1326
|
+
});
|
|
1327
|
+
this.writeStream.once("error", (error) => {
|
|
1328
|
+
this.dispose(error instanceof Error ? error : new Error(String(error)));
|
|
1329
|
+
});
|
|
1330
|
+
this.consumeWrittenLines().catch((error) => {
|
|
1331
|
+
this.dispose(error instanceof Error ? error : new Error(String(error)));
|
|
1332
|
+
});
|
|
1333
|
+
}
|
|
1334
|
+
dispose(reason = new Error("HTTP transport disposed")) {
|
|
1335
|
+
if (this.disposed) {
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
this.disposed = true;
|
|
1339
|
+
this.abortInFlightFetches();
|
|
1340
|
+
this.cancelOpenSseReaders();
|
|
1341
|
+
this.terminateSession();
|
|
1342
|
+
if (!this.writeStream.destroyed && !this.writeStream.writableEnded) {
|
|
1343
|
+
this.writeStream.end();
|
|
1344
|
+
}
|
|
1345
|
+
if (!this.readStream.destroyed && !this.readStream.writableEnded) {
|
|
1346
|
+
this.readStream.end();
|
|
1347
|
+
}
|
|
1348
|
+
const resolveClosed = this.resolveClosed;
|
|
1349
|
+
this.resolveClosed = void 0;
|
|
1350
|
+
resolveClosed?.({ reason });
|
|
1351
|
+
}
|
|
1352
|
+
abortInFlightFetches() {
|
|
1353
|
+
for (const abortController of this.inFlightFetchAbortControllers) {
|
|
1354
|
+
abortController.abort();
|
|
1355
|
+
}
|
|
1356
|
+
this.inFlightFetchAbortControllers.clear();
|
|
1357
|
+
}
|
|
1358
|
+
cancelOpenSseReaders() {
|
|
1359
|
+
for (const reader of this.openSseReaders) {
|
|
1360
|
+
void reader.cancel().catch(() => void 0);
|
|
1361
|
+
}
|
|
1362
|
+
this.openSseReaders.clear();
|
|
1363
|
+
}
|
|
1364
|
+
async fetchWithAbort(input, init) {
|
|
1365
|
+
const abortController = new AbortController();
|
|
1366
|
+
this.inFlightFetchAbortControllers.add(abortController);
|
|
1367
|
+
try {
|
|
1368
|
+
return await this.fetchImpl(input, {
|
|
1369
|
+
...init,
|
|
1370
|
+
signal: abortController.signal
|
|
1371
|
+
});
|
|
1372
|
+
} finally {
|
|
1373
|
+
this.inFlightFetchAbortControllers.delete(abortController);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
async consumeWrittenLines() {
|
|
1377
|
+
for await (const line of readLines2(this.writeStream)) {
|
|
1378
|
+
if (this.disposed || line.length === 0) {
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1381
|
+
const hasSessionId = this.sessionId !== void 0;
|
|
1382
|
+
const response = await this.fetchWithAbort(this.url, {
|
|
1383
|
+
method: "POST",
|
|
1384
|
+
headers: this.createPostHeaders(),
|
|
1385
|
+
body: line
|
|
1386
|
+
});
|
|
1387
|
+
if (hasSessionId && response.status === 404) {
|
|
1388
|
+
this.sessionId = void 0;
|
|
1389
|
+
this.dispose(new Error("HTTP transport session expired (404 response)"));
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
await this.throwForPostHttpError(response);
|
|
1393
|
+
this.captureSessionId(response);
|
|
1394
|
+
this.maybeOpenGetSseStream();
|
|
1395
|
+
await this.forwardResponseMessages(response);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
createPostHeaders() {
|
|
1399
|
+
const headers = new Headers(this.headers);
|
|
1400
|
+
headers.set("Accept", "application/json, text/event-stream");
|
|
1401
|
+
headers.set("Content-Type", "application/json");
|
|
1402
|
+
if (this.sessionId !== void 0) {
|
|
1403
|
+
headers.set("Mcp-Session-Id", this.sessionId);
|
|
1404
|
+
}
|
|
1405
|
+
return headers;
|
|
1406
|
+
}
|
|
1407
|
+
createGetHeaders() {
|
|
1408
|
+
const headers = new Headers(this.headers);
|
|
1409
|
+
headers.set("Accept", "text/event-stream");
|
|
1410
|
+
if (this.sessionId !== void 0) {
|
|
1411
|
+
headers.set("Mcp-Session-Id", this.sessionId);
|
|
1412
|
+
}
|
|
1413
|
+
if (this.lastEventId !== void 0) {
|
|
1414
|
+
headers.set("Last-Event-ID", this.lastEventId);
|
|
1415
|
+
}
|
|
1416
|
+
return headers;
|
|
1417
|
+
}
|
|
1418
|
+
createDeleteHeaders(sessionId) {
|
|
1419
|
+
const headers = new Headers(this.headers);
|
|
1420
|
+
headers.set("Mcp-Session-Id", sessionId);
|
|
1421
|
+
return headers;
|
|
1422
|
+
}
|
|
1423
|
+
captureSessionId(response) {
|
|
1424
|
+
const sessionId = response.headers.get("Mcp-Session-Id");
|
|
1425
|
+
if (sessionId === null || sessionId.length === 0) {
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
this.sessionId = sessionId;
|
|
1429
|
+
}
|
|
1430
|
+
maybeOpenGetSseStream() {
|
|
1431
|
+
if (this.disposed || this.sessionId === void 0 || this.getSseStreamStarted) {
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
this.getSseStreamStarted = true;
|
|
1435
|
+
this.consumeGetSseStream().catch((error) => {
|
|
1436
|
+
if (error instanceof HttpTransportGetSseNotSupportedError || this.disposed) {
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
this.dispose(error instanceof Error ? error : new Error(String(error)));
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
terminateSession() {
|
|
1443
|
+
if (this.sessionId === void 0) {
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
const sessionId = this.sessionId;
|
|
1447
|
+
this.sessionId = void 0;
|
|
1448
|
+
this.sendSessionTerminationRequest(sessionId).catch(() => void 0);
|
|
1449
|
+
}
|
|
1450
|
+
async sendSessionTerminationRequest(sessionId) {
|
|
1451
|
+
const response = await this.fetchImpl(this.url, {
|
|
1452
|
+
method: "DELETE",
|
|
1453
|
+
headers: this.createDeleteHeaders(sessionId)
|
|
1454
|
+
});
|
|
1455
|
+
if (response.status === 405) {
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
async consumeGetSseStream() {
|
|
1460
|
+
const response = await this.fetchWithAbort(this.url, {
|
|
1461
|
+
method: "GET",
|
|
1462
|
+
headers: this.createGetHeaders()
|
|
1463
|
+
});
|
|
1464
|
+
if (response.status === 405) {
|
|
1465
|
+
throw new HttpTransportGetSseNotSupportedError();
|
|
1466
|
+
}
|
|
1467
|
+
const contentType = response.headers.get("Content-Type");
|
|
1468
|
+
if (contentType === null) {
|
|
1469
|
+
return;
|
|
1470
|
+
}
|
|
1471
|
+
if (contentType.toLowerCase().includes("text/event-stream")) {
|
|
1472
|
+
await this.forwardSseResponseMessages(response);
|
|
1473
|
+
this.getSseStreamStarted = false;
|
|
1474
|
+
if (!this.disposed && this.sessionId !== void 0 && this.lastEventId !== void 0) {
|
|
1475
|
+
this.maybeOpenGetSseStream();
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
async throwForPostHttpError(response) {
|
|
1480
|
+
if (response.status < 400) {
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
const responseBody = (await response.text()).trim();
|
|
1484
|
+
const statusDescriptor = `${response.status} ${response.statusText}`.trim();
|
|
1485
|
+
const message = responseBody.length === 0 ? `HTTP transport POST failed (${statusDescriptor})` : `HTTP transport POST failed (${statusDescriptor}): ${responseBody}`;
|
|
1486
|
+
throw new Error(message);
|
|
1487
|
+
}
|
|
1488
|
+
async forwardResponseMessages(response) {
|
|
1489
|
+
if (response.status === 202) {
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
const contentType = response.headers.get("Content-Type");
|
|
1493
|
+
if (contentType === null) {
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
const normalizedContentType = contentType.toLowerCase();
|
|
1497
|
+
if (normalizedContentType.includes("text/event-stream")) {
|
|
1498
|
+
await this.forwardSseResponseMessages(response);
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
if (normalizedContentType.includes("application/json")) {
|
|
1502
|
+
await this.forwardJsonResponseMessage(response);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
async forwardSseResponseMessages(response) {
|
|
1506
|
+
if (response.body === null) {
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
const parser = new SseParser();
|
|
1510
|
+
const decoder = new TextDecoder();
|
|
1511
|
+
const reader = response.body.getReader();
|
|
1512
|
+
this.openSseReaders.add(reader);
|
|
1513
|
+
try {
|
|
1514
|
+
while (true) {
|
|
1515
|
+
const { done, value } = await reader.read();
|
|
1516
|
+
if (done) {
|
|
1517
|
+
break;
|
|
1518
|
+
}
|
|
1519
|
+
if (value === void 0) {
|
|
1520
|
+
continue;
|
|
1521
|
+
}
|
|
1522
|
+
const messages = parser.push(decoder.decode(value, { stream: true }));
|
|
1523
|
+
this.writeSseMessages(messages);
|
|
1524
|
+
this.lastEventId = parser.lastEventId;
|
|
1525
|
+
}
|
|
1526
|
+
const trailingChunk = decoder.decode();
|
|
1527
|
+
if (trailingChunk.length > 0) {
|
|
1528
|
+
this.writeSseMessages(parser.push(trailingChunk));
|
|
1529
|
+
this.lastEventId = parser.lastEventId;
|
|
1530
|
+
}
|
|
1531
|
+
this.writeSseMessages(parser.flush());
|
|
1532
|
+
this.lastEventId = parser.lastEventId;
|
|
1533
|
+
} finally {
|
|
1534
|
+
this.openSseReaders.delete(reader);
|
|
1535
|
+
reader.releaseLock();
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
async forwardJsonResponseMessage(response) {
|
|
1539
|
+
const payload = await response.text();
|
|
1540
|
+
if (payload.length === 0) {
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
const parsedPayload = JSON.parse(payload);
|
|
1544
|
+
this.writeReadableLine(JSON.stringify(parsedPayload));
|
|
1545
|
+
}
|
|
1546
|
+
writeSseMessages(messages) {
|
|
1547
|
+
for (const message of messages) {
|
|
1548
|
+
this.writeReadableLine(message.data);
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
writeReadableLine(line) {
|
|
1552
|
+
if (this.disposed || this.readStream.destroyed || this.readStream.writableEnded) {
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
this.readStream.write(`${line}
|
|
1556
|
+
`);
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
HttpTransportGetSseNotSupportedError = class extends Error {
|
|
1560
|
+
constructor() {
|
|
1561
|
+
super("HTTP transport server does not support GET SSE streams");
|
|
1562
|
+
}
|
|
1563
|
+
};
|
|
1564
|
+
McpError = class extends Error {
|
|
1565
|
+
code;
|
|
1566
|
+
constructor(code, message, data) {
|
|
1567
|
+
super(message);
|
|
1568
|
+
this.name = "McpError";
|
|
1569
|
+
this.code = code;
|
|
1570
|
+
if (data !== void 0) {
|
|
1571
|
+
this.data = data;
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
SseParser = class {
|
|
1576
|
+
buffer = "";
|
|
1577
|
+
eventType;
|
|
1578
|
+
dataLines = [];
|
|
1579
|
+
eventId = "";
|
|
1580
|
+
hasEventId = false;
|
|
1581
|
+
_lastEventId;
|
|
1582
|
+
get lastEventId() {
|
|
1583
|
+
return this._lastEventId;
|
|
1584
|
+
}
|
|
1585
|
+
push(chunk) {
|
|
1586
|
+
if (chunk.length === 0) {
|
|
1587
|
+
return [];
|
|
1588
|
+
}
|
|
1589
|
+
this.buffer += chunk;
|
|
1590
|
+
const messages = [];
|
|
1591
|
+
while (true) {
|
|
1592
|
+
const newlineIndex = this.buffer.indexOf("\n");
|
|
1593
|
+
if (newlineIndex === -1) {
|
|
1594
|
+
break;
|
|
1595
|
+
}
|
|
1596
|
+
const line = normalizeLine2(this.buffer.slice(0, newlineIndex));
|
|
1597
|
+
this.buffer = this.buffer.slice(newlineIndex + 1);
|
|
1598
|
+
this.consumeLine(line, messages);
|
|
1599
|
+
}
|
|
1600
|
+
return messages;
|
|
1601
|
+
}
|
|
1602
|
+
flush() {
|
|
1603
|
+
const messages = [];
|
|
1604
|
+
if (this.buffer.length > 0) {
|
|
1605
|
+
this.consumeLine(normalizeLine2(this.buffer), messages);
|
|
1606
|
+
this.buffer = "";
|
|
1607
|
+
}
|
|
1608
|
+
this.emitEvent(messages);
|
|
1609
|
+
return messages;
|
|
1610
|
+
}
|
|
1611
|
+
consumeLine(line, messages) {
|
|
1612
|
+
if (line.length === 0) {
|
|
1613
|
+
this.emitEvent(messages);
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
if (line.startsWith(":")) {
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
const separatorIndex = line.indexOf(":");
|
|
1620
|
+
const field = separatorIndex === -1 ? line : line.slice(0, separatorIndex);
|
|
1621
|
+
const rawValue = separatorIndex === -1 ? "" : line.slice(separatorIndex + 1);
|
|
1622
|
+
const value = rawValue.startsWith(" ") ? rawValue.slice(1) : rawValue;
|
|
1623
|
+
if (field === "event") {
|
|
1624
|
+
this.eventType = value;
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
if (field === "data") {
|
|
1628
|
+
this.dataLines.push(value);
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
if (field === "id") {
|
|
1632
|
+
if (value.includes("\0")) {
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
this.eventId = value;
|
|
1636
|
+
this.hasEventId = true;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
emitEvent(messages) {
|
|
1640
|
+
const eventType = this.eventType ?? "message";
|
|
1641
|
+
if (this.hasEventId) {
|
|
1642
|
+
this._lastEventId = this.eventId;
|
|
1643
|
+
}
|
|
1644
|
+
if (this.dataLines.length === 0 || eventType !== "message") {
|
|
1645
|
+
this.resetEvent();
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
const message = {
|
|
1649
|
+
data: this.dataLines.join("\n")
|
|
1650
|
+
};
|
|
1651
|
+
if (this.hasEventId) {
|
|
1652
|
+
message.id = this.eventId;
|
|
1653
|
+
}
|
|
1654
|
+
messages.push(message);
|
|
1655
|
+
this.resetEvent();
|
|
1656
|
+
}
|
|
1657
|
+
resetEvent() {
|
|
1658
|
+
this.eventType = void 0;
|
|
1659
|
+
this.dataLines = [];
|
|
1660
|
+
this.eventId = "";
|
|
1661
|
+
this.hasEventId = false;
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
JsonRpcMessageLayer2 = class {
|
|
1665
|
+
requestTimeoutMs;
|
|
1666
|
+
input;
|
|
1667
|
+
output;
|
|
1668
|
+
inputClosedReason;
|
|
1669
|
+
nextRequestId = 1;
|
|
1670
|
+
disposedError;
|
|
1671
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
1672
|
+
activeIncomingRequests = /* @__PURE__ */ new Map();
|
|
1673
|
+
requestHandlers = /* @__PURE__ */ new Map();
|
|
1674
|
+
notificationHandlers = /* @__PURE__ */ new Map();
|
|
1675
|
+
constructor(input, output, requestTimeoutMs = 3e4, inputClosedReason) {
|
|
1676
|
+
if (!Number.isFinite(requestTimeoutMs) || requestTimeoutMs < 0) {
|
|
1677
|
+
throw new Error("requestTimeoutMs must be a non-negative finite number");
|
|
1678
|
+
}
|
|
1679
|
+
this.input = input;
|
|
1680
|
+
this.output = output;
|
|
1681
|
+
this.inputClosedReason = inputClosedReason;
|
|
1682
|
+
this.requestTimeoutMs = requestTimeoutMs;
|
|
1683
|
+
this.consumeInput().catch(() => void 0);
|
|
1684
|
+
}
|
|
1685
|
+
sendNotification(method, params) {
|
|
1686
|
+
if (this.disposedError !== void 0) {
|
|
1687
|
+
throw this.disposedError;
|
|
1688
|
+
}
|
|
1689
|
+
const message = {
|
|
1690
|
+
jsonrpc: "2.0",
|
|
1691
|
+
method
|
|
1692
|
+
};
|
|
1693
|
+
if (params !== void 0) {
|
|
1694
|
+
message.params = params;
|
|
1695
|
+
}
|
|
1696
|
+
this.output.write(serializeJsonRpcMessage2(message));
|
|
1697
|
+
}
|
|
1698
|
+
onRequest(method, handler) {
|
|
1699
|
+
this.requestHandlers.set(method, handler);
|
|
1700
|
+
}
|
|
1701
|
+
onNotification(method, handler) {
|
|
1702
|
+
this.notificationHandlers.set(method, handler);
|
|
1703
|
+
}
|
|
1704
|
+
sendRequest(method, params, options = {}) {
|
|
1705
|
+
if (this.disposedError !== void 0) {
|
|
1706
|
+
throw this.disposedError;
|
|
1707
|
+
}
|
|
1708
|
+
const id = this.nextRequestId;
|
|
1709
|
+
this.nextRequestId += 1;
|
|
1710
|
+
const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;
|
|
1711
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
|
1712
|
+
throw new Error("timeoutMs must be a non-negative finite number");
|
|
1713
|
+
}
|
|
1714
|
+
if (options.onRequestId !== void 0) {
|
|
1715
|
+
options.onRequestId(id);
|
|
1716
|
+
}
|
|
1717
|
+
const message = {
|
|
1718
|
+
jsonrpc: "2.0",
|
|
1719
|
+
id,
|
|
1720
|
+
method
|
|
1721
|
+
};
|
|
1722
|
+
if (params !== void 0) {
|
|
1723
|
+
message.params = params;
|
|
1724
|
+
}
|
|
1725
|
+
return new Promise((resolve, reject) => {
|
|
1726
|
+
const timeout = setTimeout(() => {
|
|
1727
|
+
this.pendingRequests.delete(id);
|
|
1728
|
+
reject(new Error(`JSON-RPC request "${method}" timed out after ${timeoutMs}ms`));
|
|
1729
|
+
}, timeoutMs);
|
|
1730
|
+
this.pendingRequests.set(id, { resolve, reject, timeout });
|
|
1731
|
+
try {
|
|
1732
|
+
this.output.write(serializeJsonRpcMessage2(message));
|
|
1733
|
+
} catch (error) {
|
|
1734
|
+
clearTimeout(timeout);
|
|
1735
|
+
this.pendingRequests.delete(id);
|
|
1736
|
+
reject(error);
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
dispose(reason = new Error("JSON-RPC message layer disposed")) {
|
|
1741
|
+
if (this.disposedError !== void 0) {
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
this.disposedError = reason;
|
|
1745
|
+
for (const pending of this.pendingRequests.values()) {
|
|
1746
|
+
clearTimeout(pending.timeout);
|
|
1747
|
+
pending.reject(reason);
|
|
1748
|
+
}
|
|
1749
|
+
this.pendingRequests.clear();
|
|
1750
|
+
this.activeIncomingRequests.clear();
|
|
1751
|
+
}
|
|
1752
|
+
async consumeInput() {
|
|
1753
|
+
try {
|
|
1754
|
+
for await (const line of readLines2(this.input)) {
|
|
1755
|
+
if (this.disposedError !== void 0) {
|
|
1756
|
+
break;
|
|
1757
|
+
}
|
|
1758
|
+
if (line.length === 0) {
|
|
1759
|
+
continue;
|
|
1760
|
+
}
|
|
1761
|
+
let parsedLine;
|
|
1762
|
+
try {
|
|
1763
|
+
parsedLine = JSON.parse(line);
|
|
1764
|
+
} catch {
|
|
1765
|
+
await this.processParsedMessage({
|
|
1766
|
+
type: "invalid",
|
|
1767
|
+
id: null,
|
|
1768
|
+
error: parseError2()
|
|
1769
|
+
});
|
|
1770
|
+
continue;
|
|
1771
|
+
}
|
|
1772
|
+
if (Array.isArray(parsedLine)) {
|
|
1773
|
+
for (const message of parsedLine) {
|
|
1774
|
+
if (this.disposedError !== void 0) {
|
|
1775
|
+
break;
|
|
1776
|
+
}
|
|
1777
|
+
await this.processParsedMessage(parseJsonRpcPayload(message));
|
|
1778
|
+
}
|
|
1779
|
+
continue;
|
|
1780
|
+
}
|
|
1781
|
+
await this.processParsedMessage(parseJsonRpcPayload(parsedLine));
|
|
1782
|
+
}
|
|
1783
|
+
} catch (error) {
|
|
1784
|
+
if (this.disposedError === void 0) {
|
|
1785
|
+
this.dispose(
|
|
1786
|
+
error instanceof Error ? error : new Error(`JSON-RPC input stream failed: ${String(error)}`)
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
return;
|
|
1790
|
+
}
|
|
1791
|
+
if (this.disposedError === void 0) {
|
|
1792
|
+
const streamClosedReason = await this.resolveInputStreamClosedReason();
|
|
1793
|
+
if (this.disposedError === void 0) {
|
|
1794
|
+
this.dispose(streamClosedReason);
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
async resolveInputStreamClosedReason() {
|
|
1799
|
+
const streamClosedError = new Error("JSON-RPC input stream closed");
|
|
1800
|
+
if (this.inputClosedReason === void 0) {
|
|
1801
|
+
return streamClosedError;
|
|
1802
|
+
}
|
|
1803
|
+
try {
|
|
1804
|
+
return await Promise.race([
|
|
1805
|
+
this.inputClosedReason,
|
|
1806
|
+
new Promise((resolve) => {
|
|
1807
|
+
setTimeout(() => {
|
|
1808
|
+
resolve(streamClosedError);
|
|
1809
|
+
}, 50);
|
|
1810
|
+
})
|
|
1811
|
+
]);
|
|
1812
|
+
} catch {
|
|
1813
|
+
return streamClosedError;
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
async processParsedMessage(parsed) {
|
|
1817
|
+
if (parsed.type === "request") {
|
|
1818
|
+
const handler = this.requestHandlers.get(parsed.message.method);
|
|
1819
|
+
if (handler === void 0) {
|
|
1820
|
+
this.output.write(
|
|
1821
|
+
serializeJsonRpcMessage2({
|
|
1822
|
+
jsonrpc: "2.0",
|
|
1823
|
+
id: parsed.message.id,
|
|
1824
|
+
error: {
|
|
1825
|
+
code: ERROR_METHOD_NOT_FOUND,
|
|
1826
|
+
message: `Method not found: ${parsed.message.method}`
|
|
1827
|
+
}
|
|
1828
|
+
})
|
|
1829
|
+
);
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
this.handleIncomingRequest(parsed.message, handler);
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
if (parsed.type === "notification") {
|
|
1836
|
+
if (parsed.message.method === "notifications/cancelled") {
|
|
1837
|
+
this.handleCancellationNotification(parsed.message.params);
|
|
1838
|
+
}
|
|
1839
|
+
const handler = this.notificationHandlers.get(parsed.message.method);
|
|
1840
|
+
if (handler === void 0) {
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
try {
|
|
1844
|
+
await handler(parsed.message.params, {
|
|
1845
|
+
method: parsed.message.method
|
|
1846
|
+
});
|
|
1847
|
+
} catch {
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
return;
|
|
1851
|
+
}
|
|
1852
|
+
if (parsed.type === "invalid") {
|
|
1853
|
+
const errorResponse = {
|
|
1854
|
+
jsonrpc: "2.0",
|
|
1855
|
+
id: parsed.id,
|
|
1856
|
+
error: {
|
|
1857
|
+
code: parsed.error.code,
|
|
1858
|
+
message: parsed.error.message
|
|
1859
|
+
}
|
|
1860
|
+
};
|
|
1861
|
+
if (parsed.error.data !== void 0) {
|
|
1862
|
+
errorResponse.error.data = parsed.error.data;
|
|
1863
|
+
}
|
|
1864
|
+
this.output.write(`${JSON.stringify(errorResponse)}
|
|
1865
|
+
`);
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
if (parsed.type !== "response") {
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
const pending = this.pendingRequests.get(parsed.message.id);
|
|
1872
|
+
if (pending === void 0) {
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
this.pendingRequests.delete(parsed.message.id);
|
|
1876
|
+
clearTimeout(pending.timeout);
|
|
1877
|
+
if ("result" in parsed.message) {
|
|
1878
|
+
pending.resolve(parsed.message.result);
|
|
1879
|
+
return;
|
|
1880
|
+
}
|
|
1881
|
+
pending.reject(
|
|
1882
|
+
new McpError(
|
|
1883
|
+
parsed.message.error.code,
|
|
1884
|
+
parsed.message.error.message,
|
|
1885
|
+
parsed.message.error.data
|
|
1886
|
+
)
|
|
1887
|
+
);
|
|
1888
|
+
}
|
|
1889
|
+
handleIncomingRequest(message, handler) {
|
|
1890
|
+
const activeRequest = {
|
|
1891
|
+
cancelled: false
|
|
1892
|
+
};
|
|
1893
|
+
this.activeIncomingRequests.set(message.id, activeRequest);
|
|
1894
|
+
void (async () => {
|
|
1895
|
+
try {
|
|
1896
|
+
const result = await handler(message.params, {
|
|
1897
|
+
id: message.id,
|
|
1898
|
+
method: message.method
|
|
1899
|
+
});
|
|
1900
|
+
if (this.disposedError !== void 0 || activeRequest.cancelled) {
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1903
|
+
this.output.write(
|
|
1904
|
+
serializeJsonRpcMessage2({
|
|
1905
|
+
jsonrpc: "2.0",
|
|
1906
|
+
id: message.id,
|
|
1907
|
+
result
|
|
1908
|
+
})
|
|
1909
|
+
);
|
|
1910
|
+
} catch (error) {
|
|
1911
|
+
if (this.disposedError !== void 0 || activeRequest.cancelled) {
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
1914
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1915
|
+
this.output.write(
|
|
1916
|
+
serializeJsonRpcMessage2({
|
|
1917
|
+
jsonrpc: "2.0",
|
|
1918
|
+
id: message.id,
|
|
1919
|
+
error: {
|
|
1920
|
+
code: ERROR_INTERNAL,
|
|
1921
|
+
message: errorMessage
|
|
1922
|
+
}
|
|
1923
|
+
})
|
|
1924
|
+
);
|
|
1925
|
+
} finally {
|
|
1926
|
+
const inFlightRequest = this.activeIncomingRequests.get(message.id);
|
|
1927
|
+
if (inFlightRequest === activeRequest) {
|
|
1928
|
+
this.activeIncomingRequests.delete(message.id);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
})();
|
|
1932
|
+
}
|
|
1933
|
+
handleCancellationNotification(params) {
|
|
1934
|
+
if (!isObjectRecord3(params)) {
|
|
1935
|
+
return;
|
|
1936
|
+
}
|
|
1937
|
+
const requestId = params.requestId;
|
|
1938
|
+
if (!isRequestId2(requestId)) {
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
const activeRequest = this.activeIncomingRequests.get(requestId);
|
|
1942
|
+
if (activeRequest === void 0) {
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
activeRequest.cancelled = true;
|
|
1946
|
+
this.activeIncomingRequests.delete(requestId);
|
|
1947
|
+
}
|
|
1948
|
+
};
|
|
1949
|
+
}
|
|
1950
|
+
});
|
|
1951
|
+
|
|
1952
|
+
// packages/tiny-mcp-client/src/index.ts
|
|
1953
|
+
var init_src2 = __esm({
|
|
1954
|
+
"packages/tiny-mcp-client/src/index.ts"() {
|
|
1955
|
+
"use strict";
|
|
1956
|
+
init_internal();
|
|
1957
|
+
}
|
|
1958
|
+
});
|
|
1959
|
+
|
|
1960
|
+
// packages/poe-agent/src/mcp-tool-executor.ts
|
|
1961
|
+
function namespaceMcpToolName(serverName, toolName) {
|
|
1962
|
+
return `mcp__${serverName}__${toolName}`;
|
|
1963
|
+
}
|
|
1964
|
+
function mcpToolToOpenAiTool(serverName, mcpTool) {
|
|
1965
|
+
const parameters = {
|
|
1966
|
+
type: "object",
|
|
1967
|
+
properties: getInputSchemaProperties(mcpTool.inputSchema)
|
|
1968
|
+
};
|
|
1969
|
+
const required = getInputSchemaRequired(mcpTool.inputSchema);
|
|
1970
|
+
if (required) {
|
|
1971
|
+
parameters.required = required;
|
|
1972
|
+
}
|
|
1973
|
+
return {
|
|
1974
|
+
type: "function",
|
|
1975
|
+
function: {
|
|
1976
|
+
name: namespaceMcpToolName(serverName, mcpTool.name),
|
|
1977
|
+
description: mcpTool.description ?? "",
|
|
1978
|
+
parameters
|
|
1979
|
+
}
|
|
1980
|
+
};
|
|
1981
|
+
}
|
|
1982
|
+
function callToolResultToString(result) {
|
|
1983
|
+
const content = result.content.map(contentItemToString).join("\n");
|
|
1984
|
+
if (result.isError) {
|
|
1985
|
+
throw new Error(content);
|
|
1986
|
+
}
|
|
1987
|
+
return content;
|
|
1988
|
+
}
|
|
1989
|
+
function getInputSchemaProperties(inputSchema) {
|
|
1990
|
+
const properties = inputSchema.properties;
|
|
1991
|
+
return isObjectRecord4(properties) ? properties : {};
|
|
1992
|
+
}
|
|
1993
|
+
function getInputSchemaRequired(inputSchema) {
|
|
1994
|
+
const required = inputSchema.required;
|
|
1995
|
+
if (!Array.isArray(required) || required.some((value) => typeof value !== "string")) {
|
|
1996
|
+
return void 0;
|
|
1997
|
+
}
|
|
1998
|
+
return required;
|
|
1999
|
+
}
|
|
2000
|
+
function contentItemToString(item) {
|
|
2001
|
+
switch (item.type) {
|
|
2002
|
+
case "text":
|
|
2003
|
+
return item.text;
|
|
2004
|
+
case "image":
|
|
2005
|
+
return `[image: ${item.mimeType}]`;
|
|
2006
|
+
case "audio":
|
|
2007
|
+
return `[audio: ${item.mimeType}]`;
|
|
2008
|
+
case "resource":
|
|
2009
|
+
return resourceContentsToString(item.resource);
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
function resourceContentsToString(resource) {
|
|
2013
|
+
if ("text" in resource) {
|
|
2014
|
+
return resource.text;
|
|
2015
|
+
}
|
|
2016
|
+
return `[blob: ${resource.uri}]`;
|
|
2017
|
+
}
|
|
2018
|
+
function isObjectRecord4(value) {
|
|
2019
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2020
|
+
}
|
|
2021
|
+
var McpToolExecutor;
|
|
2022
|
+
var init_mcp_tool_executor = __esm({
|
|
2023
|
+
"packages/poe-agent/src/mcp-tool-executor.ts"() {
|
|
2024
|
+
"use strict";
|
|
2025
|
+
McpToolExecutor = class {
|
|
2026
|
+
discoveredTools = [];
|
|
2027
|
+
toolToClient = /* @__PURE__ */ new Map();
|
|
2028
|
+
clients = /* @__PURE__ */ new Set();
|
|
2029
|
+
disposed = false;
|
|
2030
|
+
async addServer(serverName, client) {
|
|
2031
|
+
this.clients.add(client);
|
|
2032
|
+
let nextCursor;
|
|
2033
|
+
while (true) {
|
|
2034
|
+
const page = nextCursor === void 0 ? await client.listTools() : await client.listTools({ cursor: nextCursor });
|
|
2035
|
+
for (const mcpTool of page.tools) {
|
|
2036
|
+
const openAiTool = mcpToolToOpenAiTool(serverName, mcpTool);
|
|
2037
|
+
this.discoveredTools.push(openAiTool);
|
|
2038
|
+
this.toolToClient.set(openAiTool.function.name, {
|
|
2039
|
+
client,
|
|
2040
|
+
originalName: mcpTool.name
|
|
2041
|
+
});
|
|
2042
|
+
}
|
|
2043
|
+
if (page.nextCursor === void 0) {
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
nextCursor = page.nextCursor;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
getAvailableTools() {
|
|
2050
|
+
return [...this.discoveredTools];
|
|
2051
|
+
}
|
|
2052
|
+
async executeTool(name, args) {
|
|
2053
|
+
if (this.disposed) {
|
|
2054
|
+
throw new Error("MCP tool executor is disposed");
|
|
2055
|
+
}
|
|
2056
|
+
const registration = this.toolToClient.get(name);
|
|
2057
|
+
if (!registration) {
|
|
2058
|
+
throw new Error(`MCP tool not found: ${name}`);
|
|
2059
|
+
}
|
|
2060
|
+
const result = await registration.client.callTool({
|
|
2061
|
+
name: registration.originalName,
|
|
2062
|
+
arguments: args
|
|
2063
|
+
});
|
|
2064
|
+
return callToolResultToString(result);
|
|
2065
|
+
}
|
|
2066
|
+
async dispose() {
|
|
2067
|
+
this.disposed = true;
|
|
2068
|
+
const closeOperations = [];
|
|
2069
|
+
for (const client of this.clients) {
|
|
2070
|
+
if (client.close === void 0) {
|
|
2071
|
+
continue;
|
|
2072
|
+
}
|
|
2073
|
+
closeOperations.push(client.close());
|
|
2074
|
+
}
|
|
2075
|
+
await Promise.allSettled(closeOperations);
|
|
2076
|
+
this.clients.clear();
|
|
2077
|
+
}
|
|
2078
|
+
};
|
|
2079
|
+
}
|
|
2080
|
+
});
|
|
2081
|
+
|
|
2082
|
+
// packages/poe-agent/src/SYSTEM_PROMPT.md
|
|
2083
|
+
var SYSTEM_PROMPT_default;
|
|
2084
|
+
var init_SYSTEM_PROMPT = __esm({
|
|
2085
|
+
"packages/poe-agent/src/SYSTEM_PROMPT.md"() {
|
|
2086
|
+
SYSTEM_PROMPT_default = "You are a Poe agent, built by Poe \u2014 an interactive CLI tool that helps users with software engineering tasks.\n\n## Security\n\nAssist with defensive security only. Refuse malicious code, credential harvesting, or bulk crawling for secrets. Allow security analysis, detection rules, vulnerability explanations, and defensive tools.\n\nNever generate or guess URLs unless they help with programming. You may use URLs from user messages or local files.\n\n## Behavior\n\n- Be concise and direct. Minimize output tokens. Skip preamble and postamble.\n- Do what was asked \u2014 nothing more, nothing less.\n- Prefer editing existing files over creating new ones. Never create docs/READMEs unless asked.\n- Prioritize technical accuracy over validating beliefs. Disagree when necessary.\n- Read before you write.\n";
|
|
2087
|
+
}
|
|
2088
|
+
});
|
|
2089
|
+
|
|
671
2090
|
// packages/poe-agent/src/system-prompt.ts
|
|
672
|
-
import { readFileSync } from "node:fs";
|
|
673
|
-
import { readFile } from "node:fs/promises";
|
|
674
2091
|
async function loadSystemPrompt() {
|
|
675
|
-
return
|
|
2092
|
+
return SYSTEM_PROMPT_default;
|
|
676
2093
|
}
|
|
677
|
-
var systemPromptUrl;
|
|
678
2094
|
var init_system_prompt = __esm({
|
|
679
2095
|
"packages/poe-agent/src/system-prompt.ts"() {
|
|
680
2096
|
"use strict";
|
|
681
|
-
|
|
2097
|
+
init_SYSTEM_PROMPT();
|
|
682
2098
|
}
|
|
683
2099
|
});
|
|
684
2100
|
|
|
@@ -1006,7 +2422,41 @@ async function createAgentSession(options = {}) {
|
|
|
1006
2422
|
cwd: options.cwd,
|
|
1007
2423
|
allowedPaths: options.allowedPaths
|
|
1008
2424
|
});
|
|
1009
|
-
const
|
|
2425
|
+
const builtInTools = toolExecutor.getAvailableTools();
|
|
2426
|
+
const builtInToolNames = new Set(builtInTools.map((tool) => tool.function.name));
|
|
2427
|
+
let tools = builtInTools;
|
|
2428
|
+
let chatToolExecutor = toolExecutor;
|
|
2429
|
+
let mcpToolExecutor;
|
|
2430
|
+
if (options.mcpServers !== void 0) {
|
|
2431
|
+
const createdMcpToolExecutor = new McpToolExecutor();
|
|
2432
|
+
mcpToolExecutor = createdMcpToolExecutor;
|
|
2433
|
+
try {
|
|
2434
|
+
for (const [serverName, serverDefinition] of Object.entries(options.mcpServers)) {
|
|
2435
|
+
const mcpClient = new McpClient({
|
|
2436
|
+
clientInfo: {
|
|
2437
|
+
name: "poe-agent",
|
|
2438
|
+
version: "0.0.1"
|
|
2439
|
+
}
|
|
2440
|
+
});
|
|
2441
|
+
const transport = createMcpTransport(serverDefinition);
|
|
2442
|
+
await mcpClient.connect(transport);
|
|
2443
|
+
await createdMcpToolExecutor.addServer(serverName, mcpClient);
|
|
2444
|
+
}
|
|
2445
|
+
} catch (error) {
|
|
2446
|
+
await createdMcpToolExecutor.dispose();
|
|
2447
|
+
throw error;
|
|
2448
|
+
}
|
|
2449
|
+
const mcpTools = createdMcpToolExecutor.getAvailableTools();
|
|
2450
|
+
tools = [...builtInTools, ...mcpTools];
|
|
2451
|
+
chatToolExecutor = {
|
|
2452
|
+
executeTool(name, args) {
|
|
2453
|
+
if (builtInToolNames.has(name)) {
|
|
2454
|
+
return toolExecutor.executeTool(name, args);
|
|
2455
|
+
}
|
|
2456
|
+
return createdMcpToolExecutor.executeTool(name, args);
|
|
2457
|
+
}
|
|
2458
|
+
};
|
|
2459
|
+
}
|
|
1010
2460
|
let currentOnSessionUpdate;
|
|
1011
2461
|
const chatService = new PoeChatService({
|
|
1012
2462
|
apiKey,
|
|
@@ -1014,7 +2464,7 @@ async function createAgentSession(options = {}) {
|
|
|
1014
2464
|
baseUrl: options.baseUrl,
|
|
1015
2465
|
fetch: options.fetch,
|
|
1016
2466
|
systemPrompt,
|
|
1017
|
-
toolExecutor,
|
|
2467
|
+
toolExecutor: chatToolExecutor,
|
|
1018
2468
|
maxToolCallIterations: options.maxToolCallIterations,
|
|
1019
2469
|
onToolCall: (event) => {
|
|
1020
2470
|
if (!currentOnSessionUpdate) return;
|
|
@@ -1052,12 +2502,32 @@ async function createAgentSession(options = {}) {
|
|
|
1052
2502
|
disposed = true;
|
|
1053
2503
|
chatService.clearConversationHistory();
|
|
1054
2504
|
const disposableToolExecutor = toolExecutor;
|
|
2505
|
+
const disposePromises = [];
|
|
1055
2506
|
if (typeof disposableToolExecutor.dispose === "function") {
|
|
1056
|
-
|
|
2507
|
+
disposePromises.push(Promise.resolve(disposableToolExecutor.dispose()));
|
|
2508
|
+
}
|
|
2509
|
+
if (mcpToolExecutor) {
|
|
2510
|
+
disposePromises.push(mcpToolExecutor.dispose());
|
|
2511
|
+
}
|
|
2512
|
+
if (disposePromises.length > 0) {
|
|
2513
|
+
await Promise.all(disposePromises);
|
|
1057
2514
|
}
|
|
1058
2515
|
}
|
|
1059
2516
|
};
|
|
1060
2517
|
}
|
|
2518
|
+
function createMcpTransport(server) {
|
|
2519
|
+
if (server.transport === "stdio") {
|
|
2520
|
+
return new StdioTransport({
|
|
2521
|
+
command: server.command,
|
|
2522
|
+
args: server.args,
|
|
2523
|
+
env: server.env
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
return new HttpTransport({
|
|
2527
|
+
url: server.url,
|
|
2528
|
+
headers: server.headers
|
|
2529
|
+
});
|
|
2530
|
+
}
|
|
1061
2531
|
async function resolveApiKey(explicitApiKey) {
|
|
1062
2532
|
const normalizedExplicitApiKey = normalizeNonEmptyString(explicitApiKey);
|
|
1063
2533
|
if (normalizedExplicitApiKey) {
|
|
@@ -1121,6 +2591,8 @@ var init_agent_session = __esm({
|
|
|
1121
2591
|
"use strict";
|
|
1122
2592
|
init_src();
|
|
1123
2593
|
init_chat();
|
|
2594
|
+
init_src2();
|
|
2595
|
+
init_mcp_tool_executor();
|
|
1124
2596
|
init_system_prompt();
|
|
1125
2597
|
init_tool_executor();
|
|
1126
2598
|
}
|
|
@@ -1131,7 +2603,7 @@ var src_exports = {};
|
|
|
1131
2603
|
__export(src_exports, {
|
|
1132
2604
|
createAgentSession: () => createAgentSession
|
|
1133
2605
|
});
|
|
1134
|
-
var
|
|
2606
|
+
var init_src3 = __esm({
|
|
1135
2607
|
"packages/poe-agent/src/index.ts"() {
|
|
1136
2608
|
"use strict";
|
|
1137
2609
|
init_agent_session();
|
|
@@ -1629,13 +3101,13 @@ var AcpTransport = class {
|
|
|
1629
3101
|
env,
|
|
1630
3102
|
requestTimeoutMs,
|
|
1631
3103
|
firstRequestId,
|
|
1632
|
-
spawn:
|
|
3104
|
+
spawn: spawn3 = spawnChildProcess
|
|
1633
3105
|
} = options;
|
|
1634
3106
|
this.command = command;
|
|
1635
3107
|
this.closed = new Promise((resolve) => {
|
|
1636
3108
|
this.resolveClosed = resolve;
|
|
1637
3109
|
});
|
|
1638
|
-
this.child =
|
|
3110
|
+
this.child = spawn3(command, [...args], {
|
|
1639
3111
|
cwd,
|
|
1640
3112
|
env,
|
|
1641
3113
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -3399,6 +4871,7 @@ function createProvider(opts) {
|
|
|
3399
4871
|
branding: opts.branding,
|
|
3400
4872
|
disabled: opts.disabled,
|
|
3401
4873
|
supportsStdinPrompt: opts.supportsStdinPrompt,
|
|
4874
|
+
supportsMcpSpawn: opts.supportsMcpSpawn,
|
|
3402
4875
|
configurePrompts: opts.configurePrompts,
|
|
3403
4876
|
postConfigureMessages: opts.postConfigureMessages,
|
|
3404
4877
|
isolatedEnv: opts.isolatedEnv,
|
|
@@ -3501,6 +4974,18 @@ function createToolRenderState() {
|
|
|
3501
4974
|
toolCallTitles: /* @__PURE__ */ new Map()
|
|
3502
4975
|
};
|
|
3503
4976
|
}
|
|
4977
|
+
function toAgentSessionMcpServers(servers) {
|
|
4978
|
+
const mappedServers = {};
|
|
4979
|
+
for (const [name, server] of Object.entries(servers)) {
|
|
4980
|
+
mappedServers[name] = {
|
|
4981
|
+
transport: "stdio",
|
|
4982
|
+
command: server.command,
|
|
4983
|
+
...server.args && server.args.length > 0 ? { args: [...server.args] } : {},
|
|
4984
|
+
...server.env && Object.keys(server.env).length > 0 ? { env: { ...server.env } } : {}
|
|
4985
|
+
};
|
|
4986
|
+
}
|
|
4987
|
+
return Object.keys(mappedServers).length > 0 ? mappedServers : void 0;
|
|
4988
|
+
}
|
|
3504
4989
|
function toErrorMessage2(value) {
|
|
3505
4990
|
if (value instanceof Error) {
|
|
3506
4991
|
return value.message;
|
|
@@ -3725,6 +5210,7 @@ function createInMemoryAcpTransport(options) {
|
|
|
3725
5210
|
const closedPromise = new Promise((resolve) => {
|
|
3726
5211
|
resolveClosed = resolve;
|
|
3727
5212
|
});
|
|
5213
|
+
const sessionMcpServers = options.mcpServers ? toAgentSessionMcpServers(options.mcpServers) : void 0;
|
|
3728
5214
|
const closeTransport = (reason) => {
|
|
3729
5215
|
if (closed) {
|
|
3730
5216
|
return;
|
|
@@ -3760,10 +5246,12 @@ function createInMemoryAcpTransport(options) {
|
|
|
3760
5246
|
}
|
|
3761
5247
|
if (method === "session/new") {
|
|
3762
5248
|
const request = params;
|
|
3763
|
-
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (
|
|
5249
|
+
const { createAgentSession: createAgentSession2 } = await Promise.resolve().then(() => (init_src3(), src_exports));
|
|
3764
5250
|
const session = await createAgentSession2({
|
|
3765
5251
|
model: options.model,
|
|
3766
|
-
cwd: request.cwd || options.cwd
|
|
5252
|
+
cwd: request.cwd || options.cwd,
|
|
5253
|
+
...options.baseUrl ? { baseUrl: options.baseUrl } : {},
|
|
5254
|
+
...sessionMcpServers ? { mcpServers: sessionMcpServers } : {}
|
|
3767
5255
|
});
|
|
3768
5256
|
const sessionId = `poe-agent-session-${sessionCounter + 1}`;
|
|
3769
5257
|
sessionCounter += 1;
|
|
@@ -3834,7 +5322,9 @@ async function runPoeAgentAcpLifecycle(options) {
|
|
|
3834
5322
|
let assistantText = "";
|
|
3835
5323
|
const transport = createInMemoryAcpTransport({
|
|
3836
5324
|
model: options.model,
|
|
3837
|
-
cwd: options.cwd
|
|
5325
|
+
cwd: options.cwd,
|
|
5326
|
+
baseUrl: options.baseUrl,
|
|
5327
|
+
mcpServers: options.mcpServers
|
|
3838
5328
|
});
|
|
3839
5329
|
const client = new AcpClient({ transport });
|
|
3840
5330
|
try {
|
|
@@ -3888,6 +5378,8 @@ function spawnPoeAgentWithAcp(options) {
|
|
|
3888
5378
|
prompt: options.prompt,
|
|
3889
5379
|
model,
|
|
3890
5380
|
cwd,
|
|
5381
|
+
baseUrl: options.baseUrl,
|
|
5382
|
+
mcpServers: options.mcpServers,
|
|
3891
5383
|
onEvent: (event) => {
|
|
3892
5384
|
queue.push(event);
|
|
3893
5385
|
}
|
|
@@ -3905,6 +5397,7 @@ var poeAgentService = createProvider({
|
|
|
3905
5397
|
label: "Poe Agent",
|
|
3906
5398
|
summary: "Run one-shot prompts with the built-in Poe agent runtime.",
|
|
3907
5399
|
supportsStdinPrompt: true,
|
|
5400
|
+
supportsMcpSpawn: true,
|
|
3908
5401
|
manifest: {
|
|
3909
5402
|
configure: []
|
|
3910
5403
|
},
|
|
@@ -3912,7 +5405,9 @@ var poeAgentService = createProvider({
|
|
|
3912
5405
|
const result = await runPoeAgentAcpLifecycle({
|
|
3913
5406
|
prompt: options.prompt,
|
|
3914
5407
|
model: options.model ?? DEFAULT_FRONTIER_MODEL,
|
|
3915
|
-
cwd: options.cwd ?? context.env.cwd
|
|
5408
|
+
cwd: options.cwd ?? context.env.cwd,
|
|
5409
|
+
baseUrl: context.env.poeApiBaseUrl,
|
|
5410
|
+
mcpServers: options.mcpServers
|
|
3916
5411
|
});
|
|
3917
5412
|
return {
|
|
3918
5413
|
stdout: result.stdout,
|