@frontmcp/sdk 1.8.5 → 1.8.6
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/auth/flows/session.verify.flow.d.ts.map +1 -1
- package/common/dynamic/dynamic.plugin.d.ts +11 -2
- package/common/dynamic/dynamic.plugin.d.ts.map +1 -1
- package/common/utils/list-all-pages.utils.d.ts +17 -0
- package/common/utils/list-all-pages.utils.d.ts.map +1 -0
- package/esm/index.mjs +272 -130
- package/index.js +245 -111
- package/package.json +10 -10
- package/plugin/plugin.registry.d.ts.map +1 -1
- package/remote-mcp/mcp-client.service.d.ts.map +1 -1
- package/remote-mcp/mcp-stateless-client.adapter.d.ts +16 -5
- package/remote-mcp/mcp-stateless-client.adapter.d.ts.map +1 -1
- package/scope/scope.instance.d.ts.map +1 -1
- package/tool/flows/call-tool.flow.d.ts +1 -0
- package/tool/flows/call-tool.flow.d.ts.map +1 -1
- package/transport/flows/handle.sse.flow.d.ts +25 -0
- package/transport/flows/handle.sse.flow.d.ts.map +1 -1
- package/transport/flows/handle.streamable-http.flow.d.ts +10 -0
- package/transport/flows/handle.streamable-http.flow.d.ts.map +1 -1
- package/transport/mcp-20260728/client/mcp-stateless.client.d.ts +7 -2
- package/transport/mcp-20260728/client/mcp-stateless.client.d.ts.map +1 -1
- package/transport/mcp-20260728/dispatcher.d.ts.map +1 -1
- package/transport/mcp-20260728/request-state.d.ts +28 -0
- package/transport/mcp-20260728/request-state.d.ts.map +1 -1
package/index.js
CHANGED
|
@@ -5972,6 +5972,33 @@ var init_errors = __esm({
|
|
|
5972
5972
|
}
|
|
5973
5973
|
});
|
|
5974
5974
|
|
|
5975
|
+
// libs/sdk/src/common/utils/list-all-pages.utils.ts
|
|
5976
|
+
async function listAllPages(method, fetchPage, fail = (message) => new InternalMcpError(message, "LIST_PAGINATION_STALLED")) {
|
|
5977
|
+
const items = [];
|
|
5978
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
5979
|
+
let cursor;
|
|
5980
|
+
for (let page = 0; page < MAX_LIST_PAGES; page++) {
|
|
5981
|
+
const result = await fetchPage(cursor);
|
|
5982
|
+
items.push(...result.items ?? []);
|
|
5983
|
+
const next = result.nextCursor;
|
|
5984
|
+
if (!next) return items;
|
|
5985
|
+
if (seenCursors.has(next)) {
|
|
5986
|
+
throw fail(`${method} returned the cursor "${next}" twice`);
|
|
5987
|
+
}
|
|
5988
|
+
seenCursors.add(next);
|
|
5989
|
+
cursor = next;
|
|
5990
|
+
}
|
|
5991
|
+
throw fail(`${method} did not finish within ${MAX_LIST_PAGES} pages`);
|
|
5992
|
+
}
|
|
5993
|
+
var MAX_LIST_PAGES;
|
|
5994
|
+
var init_list_all_pages_utils = __esm({
|
|
5995
|
+
"libs/sdk/src/common/utils/list-all-pages.utils.ts"() {
|
|
5996
|
+
"use strict";
|
|
5997
|
+
init_mcp_error();
|
|
5998
|
+
MAX_LIST_PAGES = 1e3;
|
|
5999
|
+
}
|
|
6000
|
+
});
|
|
6001
|
+
|
|
5975
6002
|
// libs/sdk/src/transport/mcp-handlers/skills-mcp.types.ts
|
|
5976
6003
|
var import_lazy_zod40, SkillsSearchRequestSchema, SkillsSearchResultSchema, SkillsLoadRequestSchema, SkillsLoadResultSchema, SkillsListRequestSchema, SkillsListResultSchema;
|
|
5977
6004
|
var init_skills_mcp_types = __esm({
|
|
@@ -12043,6 +12070,7 @@ var init_direct_client = __esm({
|
|
|
12043
12070
|
"use strict";
|
|
12044
12071
|
import_protocol30 = require("@frontmcp/protocol");
|
|
12045
12072
|
import_utils29 = require("@frontmcp/utils");
|
|
12073
|
+
init_list_all_pages_utils();
|
|
12046
12074
|
init_errors();
|
|
12047
12075
|
init_skills_mcp_types();
|
|
12048
12076
|
init_llm_platform();
|
|
@@ -12189,8 +12217,11 @@ var init_direct_client = __esm({
|
|
|
12189
12217
|
// Tool Operations (platform-formatted)
|
|
12190
12218
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
12191
12219
|
async listTools() {
|
|
12192
|
-
const
|
|
12193
|
-
|
|
12220
|
+
const tools = await listAllPages("tools/list", async (cursor) => {
|
|
12221
|
+
const result = await this.mcpClient.listTools(cursor ? { cursor } : void 0);
|
|
12222
|
+
return { items: result.tools, nextCursor: result.nextCursor };
|
|
12223
|
+
});
|
|
12224
|
+
return formatToolsForPlatform(tools, this.platform);
|
|
12194
12225
|
}
|
|
12195
12226
|
async callTool(name44, args) {
|
|
12196
12227
|
const result = await this.mcpClient.callTool({
|
|
@@ -21992,6 +22023,9 @@ var init_call_tool_flow = __esm({
|
|
|
21992
22023
|
uiResult: import_lazy_zod57.z.any().optional(),
|
|
21993
22024
|
// UI metadata from rendering (merged into _meta)
|
|
21994
22025
|
uiMeta: import_lazy_zod57.z.record(import_lazy_zod57.z.string(), import_lazy_zod57.z.unknown()).optional(),
|
|
22026
|
+
// Metadata hooks add to the result (e.g. the cache plugin's `cache: 'hit'`), merged into the
|
|
22027
|
+
// result's _meta; never merged into rawOutput, which is the tool's data
|
|
22028
|
+
resultMeta: import_lazy_zod57.z.record(import_lazy_zod57.z.string(), import_lazy_zod57.z.unknown()).optional(),
|
|
21995
22029
|
// Progress token from request's _meta (for progress notifications)
|
|
21996
22030
|
progressToken: import_lazy_zod57.z.union([import_lazy_zod57.z.string(), import_lazy_zod57.z.number()]).optional(),
|
|
21997
22031
|
// JSON-RPC request ID (for elicitation routing)
|
|
@@ -22819,7 +22853,7 @@ ${JSON.stringify(error.schema, null, 2)}
|
|
|
22819
22853
|
}
|
|
22820
22854
|
async finalize() {
|
|
22821
22855
|
this.logger.verbose("finalize:start");
|
|
22822
|
-
const { tool, rawOutput, uiResult, uiMeta } = this.state;
|
|
22856
|
+
const { tool, rawOutput, uiResult, uiMeta, resultMeta } = this.state;
|
|
22823
22857
|
if (!tool) {
|
|
22824
22858
|
this.logger.verbose("finalize: skipping (no tool in state)");
|
|
22825
22859
|
return;
|
|
@@ -22862,6 +22896,9 @@ ${JSON.stringify(error.schema, null, 2)}
|
|
|
22862
22896
|
if (rawMeta) {
|
|
22863
22897
|
result._meta = { ...result._meta, ...rawMeta };
|
|
22864
22898
|
}
|
|
22899
|
+
if (resultMeta) {
|
|
22900
|
+
result._meta = { ...result._meta, ...resultMeta };
|
|
22901
|
+
}
|
|
22865
22902
|
if (uiResult) {
|
|
22866
22903
|
result.content = uiResult.content;
|
|
22867
22904
|
if (uiResult.structuredContent !== void 0 && uiResult.structuredContent !== null) {
|
|
@@ -25407,6 +25444,56 @@ var init_dynamic_utils = __esm({
|
|
|
25407
25444
|
}
|
|
25408
25445
|
});
|
|
25409
25446
|
|
|
25447
|
+
// libs/sdk/src/common/dynamic/dynamic.plugin.ts
|
|
25448
|
+
function isDynamicPluginClass(value) {
|
|
25449
|
+
return typeof value === "function" && value.prototype instanceof DynamicPlugin;
|
|
25450
|
+
}
|
|
25451
|
+
function initOptionsOf(instance) {
|
|
25452
|
+
return initOptionsByInstance.has(instance) ? { options: initOptionsByInstance.get(instance) } : void 0;
|
|
25453
|
+
}
|
|
25454
|
+
var initOptionsByInstance, DynamicPlugin;
|
|
25455
|
+
var init_dynamic_plugin = __esm({
|
|
25456
|
+
"libs/sdk/src/common/dynamic/dynamic.plugin.ts"() {
|
|
25457
|
+
"use strict";
|
|
25458
|
+
init_transport_errors();
|
|
25459
|
+
init_dynamic_utils();
|
|
25460
|
+
initOptionsByInstance = /* @__PURE__ */ new WeakMap();
|
|
25461
|
+
DynamicPlugin = class {
|
|
25462
|
+
get(token) {
|
|
25463
|
+
throw new MethodNotImplementedError("DynamicPlugin", "get");
|
|
25464
|
+
}
|
|
25465
|
+
/**
|
|
25466
|
+
* Static init() method to create a plugin provider.
|
|
25467
|
+
* @param options - Input options (with optional fields for defaults). Omitted, the plugin is
|
|
25468
|
+
* built with `{}`, as `ApprovalPlugin.init()` is documented.
|
|
25469
|
+
*/
|
|
25470
|
+
static init(options = {}) {
|
|
25471
|
+
const extraProviders = options.providers;
|
|
25472
|
+
const typedOptions = options;
|
|
25473
|
+
if ("useFactory" in options) {
|
|
25474
|
+
return {
|
|
25475
|
+
...typedOptions,
|
|
25476
|
+
provide: this,
|
|
25477
|
+
inject: options.inject,
|
|
25478
|
+
useFactory: options.useFactory,
|
|
25479
|
+
providers: dedupePluginProviders(extraProviders ?? [])
|
|
25480
|
+
};
|
|
25481
|
+
}
|
|
25482
|
+
const dyn = collectDynamicProviders(this, typedOptions);
|
|
25483
|
+
const mergedProviders = dedupePluginProviders([...dyn ?? [], ...extraProviders ?? []]);
|
|
25484
|
+
const instance = new this(options);
|
|
25485
|
+
initOptionsByInstance.set(instance, options);
|
|
25486
|
+
return {
|
|
25487
|
+
...typedOptions,
|
|
25488
|
+
provide: this,
|
|
25489
|
+
useValue: instance,
|
|
25490
|
+
providers: mergedProviders
|
|
25491
|
+
};
|
|
25492
|
+
}
|
|
25493
|
+
};
|
|
25494
|
+
}
|
|
25495
|
+
});
|
|
25496
|
+
|
|
25410
25497
|
// libs/sdk/src/common/interfaces/internal/flow.utils.ts
|
|
25411
25498
|
var FlowState;
|
|
25412
25499
|
var init_flow_utils2 = __esm({
|
|
@@ -28895,7 +28982,7 @@ var init_plugin_utils = __esm({
|
|
|
28895
28982
|
});
|
|
28896
28983
|
|
|
28897
28984
|
// libs/sdk/src/plugin/plugin.registry.ts
|
|
28898
|
-
var import_reflect_metadata12, import_di24, PluginRegistry;
|
|
28985
|
+
var import_reflect_metadata12, import_di24, installedPluginValues, PluginRegistry;
|
|
28899
28986
|
var init_plugin_registry = __esm({
|
|
28900
28987
|
"libs/sdk/src/plugin/plugin.registry.ts"() {
|
|
28901
28988
|
"use strict";
|
|
@@ -28903,6 +28990,7 @@ var init_plugin_registry = __esm({
|
|
|
28903
28990
|
import_di24 = require("@frontmcp/di");
|
|
28904
28991
|
init_adapter_registry();
|
|
28905
28992
|
init_common();
|
|
28993
|
+
init_dynamic_plugin();
|
|
28906
28994
|
init_dynamic_utils();
|
|
28907
28995
|
init_context_extension();
|
|
28908
28996
|
init_errors();
|
|
@@ -28915,6 +29003,7 @@ var init_plugin_registry = __esm({
|
|
|
28915
29003
|
init_skill_registry();
|
|
28916
29004
|
init_tool_registry();
|
|
28917
29005
|
init_plugin_utils();
|
|
29006
|
+
installedPluginValues = /* @__PURE__ */ new WeakSet();
|
|
28918
29007
|
PluginRegistry = class _PluginRegistry extends RegistryAbstract {
|
|
28919
29008
|
/** providers by token */
|
|
28920
29009
|
pProviders = /* @__PURE__ */ new Map();
|
|
@@ -29103,8 +29192,15 @@ var init_plugin_registry = __esm({
|
|
|
29103
29192
|
pluginInstance: new rec.provide(...depsInstances),
|
|
29104
29193
|
dynamicProviders: rec.providers
|
|
29105
29194
|
};
|
|
29106
|
-
case "VALUE" /* VALUE */:
|
|
29107
|
-
|
|
29195
|
+
case "VALUE" /* VALUE */: {
|
|
29196
|
+
const value = rec.useValue;
|
|
29197
|
+
const init = installedPluginValues.has(value) ? initOptionsOf(value) : void 0;
|
|
29198
|
+
installedPluginValues.add(value);
|
|
29199
|
+
if (init && isDynamicPluginClass(rec.provide)) {
|
|
29200
|
+
return { pluginInstance: new rec.provide(init.options), dynamicProviders: rec.providers };
|
|
29201
|
+
}
|
|
29202
|
+
return { pluginInstance: value, dynamicProviders: rec.providers };
|
|
29203
|
+
}
|
|
29108
29204
|
case "FACTORY" /* FACTORY */: {
|
|
29109
29205
|
const args = [];
|
|
29110
29206
|
for (const d of rec.inject()) args.push(await this.providers.resolveBootstrapDep(d));
|
|
@@ -31641,12 +31737,36 @@ var init_request_validation = __esm({
|
|
|
31641
31737
|
});
|
|
31642
31738
|
|
|
31643
31739
|
// libs/sdk/src/transport/mcp-20260728/request-state.ts
|
|
31644
|
-
function
|
|
31740
|
+
function configuredSecret(name44) {
|
|
31741
|
+
const value = (0, import_utils65.getEnv)(name44);
|
|
31742
|
+
return value && value.trim().length > 0 ? value : void 0;
|
|
31743
|
+
}
|
|
31744
|
+
function resolveKey() {
|
|
31645
31745
|
if (cachedKey) return cachedKey;
|
|
31646
|
-
const
|
|
31647
|
-
|
|
31746
|
+
const vault = configuredSecret("VAULT_SECRET");
|
|
31747
|
+
const jwt = vault ? void 0 : configuredSecret("JWT_SECRET");
|
|
31748
|
+
if (vault) cachedKey = { key: encoder.encode(vault), source: "VAULT_SECRET" };
|
|
31749
|
+
else if (jwt) cachedKey = { key: encoder.encode(jwt), source: "JWT_SECRET" };
|
|
31750
|
+
else cachedKey = { key: (0, import_utils65.randomBytes)(32), source: "per-process" };
|
|
31648
31751
|
return cachedKey;
|
|
31649
31752
|
}
|
|
31753
|
+
function getRequestStateKey() {
|
|
31754
|
+
return resolveKey().key;
|
|
31755
|
+
}
|
|
31756
|
+
function getRequestStateKeySource() {
|
|
31757
|
+
return resolveKey().source;
|
|
31758
|
+
}
|
|
31759
|
+
function warnIfRequestStateKeyNotShared(options) {
|
|
31760
|
+
if (warnedKeyNotShared || !(0, import_utils65.isProduction)()) return;
|
|
31761
|
+
const { metadata } = options;
|
|
31762
|
+
const persistence = metadata.transport?.persistence;
|
|
31763
|
+
const sharesState = Boolean(metadata.redis) || typeof persistence === "object" && persistence !== null;
|
|
31764
|
+
if (!sharesState || getRequestStateKeySource() !== "per-process") return;
|
|
31765
|
+
warnedKeyNotShared = true;
|
|
31766
|
+
options.logger.warn(
|
|
31767
|
+
"requestState is signed with a per-process key (neither VAULT_SECRET nor JWT_SECRET is set). Multi-round tools (elicit/sample) restart when a round lands on another instance; set VAULT_SECRET (or JWT_SECRET) to the same value on every instance."
|
|
31768
|
+
);
|
|
31769
|
+
}
|
|
31650
31770
|
function computeRequestBinding(method, params) {
|
|
31651
31771
|
const salient = {};
|
|
31652
31772
|
for (const key of ["name", "uri", "arguments"]) {
|
|
@@ -31696,13 +31816,14 @@ function decodeRequestState(state, expected) {
|
|
|
31696
31816
|
if (payload.b !== expected.binding) return { ok: false, reason: "request-mismatch" };
|
|
31697
31817
|
return { ok: true, responses: payload.r };
|
|
31698
31818
|
}
|
|
31699
|
-
var import_utils65, DEFAULT_REQUEST_STATE_TTL_MS, MAX_REQUEST_STATE_BYTES, cachedKey, encoder, decoder;
|
|
31819
|
+
var import_utils65, DEFAULT_REQUEST_STATE_TTL_MS, MAX_REQUEST_STATE_BYTES, cachedKey, warnedKeyNotShared, encoder, decoder;
|
|
31700
31820
|
var init_request_state = __esm({
|
|
31701
31821
|
"libs/sdk/src/transport/mcp-20260728/request-state.ts"() {
|
|
31702
31822
|
"use strict";
|
|
31703
31823
|
import_utils65 = require("@frontmcp/utils");
|
|
31704
31824
|
DEFAULT_REQUEST_STATE_TTL_MS = 10 * 60 * 1e3;
|
|
31705
31825
|
MAX_REQUEST_STATE_BYTES = 256 * 1024;
|
|
31826
|
+
warnedKeyNotShared = false;
|
|
31706
31827
|
encoder = new TextEncoder();
|
|
31707
31828
|
decoder = new TextDecoder();
|
|
31708
31829
|
}
|
|
@@ -32423,7 +32544,8 @@ async function dispatch20260728(options) {
|
|
|
32423
32544
|
};
|
|
32424
32545
|
const carried = decodeRequestState(params["requestState"], binding);
|
|
32425
32546
|
if (!carried.ok && carried.reason !== "absent") {
|
|
32426
|
-
|
|
32547
|
+
const hint = carried.reason === "bad-signature" && getRequestStateKeySource() === "per-process" ? "requestState is signed with a per-process key; set VAULT_SECRET (or JWT_SECRET) to the same value on every instance so a round can land on any of them" : void 0;
|
|
32548
|
+
scope.logger.warn("mcp-20260728: rejected requestState", { method, reason: carried.reason, ...hint && { hint } });
|
|
32427
32549
|
}
|
|
32428
32550
|
const exchange = new MrtrExchange({
|
|
32429
32551
|
inputResponses: params["inputResponses"],
|
|
@@ -32580,6 +32702,7 @@ var init_mcp_stateless_client = __esm({
|
|
|
32580
32702
|
"libs/sdk/src/transport/mcp-20260728/client/mcp-stateless.client.ts"() {
|
|
32581
32703
|
"use strict";
|
|
32582
32704
|
import_protocol47 = require("@frontmcp/protocol");
|
|
32705
|
+
init_list_all_pages_utils();
|
|
32583
32706
|
init_header_codec();
|
|
32584
32707
|
init_protocol_20260728_constants();
|
|
32585
32708
|
init_tasks_extension();
|
|
@@ -32620,10 +32743,22 @@ var init_mcp_stateless_client = __esm({
|
|
|
32620
32743
|
* The spec requires this: one malformed tool definition must not prevent the
|
|
32621
32744
|
* other tools from being used, so the offender is excluded and logged rather
|
|
32622
32745
|
* than failing the call.
|
|
32746
|
+
*
|
|
32747
|
+
* Every page is fetched (`nextCursor` is followed to the end), since the
|
|
32748
|
+
* schemas cached here are what later `tools/call` headers are derived from.
|
|
32623
32749
|
*/
|
|
32624
32750
|
async listTools() {
|
|
32625
|
-
const
|
|
32626
|
-
|
|
32751
|
+
const tools = await listAllPages(
|
|
32752
|
+
"tools/list",
|
|
32753
|
+
async (cursor) => {
|
|
32754
|
+
const result = await this.request("tools/list", cursor ? { cursor } : {});
|
|
32755
|
+
return {
|
|
32756
|
+
items: Array.isArray(result["tools"]) ? result["tools"] : [],
|
|
32757
|
+
nextCursor: typeof result["nextCursor"] === "string" ? result["nextCursor"] : void 0
|
|
32758
|
+
};
|
|
32759
|
+
},
|
|
32760
|
+
(message) => new McpStatelessError(-32603, message)
|
|
32761
|
+
);
|
|
32627
32762
|
const usable = [];
|
|
32628
32763
|
for (const tool of tools) {
|
|
32629
32764
|
const validation = validateHeaderParams(tool["inputSchema"]);
|
|
@@ -32642,11 +32777,13 @@ var init_mcp_stateless_client = __esm({
|
|
|
32642
32777
|
async readResource(uri) {
|
|
32643
32778
|
return this.request("resources/read", { uri });
|
|
32644
32779
|
}
|
|
32645
|
-
|
|
32646
|
-
|
|
32780
|
+
/** One page of `resources/list`; pass the previous page's `nextCursor` for the next. */
|
|
32781
|
+
async listResources(cursor) {
|
|
32782
|
+
return this.request("resources/list", cursor ? { cursor } : {});
|
|
32647
32783
|
}
|
|
32648
|
-
|
|
32649
|
-
|
|
32784
|
+
/** One page of `prompts/list`; pass the previous page's `nextCursor` for the next. */
|
|
32785
|
+
async listPrompts(cursor) {
|
|
32786
|
+
return this.request("prompts/list", cursor ? { cursor } : {});
|
|
32650
32787
|
}
|
|
32651
32788
|
async getPrompt(name44, args = {}) {
|
|
32652
32789
|
return this.request("prompts/get", { name: name44, arguments: args });
|
|
@@ -32932,6 +33069,10 @@ var init_mcp_20260728 = __esm({
|
|
|
32932
33069
|
});
|
|
32933
33070
|
|
|
32934
33071
|
// libs/sdk/src/remote-mcp/mcp-stateless-client.adapter.ts
|
|
33072
|
+
function nextCursorOf(result) {
|
|
33073
|
+
const next = result["nextCursor"];
|
|
33074
|
+
return typeof next === "string" && next.length > 0 ? { nextCursor: next } : {};
|
|
33075
|
+
}
|
|
32935
33076
|
async function negotiateRemoteProtocol(url, configured, headers, fetchImpl = fetch) {
|
|
32936
33077
|
if (configured === "2026-07-28") return "2026-07-28";
|
|
32937
33078
|
if (configured !== "auto") return "legacy";
|
|
@@ -32974,16 +33115,22 @@ var init_mcp_stateless_client_adapter = __esm({
|
|
|
32974
33115
|
async callTool(params) {
|
|
32975
33116
|
return this.client.callTool(params.name, params.arguments ?? {});
|
|
32976
33117
|
}
|
|
32977
|
-
async listResources() {
|
|
32978
|
-
const result = await this.client.listResources();
|
|
32979
|
-
return {
|
|
33118
|
+
async listResources(params) {
|
|
33119
|
+
const result = await this.client.listResources(params?.cursor);
|
|
33120
|
+
return {
|
|
33121
|
+
resources: Array.isArray(result["resources"]) ? result["resources"] : [],
|
|
33122
|
+
...nextCursorOf(result)
|
|
33123
|
+
};
|
|
32980
33124
|
}
|
|
32981
33125
|
async readResource(params) {
|
|
32982
33126
|
return this.client.readResource(params.uri);
|
|
32983
33127
|
}
|
|
32984
|
-
async listPrompts() {
|
|
32985
|
-
const result = await this.client.listPrompts();
|
|
32986
|
-
return {
|
|
33128
|
+
async listPrompts(params) {
|
|
33129
|
+
const result = await this.client.listPrompts(params?.cursor);
|
|
33130
|
+
return {
|
|
33131
|
+
prompts: Array.isArray(result["prompts"]) ? result["prompts"] : [],
|
|
33132
|
+
...nextCursorOf(result)
|
|
33133
|
+
};
|
|
32987
33134
|
}
|
|
32988
33135
|
async getPrompt(params) {
|
|
32989
33136
|
return this.client.getPrompt(params.name, params.arguments ?? {});
|
|
@@ -33506,6 +33653,7 @@ var init_mcp_client_service = __esm({
|
|
|
33506
33653
|
"libs/sdk/src/remote-mcp/mcp-client.service.ts"() {
|
|
33507
33654
|
"use strict";
|
|
33508
33655
|
import_protocol48 = require("@frontmcp/protocol");
|
|
33656
|
+
init_list_all_pages_utils();
|
|
33509
33657
|
init_mcp_error();
|
|
33510
33658
|
init_remote_errors();
|
|
33511
33659
|
init_transport_errors();
|
|
@@ -34109,10 +34257,15 @@ var init_mcp_client_service = __esm({
|
|
|
34109
34257
|
const httpOptions = request.transportOptions;
|
|
34110
34258
|
return httpOptions?.fallbackToSSE ?? true;
|
|
34111
34259
|
}
|
|
34260
|
+
// Each list follows `nextCursor` to the end: a FrontMCP remote pages its lists
|
|
34261
|
+
// (40 per page by default), and proxying only the first page silently dropped
|
|
34262
|
+
// everything after it.
|
|
34112
34263
|
async listToolsInternal(connection) {
|
|
34113
34264
|
try {
|
|
34114
|
-
|
|
34115
|
-
|
|
34265
|
+
return await listAllPages("tools/list", async (cursor) => {
|
|
34266
|
+
const result = await connection.client.listTools(cursor ? { cursor } : void 0);
|
|
34267
|
+
return { items: result.tools, nextCursor: result.nextCursor };
|
|
34268
|
+
});
|
|
34116
34269
|
} catch (error) {
|
|
34117
34270
|
this.logger.warn(`Failed to list tools: ${error.message}`);
|
|
34118
34271
|
return [];
|
|
@@ -34120,8 +34273,10 @@ var init_mcp_client_service = __esm({
|
|
|
34120
34273
|
}
|
|
34121
34274
|
async listResourcesInternal(connection) {
|
|
34122
34275
|
try {
|
|
34123
|
-
|
|
34124
|
-
|
|
34276
|
+
return await listAllPages("resources/list", async (cursor) => {
|
|
34277
|
+
const result = await connection.client.listResources(cursor ? { cursor } : void 0);
|
|
34278
|
+
return { items: result.resources, nextCursor: result.nextCursor };
|
|
34279
|
+
});
|
|
34125
34280
|
} catch (error) {
|
|
34126
34281
|
this.logger.warn(`Failed to list resources: ${error.message}`);
|
|
34127
34282
|
return [];
|
|
@@ -34129,8 +34284,10 @@ var init_mcp_client_service = __esm({
|
|
|
34129
34284
|
}
|
|
34130
34285
|
async listResourceTemplatesInternal(connection) {
|
|
34131
34286
|
try {
|
|
34132
|
-
|
|
34133
|
-
|
|
34287
|
+
return await listAllPages("resources/templates/list", async (cursor) => {
|
|
34288
|
+
const result = await connection.client.listResourceTemplates(cursor ? { cursor } : void 0);
|
|
34289
|
+
return { items: result.resourceTemplates, nextCursor: result.nextCursor };
|
|
34290
|
+
});
|
|
34134
34291
|
} catch (error) {
|
|
34135
34292
|
this.logger.warn(`Failed to list resource templates: ${error.message}`);
|
|
34136
34293
|
return [];
|
|
@@ -34138,8 +34295,10 @@ var init_mcp_client_service = __esm({
|
|
|
34138
34295
|
}
|
|
34139
34296
|
async listPromptsInternal(connection) {
|
|
34140
34297
|
try {
|
|
34141
|
-
|
|
34142
|
-
|
|
34298
|
+
return await listAllPages("prompts/list", async (cursor) => {
|
|
34299
|
+
const result = await connection.client.listPrompts(cursor ? { cursor } : void 0);
|
|
34300
|
+
return { items: result.prompts, nextCursor: result.nextCursor };
|
|
34301
|
+
});
|
|
34143
34302
|
} catch (error) {
|
|
34144
34303
|
this.logger.warn(`Failed to list prompts: ${error.message}`);
|
|
34145
34304
|
return [];
|
|
@@ -41592,8 +41751,11 @@ var init_session_verify_flow = __esm({
|
|
|
41592
41751
|
const machineId = (0, import_utils78.getMachineId)();
|
|
41593
41752
|
const authSignature = subject ? `${authMode}:${subject}` : authMode;
|
|
41594
41753
|
if (sessionIdHeader) {
|
|
41595
|
-
const
|
|
41596
|
-
|
|
41754
|
+
const body = this.rawInput.request.body;
|
|
41755
|
+
const isInitialize2 = typeof body === "object" && body !== null && "method" in body && body.method === "initialize";
|
|
41756
|
+
const decrypted = decryptPublicSession(sessionIdHeader, authSignature);
|
|
41757
|
+
const existingPayload = decrypted && isInitialize2 && decrypted.nodeId !== machineId ? void 0 : decrypted;
|
|
41758
|
+
if (existingPayload) {
|
|
41597
41759
|
const anonId = existingPayload.uuid ?? `${existingPayload.iat * 1e3}`;
|
|
41598
41760
|
const user2 = (0, import_auth39.anonymousCallerClaims)(options, anonId);
|
|
41599
41761
|
this.respond({
|
|
@@ -56899,6 +57061,30 @@ function getQuerySessionId2(urlPath) {
|
|
|
56899
57061
|
return void 0;
|
|
56900
57062
|
}
|
|
56901
57063
|
}
|
|
57064
|
+
function resolveLegacySseSession(params) {
|
|
57065
|
+
const { rawHeader, requestUrl, authorizationSession, createSession } = params;
|
|
57066
|
+
const rawMcpSessionHeader = typeof rawHeader === "string" ? rawHeader : void 0;
|
|
57067
|
+
const mcpSessionHeader = validateMcpSessionHeader(rawMcpSessionHeader);
|
|
57068
|
+
const querySessionId = getQuerySessionId2(requestUrl);
|
|
57069
|
+
const validatedQuerySessionId = querySessionId ? validateMcpSessionHeader(querySessionId) : void 0;
|
|
57070
|
+
if (rawHeader !== void 0 && !mcpSessionHeader) {
|
|
57071
|
+
return { responded404: true, createdNew: false };
|
|
57072
|
+
}
|
|
57073
|
+
if (querySessionId !== void 0 && !validatedQuerySessionId) {
|
|
57074
|
+
return { responded404: true, createdNew: false };
|
|
57075
|
+
}
|
|
57076
|
+
const effectiveSessionId = mcpSessionHeader ?? validatedQuerySessionId;
|
|
57077
|
+
if (effectiveSessionId) {
|
|
57078
|
+
if (authorizationSession?.id === effectiveSessionId) {
|
|
57079
|
+
return { session: authorizationSession, createdNew: false, responded404: false };
|
|
57080
|
+
}
|
|
57081
|
+
return { responded404: true, createdNew: false };
|
|
57082
|
+
}
|
|
57083
|
+
if (authorizationSession) {
|
|
57084
|
+
return { session: authorizationSession, createdNew: false, responded404: false };
|
|
57085
|
+
}
|
|
57086
|
+
return { session: createSession(), createdNew: true, responded404: false };
|
|
57087
|
+
}
|
|
56902
57088
|
var import_lazy_zod103, import_utils96, plan38, stateSessionSchema, stateSchema38, name39, Stage39, HandleSseFlow;
|
|
56903
57089
|
var init_handle_sse_flow = __esm({
|
|
56904
57090
|
"libs/sdk/src/transport/flows/handle.sse.flow.ts"() {
|
|
@@ -56940,39 +57126,26 @@ var init_handle_sse_flow = __esm({
|
|
|
56940
57126
|
const { request } = this.rawInput;
|
|
56941
57127
|
const authorization = request[ServerRequestTokens.auth];
|
|
56942
57128
|
const { token } = authorization;
|
|
56943
|
-
const raw = request.headers?.["mcp-session-id"];
|
|
56944
|
-
const rawMcpSessionHeader = typeof raw === "string" ? raw : void 0;
|
|
56945
|
-
const mcpSessionHeader = validateMcpSessionHeader(rawMcpSessionHeader);
|
|
56946
57129
|
const anyReq = request;
|
|
56947
|
-
const
|
|
56948
|
-
|
|
56949
|
-
|
|
56950
|
-
|
|
56951
|
-
|
|
56952
|
-
|
|
56953
|
-
|
|
57130
|
+
const resolution = resolveLegacySseSession({
|
|
57131
|
+
rawHeader: request.headers?.["mcp-session-id"],
|
|
57132
|
+
requestUrl: anyReq.url ?? anyReq.path,
|
|
57133
|
+
authorizationSession: authorization.session,
|
|
57134
|
+
createSession: () => {
|
|
57135
|
+
const query = request.query;
|
|
57136
|
+
const skillsOnlyMode = detectSkillsOnlyMode(query);
|
|
57137
|
+
return createSessionId("legacy-sse", token, {
|
|
57138
|
+
userAgent: request.headers?.["user-agent"],
|
|
57139
|
+
platformDetectionConfig: this.scope.metadata.transport?.platformDetection,
|
|
57140
|
+
skillsOnlyMode
|
|
57141
|
+
});
|
|
57142
|
+
}
|
|
57143
|
+
});
|
|
57144
|
+
if (resolution.responded404 || !resolution.session) {
|
|
56954
57145
|
this.respond(httpRespond.sessionNotFound("invalid session id"));
|
|
56955
57146
|
return;
|
|
56956
57147
|
}
|
|
56957
|
-
const
|
|
56958
|
-
let session;
|
|
56959
|
-
if (effectiveSessionId) {
|
|
56960
|
-
if (authorization.session?.id === effectiveSessionId) {
|
|
56961
|
-
session = authorization.session;
|
|
56962
|
-
} else {
|
|
56963
|
-
session = { id: effectiveSessionId };
|
|
56964
|
-
}
|
|
56965
|
-
} else if (authorization.session) {
|
|
56966
|
-
session = authorization.session;
|
|
56967
|
-
} else {
|
|
56968
|
-
const query = request.query;
|
|
56969
|
-
const skillsOnlyMode = detectSkillsOnlyMode(query);
|
|
56970
|
-
session = createSessionId("legacy-sse", token, {
|
|
56971
|
-
userAgent: request.headers?.["user-agent"],
|
|
56972
|
-
platformDetectionConfig: this.scope.metadata.transport?.platformDetection,
|
|
56973
|
-
skillsOnlyMode
|
|
56974
|
-
});
|
|
56975
|
-
}
|
|
57148
|
+
const session = resolution.session;
|
|
56976
57149
|
this.state.set(stateSchema38.parse({ token, session }));
|
|
56977
57150
|
}
|
|
56978
57151
|
async router() {
|
|
@@ -57585,7 +57758,7 @@ function resolveStreamableHttpSession(params) {
|
|
|
57585
57758
|
if (authorizationSession?.id === mcpSessionHeader) {
|
|
57586
57759
|
return { session: authorizationSession, createdNew: false, responded404: false };
|
|
57587
57760
|
}
|
|
57588
|
-
return {
|
|
57761
|
+
return { responded404: true, createdNew: false };
|
|
57589
57762
|
}
|
|
57590
57763
|
if (authorizationSession) {
|
|
57591
57764
|
return { session: authorizationSession, createdNew: false, responded404: false };
|
|
@@ -57733,7 +57906,7 @@ var init_handle_streamable_http_flow = __esm({
|
|
|
57733
57906
|
});
|
|
57734
57907
|
}
|
|
57735
57908
|
if (sessionResolution.responded404 || !sessionResolution.session) {
|
|
57736
|
-
logger.warn("parseInput:
|
|
57909
|
+
logger.warn("parseInput: mcp-session-id is not a session this server verified");
|
|
57737
57910
|
this.respond(httpRespond.sessionNotFound("invalid session id"));
|
|
57738
57911
|
return;
|
|
57739
57912
|
}
|
|
@@ -61293,6 +61466,7 @@ var init_scope_instance = __esm({
|
|
|
61293
61466
|
init_ui();
|
|
61294
61467
|
init_bus();
|
|
61295
61468
|
init_event_stores();
|
|
61469
|
+
init_request_state();
|
|
61296
61470
|
init_transport_registry();
|
|
61297
61471
|
init_http_ip_filter_flow();
|
|
61298
61472
|
init_http_request_flow();
|
|
@@ -61421,6 +61595,7 @@ var init_scope_instance = __esm({
|
|
|
61421
61595
|
effectivePersistence = { sqlite: resolvedTopLevelSqlite };
|
|
61422
61596
|
}
|
|
61423
61597
|
this.transportService = new TransportService(this, effectivePersistence, transportBus);
|
|
61598
|
+
warnIfRequestStateKeyNotShared({ logger: this.logger, metadata: this.metadata });
|
|
61424
61599
|
if (this.haManager && isDistributed) {
|
|
61425
61600
|
const persistCfg = transportConfig?.persistence;
|
|
61426
61601
|
const resolvedPrefix = persistCfg && typeof persistCfg === "object" && persistCfg.redis?.keyPrefix ? persistCfg.redis.keyPrefix : "mcp:transport:";
|
|
@@ -64135,9 +64310,9 @@ var init_noop_server = __esm({
|
|
|
64135
64310
|
});
|
|
64136
64311
|
|
|
64137
64312
|
// libs/sdk/src/server/security/security-audit.ts
|
|
64138
|
-
function auditSecurityDefaults(config,
|
|
64313
|
+
function auditSecurityDefaults(config, isProduction7) {
|
|
64139
64314
|
const findings = [];
|
|
64140
|
-
if (!
|
|
64315
|
+
if (!isProduction7 && config.deploymentMode !== "distributed") {
|
|
64141
64316
|
return findings;
|
|
64142
64317
|
}
|
|
64143
64318
|
const strict = config.security?.strict === true;
|
|
@@ -64693,7 +64868,7 @@ var init_server_instance = __esm({
|
|
|
64693
64868
|
this.prepare();
|
|
64694
64869
|
const deploymentMode = (0, import_utils108.getRuntimeContext)().deployment;
|
|
64695
64870
|
const bindAddress = resolveBindAddress(this.config.security, deploymentMode);
|
|
64696
|
-
const
|
|
64871
|
+
const isProduction7 = process.env["NODE_ENV"] === "production";
|
|
64697
64872
|
const findings = auditSecurityDefaults(
|
|
64698
64873
|
{
|
|
64699
64874
|
cors: this.config.cors,
|
|
@@ -64701,7 +64876,7 @@ var init_server_instance = __esm({
|
|
|
64701
64876
|
resolvedBindAddress: bindAddress,
|
|
64702
64877
|
deploymentMode
|
|
64703
64878
|
},
|
|
64704
|
-
|
|
64879
|
+
isProduction7
|
|
64705
64880
|
);
|
|
64706
64881
|
logSecurityFindings(findings, console);
|
|
64707
64882
|
await this.host.start(this.config.socketPath ?? this.config.port, bindAddress);
|
|
@@ -66546,49 +66721,6 @@ var init_dynamic_adapter = __esm({
|
|
|
66546
66721
|
}
|
|
66547
66722
|
});
|
|
66548
66723
|
|
|
66549
|
-
// libs/sdk/src/common/dynamic/dynamic.plugin.ts
|
|
66550
|
-
function isDynamicPluginClass(value) {
|
|
66551
|
-
return typeof value === "function" && value.prototype instanceof DynamicPlugin;
|
|
66552
|
-
}
|
|
66553
|
-
var DynamicPlugin;
|
|
66554
|
-
var init_dynamic_plugin = __esm({
|
|
66555
|
-
"libs/sdk/src/common/dynamic/dynamic.plugin.ts"() {
|
|
66556
|
-
"use strict";
|
|
66557
|
-
init_transport_errors();
|
|
66558
|
-
init_dynamic_utils();
|
|
66559
|
-
DynamicPlugin = class {
|
|
66560
|
-
get(token) {
|
|
66561
|
-
throw new MethodNotImplementedError("DynamicPlugin", "get");
|
|
66562
|
-
}
|
|
66563
|
-
/**
|
|
66564
|
-
* Static init() method to create a plugin provider.
|
|
66565
|
-
* @param options - Input options (with optional fields for defaults)
|
|
66566
|
-
*/
|
|
66567
|
-
static init(options) {
|
|
66568
|
-
const extraProviders = options.providers;
|
|
66569
|
-
const typedOptions = options;
|
|
66570
|
-
if ("useFactory" in options) {
|
|
66571
|
-
return {
|
|
66572
|
-
...typedOptions,
|
|
66573
|
-
provide: this,
|
|
66574
|
-
inject: options.inject,
|
|
66575
|
-
useFactory: options.useFactory,
|
|
66576
|
-
providers: dedupePluginProviders(extraProviders ?? [])
|
|
66577
|
-
};
|
|
66578
|
-
}
|
|
66579
|
-
const dyn = collectDynamicProviders(this, typedOptions);
|
|
66580
|
-
const mergedProviders = dedupePluginProviders([...dyn ?? [], ...extraProviders ?? []]);
|
|
66581
|
-
return {
|
|
66582
|
-
...typedOptions,
|
|
66583
|
-
provide: this,
|
|
66584
|
-
useValue: new this(options),
|
|
66585
|
-
providers: mergedProviders
|
|
66586
|
-
};
|
|
66587
|
-
}
|
|
66588
|
-
};
|
|
66589
|
-
}
|
|
66590
|
-
});
|
|
66591
|
-
|
|
66592
66724
|
// libs/sdk/src/common/dynamic/index.ts
|
|
66593
66725
|
var init_dynamic = __esm({
|
|
66594
66726
|
"libs/sdk/src/common/dynamic/index.ts"() {
|
|
@@ -68188,6 +68320,7 @@ __export(index_exports, {
|
|
|
68188
68320
|
httpRequestInputSchema: () => httpRequestInputSchema,
|
|
68189
68321
|
httpRespond: () => httpRespond,
|
|
68190
68322
|
incrementalAuthConfigSchema: () => import_auth5.incrementalAuthConfigSchema,
|
|
68323
|
+
initOptionsOf: () => initOptionsOf,
|
|
68191
68324
|
intentSchema: () => intentSchema,
|
|
68192
68325
|
isAlive: () => isAlive,
|
|
68193
68326
|
isAnonymousSubject: () => import_auth61.isAnonymousSubject,
|
|
@@ -69430,6 +69563,7 @@ var ChannelListHook = FlowHooksOf("channels:list");
|
|
|
69430
69563
|
httpRequestInputSchema,
|
|
69431
69564
|
httpRespond,
|
|
69432
69565
|
incrementalAuthConfigSchema,
|
|
69566
|
+
initOptionsOf,
|
|
69433
69567
|
intentSchema,
|
|
69434
69568
|
isAlive,
|
|
69435
69569
|
isAnonymousSubject,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/sdk",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.6",
|
|
4
4
|
"description": "FrontMCP SDK",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -90,8 +90,8 @@
|
|
|
90
90
|
"peerDependencies": {
|
|
91
91
|
"@anthropic-ai/sdk": "^0.30.0 || ^0.78.0",
|
|
92
92
|
"@enclave-vm/core": "^2.15.3",
|
|
93
|
-
"@frontmcp/observability": "1.8.
|
|
94
|
-
"@frontmcp/storage-sqlite": "1.8.
|
|
93
|
+
"@frontmcp/observability": "1.8.6",
|
|
94
|
+
"@frontmcp/storage-sqlite": "1.8.6",
|
|
95
95
|
"@opentelemetry/api": "^1.9.0",
|
|
96
96
|
"@opentelemetry/sdk-trace-base": "^2.8.0",
|
|
97
97
|
"@vercel/kv": "^3.0.0",
|
|
@@ -132,13 +132,13 @@
|
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
134
|
"dependencies": {
|
|
135
|
-
"@frontmcp/auth": "1.8.
|
|
136
|
-
"@frontmcp/di": "1.8.
|
|
137
|
-
"@frontmcp/guard": "1.8.
|
|
138
|
-
"@frontmcp/lazy-zod": "1.8.
|
|
139
|
-
"@frontmcp/protocol": "1.8.
|
|
140
|
-
"@frontmcp/uipack": "1.8.
|
|
141
|
-
"@frontmcp/utils": "1.8.
|
|
135
|
+
"@frontmcp/auth": "1.8.6",
|
|
136
|
+
"@frontmcp/di": "1.8.6",
|
|
137
|
+
"@frontmcp/guard": "1.8.6",
|
|
138
|
+
"@frontmcp/lazy-zod": "1.8.6",
|
|
139
|
+
"@frontmcp/protocol": "1.8.6",
|
|
140
|
+
"@frontmcp/uipack": "1.8.6",
|
|
141
|
+
"@frontmcp/utils": "1.8.6",
|
|
142
142
|
"@types/cors": "^2.8.17",
|
|
143
143
|
"ioredis": "^5.8.0",
|
|
144
144
|
"jose": "^6.1.3",
|