mcp-use 1.5.0-canary.5 → 1.5.0-canary.7
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/.tsbuildinfo +1 -1
- package/dist/index.js +20 -20
- package/dist/src/browser.js +7 -7
- package/dist/src/server/index.cjs +282 -258
- package/dist/src/server/index.js +282 -258
- package/dist/src/server/mcp-server.d.ts +22 -8
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/types/common.d.ts +26 -0
- package/dist/src/server/types/common.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/src/server/index.js
CHANGED
|
@@ -1756,7 +1756,7 @@ if (container && Component) {
|
|
|
1756
1756
|
});
|
|
1757
1757
|
}
|
|
1758
1758
|
/**
|
|
1759
|
-
* Mount MCP server endpoints at /mcp
|
|
1759
|
+
* Mount MCP server endpoints at /mcp and /sse
|
|
1760
1760
|
*
|
|
1761
1761
|
* Sets up the HTTP transport layer for the MCP server, creating endpoints for
|
|
1762
1762
|
* Server-Sent Events (SSE) streaming, POST message handling, and DELETE session cleanup.
|
|
@@ -1770,48 +1770,65 @@ if (container && Component) {
|
|
|
1770
1770
|
*
|
|
1771
1771
|
* @example
|
|
1772
1772
|
* Endpoints created:
|
|
1773
|
-
* - GET /mcp - SSE streaming endpoint for real-time communication
|
|
1774
|
-
* - POST /mcp - Message handling endpoint for MCP protocol messages
|
|
1775
|
-
* - DELETE /mcp - Session cleanup endpoint
|
|
1773
|
+
* - GET /mcp, GET /sse - SSE streaming endpoint for real-time communication
|
|
1774
|
+
* - POST /mcp, POST /sse - Message handling endpoint for MCP protocol messages
|
|
1775
|
+
* - DELETE /mcp, DELETE /sse - Session cleanup endpoint
|
|
1776
1776
|
*/
|
|
1777
1777
|
async mountMcp() {
|
|
1778
1778
|
if (this.mcpMounted) return;
|
|
1779
1779
|
const { StreamableHTTPServerTransport } = await import("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
1780
|
-
const endpoint = "/mcp";
|
|
1781
1780
|
const idleTimeoutMs = this.config.sessionIdleTimeoutMs ?? 3e5;
|
|
1782
1781
|
const getOrCreateTransport = /* @__PURE__ */ __name(async (sessionId, isInit = false) => {
|
|
1782
|
+
if (isInit) {
|
|
1783
|
+
if (sessionId && this.sessions.has(sessionId)) {
|
|
1784
|
+
try {
|
|
1785
|
+
this.sessions.get(sessionId).transport.close();
|
|
1786
|
+
} catch (error) {
|
|
1787
|
+
}
|
|
1788
|
+
this.sessions.delete(sessionId);
|
|
1789
|
+
}
|
|
1790
|
+
const isProduction = this.isProductionMode();
|
|
1791
|
+
let allowedOrigins = this.config.allowedOrigins;
|
|
1792
|
+
let enableDnsRebindingProtection = false;
|
|
1793
|
+
if (isProduction) {
|
|
1794
|
+
if (allowedOrigins !== void 0) {
|
|
1795
|
+
enableDnsRebindingProtection = allowedOrigins.length > 0;
|
|
1796
|
+
}
|
|
1797
|
+
} else {
|
|
1798
|
+
allowedOrigins = void 0;
|
|
1799
|
+
enableDnsRebindingProtection = false;
|
|
1800
|
+
}
|
|
1801
|
+
const transport = new StreamableHTTPServerTransport({
|
|
1802
|
+
sessionIdGenerator: /* @__PURE__ */ __name(() => generateUUID(), "sessionIdGenerator"),
|
|
1803
|
+
enableJsonResponse: true,
|
|
1804
|
+
allowedOrigins,
|
|
1805
|
+
enableDnsRebindingProtection,
|
|
1806
|
+
onsessioninitialized: /* @__PURE__ */ __name((id) => {
|
|
1807
|
+
if (id) {
|
|
1808
|
+
this.sessions.set(id, {
|
|
1809
|
+
transport,
|
|
1810
|
+
lastAccessedAt: Date.now()
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
}, "onsessioninitialized"),
|
|
1814
|
+
onsessionclosed: /* @__PURE__ */ __name((id) => {
|
|
1815
|
+
if (id) {
|
|
1816
|
+
this.sessions.delete(id);
|
|
1817
|
+
}
|
|
1818
|
+
}, "onsessionclosed")
|
|
1819
|
+
});
|
|
1820
|
+
await this.server.connect(transport);
|
|
1821
|
+
return transport;
|
|
1822
|
+
}
|
|
1783
1823
|
if (sessionId && this.sessions.has(sessionId)) {
|
|
1784
1824
|
const session = this.sessions.get(sessionId);
|
|
1785
1825
|
session.lastAccessedAt = Date.now();
|
|
1786
1826
|
return session.transport;
|
|
1787
1827
|
}
|
|
1788
|
-
if (
|
|
1828
|
+
if (sessionId) {
|
|
1789
1829
|
return null;
|
|
1790
1830
|
}
|
|
1791
|
-
|
|
1792
|
-
return null;
|
|
1793
|
-
}
|
|
1794
|
-
const transport = new StreamableHTTPServerTransport({
|
|
1795
|
-
sessionIdGenerator: /* @__PURE__ */ __name(() => generateUUID(), "sessionIdGenerator"),
|
|
1796
|
-
enableJsonResponse: true,
|
|
1797
|
-
allowedOrigins: this.config.allowedOrigins,
|
|
1798
|
-
enableDnsRebindingProtection: this.config.allowedOrigins !== void 0 && this.config.allowedOrigins.length > 0,
|
|
1799
|
-
onsessioninitialized: /* @__PURE__ */ __name((id) => {
|
|
1800
|
-
if (id) {
|
|
1801
|
-
this.sessions.set(id, {
|
|
1802
|
-
transport,
|
|
1803
|
-
lastAccessedAt: Date.now()
|
|
1804
|
-
});
|
|
1805
|
-
}
|
|
1806
|
-
}, "onsessioninitialized"),
|
|
1807
|
-
onsessionclosed: /* @__PURE__ */ __name((id) => {
|
|
1808
|
-
if (id) {
|
|
1809
|
-
this.sessions.delete(id);
|
|
1810
|
-
}
|
|
1811
|
-
}, "onsessionclosed")
|
|
1812
|
-
});
|
|
1813
|
-
await this.server.connect(transport);
|
|
1814
|
-
return transport;
|
|
1831
|
+
return null;
|
|
1815
1832
|
}, "getOrCreateTransport");
|
|
1816
1833
|
if (idleTimeoutMs > 0 && !this.idleCleanupInterval) {
|
|
1817
1834
|
this.idleCleanupInterval = setInterval(() => {
|
|
@@ -1934,245 +1951,250 @@ if (container && Component) {
|
|
|
1934
1951
|
}, "getResponse")
|
|
1935
1952
|
};
|
|
1936
1953
|
}, "createExpressLikeObjects");
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
const isInit = body?.method === "initialize";
|
|
1947
|
-
const sessionId = c.req.header("mcp-session-id");
|
|
1948
|
-
const transport = await getOrCreateTransport(sessionId, isInit);
|
|
1949
|
-
if (!transport) {
|
|
1950
|
-
if (sessionId) {
|
|
1951
|
-
return c.json(
|
|
1952
|
-
{
|
|
1953
|
-
jsonrpc: "2.0",
|
|
1954
|
-
error: {
|
|
1955
|
-
code: -32e3,
|
|
1956
|
-
message: "Session not found or expired"
|
|
1957
|
-
},
|
|
1958
|
-
id: null
|
|
1959
|
-
},
|
|
1960
|
-
404
|
|
1961
|
-
);
|
|
1962
|
-
} else {
|
|
1963
|
-
return c.json(
|
|
1964
|
-
{
|
|
1965
|
-
jsonrpc: "2.0",
|
|
1966
|
-
error: {
|
|
1967
|
-
code: -32e3,
|
|
1968
|
-
message: "Bad Request: Mcp-Session-Id header is required"
|
|
1969
|
-
},
|
|
1970
|
-
id: null
|
|
1971
|
-
},
|
|
1972
|
-
400
|
|
1973
|
-
);
|
|
1954
|
+
const mountEndpoint = /* @__PURE__ */ __name((endpoint) => {
|
|
1955
|
+
this.app.post(endpoint, async (c) => {
|
|
1956
|
+
const { expressReq, expressRes, getResponse } = createExpressLikeObjects(c);
|
|
1957
|
+
let body = {};
|
|
1958
|
+
try {
|
|
1959
|
+
body = await c.req.json();
|
|
1960
|
+
expressReq.body = body;
|
|
1961
|
+
} catch {
|
|
1962
|
+
expressReq.body = {};
|
|
1974
1963
|
}
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
);
|
|
1990
|
-
const response = getResponse();
|
|
1991
|
-
if (response) {
|
|
1992
|
-
return response;
|
|
1993
|
-
}
|
|
1994
|
-
return c.text("", 200);
|
|
1995
|
-
});
|
|
1996
|
-
this.app.get(endpoint, async (c) => {
|
|
1997
|
-
const sessionId = c.req.header("mcp-session-id");
|
|
1998
|
-
const transport = await getOrCreateTransport(sessionId, false);
|
|
1999
|
-
if (!transport) {
|
|
2000
|
-
if (sessionId) {
|
|
2001
|
-
return c.json(
|
|
2002
|
-
{
|
|
2003
|
-
jsonrpc: "2.0",
|
|
2004
|
-
error: {
|
|
2005
|
-
code: -32e3,
|
|
2006
|
-
message: "Session not found or expired"
|
|
1964
|
+
const isInit = body?.method === "initialize";
|
|
1965
|
+
const sessionId = c.req.header("mcp-session-id");
|
|
1966
|
+
const transport = await getOrCreateTransport(sessionId, isInit);
|
|
1967
|
+
if (!transport) {
|
|
1968
|
+
if (sessionId) {
|
|
1969
|
+
return c.json(
|
|
1970
|
+
{
|
|
1971
|
+
jsonrpc: "2.0",
|
|
1972
|
+
error: {
|
|
1973
|
+
code: -32e3,
|
|
1974
|
+
message: "Session not found or expired"
|
|
1975
|
+
},
|
|
1976
|
+
// Notifications don't have an id, but we include null for consistency
|
|
1977
|
+
id: body?.id ?? null
|
|
2007
1978
|
},
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
1979
|
+
404
|
|
1980
|
+
);
|
|
1981
|
+
} else {
|
|
1982
|
+
return c.json(
|
|
1983
|
+
{
|
|
1984
|
+
jsonrpc: "2.0",
|
|
1985
|
+
error: {
|
|
1986
|
+
code: -32e3,
|
|
1987
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
1988
|
+
},
|
|
1989
|
+
id: body?.id ?? null
|
|
2019
1990
|
},
|
|
2020
|
-
|
|
2021
|
-
},
|
|
2022
|
-
400
|
|
2023
|
-
);
|
|
2024
|
-
}
|
|
2025
|
-
}
|
|
2026
|
-
if (sessionId && this.sessions.has(sessionId)) {
|
|
2027
|
-
this.sessions.get(sessionId).lastAccessedAt = Date.now();
|
|
2028
|
-
}
|
|
2029
|
-
c.req.raw.signal?.addEventListener("abort", () => {
|
|
2030
|
-
transport.close();
|
|
2031
|
-
});
|
|
2032
|
-
const { readable, writable } = new globalThis.TransformStream();
|
|
2033
|
-
const writer = writable.getWriter();
|
|
2034
|
-
const encoder = new TextEncoder();
|
|
2035
|
-
let resolveResponse;
|
|
2036
|
-
const responsePromise = new Promise((resolve) => {
|
|
2037
|
-
resolveResponse = resolve;
|
|
2038
|
-
});
|
|
2039
|
-
let headersSent = false;
|
|
2040
|
-
const headers = {};
|
|
2041
|
-
let statusCode = 200;
|
|
2042
|
-
const expressRes = {
|
|
2043
|
-
statusCode: 200,
|
|
2044
|
-
headersSent: false,
|
|
2045
|
-
status: /* @__PURE__ */ __name((code) => {
|
|
2046
|
-
statusCode = code;
|
|
2047
|
-
expressRes.statusCode = code;
|
|
2048
|
-
return expressRes;
|
|
2049
|
-
}, "status"),
|
|
2050
|
-
setHeader: /* @__PURE__ */ __name((name, value) => {
|
|
2051
|
-
if (!headersSent) {
|
|
2052
|
-
headers[name] = Array.isArray(value) ? value.join(", ") : value;
|
|
2053
|
-
}
|
|
2054
|
-
}, "setHeader"),
|
|
2055
|
-
getHeader: /* @__PURE__ */ __name((name) => headers[name], "getHeader"),
|
|
2056
|
-
write: /* @__PURE__ */ __name((chunk) => {
|
|
2057
|
-
if (!headersSent) {
|
|
2058
|
-
headersSent = true;
|
|
2059
|
-
resolveResponse(
|
|
2060
|
-
new Response(readable, {
|
|
2061
|
-
status: statusCode,
|
|
2062
|
-
headers
|
|
2063
|
-
})
|
|
1991
|
+
400
|
|
2064
1992
|
);
|
|
2065
1993
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
}
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
1994
|
+
}
|
|
1995
|
+
if (sessionId && this.sessions.has(sessionId)) {
|
|
1996
|
+
this.sessions.get(sessionId).lastAccessedAt = Date.now();
|
|
1997
|
+
}
|
|
1998
|
+
if (expressRes._closeHandler) {
|
|
1999
|
+
c.req.raw.signal?.addEventListener("abort", () => {
|
|
2000
|
+
transport.close();
|
|
2001
|
+
});
|
|
2002
|
+
}
|
|
2003
|
+
await this.waitForRequestComplete(
|
|
2004
|
+
transport,
|
|
2005
|
+
expressReq,
|
|
2006
|
+
expressRes,
|
|
2007
|
+
expressReq.body
|
|
2008
|
+
);
|
|
2009
|
+
const response = getResponse();
|
|
2010
|
+
if (response) {
|
|
2011
|
+
return response;
|
|
2012
|
+
}
|
|
2013
|
+
return c.text("", 200);
|
|
2014
|
+
});
|
|
2015
|
+
this.app.get(endpoint, async (c) => {
|
|
2016
|
+
const sessionId = c.req.header("mcp-session-id");
|
|
2017
|
+
const transport = await getOrCreateTransport(sessionId, false);
|
|
2018
|
+
if (!transport) {
|
|
2019
|
+
if (sessionId) {
|
|
2020
|
+
return c.json(
|
|
2021
|
+
{
|
|
2022
|
+
jsonrpc: "2.0",
|
|
2023
|
+
error: {
|
|
2024
|
+
code: -32e3,
|
|
2025
|
+
message: "Session not found or expired"
|
|
2026
|
+
},
|
|
2027
|
+
id: null
|
|
2028
|
+
},
|
|
2029
|
+
404
|
|
2081
2030
|
);
|
|
2082
|
-
writer.close();
|
|
2083
2031
|
} else {
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
removeListener: /* @__PURE__ */ __name(() => {
|
|
2095
|
-
}, "removeListener"),
|
|
2096
|
-
writeHead: /* @__PURE__ */ __name((code, _headers) => {
|
|
2097
|
-
statusCode = code;
|
|
2098
|
-
expressRes.statusCode = code;
|
|
2099
|
-
if (_headers) {
|
|
2100
|
-
Object.assign(headers, _headers);
|
|
2101
|
-
}
|
|
2102
|
-
if (!headersSent) {
|
|
2103
|
-
headersSent = true;
|
|
2104
|
-
resolveResponse(
|
|
2105
|
-
new Response(readable, {
|
|
2106
|
-
status: statusCode,
|
|
2107
|
-
headers
|
|
2108
|
-
})
|
|
2032
|
+
return c.json(
|
|
2033
|
+
{
|
|
2034
|
+
jsonrpc: "2.0",
|
|
2035
|
+
error: {
|
|
2036
|
+
code: -32e3,
|
|
2037
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
2038
|
+
},
|
|
2039
|
+
id: null
|
|
2040
|
+
},
|
|
2041
|
+
400
|
|
2109
2042
|
);
|
|
2110
2043
|
}
|
|
2111
|
-
return expressRes;
|
|
2112
|
-
}, "writeHead"),
|
|
2113
|
-
flushHeaders: /* @__PURE__ */ __name(() => {
|
|
2114
|
-
}, "flushHeaders")
|
|
2115
|
-
};
|
|
2116
|
-
const expressReq = {
|
|
2117
|
-
...c.req.raw,
|
|
2118
|
-
url: new URL(c.req.url).pathname + new URL(c.req.url).search,
|
|
2119
|
-
path: new URL(c.req.url).pathname,
|
|
2120
|
-
query: Object.fromEntries(new URL(c.req.url).searchParams),
|
|
2121
|
-
headers: c.req.header(),
|
|
2122
|
-
method: c.req.method
|
|
2123
|
-
};
|
|
2124
|
-
transport.handleRequest(expressReq, expressRes).catch((err) => {
|
|
2125
|
-
console.error("MCP Transport error:", err);
|
|
2126
|
-
try {
|
|
2127
|
-
writer.close();
|
|
2128
|
-
} catch {
|
|
2129
2044
|
}
|
|
2045
|
+
if (sessionId && this.sessions.has(sessionId)) {
|
|
2046
|
+
this.sessions.get(sessionId).lastAccessedAt = Date.now();
|
|
2047
|
+
}
|
|
2048
|
+
c.req.raw.signal?.addEventListener("abort", () => {
|
|
2049
|
+
transport.close();
|
|
2050
|
+
});
|
|
2051
|
+
const { readable, writable } = new globalThis.TransformStream();
|
|
2052
|
+
const writer = writable.getWriter();
|
|
2053
|
+
const encoder = new TextEncoder();
|
|
2054
|
+
let resolveResponse;
|
|
2055
|
+
const responsePromise = new Promise((resolve) => {
|
|
2056
|
+
resolveResponse = resolve;
|
|
2057
|
+
});
|
|
2058
|
+
let headersSent = false;
|
|
2059
|
+
const headers = {};
|
|
2060
|
+
let statusCode = 200;
|
|
2061
|
+
const expressRes = {
|
|
2062
|
+
statusCode: 200,
|
|
2063
|
+
headersSent: false,
|
|
2064
|
+
status: /* @__PURE__ */ __name((code) => {
|
|
2065
|
+
statusCode = code;
|
|
2066
|
+
expressRes.statusCode = code;
|
|
2067
|
+
return expressRes;
|
|
2068
|
+
}, "status"),
|
|
2069
|
+
setHeader: /* @__PURE__ */ __name((name, value) => {
|
|
2070
|
+
if (!headersSent) {
|
|
2071
|
+
headers[name] = Array.isArray(value) ? value.join(", ") : value;
|
|
2072
|
+
}
|
|
2073
|
+
}, "setHeader"),
|
|
2074
|
+
getHeader: /* @__PURE__ */ __name((name) => headers[name], "getHeader"),
|
|
2075
|
+
write: /* @__PURE__ */ __name((chunk) => {
|
|
2076
|
+
if (!headersSent) {
|
|
2077
|
+
headersSent = true;
|
|
2078
|
+
resolveResponse(
|
|
2079
|
+
new Response(readable, {
|
|
2080
|
+
status: statusCode,
|
|
2081
|
+
headers
|
|
2082
|
+
})
|
|
2083
|
+
);
|
|
2084
|
+
}
|
|
2085
|
+
const data = typeof chunk === "string" ? encoder.encode(chunk) : chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
|
|
2086
|
+
writer.write(data);
|
|
2087
|
+
return true;
|
|
2088
|
+
}, "write"),
|
|
2089
|
+
end: /* @__PURE__ */ __name((chunk) => {
|
|
2090
|
+
if (chunk) {
|
|
2091
|
+
expressRes.write(chunk);
|
|
2092
|
+
}
|
|
2093
|
+
if (!headersSent) {
|
|
2094
|
+
headersSent = true;
|
|
2095
|
+
resolveResponse(
|
|
2096
|
+
new Response(null, {
|
|
2097
|
+
status: statusCode,
|
|
2098
|
+
headers
|
|
2099
|
+
})
|
|
2100
|
+
);
|
|
2101
|
+
writer.close();
|
|
2102
|
+
} else {
|
|
2103
|
+
writer.close();
|
|
2104
|
+
}
|
|
2105
|
+
}, "end"),
|
|
2106
|
+
on: /* @__PURE__ */ __name((event, handler) => {
|
|
2107
|
+
if (event === "close") {
|
|
2108
|
+
expressRes._closeHandler = handler;
|
|
2109
|
+
}
|
|
2110
|
+
}, "on"),
|
|
2111
|
+
once: /* @__PURE__ */ __name(() => {
|
|
2112
|
+
}, "once"),
|
|
2113
|
+
removeListener: /* @__PURE__ */ __name(() => {
|
|
2114
|
+
}, "removeListener"),
|
|
2115
|
+
writeHead: /* @__PURE__ */ __name((code, _headers) => {
|
|
2116
|
+
statusCode = code;
|
|
2117
|
+
expressRes.statusCode = code;
|
|
2118
|
+
if (_headers) {
|
|
2119
|
+
Object.assign(headers, _headers);
|
|
2120
|
+
}
|
|
2121
|
+
if (!headersSent) {
|
|
2122
|
+
headersSent = true;
|
|
2123
|
+
resolveResponse(
|
|
2124
|
+
new Response(readable, {
|
|
2125
|
+
status: statusCode,
|
|
2126
|
+
headers
|
|
2127
|
+
})
|
|
2128
|
+
);
|
|
2129
|
+
}
|
|
2130
|
+
return expressRes;
|
|
2131
|
+
}, "writeHead"),
|
|
2132
|
+
flushHeaders: /* @__PURE__ */ __name(() => {
|
|
2133
|
+
}, "flushHeaders")
|
|
2134
|
+
};
|
|
2135
|
+
const expressReq = {
|
|
2136
|
+
...c.req.raw,
|
|
2137
|
+
url: new URL(c.req.url).pathname + new URL(c.req.url).search,
|
|
2138
|
+
path: new URL(c.req.url).pathname,
|
|
2139
|
+
query: Object.fromEntries(new URL(c.req.url).searchParams),
|
|
2140
|
+
headers: c.req.header(),
|
|
2141
|
+
method: c.req.method
|
|
2142
|
+
};
|
|
2143
|
+
transport.handleRequest(expressReq, expressRes).catch((err) => {
|
|
2144
|
+
console.error("MCP Transport error:", err);
|
|
2145
|
+
try {
|
|
2146
|
+
writer.close();
|
|
2147
|
+
} catch {
|
|
2148
|
+
}
|
|
2149
|
+
});
|
|
2150
|
+
return responsePromise;
|
|
2130
2151
|
});
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2152
|
+
this.app.delete(endpoint, async (c) => {
|
|
2153
|
+
const { expressReq, expressRes, getResponse } = createExpressLikeObjects(c);
|
|
2154
|
+
const sessionId = c.req.header("mcp-session-id");
|
|
2155
|
+
const transport = await getOrCreateTransport(sessionId, false);
|
|
2156
|
+
if (!transport) {
|
|
2157
|
+
if (sessionId) {
|
|
2158
|
+
return c.json(
|
|
2159
|
+
{
|
|
2160
|
+
jsonrpc: "2.0",
|
|
2161
|
+
error: {
|
|
2162
|
+
code: -32e3,
|
|
2163
|
+
message: "Session not found or expired"
|
|
2164
|
+
},
|
|
2165
|
+
id: null
|
|
2145
2166
|
},
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2167
|
+
404
|
|
2168
|
+
);
|
|
2169
|
+
} else {
|
|
2170
|
+
return c.json(
|
|
2171
|
+
{
|
|
2172
|
+
jsonrpc: "2.0",
|
|
2173
|
+
error: {
|
|
2174
|
+
code: -32e3,
|
|
2175
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
2176
|
+
},
|
|
2177
|
+
id: null
|
|
2157
2178
|
},
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
);
|
|
2179
|
+
400
|
|
2180
|
+
);
|
|
2181
|
+
}
|
|
2162
2182
|
}
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2183
|
+
c.req.raw.signal?.addEventListener("abort", () => {
|
|
2184
|
+
transport.close();
|
|
2185
|
+
});
|
|
2186
|
+
await this.waitForRequestComplete(transport, expressReq, expressRes);
|
|
2187
|
+
const response = getResponse();
|
|
2188
|
+
if (response) {
|
|
2189
|
+
return response;
|
|
2190
|
+
}
|
|
2191
|
+
return c.text("", 200);
|
|
2166
2192
|
});
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
return response;
|
|
2171
|
-
}
|
|
2172
|
-
return c.text("", 200);
|
|
2173
|
-
});
|
|
2193
|
+
}, "mountEndpoint");
|
|
2194
|
+
mountEndpoint("/mcp");
|
|
2195
|
+
mountEndpoint("/sse");
|
|
2174
2196
|
this.mcpMounted = true;
|
|
2175
|
-
console.log(`[MCP] Server mounted at
|
|
2197
|
+
console.log(`[MCP] Server mounted at /mcp and /sse`);
|
|
2176
2198
|
}
|
|
2177
2199
|
/**
|
|
2178
2200
|
* Start the Hono server with MCP endpoints
|
|
@@ -2181,7 +2203,7 @@ if (container && Component) {
|
|
|
2181
2203
|
* the inspector UI (if available), and starting the server to listen
|
|
2182
2204
|
* for incoming connections. This is the main entry point for running the server.
|
|
2183
2205
|
*
|
|
2184
|
-
* The server will be accessible at the specified port with MCP endpoints at /mcp
|
|
2206
|
+
* The server will be accessible at the specified port with MCP endpoints at /mcp and /sse
|
|
2185
2207
|
* and inspector UI at /inspector (if the inspector package is installed).
|
|
2186
2208
|
*
|
|
2187
2209
|
* @param port - Port number to listen on (defaults to 3001 if not specified)
|
|
@@ -2191,7 +2213,7 @@ if (container && Component) {
|
|
|
2191
2213
|
* ```typescript
|
|
2192
2214
|
* await server.listen(8080)
|
|
2193
2215
|
* // Server now running at http://localhost:8080 (or configured host)
|
|
2194
|
-
* // MCP endpoints: http://localhost:8080/mcp
|
|
2216
|
+
* // MCP endpoints: http://localhost:8080/mcp and http://localhost:8080/sse
|
|
2195
2217
|
* // Inspector UI: http://localhost:8080/inspector
|
|
2196
2218
|
* ```
|
|
2197
2219
|
*/
|
|
@@ -2295,7 +2317,7 @@ if (container && Component) {
|
|
|
2295
2317
|
`[SERVER] Listening on http://${this.serverHost}:${this.serverPort}`
|
|
2296
2318
|
);
|
|
2297
2319
|
console.log(
|
|
2298
|
-
`[MCP] Endpoints: http://${this.serverHost}:${this.serverPort}/mcp`
|
|
2320
|
+
`[MCP] Endpoints: http://${this.serverHost}:${this.serverPort}/mcp and http://${this.serverHost}:${this.serverPort}/sse`
|
|
2299
2321
|
);
|
|
2300
2322
|
}
|
|
2301
2323
|
);
|
|
@@ -2581,7 +2603,7 @@ if (container && Component) {
|
|
|
2581
2603
|
* @example
|
|
2582
2604
|
* If @mcp-use/inspector is installed:
|
|
2583
2605
|
* - Inspector UI available at http://localhost:PORT/inspector
|
|
2584
|
-
* - Automatically connects to http://localhost:PORT/mcp
|
|
2606
|
+
* - Automatically connects to http://localhost:PORT/mcp (or /sse)
|
|
2585
2607
|
*
|
|
2586
2608
|
* If not installed:
|
|
2587
2609
|
* - Server continues to function normally
|
|
@@ -2931,7 +2953,9 @@ function createMCPServer(name, config = {}) {
|
|
|
2931
2953
|
version: config.version || "1.0.0",
|
|
2932
2954
|
description: config.description,
|
|
2933
2955
|
host: config.host,
|
|
2934
|
-
baseUrl: config.baseUrl
|
|
2956
|
+
baseUrl: config.baseUrl,
|
|
2957
|
+
allowedOrigins: config.allowedOrigins,
|
|
2958
|
+
sessionIdleTimeoutMs: config.sessionIdleTimeoutMs
|
|
2935
2959
|
});
|
|
2936
2960
|
return instance;
|
|
2937
2961
|
}
|