@every-app/sdk 0.2.0 → 0.3.0-rc.10

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 (189) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +609 -3
  3. package/dist/cloudflare/catalogSettings.generated.d.ts +81 -0
  4. package/dist/cloudflare/catalogSettings.generated.d.ts.map +1 -0
  5. package/dist/cloudflare/catalogSettings.generated.js +174 -0
  6. package/dist/cloudflare/index.d.ts +23 -0
  7. package/dist/cloudflare/index.d.ts.map +1 -0
  8. package/dist/cloudflare/index.js +24 -0
  9. package/dist/cloudflare/sentinel.d.ts +127 -0
  10. package/dist/cloudflare/sentinel.d.ts.map +1 -0
  11. package/dist/cloudflare/sentinel.js +85 -0
  12. package/dist/cloudflare/worker.d.ts +805 -0
  13. package/dist/cloudflare/worker.d.ts.map +1 -0
  14. package/dist/cloudflare/worker.js +997 -0
  15. package/dist/dev/index.d.ts +8 -0
  16. package/dist/dev/index.d.ts.map +1 -0
  17. package/dist/dev/index.js +7 -0
  18. package/dist/dev/keypair.d.ts +26 -0
  19. package/dist/dev/keypair.d.ts.map +1 -0
  20. package/dist/dev/keypair.js +62 -0
  21. package/dist/index.d.ts +6 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +5 -0
  24. package/dist/internal/aiDefault.d.ts +204 -0
  25. package/dist/internal/aiDefault.d.ts.map +1 -0
  26. package/dist/internal/aiDefault.js +334 -0
  27. package/dist/internal/aiProviders.d.ts +72 -0
  28. package/dist/internal/aiProviders.d.ts.map +1 -0
  29. package/dist/internal/aiProviders.js +233 -0
  30. package/dist/internal/appSettings.d.ts +315 -0
  31. package/dist/internal/appSettings.d.ts.map +1 -0
  32. package/dist/internal/appSettings.js +549 -0
  33. package/dist/internal/audit.d.ts +108 -0
  34. package/dist/internal/audit.d.ts.map +1 -0
  35. package/dist/internal/audit.js +235 -0
  36. package/dist/internal/capabilities.d.ts +3174 -0
  37. package/dist/internal/capabilities.d.ts.map +1 -0
  38. package/dist/internal/capabilities.js +1110 -0
  39. package/dist/internal/catalog/commerce.d.ts +394 -0
  40. package/dist/internal/catalog/commerce.d.ts.map +1 -0
  41. package/dist/internal/catalog/commerce.js +477 -0
  42. package/dist/internal/catalog/comms.d.ts +375 -0
  43. package/dist/internal/catalog/comms.d.ts.map +1 -0
  44. package/dist/internal/catalog/comms.js +520 -0
  45. package/dist/internal/catalog/index.d.ts +1973 -0
  46. package/dist/internal/catalog/index.d.ts.map +1 -0
  47. package/dist/internal/catalog/index.js +19 -0
  48. package/dist/internal/catalog/inference.d.ts +393 -0
  49. package/dist/internal/catalog/inference.d.ts.map +1 -0
  50. package/dist/internal/catalog/inference.js +460 -0
  51. package/dist/internal/catalog/infra.d.ts +423 -0
  52. package/dist/internal/catalog/infra.d.ts.map +1 -0
  53. package/dist/internal/catalog/infra.js +543 -0
  54. package/dist/internal/catalog/search.d.ts +400 -0
  55. package/dist/internal/catalog/search.d.ts.map +1 -0
  56. package/dist/internal/catalog/search.js +463 -0
  57. package/dist/internal/devProviders.d.ts +49 -0
  58. package/dist/internal/devProviders.d.ts.map +1 -0
  59. package/dist/internal/devProviders.js +80 -0
  60. package/dist/internal/email.d.ts +280 -0
  61. package/dist/internal/email.d.ts.map +1 -0
  62. package/dist/internal/email.js +613 -0
  63. package/dist/internal/events.d.ts +193 -0
  64. package/dist/internal/events.d.ts.map +1 -0
  65. package/dist/internal/events.js +367 -0
  66. package/dist/internal/gatewaySettings.d.ts +83 -0
  67. package/dist/internal/gatewaySettings.d.ts.map +1 -0
  68. package/dist/internal/gatewaySettings.js +215 -0
  69. package/dist/internal/identity.d.ts +57 -5
  70. package/dist/internal/identity.d.ts.map +1 -1
  71. package/dist/internal/identity.js +99 -22
  72. package/dist/internal/index.d.ts +22 -1
  73. package/dist/internal/index.d.ts.map +1 -1
  74. package/dist/internal/index.js +22 -1
  75. package/dist/internal/members.d.ts +36 -0
  76. package/dist/internal/members.d.ts.map +1 -0
  77. package/dist/internal/members.js +7 -0
  78. package/dist/internal/oauthClient.d.ts +61 -0
  79. package/dist/internal/oauthClient.d.ts.map +1 -0
  80. package/dist/internal/oauthClient.js +133 -0
  81. package/dist/internal/oauthPresets.d.ts +33 -0
  82. package/dist/internal/oauthPresets.d.ts.map +1 -0
  83. package/dist/internal/oauthPresets.js +1064 -0
  84. package/dist/internal/oauthScopes.d.ts +172 -0
  85. package/dist/internal/oauthScopes.d.ts.map +1 -0
  86. package/dist/internal/oauthScopes.js +510 -0
  87. package/dist/internal/oauthSpec.d.ts +102 -0
  88. package/dist/internal/oauthSpec.d.ts.map +1 -0
  89. package/dist/internal/oauthSpec.js +789 -0
  90. package/dist/internal/organizationName.d.ts +18 -0
  91. package/dist/internal/organizationName.d.ts.map +1 -0
  92. package/dist/internal/organizationName.js +24 -0
  93. package/dist/internal/protocol.d.ts +150 -3
  94. package/dist/internal/protocol.d.ts.map +1 -1
  95. package/dist/internal/protocol.js +163 -2
  96. package/dist/internal/providerApps.d.ts +75 -0
  97. package/dist/internal/providerApps.d.ts.map +1 -0
  98. package/dist/internal/providerApps.js +59 -0
  99. package/dist/internal/providerRegistry.d.ts +218 -0
  100. package/dist/internal/providerRegistry.d.ts.map +1 -0
  101. package/dist/internal/providerRegistry.js +432 -0
  102. package/dist/internal/providerSpec.d.ts +66 -0
  103. package/dist/internal/providerSpec.d.ts.map +1 -0
  104. package/dist/internal/providerSpec.js +1154 -0
  105. package/dist/internal/remoteMcp.d.ts +188 -0
  106. package/dist/internal/remoteMcp.d.ts.map +1 -0
  107. package/dist/internal/remoteMcp.js +543 -0
  108. package/dist/internal/signInProviders.d.ts +104 -0
  109. package/dist/internal/signInProviders.d.ts.map +1 -0
  110. package/dist/internal/signInProviders.js +245 -0
  111. package/dist/internal/tools.d.ts +115 -0
  112. package/dist/internal/tools.d.ts.map +1 -0
  113. package/dist/internal/tools.js +80 -0
  114. package/dist/manifest.d.ts +238 -0
  115. package/dist/manifest.d.ts.map +1 -0
  116. package/dist/manifest.js +30 -0
  117. package/dist/server/ai.d.ts +111 -0
  118. package/dist/server/ai.d.ts.map +1 -0
  119. package/dist/server/ai.js +145 -0
  120. package/dist/server/aiBinding.d.ts +68 -0
  121. package/dist/server/aiBinding.d.ts.map +1 -0
  122. package/dist/server/aiBinding.js +294 -0
  123. package/dist/server/attribution.d.ts +43 -0
  124. package/dist/server/attribution.d.ts.map +1 -0
  125. package/dist/server/attribution.js +75 -0
  126. package/dist/server/authorizeUrl.d.ts +43 -0
  127. package/dist/server/authorizeUrl.d.ts.map +1 -0
  128. package/dist/server/authorizeUrl.js +106 -0
  129. package/dist/server/connectUrl.d.ts +21 -0
  130. package/dist/server/connectUrl.d.ts.map +1 -0
  131. package/dist/server/connectUrl.js +37 -0
  132. package/dist/server/context.d.ts +68 -0
  133. package/dist/server/context.d.ts.map +1 -0
  134. package/dist/server/context.js +117 -0
  135. package/dist/server/emailBinding.d.ts +72 -0
  136. package/dist/server/emailBinding.d.ts.map +1 -0
  137. package/dist/server/emailBinding.js +124 -0
  138. package/dist/server/emit.d.ts +63 -0
  139. package/dist/server/emit.d.ts.map +1 -0
  140. package/dist/server/emit.js +101 -0
  141. package/dist/server/env.d.ts +44 -0
  142. package/dist/server/env.d.ts.map +1 -0
  143. package/dist/server/env.js +1 -0
  144. package/dist/server/everyApp.d.ts +65 -19
  145. package/dist/server/everyApp.d.ts.map +1 -1
  146. package/dist/server/everyApp.js +195 -30
  147. package/dist/server/fromMcpTools.d.ts +89 -0
  148. package/dist/server/fromMcpTools.d.ts.map +1 -0
  149. package/dist/server/fromMcpTools.js +192 -0
  150. package/dist/server/gatewayFetch.d.ts +54 -14
  151. package/dist/server/gatewayFetch.d.ts.map +1 -1
  152. package/dist/server/gatewayFetch.js +201 -37
  153. package/dist/server/gatewayUrl.d.ts +13 -0
  154. package/dist/server/gatewayUrl.d.ts.map +1 -0
  155. package/dist/server/gatewayUrl.js +34 -0
  156. package/dist/server/index.d.ts +23 -3
  157. package/dist/server/index.d.ts.map +1 -1
  158. package/dist/server/index.js +19 -2
  159. package/dist/server/integrationFetch.d.ts +162 -0
  160. package/dist/server/integrationFetch.d.ts.map +1 -0
  161. package/dist/server/integrationFetch.js +688 -0
  162. package/dist/server/listMembers.d.ts +32 -0
  163. package/dist/server/listMembers.d.ts.map +1 -0
  164. package/dist/server/listMembers.js +71 -0
  165. package/dist/server/nodeServer.d.ts +48 -0
  166. package/dist/server/nodeServer.d.ts.map +1 -0
  167. package/dist/server/nodeServer.js +45 -0
  168. package/dist/server/refusal.d.ts +55 -0
  169. package/dist/server/refusal.d.ts.map +1 -0
  170. package/dist/server/refusal.js +193 -0
  171. package/dist/server/sendEmail.d.ts +39 -0
  172. package/dist/server/sendEmail.d.ts.map +1 -0
  173. package/dist/server/sendEmail.js +114 -0
  174. package/dist/server/tools.d.ts +184 -0
  175. package/dist/server/tools.d.ts.map +1 -0
  176. package/dist/server/tools.js +347 -0
  177. package/dist/server/toolsEndpoint.d.ts +32 -0
  178. package/dist/server/toolsEndpoint.d.ts.map +1 -0
  179. package/dist/server/toolsEndpoint.js +237 -0
  180. package/dist/tanstack-start/index.d.ts +9 -0
  181. package/dist/tanstack-start/index.d.ts.map +1 -0
  182. package/dist/tanstack-start/index.js +29 -0
  183. package/dist/testing/index.d.ts +93 -0
  184. package/dist/testing/index.d.ts.map +1 -0
  185. package/dist/testing/index.js +156 -0
  186. package/package.json +42 -8
  187. package/dist/server/mcp.d.ts +0 -66
  188. package/dist/server/mcp.d.ts.map +0 -1
  189. package/dist/server/mcp.js +0 -147
@@ -0,0 +1,184 @@
1
+ /**
2
+ * `defineTools()` — agent tools an app offers to MCP clients through the
3
+ * Every App gateway.
4
+ *
5
+ * export const tools = defineTools(
6
+ * {
7
+ * list_todos: {
8
+ * description: "List the user's todos.",
9
+ * risk: "read",
10
+ * input: z.object({}).strict(),
11
+ * handler: async (_input, { user }) => listTodos(user.id),
12
+ * },
13
+ * },
14
+ * { instructions: "Never guess todo ids; call list_todos first." },
15
+ * );
16
+ * export default everyApp(handler, { tools });
17
+ *
18
+ * Apps never speak MCP. The gateway snapshots this catalog at deploy, serves
19
+ * MCP clients from the snapshot, and calls a tool over the internal tools
20
+ * contract (../internal/tools.ts) with a verified `chan: "mcp"` identity.
21
+ *
22
+ * `input` and `output` accept any validator implementing Standard Schema and
23
+ * Standard JSON Schema (zod >= 4.2 does both), or a plain
24
+ * `{ jsonSchema, validate }` pair. The SDK itself takes no dependency.
25
+ */
26
+ import { type EveryAppUser, type ToolCallResultV1, type ToolDescriptorV1, type ToolIssueV1, type ToolRisk } from "../internal/index.js";
27
+ import type { ExecutionContextLike } from "./everyApp.js";
28
+ /** Reported with every catalog; must match package.json. */
29
+ export declare const SDK_VERSION = "0.3.0";
30
+ /**
31
+ * Throw from a tool handler to return an error the model can read and act on
32
+ * ("No todo with that id"). Any other error is logged here and reaches the
33
+ * client only as "Internal error in <app> (ref <call id>)".
34
+ */
35
+ export declare class ToolError extends Error {
36
+ constructor(message: string);
37
+ }
38
+ type StandardPathSegment = PropertyKey | {
39
+ readonly key: PropertyKey;
40
+ };
41
+ interface StandardIssue {
42
+ readonly message: string;
43
+ readonly path?: ReadonlyArray<StandardPathSegment> | undefined;
44
+ }
45
+ type StandardResult<Output> = {
46
+ readonly value: Output;
47
+ readonly issues?: undefined;
48
+ } | {
49
+ readonly issues: ReadonlyArray<StandardIssue>;
50
+ };
51
+ interface StandardSchemaProps<Input, Output> {
52
+ readonly version: 1;
53
+ readonly vendor: string;
54
+ readonly validate: (value: unknown, options?: {
55
+ readonly libraryOptions?: Record<string, unknown>;
56
+ }) => StandardResult<Output> | Promise<StandardResult<Output>>;
57
+ readonly types?: {
58
+ readonly input: Input;
59
+ readonly output: Output;
60
+ } | undefined;
61
+ }
62
+ interface StandardJsonSchemaConverter {
63
+ readonly input: (options: {
64
+ readonly target: string;
65
+ }) => Record<string, unknown>;
66
+ readonly output: (options: {
67
+ readonly target: string;
68
+ }) => Record<string, unknown>;
69
+ }
70
+ /** A Standard Schema validator that also converts to JSON Schema (zod >= 4.2). */
71
+ export interface StandardSchemaWithJSON<Input = unknown, Output = Input> {
72
+ readonly "~standard": StandardSchemaProps<Input, Output> & {
73
+ readonly jsonSchema: StandardJsonSchemaConverter;
74
+ };
75
+ }
76
+ /** For validators without Standard JSON Schema: supply the JSON Schema too. */
77
+ export interface PlainToolSchema<Output = unknown> {
78
+ jsonSchema: Record<string, unknown>;
79
+ validate(value: unknown): StandardResult<Output> | Promise<StandardResult<Output>>;
80
+ }
81
+ export type ToolSchema<Output = unknown> = StandardSchemaWithJSON<unknown, Output> | PlainToolSchema<Output>;
82
+ /** What a tool handler receives besides its validated input. */
83
+ export interface ToolContext<TEnv = Cloudflare.Env> {
84
+ /** The verified caller. `channel` is "mcp"; `toolCall` names this call. */
85
+ user: EveryAppUser;
86
+ env: TEnv;
87
+ ctx: ExecutionContextLike;
88
+ request: Request;
89
+ /** Unique id of this call; also the ref in masked error messages. */
90
+ callId: string;
91
+ }
92
+ export interface ToolDefinition<TInput = unknown> {
93
+ /** Short human-readable name clients may show. */
94
+ title?: string;
95
+ /** What the tool does and when to use it. The model reads this. */
96
+ description: string;
97
+ /**
98
+ * `read` changes nothing. `write` creates or changes data. `destructive`
99
+ * deletes or irreversibly changes data; AI clients can't see or call
100
+ * destructive tools until approvals exist.
101
+ */
102
+ risk: ToolRisk;
103
+ /** Arguments schema; must describe an object. */
104
+ input: ToolSchema<TInput>;
105
+ /**
106
+ * Result schema; must describe an object. The result is validated and
107
+ * also sent as MCP structured content.
108
+ */
109
+ output?: ToolSchema;
110
+ /** Repeating a call with the same arguments has no further effect. */
111
+ idempotent?: boolean;
112
+ /** The tool reaches systems outside this app (other APIs, the web). */
113
+ openWorld?: boolean;
114
+ /**
115
+ * Return a string (sent as text), a JSON-serializable value (sent as a
116
+ * JSON text block), or {@link toolResult} for text and data together.
117
+ * Throw {@link ToolError} for errors the model may see.
118
+ */
119
+ handler: (input: TInput, context: ToolContext) => unknown;
120
+ }
121
+ declare const TOOL_RESULT: unique symbol;
122
+ /** What {@link toolResult} returns; a handler returns it as is. */
123
+ export interface ToolResult {
124
+ readonly [TOOL_RESULT]: true;
125
+ readonly text: string;
126
+ readonly structured: Record<string, unknown>;
127
+ }
128
+ /**
129
+ * Return a written result and the same result as data. The model reads
130
+ * `text` (a summary, a table); clients also get `structured`, checked
131
+ * against the tool's `output` schema. Without this, a tool with an `output`
132
+ * schema sends its value as JSON text.
133
+ */
134
+ export declare function toolResult(result: {
135
+ text: string;
136
+ structured: Record<string, unknown>;
137
+ }): ToolResult;
138
+ export interface DefineToolsOptions {
139
+ /** Guidance for the model that spans this app's tools (at most 2 KB). */
140
+ instructions?: string;
141
+ }
142
+ /** Returned by {@link defineTools}; pass it to `everyApp(…, { tools })`. */
143
+ export interface ToolSet {
144
+ /** Tool names, sorted. */
145
+ readonly names: readonly string[];
146
+ }
147
+ export interface ToolCatalog {
148
+ instructions?: string;
149
+ tools: ToolDescriptorV1[];
150
+ hash: string;
151
+ /** Tools left out because they can't be described, and why. */
152
+ warnings: string[];
153
+ }
154
+ interface ToolSetInternals {
155
+ tool(name: string): ToolDefinition | undefined;
156
+ /** Descriptors and hash, computed once per isolate. */
157
+ catalog(): Promise<ToolCatalog>;
158
+ }
159
+ /** @internal The everyApp() side of a tool set. */
160
+ export declare function toolSetInternals(toolSet: ToolSet): ToolSetInternals;
161
+ /**
162
+ * Define an app's agent tools. Names are lowercase snake_case (at most 48
163
+ * characters); the gateway prefixes them with the app id where several apps
164
+ * share one MCP endpoint. Handler inputs are typed from each `input` schema.
165
+ */
166
+ export declare function defineTools<TInputs extends Record<string, unknown>>(tools: {
167
+ [K in keyof TInputs]: ToolDefinition<TInputs[K]>;
168
+ }, options?: DefineToolsOptions): ToolSet;
169
+ export type ValidationOutcome<T> = {
170
+ ok: true;
171
+ value: T;
172
+ } | {
173
+ ok: false;
174
+ issues: ToolIssueV1[];
175
+ };
176
+ /** Run a tool schema's validator. */
177
+ export declare function validateWithSchema<T>(schema: ToolSchema<T>, value: unknown): Promise<ValidationOutcome<T>>;
178
+ /**
179
+ * Turn a handler's return value into a tool result. With an output schema,
180
+ * the value must validate and is sent as structured content as well as text.
181
+ */
182
+ export declare function toToolResult(definition: ToolDefinition, value: unknown): Promise<ToolCallResultV1>;
183
+ export {};
184
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/server/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,347 @@
1
+ /**
2
+ * `defineTools()` — agent tools an app offers to MCP clients through the
3
+ * Every App gateway.
4
+ *
5
+ * export const tools = defineTools(
6
+ * {
7
+ * list_todos: {
8
+ * description: "List the user's todos.",
9
+ * risk: "read",
10
+ * input: z.object({}).strict(),
11
+ * handler: async (_input, { user }) => listTodos(user.id),
12
+ * },
13
+ * },
14
+ * { instructions: "Never guess todo ids; call list_todos first." },
15
+ * );
16
+ * export default everyApp(handler, { tools });
17
+ *
18
+ * Apps never speak MCP. The gateway snapshots this catalog at deploy, serves
19
+ * MCP clients from the snapshot, and calls a tool over the internal tools
20
+ * contract (../internal/tools.ts) with a verified `chan: "mcp"` identity.
21
+ *
22
+ * `input` and `output` accept any validator implementing Standard Schema and
23
+ * Standard JSON Schema (zod >= 4.2 does both), or a plain
24
+ * `{ jsonSchema, validate }` pair. The SDK itself takes no dependency.
25
+ */
26
+ import { TOOL_NAME_PATTERN, catalogHash, isToolRisk, } from "../internal/index.js";
27
+ /** Reported with every catalog; must match package.json. */
28
+ export const SDK_VERSION = "0.3.0";
29
+ const JSON_SCHEMA_TARGET = "draft-2020-12";
30
+ const DRAFT_2020_12 = "https://json-schema.org/draft/2020-12/schema";
31
+ // The 2026-07-28 MCP revision lets a schema property ask clients to mirror an
32
+ // argument into an HTTP header. Apps never route on headers, and the gateway
33
+ // fronts many apps, so the hint is never passed on.
34
+ const MCP_HEADER_KEYWORD = "x-mcp-header";
35
+ /**
36
+ * Throw from a tool handler to return an error the model can read and act on
37
+ * ("No todo with that id"). Any other error is logged here and reaches the
38
+ * client only as "Internal error in <app> (ref <call id>)".
39
+ */
40
+ export class ToolError extends Error {
41
+ constructor(message) {
42
+ super(message);
43
+ this.name = "ToolError";
44
+ }
45
+ }
46
+ const TOOL_RESULT = Symbol.for("everyapp.toolResult");
47
+ /**
48
+ * Return a written result and the same result as data. The model reads
49
+ * `text` (a summary, a table); clients also get `structured`, checked
50
+ * against the tool's `output` schema. Without this, a tool with an `output`
51
+ * schema sends its value as JSON text.
52
+ */
53
+ export function toolResult(result) {
54
+ return {
55
+ [TOOL_RESULT]: true,
56
+ text: result.text,
57
+ structured: result.structured,
58
+ };
59
+ }
60
+ function isToolResult(value) {
61
+ return (isRecord(value) && value[TOOL_RESULT] === true);
62
+ }
63
+ const internals = new WeakMap();
64
+ /** @internal The everyApp() side of a tool set. */
65
+ export function toolSetInternals(toolSet) {
66
+ const found = internals.get(toolSet);
67
+ if (!found) {
68
+ throw new TypeError("tools must be the value returned by defineTools()");
69
+ }
70
+ return found;
71
+ }
72
+ /**
73
+ * Define an app's agent tools. Names are lowercase snake_case (at most 48
74
+ * characters); the gateway prefixes them with the app id where several apps
75
+ * share one MCP endpoint. Handler inputs are typed from each `input` schema.
76
+ */
77
+ export function defineTools(tools, options = {}) {
78
+ const definitions = new Map();
79
+ for (const name of Object.keys(tools).sort()) {
80
+ const definition = tools[name];
81
+ assertToolDefinition(name, definition);
82
+ definitions.set(name, definition);
83
+ }
84
+ if (options.instructions !== undefined &&
85
+ typeof options.instructions !== "string") {
86
+ throw new TypeError("defineTools: instructions must be a string");
87
+ }
88
+ let catalog;
89
+ const toolSet = Object.freeze({
90
+ names: Object.freeze([...definitions.keys()]),
91
+ });
92
+ internals.set(toolSet, {
93
+ tool: (name) => definitions.get(name),
94
+ catalog: () => {
95
+ catalog ??= buildCatalog(definitions, options.instructions).catch((error) => {
96
+ catalog = undefined;
97
+ throw error;
98
+ });
99
+ return catalog;
100
+ },
101
+ });
102
+ return toolSet;
103
+ }
104
+ function assertToolDefinition(name, definition) {
105
+ const problem = (message) => new TypeError(`defineTools: tool "${name}" ${message}`);
106
+ if (!TOOL_NAME_PATTERN.test(name)) {
107
+ throw problem("must be named in lowercase snake_case: a letter, then letters, digits or _ (at most 48 characters)");
108
+ }
109
+ if (!definition || typeof definition !== "object") {
110
+ throw problem("must be an object");
111
+ }
112
+ if (typeof definition.description !== "string" ||
113
+ !definition.description.trim()) {
114
+ throw problem("needs a description");
115
+ }
116
+ if (!isToolRisk(definition.risk)) {
117
+ throw problem('needs a risk: "read", "write" or "destructive"');
118
+ }
119
+ if (!isToolSchema(definition.input)) {
120
+ throw problem("input must be a Standard Schema with JSON Schema support (zod >= 4.2) or { jsonSchema, validate }");
121
+ }
122
+ if (definition.output !== undefined && !isToolSchema(definition.output)) {
123
+ throw problem("output must be a Standard Schema with JSON Schema support (zod >= 4.2) or { jsonSchema, validate }");
124
+ }
125
+ if (typeof definition.handler !== "function") {
126
+ throw problem("needs a handler function");
127
+ }
128
+ if (definition.title !== undefined && typeof definition.title !== "string") {
129
+ throw problem("title must be a string");
130
+ }
131
+ for (const flag of ["idempotent", "openWorld"]) {
132
+ if (definition[flag] !== undefined &&
133
+ typeof definition[flag] !== "boolean") {
134
+ throw problem(`${flag} must be a boolean`);
135
+ }
136
+ }
137
+ }
138
+ function isRecord(value) {
139
+ return ((typeof value === "object" || typeof value === "function") && value !== null);
140
+ }
141
+ function isPlainToolSchema(value) {
142
+ return (isRecord(value) &&
143
+ !("~standard" in value) &&
144
+ isRecord(value.jsonSchema) &&
145
+ typeof value.validate === "function");
146
+ }
147
+ function isStandardWithJson(value) {
148
+ if (!isRecord(value))
149
+ return false;
150
+ const standard = value["~standard"];
151
+ if (!isRecord(standard) || typeof standard.validate !== "function") {
152
+ return false;
153
+ }
154
+ const converter = standard.jsonSchema;
155
+ return (isRecord(converter) &&
156
+ typeof converter.input === "function" &&
157
+ typeof converter.output === "function");
158
+ }
159
+ function isToolSchema(value) {
160
+ return isStandardWithJson(value) || isPlainToolSchema(value);
161
+ }
162
+ /**
163
+ * Describe every tool that can be described. A tool whose schema has no
164
+ * object JSON Schema form is left out with a warning (logged here, and
165
+ * reported to the gateway so the deploy prints it) instead of taking the
166
+ * app's other tools down with it.
167
+ */
168
+ async function buildCatalog(definitions, instructions) {
169
+ const tools = [];
170
+ const warnings = [];
171
+ for (const [name, definition] of definitions) {
172
+ const described = describeTool(name, definition);
173
+ if (typeof described === "string") {
174
+ warnings.push(`${name}: skipped, ${described}`);
175
+ console.warn(`[everyapp] defineTools: tool "${name}" ${described}`);
176
+ }
177
+ else {
178
+ tools.push(described);
179
+ }
180
+ }
181
+ return {
182
+ ...(instructions !== undefined ? { instructions } : {}),
183
+ tools,
184
+ hash: await catalogHash({ instructions, tools }),
185
+ warnings,
186
+ };
187
+ }
188
+ /** A tool's descriptor, or why it can't be described. */
189
+ function describeTool(name, definition) {
190
+ const inputSchema = objectJsonSchema(definition.input, "input");
191
+ if (typeof inputSchema === "string")
192
+ return inputSchema;
193
+ const outputSchema = definition.output
194
+ ? objectJsonSchema(definition.output, "output")
195
+ : undefined;
196
+ if (typeof outputSchema === "string")
197
+ return outputSchema;
198
+ const annotations = {
199
+ ...(definition.idempotent !== undefined
200
+ ? { idempotentHint: definition.idempotent }
201
+ : {}),
202
+ ...(definition.openWorld !== undefined
203
+ ? { openWorldHint: definition.openWorld }
204
+ : {}),
205
+ };
206
+ return {
207
+ name,
208
+ ...(definition.title ? { title: definition.title } : {}),
209
+ description: definition.description,
210
+ risk: definition.risk,
211
+ inputSchema,
212
+ ...(outputSchema ? { outputSchema } : {}),
213
+ ...(Object.keys(annotations).length > 0 ? { annotations } : {}),
214
+ };
215
+ }
216
+ /**
217
+ * The JSON Schema for one side of a tool: the arguments a client sends
218
+ * (`input`) or the result it receives (`output`), or why there is none.
219
+ *
220
+ * Both sides must describe objects. Unions of objects (zod's `union` and
221
+ * `discriminatedUnion`) come out as a root `anyOf`/`oneOf` without a `type`,
222
+ * so like the MCP SDK this adds `type: "object"` to a typeless input root
223
+ * (MCP arguments are always an object) and to a typeless output root whose
224
+ * every branch is an object.
225
+ */
226
+ function objectJsonSchema(schema, side) {
227
+ let raw;
228
+ try {
229
+ raw = isPlainToolSchema(schema)
230
+ ? schema.jsonSchema
231
+ : schema["~standard"].jsonSchema[side]({ target: JSON_SCHEMA_TARGET });
232
+ // A JSON round trip copies the schema and drops anything JSON can't carry.
233
+ raw = JSON.parse(JSON.stringify(raw));
234
+ }
235
+ catch (error) {
236
+ return `${side} has no JSON Schema form: ${error.message}`;
237
+ }
238
+ if (!isRecord(raw) || Array.isArray(raw)) {
239
+ return `${side} has no JSON Schema form`;
240
+ }
241
+ const copy = withoutMcpHeaders(raw);
242
+ if (copy.$schema === DRAFT_2020_12)
243
+ delete copy.$schema;
244
+ if (copy.type === undefined &&
245
+ (side === "input" || isProvablyObjectShaped(copy))) {
246
+ return { type: "object", ...copy };
247
+ }
248
+ if (copy.type !== "object") {
249
+ return `${side} must describe an object (JSON Schema type "object")`;
250
+ }
251
+ return copy;
252
+ }
253
+ /**
254
+ * A typeless schema that can only match objects: it has object keywords, or
255
+ * every branch of its `oneOf`/`anyOf`/`allOf` is an object. `$ref` is not
256
+ * followed.
257
+ */
258
+ function isProvablyObjectShaped(schema) {
259
+ if ([
260
+ "properties",
261
+ "patternProperties",
262
+ "additionalProperties",
263
+ "required",
264
+ ].some((keyword) => keyword in schema)) {
265
+ return true;
266
+ }
267
+ for (const keyword of ["oneOf", "anyOf", "allOf"]) {
268
+ const branches = schema[keyword];
269
+ if (Array.isArray(branches) && branches.length > 0) {
270
+ return branches.every((branch) => isRecord(branch) &&
271
+ (branch.type === "object" || isProvablyObjectShaped(branch)));
272
+ }
273
+ }
274
+ return false;
275
+ }
276
+ function withoutMcpHeaders(value) {
277
+ if (Array.isArray(value))
278
+ return value.map(withoutMcpHeaders);
279
+ if (!isRecord(value))
280
+ return value;
281
+ const out = {};
282
+ for (const [key, member] of Object.entries(value)) {
283
+ if (key !== MCP_HEADER_KEYWORD)
284
+ out[key] = withoutMcpHeaders(member);
285
+ }
286
+ return out;
287
+ }
288
+ /** Run a tool schema's validator. */
289
+ export async function validateWithSchema(schema, value) {
290
+ const result = isPlainToolSchema(schema)
291
+ ? await schema.validate(value)
292
+ : await schema["~standard"].validate(value);
293
+ if (result.issues) {
294
+ return { ok: false, issues: result.issues.map(toIssue) };
295
+ }
296
+ return { ok: true, value: result.value };
297
+ }
298
+ function toIssue(issue) {
299
+ const path = (issue.path ?? [])
300
+ .map((segment) => typeof segment === "object" && segment !== null ? segment.key : segment)
301
+ .filter((key) => typeof key === "string" || typeof key === "number");
302
+ return {
303
+ message: String(issue.message),
304
+ ...(path.length > 0 ? { path } : {}),
305
+ };
306
+ }
307
+ /**
308
+ * Turn a handler's return value into a tool result. With an output schema,
309
+ * the value must validate and is sent as structured content as well as text.
310
+ */
311
+ export async function toToolResult(definition, value) {
312
+ if (isToolResult(value)) {
313
+ const structured = definition.output
314
+ ? (await toToolResult(definition, value.structured)).structuredContent
315
+ : value.structured;
316
+ if (!isRecord(structured) || Array.isArray(structured)) {
317
+ throw new Error("structured results must be JSON objects");
318
+ }
319
+ return {
320
+ content: [{ type: "text", text: value.text }],
321
+ structuredContent: structured,
322
+ };
323
+ }
324
+ if (definition.output) {
325
+ const checked = await validateWithSchema(definition.output, value);
326
+ if (!checked.ok) {
327
+ throw new Error(`result does not match the output schema: ${checked.issues
328
+ .map((issue) => issue.message)
329
+ .join("; ")}`);
330
+ }
331
+ if (!isRecord(checked.value) ||
332
+ Array.isArray(checked.value) ||
333
+ typeof checked.value === "function") {
334
+ throw new Error("structured results must be JSON objects");
335
+ }
336
+ return {
337
+ content: [{ type: "text", text: JSON.stringify(checked.value) }],
338
+ structuredContent: checked.value,
339
+ };
340
+ }
341
+ if (typeof value === "string") {
342
+ return { content: [{ type: "text", text: value }] };
343
+ }
344
+ if (value === undefined)
345
+ return { content: [] };
346
+ return { content: [{ type: "text", text: JSON.stringify(value) }] };
347
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The app side of the internal tools contract (../internal/tools.ts).
3
+ *
4
+ * `everyApp()` answers the two reserved paths here, before any app code runs
5
+ * and whether or not the app defines tools:
6
+ *
7
+ * - `/__everyapp/tools/list` needs the gateway's system token for this app
8
+ * (purpose "tools.list"). It describes tools; it never runs them.
9
+ * - `/__everyapp/tools/call` needs an identity token minted for this exact
10
+ * call: `chan: "mcp"` plus a `tc` claim naming the tool and call id. The
11
+ * token's scopes must include the scope the tool's risk requires; `*` does
12
+ * not count, because the ToolBus only ever mints explicit scopes.
13
+ *
14
+ * The perimeter also refuses these paths from outside and strips inbound
15
+ * `x-everyapp-*` headers, so only the gateway's ToolBus ever reaches them.
16
+ */
17
+ import { type RequestIdentityOptions } from "../internal/index.js";
18
+ import type { ExecutionContextLike } from "./everyApp.js";
19
+ import { type ToolSet } from "./tools.js";
20
+ export interface ToolsEndpointOptions {
21
+ toolSet?: ToolSet;
22
+ /** This app's id, for the masked-error label. */
23
+ appId: string;
24
+ /** How to verify gateway-minted tokens (keys, issuer, dev opt-in). */
25
+ identity: RequestIdentityOptions;
26
+ }
27
+ /**
28
+ * Answer a request to the reserved tools paths, or return null for any other
29
+ * path so the app's own handler runs.
30
+ */
31
+ export declare function handleToolsRequest(request: Request, env: unknown, ctx: ExecutionContextLike, options: ToolsEndpointOptions): Promise<Response | null>;
32
+ //# sourceMappingURL=toolsEndpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolsEndpoint.d.ts","sourceRoot":"","sources":["../../src/server/toolsEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAcL,KAAK,sBAAsB,EAO5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAOL,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,QAAQ,EAAE,sBAAsB,CAAC;CAClC;AAoFD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,oBAAoB,EACzB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAyB1B"}