@questpie/mcp 3.28.10 → 3.28.11
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/{create-server-DvumhdI_.mjs → create-server-5Eo4QP3q.mjs} +158 -5
- package/dist/index.mjs +3 -3
- package/dist/{mcp-uf7du4OS.mjs → mcp-i0Kqu_bB.mjs} +1 -1
- package/dist/modules/mcp.mjs +1 -1
- package/dist/{stdio-HmbmENQN.mjs → stdio-37bSPka9.mjs} +1 -1
- package/dist/stdio.mjs +1 -1
- package/package.json +3 -3
|
@@ -128,7 +128,7 @@ const DEFAULT_MCP_CONFIG = {
|
|
|
128
128
|
stdio: { trustedMaintenance: false },
|
|
129
129
|
execution: {}
|
|
130
130
|
};
|
|
131
|
-
function isPlainObject(value) {
|
|
131
|
+
function isPlainObject$1(value) {
|
|
132
132
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
133
133
|
}
|
|
134
134
|
const UNSAFE_CONFIG_KEYS = new Set([
|
|
@@ -137,7 +137,7 @@ const UNSAFE_CONFIG_KEYS = new Set([
|
|
|
137
137
|
"constructor"
|
|
138
138
|
]);
|
|
139
139
|
function ownDataEntries(value) {
|
|
140
|
-
if (!isPlainObject(value)) return [];
|
|
140
|
+
if (!isPlainObject$1(value)) return [];
|
|
141
141
|
try {
|
|
142
142
|
return Object.entries(Object.getOwnPropertyDescriptors(value)).filter(([key, descriptor]) => !UNSAFE_CONFIG_KEYS.has(key) && "value" in descriptor).map(([key, descriptor]) => [key, descriptor.value]);
|
|
143
143
|
} catch {
|
|
@@ -146,14 +146,14 @@ function ownDataEntries(value) {
|
|
|
146
146
|
}
|
|
147
147
|
function safeCloneConfigValue(value) {
|
|
148
148
|
if (Array.isArray(value)) return value.map((entry) => safeCloneConfigValue(entry));
|
|
149
|
-
if (!isPlainObject(value)) return value;
|
|
149
|
+
if (!isPlainObject$1(value)) return value;
|
|
150
150
|
const clone = Object.create(null);
|
|
151
151
|
for (const [key, entry] of ownDataEntries(value)) clone[key] = safeCloneConfigValue(entry);
|
|
152
152
|
return clone;
|
|
153
153
|
}
|
|
154
154
|
function mergeDeep(base, override) {
|
|
155
155
|
const out = safeCloneConfigValue(base);
|
|
156
|
-
for (const [key, value] of ownDataEntries(override)) if (isPlainObject(value) && isPlainObject(out[key])) out[key] = mergeDeep(out[key], value);
|
|
156
|
+
for (const [key, value] of ownDataEntries(override)) if (isPlainObject$1(value) && isPlainObject$1(out[key])) out[key] = mergeDeep(out[key], value);
|
|
157
157
|
else if (value !== void 0) out[key] = safeCloneConfigValue(value);
|
|
158
158
|
return out;
|
|
159
159
|
}
|
|
@@ -1073,11 +1073,123 @@ function toJsonSchema(schema) {
|
|
|
1073
1073
|
const compatible = jsonSchemaCompatibleSchema(schema);
|
|
1074
1074
|
if (!compatible) return void 0;
|
|
1075
1075
|
try {
|
|
1076
|
-
return z.toJSONSchema(compatible, { reused: "ref" });
|
|
1076
|
+
return applyMcpSchemaDiet(z.toJSONSchema(compatible, { reused: "ref" }));
|
|
1077
1077
|
} catch {
|
|
1078
1078
|
return;
|
|
1079
1079
|
}
|
|
1080
1080
|
}
|
|
1081
|
+
function isPlainObject(value) {
|
|
1082
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1083
|
+
}
|
|
1084
|
+
const SCHEMA_MAP_KEYS = [
|
|
1085
|
+
"properties",
|
|
1086
|
+
"patternProperties",
|
|
1087
|
+
"dependentSchemas",
|
|
1088
|
+
"$defs",
|
|
1089
|
+
"definitions"
|
|
1090
|
+
];
|
|
1091
|
+
const NEUTRAL_SCHEMA_LIST_KEYS = [
|
|
1092
|
+
"anyOf",
|
|
1093
|
+
"allOf",
|
|
1094
|
+
"prefixItems"
|
|
1095
|
+
];
|
|
1096
|
+
const NEUTRAL_SCHEMA_KEYS = [
|
|
1097
|
+
"items",
|
|
1098
|
+
"then",
|
|
1099
|
+
"else",
|
|
1100
|
+
"propertyNames",
|
|
1101
|
+
"contains"
|
|
1102
|
+
];
|
|
1103
|
+
const NEUTRAL_MAYBE_BOOLEAN_SCHEMA_KEYS = [
|
|
1104
|
+
"additionalProperties",
|
|
1105
|
+
"unevaluatedProperties",
|
|
1106
|
+
"unevaluatedItems",
|
|
1107
|
+
"additionalItems"
|
|
1108
|
+
];
|
|
1109
|
+
/**
|
|
1110
|
+
* Rewrites a draft-07-style tuple (`items: [...]` + `additionalItems`) into
|
|
1111
|
+
* its 2020-12 equivalent (`prefixItems: [...]` + trailing `items`) in place.
|
|
1112
|
+
*
|
|
1113
|
+
* The MCP SDK's own `tools/list` projection (`zod-json-schema-compat.js`,
|
|
1114
|
+
* called with no `target`) emits JSON Schema **draft-07**, not 2020-12 — the
|
|
1115
|
+
* only place that difference is load-bearing for this codebase's schemas is
|
|
1116
|
+
* tuple typing, where draft-07's array-form `items` means something entirely
|
|
1117
|
+
* different in 2020-12 (a single "all items must match" schema). Our own
|
|
1118
|
+
* `toJsonSchema()` below (full zod's `z.toJSONSchema`) already emits native
|
|
1119
|
+
* 2020-12 `prefixItems`, so this is a no-op there. Converting first — for
|
|
1120
|
+
* every tuple anywhere in the tree, not just the root — makes the whole
|
|
1121
|
+
* document genuinely dialect-correct 2020-12 before `applyMcpSchemaDiet`
|
|
1122
|
+
* drops the top-level `$schema` pointer.
|
|
1123
|
+
*/
|
|
1124
|
+
function normalizeTupleDialect(node) {
|
|
1125
|
+
if (!Array.isArray(node.items) || node.prefixItems !== void 0) return;
|
|
1126
|
+
const tuple = node.items;
|
|
1127
|
+
const additionalItems = node.additionalItems;
|
|
1128
|
+
delete node.items;
|
|
1129
|
+
delete node.additionalItems;
|
|
1130
|
+
node.prefixItems = tuple;
|
|
1131
|
+
if (additionalItems === false) node.items = false;
|
|
1132
|
+
else if (isPlainObject(additionalItems)) node.items = additionalItems;
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Strips wire noise the zod v4 / MCP SDK JSON Schema codecs emit on every
|
|
1136
|
+
* tool schema, without touching example/default/const/enum payloads (those
|
|
1137
|
+
* carry caller data, not schema structure, and must never be walked).
|
|
1138
|
+
*
|
|
1139
|
+
* - Removes the document-level `$schema` dialect pointer (informational only;
|
|
1140
|
+
* `normalizeTupleDialect` above makes the document genuinely 2020-12-shaped
|
|
1141
|
+
* first, so an absent `$schema` is universally, correctly, read as 2020-12).
|
|
1142
|
+
* - Drops `additionalProperties: false`, *except inside a `oneOf`/`not`/`if`
|
|
1143
|
+
* subtree*. Ordinarily this is safe to drop everywhere: the MCP SDK
|
|
1144
|
+
* validates tool arguments against the *original* zod schema at call time
|
|
1145
|
+
* (`McpServer#validateToolInput` in `mcp.js`), never against this projected
|
|
1146
|
+
* JSON Schema, so removing the annotation does not change what a call gets
|
|
1147
|
+
* rejected for. But inside `oneOf`, `additionalProperties: false` can be
|
|
1148
|
+
* the only thing making two branches mutually exclusive (reproduced:
|
|
1149
|
+
* `z.xor` of two `.strict()` objects with disjoint keys — stripping it from
|
|
1150
|
+
* both branches makes a value that should match exactly one branch match
|
|
1151
|
+
* both, which every `oneOf`-aware validator then rejects as ambiguous, even
|
|
1152
|
+
* though the MCP server itself would still accept it). Inside `not`, it can
|
|
1153
|
+
* be the very thing being negated — stripping it *widens* what `not`
|
|
1154
|
+
* excludes, which can turn a previously-schema-valid value into
|
|
1155
|
+
* schema-invalid for any client-side validator. `if` shares the same
|
|
1156
|
+
* "widening changes routing" hazard. `anyOf`/`allOf` don't have this
|
|
1157
|
+
* problem (a widened disjunct can never invalidate an already-valid input),
|
|
1158
|
+
* so only `oneOf`/`not`/`if` propagate the protection flag.
|
|
1159
|
+
* - Drops the `pattern` on a `format: "uuid"` node, keeping `format`. The
|
|
1160
|
+
* pattern is the zod-generated uuid regex that always accompanies
|
|
1161
|
+
* `format: "uuid"` in this codebase's schemas (there is no path that sets
|
|
1162
|
+
* `format: "uuid"` other than zod's own `.uuid()`), and — same reasoning as
|
|
1163
|
+
* `additionalProperties` — the MCP SDK never validates against this
|
|
1164
|
+
* projected schema, so the regex is redundant here. `pattern` on any other
|
|
1165
|
+
* node — a node without `format: "uuid"` — is a user-authored constraint
|
|
1166
|
+
* and is left untouched.
|
|
1167
|
+
*/
|
|
1168
|
+
function walkSchemaNode(node, protectAdditionalProperties = false) {
|
|
1169
|
+
if (!isPlainObject(node)) return;
|
|
1170
|
+
normalizeTupleDialect(node);
|
|
1171
|
+
if (node.format === "uuid" && typeof node.pattern === "string") delete node.pattern;
|
|
1172
|
+
if (!protectAdditionalProperties && node.additionalProperties === false) delete node.additionalProperties;
|
|
1173
|
+
for (const key of SCHEMA_MAP_KEYS) {
|
|
1174
|
+
const map = node[key];
|
|
1175
|
+
if (isPlainObject(map)) for (const value of Object.values(map)) walkSchemaNode(value, protectAdditionalProperties);
|
|
1176
|
+
}
|
|
1177
|
+
for (const key of NEUTRAL_SCHEMA_LIST_KEYS) {
|
|
1178
|
+
const list = node[key];
|
|
1179
|
+
if (Array.isArray(list)) for (const item of list) walkSchemaNode(item, protectAdditionalProperties);
|
|
1180
|
+
}
|
|
1181
|
+
for (const key of NEUTRAL_SCHEMA_KEYS) walkSchemaNode(node[key], protectAdditionalProperties);
|
|
1182
|
+
for (const key of NEUTRAL_MAYBE_BOOLEAN_SCHEMA_KEYS) walkSchemaNode(node[key], protectAdditionalProperties);
|
|
1183
|
+
if (Array.isArray(node.oneOf)) for (const item of node.oneOf) walkSchemaNode(item, true);
|
|
1184
|
+
walkSchemaNode(node.not, true);
|
|
1185
|
+
walkSchemaNode(node.if, true);
|
|
1186
|
+
}
|
|
1187
|
+
function applyMcpSchemaDiet(schema) {
|
|
1188
|
+
if (!isPlainObject(schema)) return schema;
|
|
1189
|
+
delete schema.$schema;
|
|
1190
|
+
walkSchemaNode(schema);
|
|
1191
|
+
return schema;
|
|
1192
|
+
}
|
|
1081
1193
|
function toToolInputJsonSchema(schema) {
|
|
1082
1194
|
const parsed = ToolSchema.shape.inputSchema.safeParse(toJsonSchema(schema));
|
|
1083
1195
|
return parsed.success ? parsed.data : {
|
|
@@ -2385,6 +2497,46 @@ async function registerRouteTools(server, scope, catalog) {
|
|
|
2385
2497
|
|
|
2386
2498
|
//#endregion
|
|
2387
2499
|
//#region src/server/create-server.ts
|
|
2500
|
+
function isProductionEnvironment() {
|
|
2501
|
+
return typeof process !== "undefined" && process.env?.NODE_ENV === "production";
|
|
2502
|
+
}
|
|
2503
|
+
/**
|
|
2504
|
+
* Reports a schema-diet install failure loudly instead of either crashing
|
|
2505
|
+
* every session (a renamed/removed SDK internal would otherwise throw deep
|
|
2506
|
+
* inside request handling on the very first `tools/list` call) or failing
|
|
2507
|
+
* silently (shipping an undieted catalogue with nobody told why). Always
|
|
2508
|
+
* logs; only throws outside production, so a CI/dev run surfaces the break
|
|
2509
|
+
* immediately while a live server degrades to the SDK's own undieted
|
|
2510
|
+
* `tools/list` response.
|
|
2511
|
+
*/
|
|
2512
|
+
function reportSchemaDietInstallFailure(message) {
|
|
2513
|
+
const prefixed = `@questpie/mcp: ${message}`;
|
|
2514
|
+
console.error(prefixed);
|
|
2515
|
+
if (!isProductionEnvironment()) throw new Error(prefixed);
|
|
2516
|
+
}
|
|
2517
|
+
function installSchemaDietListToolsHandler(server) {
|
|
2518
|
+
const handlers = Reflect.get(server.server, "_requestHandlers");
|
|
2519
|
+
if (!(handlers instanceof Map)) {
|
|
2520
|
+
reportSchemaDietInstallFailure("could not install the tools/list schema diet — McpServer#server's internal request-handler map is missing or not a Map (the MCP SDK's internals likely changed shape). Tools will be listed without the diet applied.");
|
|
2521
|
+
return;
|
|
2522
|
+
}
|
|
2523
|
+
const defaultHandler = handlers.get("tools/list");
|
|
2524
|
+
if (!defaultHandler) {
|
|
2525
|
+
reportSchemaDietInstallFailure("could not install the tools/list schema diet — no default tools/list handler was registered even though at least one tool exists. Tools will be listed without the diet applied.");
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
server.server.setRequestHandler(ListToolsRequestSchema, async (request, extra) => {
|
|
2529
|
+
const result = await defaultHandler(request, extra);
|
|
2530
|
+
return {
|
|
2531
|
+
...result,
|
|
2532
|
+
tools: result.tools.map((tool) => ({
|
|
2533
|
+
...tool,
|
|
2534
|
+
inputSchema: applyMcpSchemaDiet(tool.inputSchema),
|
|
2535
|
+
...tool.outputSchema ? { outputSchema: applyMcpSchemaDiet(tool.outputSchema) } : {}
|
|
2536
|
+
}))
|
|
2537
|
+
};
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2388
2540
|
async function createServer(app, options, workload) {
|
|
2389
2541
|
const release = workload ? createWorkloadMcpRelease(app, options.config) : options.config ? createIsolatedMcpRelease(app, options.config) : getAppMcpRelease(app);
|
|
2390
2542
|
const { config, catalog } = release;
|
|
@@ -2409,6 +2561,7 @@ async function createServer(app, options, workload) {
|
|
|
2409
2561
|
await registerCustomTools(server, scope, catalog);
|
|
2410
2562
|
if (workload) server.server.setRequestHandler(ListToolsRequestSchema, (_request, extra) => listWorkloadTools(workload, release.execution, extra));
|
|
2411
2563
|
else if ([...catalog.collections.values()].every((entry) => entry.operations.length === 0) && [...catalog.globals.values()].every((entry) => entry.operations.length === 0) && catalog.routes.size === 0 && catalog.customTools.size === 0) server.server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: [] }));
|
|
2564
|
+
else installSchemaDietListToolsHandler(server);
|
|
2412
2565
|
return server;
|
|
2413
2566
|
}
|
|
2414
2567
|
function resolveStdioAccessMode(options, trustedMaintenance) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { S as scopesFromContext, _ as resolveMcpCatalog, a as customToolWorkloadIdentity, b as requiredScopesForOperation, c as createWorkloadMcpBoundary, f as McpAccessDeniedError, g as toMcpToolError, h as mcpPublicErrorCode, i as customToolDescriptor, l as createRuntimeScope, m as assertBoundedMcpValue, n as createWorkloadMcpServer, o as executeCustomToolCall, p as McpPublicError, r as customToolAllows, s as authorizeWorkload, t as createMcpServer, u as createWorkloadMcpRelease, v as defaultOperationScope, w as mcpTool, x as scopeGateAllows, y as normalizeRequiredScopes } from "./create-server-
|
|
2
|
-
import { n as mcp_default, t as mcpModule } from "./mcp-
|
|
1
|
+
import { S as scopesFromContext, _ as resolveMcpCatalog, a as customToolWorkloadIdentity, b as requiredScopesForOperation, c as createWorkloadMcpBoundary, f as McpAccessDeniedError, g as toMcpToolError, h as mcpPublicErrorCode, i as customToolDescriptor, l as createRuntimeScope, m as assertBoundedMcpValue, n as createWorkloadMcpServer, o as executeCustomToolCall, p as McpPublicError, r as customToolAllows, s as authorizeWorkload, t as createMcpServer, u as createWorkloadMcpRelease, v as defaultOperationScope, w as mcpTool, x as scopeGateAllows, y as normalizeRequiredScopes } from "./create-server-5Eo4QP3q.mjs";
|
|
2
|
+
import { n as mcp_default, t as mcpModule } from "./mcp-i0Kqu_bB.mjs";
|
|
3
3
|
import { t as mcpPlugin } from "./plugin-BZQe1pji.mjs";
|
|
4
|
-
import { t as startStdioServer } from "./stdio-
|
|
4
|
+
import { t as startStdioServer } from "./stdio-37bSPka9.mjs";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
6
|
|
|
7
7
|
//#region src/server/workload-tool-port.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as validateMcpPrincipal, d as getAppMcpRelease, m as assertBoundedMcpValue, t as createMcpServer } from "./create-server-
|
|
1
|
+
import { C as validateMcpPrincipal, d as getAppMcpRelease, m as assertBoundedMcpValue, t as createMcpServer } from "./create-server-5Eo4QP3q.mjs";
|
|
2
2
|
import { t as mcpPlugin } from "./plugin-BZQe1pji.mjs";
|
|
3
3
|
import { route } from "questpie";
|
|
4
4
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
package/dist/modules/mcp.mjs
CHANGED
package/dist/stdio.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@questpie/mcp",
|
|
3
|
-
"version": "3.28.
|
|
3
|
+
"version": "3.28.11",
|
|
4
4
|
"description": "Model Context Protocol server for QUESTPIE apps, under the app's own access rules",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
73
|
-
"questpie": "^3.28.
|
|
73
|
+
"questpie": "^3.28.11",
|
|
74
74
|
"zod": "^4.2.1"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
@@ -80,6 +80,6 @@
|
|
|
80
80
|
"tsdown": "^0.18.3"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
|
-
"questpie": "^3.28.
|
|
83
|
+
"questpie": "^3.28.11"
|
|
84
84
|
}
|
|
85
85
|
}
|