@ampless/backend 1.0.0-beta.89 → 1.0.0-beta.90

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.
@@ -1841,6 +1841,69 @@ function hasValidJsonRpcId(req) {
1841
1841
  function isPlainObject(v) {
1842
1842
  return typeof v === "object" && v !== null && !Array.isArray(v);
1843
1843
  }
1844
+ var MAX_BATCH = 50;
1845
+ function idForError(input) {
1846
+ if (isPlainObject(input) && hasValidJsonRpcId(input)) {
1847
+ return input.id ?? null;
1848
+ }
1849
+ return null;
1850
+ }
1851
+ function validateEnvelope(input, inBatch) {
1852
+ if (!isPlainObject(input)) {
1853
+ return { ok: false, error: jsonRpcError(null, JSON_RPC_INVALID_REQUEST, "Invalid Request") };
1854
+ }
1855
+ const jsonrpc = input.jsonrpc;
1856
+ const method = input.method;
1857
+ if (jsonrpc !== "2.0" || typeof method !== "string" || !hasValidJsonRpcId(input)) {
1858
+ return {
1859
+ ok: false,
1860
+ error: jsonRpcError(idForError(input), JSON_RPC_INVALID_REQUEST, "Invalid Request")
1861
+ };
1862
+ }
1863
+ if (inBatch && method === "initialize") {
1864
+ return {
1865
+ ok: false,
1866
+ error: jsonRpcError(
1867
+ idForError(input),
1868
+ JSON_RPC_INVALID_REQUEST,
1869
+ "Invalid Request: `initialize` is not allowed in a batch"
1870
+ )
1871
+ };
1872
+ }
1873
+ return { ok: true, req: input };
1874
+ }
1875
+ async function dispatchJsonRpcMessage(input, opts) {
1876
+ const maxBatch = opts.maxBatch ?? MAX_BATCH;
1877
+ if (Array.isArray(input)) {
1878
+ if (input.length === 0 || input.length > maxBatch) {
1879
+ return {
1880
+ status: "invalid",
1881
+ body: jsonRpcError(
1882
+ null,
1883
+ JSON_RPC_INVALID_REQUEST,
1884
+ input.length === 0 ? "Invalid Request: empty batch" : `Invalid Request: batch exceeds the maximum of ${maxBatch} elements`
1885
+ )
1886
+ };
1887
+ }
1888
+ const responses = [];
1889
+ for (const element of input) {
1890
+ const validated2 = validateEnvelope(element, true);
1891
+ if (!validated2.ok) {
1892
+ responses.push(validated2.error);
1893
+ continue;
1894
+ }
1895
+ const res2 = await dispatchJsonRpc(validated2.req, opts);
1896
+ if (res2 !== null) responses.push(res2);
1897
+ }
1898
+ return responses.length === 0 ? { status: "no-content" } : { status: "ok", body: responses };
1899
+ }
1900
+ const validated = validateEnvelope(input, false);
1901
+ if (!validated.ok) {
1902
+ return { status: "invalid", body: validated.error };
1903
+ }
1904
+ const res = await dispatchJsonRpc(validated.req, opts);
1905
+ return res === null ? { status: "no-content" } : { status: "ok", body: res };
1906
+ }
1844
1907
  function toolAnnotations(t) {
1845
1908
  const annotations = {};
1846
1909
  if (typeof t.readOnly === "boolean") annotations.readOnlyHint = t.readOnly;
@@ -2140,43 +2203,37 @@ var handler = async (event) => {
2140
2203
  return jsonResponse(401, { error: "invalid_token" });
2141
2204
  }
2142
2205
  await touchLastUsedAt(meta.hash);
2143
- let req;
2206
+ let parsed;
2144
2207
  try {
2145
2208
  const body = event.isBase64Encoded ? Buffer.from(event.body ?? "", "base64").toString("utf8") : event.body ?? "";
2146
2209
  if (!body) {
2147
2210
  return jsonResponse(400, jsonRpcError(null, JSON_RPC_INVALID_REQUEST, "Empty body"));
2148
2211
  }
2149
- req = JSON.parse(body);
2212
+ parsed = JSON.parse(body);
2150
2213
  } catch {
2151
2214
  return jsonResponse(400, jsonRpcError(null, JSON_RPC_PARSE_ERROR, "Parse error"));
2152
2215
  }
2153
- if (typeof req !== "object" || req === null || Array.isArray(req)) {
2154
- return jsonResponse(400, jsonRpcError(null, JSON_RPC_INVALID_REQUEST, "Invalid Request"));
2155
- }
2156
- if (req.jsonrpc !== "2.0" || typeof req.method !== "string" || !hasValidJsonRpcId(req)) {
2157
- const responseId = hasValidJsonRpcId(req) ? req.id ?? null : null;
2158
- return jsonResponse(
2159
- 400,
2160
- jsonRpcError(responseId, JSON_RPC_INVALID_REQUEST, "Invalid Request")
2161
- );
2162
- }
2163
2216
  try {
2164
- const response = await dispatchJsonRpc(req, {
2217
+ const result = await dispatchJsonRpcMessage(parsed, {
2165
2218
  tools: HTTP_TOOLS,
2166
2219
  getContext: makeContext,
2167
2220
  serverInfo: { name: "ampless-mcp", version: "0.2" }
2168
2221
  });
2169
- if (response === null) {
2222
+ if (result.status === "invalid") {
2223
+ return jsonResponse(400, result.body);
2224
+ }
2225
+ if (result.status === "no-content") {
2170
2226
  return { statusCode: 202, body: "" };
2171
2227
  }
2172
- return jsonResponse(200, response);
2228
+ return jsonResponse(200, result.body);
2173
2229
  } catch (err2) {
2230
+ const method = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed.method : void 0;
2174
2231
  const message = err2 instanceof Error ? err2.message : String(err2);
2175
- console.error("[mcp-handler] dispatch threw", { method: req.method, message });
2176
- return jsonResponse(
2177
- 500,
2178
- jsonRpcError(req.id ?? null, JSON_RPC_INTERNAL_ERROR, message)
2179
- );
2232
+ console.error("[mcp-handler] dispatch threw", {
2233
+ method: typeof method === "string" ? method : void 0,
2234
+ message
2235
+ });
2236
+ return jsonResponse(500, jsonRpcError(null, JSON_RPC_INTERNAL_ERROR, message));
2180
2237
  }
2181
2238
  };
2182
2239
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ampless/backend",
3
- "version": "1.0.0-beta.89",
3
+ "version": "1.0.0-beta.90",
4
4
  "description": "Amplify Gen 2 backend factories for ampless: auth, data, storage, event processors, API key renewer",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -69,8 +69,8 @@
69
69
  "@smithy/protocol-http": "^5.4.4",
70
70
  "@smithy/signature-v4": "^5.4.4",
71
71
  "fflate": "^0.8.3",
72
- "@ampless/mcp-server": "1.0.0-beta.66",
73
- "ampless": "1.0.0-beta.59"
72
+ "@ampless/mcp-server": "1.0.0-beta.67",
73
+ "ampless": "1.0.0-beta.60"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "@aws-amplify/backend": "^1.19.0",