@zuplo/cli 7.12.3 → 7.12.4

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.
Files changed (51) hide show
  1. package/node_modules/@inquirer/checkbox/dist/index.js +4 -0
  2. package/node_modules/@inquirer/checkbox/package.json +3 -3
  3. package/node_modules/@inquirer/confirm/package.json +3 -3
  4. package/node_modules/@inquirer/core/dist/lib/create-prompt.js +3 -1
  5. package/node_modules/@inquirer/core/package.json +2 -2
  6. package/node_modules/@inquirer/editor/package.json +3 -3
  7. package/node_modules/@inquirer/expand/package.json +3 -3
  8. package/node_modules/@inquirer/input/package.json +3 -3
  9. package/node_modules/@inquirer/number/dist/index.js +1 -1
  10. package/node_modules/@inquirer/number/package.json +3 -3
  11. package/node_modules/@inquirer/password/package.json +3 -3
  12. package/node_modules/@inquirer/rawlist/package.json +3 -3
  13. package/node_modules/@inquirer/search/package.json +3 -3
  14. package/node_modules/@inquirer/select/package.json +3 -3
  15. package/node_modules/@zuplo/core/customer.cli.minified.js +269 -269
  16. package/node_modules/@zuplo/core/index.minified.js +262 -262
  17. package/node_modules/@zuplo/core/package.json +1 -1
  18. package/node_modules/@zuplo/graphql/package.json +1 -1
  19. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  20. package/node_modules/@zuplo/otel/package.json +1 -1
  21. package/node_modules/@zuplo/runtime/out/esm/{chunk-3UPXKWR6.js → chunk-RH345HSZ.js} +3 -3
  22. package/node_modules/@zuplo/runtime/out/esm/chunk-RH345HSZ.js.map +1 -0
  23. package/node_modules/@zuplo/runtime/out/esm/chunk-WIQFTAJL.js +26 -0
  24. package/node_modules/@zuplo/runtime/out/esm/chunk-WIQFTAJL.js.map +1 -0
  25. package/node_modules/@zuplo/runtime/out/esm/{chunk-JBEZQ336.js → chunk-WTWRZT3M.js} +112 -111
  26. package/node_modules/@zuplo/runtime/out/esm/chunk-WTWRZT3M.js.map +1 -0
  27. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  28. package/node_modules/@zuplo/runtime/out/esm/index.js.map +1 -1
  29. package/node_modules/@zuplo/runtime/out/esm/internal/index.js +1 -1
  30. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
  31. package/node_modules/@zuplo/runtime/out/esm/mocks/index.js +1 -1
  32. package/node_modules/@zuplo/runtime/out/esm/sdks/aws/index.js +1 -1
  33. package/node_modules/@zuplo/runtime/out/types/index.d.ts +140 -16
  34. package/node_modules/@zuplo/runtime/out/types/internal/index.d.ts +93 -16
  35. package/node_modules/@zuplo/runtime/package.json +1 -1
  36. package/node_modules/fast-uri/.github/workflows/release.yml +35 -0
  37. package/node_modules/fast-uri/README.md +8 -0
  38. package/node_modules/fast-uri/index.js +98 -18
  39. package/node_modules/fast-uri/lib/utils.js +52 -0
  40. package/node_modules/fast-uri/package.json +1 -1
  41. package/node_modules/fast-uri/test/host-delimiter-security.test.js +94 -0
  42. package/node_modules/fast-uri/test/relative-normalization-security.test.js +156 -0
  43. package/node_modules/fast-uri/test/reserved-path-normalization.test.js +32 -4
  44. package/node_modules/fast-uri/test/scheme-validation.test.js +53 -14
  45. package/package.json +11 -11
  46. package/node_modules/@zuplo/runtime/out/esm/chunk-3UPXKWR6.js.map +0 -1
  47. package/node_modules/@zuplo/runtime/out/esm/chunk-GQMNFQTN.js +0 -26
  48. package/node_modules/@zuplo/runtime/out/esm/chunk-GQMNFQTN.js.map +0 -1
  49. package/node_modules/@zuplo/runtime/out/esm/chunk-JBEZQ336.js.map +0 -1
  50. /package/node_modules/@zuplo/runtime/out/esm/{chunk-3UPXKWR6.js.LEGAL.txt → chunk-RH345HSZ.js.LEGAL.txt} +0 -0
  51. /package/node_modules/@zuplo/runtime/out/esm/{chunk-JBEZQ336.js.LEGAL.txt → chunk-WTWRZT3M.js.LEGAL.txt} +0 -0
@@ -22,5 +22,5 @@
22
22
  * DEALINGS IN THE SOFTWARE.
23
23
  *--------------------------------------------------------------------------------------------*/
24
24
 
25
- import{F as p,K as c,N as u}from"../chunk-JBEZQ336.js";import"../chunk-GQMNFQTN.js";import{a as d}from"../chunk-QGAJTUPE.js";import"../chunk-A3QGJZO7.js";import{aa as i}from"../chunk-3UPXKWR6.js";import"../chunk-UKQQD2JN.js";import{a as o}from"../chunk-TYV53J3B.js";function w(l={request:new Request("https://api.example.com")}){let e=[];function t(s){e.push(Promise.resolve(s))}return o(t,"waitUntil"),{context:new a({event:{waitUntil:t},route:l.route,originalRequest:l.request}),invokeResponse:o(async()=>{await Promise.all(e)},"invokeResponse")}}o(w,"createMockContext");var g={path:"/",methods:["GET"],handler:{module:{},export:"default"},raw:o(()=>({}),"raw")},a=class extends EventTarget{static{o(this,"MockZuploContext")}#e;#t;contextId;requestId;log;route;custom;incomingRequestProperties;parentContext;analyticsContext;constructor({event:e,route:t=g,parentContext:n,originalRequest:r}){super(),this.requestId=crypto.randomUUID(),this.contextId=crypto.randomUUID(),this.log={info:i.console.info,log:i.console.log,debug:i.console.debug,warn:i.console.warn,error:i.console.error,setLogProperties:o(()=>{},"setLogProperties")},this.custom={},this.route=t,this.incomingRequestProperties={ip:"203.0.113.7",asn:1234,asOrganization:"ORGANIZATION",city:"Seattle",region:"Washington",regionCode:"WA",colo:"SEA",continent:"NA",country:"US",postalCode:"98004",metroCode:"SEA",latitude:void 0,longitude:void 0,timezone:void 0,httpProtocol:void 0,clientCert:void 0,clientMtlsVerificationStatus:void 0,clientMtlsVerificationReason:void 0,clientCertFingerprintSha256:void 0,clientCertNotBefore:void 0,clientCertNotAfter:void 0,clientCertIssuerDn:void 0,clientCertSubjectDn:void 0},this.parentContext=n,this.#e=e,this.#t=r,this.analyticsContext=new c(this.requestId)}waitUntil(e){this.#e.waitUntil(e)}invokeInboundPolicy(e,t){throw new Error("Not implemented")}invokeOutboundPolicy(e,t,n){throw new Error("Not implemented")}invokeRoute(e,t){throw new Error("Not implemented")}addResponseSendingHook(e){throw new Error("Not implemented")}addResponseSendingFinalHook(e){throw new Error("Not implemented")}addPreRequestHandler(e,t){let n;try{n=u.getContextExtensions(this)}catch{n=u.initialize(this,new d(this.#t??new Request("https://api.example.com")))}n.preRequestPhase??="active",p(this,n,e,t)}get preRequestHandlers(){let e;try{e=u.getContextExtensions(this)}catch{return[]}return(e.preRequestState?.entries??[]).map(t=>({policyName:t.policyName,name:t.name}))}addEventListener(e,t,n){let r=o(s=>{try{typeof t=="function"?t(s):t.handleEvent(s)}catch(m){throw this.log.error(`Error invoking event ${e}. See following logs for details.`),m}},"wrapped");super.addEventListener(e,r,n)}};export{a as MockZuploContext,w as createMockContext};
25
+ import{F as p,K as c,N as u}from"../chunk-WTWRZT3M.js";import"../chunk-WIQFTAJL.js";import{a as d}from"../chunk-QGAJTUPE.js";import"../chunk-A3QGJZO7.js";import{aa as i}from"../chunk-RH345HSZ.js";import"../chunk-UKQQD2JN.js";import{a as o}from"../chunk-TYV53J3B.js";function w(l={request:new Request("https://api.example.com")}){let e=[];function t(s){e.push(Promise.resolve(s))}return o(t,"waitUntil"),{context:new a({event:{waitUntil:t},route:l.route,originalRequest:l.request}),invokeResponse:o(async()=>{await Promise.all(e)},"invokeResponse")}}o(w,"createMockContext");var g={path:"/",methods:["GET"],handler:{module:{},export:"default"},raw:o(()=>({}),"raw")},a=class extends EventTarget{static{o(this,"MockZuploContext")}#e;#t;contextId;requestId;log;route;custom;incomingRequestProperties;parentContext;analyticsContext;constructor({event:e,route:t=g,parentContext:n,originalRequest:r}){super(),this.requestId=crypto.randomUUID(),this.contextId=crypto.randomUUID(),this.log={info:i.console.info,log:i.console.log,debug:i.console.debug,warn:i.console.warn,error:i.console.error,setLogProperties:o(()=>{},"setLogProperties")},this.custom={},this.route=t,this.incomingRequestProperties={ip:"203.0.113.7",asn:1234,asOrganization:"ORGANIZATION",city:"Seattle",region:"Washington",regionCode:"WA",colo:"SEA",continent:"NA",country:"US",postalCode:"98004",metroCode:"SEA",latitude:void 0,longitude:void 0,timezone:void 0,httpProtocol:void 0,clientCert:void 0,clientMtlsVerificationStatus:void 0,clientMtlsVerificationReason:void 0,clientCertFingerprintSha256:void 0,clientCertNotBefore:void 0,clientCertNotAfter:void 0,clientCertIssuerDn:void 0,clientCertSubjectDn:void 0},this.parentContext=n,this.#e=e,this.#t=r,this.analyticsContext=new c(this.requestId)}waitUntil(e){this.#e.waitUntil(e)}invokeInboundPolicy(e,t){throw new Error("Not implemented")}invokeOutboundPolicy(e,t,n){throw new Error("Not implemented")}invokeRoute(e,t){throw new Error("Not implemented")}addResponseSendingHook(e){throw new Error("Not implemented")}addResponseSendingFinalHook(e){throw new Error("Not implemented")}addPreRequestHandler(e,t){let n;try{n=u.getContextExtensions(this)}catch{n=u.initialize(this,new d(this.#t??new Request("https://api.example.com")))}n.preRequestPhase??="active",p(this,n,e,t)}get preRequestHandlers(){let e;try{e=u.getContextExtensions(this)}catch{return[]}return(e.preRequestState?.entries??[]).map(t=>({policyName:t.policyName,name:t.name}))}addEventListener(e,t,n){let r=o(s=>{try{typeof t=="function"?t(s):t.handleEvent(s)}catch(m){throw this.log.error(`Error invoking event ${e}. See following logs for details.`),m}},"wrapped");super.addEventListener(e,r,n)}};export{a as MockZuploContext,w as createMockContext};
26
26
  //# sourceMappingURL=index.js.map
@@ -22,5 +22,5 @@
22
22
  * DEALINGS IN THE SOFTWARE.
23
23
  *--------------------------------------------------------------------------------------------*/
24
24
 
25
- import{Ia as a,Ja as l,Ka as c,La as o,Oa as p,Pa as y,Qa as m}from"../../chunk-3UPXKWR6.js";import"../../chunk-UKQQD2JN.js";import{a as i}from"../../chunk-TYV53J3B.js";async function g(r,e){let t=typeof e.credentials=="function"?await e.credentials():e.credentials,n=r.method,d=n!=="GET"&&n!=="HEAD"&&r.body!=null?await r.arrayBuffer():null,s=await new o({method:n,url:r.url,headers:r.headers,body:d,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,sessionToken:t.sessionToken,service:e.service,region:e.region,signQuery:e.signQuery}).sign();return new Request(s.url.toString(),{method:s.method,headers:s.headers,body:s.body})}i(g,"signRequest");export{c as AwsClient,o as AwsV4Signer,p as fromTemporaryCredentials,y as fromWebToken,m as fromZuploIdentity,l as getAwsCredentialProvider,a as setAwsCredentialProvider,g as signRequest};
25
+ import{Ia as a,Ja as l,Ka as c,La as o,Oa as p,Pa as y,Qa as m}from"../../chunk-RH345HSZ.js";import"../../chunk-UKQQD2JN.js";import{a as i}from"../../chunk-TYV53J3B.js";async function g(r,e){let t=typeof e.credentials=="function"?await e.credentials():e.credentials,n=r.method,d=n!=="GET"&&n!=="HEAD"&&r.body!=null?await r.arrayBuffer():null,s=await new o({method:n,url:r.url,headers:r.headers,body:d,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,sessionToken:t.sessionToken,service:e.service,region:e.region,signQuery:e.signQuery}).sign();return new Request(s.url.toString(),{method:s.method,headers:s.headers,body:s.body})}i(g,"signRequest");export{c as AwsClient,o as AwsV4Signer,p as fromTemporaryCredentials,y as fromWebToken,m as fromZuploIdentity,l as getAwsCredentialProvider,a as setAwsCredentialProvider,g as signRequest};
26
26
  //# sourceMappingURL=index.js.map
@@ -4306,29 +4306,30 @@ declare interface CompatibilityFlags {
4306
4306
  */
4307
4307
  return501ForUnsupportedHttpMethods: boolean;
4308
4308
  /**
4309
- * Whether the MCP server handler leaves the non-standard
4310
- * `capabilities.tools.supported` and `capabilities.tools.available` fields
4311
- * out of its `initialize` response.
4309
+ * Retired: still accepted in `compatibilityFlags`, with no effect.
4312
4310
  *
4313
- * Before this flag: `initialize` returns `supported: true` and lists every
4314
- * registered tool name in `available`, to every caller.
4311
+ * The MCP server handler's `initialize` returns `capabilities.tools: {}` for
4312
+ * every project, without the non-standard `supported` and `available`
4313
+ * fields this flag used to remove. Clients discover tools with
4314
+ * `tools/list`. See `packages/runtime/specs/mcp-json-rpc.md`, MCPRPC-26 to
4315
+ * MCPRPC-28.
4315
4316
  *
4316
- * After this flag: `initialize` returns `capabilities.tools: {}`. Clients
4317
- * discover tools with `tools/list`, as the MCP spec defines.
4317
+ * @deprecated The behavior is unconditional; listing the flag changes
4318
+ * nothing.
4318
4319
  */
4319
4320
  removeMcpToolsCapabilityExtension: boolean;
4320
4321
  /**
4321
- * Whether the MCP server handler reports a `tools/call` whose arguments fail
4322
- * the tool's `inputSchema` as a tool result with `isError: true`, as
4323
- * MCP 2025-11-25 specifies for input validation errors.
4322
+ * Retired: still accepted in `compatibilityFlags`, with no effect.
4324
4323
  *
4325
- * Before this flag: Invalid arguments return a JSON-RPC `-32602` error.
4324
+ * For every project, when the request's `MCP-Protocol-Version` header is
4325
+ * `2025-11-25` or later, a `tools/call` whose arguments fail the tool's
4326
+ * `inputSchema` returns a result with `isError: true` and the validation
4327
+ * message as text content, and the tool is not called. Earlier or missing
4328
+ * protocol versions return a JSON-RPC `-32602` error. See
4329
+ * `packages/runtime/specs/mcp-json-rpc.md`, MCPRPC-19 to MCPRPC-25.
4326
4330
  *
4327
- * After this flag: When the request's `MCP-Protocol-Version` header is
4328
- * `2025-11-25` or later, invalid arguments return a result with
4329
- * `isError: true` and the validation message as text content, and the tool
4330
- * is not called. Earlier or missing protocol versions still return
4331
- * `-32602`. Unknown tools and malformed requests return `-32602` either way.
4331
+ * @deprecated The behavior is unconditional; listing the flag changes
4332
+ * nothing.
4332
4333
  */
4333
4334
  returnMcpToolInputErrorsAsToolResults: boolean;
4334
4335
  /**
@@ -4339,6 +4340,56 @@ declare interface CompatibilityFlags {
4339
4340
  * Opt in only on the JavaScript runtimes (workerd and Zeno).
4340
4341
  */
4341
4342
  useMcpDirectSchemaValidation: boolean;
4343
+ /**
4344
+ * Whether the MCP server handler rewrites tool names to follow the MCP tool
4345
+ * naming rule: 1 to 128 characters of `A-Z`, `a-z`, `0-9`, `_`, `-` and
4346
+ * `.`, unique within the server (MCP 2025-11-25, server/tools#tool-names).
4347
+ *
4348
+ * Before this flag: Each tool is advertised and called by its configured
4349
+ * name (`x-zuplo-route.mcp.name`, or the operationId) as is, including
4350
+ * spaces, `/` and names over 128 characters. When a tool from the
4351
+ * deprecated `files` option reuses the name of a tool from `operations`
4352
+ * (or a content-type suffix repeats another tool's name), the later tool
4353
+ * replaces the earlier one.
4354
+ *
4355
+ * After this flag: A name that already follows the rule is unchanged. In
4356
+ * any other name, each character outside the allowed set becomes `_`, an
4357
+ * empty name becomes `tool`, and the name is cut to 128 characters. A
4358
+ * rewritten or repeated name that is already taken gets `_2`, `_3`, and so
4359
+ * on, in registration order, still within 128 characters, so both tools
4360
+ * stay. `tools/list`, `tools/call` and analytics use the advertised name,
4361
+ * and `tools/call` no longer accepts the configured name of a rewritten
4362
+ * tool. Two operations with the same `x-zuplo-route.mcp.name` still stop
4363
+ * the server from starting, as before.
4364
+ *
4365
+ * The build warns about every name that breaks the rule or repeats, with or
4366
+ * without this flag. Set `x-zuplo-route.mcp.name` to keep a name stable.
4367
+ */
4368
+ sanitizeMcpToolNames: boolean;
4369
+ /**
4370
+ * Whether the MCP server handler leaves out of its responses the fields
4371
+ * that protocol revisions newer than the request's added.
4372
+ *
4373
+ * Before this flag: Every response carries every field on every protocol
4374
+ * version, so a `2025-03-26` client gets `outputSchema` on `tools/list` and
4375
+ * `structuredContent` on `tools/call`.
4376
+ *
4377
+ * After this flag: The request's `MCP-Protocol-Version` header, or
4378
+ * `2025-03-26` when it is missing, decides which fields are sent:
4379
+ *
4380
+ * - Before `2025-06-18`: tools leave out `outputSchema` and `title`,
4381
+ * resources leave out `title`, and `tools/call` results leave out
4382
+ * `structuredContent` (when the result has no text block, its JSON is
4383
+ * added as one). In `tools/call` and `prompts/get` content, annotations
4384
+ * leave out `lastModified` and a `resource_link` block becomes a text
4385
+ * block holding the link as JSON.
4386
+ * - Before `2025-11-25`: tools leave out `icons` and `execution`, and
4387
+ * resources and resource links leave out `icons`.
4388
+ * - Before `2025-03-26`: tools also leave out `annotations`.
4389
+ *
4390
+ * `_meta` is sent on every version.
4391
+ */
4392
+ omitMcpFieldsNewerThanNegotiatedVersion: boolean;
4342
4393
  }
4343
4394
 
4344
4395
  declare interface CompletionsFallbacks {
@@ -4526,6 +4577,61 @@ declare interface ComputerUseTool {
4526
4577
  environment: "windows" | "mac" | "linux" | "ubuntu" | "browser";
4527
4578
  }
4528
4579
 
4580
+ /**
4581
+ * The identifying element of the request that enforces distinct rate limits. For example, you can limit by `user`, `ip`, `function` or `all` - function allows you to specify a simple function to create a string identifier to create a rate-limit group.
4582
+ * @public
4583
+ */
4584
+ declare type ConcurrencyLimitBy = "user" | "ip" | "function" | "all";
4585
+
4586
+ /**
4587
+ * Adds the retry-after header.
4588
+ * @public
4589
+ */
4590
+ declare type ConcurrencyLimitHeaderMode = "none" | "retry-after";
4591
+
4592
+ /**
4593
+ * Limits active request/response leases. Expiry frees capacity without ending
4594
+ * the request. Regional replication provides an approximate global limit.
4595
+ * @title Concurrency Limiting
4596
+ * @hidden
4597
+ * @public
4598
+ */
4599
+ export declare const ConcurrencyLimitInboundPolicy: InboundPolicyHandler<ConcurrencyLimitInboundPolicyOptions>;
4600
+
4601
+ /**
4602
+ * The options for this policy.
4603
+ * @public
4604
+ */
4605
+ export declare interface ConcurrencyLimitInboundPolicyOptions {
4606
+ rateLimitBy: ConcurrencyLimitBy;
4607
+ /**
4608
+ * Maximum active request leases in this bucket.
4609
+ */
4610
+ requestsAllowed: number;
4611
+ /**
4612
+ * The function that returns dynamic configuration data. Used only with `rateLimitBy=function`.
4613
+ */
4614
+ identifier?: {
4615
+ /**
4616
+ * used only with rateLimitBy=function. Specifies the export to load your custom bucket function, e.g. `default`, `rateLimitIdentifier`.
4617
+ */
4618
+ export: string;
4619
+ /**
4620
+ * Specifies the module to load your custom bucket function, in the format `$import(./modules/my-module)`.
4621
+ */
4622
+ module: string;
4623
+ };
4624
+ headerMode?: ConcurrencyLimitHeaderMode;
4625
+ /**
4626
+ * If true, the policy will throw an error in the event there is a problem connecting to the rate limit service.
4627
+ */
4628
+ throwOnFailure?: boolean;
4629
+ /**
4630
+ * Fixed lease duration. Expiry frees capacity without terminating the request. Five minutes caps shared storage retention.
4631
+ */
4632
+ leaseSeconds?: number;
4633
+ }
4634
+
4529
4635
  /**
4530
4636
  * Errors caused by invalid user configuration such as invalid parameters on policies,
4531
4637
  * handlers that are not functions, or missing required configuration values.
@@ -4833,6 +4939,24 @@ export declare interface CurityPhantomTokenInboundPolicyOptions {
4833
4939
  cacheDurationSeconds?: number;
4834
4940
  }
4835
4941
 
4942
+ /** Custom bucket identity and optional fixed-lease overrides. @public */
4943
+ export declare interface CustomConcurrencyLimitDetails {
4944
+ key: string;
4945
+ requestsAllowed?: number;
4946
+ leaseSeconds?: number;
4947
+ }
4948
+
4949
+ /** Returning null or undefined exempts this request. @public */
4950
+ export declare type CustomConcurrencyLimitFunction = (
4951
+ request: ZuploRequest,
4952
+ context: ZuploContext,
4953
+ policyName: string
4954
+ ) =>
4955
+ | CustomConcurrencyLimitDetails
4956
+ | null
4957
+ | undefined
4958
+ | Promise<CustomConcurrencyLimitDetails | null | undefined>;
4959
+
4836
4960
  declare type CustomLogFields = Record<string, number | string | boolean>;
4837
4961
 
4838
4962
  /**
@@ -4,6 +4,23 @@ export declare interface ApiRuntimeConfig {
4
4
  urls: UrlConfig | undefined;
5
5
  }
6
6
 
7
+ /**
8
+ * Assigns each tool a name that follows the MCP tool naming rule and is
9
+ * unique among `names`, deterministically. `names` are the configured names
10
+ * in registration order and may repeat; the result has the advertised name
11
+ * at the same index.
12
+ *
13
+ * 1. A name that already follows the rule keeps it, the first time it
14
+ * appears. So turning `sanitizeMcpToolNames` on never renames a tool whose
15
+ * name was already valid and unique.
16
+ * 2. Every other name, in registration order, gets
17
+ * {@link sanitizeMcpToolName}, plus `_2`, `_3`, … when that name is
18
+ * taken. The suffix replaces the end of a name that would otherwise
19
+ * exceed 128 characters.
20
+ * @param names - configured tool names, in registration order
21
+ */
22
+ export declare function assignMcpToolNames(names: readonly string[]): string[];
23
+
7
24
  /**
8
25
  * Base logger interface with methods for each log level.
9
26
  * @beta
@@ -143,29 +160,30 @@ declare interface CompatibilityFlags {
143
160
  */
144
161
  return501ForUnsupportedHttpMethods: boolean;
145
162
  /**
146
- * Whether the MCP server handler leaves the non-standard
147
- * `capabilities.tools.supported` and `capabilities.tools.available` fields
148
- * out of its `initialize` response.
163
+ * Retired: still accepted in `compatibilityFlags`, with no effect.
149
164
  *
150
- * Before this flag: `initialize` returns `supported: true` and lists every
151
- * registered tool name in `available`, to every caller.
165
+ * The MCP server handler's `initialize` returns `capabilities.tools: {}` for
166
+ * every project, without the non-standard `supported` and `available`
167
+ * fields this flag used to remove. Clients discover tools with
168
+ * `tools/list`. See `packages/runtime/specs/mcp-json-rpc.md`, MCPRPC-26 to
169
+ * MCPRPC-28.
152
170
  *
153
- * After this flag: `initialize` returns `capabilities.tools: {}`. Clients
154
- * discover tools with `tools/list`, as the MCP spec defines.
171
+ * @deprecated The behavior is unconditional; listing the flag changes
172
+ * nothing.
155
173
  */
156
174
  removeMcpToolsCapabilityExtension: boolean;
157
175
  /**
158
- * Whether the MCP server handler reports a `tools/call` whose arguments fail
159
- * the tool's `inputSchema` as a tool result with `isError: true`, as
160
- * MCP 2025-11-25 specifies for input validation errors.
176
+ * Retired: still accepted in `compatibilityFlags`, with no effect.
161
177
  *
162
- * Before this flag: Invalid arguments return a JSON-RPC `-32602` error.
178
+ * For every project, when the request's `MCP-Protocol-Version` header is
179
+ * `2025-11-25` or later, a `tools/call` whose arguments fail the tool's
180
+ * `inputSchema` returns a result with `isError: true` and the validation
181
+ * message as text content, and the tool is not called. Earlier or missing
182
+ * protocol versions return a JSON-RPC `-32602` error. See
183
+ * `packages/runtime/specs/mcp-json-rpc.md`, MCPRPC-19 to MCPRPC-25.
163
184
  *
164
- * After this flag: When the request's `MCP-Protocol-Version` header is
165
- * `2025-11-25` or later, invalid arguments return a result with
166
- * `isError: true` and the validation message as text content, and the tool
167
- * is not called. Earlier or missing protocol versions still return
168
- * `-32602`. Unknown tools and malformed requests return `-32602` either way.
185
+ * @deprecated The behavior is unconditional; listing the flag changes
186
+ * nothing.
169
187
  */
170
188
  returnMcpToolInputErrorsAsToolResults: boolean;
171
189
  /**
@@ -176,6 +194,56 @@ declare interface CompatibilityFlags {
176
194
  * Opt in only on the JavaScript runtimes (workerd and Zeno).
177
195
  */
178
196
  useMcpDirectSchemaValidation: boolean;
197
+ /**
198
+ * Whether the MCP server handler rewrites tool names to follow the MCP tool
199
+ * naming rule: 1 to 128 characters of `A-Z`, `a-z`, `0-9`, `_`, `-` and
200
+ * `.`, unique within the server (MCP 2025-11-25, server/tools#tool-names).
201
+ *
202
+ * Before this flag: Each tool is advertised and called by its configured
203
+ * name (`x-zuplo-route.mcp.name`, or the operationId) as is, including
204
+ * spaces, `/` and names over 128 characters. When a tool from the
205
+ * deprecated `files` option reuses the name of a tool from `operations`
206
+ * (or a content-type suffix repeats another tool's name), the later tool
207
+ * replaces the earlier one.
208
+ *
209
+ * After this flag: A name that already follows the rule is unchanged. In
210
+ * any other name, each character outside the allowed set becomes `_`, an
211
+ * empty name becomes `tool`, and the name is cut to 128 characters. A
212
+ * rewritten or repeated name that is already taken gets `_2`, `_3`, and so
213
+ * on, in registration order, still within 128 characters, so both tools
214
+ * stay. `tools/list`, `tools/call` and analytics use the advertised name,
215
+ * and `tools/call` no longer accepts the configured name of a rewritten
216
+ * tool. Two operations with the same `x-zuplo-route.mcp.name` still stop
217
+ * the server from starting, as before.
218
+ *
219
+ * The build warns about every name that breaks the rule or repeats, with or
220
+ * without this flag. Set `x-zuplo-route.mcp.name` to keep a name stable.
221
+ */
222
+ sanitizeMcpToolNames: boolean;
223
+ /**
224
+ * Whether the MCP server handler leaves out of its responses the fields
225
+ * that protocol revisions newer than the request's added.
226
+ *
227
+ * Before this flag: Every response carries every field on every protocol
228
+ * version, so a `2025-03-26` client gets `outputSchema` on `tools/list` and
229
+ * `structuredContent` on `tools/call`.
230
+ *
231
+ * After this flag: The request's `MCP-Protocol-Version` header, or
232
+ * `2025-03-26` when it is missing, decides which fields are sent:
233
+ *
234
+ * - Before `2025-06-18`: tools leave out `outputSchema` and `title`,
235
+ * resources leave out `title`, and `tools/call` results leave out
236
+ * `structuredContent` (when the result has no text block, its JSON is
237
+ * added as one). In `tools/call` and `prompts/get` content, annotations
238
+ * leave out `lastModified` and a `resource_link` block becomes a text
239
+ * block holding the link as JSON.
240
+ * - Before `2025-11-25`: tools leave out `icons` and `execution`, and
241
+ * resources and resource links leave out `icons`.
242
+ * - Before `2025-03-26`: tools also leave out `annotations`.
243
+ *
244
+ * `_meta` is sent on every version.
245
+ */
246
+ omitMcpFieldsNewerThanNegotiatedVersion: boolean;
179
247
  }
180
248
 
181
249
  /**
@@ -202,6 +270,15 @@ declare interface CorsPolicyConfiguration {
202
270
  exposeHeaders?: string[] | string;
203
271
  }
204
272
 
273
+ /**
274
+ * Says how `name` breaks the MCP tool naming rule, or returns `undefined`
275
+ * when it follows it. The reasons are customer-facing (build warnings).
276
+ * @param name - a tool name
277
+ */
278
+ export declare function describeMcpToolNameProblem(
279
+ name: string
280
+ ): string | undefined;
281
+
205
282
  /* Excluded from this release type: DevPortalRuntimeConfig */
206
283
 
207
284
  export declare type DevPortalType = "legacy" | "zudoku";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zuplo/runtime",
3
3
  "type": "module",
4
- "version": "7.12.3",
4
+ "version": "7.12.4",
5
5
  "repository": "https://github.com/zuplo/zuplo",
6
6
  "author": "Zuplo, Inc.",
7
7
  "exports": {
@@ -0,0 +1,35 @@
1
+ name: Release the package
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ semver:
7
+ description: 'Release bump type'
8
+ required: true
9
+ type: choice
10
+ options:
11
+ - patch
12
+ - minor
13
+ - major
14
+ - prepatch
15
+ - preminor
16
+ - premajor
17
+ - prerelease
18
+ preid:
19
+ description: 'Prerelease identifier (e.g. rc), used by the pre* bump types'
20
+ required: false
21
+ type: string
22
+
23
+ permissions: {}
24
+
25
+ jobs:
26
+ release:
27
+ permissions:
28
+ id-token: write # required for npm provenance via OIDC
29
+ contents: write # required to push the release commit and the tag
30
+ uses: fastify/workflows/.github/workflows/reusable-release.yml@b0a2ab2d8259b6bd574b804cd6874bbd75c3577c
31
+ with:
32
+ semver: ${{ inputs.semver }}
33
+ preid: ${{ inputs.preid }}
34
+ dist-tag: ${{ startsWith(inputs.semver, 'pre') && 'three-next' || 'three' }}
35
+ make-latest: false
@@ -14,12 +14,18 @@ All of the above functions can accept an additional options argument that is an
14
14
 
15
15
  Malformed authorities and out-of-range ports are reported through the parsed component's `error` field. `normalize()` leaves malformed string inputs unchanged, and `equal()` returns `false` when either string input is malformed.
16
16
 
17
+ Schemes are never percent-decoded. RFC 3986 does not allow percent-encoding in a scheme, so an input such as `%6Aavascript:alert(1)` is reported as malformed (`error: 'URI scheme is malformed.'`) instead of being parsed as `javascript:`. `normalize()` leaves it unchanged, `equal()` returns `false`, and `resolve()` and `serialize()` throw.
18
+
19
+ For schemes with domain hosts (`http`, `https`, `ws`, `wss`, or any scheme with the `domainHost` option), a host containing an ASCII character that RFC 3986 does not allow in a reg-name (for example `@`, TAB, LF, CR, space, `"`, `<`, `>`, `^`, `` ` ``, `{`, `|`, `}`) is reported as malformed (`error: 'URI host is malformed.'`). It is never passed through a WHATWG URL parser that could treat `@` as a delimiter or strip whitespace. `normalize()` leaves such input unchanged, `equal()` returns `false`, and `resolve()` throws.
20
+
17
21
  * `scheme` (string)
18
22
  Indicates the scheme that the URI should be treated as, overriding the URI's normal scheme parsing behavior.
19
23
 
20
24
  * `reference` (string)
21
25
  If set to `"suffix"`, it indicates that the URI is in the suffix format and the parser will use the option's `scheme` property to determine the URI's scheme.
22
26
 
27
+ A suffix reference is written without its scheme and without the `//` authority marker (RFC 3986 section 4.5). Such a reference is inherently ambiguous: an authority component cannot always be distinguished from a path. When the input carries an authority of the form `host:port` (for example `//javascript:80/x`) or a userinfo containing a colon, the serialized suffix output can begin with text that reparses as a URI scheme (for example `javascript:80/x`). Do not treat suffix output as a trusted absolute URL, and do not render it or use it in a scheme allowlist without first validating it with `parse()`. If you need an unambiguous result, use the default (non-suffix) serialization.
28
+
23
29
  * `tolerant` (boolean, false)
24
30
  If set to `true`, the parser will relax URI resolving rules.
25
31
 
@@ -79,6 +85,8 @@ uri.normalize('http://example.com/a%2Fb')
79
85
 
80
86
  Reserved path escapes such as `%2F` and `%2E` are preserved as path data during normalization and comparison.
81
87
 
88
+ Dot segments in relative references are removed without changing what the reference resolves to: leading `..` segments that cannot be collapsed are kept, a relative path is never turned into a root-relative one, and a first-segment colon exposed by the removal is kept behind a leading `./` so the reference is not reparsed as a scheme (`a/../b` → `b`, `../x` → `../x`, `x/..` → `./`, `a/../a:b` → `./a:b`).
89
+
82
90
  ### Equal
83
91
 
84
92
  ```js