orpc-fn 0.7.0 → 0.9.0
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/README.md +66 -28
- package/dist/assemble-procedure.d.ts.map +1 -1
- package/dist/assemble-procedure.js +3 -1
- package/dist/assemble-procedure.js.map +1 -1
- package/dist/client.d.ts +13 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +21 -1
- package/dist/client.js.map +1 -1
- package/dist/create-fn.d.ts +63 -5
- package/dist/create-fn.d.ts.map +1 -1
- package/dist/create-fn.js +45 -16
- package/dist/create-fn.js.map +1 -1
- package/dist/expected-client-error.d.ts +6 -0
- package/dist/expected-client-error.d.ts.map +1 -1
- package/dist/expected-client-error.js +16 -0
- package/dist/expected-client-error.js.map +1 -1
- package/dist/hono.d.ts +44 -22
- package/dist/hono.d.ts.map +1 -1
- package/dist/hono.js +51 -20
- package/dist/hono.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/issues.d.ts +12 -0
- package/dist/issues.d.ts.map +1 -0
- package/dist/issues.js +22 -0
- package/dist/issues.js.map +1 -0
- package/dist/json-schema.d.ts +3 -6
- package/dist/json-schema.d.ts.map +1 -1
- package/dist/json-schema.js +12 -7
- package/dist/json-schema.js.map +1 -1
- package/dist/live/codec.d.ts +2 -0
- package/dist/live/codec.d.ts.map +1 -1
- package/dist/live/codec.js +21 -16
- package/dist/live/codec.js.map +1 -1
- package/dist/live/fn-live.d.ts +6 -19
- package/dist/live/fn-live.d.ts.map +1 -1
- package/dist/live/fn-live.js +15 -23
- package/dist/live/fn-live.js.map +1 -1
- package/dist/live/index.d.ts +2 -2
- package/dist/live/index.d.ts.map +1 -1
- package/dist/live/index.js +1 -1
- package/dist/live/index.js.map +1 -1
- package/dist/live/memory.d.ts +11 -1
- package/dist/live/memory.d.ts.map +1 -1
- package/dist/live/memory.js +14 -1
- package/dist/live/memory.js.map +1 -1
- package/dist/live/pub-sub.d.ts +50 -8
- package/dist/live/pub-sub.d.ts.map +1 -1
- package/dist/live/pub-sub.js +79 -26
- package/dist/live/pub-sub.js.map +1 -1
- package/dist/live/redis-bun.d.ts +6 -1
- package/dist/live/redis-bun.d.ts.map +1 -1
- package/dist/live/redis-bun.js +10 -1
- package/dist/live/redis-bun.js.map +1 -1
- package/dist/live/scoped-change-bus.d.ts +3 -1
- package/dist/live/scoped-change-bus.d.ts.map +1 -1
- package/dist/live/scoped-change-bus.js +3 -0
- package/dist/live/scoped-change-bus.js.map +1 -1
- package/dist/mastra.d.ts +16 -3
- package/dist/mastra.d.ts.map +1 -1
- package/dist/mastra.js +15 -3
- package/dist/mastra.js.map +1 -1
- package/dist/mcp/core.d.ts +31 -14
- package/dist/mcp/core.d.ts.map +1 -1
- package/dist/mcp/core.js +39 -20
- package/dist/mcp/core.js.map +1 -1
- package/dist/mcp/sdk.d.ts +6 -2
- package/dist/mcp/sdk.d.ts.map +1 -1
- package/dist/mcp/sdk.js +9 -3
- package/dist/mcp/sdk.js.map +1 -1
- package/dist/mcp/server.d.ts +6 -2
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +9 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp.d.ts +3 -7
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +4 -6
- package/dist/mcp.js.map +1 -1
- package/dist/meta.d.ts +14 -2
- package/dist/meta.d.ts.map +1 -1
- package/dist/meta.js +6 -2
- package/dist/meta.js.map +1 -1
- package/dist/otel.d.ts +16 -4
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +40 -10
- package/dist/otel.js.map +1 -1
- package/dist/react.d.ts +6 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +5 -1
- package/dist/react.js.map +1 -1
- package/dist/route-options.d.ts.map +1 -1
- package/dist/route-options.js +4 -0
- package/dist/route-options.js.map +1 -1
- package/dist/stream-call.d.ts +15 -0
- package/dist/stream-call.d.ts.map +1 -0
- package/dist/stream-call.js +13 -0
- package/dist/stream-call.js.map +1 -0
- package/dist/timing.d.ts +2 -0
- package/dist/timing.d.ts.map +1 -1
- package/dist/timing.js +2 -0
- package/dist/timing.js.map +1 -1
- package/dist/tool-errors.d.ts +24 -0
- package/dist/tool-errors.d.ts.map +1 -0
- package/dist/tool-errors.js +36 -0
- package/dist/tool-errors.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vue.d.ts +47 -4
- package/dist/vue.d.ts.map +1 -1
- package/dist/vue.js +39 -9
- package/dist/vue.js.map +1 -1
- package/package.json +2 -2
- package/src/assemble-procedure.ts +3 -1
- package/src/client.ts +26 -2
- package/src/create-fn.ts +149 -19
- package/src/expected-client-error.ts +19 -0
- package/src/hono.ts +120 -41
- package/src/index.ts +3 -2
- package/src/issues.ts +35 -0
- package/src/json-schema.ts +16 -10
- package/src/live/codec.ts +21 -19
- package/src/live/fn-live.ts +18 -36
- package/src/live/index.ts +2 -2
- package/src/live/memory.ts +22 -1
- package/src/live/pub-sub.ts +142 -37
- package/src/live/redis-bun.ts +23 -2
- package/src/live/scoped-change-bus.ts +10 -1
- package/src/mastra.ts +25 -6
- package/src/mcp/core.ts +76 -29
- package/src/mcp/sdk.ts +27 -2
- package/src/mcp/server.ts +27 -2
- package/src/mcp.ts +5 -16
- package/src/meta.ts +28 -4
- package/src/otel.ts +41 -9
- package/src/react.ts +10 -3
- package/src/route-options.ts +8 -0
- package/src/stream-call.ts +15 -0
- package/src/timing.ts +3 -0
- package/src/tool-errors.ts +52 -0
- package/src/types.ts +2 -0
- package/src/vue.ts +92 -19
package/dist/live/redis-bun.js
CHANGED
|
@@ -8,11 +8,12 @@ import { createRedisTransport } from './redis.js';
|
|
|
8
8
|
* Call `close()` on shutdown to close the subscriber connection it created.
|
|
9
9
|
*/
|
|
10
10
|
export function bunRedisTransport(client, options = {}) {
|
|
11
|
+
const openSubscriber = subscriberSource(client, options.subscriber);
|
|
11
12
|
return createRedisTransport({
|
|
12
13
|
send: (command, args) => client.send(command, args),
|
|
13
14
|
async connectSubscriber(handlers) {
|
|
14
15
|
const owned = !options.subscriber;
|
|
15
|
-
const subscriber =
|
|
16
|
+
const subscriber = await openSubscriber();
|
|
16
17
|
const dispatch = (message, channel) => handlers.onMessage(channel, message);
|
|
17
18
|
const ours = new Set();
|
|
18
19
|
// Bun reconnects on its own but drops every subscription. Also fires on
|
|
@@ -55,4 +56,12 @@ export function bunRedisTransport(client, options = {}) {
|
|
|
55
56
|
}
|
|
56
57
|
});
|
|
57
58
|
}
|
|
59
|
+
function subscriberSource(client, given) {
|
|
60
|
+
if (given)
|
|
61
|
+
return async () => given;
|
|
62
|
+
const { duplicate } = client;
|
|
63
|
+
if (typeof duplicate !== 'function')
|
|
64
|
+
throw new TypeError('orpc-fn: bunRedisTransport needs a client with duplicate() or a subscriber');
|
|
65
|
+
return () => duplicate.call(client);
|
|
66
|
+
}
|
|
58
67
|
//# sourceMappingURL=redis-bun.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis-bun.js","sourceRoot":"","sources":["../../src/live/redis-bun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"redis-bun.js","sourceRoot":"","sources":["../../src/live/redis-bun.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRedisTransport } from './redis.js'\n\ntype Listener = (message: string, channel: string) => void\n\n/** The part of Bun's `RedisClient` this transport uses. */\nexport interface BunRedisClientLike {\n\tsend(command: string, args: string[]): Promise<unknown>\n\tsubscribe(channel: string, listener: Listener): Promise<unknown>\n\tunsubscribe(channel: string, listener?: Listener): Promise<unknown>\n\tduplicate(): Promise<BunRedisClientLike>\n\tclose(): void\n\t/** Bun's `RedisClient.connected`; read by `stats()` when present. */\n\treadonly connected?: boolean\n\tonconnect: ((this: never) => void) | null\n\tonclose: ((this: never, error: Error) => void) | null\n}\n\n/**\n * What the command client must offer: `send`, and `duplicate` unless a\n * `subscriber` is given. A wrapper with timeouts around Bun's client fits.\n */\nexport type BunRedisCommandClientLike = Pick<BunRedisClientLike, 'send'> &\n\tPartial<Pick<BunRedisClientLike, 'duplicate'>>\n\n/**\n * `PubSubTransport` for Bun's built-in `RedisClient`. Subscriptions use a\n * dedicated connection (`client.duplicate()` unless `subscriber` is given)\n * that re-subscribes its channels after every reconnect; configure retries on\n * the client (`maxRetries`) since the duplicate copies its options.\n *\n * Call `close()` on shutdown to close the subscriber connection it created.\n */\nexport function bunRedisTransport(\n\tclient: BunRedisCommandClientLike,\n\toptions: { subscriber?: BunRedisClientLike } = {}\n) {\n\tconst openSubscriber = subscriberSource(client, options.subscriber)\n\treturn createRedisTransport({\n\t\tsend: (command, args) => client.send(command, args),\n\t\tasync connectSubscriber(handlers) {\n\t\t\tconst owned = !options.subscriber\n\t\t\tconst subscriber = await openSubscriber()\n\t\t\tconst dispatch: Listener = (message, channel) =>\n\t\t\t\thandlers.onMessage(channel, message)\n\t\t\tconst ours = new Set<string>()\n\t\t\t// Bun reconnects on its own but drops every subscription. Also fires on\n\t\t\t// the first connect, when there is nothing to restore yet.\n\t\t\tsubscriber.onconnect = () => handlers.onReconnect()\n\t\t\t// Fires only when Bun gives up reconnecting (and on close(), which\n\t\t\t// detaches it first).\n\t\t\tsubscriber.onclose = (error) =>\n\t\t\t\thandlers.onLost(error ?? new Error('Redis subscriber closed'))\n\t\t\treturn {\n\t\t\t\tsubscribe: (channel) => {\n\t\t\t\t\tours.add(channel)\n\t\t\t\t\treturn subscriber.subscribe(channel, dispatch)\n\t\t\t\t},\n\t\t\t\t// Bun keeps listeners across a reconnect and does not dedupe them, so\n\t\t\t\t// clear the channel before adding its listener again. unsubscribe\n\t\t\t\t// throws synchronously outside subscriber mode.\n\t\t\t\tresubscribe: async (channel) => {\n\t\t\t\t\tawait Promise.resolve()\n\t\t\t\t\t\t.then(() => subscriber.unsubscribe(channel))\n\t\t\t\t\t\t.catch(() => {})\n\t\t\t\t\treturn subscriber.subscribe(channel, dispatch)\n\t\t\t\t},\n\t\t\t\tunsubscribe: (channel) => {\n\t\t\t\t\tours.delete(channel)\n\t\t\t\t\treturn subscriber.unsubscribe(channel, dispatch)\n\t\t\t\t},\n\t\t\t\tconnected: () => subscriber.connected !== false,\n\t\t\t\tclose() {\n\t\t\t\t\t// No-ops, not null: Bun calls `onclose` without checking it.\n\t\t\t\t\tsubscriber.onconnect = () => {}\n\t\t\t\t\tsubscriber.onclose = () => {}\n\t\t\t\t\tif (owned) return subscriber.close()\n\t\t\t\t\t// A given subscriber stays open: remove only this transport's listeners.\n\t\t\t\t\treturn Promise.all(\n\t\t\t\t\t\t[...ours].map((channel) =>\n\t\t\t\t\t\t\tPromise.resolve()\n\t\t\t\t\t\t\t\t.then(() => subscriber.unsubscribe(channel, dispatch))\n\t\t\t\t\t\t\t\t.catch(() => {})\n\t\t\t\t\t\t)\n\t\t\t\t\t).then(() => {})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction subscriberSource(\n\tclient: BunRedisCommandClientLike,\n\tgiven: BunRedisClientLike | undefined\n): () => Promise<BunRedisClientLike> {\n\tif (given) return async () => given\n\tconst { duplicate } = client\n\tif (typeof duplicate !== 'function')\n\t\tthrow new TypeError(\n\t\t\t'orpc-fn: bunRedisTransport needs a client with duplicate() or a subscriber'\n\t\t)\n\treturn () => duplicate.call(client)\n}\n"]}
|
|
@@ -29,6 +29,8 @@ declare const noInput: z.ZodObject<{}, z.core.$strip>;
|
|
|
29
29
|
* subscriber in a scope "something changed". Each bus then names only its
|
|
30
30
|
* channel prefix: events go to `${prefix}:${scope}`. Publishing is safe by
|
|
31
31
|
* default (`safePublish: true`), because buses publish after committed writes.
|
|
32
|
+
* The scope is the access decision (a subscriber hears only its own scope),
|
|
33
|
+
* so `authFn` defaults to `true`.
|
|
32
34
|
*
|
|
33
35
|
* ```ts
|
|
34
36
|
* const defineChangeBus = defineScopedChangeBus(createPubSub, {
|
|
@@ -43,7 +45,7 @@ declare const noInput: z.ZodObject<{}, z.core.$strip>;
|
|
|
43
45
|
* // fnLive({ live: { channel: dealChanges.channel, ... } }) shares the channel.
|
|
44
46
|
* ```
|
|
45
47
|
*/
|
|
46
|
-
export declare function defineScopedChangeBus<TDef extends FnDefinition, TScopeEvent>(createPubSub: CreatePubSub<TDef>, scope: ChangeBusScope<AnyFnContext<TDef>, TScopeEvent>): <TEventSchema extends ZodType<TScopeEvent>, TInputSchema extends ObjectSchema = typeof noInput, TKey extends ProcedureKey<TDef> = TDef['default']>(options: Omit<PubSubOptions<TDef, TInputSchema, TEventSchema, NoInfer<TKey>>, 'channel' | 'inputSchema'> & GuardOptions<TDef['guards']> & Pick<FnRouteOptions<TDef, TKey, z.output<TInputSchema>>, 'meta' | 'guardResolvers'> & ProcedureOption<TDef, TKey> & {
|
|
48
|
+
export declare function defineScopedChangeBus<TDef extends FnDefinition, TScopeEvent>(createPubSub: CreatePubSub<TDef>, scope: ChangeBusScope<AnyFnContext<TDef>, TScopeEvent>): <TEventSchema extends ZodType<TScopeEvent>, TInputSchema extends ObjectSchema = typeof noInput, TKey extends ProcedureKey<TDef> = TDef['default']>(options: Omit<PubSubOptions<TDef, TInputSchema, TEventSchema, NoInfer<TKey>>, 'channel' | 'inputSchema' | 'authFn'> & Partial<Pick<PubSubOptions<TDef, TInputSchema, TEventSchema, NoInfer<TKey>>, 'authFn'>> & GuardOptions<TDef['guards']> & Pick<FnRouteOptions<TDef, TKey, z.output<TInputSchema>>, 'meta' | 'guardResolvers'> & ProcedureOption<TDef, TKey> & {
|
|
47
49
|
/** Channel prefix; the scope key is appended as `${prefix}:${scope}`. */
|
|
48
50
|
prefix: string;
|
|
49
51
|
/** What the subscriber provides (default: no input). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoped-change-bus.d.ts","sourceRoot":"","sources":["../../src/live/scoped-change-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACrC,OAAO,KAAK,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EACX,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,aAAa,EACb,MAAM,cAAc,CAAA;AAErB,6EAA6E;AAC7E,MAAM,MAAM,cAAc,CAAC,QAAQ,EAAE,MAAM,IAAI;IAC9C,sFAAsF;IACtF,SAAS,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAA;IACxC,0DAA0D;IAC1D,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CAClC,CAAA;AAED,iFAAiF;AACjF,MAAM,MAAM,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI;IAChD,SAAS,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,QAAQ,CAAA;KAAE,KAAK,MAAM,CAAA;IACpD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,eAAe,CAC1B,IAAI,SAAS,YAAY,EACzB,YAAY,SAAS,YAAY,EACjC,YAAY,SAAS,OAAO,EAC5B,IAAI,SAAS,YAAY,CAAC,IAAI,CAAC,EAC/B,WAAW,IACR,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG;IACpD,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAA;IAC1D;;;OAGG;IACH,UAAU,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,CAAA;CAC1C,CAAA;AAED,QAAA,MAAM,OAAO,gCAAe,CAAA;AAE5B
|
|
1
|
+
{"version":3,"file":"scoped-change-bus.d.ts","sourceRoot":"","sources":["../../src/live/scoped-change-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACrC,OAAO,KAAK,EACX,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EACX,YAAY,EACZ,YAAY,EACZ,MAAM,EACN,aAAa,EACb,MAAM,cAAc,CAAA;AAErB,6EAA6E;AAC7E,MAAM,MAAM,cAAc,CAAC,QAAQ,EAAE,MAAM,IAAI;IAC9C,sFAAsF;IACtF,SAAS,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,MAAM,CAAA;IACxC,0DAA0D;IAC1D,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CAClC,CAAA;AAED,iFAAiF;AACjF,MAAM,MAAM,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI;IAChD,SAAS,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,QAAQ,CAAA;KAAE,KAAK,MAAM,CAAA;IACpD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,eAAe,CAC1B,IAAI,SAAS,YAAY,EACzB,YAAY,SAAS,YAAY,EACjC,YAAY,SAAS,OAAO,EAC5B,IAAI,SAAS,YAAY,CAAC,IAAI,CAAC,EAC/B,WAAW,IACR,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG;IACpD,OAAO,EAAE,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAA;IAC1D;;;OAGG;IACH,UAAU,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,CAAA;CAC1C,CAAA;AAED,QAAA,MAAM,OAAO,gCAAe,CAAA;AAE5B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,SAAS,YAAY,EAAE,WAAW,EAC3E,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC,EAChC,KAAK,EAAE,cAAc,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,IAGrD,YAAY,SAAS,OAAO,CAAC,WAAW,CAAC,EACzC,YAAY,SAAS,YAAY,GAAG,OAAO,OAAO,EAClD,IAAI,SAAS,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,WAExC,IAAI,CACZ,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAC9D,SAAS,GAAG,aAAa,GAAG,QAAQ,CACpC,GACA,OAAO,CACN,IAAI,CACH,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAC9D,QAAQ,CACR,CACD,GACD,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAC5B,IAAI,CACH,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,EAClD,MAAM,GAAG,gBAAgB,CACzB,GACD,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG;IAC7B,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,WAAW,CAAC,EAAE,YAAY,CAAA;CAC1B,KACA,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,WAAW,CAAC,CAqBvE"}
|
|
@@ -5,6 +5,8 @@ const noInput = z.object({});
|
|
|
5
5
|
* subscriber in a scope "something changed". Each bus then names only its
|
|
6
6
|
* channel prefix: events go to `${prefix}:${scope}`. Publishing is safe by
|
|
7
7
|
* default (`safePublish: true`), because buses publish after committed writes.
|
|
8
|
+
* The scope is the access decision (a subscriber hears only its own scope),
|
|
9
|
+
* so `authFn` defaults to `true`.
|
|
8
10
|
*
|
|
9
11
|
* ```ts
|
|
10
12
|
* const defineChangeBus = defineScopedChangeBus(createPubSub, {
|
|
@@ -30,6 +32,7 @@ export function defineScopedChangeBus(createPubSub, scope) {
|
|
|
30
32
|
// signature of createPubSub cannot see.
|
|
31
33
|
const bus = createPubSub({
|
|
32
34
|
safePublish: true,
|
|
35
|
+
authFn: true,
|
|
33
36
|
...pubsubOptions,
|
|
34
37
|
inputSchema: pubsubOptions.inputSchema ?? noInput,
|
|
35
38
|
channel
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoped-change-bus.js","sourceRoot":"","sources":["../../src/live/scoped-change-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,CAAC,EAAE,MAAM,KAAK,CAAA;AA6CrC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAE5B
|
|
1
|
+
{"version":3,"file":"scoped-change-bus.js","sourceRoot":"","sources":["../../src/live/scoped-change-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,CAAC,EAAE,MAAM,KAAK,CAAA;AA6CrC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAE5B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,qBAAqB,CACpC,YAAgC,EAChC,KAAsD;IAEtD,OAAO,CAKN,OAoBE,EACqE,EAAE;QACzE,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAA;QAC5C,MAAM,OAAO,GAAsD;YAClE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;YACnE,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;SACvD,CAAA;QACD,qEAAqE;QACrE,wCAAwC;QACxC,MAAM,GAAG,GAAI,YAA4C,CAAC;YACzD,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,IAAI;YACZ,GAAG,aAAa;YAChB,WAAW,EAAE,aAAa,CAAC,WAAW,IAAI,OAAO;YACjD,OAAO;SACP,CAAmD,CAAA;QACpD,0EAA0E;QAC1E,MAAM,UAAU,GAAG,GAAG,CAAC,qBAEZ,CAAA;QACX,OAAO,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,CAAA;IACvC,CAAC,CAAA;AACF,CAAC","sourcesContent":["import { type ZodType, z } from 'zod'\nimport type {\n\tAnyFnContext,\n\tFnDefinition,\n\tFnRouteOptions,\n\tGuardOptions,\n\tProcedureKey,\n\tProcedureOption\n} from '../types.js'\nimport type {\n\tCreatePubSub,\n\tObjectSchema,\n\tPubSub,\n\tPubSubOptions\n} from './pub-sub.js'\n\n/** Where a change bus partitions its channels, e.g. one per organization. */\nexport type ChangeBusScope<TContext, TEvent> = {\n\t/** The subscriber's scope key, from its context. Throw to refuse the subscription. */\n\tsubscribe: (context: TContext) => string\n\t/** The event's scope key, carried in the event itself. */\n\tpublish: (event: TEvent) => string\n}\n\n/** A bus's channel definition; pass it to `fnLive` to share the bus's events. */\nexport type ChangeBusChannel<TContext, TEvent> = {\n\tsubscribe: (params: { context: TContext }) => string\n\tpublish: (event: TEvent) => string\n}\n\nexport type ScopedChangeBus<\n\tTDef extends FnDefinition,\n\tTInputSchema extends ObjectSchema,\n\tTEventSchema extends ZodType,\n\tTKey extends ProcedureKey<TDef>,\n\tTScopeEvent\n> = PubSub<TDef, TInputSchema, TEventSchema, TKey> & {\n\tchannel: ChangeBusChannel<AnyFnContext<TDef>, TScopeEvent>\n\t/**\n\t * The full channel name for a scope, namespace included:\n\t * `backlogKey(bus.channelFor({ organizationId }))` reads its backlog.\n\t */\n\tchannelFor: (scope: TScopeEvent) => string\n}\n\nconst noInput = z.object({})\n\n/**\n * Binds the app's `createPubSub` to one scope rule, for buses that tell every\n * subscriber in a scope \"something changed\". Each bus then names only its\n * channel prefix: events go to `${prefix}:${scope}`. Publishing is safe by\n * default (`safePublish: true`), because buses publish after committed writes.\n * The scope is the access decision (a subscriber hears only its own scope),\n * so `authFn` defaults to `true`.\n *\n * ```ts\n * const defineChangeBus = defineScopedChangeBus(createPubSub, {\n * subscribe: (context) => activeOrganizationId(context),\n * publish: (event: { organizationId: string }) => event.organizationId\n * })\n * export const dealChanges = defineChangeBus({\n * name: 'deal.subscribe',\n * prefix: 'deal:change',\n * eventSchema: z.object({ organizationId: z.string(), dealId: z.string() })\n * })\n * // fnLive({ live: { channel: dealChanges.channel, ... } }) shares the channel.\n * ```\n */\nexport function defineScopedChangeBus<TDef extends FnDefinition, TScopeEvent>(\n\tcreatePubSub: CreatePubSub<TDef>,\n\tscope: ChangeBusScope<AnyFnContext<TDef>, TScopeEvent>\n) {\n\treturn <\n\t\tTEventSchema extends ZodType<TScopeEvent>,\n\t\tTInputSchema extends ObjectSchema = typeof noInput,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default']\n\t>(\n\t\toptions: Omit<\n\t\t\tPubSubOptions<TDef, TInputSchema, TEventSchema, NoInfer<TKey>>,\n\t\t\t'channel' | 'inputSchema' | 'authFn'\n\t\t> &\n\t\t\tPartial<\n\t\t\t\tPick<\n\t\t\t\t\tPubSubOptions<TDef, TInputSchema, TEventSchema, NoInfer<TKey>>,\n\t\t\t\t\t'authFn'\n\t\t\t\t>\n\t\t\t> &\n\t\t\tGuardOptions<TDef['guards']> &\n\t\t\tPick<\n\t\t\t\tFnRouteOptions<TDef, TKey, z.output<TInputSchema>>,\n\t\t\t\t'meta' | 'guardResolvers'\n\t\t\t> &\n\t\t\tProcedureOption<TDef, TKey> & {\n\t\t\t\t/** Channel prefix; the scope key is appended as `${prefix}:${scope}`. */\n\t\t\t\tprefix: string\n\t\t\t\t/** What the subscriber provides (default: no input). */\n\t\t\t\tinputSchema?: TInputSchema\n\t\t\t}\n\t): ScopedChangeBus<TDef, TInputSchema, TEventSchema, TKey, TScopeEvent> => {\n\t\tconst { prefix, ...pubsubOptions } = options\n\t\tconst channel: ChangeBusChannel<AnyFnContext<TDef>, TScopeEvent> = {\n\t\t\tsubscribe: ({ context }) => `${prefix}:${scope.subscribe(context)}`,\n\t\t\tpublish: (event) => `${prefix}:${scope.publish(event)}`\n\t\t}\n\t\t// The bus's context is one member of AnyFnContext, which the generic\n\t\t// signature of createPubSub cannot see.\n\t\tconst bus = (createPubSub as (options: object) => object)({\n\t\t\tsafePublish: true,\n\t\t\tauthFn: true,\n\t\t\t...pubsubOptions,\n\t\t\tinputSchema: pubsubOptions.inputSchema ?? noInput,\n\t\t\tchannel\n\t\t}) as PubSub<TDef, TInputSchema, TEventSchema, TKey>\n\t\t// The scope reads only its own fields, so a scope stands in for an event.\n\t\tconst channelFor = bus.getPublishChannelName as (\n\t\t\tscope: TScopeEvent\n\t\t) => string\n\t\treturn { ...bus, channel, channelFor }\n\t}\n}\n"]}
|
package/dist/mastra.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import type { RequestContext } from '@mastra/core/request-context';
|
|
1
2
|
import { type Tool } from '@mastra/core/tools';
|
|
2
3
|
import { type AnyProcedure } from '@orpc/server';
|
|
3
4
|
import { toToolName } from './meta.js';
|
|
5
|
+
import { type ToolErrorOptions } from './tool-errors.js';
|
|
4
6
|
import type { ProcedureInput, ProcedureOutput } from './types.js';
|
|
5
|
-
export { toToolName };
|
|
6
|
-
export type CreateMastraToolOptions = {
|
|
7
|
+
export { toToolName, type ToolErrorOptions };
|
|
8
|
+
export type CreateMastraToolOptions = ToolErrorOptions & {
|
|
7
9
|
/** Override the tool id (defaults to the sanitized `fn` name). */
|
|
8
10
|
id?: string;
|
|
9
|
-
/** Override the tool description (defaults to the route summary). */
|
|
11
|
+
/** Override the tool description (defaults to the route description, else its summary). */
|
|
10
12
|
description?: string;
|
|
11
13
|
/** Gate execution behind the AI SDK tool-approval flow. */
|
|
12
14
|
requireApproval?: boolean;
|
|
@@ -22,6 +24,13 @@ export type CreateMastraToolOptions = {
|
|
|
22
24
|
}) => void;
|
|
23
25
|
/** Key holding the oRPC context in Mastra's `RequestContext`. Default 'orpcContext'. */
|
|
24
26
|
contextKey?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Reads the oRPC context from the run's request context, in place of
|
|
29
|
+
* `contextKey`. Mastra writes plain request-context values into run
|
|
30
|
+
* snapshots and spans, so an app whose context holds a session keeps it
|
|
31
|
+
* in a slot that serializes to nothing and reads it here.
|
|
32
|
+
*/
|
|
33
|
+
context?: (requestContext: RequestContext) => unknown;
|
|
25
34
|
};
|
|
26
35
|
/** What the tool takes: the procedure's raw input, or `{}` without a schema. */
|
|
27
36
|
export type MastraToolInput<TProc> = unknown extends ProcedureInput<TProc> ? Record<string, never> : ProcedureInput<TProc>;
|
|
@@ -39,6 +48,10 @@ type ObjectInputCheck<TProc> = MastraToolInput<TProc> extends Record<string, unk
|
|
|
39
48
|
* Mastra checks the input against the procedure's schema (with dates coerced
|
|
40
49
|
* from strings) but passes the raw input on for the procedure to parse;
|
|
41
50
|
* the output is the procedure's parsed result, passed through unchanged.
|
|
51
|
+
*
|
|
52
|
+
* A failed call throws an `Error` whose message is what the model reads:
|
|
53
|
+
* `CODE: message` with validation paths for an expected error, a fixed
|
|
54
|
+
* sentence for anything else (reported to `onError`).
|
|
42
55
|
*/
|
|
43
56
|
export declare function createMastraTool<TProc extends AnyProcedure>(procedure: TProc & ObjectInputCheck<TProc>, options?: CreateMastraToolOptions): MastraTool<TProc>;
|
|
44
57
|
//# sourceMappingURL=mastra.d.ts.map
|
package/dist/mastra.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mastra.d.ts","sourceRoot":"","sources":["../src/mastra.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mastra.d.ts","sourceRoot":"","sources":["../src/mastra.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,KAAK,YAAY,EAAQ,MAAM,cAAc,CAAA;AAOtD,OAAO,EAAc,UAAU,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,KAAK,gBAAgB,EAAiB,MAAM,kBAAkB,CAAA;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjE,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,CAAA;AAE5C,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG;IACxD,kEAAkE;IAClE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QACzB,MAAM,EAAE,MAAM,CAAA;QACd,UAAU,EAAE,MAAM,CAAA;QAClB,OAAO,EAAE,SAAS,GAAG,OAAO,CAAA;KAC5B,KAAK,IAAI,CAAA;IACV,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,OAAO,CAAA;CACrD,CAAA;AAED,gFAAgF;AAChF,MAAM,MAAM,eAAe,CAAC,KAAK,IAChC,OAAO,SAAS,cAAc,CAAC,KAAK,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACrB,cAAc,CAAC,KAAK,CAAC,CAAA;AAEzB,0EAA0E;AAC1E,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,YAAY,IAAI,IAAI,CACxD,eAAe,CAAC,KAAK,CAAC,EACtB,eAAe,CAAC,KAAK,CAAC,CACtB,CAAA;AAED,4EAA4E;AAC5E,KAAK,gBAAgB,CAAC,KAAK,IAC1B,eAAe,CAAC,KAAK,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnD,OAAO,GACP;IAAE,8CAA8C,EAAE,cAAc,CAAC,KAAK,CAAC,CAAA;CAAE,CAAA;AAE7E;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,SAAS,YAAY,EAC1D,SAAS,EAAE,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAC1C,OAAO,GAAE,uBAA4B,GACnC,UAAU,CAAC,KAAK,CAAC,CAyFnB"}
|
package/dist/mastra.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createTool } from '@mastra/core/tools';
|
|
|
2
2
|
import { call } from '@orpc/server';
|
|
3
3
|
import { isObjectJsonSchema, passThroughOutputSchema, rawInputSchema } from './json-schema.js';
|
|
4
4
|
import { readFnMeta, toToolName } from './meta.js';
|
|
5
|
+
import { toolErrorText } from './tool-errors.js';
|
|
5
6
|
export { toToolName };
|
|
6
7
|
/**
|
|
7
8
|
* Creates a Mastra tool from a procedure made with `fn()`. Execution calls
|
|
@@ -11,6 +12,10 @@ export { toToolName };
|
|
|
11
12
|
* Mastra checks the input against the procedure's schema (with dates coerced
|
|
12
13
|
* from strings) but passes the raw input on for the procedure to parse;
|
|
13
14
|
* the output is the procedure's parsed result, passed through unchanged.
|
|
15
|
+
*
|
|
16
|
+
* A failed call throws an `Error` whose message is what the model reads:
|
|
17
|
+
* `CODE: message` with validation paths for an expected error, a fixed
|
|
18
|
+
* sentence for anything else (reported to `onError`).
|
|
14
19
|
*/
|
|
15
20
|
export function createMastraTool(procedure, options = {}) {
|
|
16
21
|
const meta = readFnMeta(procedure);
|
|
@@ -53,9 +58,14 @@ export function createMastraTool(procedure, options = {}) {
|
|
|
53
58
|
: {}),
|
|
54
59
|
execute: async (input, ctx) => {
|
|
55
60
|
const requestContext = ctx?.requestContext;
|
|
56
|
-
const context = requestContext
|
|
61
|
+
const context = requestContext &&
|
|
62
|
+
(options.context
|
|
63
|
+
? options.context(requestContext)
|
|
64
|
+
: requestContext.get(contextKey));
|
|
57
65
|
if (!context) {
|
|
58
|
-
throw new Error(
|
|
66
|
+
throw new Error(options.context
|
|
67
|
+
? 'createMastraTool execution found no oRPC context through its context option'
|
|
68
|
+
: `createMastraTool execution requires ${contextKey} in the Mastra request context`);
|
|
59
69
|
}
|
|
60
70
|
const startedAt = performance.now();
|
|
61
71
|
const finish = (outcome) => {
|
|
@@ -77,7 +87,9 @@ export function createMastraTool(procedure, options = {}) {
|
|
|
77
87
|
}
|
|
78
88
|
catch (error) {
|
|
79
89
|
finish('error');
|
|
80
|
-
|
|
90
|
+
if (ctx?.abortSignal?.aborted)
|
|
91
|
+
throw error;
|
|
92
|
+
throw new Error(toolErrorText(error, id, options));
|
|
81
93
|
}
|
|
82
94
|
}
|
|
83
95
|
});
|
package/dist/mastra.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mastra.js","sourceRoot":"","sources":["../src/mastra.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAa,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAqB,IAAI,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EAEd,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"mastra.js","sourceRoot":"","sources":["../src/mastra.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RequestContext } from '@mastra/core/request-context'\nimport { createTool, type Tool } from '@mastra/core/tools'\nimport { type AnyProcedure, call } from '@orpc/server'\nimport {\n\tisObjectJsonSchema,\n\tpassThroughOutputSchema,\n\trawInputSchema,\n\ttype ToolSchema\n} from './json-schema.js'\nimport { readFnMeta, toToolName } from './meta.js'\nimport { type ToolErrorOptions, toolErrorText } from './tool-errors.js'\nimport type { ProcedureInput, ProcedureOutput } from './types.js'\n\nexport { toToolName, type ToolErrorOptions }\n\nexport type CreateMastraToolOptions = ToolErrorOptions & {\n\t/** Override the tool id (defaults to the sanitized `fn` name). */\n\tid?: string\n\t/** Override the tool description (defaults to the route description, else its summary). */\n\tdescription?: string\n\t/** Gate execution behind the AI SDK tool-approval flow. */\n\trequireApproval?: boolean\n\t/**\n\t * Accept a procedure without an input schema (the tool then takes an empty\n\t * object). For no-input queries like `teams.list`.\n\t */\n\tallowMissingInputSchema?: boolean\n\tonExecuteFinish?: (event: {\n\t\ttoolId: string\n\t\tdurationMs: number\n\t\toutcome: 'success' | 'error'\n\t}) => void\n\t/** Key holding the oRPC context in Mastra's `RequestContext`. Default 'orpcContext'. */\n\tcontextKey?: string\n\t/**\n\t * Reads the oRPC context from the run's request context, in place of\n\t * `contextKey`. Mastra writes plain request-context values into run\n\t * snapshots and spans, so an app whose context holds a session keeps it\n\t * in a slot that serializes to nothing and reads it here.\n\t */\n\tcontext?: (requestContext: RequestContext) => unknown\n}\n\n/** What the tool takes: the procedure's raw input, or `{}` without a schema. */\nexport type MastraToolInput<TProc> =\n\tunknown extends ProcedureInput<TProc>\n\t\t? Record<string, never>\n\t\t: ProcedureInput<TProc>\n\n/** A Mastra tool typed by the procedure's raw input and parsed output. */\nexport type MastraTool<TProc extends AnyProcedure> = Tool<\n\tMastraToolInput<TProc>,\n\tProcedureOutput<TProc>\n>\n\n/** LLM tool parameters must be an object; other inputs are a type error. */\ntype ObjectInputCheck<TProc> =\n\tMastraToolInput<TProc> extends Record<string, unknown>\n\t\t? unknown\n\t\t: { 'orpc-fn: an agent tool needs an object input': ProcedureInput<TProc> }\n\n/**\n * Creates a Mastra tool from a procedure made with `fn()`. Execution calls\n * the procedure with the oRPC context stored in the Mastra request context\n * (`requestContext.set('orpcContext', context)`), so auth and guards apply.\n *\n * Mastra checks the input against the procedure's schema (with dates coerced\n * from strings) but passes the raw input on for the procedure to parse;\n * the output is the procedure's parsed result, passed through unchanged.\n *\n * A failed call throws an `Error` whose message is what the model reads:\n * `CODE: message` with validation paths for an expected error, a fixed\n * sentence for anything else (reported to `onError`).\n */\nexport function createMastraTool<TProc extends AnyProcedure>(\n\tprocedure: TProc & ObjectInputCheck<TProc>,\n\toptions: CreateMastraToolOptions = {}\n): MastraTool<TProc> {\n\tconst meta = readFnMeta(procedure)\n\tif (meta.stream)\n\t\tthrow new TypeError('orpc-fn: streaming procedures cannot be Mastra tools')\n\tconst name = options.id ?? meta.name\n\tif (!name) {\n\t\tthrow new Error(\n\t\t\t'Procedure must be created with fn() to use createMastraTool'\n\t\t)\n\t}\n\tlet inputSchema: ToolSchema | undefined\n\tif (meta.inputSchema) {\n\t\tinputSchema = rawInputSchema(meta.inputSchema)\n\t\tif (!isObjectJsonSchema(inputSchema['~standard'].jsonSchema.input())) {\n\t\t\tthrow new Error(`${name} must take an object input to be an agent tool`)\n\t\t}\n\t} else if (!options.allowMissingInputSchema) {\n\t\tthrow new Error(\n\t\t\t`${name} must declare an input schema to be exposed as an agent tool`\n\t\t)\n\t}\n\n\tconst id = options.id ?? toToolName(name)\n\tconst contextKey = options.contextKey ?? 'orpcContext'\n\n\tconst tool = createTool({\n\t\tid,\n\t\tdescription: options.description ?? meta.description,\n\t\trequireApproval: options.requireApproval === true,\n\t\tinputSchema:\n\t\t\tinputSchema ??\n\t\t\t({\n\t\t\t\t'~standard': {\n\t\t\t\t\tversion: 1,\n\t\t\t\t\tvendor: 'orpc-fn',\n\t\t\t\t\tvalidate: () => ({ value: {} }),\n\t\t\t\t\tjsonSchema: {\n\t\t\t\t\t\tinput: () => ({ type: 'object', properties: {} }),\n\t\t\t\t\t\toutput: () => ({ type: 'object', properties: {} })\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} satisfies ToolSchema),\n\t\t...(meta.outputSchema\n\t\t\t? { outputSchema: passThroughOutputSchema(meta.outputSchema) }\n\t\t\t: {}),\n\t\texecute: async (input, ctx) => {\n\t\t\tconst requestContext = ctx?.requestContext as RequestContext | undefined\n\t\t\tconst context =\n\t\t\t\trequestContext &&\n\t\t\t\t(options.context\n\t\t\t\t\t? options.context(requestContext)\n\t\t\t\t\t: requestContext.get(contextKey))\n\t\t\tif (!context) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\toptions.context\n\t\t\t\t\t\t? 'createMastraTool execution found no oRPC context through its context option'\n\t\t\t\t\t\t: `createMastraTool execution requires ${contextKey} in the Mastra request context`\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst startedAt = performance.now()\n\t\t\tconst finish = (outcome: 'success' | 'error') => {\n\t\t\t\ttry {\n\t\t\t\t\toptions.onExecuteFinish?.({\n\t\t\t\t\t\ttoolId: id,\n\t\t\t\t\t\tdurationMs: performance.now() - startedAt,\n\t\t\t\t\t\toutcome\n\t\t\t\t\t})\n\t\t\t\t} catch {\n\t\t\t\t\t/* A telemetry hook cannot change tool execution. */\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst result = await call(\n\t\t\t\t\tprocedure,\n\t\t\t\t\tmeta.inputSchema ? input : undefined,\n\t\t\t\t\tctx?.abortSignal ? { context, signal: ctx.abortSignal } : { context }\n\t\t\t\t)\n\t\t\t\tfinish('success')\n\t\t\t\treturn result\n\t\t\t} catch (error) {\n\t\t\t\tfinish('error')\n\t\t\t\tif (ctx?.abortSignal?.aborted) throw error\n\t\t\t\tthrow new Error(toolErrorText(error, id, options))\n\t\t\t}\n\t\t}\n\t})\n\n\t// The runtime schemas are untyped `ToolSchema`s; `MastraTool` is the typed surface.\n\treturn tool as unknown as MastraTool<TProc>\n}\n"]}
|
package/dist/mcp/core.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type AnyRouter, type InferRouterInitialContext } from '@orpc/server';
|
|
2
2
|
import { listTools, type McpTool, type ProcedureFilter } from '../mcp.js';
|
|
3
|
+
import { type ToolErrorOptions } from '../tool-errors.js';
|
|
3
4
|
/** Text-only tool result: the shape both MCP SDK majors accept. */
|
|
4
5
|
export type TextToolResult = {
|
|
5
6
|
content: {
|
|
@@ -8,34 +9,50 @@ export type TextToolResult = {
|
|
|
8
9
|
}[];
|
|
9
10
|
isError?: boolean;
|
|
10
11
|
};
|
|
11
|
-
|
|
12
|
+
/** Which procedures become tools, and their names and hints. */
|
|
13
|
+
export type McpToolSelection = {
|
|
12
14
|
/** Tool exposure must be an explicit application choice. */
|
|
13
15
|
filter: ProcedureFilter;
|
|
16
|
+
readOnly?: ProcedureFilter;
|
|
17
|
+
name?: NonNullable<Parameters<typeof listTools>[1]>['name'];
|
|
18
|
+
};
|
|
19
|
+
/** How a registered tool is called and how its outcome reads. */
|
|
20
|
+
export type McpCallOptions<R extends AnyRouter, TResult> = ToolErrorOptions & {
|
|
14
21
|
context: (request: {
|
|
15
22
|
name: string;
|
|
16
23
|
signal: AbortSignal;
|
|
17
24
|
}) => InferRouterInitialContext<R> | Promise<InferRouterInitialContext<R>>;
|
|
18
|
-
readOnly?: ProcedureFilter;
|
|
19
|
-
name?: NonNullable<Parameters<typeof listTools>[1]>['name'];
|
|
20
25
|
formatResult?: (value: unknown, tool: McpTool) => TResult | Promise<TResult>;
|
|
21
26
|
};
|
|
27
|
+
export type RegisterMcpToolsOptions<R extends AnyRouter, TResult> = McpToolSelection & McpCallOptions<R, TResult>;
|
|
28
|
+
type ToolDescription = Omit<McpTool['config'], 'inputSchema'> & {
|
|
29
|
+
name: string;
|
|
30
|
+
inputSchema: Record<string, unknown> & {
|
|
31
|
+
type: 'object';
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/** Tools listed and converted once, then registered per server or request. */
|
|
35
|
+
export type PreparedMcpTools<R extends AnyRouter> = {
|
|
36
|
+
readonly router: R;
|
|
37
|
+
readonly names: readonly string[];
|
|
38
|
+
readonly tools: readonly McpTool[];
|
|
39
|
+
/** @internal The `tools/list` answer. */
|
|
40
|
+
readonly descriptions: readonly ToolDescription[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* List and convert a router's tools once, for an app that builds an MCP
|
|
44
|
+
* server per request: `registerPreparedMcpTools(server, prepared, { context })`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function prepareMcpTools<R extends AnyRouter>(router: R, options: McpToolSelection): PreparedMcpTools<R>;
|
|
22
47
|
/** Default protocol result: JSON/text. Provide formatResult for other MCP content. */
|
|
23
48
|
export declare function formatMcpResult(value: unknown): TextToolResult;
|
|
24
49
|
/** @internal SDK-independent `tools/list` and `tools/call` behind both adapters. */
|
|
25
|
-
export declare function createToolHandlers<R extends AnyRouter, TResult>(
|
|
50
|
+
export declare function createToolHandlers<R extends AnyRouter, TResult>(prepared: PreparedMcpTools<R>, options: McpCallOptions<R, TResult>): {
|
|
26
51
|
names: readonly string[];
|
|
27
52
|
list: () => {
|
|
28
|
-
tools:
|
|
29
|
-
description?: string;
|
|
30
|
-
annotations: {
|
|
31
|
-
readOnlyHint: boolean;
|
|
32
|
-
};
|
|
33
|
-
name: string;
|
|
34
|
-
inputSchema: {
|
|
35
|
-
type: 'object';
|
|
36
|
-
};
|
|
37
|
-
}[];
|
|
53
|
+
tools: ToolDescription[];
|
|
38
54
|
};
|
|
39
55
|
call: (name: string, args: Record<string, unknown> | undefined, signal: AbortSignal) => Promise<TResult | TextToolResult>;
|
|
40
56
|
};
|
|
57
|
+
export {};
|
|
41
58
|
//# sourceMappingURL=core.d.ts.map
|
package/dist/mcp/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/mcp/core.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EACd,KAAK,yBAAyB,EAE9B,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/mcp/core.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EACd,KAAK,yBAAyB,EAE9B,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,SAAS,EAAE,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AACzE,OAAO,EAAE,KAAK,gBAAgB,EAAiB,MAAM,mBAAmB,CAAA;AAExE,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,gEAAgE;AAChE,MAAM,MAAM,gBAAgB,GAAG;IAC9B,4DAA4D;IAC5D,MAAM,EAAE,eAAe,CAAA;IACvB,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,IAAI,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;CAC3D,CAAA;AAED,iEAAiE;AACjE,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,SAAS,EAAE,OAAO,IAAI,gBAAgB,GAAG;IAC7E,OAAO,EAAE,CAAC,OAAO,EAAE;QAClB,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,WAAW,CAAA;KACnB,KAAK,yBAAyB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1E,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC5E,CAAA;AAED,MAAM,MAAM,uBAAuB,CAClC,CAAC,SAAS,SAAS,EACnB,OAAO,IACJ,gBAAgB,GAAG,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;AAEjD,KAAK,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,GAAG;IAC/D,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAA;CACzD,CAAA;AAED,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,SAAS,IAAI;IACnD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAClB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAA;IAClC,yCAAyC;IACzC,QAAQ,CAAC,YAAY,EAAE,SAAS,eAAe,EAAE,CAAA;CACjD,CAAA;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,SAAS,EAClD,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,gBAAgB,GACvB,gBAAgB,CAAC,CAAC,CAAC,CA+BrB;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAQ9D;AAOD,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,SAAS,EAAE,OAAO,EAC9D,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC7B,OAAO,EAAE,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC;IAIlC,KAAK;IACL,IAAI;QAAW,KAAK;;IACpB,IAAI,SACG,MAAM,QACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,UACjC,WAAW,KACjB,OAAO,CAAC,OAAO,GAAG,cAAc,CAAC;EA2BrC"}
|
package/dist/mcp/core.js
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
import { call } from '@orpc/server';
|
|
2
|
+
import { formatIssue } from '../issues.js';
|
|
2
3
|
import { isObjectJsonSchema } from '../json-schema.js';
|
|
3
4
|
import { listTools } from '../mcp.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
isError: true
|
|
14
|
-
});
|
|
15
|
-
/** @internal SDK-independent `tools/list` and `tools/call` behind both adapters. */
|
|
16
|
-
export function createToolHandlers(router, options) {
|
|
17
|
-
const definitions = listTools(router, {
|
|
5
|
+
import { toolErrorText } from '../tool-errors.js';
|
|
6
|
+
/**
|
|
7
|
+
* List and convert a router's tools once, for an app that builds an MCP
|
|
8
|
+
* server per request: `registerPreparedMcpTools(server, prepared, { context })`.
|
|
9
|
+
*/
|
|
10
|
+
export function prepareMcpTools(router, options) {
|
|
11
|
+
if (typeof options.filter !== 'function')
|
|
12
|
+
throw new TypeError('orpc-fn: MCP tools need a filter; tool exposure is an explicit choice');
|
|
13
|
+
const tools = listTools(router, {
|
|
18
14
|
filter: options.filter,
|
|
19
15
|
...(options.readOnly ? { readOnly: options.readOnly } : {}),
|
|
20
16
|
...(options.name ? { name: options.name } : {})
|
|
21
17
|
});
|
|
22
|
-
const
|
|
23
|
-
const descriptions = definitions.map((tool) => {
|
|
18
|
+
const descriptions = tools.map((tool) => {
|
|
24
19
|
const inputSchema = tool.config.inputSchema?.['~standard'].jsonSchema.input() ?? { type: 'object', properties: {} };
|
|
25
20
|
if (!isObjectJsonSchema(inputSchema))
|
|
26
21
|
throw new TypeError(`orpc-fn: MCP tool ${tool.name} needs an object input`);
|
|
@@ -32,8 +27,29 @@ export function createToolHandlers(router, options) {
|
|
|
32
27
|
};
|
|
33
28
|
});
|
|
34
29
|
return {
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
router,
|
|
31
|
+
names: tools.map((tool) => tool.name),
|
|
32
|
+
tools,
|
|
33
|
+
descriptions
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Default protocol result: JSON/text. Provide formatResult for other MCP content. */
|
|
37
|
+
export function formatMcpResult(value) {
|
|
38
|
+
const text = typeof value === 'string'
|
|
39
|
+
? value
|
|
40
|
+
: (JSON.stringify(value, (_key, item) => typeof item === 'bigint' ? item.toString() : item) ?? 'null');
|
|
41
|
+
return { content: [{ type: 'text', text }] };
|
|
42
|
+
}
|
|
43
|
+
const errorResult = (text) => ({
|
|
44
|
+
content: [{ type: 'text', text }],
|
|
45
|
+
isError: true
|
|
46
|
+
});
|
|
47
|
+
/** @internal SDK-independent `tools/list` and `tools/call` behind both adapters. */
|
|
48
|
+
export function createToolHandlers(prepared, options) {
|
|
49
|
+
const tools = new Map(prepared.tools.map((tool) => [tool.name, tool]));
|
|
50
|
+
return {
|
|
51
|
+
names: prepared.names,
|
|
52
|
+
list: () => ({ tools: [...prepared.descriptions] }),
|
|
37
53
|
call: async (name, args, signal) => {
|
|
38
54
|
const tool = tools.get(name);
|
|
39
55
|
if (!tool)
|
|
@@ -42,7 +58,10 @@ export function createToolHandlers(router, options) {
|
|
|
42
58
|
signal.throwIfAborted();
|
|
43
59
|
const validation = await tool.config.inputSchema?.['~standard'].validate(args ?? {});
|
|
44
60
|
if (validation?.issues)
|
|
45
|
-
return errorResult(
|
|
61
|
+
return errorResult([
|
|
62
|
+
'BAD_REQUEST: Invalid tool input',
|
|
63
|
+
...validation.issues.map(formatIssue)
|
|
64
|
+
].join('\n'));
|
|
46
65
|
const context = await options.context({ name: tool.name, signal });
|
|
47
66
|
const result = await call(tool.procedure, validation?.value, {
|
|
48
67
|
context,
|
|
@@ -53,7 +72,7 @@ export function createToolHandlers(router, options) {
|
|
|
53
72
|
catch (error) {
|
|
54
73
|
if (signal.aborted)
|
|
55
74
|
throw error;
|
|
56
|
-
return errorResult(error
|
|
75
|
+
return errorResult(toolErrorText(error, tool.name, options));
|
|
57
76
|
}
|
|
58
77
|
}
|
|
59
78
|
};
|
package/dist/mcp/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/mcp/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,IAAI,EACJ,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAsC,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/mcp/core.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AnyRouter,\n\ttype InferRouterInitialContext,\n\tcall\n} from '@orpc/server'\nimport { formatIssue } from '../issues.js'\nimport { isObjectJsonSchema } from '../json-schema.js'\nimport { listTools, type McpTool, type ProcedureFilter } from '../mcp.js'\nimport { type ToolErrorOptions, toolErrorText } from '../tool-errors.js'\n\n/** Text-only tool result: the shape both MCP SDK majors accept. */\nexport type TextToolResult = {\n\tcontent: { type: 'text'; text: string }[]\n\tisError?: boolean\n}\n\n/** Which procedures become tools, and their names and hints. */\nexport type McpToolSelection = {\n\t/** Tool exposure must be an explicit application choice. */\n\tfilter: ProcedureFilter\n\treadOnly?: ProcedureFilter\n\tname?: NonNullable<Parameters<typeof listTools>[1]>['name']\n}\n\n/** How a registered tool is called and how its outcome reads. */\nexport type McpCallOptions<R extends AnyRouter, TResult> = ToolErrorOptions & {\n\tcontext: (request: {\n\t\tname: string\n\t\tsignal: AbortSignal\n\t}) => InferRouterInitialContext<R> | Promise<InferRouterInitialContext<R>>\n\tformatResult?: (value: unknown, tool: McpTool) => TResult | Promise<TResult>\n}\n\nexport type RegisterMcpToolsOptions<\n\tR extends AnyRouter,\n\tTResult\n> = McpToolSelection & McpCallOptions<R, TResult>\n\ntype ToolDescription = Omit<McpTool['config'], 'inputSchema'> & {\n\tname: string\n\tinputSchema: Record<string, unknown> & { type: 'object' }\n}\n\n/** Tools listed and converted once, then registered per server or request. */\nexport type PreparedMcpTools<R extends AnyRouter> = {\n\treadonly router: R\n\treadonly names: readonly string[]\n\treadonly tools: readonly McpTool[]\n\t/** @internal The `tools/list` answer. */\n\treadonly descriptions: readonly ToolDescription[]\n}\n\n/**\n * List and convert a router's tools once, for an app that builds an MCP\n * server per request: `registerPreparedMcpTools(server, prepared, { context })`.\n */\nexport function prepareMcpTools<R extends AnyRouter>(\n\trouter: R,\n\toptions: McpToolSelection\n): PreparedMcpTools<R> {\n\tif (typeof options.filter !== 'function')\n\t\tthrow new TypeError(\n\t\t\t'orpc-fn: MCP tools need a filter; tool exposure is an explicit choice'\n\t\t)\n\tconst tools = listTools(router, {\n\t\tfilter: options.filter,\n\t\t...(options.readOnly ? { readOnly: options.readOnly } : {}),\n\t\t...(options.name ? { name: options.name } : {})\n\t})\n\tconst descriptions = tools.map((tool) => {\n\t\tconst inputSchema = tool.config.inputSchema?.[\n\t\t\t'~standard'\n\t\t].jsonSchema.input() ?? { type: 'object', properties: {} }\n\t\tif (!isObjectJsonSchema(inputSchema))\n\t\t\tthrow new TypeError(\n\t\t\t\t`orpc-fn: MCP tool ${tool.name} needs an object input`\n\t\t\t)\n\t\t// MCP requires a top-level object; object unions retain their constraints.\n\t\treturn {\n\t\t\tname: tool.name,\n\t\t\t...tool.config,\n\t\t\tinputSchema: { ...inputSchema, type: 'object' as const }\n\t\t}\n\t})\n\treturn {\n\t\trouter,\n\t\tnames: tools.map((tool) => tool.name),\n\t\ttools,\n\t\tdescriptions\n\t}\n}\n\n/** Default protocol result: JSON/text. Provide formatResult for other MCP content. */\nexport function formatMcpResult(value: unknown): TextToolResult {\n\tconst text =\n\t\ttypeof value === 'string'\n\t\t\t? value\n\t\t\t: (JSON.stringify(value, (_key, item) =>\n\t\t\t\t\ttypeof item === 'bigint' ? item.toString() : item\n\t\t\t\t) ?? 'null')\n\treturn { content: [{ type: 'text', text }] }\n}\n\nconst errorResult = (text: string): TextToolResult => ({\n\tcontent: [{ type: 'text', text }],\n\tisError: true\n})\n\n/** @internal SDK-independent `tools/list` and `tools/call` behind both adapters. */\nexport function createToolHandlers<R extends AnyRouter, TResult>(\n\tprepared: PreparedMcpTools<R>,\n\toptions: McpCallOptions<R, TResult>\n) {\n\tconst tools = new Map(prepared.tools.map((tool) => [tool.name, tool]))\n\treturn {\n\t\tnames: prepared.names,\n\t\tlist: () => ({ tools: [...prepared.descriptions] }),\n\t\tcall: async (\n\t\t\tname: string,\n\t\t\targs: Record<string, unknown> | undefined,\n\t\t\tsignal: AbortSignal\n\t\t): Promise<TResult | TextToolResult> => {\n\t\t\tconst tool = tools.get(name)\n\t\t\tif (!tool) return errorResult(`Unknown tool: ${name}`)\n\t\t\ttry {\n\t\t\t\tsignal.throwIfAborted()\n\t\t\t\tconst validation = await tool.config.inputSchema?.[\n\t\t\t\t\t'~standard'\n\t\t\t\t].validate(args ?? {})\n\t\t\t\tif (validation?.issues)\n\t\t\t\t\treturn errorResult(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'BAD_REQUEST: Invalid tool input',\n\t\t\t\t\t\t\t...validation.issues.map(formatIssue)\n\t\t\t\t\t\t].join('\\n')\n\t\t\t\t\t)\n\t\t\t\tconst context = await options.context({ name: tool.name, signal })\n\t\t\t\tconst result = await call(tool.procedure, validation?.value, {\n\t\t\t\t\tcontext,\n\t\t\t\t\tsignal\n\t\t\t\t})\n\t\t\t\treturn await (options.formatResult ?? formatMcpResult)(result, tool)\n\t\t\t} catch (error) {\n\t\t\t\tif (signal.aborted) throw error\n\t\t\t\treturn errorResult(toolErrorText(error, tool.name, options))\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
package/dist/mcp/sdk.d.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
2
|
import { type CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import type { AnyRouter } from '@orpc/server';
|
|
4
|
-
import { formatMcpResult, type RegisterMcpToolsOptions as CoreOptions } from './core.js';
|
|
5
|
-
export { formatMcpResult };
|
|
4
|
+
import { formatMcpResult, type McpCallOptions, type PreparedMcpTools, prepareMcpTools, type RegisterMcpToolsOptions as CoreOptions } from './core.js';
|
|
5
|
+
export { formatMcpResult, prepareMcpTools, type PreparedMcpTools };
|
|
6
6
|
export type RegisterMcpToolsOptions<R extends AnyRouter> = CoreOptions<R, CallToolResult>;
|
|
7
|
+
/** Options for registering tools from {@link prepareMcpTools}. */
|
|
8
|
+
export type RegisterPreparedMcpToolsOptions<R extends AnyRouter> = McpCallOptions<R, CallToolResult>;
|
|
7
9
|
/**
|
|
8
10
|
* Register on the SDK v1 low-level Server, or on McpServer.server. For SDK v2
|
|
9
11
|
* (`@modelcontextprotocol/server`) use `orpc-fn/mcp/server`.
|
|
10
12
|
*/
|
|
11
13
|
export declare function registerMcpTools<R extends AnyRouter>(server: Pick<Server, 'setRequestHandler'>, router: R, options: RegisterMcpToolsOptions<R>): readonly string[];
|
|
14
|
+
/** Register tools listed once with {@link prepareMcpTools}, e.g. on a server built per request. */
|
|
15
|
+
export declare function registerPreparedMcpTools<R extends AnyRouter>(server: Pick<Server, 'setRequestHandler'>, tools: PreparedMcpTools<R>, options: RegisterPreparedMcpToolsOptions<R>): readonly string[];
|
|
12
16
|
//# sourceMappingURL=sdk.d.ts.map
|
package/dist/mcp/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/mcp/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AACvE,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAEN,eAAe,EACf,KAAK,uBAAuB,IAAI,WAAW,EAC3C,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,eAAe,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/mcp/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AACvE,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAEN,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,uBAAuB,IAAI,WAAW,EAC3C,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,CAAA;AAElE,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,SAAS,IAAI,WAAW,CACrE,CAAC,EACD,cAAc,CACd,CAAA;AAED,kEAAkE;AAClE,MAAM,MAAM,+BAA+B,CAAC,CAAC,SAAS,SAAS,IAC9D,cAAc,CAAC,CAAC,EAAE,cAAc,CAAC,CAAA;AAElC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,SAAS,EACnD,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACzC,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,GACjC,SAAS,MAAM,EAAE,CAKnB;AAED,mGAAmG;AACnG,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,SAAS,EAC3D,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACzC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC1B,OAAO,EAAE,+BAA+B,CAAC,CAAC,CAAC,GACzC,SAAS,MAAM,EAAE,CAEnB"}
|
package/dist/mcp/sdk.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import { createToolHandlers, formatMcpResult } from './core.js';
|
|
3
|
-
export { formatMcpResult };
|
|
2
|
+
import { createToolHandlers, formatMcpResult, prepareMcpTools } from './core.js';
|
|
3
|
+
export { formatMcpResult, prepareMcpTools };
|
|
4
4
|
/**
|
|
5
5
|
* Register on the SDK v1 low-level Server, or on McpServer.server. For SDK v2
|
|
6
6
|
* (`@modelcontextprotocol/server`) use `orpc-fn/mcp/server`.
|
|
7
7
|
*/
|
|
8
8
|
export function registerMcpTools(server, router, options) {
|
|
9
|
-
|
|
9
|
+
return install(server, createToolHandlers(prepareMcpTools(router, options), options));
|
|
10
|
+
}
|
|
11
|
+
/** Register tools listed once with {@link prepareMcpTools}, e.g. on a server built per request. */
|
|
12
|
+
export function registerPreparedMcpTools(server, tools, options) {
|
|
13
|
+
return install(server, createToolHandlers(tools, options));
|
|
14
|
+
}
|
|
15
|
+
function install(server, handlers) {
|
|
10
16
|
server.setRequestHandler(ListToolsRequestSchema, handlers.list);
|
|
11
17
|
server.setRequestHandler(CallToolRequestSchema, (request, extra) => handlers.call(request.params.name, request.params.arguments, extra.signal));
|
|
12
18
|
return handlers.names;
|
package/dist/mcp/sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/mcp/sdk.ts"],"names":[],"mappings":"AACA,OAAO,EACN,qBAAqB,EACrB,sBAAsB,EAEtB,MAAM,oCAAoC,CAAA;AAE3C,OAAO,EACN,kBAAkB,EAClB,eAAe,EAEf,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,eAAe,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/mcp/sdk.ts"],"names":[],"mappings":"AACA,OAAO,EACN,qBAAqB,EACrB,sBAAsB,EAEtB,MAAM,oCAAoC,CAAA;AAE3C,OAAO,EACN,kBAAkB,EAClB,eAAe,EAGf,eAAe,EAEf,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAyB,CAAA;AAWlE;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC/B,MAAyC,EACzC,MAAS,EACT,OAAmC;IAEnC,OAAO,OAAO,CACb,MAAM,EACN,kBAAkB,CAAC,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAC7D,CAAA;AACF,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,wBAAwB,CACvC,MAAyC,EACzC,KAA0B,EAC1B,OAA2C;IAE3C,OAAO,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,SAAS,OAAO,CACf,MAAyC,EACzC,QAA0E;IAE1E,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC/D,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAClE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAC1E,CAAA;IACD,OAAO,QAAQ,CAAC,KAAK,CAAA;AACtB,CAAC","sourcesContent":["import type { Server } from '@modelcontextprotocol/sdk/server/index.js'\nimport {\n\tCallToolRequestSchema,\n\tListToolsRequestSchema,\n\ttype CallToolResult\n} from '@modelcontextprotocol/sdk/types.js'\nimport type { AnyRouter } from '@orpc/server'\nimport {\n\tcreateToolHandlers,\n\tformatMcpResult,\n\ttype McpCallOptions,\n\ttype PreparedMcpTools,\n\tprepareMcpTools,\n\ttype RegisterMcpToolsOptions as CoreOptions\n} from './core.js'\n\nexport { formatMcpResult, prepareMcpTools, type PreparedMcpTools }\n\nexport type RegisterMcpToolsOptions<R extends AnyRouter> = CoreOptions<\n\tR,\n\tCallToolResult\n>\n\n/** Options for registering tools from {@link prepareMcpTools}. */\nexport type RegisterPreparedMcpToolsOptions<R extends AnyRouter> =\n\tMcpCallOptions<R, CallToolResult>\n\n/**\n * Register on the SDK v1 low-level Server, or on McpServer.server. For SDK v2\n * (`@modelcontextprotocol/server`) use `orpc-fn/mcp/server`.\n */\nexport function registerMcpTools<R extends AnyRouter>(\n\tserver: Pick<Server, 'setRequestHandler'>,\n\trouter: R,\n\toptions: RegisterMcpToolsOptions<R>\n): readonly string[] {\n\treturn install(\n\t\tserver,\n\t\tcreateToolHandlers(prepareMcpTools(router, options), options)\n\t)\n}\n\n/** Register tools listed once with {@link prepareMcpTools}, e.g. on a server built per request. */\nexport function registerPreparedMcpTools<R extends AnyRouter>(\n\tserver: Pick<Server, 'setRequestHandler'>,\n\ttools: PreparedMcpTools<R>,\n\toptions: RegisterPreparedMcpToolsOptions<R>\n): readonly string[] {\n\treturn install(server, createToolHandlers(tools, options))\n}\n\nfunction install(\n\tserver: Pick<Server, 'setRequestHandler'>,\n\thandlers: ReturnType<typeof createToolHandlers<AnyRouter, CallToolResult>>\n): readonly string[] {\n\tserver.setRequestHandler(ListToolsRequestSchema, handlers.list)\n\tserver.setRequestHandler(CallToolRequestSchema, (request, extra) =>\n\t\thandlers.call(request.params.name, request.params.arguments, extra.signal)\n\t)\n\treturn handlers.names\n}\n"]}
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { CallToolResult, Server } from '@modelcontextprotocol/server';
|
|
2
2
|
import type { AnyRouter } from '@orpc/server';
|
|
3
|
-
import { formatMcpResult, type RegisterMcpToolsOptions as CoreOptions } from './core.js';
|
|
4
|
-
export { formatMcpResult };
|
|
3
|
+
import { formatMcpResult, type McpCallOptions, type PreparedMcpTools, prepareMcpTools, type RegisterMcpToolsOptions as CoreOptions } from './core.js';
|
|
4
|
+
export { formatMcpResult, prepareMcpTools, type PreparedMcpTools };
|
|
5
5
|
export type RegisterMcpToolsOptions<R extends AnyRouter> = CoreOptions<R, CallToolResult>;
|
|
6
|
+
/** Options for registering tools from {@link prepareMcpTools}. */
|
|
7
|
+
export type RegisterPreparedMcpToolsOptions<R extends AnyRouter> = McpCallOptions<R, CallToolResult>;
|
|
6
8
|
/**
|
|
7
9
|
* Register on the SDK v2 (`@modelcontextprotocol/server`) low-level Server, or
|
|
8
10
|
* on McpServer.server. Declare `capabilities: { tools: {} }` on the Server.
|
|
9
11
|
*/
|
|
10
12
|
export declare function registerMcpTools<R extends AnyRouter>(server: Pick<Server, 'setRequestHandler'>, router: R, options: RegisterMcpToolsOptions<R>): readonly string[];
|
|
13
|
+
/** Register tools listed once with {@link prepareMcpTools}, e.g. on a server built per request. */
|
|
14
|
+
export declare function registerPreparedMcpTools<R extends AnyRouter>(server: Pick<Server, 'setRequestHandler'>, tools: PreparedMcpTools<R>, options: RegisterPreparedMcpToolsOptions<R>): readonly string[];
|
|
11
15
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/mcp/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAA;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAEN,eAAe,EACf,KAAK,uBAAuB,IAAI,WAAW,EAC3C,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,eAAe,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAA;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAEN,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,uBAAuB,IAAI,WAAW,EAC3C,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,CAAA;AAElE,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,SAAS,IAAI,WAAW,CACrE,CAAC,EACD,cAAc,CACd,CAAA;AAED,kEAAkE;AAClE,MAAM,MAAM,+BAA+B,CAAC,CAAC,SAAS,SAAS,IAC9D,cAAc,CAAC,CAAC,EAAE,cAAc,CAAC,CAAA;AAElC;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,SAAS,EACnD,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACzC,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,GACjC,SAAS,MAAM,EAAE,CAKnB;AAED,mGAAmG;AACnG,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,SAAS,EAC3D,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACzC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC1B,OAAO,EAAE,+BAA+B,CAAC,CAAC,CAAC,GACzC,SAAS,MAAM,EAAE,CAEnB"}
|