mcp-use 1.5.0-canary.6 → 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
|
@@ -1794,7 +1794,7 @@ if (container && Component) {
|
|
|
1794
1794
|
});
|
|
1795
1795
|
}
|
|
1796
1796
|
/**
|
|
1797
|
-
* Mount MCP server endpoints at /mcp
|
|
1797
|
+
* Mount MCP server endpoints at /mcp and /sse
|
|
1798
1798
|
*
|
|
1799
1799
|
* Sets up the HTTP transport layer for the MCP server, creating endpoints for
|
|
1800
1800
|
* Server-Sent Events (SSE) streaming, POST message handling, and DELETE session cleanup.
|
|
@@ -1808,48 +1808,65 @@ if (container && Component) {
|
|
|
1808
1808
|
*
|
|
1809
1809
|
* @example
|
|
1810
1810
|
* Endpoints created:
|
|
1811
|
-
* - GET /mcp - SSE streaming endpoint for real-time communication
|
|
1812
|
-
* - POST /mcp - Message handling endpoint for MCP protocol messages
|
|
1813
|
-
* - DELETE /mcp - Session cleanup endpoint
|
|
1811
|
+
* - GET /mcp, GET /sse - SSE streaming endpoint for real-time communication
|
|
1812
|
+
* - POST /mcp, POST /sse - Message handling endpoint for MCP protocol messages
|
|
1813
|
+
* - DELETE /mcp, DELETE /sse - Session cleanup endpoint
|
|
1814
1814
|
*/
|
|
1815
1815
|
async mountMcp() {
|
|
1816
1816
|
if (this.mcpMounted) return;
|
|
1817
1817
|
const { StreamableHTTPServerTransport } = await import("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
1818
|
-
const endpoint = "/mcp";
|
|
1819
1818
|
const idleTimeoutMs = this.config.sessionIdleTimeoutMs ?? 3e5;
|
|
1820
1819
|
const getOrCreateTransport = /* @__PURE__ */ __name(async (sessionId, isInit = false) => {
|
|
1820
|
+
if (isInit) {
|
|
1821
|
+
if (sessionId && this.sessions.has(sessionId)) {
|
|
1822
|
+
try {
|
|
1823
|
+
this.sessions.get(sessionId).transport.close();
|
|
1824
|
+
} catch (error) {
|
|
1825
|
+
}
|
|
1826
|
+
this.sessions.delete(sessionId);
|
|
1827
|
+
}
|
|
1828
|
+
const isProduction = this.isProductionMode();
|
|
1829
|
+
let allowedOrigins = this.config.allowedOrigins;
|
|
1830
|
+
let enableDnsRebindingProtection = false;
|
|
1831
|
+
if (isProduction) {
|
|
1832
|
+
if (allowedOrigins !== void 0) {
|
|
1833
|
+
enableDnsRebindingProtection = allowedOrigins.length > 0;
|
|
1834
|
+
}
|
|
1835
|
+
} else {
|
|
1836
|
+
allowedOrigins = void 0;
|
|
1837
|
+
enableDnsRebindingProtection = false;
|
|
1838
|
+
}
|
|
1839
|
+
const transport = new StreamableHTTPServerTransport({
|
|
1840
|
+
sessionIdGenerator: /* @__PURE__ */ __name(() => generateUUID(), "sessionIdGenerator"),
|
|
1841
|
+
enableJsonResponse: true,
|
|
1842
|
+
allowedOrigins,
|
|
1843
|
+
enableDnsRebindingProtection,
|
|
1844
|
+
onsessioninitialized: /* @__PURE__ */ __name((id) => {
|
|
1845
|
+
if (id) {
|
|
1846
|
+
this.sessions.set(id, {
|
|
1847
|
+
transport,
|
|
1848
|
+
lastAccessedAt: Date.now()
|
|
1849
|
+
});
|
|
1850
|
+
}
|
|
1851
|
+
}, "onsessioninitialized"),
|
|
1852
|
+
onsessionclosed: /* @__PURE__ */ __name((id) => {
|
|
1853
|
+
if (id) {
|
|
1854
|
+
this.sessions.delete(id);
|
|
1855
|
+
}
|
|
1856
|
+
}, "onsessionclosed")
|
|
1857
|
+
});
|
|
1858
|
+
await this.server.connect(transport);
|
|
1859
|
+
return transport;
|
|
1860
|
+
}
|
|
1821
1861
|
if (sessionId && this.sessions.has(sessionId)) {
|
|
1822
1862
|
const session = this.sessions.get(sessionId);
|
|
1823
1863
|
session.lastAccessedAt = Date.now();
|
|
1824
1864
|
return session.transport;
|
|
1825
1865
|
}
|
|
1826
|
-
if (
|
|
1866
|
+
if (sessionId) {
|
|
1827
1867
|
return null;
|
|
1828
1868
|
}
|
|
1829
|
-
|
|
1830
|
-
return null;
|
|
1831
|
-
}
|
|
1832
|
-
const transport = new StreamableHTTPServerTransport({
|
|
1833
|
-
sessionIdGenerator: /* @__PURE__ */ __name(() => generateUUID(), "sessionIdGenerator"),
|
|
1834
|
-
enableJsonResponse: true,
|
|
1835
|
-
allowedOrigins: this.config.allowedOrigins,
|
|
1836
|
-
enableDnsRebindingProtection: this.config.allowedOrigins !== void 0 && this.config.allowedOrigins.length > 0,
|
|
1837
|
-
onsessioninitialized: /* @__PURE__ */ __name((id) => {
|
|
1838
|
-
if (id) {
|
|
1839
|
-
this.sessions.set(id, {
|
|
1840
|
-
transport,
|
|
1841
|
-
lastAccessedAt: Date.now()
|
|
1842
|
-
});
|
|
1843
|
-
}
|
|
1844
|
-
}, "onsessioninitialized"),
|
|
1845
|
-
onsessionclosed: /* @__PURE__ */ __name((id) => {
|
|
1846
|
-
if (id) {
|
|
1847
|
-
this.sessions.delete(id);
|
|
1848
|
-
}
|
|
1849
|
-
}, "onsessionclosed")
|
|
1850
|
-
});
|
|
1851
|
-
await this.server.connect(transport);
|
|
1852
|
-
return transport;
|
|
1869
|
+
return null;
|
|
1853
1870
|
}, "getOrCreateTransport");
|
|
1854
1871
|
if (idleTimeoutMs > 0 && !this.idleCleanupInterval) {
|
|
1855
1872
|
this.idleCleanupInterval = setInterval(() => {
|
|
@@ -1972,245 +1989,250 @@ if (container && Component) {
|
|
|
1972
1989
|
}, "getResponse")
|
|
1973
1990
|
};
|
|
1974
1991
|
}, "createExpressLikeObjects");
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
const isInit = body?.method === "initialize";
|
|
1985
|
-
const sessionId = c.req.header("mcp-session-id");
|
|
1986
|
-
const transport = await getOrCreateTransport(sessionId, isInit);
|
|
1987
|
-
if (!transport) {
|
|
1988
|
-
if (sessionId) {
|
|
1989
|
-
return c.json(
|
|
1990
|
-
{
|
|
1991
|
-
jsonrpc: "2.0",
|
|
1992
|
-
error: {
|
|
1993
|
-
code: -32e3,
|
|
1994
|
-
message: "Session not found or expired"
|
|
1995
|
-
},
|
|
1996
|
-
id: null
|
|
1997
|
-
},
|
|
1998
|
-
404
|
|
1999
|
-
);
|
|
2000
|
-
} else {
|
|
2001
|
-
return c.json(
|
|
2002
|
-
{
|
|
2003
|
-
jsonrpc: "2.0",
|
|
2004
|
-
error: {
|
|
2005
|
-
code: -32e3,
|
|
2006
|
-
message: "Bad Request: Mcp-Session-Id header is required"
|
|
2007
|
-
},
|
|
2008
|
-
id: null
|
|
2009
|
-
},
|
|
2010
|
-
400
|
|
2011
|
-
);
|
|
1992
|
+
const mountEndpoint = /* @__PURE__ */ __name((endpoint) => {
|
|
1993
|
+
this.app.post(endpoint, async (c) => {
|
|
1994
|
+
const { expressReq, expressRes, getResponse } = createExpressLikeObjects(c);
|
|
1995
|
+
let body = {};
|
|
1996
|
+
try {
|
|
1997
|
+
body = await c.req.json();
|
|
1998
|
+
expressReq.body = body;
|
|
1999
|
+
} catch {
|
|
2000
|
+
expressReq.body = {};
|
|
2012
2001
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
);
|
|
2028
|
-
const response = getResponse();
|
|
2029
|
-
if (response) {
|
|
2030
|
-
return response;
|
|
2031
|
-
}
|
|
2032
|
-
return c.text("", 200);
|
|
2033
|
-
});
|
|
2034
|
-
this.app.get(endpoint, async (c) => {
|
|
2035
|
-
const sessionId = c.req.header("mcp-session-id");
|
|
2036
|
-
const transport = await getOrCreateTransport(sessionId, false);
|
|
2037
|
-
if (!transport) {
|
|
2038
|
-
if (sessionId) {
|
|
2039
|
-
return c.json(
|
|
2040
|
-
{
|
|
2041
|
-
jsonrpc: "2.0",
|
|
2042
|
-
error: {
|
|
2043
|
-
code: -32e3,
|
|
2044
|
-
message: "Session not found or expired"
|
|
2002
|
+
const isInit = body?.method === "initialize";
|
|
2003
|
+
const sessionId = c.req.header("mcp-session-id");
|
|
2004
|
+
const transport = await getOrCreateTransport(sessionId, isInit);
|
|
2005
|
+
if (!transport) {
|
|
2006
|
+
if (sessionId) {
|
|
2007
|
+
return c.json(
|
|
2008
|
+
{
|
|
2009
|
+
jsonrpc: "2.0",
|
|
2010
|
+
error: {
|
|
2011
|
+
code: -32e3,
|
|
2012
|
+
message: "Session not found or expired"
|
|
2013
|
+
},
|
|
2014
|
+
// Notifications don't have an id, but we include null for consistency
|
|
2015
|
+
id: body?.id ?? null
|
|
2045
2016
|
},
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2017
|
+
404
|
|
2018
|
+
);
|
|
2019
|
+
} else {
|
|
2020
|
+
return c.json(
|
|
2021
|
+
{
|
|
2022
|
+
jsonrpc: "2.0",
|
|
2023
|
+
error: {
|
|
2024
|
+
code: -32e3,
|
|
2025
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
2026
|
+
},
|
|
2027
|
+
id: body?.id ?? null
|
|
2057
2028
|
},
|
|
2058
|
-
|
|
2059
|
-
},
|
|
2060
|
-
400
|
|
2061
|
-
);
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
if (sessionId && this.sessions.has(sessionId)) {
|
|
2065
|
-
this.sessions.get(sessionId).lastAccessedAt = Date.now();
|
|
2066
|
-
}
|
|
2067
|
-
c.req.raw.signal?.addEventListener("abort", () => {
|
|
2068
|
-
transport.close();
|
|
2069
|
-
});
|
|
2070
|
-
const { readable, writable } = new globalThis.TransformStream();
|
|
2071
|
-
const writer = writable.getWriter();
|
|
2072
|
-
const encoder = new TextEncoder();
|
|
2073
|
-
let resolveResponse;
|
|
2074
|
-
const responsePromise = new Promise((resolve) => {
|
|
2075
|
-
resolveResponse = resolve;
|
|
2076
|
-
});
|
|
2077
|
-
let headersSent = false;
|
|
2078
|
-
const headers = {};
|
|
2079
|
-
let statusCode = 200;
|
|
2080
|
-
const expressRes = {
|
|
2081
|
-
statusCode: 200,
|
|
2082
|
-
headersSent: false,
|
|
2083
|
-
status: /* @__PURE__ */ __name((code) => {
|
|
2084
|
-
statusCode = code;
|
|
2085
|
-
expressRes.statusCode = code;
|
|
2086
|
-
return expressRes;
|
|
2087
|
-
}, "status"),
|
|
2088
|
-
setHeader: /* @__PURE__ */ __name((name, value) => {
|
|
2089
|
-
if (!headersSent) {
|
|
2090
|
-
headers[name] = Array.isArray(value) ? value.join(", ") : value;
|
|
2091
|
-
}
|
|
2092
|
-
}, "setHeader"),
|
|
2093
|
-
getHeader: /* @__PURE__ */ __name((name) => headers[name], "getHeader"),
|
|
2094
|
-
write: /* @__PURE__ */ __name((chunk) => {
|
|
2095
|
-
if (!headersSent) {
|
|
2096
|
-
headersSent = true;
|
|
2097
|
-
resolveResponse(
|
|
2098
|
-
new Response(readable, {
|
|
2099
|
-
status: statusCode,
|
|
2100
|
-
headers
|
|
2101
|
-
})
|
|
2029
|
+
400
|
|
2102
2030
|
);
|
|
2103
2031
|
}
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
}
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
}
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2032
|
+
}
|
|
2033
|
+
if (sessionId && this.sessions.has(sessionId)) {
|
|
2034
|
+
this.sessions.get(sessionId).lastAccessedAt = Date.now();
|
|
2035
|
+
}
|
|
2036
|
+
if (expressRes._closeHandler) {
|
|
2037
|
+
c.req.raw.signal?.addEventListener("abort", () => {
|
|
2038
|
+
transport.close();
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
await this.waitForRequestComplete(
|
|
2042
|
+
transport,
|
|
2043
|
+
expressReq,
|
|
2044
|
+
expressRes,
|
|
2045
|
+
expressReq.body
|
|
2046
|
+
);
|
|
2047
|
+
const response = getResponse();
|
|
2048
|
+
if (response) {
|
|
2049
|
+
return response;
|
|
2050
|
+
}
|
|
2051
|
+
return c.text("", 200);
|
|
2052
|
+
});
|
|
2053
|
+
this.app.get(endpoint, async (c) => {
|
|
2054
|
+
const sessionId = c.req.header("mcp-session-id");
|
|
2055
|
+
const transport = await getOrCreateTransport(sessionId, false);
|
|
2056
|
+
if (!transport) {
|
|
2057
|
+
if (sessionId) {
|
|
2058
|
+
return c.json(
|
|
2059
|
+
{
|
|
2060
|
+
jsonrpc: "2.0",
|
|
2061
|
+
error: {
|
|
2062
|
+
code: -32e3,
|
|
2063
|
+
message: "Session not found or expired"
|
|
2064
|
+
},
|
|
2065
|
+
id: null
|
|
2066
|
+
},
|
|
2067
|
+
404
|
|
2119
2068
|
);
|
|
2120
|
-
writer.close();
|
|
2121
2069
|
} else {
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
removeListener: /* @__PURE__ */ __name(() => {
|
|
2133
|
-
}, "removeListener"),
|
|
2134
|
-
writeHead: /* @__PURE__ */ __name((code, _headers) => {
|
|
2135
|
-
statusCode = code;
|
|
2136
|
-
expressRes.statusCode = code;
|
|
2137
|
-
if (_headers) {
|
|
2138
|
-
Object.assign(headers, _headers);
|
|
2139
|
-
}
|
|
2140
|
-
if (!headersSent) {
|
|
2141
|
-
headersSent = true;
|
|
2142
|
-
resolveResponse(
|
|
2143
|
-
new Response(readable, {
|
|
2144
|
-
status: statusCode,
|
|
2145
|
-
headers
|
|
2146
|
-
})
|
|
2070
|
+
return c.json(
|
|
2071
|
+
{
|
|
2072
|
+
jsonrpc: "2.0",
|
|
2073
|
+
error: {
|
|
2074
|
+
code: -32e3,
|
|
2075
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
2076
|
+
},
|
|
2077
|
+
id: null
|
|
2078
|
+
},
|
|
2079
|
+
400
|
|
2147
2080
|
);
|
|
2148
2081
|
}
|
|
2149
|
-
return expressRes;
|
|
2150
|
-
}, "writeHead"),
|
|
2151
|
-
flushHeaders: /* @__PURE__ */ __name(() => {
|
|
2152
|
-
}, "flushHeaders")
|
|
2153
|
-
};
|
|
2154
|
-
const expressReq = {
|
|
2155
|
-
...c.req.raw,
|
|
2156
|
-
url: new URL(c.req.url).pathname + new URL(c.req.url).search,
|
|
2157
|
-
path: new URL(c.req.url).pathname,
|
|
2158
|
-
query: Object.fromEntries(new URL(c.req.url).searchParams),
|
|
2159
|
-
headers: c.req.header(),
|
|
2160
|
-
method: c.req.method
|
|
2161
|
-
};
|
|
2162
|
-
transport.handleRequest(expressReq, expressRes).catch((err) => {
|
|
2163
|
-
console.error("MCP Transport error:", err);
|
|
2164
|
-
try {
|
|
2165
|
-
writer.close();
|
|
2166
|
-
} catch {
|
|
2167
2082
|
}
|
|
2083
|
+
if (sessionId && this.sessions.has(sessionId)) {
|
|
2084
|
+
this.sessions.get(sessionId).lastAccessedAt = Date.now();
|
|
2085
|
+
}
|
|
2086
|
+
c.req.raw.signal?.addEventListener("abort", () => {
|
|
2087
|
+
transport.close();
|
|
2088
|
+
});
|
|
2089
|
+
const { readable, writable } = new globalThis.TransformStream();
|
|
2090
|
+
const writer = writable.getWriter();
|
|
2091
|
+
const encoder = new TextEncoder();
|
|
2092
|
+
let resolveResponse;
|
|
2093
|
+
const responsePromise = new Promise((resolve) => {
|
|
2094
|
+
resolveResponse = resolve;
|
|
2095
|
+
});
|
|
2096
|
+
let headersSent = false;
|
|
2097
|
+
const headers = {};
|
|
2098
|
+
let statusCode = 200;
|
|
2099
|
+
const expressRes = {
|
|
2100
|
+
statusCode: 200,
|
|
2101
|
+
headersSent: false,
|
|
2102
|
+
status: /* @__PURE__ */ __name((code) => {
|
|
2103
|
+
statusCode = code;
|
|
2104
|
+
expressRes.statusCode = code;
|
|
2105
|
+
return expressRes;
|
|
2106
|
+
}, "status"),
|
|
2107
|
+
setHeader: /* @__PURE__ */ __name((name, value) => {
|
|
2108
|
+
if (!headersSent) {
|
|
2109
|
+
headers[name] = Array.isArray(value) ? value.join(", ") : value;
|
|
2110
|
+
}
|
|
2111
|
+
}, "setHeader"),
|
|
2112
|
+
getHeader: /* @__PURE__ */ __name((name) => headers[name], "getHeader"),
|
|
2113
|
+
write: /* @__PURE__ */ __name((chunk) => {
|
|
2114
|
+
if (!headersSent) {
|
|
2115
|
+
headersSent = true;
|
|
2116
|
+
resolveResponse(
|
|
2117
|
+
new Response(readable, {
|
|
2118
|
+
status: statusCode,
|
|
2119
|
+
headers
|
|
2120
|
+
})
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2123
|
+
const data = typeof chunk === "string" ? encoder.encode(chunk) : chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
|
|
2124
|
+
writer.write(data);
|
|
2125
|
+
return true;
|
|
2126
|
+
}, "write"),
|
|
2127
|
+
end: /* @__PURE__ */ __name((chunk) => {
|
|
2128
|
+
if (chunk) {
|
|
2129
|
+
expressRes.write(chunk);
|
|
2130
|
+
}
|
|
2131
|
+
if (!headersSent) {
|
|
2132
|
+
headersSent = true;
|
|
2133
|
+
resolveResponse(
|
|
2134
|
+
new Response(null, {
|
|
2135
|
+
status: statusCode,
|
|
2136
|
+
headers
|
|
2137
|
+
})
|
|
2138
|
+
);
|
|
2139
|
+
writer.close();
|
|
2140
|
+
} else {
|
|
2141
|
+
writer.close();
|
|
2142
|
+
}
|
|
2143
|
+
}, "end"),
|
|
2144
|
+
on: /* @__PURE__ */ __name((event, handler) => {
|
|
2145
|
+
if (event === "close") {
|
|
2146
|
+
expressRes._closeHandler = handler;
|
|
2147
|
+
}
|
|
2148
|
+
}, "on"),
|
|
2149
|
+
once: /* @__PURE__ */ __name(() => {
|
|
2150
|
+
}, "once"),
|
|
2151
|
+
removeListener: /* @__PURE__ */ __name(() => {
|
|
2152
|
+
}, "removeListener"),
|
|
2153
|
+
writeHead: /* @__PURE__ */ __name((code, _headers) => {
|
|
2154
|
+
statusCode = code;
|
|
2155
|
+
expressRes.statusCode = code;
|
|
2156
|
+
if (_headers) {
|
|
2157
|
+
Object.assign(headers, _headers);
|
|
2158
|
+
}
|
|
2159
|
+
if (!headersSent) {
|
|
2160
|
+
headersSent = true;
|
|
2161
|
+
resolveResponse(
|
|
2162
|
+
new Response(readable, {
|
|
2163
|
+
status: statusCode,
|
|
2164
|
+
headers
|
|
2165
|
+
})
|
|
2166
|
+
);
|
|
2167
|
+
}
|
|
2168
|
+
return expressRes;
|
|
2169
|
+
}, "writeHead"),
|
|
2170
|
+
flushHeaders: /* @__PURE__ */ __name(() => {
|
|
2171
|
+
}, "flushHeaders")
|
|
2172
|
+
};
|
|
2173
|
+
const expressReq = {
|
|
2174
|
+
...c.req.raw,
|
|
2175
|
+
url: new URL(c.req.url).pathname + new URL(c.req.url).search,
|
|
2176
|
+
path: new URL(c.req.url).pathname,
|
|
2177
|
+
query: Object.fromEntries(new URL(c.req.url).searchParams),
|
|
2178
|
+
headers: c.req.header(),
|
|
2179
|
+
method: c.req.method
|
|
2180
|
+
};
|
|
2181
|
+
transport.handleRequest(expressReq, expressRes).catch((err) => {
|
|
2182
|
+
console.error("MCP Transport error:", err);
|
|
2183
|
+
try {
|
|
2184
|
+
writer.close();
|
|
2185
|
+
} catch {
|
|
2186
|
+
}
|
|
2187
|
+
});
|
|
2188
|
+
return responsePromise;
|
|
2168
2189
|
});
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2190
|
+
this.app.delete(endpoint, async (c) => {
|
|
2191
|
+
const { expressReq, expressRes, getResponse } = createExpressLikeObjects(c);
|
|
2192
|
+
const sessionId = c.req.header("mcp-session-id");
|
|
2193
|
+
const transport = await getOrCreateTransport(sessionId, false);
|
|
2194
|
+
if (!transport) {
|
|
2195
|
+
if (sessionId) {
|
|
2196
|
+
return c.json(
|
|
2197
|
+
{
|
|
2198
|
+
jsonrpc: "2.0",
|
|
2199
|
+
error: {
|
|
2200
|
+
code: -32e3,
|
|
2201
|
+
message: "Session not found or expired"
|
|
2202
|
+
},
|
|
2203
|
+
id: null
|
|
2183
2204
|
},
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2205
|
+
404
|
|
2206
|
+
);
|
|
2207
|
+
} else {
|
|
2208
|
+
return c.json(
|
|
2209
|
+
{
|
|
2210
|
+
jsonrpc: "2.0",
|
|
2211
|
+
error: {
|
|
2212
|
+
code: -32e3,
|
|
2213
|
+
message: "Bad Request: Mcp-Session-Id header is required"
|
|
2214
|
+
},
|
|
2215
|
+
id: null
|
|
2195
2216
|
},
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
);
|
|
2217
|
+
400
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2200
2220
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2221
|
+
c.req.raw.signal?.addEventListener("abort", () => {
|
|
2222
|
+
transport.close();
|
|
2223
|
+
});
|
|
2224
|
+
await this.waitForRequestComplete(transport, expressReq, expressRes);
|
|
2225
|
+
const response = getResponse();
|
|
2226
|
+
if (response) {
|
|
2227
|
+
return response;
|
|
2228
|
+
}
|
|
2229
|
+
return c.text("", 200);
|
|
2204
2230
|
});
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
return response;
|
|
2209
|
-
}
|
|
2210
|
-
return c.text("", 200);
|
|
2211
|
-
});
|
|
2231
|
+
}, "mountEndpoint");
|
|
2232
|
+
mountEndpoint("/mcp");
|
|
2233
|
+
mountEndpoint("/sse");
|
|
2212
2234
|
this.mcpMounted = true;
|
|
2213
|
-
console.log(`[MCP] Server mounted at
|
|
2235
|
+
console.log(`[MCP] Server mounted at /mcp and /sse`);
|
|
2214
2236
|
}
|
|
2215
2237
|
/**
|
|
2216
2238
|
* Start the Hono server with MCP endpoints
|
|
@@ -2219,7 +2241,7 @@ if (container && Component) {
|
|
|
2219
2241
|
* the inspector UI (if available), and starting the server to listen
|
|
2220
2242
|
* for incoming connections. This is the main entry point for running the server.
|
|
2221
2243
|
*
|
|
2222
|
-
* The server will be accessible at the specified port with MCP endpoints at /mcp
|
|
2244
|
+
* The server will be accessible at the specified port with MCP endpoints at /mcp and /sse
|
|
2223
2245
|
* and inspector UI at /inspector (if the inspector package is installed).
|
|
2224
2246
|
*
|
|
2225
2247
|
* @param port - Port number to listen on (defaults to 3001 if not specified)
|
|
@@ -2229,7 +2251,7 @@ if (container && Component) {
|
|
|
2229
2251
|
* ```typescript
|
|
2230
2252
|
* await server.listen(8080)
|
|
2231
2253
|
* // Server now running at http://localhost:8080 (or configured host)
|
|
2232
|
-
* // MCP endpoints: http://localhost:8080/mcp
|
|
2254
|
+
* // MCP endpoints: http://localhost:8080/mcp and http://localhost:8080/sse
|
|
2233
2255
|
* // Inspector UI: http://localhost:8080/inspector
|
|
2234
2256
|
* ```
|
|
2235
2257
|
*/
|
|
@@ -2333,7 +2355,7 @@ if (container && Component) {
|
|
|
2333
2355
|
`[SERVER] Listening on http://${this.serverHost}:${this.serverPort}`
|
|
2334
2356
|
);
|
|
2335
2357
|
console.log(
|
|
2336
|
-
`[MCP] Endpoints: http://${this.serverHost}:${this.serverPort}/mcp`
|
|
2358
|
+
`[MCP] Endpoints: http://${this.serverHost}:${this.serverPort}/mcp and http://${this.serverHost}:${this.serverPort}/sse`
|
|
2337
2359
|
);
|
|
2338
2360
|
}
|
|
2339
2361
|
);
|
|
@@ -2619,7 +2641,7 @@ if (container && Component) {
|
|
|
2619
2641
|
* @example
|
|
2620
2642
|
* If @mcp-use/inspector is installed:
|
|
2621
2643
|
* - Inspector UI available at http://localhost:PORT/inspector
|
|
2622
|
-
* - Automatically connects to http://localhost:PORT/mcp
|
|
2644
|
+
* - Automatically connects to http://localhost:PORT/mcp (or /sse)
|
|
2623
2645
|
*
|
|
2624
2646
|
* If not installed:
|
|
2625
2647
|
* - Server continues to function normally
|
|
@@ -2969,7 +2991,9 @@ function createMCPServer(name, config = {}) {
|
|
|
2969
2991
|
version: config.version || "1.0.0",
|
|
2970
2992
|
description: config.description,
|
|
2971
2993
|
host: config.host,
|
|
2972
|
-
baseUrl: config.baseUrl
|
|
2994
|
+
baseUrl: config.baseUrl,
|
|
2995
|
+
allowedOrigins: config.allowedOrigins,
|
|
2996
|
+
sessionIdleTimeoutMs: config.sessionIdleTimeoutMs
|
|
2973
2997
|
});
|
|
2974
2998
|
return instance;
|
|
2975
2999
|
}
|