agents 0.0.66 → 0.0.68
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/ai-chat-agent.js +2 -2
- package/dist/ai-react.js +2 -1
- package/dist/ai-react.js.map +1 -1
- package/dist/{chunk-YZNSS675.js → chunk-WNICV3OI.js} +4 -3
- package/dist/chunk-WNICV3OI.js.map +1 -0
- package/dist/{chunk-AV3OMRR4.js → chunk-ZRZEISHY.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/index.d.ts +5 -4
- package/dist/mcp/index.js +32 -10
- package/dist/mcp/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-YZNSS675.js.map +0 -1
- /package/dist/{chunk-AV3OMRR4.js.map → chunk-ZRZEISHY.js.map} +0 -0
package/dist/ai-chat-agent.js
CHANGED
package/dist/ai-react.js
CHANGED
|
@@ -3,6 +3,7 @@ import "./chunk-HMLY7DHA.js";
|
|
|
3
3
|
// src/ai-react.tsx
|
|
4
4
|
import { useChat } from "@ai-sdk/react";
|
|
5
5
|
import { use, useEffect } from "react";
|
|
6
|
+
import { nanoid } from "nanoid";
|
|
6
7
|
var requestCache = /* @__PURE__ */ new Map();
|
|
7
8
|
function useAgentChat(options) {
|
|
8
9
|
const { agent, getInitialMessages, ...rest } = options;
|
|
@@ -65,7 +66,7 @@ function useAgentChat(options) {
|
|
|
65
66
|
window
|
|
66
67
|
// dispatcher, duplex
|
|
67
68
|
} = options2;
|
|
68
|
-
const id =
|
|
69
|
+
const id = nanoid(8);
|
|
69
70
|
const abortController = new AbortController();
|
|
70
71
|
signal?.addEventListener("abort", () => {
|
|
71
72
|
agent.send(
|
package/dist/ai-react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ai-react.tsx"],"sourcesContent":["import { useChat } from \"@ai-sdk/react\";\nimport type { Message } from \"ai\";\nimport { use, useEffect } from \"react\";\nimport type { OutgoingMessage } from \"./ai-types\";\nimport type { useAgent } from \"./react\";\n\ntype GetInitialMessagesOptions = {\n agent: string;\n name: string;\n url: string;\n};\n\n/**\n * Options for the useAgentChat hook\n */\ntype UseAgentChatOptions<State> = Omit<\n Parameters<typeof useChat>[0] & {\n /** Agent connection from useAgent */\n agent: ReturnType<typeof useAgent<State>>;\n getInitialMessages?:\n | undefined\n | null\n // | (() => Message[])\n | ((options: GetInitialMessagesOptions) => Promise<Message[]>);\n },\n \"fetch\"\n>;\n\nconst requestCache = new Map<string, Promise<Message[]>>();\n\n/**\n * React hook for building AI chat interfaces using an Agent\n * @param options Chat options including the agent connection\n * @returns Chat interface controls and state with added clearHistory method\n */\nexport function useAgentChat<State = unknown>(\n options: UseAgentChatOptions<State>\n) {\n const { agent, getInitialMessages, ...rest } = options;\n\n const agentUrl = new URL(\n `${// @ts-expect-error we're using a protected _url property that includes query params\n ((agent._url as string | null) || agent._pkurl)\n ?.replace(\"ws://\", \"http://\")\n .replace(\"wss://\", \"https://\")}`\n );\n\n // delete the _pk query param\n agentUrl.searchParams.delete(\"_pk\");\n const agentUrlString = agentUrl.toString();\n\n async function defaultGetInitialMessagesFetch({\n url,\n }: GetInitialMessagesOptions) {\n const getMessagesUrl = new URL(url);\n getMessagesUrl.pathname += \"/get-messages\";\n const response = await fetch(getMessagesUrl.toString(), {\n headers: options.headers,\n credentials: options.credentials,\n });\n return response.json<Message[]>();\n }\n\n const getInitialMessagesFetch =\n getInitialMessages || defaultGetInitialMessagesFetch;\n\n function doGetInitialMessages(\n getInitialMessagesOptions: GetInitialMessagesOptions\n ) {\n if (requestCache.has(agentUrlString)) {\n return requestCache.get(agentUrlString)!;\n }\n const promise = getInitialMessagesFetch(getInitialMessagesOptions);\n // immediately cache the promise so that we don't\n // create multiple requests for the same agent during multiple\n // concurrent renders\n requestCache.set(agentUrlString, promise);\n return promise;\n }\n\n const initialMessagesPromise =\n getInitialMessages === null\n ? null\n : doGetInitialMessages({\n agent: agent.agent,\n name: agent.name,\n url: agentUrlString,\n });\n const initialMessages = initialMessagesPromise\n ? use(initialMessagesPromise)\n : (rest.initialMessages ?? []);\n\n // manages adding and removing the promise from the cache\n useEffect(() => {\n if (!initialMessagesPromise) {\n return;\n }\n // this effect is responsible for removing the promise from the cache\n // when the component unmounts or the promise changes,\n // but that means it also must add the promise to the cache\n // so that multiple arbitrary effect runs produce the expected state\n // when resolved.\n requestCache.set(agentUrlString, initialMessagesPromise!);\n return () => {\n if (requestCache.get(agentUrlString) === initialMessagesPromise) {\n requestCache.delete(agentUrlString);\n }\n };\n }, [agentUrlString, initialMessagesPromise]);\n\n async function aiFetch(\n request: RequestInfo | URL,\n options: RequestInit = {}\n ) {\n // we're going to use a websocket to do the actual \"fetching\"\n // but still satisfy the type signature of the fetch function\n // so we'll return a promise that resolves to a response\n\n const {\n method,\n keepalive,\n headers,\n body,\n redirect,\n integrity,\n signal,\n credentials,\n mode,\n referrer,\n referrerPolicy,\n window,\n // dispatcher, duplex\n } = options;\n const id = crypto.randomUUID();\n const abortController = new AbortController();\n\n signal?.addEventListener(\"abort\", () => {\n // Propagate request cancellation to the Agent\n // We need to communciate cancellation as a websocket message, instead of a request signal\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_request_cancel\",\n id,\n })\n );\n\n // NOTE - If we wanted to, we could preserve the \"interrupted\" message here, with the code below\n // However, I think it might be the responsibility of the library user to implement that behavior manually?\n // Reasoning: This code could be subject to collisions, as it \"force saves\" the messages we have locally\n //\n // agent.send(JSON.stringify({\n // type: \"cf_agent_chat_messages\",\n // messages: ... /* some way of getting current messages ref? */\n // }))\n\n abortController.abort();\n });\n\n agent.addEventListener(\n \"message\",\n (event) => {\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_use_chat_response\") {\n if (data.id === id) {\n controller.enqueue(new TextEncoder().encode(data.body));\n if (data.done) {\n controller.close();\n abortController.abort();\n }\n }\n }\n },\n { signal: abortController.signal }\n );\n\n let controller: ReadableStreamDefaultController;\n\n const stream = new ReadableStream({\n start(c) {\n controller = c;\n },\n });\n\n agent.send(\n JSON.stringify({\n type: \"cf_agent_use_chat_request\",\n id,\n url: request.toString(),\n init: {\n method,\n keepalive,\n headers,\n body,\n redirect,\n integrity,\n credentials,\n mode,\n referrer,\n referrerPolicy,\n window,\n // dispatcher,\n // duplex\n },\n })\n );\n\n return new Response(stream);\n }\n const useChatHelpers = useChat({\n initialMessages,\n sendExtraMessageFields: true,\n fetch: aiFetch,\n ...rest,\n });\n\n useEffect(() => {\n function onClearHistory(event: MessageEvent) {\n if (typeof event.data !== \"string\") {\n return;\n }\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_chat_clear\") {\n useChatHelpers.setMessages([]);\n }\n }\n\n function onMessages(event: MessageEvent) {\n if (typeof event.data !== \"string\") {\n return;\n }\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_chat_messages\") {\n useChatHelpers.setMessages(data.messages);\n }\n }\n\n agent.addEventListener(\"message\", onClearHistory);\n agent.addEventListener(\"message\", onMessages);\n\n return () => {\n agent.removeEventListener(\"message\", onClearHistory);\n agent.removeEventListener(\"message\", onMessages);\n };\n }, [agent, useChatHelpers.setMessages]);\n\n return {\n ...useChatHelpers,\n /**\n * Set the chat messages and synchronize with the Agent\n * @param messages New messages to set\n */\n setMessages: (messages: Message[]) => {\n useChatHelpers.setMessages(messages);\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_messages\",\n messages,\n })\n );\n },\n /**\n * Clear chat history on both client and Agent\n */\n clearHistory: () => {\n useChatHelpers.setMessages([]);\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_clear\",\n })\n );\n },\n };\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;AAExB,SAAS,KAAK,iBAAiB;AA0B/B,IAAM,eAAe,oBAAI,IAAgC;AAOlD,SAAS,aACd,SACA;AACA,QAAM,EAAE,OAAO,oBAAoB,GAAG,KAAK,IAAI;AAE/C,QAAM,WAAW,IAAI;AAAA,IACnB;AAAA,KACE,MAAM,QAA0B,MAAM,SACpC,QAAQ,SAAS,SAAS,EAC3B,QAAQ,UAAU,UAAU,CAAC;AAAA,EAClC;AAGA,WAAS,aAAa,OAAO,KAAK;AAClC,QAAM,iBAAiB,SAAS,SAAS;AAEzC,iBAAe,+BAA+B;AAAA,IAC5C;AAAA,EACF,GAA8B;AAC5B,UAAM,iBAAiB,IAAI,IAAI,GAAG;AAClC,mBAAe,YAAY;AAC3B,UAAM,WAAW,MAAM,MAAM,eAAe,SAAS,GAAG;AAAA,MACtD,SAAS,QAAQ;AAAA,MACjB,aAAa,QAAQ;AAAA,IACvB,CAAC;AACD,WAAO,SAAS,KAAgB;AAAA,EAClC;AAEA,QAAM,0BACJ,sBAAsB;AAExB,WAAS,qBACP,2BACA;AACA,QAAI,aAAa,IAAI,cAAc,GAAG;AACpC,aAAO,aAAa,IAAI,cAAc;AAAA,IACxC;AACA,UAAM,UAAU,wBAAwB,yBAAyB;AAIjE,iBAAa,IAAI,gBAAgB,OAAO;AACxC,WAAO;AAAA,EACT;AAEA,QAAM,yBACJ,uBAAuB,OACnB,OACA,qBAAqB;AAAA,IACnB,OAAO,MAAM;AAAA,IACb,MAAM,MAAM;AAAA,IACZ,KAAK;AAAA,EACP,CAAC;AACP,QAAM,kBAAkB,yBACpB,IAAI,sBAAsB,IACzB,KAAK,mBAAmB,CAAC;AAG9B,YAAU,MAAM;AACd,QAAI,CAAC,wBAAwB;AAC3B;AAAA,IACF;AAMA,iBAAa,IAAI,gBAAgB,sBAAuB;AACxD,WAAO,MAAM;AACX,UAAI,aAAa,IAAI,cAAc,MAAM,wBAAwB;AAC/D,qBAAa,OAAO,cAAc;AAAA,MACpC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,gBAAgB,sBAAsB,CAAC;AAE3C,iBAAe,QACb,SACAA,WAAuB,CAAC,GACxB;AAKA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IAEF,IAAIA;AACJ,UAAM,KAAK,OAAO,WAAW;AAC7B,UAAM,kBAAkB,IAAI,gBAAgB;AAE5C,YAAQ,iBAAiB,SAAS,MAAM;AAGtC,YAAM;AAAA,QACJ,KAAK,UAAU;AAAA,UACb,MAAM;AAAA,UACN;AAAA,QACF,CAAC;AAAA,MACH;AAWA,sBAAgB,MAAM;AAAA,IACxB,CAAC;AAED,UAAM;AAAA,MACJ;AAAA,MACA,CAAC,UAAU;AACT,YAAI;AACJ,YAAI;AACF,iBAAO,KAAK,MAAM,MAAM,IAAI;AAAA,QAC9B,SAAS,OAAO;AAGd;AAAA,QACF;AACA,YAAI,KAAK,SAAS,8BAA8B;AAC9C,cAAI,KAAK,OAAO,IAAI;AAClB,uBAAW,QAAQ,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;AACtD,gBAAI,KAAK,MAAM;AACb,yBAAW,MAAM;AACjB,8BAAgB,MAAM;AAAA,YACxB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,EAAE,QAAQ,gBAAgB,OAAO;AAAA,IACnC;AAEA,QAAI;AAEJ,UAAM,SAAS,IAAI,eAAe;AAAA,MAChC,MAAM,GAAG;AACP,qBAAa;AAAA,MACf;AAAA,IACF,CAAC;AAED,UAAM;AAAA,MACJ,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,QACN;AAAA,QACA,KAAK,QAAQ,SAAS;AAAA,QACtB,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA;AAAA,QAGF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO,IAAI,SAAS,MAAM;AAAA,EAC5B;AACA,QAAM,iBAAiB,QAAQ;AAAA,IAC7B;AAAA,IACA,wBAAwB;AAAA,IACxB,OAAO;AAAA,IACP,GAAG;AAAA,EACL,CAAC;AAED,YAAU,MAAM;AACd,aAAS,eAAe,OAAqB;AAC3C,UAAI,OAAO,MAAM,SAAS,UAAU;AAClC;AAAA,MACF;AACA,UAAI;AACJ,UAAI;AACF,eAAO,KAAK,MAAM,MAAM,IAAI;AAAA,MAC9B,SAAS,OAAO;AAGd;AAAA,MACF;AACA,UAAI,KAAK,SAAS,uBAAuB;AACvC,uBAAe,YAAY,CAAC,CAAC;AAAA,MAC/B;AAAA,IACF;AAEA,aAAS,WAAW,OAAqB;AACvC,UAAI,OAAO,MAAM,SAAS,UAAU;AAClC;AAAA,MACF;AACA,UAAI;AACJ,UAAI;AACF,eAAO,KAAK,MAAM,MAAM,IAAI;AAAA,MAC9B,SAAS,OAAO;AAGd;AAAA,MACF;AACA,UAAI,KAAK,SAAS,0BAA0B;AAC1C,uBAAe,YAAY,KAAK,QAAQ;AAAA,MAC1C;AAAA,IACF;AAEA,UAAM,iBAAiB,WAAW,cAAc;AAChD,UAAM,iBAAiB,WAAW,UAAU;AAE5C,WAAO,MAAM;AACX,YAAM,oBAAoB,WAAW,cAAc;AACnD,YAAM,oBAAoB,WAAW,UAAU;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,OAAO,eAAe,WAAW,CAAC;AAEtC,SAAO;AAAA,IACL,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA,IAKH,aAAa,CAAC,aAAwB;AACpC,qBAAe,YAAY,QAAQ;AACnC,YAAM;AAAA,QACJ,KAAK,UAAU;AAAA,UACb,MAAM;AAAA,UACN;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAIA,cAAc,MAAM;AAClB,qBAAe,YAAY,CAAC,CAAC;AAC7B,YAAM;AAAA,QACJ,KAAK,UAAU;AAAA,UACb,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;","names":["options"]}
|
|
1
|
+
{"version":3,"sources":["../src/ai-react.tsx"],"sourcesContent":["import { useChat } from \"@ai-sdk/react\";\nimport type { Message } from \"ai\";\nimport { use, useEffect } from \"react\";\nimport type { OutgoingMessage } from \"./ai-types\";\nimport type { useAgent } from \"./react\";\nimport { nanoid } from \"nanoid\";\n\ntype GetInitialMessagesOptions = {\n agent: string;\n name: string;\n url: string;\n};\n\n/**\n * Options for the useAgentChat hook\n */\ntype UseAgentChatOptions<State> = Omit<\n Parameters<typeof useChat>[0] & {\n /** Agent connection from useAgent */\n agent: ReturnType<typeof useAgent<State>>;\n getInitialMessages?:\n | undefined\n | null\n // | (() => Message[])\n | ((options: GetInitialMessagesOptions) => Promise<Message[]>);\n },\n \"fetch\"\n>;\n\nconst requestCache = new Map<string, Promise<Message[]>>();\n\n/**\n * React hook for building AI chat interfaces using an Agent\n * @param options Chat options including the agent connection\n * @returns Chat interface controls and state with added clearHistory method\n */\nexport function useAgentChat<State = unknown>(\n options: UseAgentChatOptions<State>\n) {\n const { agent, getInitialMessages, ...rest } = options;\n\n const agentUrl = new URL(\n `${// @ts-expect-error we're using a protected _url property that includes query params\n ((agent._url as string | null) || agent._pkurl)\n ?.replace(\"ws://\", \"http://\")\n .replace(\"wss://\", \"https://\")}`\n );\n\n // delete the _pk query param\n agentUrl.searchParams.delete(\"_pk\");\n const agentUrlString = agentUrl.toString();\n\n async function defaultGetInitialMessagesFetch({\n url,\n }: GetInitialMessagesOptions) {\n const getMessagesUrl = new URL(url);\n getMessagesUrl.pathname += \"/get-messages\";\n const response = await fetch(getMessagesUrl.toString(), {\n headers: options.headers,\n credentials: options.credentials,\n });\n return response.json<Message[]>();\n }\n\n const getInitialMessagesFetch =\n getInitialMessages || defaultGetInitialMessagesFetch;\n\n function doGetInitialMessages(\n getInitialMessagesOptions: GetInitialMessagesOptions\n ) {\n if (requestCache.has(agentUrlString)) {\n return requestCache.get(agentUrlString)!;\n }\n const promise = getInitialMessagesFetch(getInitialMessagesOptions);\n // immediately cache the promise so that we don't\n // create multiple requests for the same agent during multiple\n // concurrent renders\n requestCache.set(agentUrlString, promise);\n return promise;\n }\n\n const initialMessagesPromise =\n getInitialMessages === null\n ? null\n : doGetInitialMessages({\n agent: agent.agent,\n name: agent.name,\n url: agentUrlString,\n });\n const initialMessages = initialMessagesPromise\n ? use(initialMessagesPromise)\n : (rest.initialMessages ?? []);\n\n // manages adding and removing the promise from the cache\n useEffect(() => {\n if (!initialMessagesPromise) {\n return;\n }\n // this effect is responsible for removing the promise from the cache\n // when the component unmounts or the promise changes,\n // but that means it also must add the promise to the cache\n // so that multiple arbitrary effect runs produce the expected state\n // when resolved.\n requestCache.set(agentUrlString, initialMessagesPromise!);\n return () => {\n if (requestCache.get(agentUrlString) === initialMessagesPromise) {\n requestCache.delete(agentUrlString);\n }\n };\n }, [agentUrlString, initialMessagesPromise]);\n\n async function aiFetch(\n request: RequestInfo | URL,\n options: RequestInit = {}\n ) {\n // we're going to use a websocket to do the actual \"fetching\"\n // but still satisfy the type signature of the fetch function\n // so we'll return a promise that resolves to a response\n\n const {\n method,\n keepalive,\n headers,\n body,\n redirect,\n integrity,\n signal,\n credentials,\n mode,\n referrer,\n referrerPolicy,\n window,\n // dispatcher, duplex\n } = options;\n const id = nanoid(8);\n const abortController = new AbortController();\n\n signal?.addEventListener(\"abort\", () => {\n // Propagate request cancellation to the Agent\n // We need to communciate cancellation as a websocket message, instead of a request signal\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_request_cancel\",\n id,\n })\n );\n\n // NOTE - If we wanted to, we could preserve the \"interrupted\" message here, with the code below\n // However, I think it might be the responsibility of the library user to implement that behavior manually?\n // Reasoning: This code could be subject to collisions, as it \"force saves\" the messages we have locally\n //\n // agent.send(JSON.stringify({\n // type: \"cf_agent_chat_messages\",\n // messages: ... /* some way of getting current messages ref? */\n // }))\n\n abortController.abort();\n });\n\n agent.addEventListener(\n \"message\",\n (event) => {\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_use_chat_response\") {\n if (data.id === id) {\n controller.enqueue(new TextEncoder().encode(data.body));\n if (data.done) {\n controller.close();\n abortController.abort();\n }\n }\n }\n },\n { signal: abortController.signal }\n );\n\n let controller: ReadableStreamDefaultController;\n\n const stream = new ReadableStream({\n start(c) {\n controller = c;\n },\n });\n\n agent.send(\n JSON.stringify({\n type: \"cf_agent_use_chat_request\",\n id,\n url: request.toString(),\n init: {\n method,\n keepalive,\n headers,\n body,\n redirect,\n integrity,\n credentials,\n mode,\n referrer,\n referrerPolicy,\n window,\n // dispatcher,\n // duplex\n },\n })\n );\n\n return new Response(stream);\n }\n const useChatHelpers = useChat({\n initialMessages,\n sendExtraMessageFields: true,\n fetch: aiFetch,\n ...rest,\n });\n\n useEffect(() => {\n function onClearHistory(event: MessageEvent) {\n if (typeof event.data !== \"string\") {\n return;\n }\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_chat_clear\") {\n useChatHelpers.setMessages([]);\n }\n }\n\n function onMessages(event: MessageEvent) {\n if (typeof event.data !== \"string\") {\n return;\n }\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_chat_messages\") {\n useChatHelpers.setMessages(data.messages);\n }\n }\n\n agent.addEventListener(\"message\", onClearHistory);\n agent.addEventListener(\"message\", onMessages);\n\n return () => {\n agent.removeEventListener(\"message\", onClearHistory);\n agent.removeEventListener(\"message\", onMessages);\n };\n }, [agent, useChatHelpers.setMessages]);\n\n return {\n ...useChatHelpers,\n /**\n * Set the chat messages and synchronize with the Agent\n * @param messages New messages to set\n */\n setMessages: (messages: Message[]) => {\n useChatHelpers.setMessages(messages);\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_messages\",\n messages,\n })\n );\n },\n /**\n * Clear chat history on both client and Agent\n */\n clearHistory: () => {\n useChatHelpers.setMessages([]);\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_clear\",\n })\n );\n },\n };\n}\n"],"mappings":"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","names":["options"]}
|
|
@@ -218,6 +218,7 @@ function capabilityErrorHandler(empty, method) {
|
|
|
218
218
|
|
|
219
219
|
// src/mcp/client.ts
|
|
220
220
|
import { jsonSchema } from "ai";
|
|
221
|
+
import { nanoid } from "nanoid";
|
|
221
222
|
var MCPClientManager = class {
|
|
222
223
|
/**
|
|
223
224
|
* @param name Name of the MCP client
|
|
@@ -238,7 +239,7 @@ var MCPClientManager = class {
|
|
|
238
239
|
* @param capabilities Client capabilities (i.e. if the client supports roots/sampling)
|
|
239
240
|
*/
|
|
240
241
|
async connect(url, options = {}) {
|
|
241
|
-
const id = options.reconnect?.id ??
|
|
242
|
+
const id = options.reconnect?.id ?? nanoid(8);
|
|
242
243
|
if (!options.transport?.authProvider) {
|
|
243
244
|
console.warn(
|
|
244
245
|
"No authProvider provided in the transport options. This client will only support unauthenticated remote MCP Servers"
|
|
@@ -341,7 +342,7 @@ var MCPClientManager = class {
|
|
|
341
342
|
return Object.fromEntries(
|
|
342
343
|
getNamespacedData(this.mcpConnections, "tools").map((tool) => {
|
|
343
344
|
return [
|
|
344
|
-
tool.name
|
|
345
|
+
`${tool.serverId}.${tool.name}`,
|
|
345
346
|
{
|
|
346
347
|
parameters: jsonSchema(tool.inputSchema),
|
|
347
348
|
description: tool.description,
|
|
@@ -432,4 +433,4 @@ export {
|
|
|
432
433
|
MCPClientManager,
|
|
433
434
|
getNamespacedData
|
|
434
435
|
};
|
|
435
|
-
//# sourceMappingURL=chunk-
|
|
436
|
+
//# sourceMappingURL=chunk-WNICV3OI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/sse-edge.ts","../src/mcp/client-connection.ts","../src/mcp/client.ts"],"sourcesContent":["import {\n SSEClientTransport,\n type SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\n\nexport class SSEEdgeClientTransport extends SSEClientTransport {\n private authProvider: OAuthClientProvider | undefined;\n /**\n * Creates a new EdgeSSEClientTransport, which overrides fetch to be compatible with the CF workers environment\n */\n constructor(url: URL, options: SSEClientTransportOptions) {\n const fetchOverride: typeof fetch = async (\n fetchUrl: RequestInfo | URL,\n fetchInit: RequestInit = {}\n ) => {\n // add auth headers\n const headers = await this.authHeaders();\n const workerOptions = {\n ...fetchInit,\n headers: {\n ...fetchInit?.headers,\n ...headers,\n },\n };\n\n // Remove unsupported properties\n // biome-ignore lint/performance/noDelete: workaround for workers environment\n delete workerOptions.mode;\n\n // Call the original fetch with fixed options\n return fetch(fetchUrl, workerOptions);\n };\n\n super(url, {\n ...options,\n eventSourceInit: {\n fetch: fetchOverride,\n },\n });\n this.authProvider = options.authProvider;\n }\n\n async authHeaders() {\n if (this.authProvider) {\n const tokens = await this.authProvider.tokens();\n if (tokens) {\n return {\n Authorization: `Bearer ${tokens.access_token}`,\n };\n }\n }\n }\n}\n","import { SSEEdgeClientTransport } from \"./sse-edge\";\n\nimport {\n ToolListChangedNotificationSchema,\n type ClientCapabilities,\n type Resource,\n type Tool,\n type Prompt,\n ResourceListChangedNotificationSchema,\n PromptListChangedNotificationSchema,\n type ListToolsResult,\n type ListResourcesResult,\n type ListPromptsResult,\n type ServerCapabilities,\n type ResourceTemplate,\n type ListResourceTemplatesResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { AgentsOAuthProvider } from \"./do-oauth-client-provider\";\n\nexport class MCPClientConnection {\n client: Client;\n connectionState:\n | \"authenticating\"\n | \"connecting\"\n | \"ready\"\n | \"discovering\"\n | \"failed\" = \"connecting\";\n instructions?: string;\n tools: Tool[] = [];\n prompts: Prompt[] = [];\n resources: Resource[] = [];\n resourceTemplates: ResourceTemplate[] = [];\n serverCapabilities: ServerCapabilities | undefined;\n\n constructor(\n public url: URL,\n info: ConstructorParameters<typeof Client>[0],\n public options: {\n transport: SSEClientTransportOptions & {\n authProvider?: AgentsOAuthProvider;\n };\n client: ConstructorParameters<typeof Client>[1];\n capabilities: ClientCapabilities;\n } = { transport: {}, client: {}, capabilities: {} }\n ) {\n this.client = new Client(info, options.client);\n this.client.registerCapabilities(options.capabilities);\n }\n\n /**\n * Initialize a client connection\n *\n * @param code Optional OAuth code to initialize the connection with if auth hasn't been initialized\n * @returns\n */\n async init(code?: string, clientId?: string) {\n try {\n const transport = new SSEEdgeClientTransport(\n this.url,\n this.options.transport\n );\n if (code) {\n await transport.finishAuth(code);\n }\n\n await this.client.connect(transport);\n // biome-ignore lint/suspicious/noExplicitAny: allow for the error check here\n } catch (e: any) {\n if (e.toString().includes(\"Unauthorized\")) {\n // unauthorized, we should wait for the user to authenticate\n this.connectionState = \"authenticating\";\n return;\n }\n this.connectionState = \"failed\";\n throw e;\n }\n\n this.connectionState = \"discovering\";\n\n this.serverCapabilities = await this.client.getServerCapabilities();\n if (!this.serverCapabilities) {\n throw new Error(\"The MCP Server failed to return server capabilities\");\n }\n\n const [instructions, tools, resources, prompts, resourceTemplates] =\n await Promise.all([\n this.client.getInstructions(),\n this.registerTools(),\n this.registerResources(),\n this.registerPrompts(),\n this.registerResourceTemplates(),\n ]);\n\n this.instructions = instructions;\n this.tools = tools;\n this.resources = resources;\n this.prompts = prompts;\n this.resourceTemplates = resourceTemplates;\n\n this.connectionState = \"ready\";\n }\n\n /**\n * Notification handler registration\n */\n async registerTools(): Promise<Tool[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.tools) {\n return [];\n }\n\n if (this.serverCapabilities.tools.listChanged) {\n this.client.setNotificationHandler(\n ToolListChangedNotificationSchema,\n async (_notification) => {\n this.tools = await this.fetchTools();\n }\n );\n }\n\n return this.fetchTools();\n }\n\n async registerResources(): Promise<Resource[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.resources) {\n return [];\n }\n\n if (this.serverCapabilities.resources.listChanged) {\n this.client.setNotificationHandler(\n ResourceListChangedNotificationSchema,\n async (_notification) => {\n this.resources = await this.fetchResources();\n }\n );\n }\n\n return this.fetchResources();\n }\n\n async registerPrompts(): Promise<Prompt[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.prompts) {\n return [];\n }\n\n if (this.serverCapabilities.prompts.listChanged) {\n this.client.setNotificationHandler(\n PromptListChangedNotificationSchema,\n async (_notification) => {\n this.prompts = await this.fetchPrompts();\n }\n );\n }\n\n return this.fetchPrompts();\n }\n\n async registerResourceTemplates(): Promise<ResourceTemplate[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.resources) {\n return [];\n }\n\n return this.fetchResourceTemplates();\n }\n\n async fetchTools() {\n let toolsAgg: Tool[] = [];\n let toolsResult: ListToolsResult = { tools: [] };\n do {\n toolsResult = await this.client\n .listTools({\n cursor: toolsResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ tools: [] }, \"tools/list\"));\n toolsAgg = toolsAgg.concat(toolsResult.tools);\n } while (toolsResult.nextCursor);\n return toolsAgg;\n }\n\n async fetchResources() {\n let resourcesAgg: Resource[] = [];\n let resourcesResult: ListResourcesResult = { resources: [] };\n do {\n resourcesResult = await this.client\n .listResources({\n cursor: resourcesResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ resources: [] }, \"resources/list\"));\n resourcesAgg = resourcesAgg.concat(resourcesResult.resources);\n } while (resourcesResult.nextCursor);\n return resourcesAgg;\n }\n\n async fetchPrompts() {\n let promptsAgg: Prompt[] = [];\n let promptsResult: ListPromptsResult = { prompts: [] };\n do {\n promptsResult = await this.client\n .listPrompts({\n cursor: promptsResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ prompts: [] }, \"prompts/list\"));\n promptsAgg = promptsAgg.concat(promptsResult.prompts);\n } while (promptsResult.nextCursor);\n return promptsAgg;\n }\n\n async fetchResourceTemplates() {\n let templatesAgg: ResourceTemplate[] = [];\n let templatesResult: ListResourceTemplatesResult = {\n resourceTemplates: [],\n };\n do {\n templatesResult = await this.client\n .listResourceTemplates({\n cursor: templatesResult.nextCursor,\n })\n .catch(\n capabilityErrorHandler(\n { resourceTemplates: [] },\n \"resources/templates/list\"\n )\n );\n templatesAgg = templatesAgg.concat(templatesResult.resourceTemplates);\n } while (templatesResult.nextCursor);\n return templatesAgg;\n }\n}\n\nfunction capabilityErrorHandler<T>(empty: T, method: string) {\n return (e: { code: number }) => {\n // server is badly behaved and returning invalid capabilities. This commonly occurs for resource templates\n if (e.code === -32601) {\n console.error(\n `The server advertised support for the capability ${method.split(\"/\")[0]}, but returned \"Method not found\" for '${method}'.`\n );\n return empty;\n }\n throw e;\n };\n}\n","import { MCPClientConnection } from \"./client-connection\";\n\nimport type {\n ClientCapabilities,\n CallToolRequest,\n CallToolResultSchema,\n CompatibilityCallToolResultSchema,\n ReadResourceRequest,\n GetPromptRequest,\n Tool,\n Resource,\n Prompt,\n ResourceTemplate,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport type { AgentsOAuthProvider } from \"./do-oauth-client-provider\";\nimport { jsonSchema, type ToolSet } from \"ai\";\nimport { nanoid } from \"nanoid\";\n\n/**\n * Utility class that aggregates multiple MCP clients into one\n */\nexport class MCPClientManager {\n public mcpConnections: Record<string, MCPClientConnection> = {};\n private callbackUrls: string[] = [];\n\n /**\n * @param name Name of the MCP client\n * @param version Version of the MCP Client\n * @param auth Auth paramters if being used to create a DurableObjectOAuthClientProvider\n */\n constructor(\n private name: string,\n private version: string\n ) {}\n\n /**\n * Connect to and register an MCP server\n *\n * @param transportConfig Transport config\n * @param clientConfig Client config\n * @param capabilities Client capabilities (i.e. if the client supports roots/sampling)\n */\n async connect(\n url: string,\n options: {\n // Allows you to reconnect to a server (in the case of a auth reconnect)\n // Doesn't handle session reconnection\n reconnect?: {\n id: string;\n oauthClientId?: string;\n oauthCode?: string;\n };\n // we're overriding authProvider here because we want to be able to access the auth URL\n transport?: SSEClientTransportOptions & {\n authProvider?: AgentsOAuthProvider;\n };\n client?: ConstructorParameters<typeof Client>[1];\n capabilities?: ClientCapabilities;\n } = {}\n ): Promise<{ id: string; authUrl: string | undefined }> {\n const id = options.reconnect?.id ?? nanoid(8);\n\n if (!options.transport?.authProvider) {\n console.warn(\n \"No authProvider provided in the transport options. This client will only support unauthenticated remote MCP Servers\"\n );\n } else {\n options.transport.authProvider.serverId = id;\n }\n\n this.mcpConnections[id] = new MCPClientConnection(\n new URL(url),\n {\n name: this.name,\n version: this.version,\n },\n {\n transport: options.transport ?? {},\n client: options.client ?? {},\n capabilities: options.client ?? {},\n }\n );\n\n await this.mcpConnections[id].init(\n options.reconnect?.oauthCode,\n options.reconnect?.oauthClientId\n );\n\n const authUrl = options.transport?.authProvider?.authUrl;\n if (authUrl && options.transport?.authProvider?.redirectUrl) {\n this.callbackUrls.push(\n options.transport.authProvider.redirectUrl.toString()\n );\n }\n\n return {\n id,\n authUrl,\n };\n }\n\n isCallbackRequest(req: Request): boolean {\n return (\n req.method === \"GET\" &&\n !!this.callbackUrls.find((url) => {\n return req.url.startsWith(url);\n })\n );\n }\n\n async handleCallbackRequest(req: Request) {\n const url = new URL(req.url);\n const urlMatch = this.callbackUrls.find((url) => {\n return req.url.startsWith(url);\n });\n if (!urlMatch) {\n throw new Error(\n `No callback URI match found for the request url: ${req.url}. Was the request matched with \\`isCallbackRequest()\\`?`\n );\n }\n const code = url.searchParams.get(\"code\");\n const clientId = url.searchParams.get(\"state\");\n const urlParams = urlMatch.split(\"/\");\n const serverId = urlParams[urlParams.length - 1];\n if (!code) {\n throw new Error(\"Unauthorized: no code provided\");\n }\n if (!clientId) {\n throw new Error(\"Unauthorized: no state provided\");\n }\n\n if (this.mcpConnections[serverId] === undefined) {\n throw new Error(`Could not find serverId: ${serverId}`);\n }\n\n if (this.mcpConnections[serverId].connectionState !== \"authenticating\") {\n throw new Error(\n \"Failed to authenticate: the client isn't in the `authenticating` state\"\n );\n }\n\n const conn = this.mcpConnections[serverId];\n if (!conn.options.transport.authProvider) {\n throw new Error(\n \"Trying to finalize authentication for a server connection without an authProvider\"\n );\n }\n\n conn.options.transport.authProvider.clientId = clientId;\n conn.options.transport.authProvider.serverId = serverId;\n\n // reconnect to server with authorization\n const serverUrl = conn.url.toString();\n await this.connect(serverUrl, {\n reconnect: {\n id: serverId,\n oauthClientId: clientId,\n oauthCode: code,\n },\n ...conn.options,\n });\n\n if (this.mcpConnections[serverId].connectionState === \"authenticating\") {\n throw new Error(\"Failed to authenticate: client failed to initialize\");\n }\n\n return { serverId };\n }\n\n /**\n * @returns namespaced list of tools\n */\n listTools(): NamespacedData[\"tools\"] {\n return getNamespacedData(this.mcpConnections, \"tools\");\n }\n\n /**\n * @returns a set of tools that you can use with the AI SDK\n */\n unstable_getAITools(): ToolSet {\n return Object.fromEntries(\n getNamespacedData(this.mcpConnections, \"tools\").map((tool) => {\n return [\n `${tool.serverId}.${tool.name}`,\n {\n parameters: jsonSchema(tool.inputSchema),\n description: tool.description,\n execute: async (args) => {\n const result = await this.callTool({\n name: tool.name,\n arguments: args,\n serverId: tool.serverId,\n });\n if (result.isError) {\n // @ts-expect-error TODO we should fix this\n throw new Error(result.content[0].text);\n }\n return result;\n },\n },\n ];\n })\n );\n }\n\n /**\n * @returns namespaced list of prompts\n */\n listPrompts(): NamespacedData[\"prompts\"] {\n return getNamespacedData(this.mcpConnections, \"prompts\");\n }\n\n /**\n * @returns namespaced list of tools\n */\n listResources(): NamespacedData[\"resources\"] {\n return getNamespacedData(this.mcpConnections, \"resources\");\n }\n\n /**\n * @returns namespaced list of resource templates\n */\n listResourceTemplates(): NamespacedData[\"resourceTemplates\"] {\n return getNamespacedData(this.mcpConnections, \"resourceTemplates\");\n }\n\n /**\n * Namespaced version of callTool\n */\n callTool(\n params: CallToolRequest[\"params\"] & { serverId: string },\n resultSchema?:\n | typeof CallToolResultSchema\n | typeof CompatibilityCallToolResultSchema,\n options?: RequestOptions\n ) {\n const unqualifiedName = params.name.replace(`${params.serverId}.`, \"\");\n return this.mcpConnections[params.serverId].client.callTool(\n {\n ...params,\n name: unqualifiedName,\n },\n resultSchema,\n options\n );\n }\n\n /**\n * Namespaced version of readResource\n */\n readResource(\n params: ReadResourceRequest[\"params\"] & { serverId: string },\n options: RequestOptions\n ) {\n return this.mcpConnections[params.serverId].client.readResource(\n params,\n options\n );\n }\n\n /**\n * Namespaced version of getPrompt\n */\n getPrompt(\n params: GetPromptRequest[\"params\"] & { serverId: string },\n options: RequestOptions\n ) {\n return this.mcpConnections[params.serverId].client.getPrompt(\n params,\n options\n );\n }\n}\n\ntype NamespacedData = {\n tools: (Tool & { serverId: string })[];\n prompts: (Prompt & { serverId: string })[];\n resources: (Resource & { serverId: string })[];\n resourceTemplates: (ResourceTemplate & { serverId: string })[];\n};\n\nexport function getNamespacedData<T extends keyof NamespacedData>(\n mcpClients: Record<string, MCPClientConnection>,\n type: T\n): NamespacedData[T] {\n const sets = Object.entries(mcpClients).map(([name, conn]) => {\n return { name, data: conn[type] };\n });\n\n const namespacedData = sets.flatMap(({ name: serverId, data }) => {\n return data.map((item) => {\n return {\n ...item,\n // we add a serverId so we can easily pull it out and send the tool call to the right server\n serverId,\n };\n });\n });\n\n return namespacedData as NamespacedData[T]; // Type assertion needed due to TS limitations with conditional return types\n}\n"],"mappings":"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","names":["url"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MCPClientManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WNICV3OI.js";
|
|
4
4
|
import {
|
|
5
5
|
__privateAdd,
|
|
6
6
|
__privateGet,
|
|
@@ -594,4 +594,4 @@ export {
|
|
|
594
594
|
getAgentByName,
|
|
595
595
|
StreamingResponse
|
|
596
596
|
};
|
|
597
|
-
//# sourceMappingURL=chunk-
|
|
597
|
+
//# sourceMappingURL=chunk-ZRZEISHY.js.map
|
package/dist/index.js
CHANGED
package/dist/mcp/client.js
CHANGED
package/dist/mcp/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ interface CORSOptions {
|
|
|
19
19
|
headers?: string;
|
|
20
20
|
maxAge?: number;
|
|
21
21
|
}
|
|
22
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
22
23
|
declare abstract class McpAgent<Env = unknown, State = unknown, Props extends Record<string, unknown> = Record<string, unknown>> extends DurableObject<Env> {
|
|
23
24
|
#private;
|
|
24
25
|
get mcp(): MCPClientManager;
|
|
@@ -35,7 +36,7 @@ declare abstract class McpAgent<Env = unknown, State = unknown, Props extends Re
|
|
|
35
36
|
/**
|
|
36
37
|
* McpAgent API
|
|
37
38
|
*/
|
|
38
|
-
abstract server: McpServer | Server
|
|
39
|
+
abstract server: MaybePromise<McpServer | Server>;
|
|
39
40
|
props: Props;
|
|
40
41
|
initRun: boolean;
|
|
41
42
|
abstract init(): Promise<void>;
|
|
@@ -54,19 +55,19 @@ declare abstract class McpAgent<Env = unknown, State = unknown, Props extends Re
|
|
|
54
55
|
binding?: string;
|
|
55
56
|
corsOptions?: CORSOptions;
|
|
56
57
|
}): {
|
|
57
|
-
fetch
|
|
58
|
+
fetch<Env>(request: Request, env: Env, ctx: ExecutionContext): Promise<Response>;
|
|
58
59
|
};
|
|
59
60
|
static serveSSE(path: string, { binding, corsOptions, }?: {
|
|
60
61
|
binding?: string;
|
|
61
62
|
corsOptions?: CORSOptions;
|
|
62
63
|
}): {
|
|
63
|
-
fetch
|
|
64
|
+
fetch<Env>(request: Request, env: Env, ctx: ExecutionContext): Promise<Response>;
|
|
64
65
|
};
|
|
65
66
|
static serve(path: string, { binding, corsOptions, }?: {
|
|
66
67
|
binding?: string;
|
|
67
68
|
corsOptions?: CORSOptions;
|
|
68
69
|
}): {
|
|
69
|
-
fetch
|
|
70
|
+
fetch<Env>(request: Request, env: Env, ctx: ExecutionContext): Promise<Response>;
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
73
|
|
package/dist/mcp/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Agent
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-ZRZEISHY.js";
|
|
4
|
+
import "../chunk-WNICV3OI.js";
|
|
5
5
|
import {
|
|
6
6
|
__privateAdd,
|
|
7
7
|
__privateGet,
|
|
@@ -189,15 +189,16 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
189
189
|
"transportType"
|
|
190
190
|
));
|
|
191
191
|
await this._init(this.props);
|
|
192
|
+
const server = await this.server;
|
|
192
193
|
if (__privateGet(this, _transportType) === "sse") {
|
|
193
194
|
__privateSet(this, _transport, new McpSSETransport(() => this.getWebSocket()));
|
|
194
|
-
await
|
|
195
|
+
await server.connect(__privateGet(this, _transport));
|
|
195
196
|
} else if (__privateGet(this, _transportType) === "streamable-http") {
|
|
196
197
|
__privateSet(this, _transport, new McpStreamableHttpTransport(
|
|
197
198
|
(id) => this.getWebSocketForResponseID(id),
|
|
198
199
|
(id) => __privateGet(this, _requestIdToConnectionId).delete(id)
|
|
199
200
|
));
|
|
200
|
-
await
|
|
201
|
+
await server.connect(__privateGet(this, _transport));
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
async _init(props) {
|
|
@@ -229,6 +230,7 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
229
230
|
}
|
|
230
231
|
const url = new URL(request.url);
|
|
231
232
|
const path = url.pathname;
|
|
233
|
+
const server = await this.server;
|
|
232
234
|
switch (path) {
|
|
233
235
|
case "/sse": {
|
|
234
236
|
const websockets = this.ctx.getWebSockets();
|
|
@@ -239,7 +241,7 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
239
241
|
__privateSet(this, _transportType, "sse");
|
|
240
242
|
if (!__privateGet(this, _transport)) {
|
|
241
243
|
__privateSet(this, _transport, new McpSSETransport(() => this.getWebSocket()));
|
|
242
|
-
await
|
|
244
|
+
await server.connect(__privateGet(this, _transport));
|
|
243
245
|
}
|
|
244
246
|
return __privateGet(this, _agent).fetch(request);
|
|
245
247
|
}
|
|
@@ -249,7 +251,7 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
249
251
|
(id) => this.getWebSocketForResponseID(id),
|
|
250
252
|
(id) => __privateGet(this, _requestIdToConnectionId).delete(id)
|
|
251
253
|
));
|
|
252
|
-
await
|
|
254
|
+
await server.connect(__privateGet(this, _transport));
|
|
253
255
|
}
|
|
254
256
|
await this.ctx.storage.put("transportType", "streamable-http");
|
|
255
257
|
__privateSet(this, _transportType, "streamable-http");
|
|
@@ -362,11 +364,21 @@ var _McpAgent = class _McpAgent extends DurableObject {
|
|
|
362
364
|
const basePattern = new URLPattern({ pathname });
|
|
363
365
|
const messagePattern = new URLPattern({ pathname: `${pathname}/message` });
|
|
364
366
|
return {
|
|
365
|
-
|
|
367
|
+
async fetch(request, env, ctx) {
|
|
366
368
|
const corsResponse = handleCORS(request, corsOptions);
|
|
367
369
|
if (corsResponse) return corsResponse;
|
|
368
370
|
const url = new URL(request.url);
|
|
369
|
-
const
|
|
371
|
+
const bindingValue = env[binding];
|
|
372
|
+
if (bindingValue == null || typeof bindingValue !== "object") {
|
|
373
|
+
console.error(
|
|
374
|
+
`Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`
|
|
375
|
+
);
|
|
376
|
+
return new Response("Invalid binding", { status: 500 });
|
|
377
|
+
}
|
|
378
|
+
if (bindingValue.toString() !== "[object DurableObjectNamespace]") {
|
|
379
|
+
return new Response("Invalid binding", { status: 500 });
|
|
380
|
+
}
|
|
381
|
+
const namespace = bindingValue;
|
|
370
382
|
if (request.method === "GET" && basePattern.test(url)) {
|
|
371
383
|
const sessionId = url.searchParams.get("sessionId") || namespace.newUniqueId().toString();
|
|
372
384
|
const { readable, writable } = new TransformStream();
|
|
@@ -515,13 +527,23 @@ data: ${JSON.stringify(result.data)}
|
|
|
515
527
|
}
|
|
516
528
|
const basePattern = new URLPattern({ pathname });
|
|
517
529
|
return {
|
|
518
|
-
|
|
530
|
+
async fetch(request, env, ctx) {
|
|
519
531
|
const corsResponse = handleCORS(request, corsOptions);
|
|
520
532
|
if (corsResponse) {
|
|
521
533
|
return corsResponse;
|
|
522
534
|
}
|
|
523
535
|
const url = new URL(request.url);
|
|
524
|
-
const
|
|
536
|
+
const bindingValue = env[binding];
|
|
537
|
+
if (bindingValue == null || typeof bindingValue !== "object") {
|
|
538
|
+
console.error(
|
|
539
|
+
`Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`
|
|
540
|
+
);
|
|
541
|
+
return new Response("Invalid binding", { status: 500 });
|
|
542
|
+
}
|
|
543
|
+
if (bindingValue.toString() !== "[object DurableObjectNamespace]") {
|
|
544
|
+
return new Response("Invalid binding", { status: 500 });
|
|
545
|
+
}
|
|
546
|
+
const namespace = bindingValue;
|
|
525
547
|
if (request.method === "POST" && basePattern.test(url)) {
|
|
526
548
|
const acceptHeader = request.headers.get("accept");
|
|
527
549
|
if (!acceptHeader?.includes("application/json") || !acceptHeader.includes("text/event-stream")) {
|
package/dist/mcp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/mcp/index.ts"],"sourcesContent":["import { DurableObject } from \"cloudflare:workers\";\nimport { Agent } from \"../\";\nimport type { WSMessage } from \"../\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Connection } from \"../\";\nimport type {\n JSONRPCError,\n JSONRPCMessage,\n JSONRPCNotification,\n JSONRPCRequest,\n JSONRPCResponse,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n InitializeRequestSchema,\n isJSONRPCError,\n isJSONRPCNotification,\n isJSONRPCRequest,\n isJSONRPCResponse,\n JSONRPCErrorSchema,\n JSONRPCMessageSchema,\n JSONRPCNotificationSchema,\n JSONRPCRequestSchema,\n JSONRPCResponseSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\n\nconst MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024; // 4MB\n\n// CORS helper function\nfunction handleCORS(\n request: Request,\n corsOptions?: CORSOptions\n): Response | null {\n const origin = request.headers.get(\"Origin\") || \"*\";\n const corsHeaders = {\n \"Access-Control-Allow-Origin\": corsOptions?.origin || origin,\n \"Access-Control-Allow-Methods\":\n corsOptions?.methods || \"GET, POST, OPTIONS\",\n \"Access-Control-Allow-Headers\": corsOptions?.headers || \"Content-Type\",\n \"Access-Control-Max-Age\": (corsOptions?.maxAge || 86400).toString(),\n };\n\n if (request.method === \"OPTIONS\") {\n return new Response(null, { headers: corsHeaders });\n }\n\n return null;\n}\n\ninterface CORSOptions {\n origin?: string;\n methods?: string;\n headers?: string;\n maxAge?: number;\n}\n\nclass McpSSETransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n sessionId?: string;\n\n #getWebSocket: () => WebSocket | null;\n #started = false;\n constructor(getWebSocket: () => WebSocket | null) {\n this.#getWebSocket = getWebSocket;\n }\n\n async start() {\n // The transport does not manage the WebSocket connection since it's terminated\n // by the Durable Object in order to allow hibernation. There's nothing to initialize.\n if (this.#started) {\n throw new Error(\"Transport already started\");\n }\n this.#started = true;\n }\n\n async send(message: JSONRPCMessage) {\n if (!this.#started) {\n throw new Error(\"Transport not started\");\n }\n const websocket = this.#getWebSocket();\n if (!websocket) {\n throw new Error(\"WebSocket not connected\");\n }\n try {\n websocket.send(JSON.stringify(message));\n } catch (error) {\n this.onerror?.(error as Error);\n throw error;\n }\n }\n\n async close() {\n // Similar to start, the only thing to do is to pass the event on to the server\n this.onclose?.();\n }\n}\n\ntype TransportType = \"sse\" | \"streamable-http\" | \"unset\";\n\nclass McpStreamableHttpTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n sessionId?: string;\n\n // TODO: If there is an open connection to send server-initiated messages\n // back, we should use that connection\n #getWebSocketForGetRequest: () => WebSocket | null;\n\n // Get the appropriate websocket connection for a given message id\n #getWebSocketForMessageID: (id: string) => WebSocket | null;\n\n // Notify the server that a response has been sent for a given message id\n // so that it may clean up it's mapping of message ids to connections\n // once they are no longer needed\n #notifyResponseIdSent: (id: string) => void;\n\n #started = false;\n constructor(\n getWebSocketForMessageID: (id: string) => WebSocket | null,\n notifyResponseIdSent: (id: string | number) => void\n ) {\n this.#getWebSocketForMessageID = getWebSocketForMessageID;\n this.#notifyResponseIdSent = notifyResponseIdSent;\n // TODO\n this.#getWebSocketForGetRequest = () => null;\n }\n\n async start() {\n // The transport does not manage the WebSocket connection since it's terminated\n // by the Durable Object in order to allow hibernation. There's nothing to initialize.\n if (this.#started) {\n throw new Error(\"Transport already started\");\n }\n this.#started = true;\n }\n\n async send(message: JSONRPCMessage) {\n if (!this.#started) {\n throw new Error(\"Transport not started\");\n }\n\n let websocket: WebSocket | null = null;\n\n if (isJSONRPCResponse(message) || isJSONRPCError(message)) {\n websocket = this.#getWebSocketForMessageID(message.id.toString());\n if (!websocket) {\n throw new Error(\n `Could not find WebSocket for message id: ${message.id}`\n );\n }\n } else if (isJSONRPCRequest(message)) {\n // requests originating from the server must be sent over the\n // the connection created by a GET request\n websocket = this.#getWebSocketForGetRequest();\n } else if (isJSONRPCNotification(message)) {\n // notifications do not have an id\n // but do have a relatedRequestId field\n // so that they can be sent to the correct connection\n websocket = null;\n }\n\n try {\n websocket?.send(JSON.stringify(message));\n if (isJSONRPCResponse(message)) {\n this.#notifyResponseIdSent(message.id.toString());\n }\n } catch (error) {\n this.onerror?.(error as Error);\n throw error;\n }\n }\n\n async close() {\n // Similar to start, the only thing to do is to pass the event on to the server\n this.onclose?.();\n }\n}\n\nexport abstract class McpAgent<\n Env = unknown,\n State = unknown,\n Props extends Record<string, unknown> = Record<string, unknown>,\n> extends DurableObject<Env> {\n #status: \"zero\" | \"starting\" | \"started\" = \"zero\";\n #transport?: Transport;\n #transportType: TransportType = \"unset\";\n #requestIdToConnectionId: Map<string | number, string> = new Map();\n\n /**\n * Since McpAgent's _aren't_ yet real \"Agents\", let's only expose a couple of the methods\n * to the outer class: initialState/state/setState/onStateUpdate/sql\n */\n #agent: Agent<Env, State>;\n\n get mcp() {\n return this.#agent.mcp;\n }\n\n protected constructor(ctx: DurableObjectState, env: Env) {\n super(ctx, env);\n const self = this;\n\n this.#agent = new (class extends Agent<Env, State> {\n static options = {\n hibernate: true,\n };\n\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n return self.onStateUpdate(state, source);\n }\n\n async onMessage(\n connection: Connection,\n message: WSMessage\n ): Promise<void> {\n return self.onMessage(connection, message);\n }\n })(ctx, env);\n }\n\n /**\n * Agents API allowlist\n */\n initialState!: State;\n get state() {\n return this.#agent.state;\n }\n sql<T = Record<string, string | number | boolean | null>>(\n strings: TemplateStringsArray,\n ...values: (string | number | boolean | null)[]\n ) {\n return this.#agent.sql<T>(strings, ...values);\n }\n\n setState(state: State) {\n return this.#agent.setState(state);\n }\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n // override this to handle state updates\n }\n async onStart() {\n const self = this;\n\n this.#agent = new (class extends Agent<Env, State> {\n initialState: State = self.initialState;\n static options = {\n hibernate: true,\n };\n\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n return self.onStateUpdate(state, source);\n }\n\n async onMessage(connection: Connection, event: WSMessage) {\n return self.onMessage(connection, event);\n }\n })(this.ctx, this.env);\n\n this.props = (await this.ctx.storage.get(\"props\")) as Props;\n this.#transportType = (await this.ctx.storage.get(\n \"transportType\"\n )) as TransportType;\n await this._init(this.props);\n\n // Connect to the MCP server\n if (this.#transportType === \"sse\") {\n this.#transport = new McpSSETransport(() => this.getWebSocket());\n await this.server.connect(this.#transport);\n } else if (this.#transportType === \"streamable-http\") {\n this.#transport = new McpStreamableHttpTransport(\n (id) => this.getWebSocketForResponseID(id),\n (id) => this.#requestIdToConnectionId.delete(id)\n );\n await this.server.connect(this.#transport);\n }\n }\n\n /**\n * McpAgent API\n */\n abstract server: McpServer | Server;\n props!: Props;\n initRun = false;\n\n abstract init(): Promise<void>;\n\n async _init(props: Props) {\n await this.ctx.storage.put(\"props\", props ?? {});\n if (!this.ctx.storage.get(\"transportType\")) {\n await this.ctx.storage.put(\"transportType\", \"unset\");\n }\n this.props = props;\n if (!this.initRun) {\n this.initRun = true;\n await this.init();\n }\n }\n\n async setInitialized() {\n await this.ctx.storage.put(\"initialized\", true);\n }\n\n async isInitialized() {\n return (await this.ctx.storage.get(\"initialized\")) === true;\n }\n\n async #initialize(): Promise<void> {\n await this.ctx.blockConcurrencyWhile(async () => {\n this.#status = \"starting\";\n await this.onStart();\n this.#status = \"started\";\n });\n }\n\n // Allow the worker to fetch a websocket connection to the agent\n async fetch(request: Request): Promise<Response> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n\n // Only handle WebSocket upgrade requests\n if (request.headers.get(\"Upgrade\") !== \"websocket\") {\n return new Response(\"Expected WebSocket Upgrade request\", {\n status: 400,\n });\n }\n\n // This request does not come from the user. The worker generates this\n // request to generate a websocket connection to the agent.\n const url = new URL(request.url);\n // This is not the path that the user requested, but the path that the worker\n // generated. We'll use this path to determine which transport to use.\n const path = url.pathname;\n\n switch (path) {\n case \"/sse\": {\n // For SSE connections, we can only have one open connection per session\n // If we get an upgrade while already connected, we should error\n const websockets = this.ctx.getWebSockets();\n if (websockets.length > 0) {\n return new Response(\"Websocket already connected\", { status: 400 });\n }\n\n // This session must always use the SSE transporo\n await this.ctx.storage.put(\"transportType\", \"sse\");\n this.#transportType = \"sse\";\n\n if (!this.#transport) {\n this.#transport = new McpSSETransport(() => this.getWebSocket());\n await this.server.connect(this.#transport);\n }\n\n // Defer to the Agent's fetch method to handle the WebSocket connection\n return this.#agent.fetch(request);\n }\n case \"/streamable-http\": {\n if (!this.#transport) {\n this.#transport = new McpStreamableHttpTransport(\n (id) => this.getWebSocketForResponseID(id),\n (id) => this.#requestIdToConnectionId.delete(id)\n );\n await this.server.connect(this.#transport);\n }\n\n // This session must always use the streamable-http transport\n await this.ctx.storage.put(\"transportType\", \"streamable-http\");\n this.#transportType = \"streamable-http\";\n\n return this.#agent.fetch(request);\n }\n default:\n return new Response(\n \"Internal Server Error: Expected /sse or /streamable-http path\",\n {\n status: 500,\n }\n );\n }\n }\n\n getWebSocket() {\n const websockets = this.ctx.getWebSockets();\n if (websockets.length === 0) {\n return null;\n }\n return websockets[0];\n }\n\n getWebSocketForResponseID(id: string): WebSocket | null {\n const connectionId = this.#requestIdToConnectionId.get(id);\n if (connectionId === undefined) {\n return null;\n }\n return this.#agent.getConnection(connectionId) ?? null;\n }\n\n // All messages received here. This is currently never called\n async onMessage(connection: Connection, event: WSMessage) {\n // Since we address the DO via both the protocol and the session id,\n // this should never happen, but let's enforce it just in case\n if (this.#transportType !== \"streamable-http\") {\n const err = new Error(\n \"Internal Server Error: Expected streamable-http protocol\"\n );\n this.#transport?.onerror?.(err);\n return;\n }\n\n let message: JSONRPCMessage;\n try {\n // Ensure event is a string\n const data =\n typeof event === \"string\" ? event : new TextDecoder().decode(event);\n message = JSONRPCMessageSchema.parse(JSON.parse(data));\n } catch (error) {\n this.#transport?.onerror?.(error as Error);\n return;\n }\n\n // We need to map every incoming message to the connection that it came in on\n // so that we can send relevant responses and notifications back on the same connection\n if (isJSONRPCRequest(message)) {\n this.#requestIdToConnectionId.set(message.id.toString(), connection.id);\n }\n\n this.#transport?.onmessage?.(message);\n }\n\n // All messages received over SSE after the initial connection has been established\n // will be passed here\n async onSSEMcpMessage(\n sessionId: string,\n request: Request\n ): Promise<Error | null> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n\n // Since we address the DO via both the protocol and the session id,\n // this should never happen, but let's enforce it just in case\n if (this.#transportType !== \"sse\") {\n return new Error(\"Internal Server Error: Expected SSE protocol\");\n }\n\n try {\n const message = await request.json();\n let parsedMessage: JSONRPCMessage;\n try {\n parsedMessage = JSONRPCMessageSchema.parse(message);\n } catch (error) {\n this.#transport?.onerror?.(error as Error);\n throw error;\n }\n\n this.#transport?.onmessage?.(parsedMessage);\n return null;\n } catch (error) {\n this.#transport?.onerror?.(error as Error);\n return error as Error;\n }\n }\n\n // Delegate all websocket events to the underlying agent\n async webSocketMessage(\n ws: WebSocket,\n event: ArrayBuffer | string\n ): Promise<void> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n return await this.#agent.webSocketMessage(ws, event);\n }\n\n // WebSocket event handlers for hibernation support\n async webSocketError(ws: WebSocket, error: unknown): Promise<void> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n return await this.#agent.webSocketError(ws, error);\n }\n\n async webSocketClose(\n ws: WebSocket,\n code: number,\n reason: string,\n wasClean: boolean\n ): Promise<void> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n return await this.#agent.webSocketClose(ws, code, reason, wasClean);\n }\n\n static mount(\n path: string,\n {\n binding = \"MCP_OBJECT\",\n corsOptions,\n }: {\n binding?: string;\n corsOptions?: CORSOptions;\n } = {}\n ) {\n return McpAgent.serveSSE(path, { binding, corsOptions });\n }\n\n static serveSSE(\n path: string,\n {\n binding = \"MCP_OBJECT\",\n corsOptions,\n }: {\n binding?: string;\n corsOptions?: CORSOptions;\n } = {}\n ) {\n let pathname = path;\n if (path === \"/\") {\n pathname = \"/*\";\n }\n const basePattern = new URLPattern({ pathname });\n const messagePattern = new URLPattern({ pathname: `${pathname}/message` });\n\n return {\n fetch: async (\n request: Request,\n env: Record<string, DurableObjectNamespace<McpAgent>>,\n ctx: ExecutionContext\n ): Promise<Response> => {\n // Handle CORS preflight\n const corsResponse = handleCORS(request, corsOptions);\n if (corsResponse) return corsResponse;\n\n const url = new URL(request.url);\n const namespace = env[binding];\n\n // Handle initial SSE connection\n if (request.method === \"GET\" && basePattern.test(url)) {\n // Use a session ID if one is passed in, or create a unique\n // session ID for this connection\n const sessionId =\n url.searchParams.get(\"sessionId\") ||\n namespace.newUniqueId().toString();\n\n // Create a Transform Stream for SSE\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n // Send the endpoint event\n const endpointUrl = new URL(request.url);\n endpointUrl.pathname = encodeURI(`${pathname}/message`);\n endpointUrl.searchParams.set(\"sessionId\", sessionId);\n const relativeUrlWithSession =\n endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;\n const endpointMessage = `event: endpoint\\ndata: ${relativeUrlWithSession}\\n\\n`;\n writer.write(encoder.encode(endpointMessage));\n\n // Get the Durable Object\n const id = namespace.idFromName(`sse:${sessionId}`);\n const doStub = namespace.get(id);\n\n // Initialize the object\n await doStub._init(ctx.props);\n\n // Connect to the Durable Object via WebSocket\n const upgradeUrl = new URL(request.url);\n // enforce that the path that the DO receives is always /sse\n upgradeUrl.pathname = \"/sse\";\n const response = await doStub.fetch(\n new Request(upgradeUrl, {\n headers: {\n Upgrade: \"websocket\",\n // Required by PartyServer\n \"x-partykit-room\": sessionId,\n },\n })\n );\n\n // Get the WebSocket\n const ws = response.webSocket;\n if (!ws) {\n console.error(\"Failed to establish WebSocket connection\");\n await writer.close();\n return new Response(\"Failed to establish WebSocket connection\", {\n status: 500,\n });\n }\n\n // Accept the WebSocket\n ws.accept();\n\n // Handle messages from the Durable Object\n ws.addEventListener(\"message\", (event) => {\n async function onMessage(event: MessageEvent) {\n try {\n const message = JSON.parse(event.data);\n\n // validate that the message is a valid JSONRPC message\n const result = JSONRPCMessageSchema.safeParse(message);\n if (!result.success) {\n // The message was not a valid JSONRPC message, so we will drop it\n // PartyKit will broadcast state change messages to all connected clients\n // and we need to filter those out so they are not passed to MCP clients\n return;\n }\n\n // Send the message as an SSE event\n const messageText = `event: message\\ndata: ${JSON.stringify(result.data)}\\n\\n`;\n await writer.write(encoder.encode(messageText));\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n }\n }\n onMessage(event).catch(console.error);\n });\n\n // Handle WebSocket errors\n ws.addEventListener(\"error\", (error) => {\n async function onError(error: Event) {\n try {\n await writer.close();\n } catch (e) {\n // Ignore errors when closing\n }\n }\n onError(error).catch(console.error);\n });\n\n // Handle WebSocket closure\n ws.addEventListener(\"close\", () => {\n async function onClose() {\n try {\n await writer.close();\n } catch (error) {\n console.error(\"Error closing SSE connection:\", error);\n }\n }\n onClose().catch(console.error);\n });\n\n // Return the SSE response\n return new Response(readable, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": corsOptions?.origin || \"*\",\n },\n });\n }\n\n // Handle incoming MCP messages. These will be passed to McpAgent\n // but the response will be sent back via the open SSE connection\n // so we only need to return a 202 Accepted response for success\n if (request.method === \"POST\" && messagePattern.test(url)) {\n const sessionId = url.searchParams.get(\"sessionId\");\n if (!sessionId) {\n return new Response(\n `Missing sessionId. Expected POST to ${pathname} to initiate new one`,\n { status: 400 }\n );\n }\n\n const contentType = request.headers.get(\"content-type\") || \"\";\n if (!contentType.includes(\"application/json\")) {\n return new Response(`Unsupported content-type: ${contentType}`, {\n status: 400,\n });\n }\n\n // check if the request body is too large\n const contentLength = Number.parseInt(\n request.headers.get(\"content-length\") || \"0\",\n 10\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {\n return new Response(\n `Request body too large: ${contentLength} bytes`,\n {\n status: 400,\n }\n );\n }\n\n // Get the Durable Object\n const id = namespace.idFromName(`sse:${sessionId}`);\n const doStub = namespace.get(id);\n\n // Forward the request to the Durable Object\n const error = await doStub.onSSEMcpMessage(sessionId, request);\n\n if (error) {\n return new Response(error.message, {\n status: 400,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": corsOptions?.origin || \"*\",\n },\n });\n }\n\n return new Response(\"Accepted\", {\n status: 202,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": corsOptions?.origin || \"*\",\n },\n });\n }\n\n return new Response(\"Not Found\", { status: 404 });\n },\n };\n }\n\n static serve(\n path: string,\n {\n binding = \"MCP_OBJECT\",\n corsOptions,\n }: { binding?: string; corsOptions?: CORSOptions } = {}\n ) {\n let pathname = path;\n if (path === \"/\") {\n pathname = \"/*\";\n }\n const basePattern = new URLPattern({ pathname });\n\n return {\n fetch: async (\n request: Request,\n env: Record<string, DurableObjectNamespace<McpAgent>>,\n ctx: ExecutionContext\n ) => {\n // Handle CORS preflight\n const corsResponse = handleCORS(request, corsOptions);\n if (corsResponse) {\n return corsResponse;\n }\n\n const url = new URL(request.url);\n const namespace = env[binding];\n\n if (request.method === \"POST\" && basePattern.test(url)) {\n // validate the Accept header\n const acceptHeader = request.headers.get(\"accept\");\n // The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.\n if (\n !acceptHeader?.includes(\"application/json\") ||\n !acceptHeader.includes(\"text/event-stream\")\n ) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message:\n \"Not Acceptable: Client must accept both application/json and text/event-stream\",\n },\n id: null,\n });\n return new Response(body, { status: 406 });\n }\n\n const ct = request.headers.get(\"content-type\");\n if (!ct || !ct.includes(\"application/json\")) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message:\n \"Unsupported Media Type: Content-Type must be application/json\",\n },\n id: null,\n });\n return new Response(body, { status: 415 });\n }\n\n // Check content length against maximum allowed size\n const contentLength = Number.parseInt(\n request.headers.get(\"content-length\") ?? \"0\",\n 10\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`,\n },\n id: null,\n });\n return new Response(body, { status: 413 });\n }\n\n let sessionId = request.headers.get(\"mcp-session-id\");\n let rawMessage: unknown;\n\n try {\n rawMessage = await request.json();\n } catch (error) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n\n // Make sure the message is an array to simplify logic\n let arrayMessage: unknown[];\n if (Array.isArray(rawMessage)) {\n arrayMessage = rawMessage;\n } else {\n arrayMessage = [rawMessage];\n }\n\n let messages: JSONRPCMessage[] = [];\n\n // Try to parse each message as JSON RPC. Fail if any message is invalid\n for (const msg of arrayMessage) {\n if (!JSONRPCMessageSchema.safeParse(msg).success) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON-RPC message\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n }\n\n messages = arrayMessage.map((msg) => JSONRPCMessageSchema.parse(msg));\n\n // Before we pass the messages to the agent, there's another error condition we need to enforce\n // Check if this is an initialization request\n // https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle/\n const isInitializationRequest = messages.some(\n (msg) => InitializeRequestSchema.safeParse(msg).success\n );\n\n if (isInitializationRequest && sessionId) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32600,\n message:\n \"Invalid Request: Initialization requests must not include a sessionId\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n\n // The initialization request must be the only request in the batch\n if (isInitializationRequest && messages.length > 1) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32600,\n message:\n \"Invalid Request: Only one initialization request is allowed\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n\n // If an Mcp-Session-Id is returned by the server during initialization,\n // clients using the Streamable HTTP transport MUST include it\n // in the Mcp-Session-Id header on all of their subsequent HTTP requests.\n if (!isInitializationRequest && !sessionId) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n\n // If we don't have a sessionId, we are serving an initialization request\n // and need to generate a new sessionId\n sessionId = sessionId ?? namespace.newUniqueId().toString();\n\n // fetch the agent DO\n const id = namespace.idFromName(`streamable-http:${sessionId}`);\n const doStub = namespace.get(id);\n const isInitialized = await doStub.isInitialized();\n\n if (isInitializationRequest) {\n await doStub.setInitialized();\n } else if (!isInitialized) {\n // if we have gotten here, then a session id that was never initialized\n // was provided\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32001,\n message: \"Session not found\",\n },\n id: null,\n });\n return new Response(body, { status: 404 });\n }\n\n // We've evaluated all the error conditions! Now it's time to establish\n // all the streams\n\n // Create a Transform Stream for SSE\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n // Connect to the Durable Object via WebSocket\n const upgradeUrl = new URL(request.url);\n upgradeUrl.pathname = \"/streamable-http\";\n const response = await doStub.fetch(\n new Request(upgradeUrl, {\n headers: {\n Upgrade: \"websocket\",\n // Required by PartyServer\n \"x-partykit-room\": sessionId,\n },\n })\n );\n\n // Get the WebSocket\n const ws = response.webSocket;\n if (!ws) {\n console.error(\"Failed to establish WebSocket connection\");\n\n await writer.close();\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32001,\n message: \"Failed to establish WebSocket connection\",\n },\n id: null,\n });\n return new Response(body, { status: 500 });\n }\n\n // Keep track of the request ids that we have sent to the server\n // so that we can close the connection once we have received\n // all the responses\n const requestIds: Set<string | number> = new Set();\n\n // Accept the WebSocket\n ws.accept();\n\n // Handle messages from the Durable Object\n ws.addEventListener(\"message\", (event) => {\n async function onMessage(event: MessageEvent) {\n try {\n const data =\n typeof event.data === \"string\"\n ? event.data\n : new TextDecoder().decode(event.data);\n const message = JSON.parse(data);\n\n // validate that the message is a valid JSONRPC message\n const result = JSONRPCMessageSchema.safeParse(message);\n if (!result.success) {\n // The message was not a valid JSONRPC message, so we will drop it\n // PartyKit will broadcast state change messages to all connected clients\n // and we need to filter those out so they are not passed to MCP clients\n return;\n }\n\n // If the message is a response or an error, remove the id from the set of\n // request ids\n if (\n isJSONRPCResponse(result.data) ||\n isJSONRPCError(result.data)\n ) {\n requestIds.delete(result.data.id);\n }\n\n // Send the message as an SSE event\n const messageText = `event: message\\ndata: ${JSON.stringify(result.data)}\\n\\n`;\n await writer.write(encoder.encode(messageText));\n\n // If we have received all the responses, close the connection\n if (requestIds.size === 0) {\n ws!.close();\n }\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n }\n }\n onMessage(event).catch(console.error);\n });\n\n // Handle WebSocket errors\n ws.addEventListener(\"error\", (error) => {\n async function onError(error: Event) {\n try {\n await writer.close();\n } catch (e) {\n // Ignore errors when closing\n }\n }\n onError(error).catch(console.error);\n });\n\n // Handle WebSocket closure\n ws.addEventListener(\"close\", () => {\n async function onClose() {\n try {\n await writer.close();\n } catch (error) {\n console.error(\"Error closing SSE connection:\", error);\n }\n }\n onClose().catch(console.error);\n });\n\n // If there are no requests, we send the messages to the agent and acknowledge the request with a 202\n // since we don't expect any responses back through this connection\n const hasOnlyNotificationsOrResponses = messages.every(\n (msg) => isJSONRPCNotification(msg) || isJSONRPCResponse(msg)\n );\n if (hasOnlyNotificationsOrResponses) {\n for (const message of messages) {\n ws.send(JSON.stringify(message));\n }\n\n // closing the websocket will also close the SSE connection\n ws.close();\n\n return new Response(null, { status: 202 });\n }\n\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n // add each request id that we send off to a set\n // so that we can keep track of which requests we\n // still need a response for\n requestIds.add(message.id);\n }\n ws.send(JSON.stringify(message));\n }\n\n // Return the SSE response. We handle closing the stream in the ws \"message\"\n // handler\n return new Response(readable, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"mcp-session-id\": sessionId,\n \"Access-Control-Allow-Origin\": corsOptions?.origin || \"*\",\n },\n status: 200,\n });\n }\n\n // We don't yet support GET or DELETE requests\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Method not allowed\",\n },\n id: null,\n });\n return new Response(body, { status: 405 });\n },\n };\n }\n}\n"],"mappings":"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","names":["_started","event","error","body"]}
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/index.ts"],"sourcesContent":["import { DurableObject } from \"cloudflare:workers\";\nimport { Agent } from \"../\";\nimport type { WSMessage } from \"../\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Connection } from \"../\";\nimport type {\n JSONRPCError,\n JSONRPCMessage,\n JSONRPCNotification,\n JSONRPCRequest,\n JSONRPCResponse,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n InitializeRequestSchema,\n isJSONRPCError,\n isJSONRPCNotification,\n isJSONRPCRequest,\n isJSONRPCResponse,\n JSONRPCErrorSchema,\n JSONRPCMessageSchema,\n JSONRPCNotificationSchema,\n JSONRPCRequestSchema,\n JSONRPCResponseSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\n\nconst MAXIMUM_MESSAGE_SIZE_BYTES = 4 * 1024 * 1024; // 4MB\n\n// CORS helper function\nfunction handleCORS(\n request: Request,\n corsOptions?: CORSOptions\n): Response | null {\n const origin = request.headers.get(\"Origin\") || \"*\";\n const corsHeaders = {\n \"Access-Control-Allow-Origin\": corsOptions?.origin || origin,\n \"Access-Control-Allow-Methods\":\n corsOptions?.methods || \"GET, POST, OPTIONS\",\n \"Access-Control-Allow-Headers\": corsOptions?.headers || \"Content-Type\",\n \"Access-Control-Max-Age\": (corsOptions?.maxAge || 86400).toString(),\n };\n\n if (request.method === \"OPTIONS\") {\n return new Response(null, { headers: corsHeaders });\n }\n\n return null;\n}\n\ninterface CORSOptions {\n origin?: string;\n methods?: string;\n headers?: string;\n maxAge?: number;\n}\n\nclass McpSSETransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n sessionId?: string;\n\n #getWebSocket: () => WebSocket | null;\n #started = false;\n constructor(getWebSocket: () => WebSocket | null) {\n this.#getWebSocket = getWebSocket;\n }\n\n async start() {\n // The transport does not manage the WebSocket connection since it's terminated\n // by the Durable Object in order to allow hibernation. There's nothing to initialize.\n if (this.#started) {\n throw new Error(\"Transport already started\");\n }\n this.#started = true;\n }\n\n async send(message: JSONRPCMessage) {\n if (!this.#started) {\n throw new Error(\"Transport not started\");\n }\n const websocket = this.#getWebSocket();\n if (!websocket) {\n throw new Error(\"WebSocket not connected\");\n }\n try {\n websocket.send(JSON.stringify(message));\n } catch (error) {\n this.onerror?.(error as Error);\n throw error;\n }\n }\n\n async close() {\n // Similar to start, the only thing to do is to pass the event on to the server\n this.onclose?.();\n }\n}\n\ntype TransportType = \"sse\" | \"streamable-http\" | \"unset\";\n\nclass McpStreamableHttpTransport implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n sessionId?: string;\n\n // TODO: If there is an open connection to send server-initiated messages\n // back, we should use that connection\n #getWebSocketForGetRequest: () => WebSocket | null;\n\n // Get the appropriate websocket connection for a given message id\n #getWebSocketForMessageID: (id: string) => WebSocket | null;\n\n // Notify the server that a response has been sent for a given message id\n // so that it may clean up it's mapping of message ids to connections\n // once they are no longer needed\n #notifyResponseIdSent: (id: string) => void;\n\n #started = false;\n constructor(\n getWebSocketForMessageID: (id: string) => WebSocket | null,\n notifyResponseIdSent: (id: string | number) => void\n ) {\n this.#getWebSocketForMessageID = getWebSocketForMessageID;\n this.#notifyResponseIdSent = notifyResponseIdSent;\n // TODO\n this.#getWebSocketForGetRequest = () => null;\n }\n\n async start() {\n // The transport does not manage the WebSocket connection since it's terminated\n // by the Durable Object in order to allow hibernation. There's nothing to initialize.\n if (this.#started) {\n throw new Error(\"Transport already started\");\n }\n this.#started = true;\n }\n\n async send(message: JSONRPCMessage) {\n if (!this.#started) {\n throw new Error(\"Transport not started\");\n }\n\n let websocket: WebSocket | null = null;\n\n if (isJSONRPCResponse(message) || isJSONRPCError(message)) {\n websocket = this.#getWebSocketForMessageID(message.id.toString());\n if (!websocket) {\n throw new Error(\n `Could not find WebSocket for message id: ${message.id}`\n );\n }\n } else if (isJSONRPCRequest(message)) {\n // requests originating from the server must be sent over the\n // the connection created by a GET request\n websocket = this.#getWebSocketForGetRequest();\n } else if (isJSONRPCNotification(message)) {\n // notifications do not have an id\n // but do have a relatedRequestId field\n // so that they can be sent to the correct connection\n websocket = null;\n }\n\n try {\n websocket?.send(JSON.stringify(message));\n if (isJSONRPCResponse(message)) {\n this.#notifyResponseIdSent(message.id.toString());\n }\n } catch (error) {\n this.onerror?.(error as Error);\n throw error;\n }\n }\n\n async close() {\n // Similar to start, the only thing to do is to pass the event on to the server\n this.onclose?.();\n }\n}\n\ntype MaybePromise<T> = T | Promise<T>;\n\nexport abstract class McpAgent<\n Env = unknown,\n State = unknown,\n Props extends Record<string, unknown> = Record<string, unknown>,\n> extends DurableObject<Env> {\n #status: \"zero\" | \"starting\" | \"started\" = \"zero\";\n #transport?: Transport;\n #transportType: TransportType = \"unset\";\n #requestIdToConnectionId: Map<string | number, string> = new Map();\n\n /**\n * Since McpAgent's _aren't_ yet real \"Agents\", let's only expose a couple of the methods\n * to the outer class: initialState/state/setState/onStateUpdate/sql\n */\n #agent: Agent<Env, State>;\n\n get mcp() {\n return this.#agent.mcp;\n }\n\n protected constructor(ctx: DurableObjectState, env: Env) {\n super(ctx, env);\n const self = this;\n\n this.#agent = new (class extends Agent<Env, State> {\n static options = {\n hibernate: true,\n };\n\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n return self.onStateUpdate(state, source);\n }\n\n async onMessage(\n connection: Connection,\n message: WSMessage\n ): Promise<void> {\n return self.onMessage(connection, message);\n }\n })(ctx, env);\n }\n\n /**\n * Agents API allowlist\n */\n initialState!: State;\n get state() {\n return this.#agent.state;\n }\n sql<T = Record<string, string | number | boolean | null>>(\n strings: TemplateStringsArray,\n ...values: (string | number | boolean | null)[]\n ) {\n return this.#agent.sql<T>(strings, ...values);\n }\n\n setState(state: State) {\n return this.#agent.setState(state);\n }\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n // override this to handle state updates\n }\n async onStart() {\n const self = this;\n\n this.#agent = new (class extends Agent<Env, State> {\n initialState: State = self.initialState;\n static options = {\n hibernate: true,\n };\n\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n return self.onStateUpdate(state, source);\n }\n\n async onMessage(connection: Connection, event: WSMessage) {\n return self.onMessage(connection, event);\n }\n })(this.ctx, this.env);\n\n this.props = (await this.ctx.storage.get(\"props\")) as Props;\n this.#transportType = (await this.ctx.storage.get(\n \"transportType\"\n )) as TransportType;\n await this._init(this.props);\n\n const server = await this.server;\n\n // Connect to the MCP server\n if (this.#transportType === \"sse\") {\n this.#transport = new McpSSETransport(() => this.getWebSocket());\n await server.connect(this.#transport);\n } else if (this.#transportType === \"streamable-http\") {\n this.#transport = new McpStreamableHttpTransport(\n (id) => this.getWebSocketForResponseID(id),\n (id) => this.#requestIdToConnectionId.delete(id)\n );\n await server.connect(this.#transport);\n }\n }\n\n /**\n * McpAgent API\n */\n abstract server: MaybePromise<McpServer | Server>;\n props!: Props;\n initRun = false;\n\n abstract init(): Promise<void>;\n\n async _init(props: Props) {\n await this.ctx.storage.put(\"props\", props ?? {});\n if (!this.ctx.storage.get(\"transportType\")) {\n await this.ctx.storage.put(\"transportType\", \"unset\");\n }\n this.props = props;\n if (!this.initRun) {\n this.initRun = true;\n await this.init();\n }\n }\n\n async setInitialized() {\n await this.ctx.storage.put(\"initialized\", true);\n }\n\n async isInitialized() {\n return (await this.ctx.storage.get(\"initialized\")) === true;\n }\n\n async #initialize(): Promise<void> {\n await this.ctx.blockConcurrencyWhile(async () => {\n this.#status = \"starting\";\n await this.onStart();\n this.#status = \"started\";\n });\n }\n\n // Allow the worker to fetch a websocket connection to the agent\n async fetch(request: Request): Promise<Response> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n\n // Only handle WebSocket upgrade requests\n if (request.headers.get(\"Upgrade\") !== \"websocket\") {\n return new Response(\"Expected WebSocket Upgrade request\", {\n status: 400,\n });\n }\n\n // This request does not come from the user. The worker generates this\n // request to generate a websocket connection to the agent.\n const url = new URL(request.url);\n // This is not the path that the user requested, but the path that the worker\n // generated. We'll use this path to determine which transport to use.\n const path = url.pathname;\n const server = await this.server;\n\n switch (path) {\n case \"/sse\": {\n // For SSE connections, we can only have one open connection per session\n // If we get an upgrade while already connected, we should error\n const websockets = this.ctx.getWebSockets();\n if (websockets.length > 0) {\n return new Response(\"Websocket already connected\", { status: 400 });\n }\n\n // This session must always use the SSE transporo\n await this.ctx.storage.put(\"transportType\", \"sse\");\n this.#transportType = \"sse\";\n\n if (!this.#transport) {\n this.#transport = new McpSSETransport(() => this.getWebSocket());\n await server.connect(this.#transport);\n }\n\n // Defer to the Agent's fetch method to handle the WebSocket connection\n return this.#agent.fetch(request);\n }\n case \"/streamable-http\": {\n if (!this.#transport) {\n this.#transport = new McpStreamableHttpTransport(\n (id) => this.getWebSocketForResponseID(id),\n (id) => this.#requestIdToConnectionId.delete(id)\n );\n await server.connect(this.#transport);\n }\n\n // This session must always use the streamable-http transport\n await this.ctx.storage.put(\"transportType\", \"streamable-http\");\n this.#transportType = \"streamable-http\";\n\n return this.#agent.fetch(request);\n }\n default:\n return new Response(\n \"Internal Server Error: Expected /sse or /streamable-http path\",\n {\n status: 500,\n }\n );\n }\n }\n\n getWebSocket() {\n const websockets = this.ctx.getWebSockets();\n if (websockets.length === 0) {\n return null;\n }\n return websockets[0];\n }\n\n getWebSocketForResponseID(id: string): WebSocket | null {\n const connectionId = this.#requestIdToConnectionId.get(id);\n if (connectionId === undefined) {\n return null;\n }\n return this.#agent.getConnection(connectionId) ?? null;\n }\n\n // All messages received here. This is currently never called\n async onMessage(connection: Connection, event: WSMessage) {\n // Since we address the DO via both the protocol and the session id,\n // this should never happen, but let's enforce it just in case\n if (this.#transportType !== \"streamable-http\") {\n const err = new Error(\n \"Internal Server Error: Expected streamable-http protocol\"\n );\n this.#transport?.onerror?.(err);\n return;\n }\n\n let message: JSONRPCMessage;\n try {\n // Ensure event is a string\n const data =\n typeof event === \"string\" ? event : new TextDecoder().decode(event);\n message = JSONRPCMessageSchema.parse(JSON.parse(data));\n } catch (error) {\n this.#transport?.onerror?.(error as Error);\n return;\n }\n\n // We need to map every incoming message to the connection that it came in on\n // so that we can send relevant responses and notifications back on the same connection\n if (isJSONRPCRequest(message)) {\n this.#requestIdToConnectionId.set(message.id.toString(), connection.id);\n }\n\n this.#transport?.onmessage?.(message);\n }\n\n // All messages received over SSE after the initial connection has been established\n // will be passed here\n async onSSEMcpMessage(\n sessionId: string,\n request: Request\n ): Promise<Error | null> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n\n // Since we address the DO via both the protocol and the session id,\n // this should never happen, but let's enforce it just in case\n if (this.#transportType !== \"sse\") {\n return new Error(\"Internal Server Error: Expected SSE protocol\");\n }\n\n try {\n const message = await request.json();\n let parsedMessage: JSONRPCMessage;\n try {\n parsedMessage = JSONRPCMessageSchema.parse(message);\n } catch (error) {\n this.#transport?.onerror?.(error as Error);\n throw error;\n }\n\n this.#transport?.onmessage?.(parsedMessage);\n return null;\n } catch (error) {\n this.#transport?.onerror?.(error as Error);\n return error as Error;\n }\n }\n\n // Delegate all websocket events to the underlying agent\n async webSocketMessage(\n ws: WebSocket,\n event: ArrayBuffer | string\n ): Promise<void> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n return await this.#agent.webSocketMessage(ws, event);\n }\n\n // WebSocket event handlers for hibernation support\n async webSocketError(ws: WebSocket, error: unknown): Promise<void> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n return await this.#agent.webSocketError(ws, error);\n }\n\n async webSocketClose(\n ws: WebSocket,\n code: number,\n reason: string,\n wasClean: boolean\n ): Promise<void> {\n if (this.#status !== \"started\") {\n // This means the server \"woke up\" after hibernation\n // so we need to hydrate it again\n await this.#initialize();\n }\n return await this.#agent.webSocketClose(ws, code, reason, wasClean);\n }\n\n static mount(\n path: string,\n {\n binding = \"MCP_OBJECT\",\n corsOptions,\n }: {\n binding?: string;\n corsOptions?: CORSOptions;\n } = {}\n ) {\n return McpAgent.serveSSE(path, { binding, corsOptions });\n }\n\n static serveSSE(\n path: string,\n {\n binding = \"MCP_OBJECT\",\n corsOptions,\n }: {\n binding?: string;\n corsOptions?: CORSOptions;\n } = {}\n ) {\n let pathname = path;\n if (path === \"/\") {\n pathname = \"/*\";\n }\n const basePattern = new URLPattern({ pathname });\n const messagePattern = new URLPattern({ pathname: `${pathname}/message` });\n\n return {\n async fetch<Env>(\n request: Request,\n env: Env,\n ctx: ExecutionContext\n ): Promise<Response> {\n // Handle CORS preflight\n const corsResponse = handleCORS(request, corsOptions);\n if (corsResponse) return corsResponse;\n\n const url = new URL(request.url);\n const bindingValue = env[binding as keyof typeof env] as unknown;\n\n // Ensure we have a binding of some sort\n if (bindingValue == null || typeof bindingValue !== \"object\") {\n console.error(\n `Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`\n );\n return new Response(\"Invalid binding\", { status: 500 });\n }\n\n // Ensure that the biding is to a DurableObject\n if (bindingValue.toString() !== \"[object DurableObjectNamespace]\") {\n return new Response(\"Invalid binding\", { status: 500 });\n }\n\n const namespace = bindingValue as DurableObjectNamespace<McpAgent>;\n\n // Handle initial SSE connection\n if (request.method === \"GET\" && basePattern.test(url)) {\n // Use a session ID if one is passed in, or create a unique\n // session ID for this connection\n const sessionId =\n url.searchParams.get(\"sessionId\") ||\n namespace.newUniqueId().toString();\n\n // Create a Transform Stream for SSE\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n // Send the endpoint event\n const endpointUrl = new URL(request.url);\n endpointUrl.pathname = encodeURI(`${pathname}/message`);\n endpointUrl.searchParams.set(\"sessionId\", sessionId);\n const relativeUrlWithSession =\n endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;\n const endpointMessage = `event: endpoint\\ndata: ${relativeUrlWithSession}\\n\\n`;\n writer.write(encoder.encode(endpointMessage));\n\n // Get the Durable Object\n const id = namespace.idFromName(`sse:${sessionId}`);\n const doStub = namespace.get(id);\n\n // Initialize the object\n await doStub._init(ctx.props);\n\n // Connect to the Durable Object via WebSocket\n const upgradeUrl = new URL(request.url);\n // enforce that the path that the DO receives is always /sse\n upgradeUrl.pathname = \"/sse\";\n const response = await doStub.fetch(\n new Request(upgradeUrl, {\n headers: {\n Upgrade: \"websocket\",\n // Required by PartyServer\n \"x-partykit-room\": sessionId,\n },\n })\n );\n\n // Get the WebSocket\n const ws = response.webSocket;\n if (!ws) {\n console.error(\"Failed to establish WebSocket connection\");\n await writer.close();\n return new Response(\"Failed to establish WebSocket connection\", {\n status: 500,\n });\n }\n\n // Accept the WebSocket\n ws.accept();\n\n // Handle messages from the Durable Object\n ws.addEventListener(\"message\", (event) => {\n async function onMessage(event: MessageEvent) {\n try {\n const message = JSON.parse(event.data);\n\n // validate that the message is a valid JSONRPC message\n const result = JSONRPCMessageSchema.safeParse(message);\n if (!result.success) {\n // The message was not a valid JSONRPC message, so we will drop it\n // PartyKit will broadcast state change messages to all connected clients\n // and we need to filter those out so they are not passed to MCP clients\n return;\n }\n\n // Send the message as an SSE event\n const messageText = `event: message\\ndata: ${JSON.stringify(result.data)}\\n\\n`;\n await writer.write(encoder.encode(messageText));\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n }\n }\n onMessage(event).catch(console.error);\n });\n\n // Handle WebSocket errors\n ws.addEventListener(\"error\", (error) => {\n async function onError(error: Event) {\n try {\n await writer.close();\n } catch (e) {\n // Ignore errors when closing\n }\n }\n onError(error).catch(console.error);\n });\n\n // Handle WebSocket closure\n ws.addEventListener(\"close\", () => {\n async function onClose() {\n try {\n await writer.close();\n } catch (error) {\n console.error(\"Error closing SSE connection:\", error);\n }\n }\n onClose().catch(console.error);\n });\n\n // Return the SSE response\n return new Response(readable, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": corsOptions?.origin || \"*\",\n },\n });\n }\n\n // Handle incoming MCP messages. These will be passed to McpAgent\n // but the response will be sent back via the open SSE connection\n // so we only need to return a 202 Accepted response for success\n if (request.method === \"POST\" && messagePattern.test(url)) {\n const sessionId = url.searchParams.get(\"sessionId\");\n if (!sessionId) {\n return new Response(\n `Missing sessionId. Expected POST to ${pathname} to initiate new one`,\n { status: 400 }\n );\n }\n\n const contentType = request.headers.get(\"content-type\") || \"\";\n if (!contentType.includes(\"application/json\")) {\n return new Response(`Unsupported content-type: ${contentType}`, {\n status: 400,\n });\n }\n\n // check if the request body is too large\n const contentLength = Number.parseInt(\n request.headers.get(\"content-length\") || \"0\",\n 10\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {\n return new Response(\n `Request body too large: ${contentLength} bytes`,\n {\n status: 400,\n }\n );\n }\n\n // Get the Durable Object\n const id = namespace.idFromName(`sse:${sessionId}`);\n const doStub = namespace.get(id);\n\n // Forward the request to the Durable Object\n const error = await doStub.onSSEMcpMessage(sessionId, request);\n\n if (error) {\n return new Response(error.message, {\n status: 400,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": corsOptions?.origin || \"*\",\n },\n });\n }\n\n return new Response(\"Accepted\", {\n status: 202,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": corsOptions?.origin || \"*\",\n },\n });\n }\n\n return new Response(\"Not Found\", { status: 404 });\n },\n };\n }\n\n static serve(\n path: string,\n {\n binding = \"MCP_OBJECT\",\n corsOptions,\n }: { binding?: string; corsOptions?: CORSOptions } = {}\n ) {\n let pathname = path;\n if (path === \"/\") {\n pathname = \"/*\";\n }\n const basePattern = new URLPattern({ pathname });\n\n return {\n async fetch<Env>(\n request: Request,\n env: Env,\n ctx: ExecutionContext\n ): Promise<Response> {\n // Handle CORS preflight\n const corsResponse = handleCORS(request, corsOptions);\n if (corsResponse) {\n return corsResponse;\n }\n\n const url = new URL(request.url);\n const bindingValue = env[binding as keyof typeof env] as unknown;\n\n // Ensure we have a binding of some sort\n if (bindingValue == null || typeof bindingValue !== \"object\") {\n console.error(\n `Could not find McpAgent binding for ${binding}. Did you update your wrangler configuration?`\n );\n return new Response(\"Invalid binding\", { status: 500 });\n }\n\n // Ensure that the biding is to a DurableObject\n if (bindingValue.toString() !== \"[object DurableObjectNamespace]\") {\n return new Response(\"Invalid binding\", { status: 500 });\n }\n\n const namespace = bindingValue as DurableObjectNamespace<McpAgent>;\n\n if (request.method === \"POST\" && basePattern.test(url)) {\n // validate the Accept header\n const acceptHeader = request.headers.get(\"accept\");\n // The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.\n if (\n !acceptHeader?.includes(\"application/json\") ||\n !acceptHeader.includes(\"text/event-stream\")\n ) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message:\n \"Not Acceptable: Client must accept both application/json and text/event-stream\",\n },\n id: null,\n });\n return new Response(body, { status: 406 });\n }\n\n const ct = request.headers.get(\"content-type\");\n if (!ct || !ct.includes(\"application/json\")) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message:\n \"Unsupported Media Type: Content-Type must be application/json\",\n },\n id: null,\n });\n return new Response(body, { status: 415 });\n }\n\n // Check content length against maximum allowed size\n const contentLength = Number.parseInt(\n request.headers.get(\"content-length\") ?? \"0\",\n 10\n );\n if (contentLength > MAXIMUM_MESSAGE_SIZE_BYTES) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: `Request body too large. Maximum size is ${MAXIMUM_MESSAGE_SIZE_BYTES} bytes`,\n },\n id: null,\n });\n return new Response(body, { status: 413 });\n }\n\n let sessionId = request.headers.get(\"mcp-session-id\");\n let rawMessage: unknown;\n\n try {\n rawMessage = await request.json();\n } catch (error) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n\n // Make sure the message is an array to simplify logic\n let arrayMessage: unknown[];\n if (Array.isArray(rawMessage)) {\n arrayMessage = rawMessage;\n } else {\n arrayMessage = [rawMessage];\n }\n\n let messages: JSONRPCMessage[] = [];\n\n // Try to parse each message as JSON RPC. Fail if any message is invalid\n for (const msg of arrayMessage) {\n if (!JSONRPCMessageSchema.safeParse(msg).success) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32700,\n message: \"Parse error: Invalid JSON-RPC message\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n }\n\n messages = arrayMessage.map((msg) => JSONRPCMessageSchema.parse(msg));\n\n // Before we pass the messages to the agent, there's another error condition we need to enforce\n // Check if this is an initialization request\n // https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle/\n const isInitializationRequest = messages.some(\n (msg) => InitializeRequestSchema.safeParse(msg).success\n );\n\n if (isInitializationRequest && sessionId) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32600,\n message:\n \"Invalid Request: Initialization requests must not include a sessionId\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n\n // The initialization request must be the only request in the batch\n if (isInitializationRequest && messages.length > 1) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32600,\n message:\n \"Invalid Request: Only one initialization request is allowed\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n\n // If an Mcp-Session-Id is returned by the server during initialization,\n // clients using the Streamable HTTP transport MUST include it\n // in the Mcp-Session-Id header on all of their subsequent HTTP requests.\n if (!isInitializationRequest && !sessionId) {\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Mcp-Session-Id header is required\",\n },\n id: null,\n });\n return new Response(body, { status: 400 });\n }\n\n // If we don't have a sessionId, we are serving an initialization request\n // and need to generate a new sessionId\n sessionId = sessionId ?? namespace.newUniqueId().toString();\n\n // fetch the agent DO\n const id = namespace.idFromName(`streamable-http:${sessionId}`);\n const doStub = namespace.get(id);\n const isInitialized = await doStub.isInitialized();\n\n if (isInitializationRequest) {\n await doStub.setInitialized();\n } else if (!isInitialized) {\n // if we have gotten here, then a session id that was never initialized\n // was provided\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32001,\n message: \"Session not found\",\n },\n id: null,\n });\n return new Response(body, { status: 404 });\n }\n\n // We've evaluated all the error conditions! Now it's time to establish\n // all the streams\n\n // Create a Transform Stream for SSE\n const { readable, writable } = new TransformStream();\n const writer = writable.getWriter();\n const encoder = new TextEncoder();\n\n // Connect to the Durable Object via WebSocket\n const upgradeUrl = new URL(request.url);\n upgradeUrl.pathname = \"/streamable-http\";\n const response = await doStub.fetch(\n new Request(upgradeUrl, {\n headers: {\n Upgrade: \"websocket\",\n // Required by PartyServer\n \"x-partykit-room\": sessionId,\n },\n })\n );\n\n // Get the WebSocket\n const ws = response.webSocket;\n if (!ws) {\n console.error(\"Failed to establish WebSocket connection\");\n\n await writer.close();\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32001,\n message: \"Failed to establish WebSocket connection\",\n },\n id: null,\n });\n return new Response(body, { status: 500 });\n }\n\n // Keep track of the request ids that we have sent to the server\n // so that we can close the connection once we have received\n // all the responses\n const requestIds: Set<string | number> = new Set();\n\n // Accept the WebSocket\n ws.accept();\n\n // Handle messages from the Durable Object\n ws.addEventListener(\"message\", (event) => {\n async function onMessage(event: MessageEvent) {\n try {\n const data =\n typeof event.data === \"string\"\n ? event.data\n : new TextDecoder().decode(event.data);\n const message = JSON.parse(data);\n\n // validate that the message is a valid JSONRPC message\n const result = JSONRPCMessageSchema.safeParse(message);\n if (!result.success) {\n // The message was not a valid JSONRPC message, so we will drop it\n // PartyKit will broadcast state change messages to all connected clients\n // and we need to filter those out so they are not passed to MCP clients\n return;\n }\n\n // If the message is a response or an error, remove the id from the set of\n // request ids\n if (\n isJSONRPCResponse(result.data) ||\n isJSONRPCError(result.data)\n ) {\n requestIds.delete(result.data.id);\n }\n\n // Send the message as an SSE event\n const messageText = `event: message\\ndata: ${JSON.stringify(result.data)}\\n\\n`;\n await writer.write(encoder.encode(messageText));\n\n // If we have received all the responses, close the connection\n if (requestIds.size === 0) {\n ws!.close();\n }\n } catch (error) {\n console.error(\"Error forwarding message to SSE:\", error);\n }\n }\n onMessage(event).catch(console.error);\n });\n\n // Handle WebSocket errors\n ws.addEventListener(\"error\", (error) => {\n async function onError(error: Event) {\n try {\n await writer.close();\n } catch (e) {\n // Ignore errors when closing\n }\n }\n onError(error).catch(console.error);\n });\n\n // Handle WebSocket closure\n ws.addEventListener(\"close\", () => {\n async function onClose() {\n try {\n await writer.close();\n } catch (error) {\n console.error(\"Error closing SSE connection:\", error);\n }\n }\n onClose().catch(console.error);\n });\n\n // If there are no requests, we send the messages to the agent and acknowledge the request with a 202\n // since we don't expect any responses back through this connection\n const hasOnlyNotificationsOrResponses = messages.every(\n (msg) => isJSONRPCNotification(msg) || isJSONRPCResponse(msg)\n );\n if (hasOnlyNotificationsOrResponses) {\n for (const message of messages) {\n ws.send(JSON.stringify(message));\n }\n\n // closing the websocket will also close the SSE connection\n ws.close();\n\n return new Response(null, { status: 202 });\n }\n\n for (const message of messages) {\n if (isJSONRPCRequest(message)) {\n // add each request id that we send off to a set\n // so that we can keep track of which requests we\n // still need a response for\n requestIds.add(message.id);\n }\n ws.send(JSON.stringify(message));\n }\n\n // Return the SSE response. We handle closing the stream in the ws \"message\"\n // handler\n return new Response(readable, {\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"mcp-session-id\": sessionId,\n \"Access-Control-Allow-Origin\": corsOptions?.origin || \"*\",\n },\n status: 200,\n });\n }\n\n // We don't yet support GET or DELETE requests\n const body = JSON.stringify({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Method not allowed\",\n },\n id: null,\n });\n return new Response(body, { status: 405 });\n },\n };\n }\n}\n"],"mappings":"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","names":["_started","event","error","body"]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/sse-edge.ts","../src/mcp/client-connection.ts","../src/mcp/client.ts"],"sourcesContent":["import {\n SSEClientTransport,\n type SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\n\nexport class SSEEdgeClientTransport extends SSEClientTransport {\n private authProvider: OAuthClientProvider | undefined;\n /**\n * Creates a new EdgeSSEClientTransport, which overrides fetch to be compatible with the CF workers environment\n */\n constructor(url: URL, options: SSEClientTransportOptions) {\n const fetchOverride: typeof fetch = async (\n fetchUrl: RequestInfo | URL,\n fetchInit: RequestInit = {}\n ) => {\n // add auth headers\n const headers = await this.authHeaders();\n const workerOptions = {\n ...fetchInit,\n headers: {\n ...fetchInit?.headers,\n ...headers,\n },\n };\n\n // Remove unsupported properties\n // biome-ignore lint/performance/noDelete: workaround for workers environment\n delete workerOptions.mode;\n\n // Call the original fetch with fixed options\n return fetch(fetchUrl, workerOptions);\n };\n\n super(url, {\n ...options,\n eventSourceInit: {\n fetch: fetchOverride,\n },\n });\n this.authProvider = options.authProvider;\n }\n\n async authHeaders() {\n if (this.authProvider) {\n const tokens = await this.authProvider.tokens();\n if (tokens) {\n return {\n Authorization: `Bearer ${tokens.access_token}`,\n };\n }\n }\n }\n}\n","import { SSEEdgeClientTransport } from \"./sse-edge\";\n\nimport {\n ToolListChangedNotificationSchema,\n type ClientCapabilities,\n type Resource,\n type Tool,\n type Prompt,\n ResourceListChangedNotificationSchema,\n PromptListChangedNotificationSchema,\n type ListToolsResult,\n type ListResourcesResult,\n type ListPromptsResult,\n type ServerCapabilities,\n type ResourceTemplate,\n type ListResourceTemplatesResult,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { AgentsOAuthProvider } from \"./do-oauth-client-provider\";\n\nexport class MCPClientConnection {\n client: Client;\n connectionState:\n | \"authenticating\"\n | \"connecting\"\n | \"ready\"\n | \"discovering\"\n | \"failed\" = \"connecting\";\n instructions?: string;\n tools: Tool[] = [];\n prompts: Prompt[] = [];\n resources: Resource[] = [];\n resourceTemplates: ResourceTemplate[] = [];\n serverCapabilities: ServerCapabilities | undefined;\n\n constructor(\n public url: URL,\n info: ConstructorParameters<typeof Client>[0],\n public options: {\n transport: SSEClientTransportOptions & {\n authProvider?: AgentsOAuthProvider;\n };\n client: ConstructorParameters<typeof Client>[1];\n capabilities: ClientCapabilities;\n } = { transport: {}, client: {}, capabilities: {} }\n ) {\n this.client = new Client(info, options.client);\n this.client.registerCapabilities(options.capabilities);\n }\n\n /**\n * Initialize a client connection\n *\n * @param code Optional OAuth code to initialize the connection with if auth hasn't been initialized\n * @returns\n */\n async init(code?: string, clientId?: string) {\n try {\n const transport = new SSEEdgeClientTransport(\n this.url,\n this.options.transport\n );\n if (code) {\n await transport.finishAuth(code);\n }\n\n await this.client.connect(transport);\n // biome-ignore lint/suspicious/noExplicitAny: allow for the error check here\n } catch (e: any) {\n if (e.toString().includes(\"Unauthorized\")) {\n // unauthorized, we should wait for the user to authenticate\n this.connectionState = \"authenticating\";\n return;\n }\n this.connectionState = \"failed\";\n throw e;\n }\n\n this.connectionState = \"discovering\";\n\n this.serverCapabilities = await this.client.getServerCapabilities();\n if (!this.serverCapabilities) {\n throw new Error(\"The MCP Server failed to return server capabilities\");\n }\n\n const [instructions, tools, resources, prompts, resourceTemplates] =\n await Promise.all([\n this.client.getInstructions(),\n this.registerTools(),\n this.registerResources(),\n this.registerPrompts(),\n this.registerResourceTemplates(),\n ]);\n\n this.instructions = instructions;\n this.tools = tools;\n this.resources = resources;\n this.prompts = prompts;\n this.resourceTemplates = resourceTemplates;\n\n this.connectionState = \"ready\";\n }\n\n /**\n * Notification handler registration\n */\n async registerTools(): Promise<Tool[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.tools) {\n return [];\n }\n\n if (this.serverCapabilities.tools.listChanged) {\n this.client.setNotificationHandler(\n ToolListChangedNotificationSchema,\n async (_notification) => {\n this.tools = await this.fetchTools();\n }\n );\n }\n\n return this.fetchTools();\n }\n\n async registerResources(): Promise<Resource[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.resources) {\n return [];\n }\n\n if (this.serverCapabilities.resources.listChanged) {\n this.client.setNotificationHandler(\n ResourceListChangedNotificationSchema,\n async (_notification) => {\n this.resources = await this.fetchResources();\n }\n );\n }\n\n return this.fetchResources();\n }\n\n async registerPrompts(): Promise<Prompt[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.prompts) {\n return [];\n }\n\n if (this.serverCapabilities.prompts.listChanged) {\n this.client.setNotificationHandler(\n PromptListChangedNotificationSchema,\n async (_notification) => {\n this.prompts = await this.fetchPrompts();\n }\n );\n }\n\n return this.fetchPrompts();\n }\n\n async registerResourceTemplates(): Promise<ResourceTemplate[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.resources) {\n return [];\n }\n\n return this.fetchResourceTemplates();\n }\n\n async fetchTools() {\n let toolsAgg: Tool[] = [];\n let toolsResult: ListToolsResult = { tools: [] };\n do {\n toolsResult = await this.client\n .listTools({\n cursor: toolsResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ tools: [] }, \"tools/list\"));\n toolsAgg = toolsAgg.concat(toolsResult.tools);\n } while (toolsResult.nextCursor);\n return toolsAgg;\n }\n\n async fetchResources() {\n let resourcesAgg: Resource[] = [];\n let resourcesResult: ListResourcesResult = { resources: [] };\n do {\n resourcesResult = await this.client\n .listResources({\n cursor: resourcesResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ resources: [] }, \"resources/list\"));\n resourcesAgg = resourcesAgg.concat(resourcesResult.resources);\n } while (resourcesResult.nextCursor);\n return resourcesAgg;\n }\n\n async fetchPrompts() {\n let promptsAgg: Prompt[] = [];\n let promptsResult: ListPromptsResult = { prompts: [] };\n do {\n promptsResult = await this.client\n .listPrompts({\n cursor: promptsResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ prompts: [] }, \"prompts/list\"));\n promptsAgg = promptsAgg.concat(promptsResult.prompts);\n } while (promptsResult.nextCursor);\n return promptsAgg;\n }\n\n async fetchResourceTemplates() {\n let templatesAgg: ResourceTemplate[] = [];\n let templatesResult: ListResourceTemplatesResult = {\n resourceTemplates: [],\n };\n do {\n templatesResult = await this.client\n .listResourceTemplates({\n cursor: templatesResult.nextCursor,\n })\n .catch(\n capabilityErrorHandler(\n { resourceTemplates: [] },\n \"resources/templates/list\"\n )\n );\n templatesAgg = templatesAgg.concat(templatesResult.resourceTemplates);\n } while (templatesResult.nextCursor);\n return templatesAgg;\n }\n}\n\nfunction capabilityErrorHandler<T>(empty: T, method: string) {\n return (e: { code: number }) => {\n // server is badly behaved and returning invalid capabilities. This commonly occurs for resource templates\n if (e.code === -32601) {\n console.error(\n `The server advertised support for the capability ${method.split(\"/\")[0]}, but returned \"Method not found\" for '${method}'.`\n );\n return empty;\n }\n throw e;\n };\n}\n","import { MCPClientConnection } from \"./client-connection\";\n\nimport type {\n ClientCapabilities,\n CallToolRequest,\n CallToolResultSchema,\n CompatibilityCallToolResultSchema,\n ReadResourceRequest,\n GetPromptRequest,\n Tool,\n Resource,\n Prompt,\n ResourceTemplate,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport type { AgentsOAuthProvider } from \"./do-oauth-client-provider\";\nimport { jsonSchema, type ToolSet } from \"ai\";\n\n/**\n * Utility class that aggregates multiple MCP clients into one\n */\nexport class MCPClientManager {\n public mcpConnections: Record<string, MCPClientConnection> = {};\n private callbackUrls: string[] = [];\n\n /**\n * @param name Name of the MCP client\n * @param version Version of the MCP Client\n * @param auth Auth paramters if being used to create a DurableObjectOAuthClientProvider\n */\n constructor(\n private name: string,\n private version: string\n ) {}\n\n /**\n * Connect to and register an MCP server\n *\n * @param transportConfig Transport config\n * @param clientConfig Client config\n * @param capabilities Client capabilities (i.e. if the client supports roots/sampling)\n */\n async connect(\n url: string,\n options: {\n // Allows you to reconnect to a server (in the case of a auth reconnect)\n // Doesn't handle session reconnection\n reconnect?: {\n id: string;\n oauthClientId?: string;\n oauthCode?: string;\n };\n // we're overriding authProvider here because we want to be able to access the auth URL\n transport?: SSEClientTransportOptions & {\n authProvider?: AgentsOAuthProvider;\n };\n client?: ConstructorParameters<typeof Client>[1];\n capabilities?: ClientCapabilities;\n } = {}\n ): Promise<{ id: string; authUrl: string | undefined }> {\n const id = options.reconnect?.id ?? crypto.randomUUID();\n\n if (!options.transport?.authProvider) {\n console.warn(\n \"No authProvider provided in the transport options. This client will only support unauthenticated remote MCP Servers\"\n );\n } else {\n options.transport.authProvider.serverId = id;\n }\n\n this.mcpConnections[id] = new MCPClientConnection(\n new URL(url),\n {\n name: this.name,\n version: this.version,\n },\n {\n transport: options.transport ?? {},\n client: options.client ?? {},\n capabilities: options.client ?? {},\n }\n );\n\n await this.mcpConnections[id].init(\n options.reconnect?.oauthCode,\n options.reconnect?.oauthClientId\n );\n\n const authUrl = options.transport?.authProvider?.authUrl;\n if (authUrl && options.transport?.authProvider?.redirectUrl) {\n this.callbackUrls.push(\n options.transport.authProvider.redirectUrl.toString()\n );\n }\n\n return {\n id,\n authUrl,\n };\n }\n\n isCallbackRequest(req: Request): boolean {\n return (\n req.method === \"GET\" &&\n !!this.callbackUrls.find((url) => {\n return req.url.startsWith(url);\n })\n );\n }\n\n async handleCallbackRequest(req: Request) {\n const url = new URL(req.url);\n const urlMatch = this.callbackUrls.find((url) => {\n return req.url.startsWith(url);\n });\n if (!urlMatch) {\n throw new Error(\n `No callback URI match found for the request url: ${req.url}. Was the request matched with \\`isCallbackRequest()\\`?`\n );\n }\n const code = url.searchParams.get(\"code\");\n const clientId = url.searchParams.get(\"state\");\n const urlParams = urlMatch.split(\"/\");\n const serverId = urlParams[urlParams.length - 1];\n if (!code) {\n throw new Error(\"Unauthorized: no code provided\");\n }\n if (!clientId) {\n throw new Error(\"Unauthorized: no state provided\");\n }\n\n if (this.mcpConnections[serverId] === undefined) {\n throw new Error(`Could not find serverId: ${serverId}`);\n }\n\n if (this.mcpConnections[serverId].connectionState !== \"authenticating\") {\n throw new Error(\n \"Failed to authenticate: the client isn't in the `authenticating` state\"\n );\n }\n\n const conn = this.mcpConnections[serverId];\n if (!conn.options.transport.authProvider) {\n throw new Error(\n \"Trying to finalize authentication for a server connection without an authProvider\"\n );\n }\n\n conn.options.transport.authProvider.clientId = clientId;\n conn.options.transport.authProvider.serverId = serverId;\n\n // reconnect to server with authorization\n const serverUrl = conn.url.toString();\n await this.connect(serverUrl, {\n reconnect: {\n id: serverId,\n oauthClientId: clientId,\n oauthCode: code,\n },\n ...conn.options,\n });\n\n if (this.mcpConnections[serverId].connectionState === \"authenticating\") {\n throw new Error(\"Failed to authenticate: client failed to initialize\");\n }\n\n return { serverId };\n }\n\n /**\n * @returns namespaced list of tools\n */\n listTools(): NamespacedData[\"tools\"] {\n return getNamespacedData(this.mcpConnections, \"tools\");\n }\n\n /**\n * @returns a set of tools that you can use with the AI SDK\n */\n unstable_getAITools(): ToolSet {\n return Object.fromEntries(\n getNamespacedData(this.mcpConnections, \"tools\").map((tool) => {\n return [\n tool.name,\n {\n parameters: jsonSchema(tool.inputSchema),\n description: tool.description,\n execute: async (args) => {\n const result = await this.callTool({\n name: tool.name,\n arguments: args,\n serverId: tool.serverId,\n });\n if (result.isError) {\n // @ts-expect-error TODO we should fix this\n throw new Error(result.content[0].text);\n }\n return result;\n },\n },\n ];\n })\n );\n }\n\n /**\n * @returns namespaced list of prompts\n */\n listPrompts(): NamespacedData[\"prompts\"] {\n return getNamespacedData(this.mcpConnections, \"prompts\");\n }\n\n /**\n * @returns namespaced list of tools\n */\n listResources(): NamespacedData[\"resources\"] {\n return getNamespacedData(this.mcpConnections, \"resources\");\n }\n\n /**\n * @returns namespaced list of resource templates\n */\n listResourceTemplates(): NamespacedData[\"resourceTemplates\"] {\n return getNamespacedData(this.mcpConnections, \"resourceTemplates\");\n }\n\n /**\n * Namespaced version of callTool\n */\n callTool(\n params: CallToolRequest[\"params\"] & { serverId: string },\n resultSchema?:\n | typeof CallToolResultSchema\n | typeof CompatibilityCallToolResultSchema,\n options?: RequestOptions\n ) {\n const unqualifiedName = params.name.replace(`${params.serverId}.`, \"\");\n return this.mcpConnections[params.serverId].client.callTool(\n {\n ...params,\n name: unqualifiedName,\n },\n resultSchema,\n options\n );\n }\n\n /**\n * Namespaced version of readResource\n */\n readResource(\n params: ReadResourceRequest[\"params\"] & { serverId: string },\n options: RequestOptions\n ) {\n return this.mcpConnections[params.serverId].client.readResource(\n params,\n options\n );\n }\n\n /**\n * Namespaced version of getPrompt\n */\n getPrompt(\n params: GetPromptRequest[\"params\"] & { serverId: string },\n options: RequestOptions\n ) {\n return this.mcpConnections[params.serverId].client.getPrompt(\n params,\n options\n );\n }\n}\n\ntype NamespacedData = {\n tools: (Tool & { serverId: string })[];\n prompts: (Prompt & { serverId: string })[];\n resources: (Resource & { serverId: string })[];\n resourceTemplates: (ResourceTemplate & { serverId: string })[];\n};\n\nexport function getNamespacedData<T extends keyof NamespacedData>(\n mcpClients: Record<string, MCPClientConnection>,\n type: T\n): NamespacedData[T] {\n const sets = Object.entries(mcpClients).map(([name, conn]) => {\n return { name, data: conn[type] };\n });\n\n const namespacedData = sets.flatMap(({ name: serverId, data }) => {\n return data.map((item) => {\n return {\n ...item,\n // we add a serverId so we can easily pull it out and send the tool call to the right server\n serverId,\n };\n });\n });\n\n return namespacedData as NamespacedData[T]; // Type assertion needed due to TS limitations with conditional return types\n}\n"],"mappings":"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","names":["url"]}
|
|
File without changes
|