trpc-to-mcp 1.3.2 → 2.0.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.
Files changed (70) hide show
  1. package/README.md +138 -178
  2. package/dist/adapters/vercel-mcp-adapter.cjs +19 -0
  3. package/dist/adapters/vercel-mcp-adapter.cjs.map +1 -0
  4. package/dist/adapters/vercel-mcp-adapter.d.cts +17 -0
  5. package/dist/adapters/vercel-mcp-adapter.d.mts +16 -13
  6. package/dist/adapters/vercel-mcp-adapter.mjs +15 -27
  7. package/dist/adapters/vercel-mcp-adapter.mjs.map +1 -1
  8. package/dist/helpers.cjs +20 -0
  9. package/dist/helpers.cjs.map +1 -0
  10. package/dist/helpers.d.cts +13 -0
  11. package/dist/helpers.d.mts +13 -6
  12. package/dist/helpers.mjs +17 -2
  13. package/dist/helpers.mjs.map +1 -1
  14. package/dist/index.cjs +9 -0
  15. package/dist/index.d.cts +5 -0
  16. package/dist/index.d.mts +5 -10
  17. package/dist/index.mjs +5 -6
  18. package/dist/server.cjs +18 -0
  19. package/dist/server.cjs.map +1 -0
  20. package/dist/server.d.cts +12 -0
  21. package/dist/server.d.mts +12 -12
  22. package/dist/server.mjs +16 -3
  23. package/dist/server.mjs.map +1 -1
  24. package/dist/tools.cjs +121 -0
  25. package/dist/tools.cjs.map +1 -0
  26. package/dist/tools.d.cts +23 -0
  27. package/dist/tools.d.mts +22 -15
  28. package/dist/tools.mjs +118 -2
  29. package/dist/tools.mjs.map +1 -1
  30. package/dist/types.cjs +0 -0
  31. package/dist/types.d.cts +31 -0
  32. package/dist/types.d.mts +30 -13
  33. package/dist/types.mjs +1 -3
  34. package/package.json +55 -73
  35. package/dist/adapters/vercel-mcp-adapter.d.ts +0 -14
  36. package/dist/adapters/vercel-mcp-adapter.js +0 -32
  37. package/dist/adapters/vercel-mcp-adapter.js.map +0 -1
  38. package/dist/chunk-55J6XMHW.js +0 -4
  39. package/dist/chunk-55J6XMHW.js.map +0 -1
  40. package/dist/chunk-7GYUHEUD.mjs +0 -47
  41. package/dist/chunk-7GYUHEUD.mjs.map +0 -1
  42. package/dist/chunk-BTXMEL6M.js +0 -55
  43. package/dist/chunk-BTXMEL6M.js.map +0 -1
  44. package/dist/chunk-FIQIIJAT.mjs +0 -11
  45. package/dist/chunk-FIQIIJAT.mjs.map +0 -1
  46. package/dist/chunk-FT3KTYAU.js +0 -13
  47. package/dist/chunk-FT3KTYAU.js.map +0 -1
  48. package/dist/chunk-KIQOUUEZ.mjs +0 -3
  49. package/dist/chunk-KIQOUUEZ.mjs.map +0 -1
  50. package/dist/chunk-RJJMUGXY.js +0 -50
  51. package/dist/chunk-RJJMUGXY.js.map +0 -1
  52. package/dist/chunk-ULLXW6IN.mjs +0 -52
  53. package/dist/chunk-ULLXW6IN.mjs.map +0 -1
  54. package/dist/helpers.d.ts +0 -6
  55. package/dist/helpers.js +0 -12
  56. package/dist/helpers.js.map +0 -1
  57. package/dist/index.d.ts +0 -10
  58. package/dist/index.js +0 -31
  59. package/dist/index.js.map +0 -1
  60. package/dist/index.mjs.map +0 -1
  61. package/dist/server.d.ts +0 -12
  62. package/dist/server.js +0 -17
  63. package/dist/server.js.map +0 -1
  64. package/dist/tools.d.ts +0 -16
  65. package/dist/tools.js +0 -16
  66. package/dist/tools.js.map +0 -1
  67. package/dist/types.d.ts +0 -14
  68. package/dist/types.js +0 -6
  69. package/dist/types.js.map +0 -1
  70. package/dist/types.mjs.map +0 -1
@@ -0,0 +1,5 @@
1
+ import { MaybePromise, McpContext, McpContextFactory, McpMeta, McpToolTransform } from "./types.cjs";
2
+ import { transformMcpProcedure } from "./helpers.cjs";
3
+ import { createMcpServer } from "./server.cjs";
4
+ import { McpTool, extractToolsFromProcedures, registerTrpcTools } from "./tools.cjs";
5
+ export { MaybePromise, McpContext, McpContextFactory, McpMeta, McpTool, McpToolTransform, createMcpServer, extractToolsFromProcedures, registerTrpcTools, transformMcpProcedure };
package/dist/index.d.mts CHANGED
@@ -1,10 +1,5 @@
1
- export { createMcpServer, setRequestHandler } from './server.mjs';
2
- export { McpTool, extractToolsFromProcedures, mergeInputs } from './tools.mjs';
3
- export { transformMcpProcedure } from './helpers.mjs';
4
- export { McpMeta, TransformMcpProcedureFunction } from './types.mjs';
5
- import '@modelcontextprotocol/sdk/server/index.js';
6
- import '@modelcontextprotocol/sdk/server/mcp.js';
7
- import '@modelcontextprotocol/sdk/types.js';
8
- import '@trpc/server/unstable-core-do-not-import';
9
- import 'zod/v4';
10
- import '@modelcontextprotocol/sdk/types';
1
+ import { MaybePromise, McpContext, McpContextFactory, McpMeta, McpToolTransform } from "./types.mjs";
2
+ import { transformMcpProcedure } from "./helpers.mjs";
3
+ import { createMcpServer } from "./server.mjs";
4
+ import { McpTool, extractToolsFromProcedures, registerTrpcTools } from "./tools.mjs";
5
+ export { MaybePromise, McpContext, McpContextFactory, McpMeta, McpTool, McpToolTransform, createMcpServer, extractToolsFromProcedures, registerTrpcTools, transformMcpProcedure };
package/dist/index.mjs CHANGED
@@ -1,6 +1,5 @@
1
- export { transformMcpProcedure } from './chunk-FIQIIJAT.mjs';
2
- import './chunk-KIQOUUEZ.mjs';
3
- export { createMcpServer, setRequestHandler } from './chunk-7GYUHEUD.mjs';
4
- export { extractToolsFromProcedures, mergeInputs } from './chunk-ULLXW6IN.mjs';
5
- //# sourceMappingURL=index.mjs.map
6
- //# sourceMappingURL=index.mjs.map
1
+ import { transformMcpProcedure } from "./helpers.mjs";
2
+ import { extractToolsFromProcedures, registerTrpcTools } from "./tools.mjs";
3
+ import { createMcpServer } from "./server.mjs";
4
+ import "./types.mjs";
5
+ export { createMcpServer, extractToolsFromProcedures, registerTrpcTools, transformMcpProcedure };
@@ -0,0 +1,18 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_tools = require("./tools.cjs");
3
+ let _modelcontextprotocol_server = require("@modelcontextprotocol/server");
4
+ //#region src/server.ts
5
+ /**
6
+ * Creates an `McpServer` with the router's MCP-enabled procedures registered
7
+ * as tools. Connect it to a transport yourself, or return it from the
8
+ * factory you pass to the SDK's `createMcpHandler`.
9
+ */
10
+ function createMcpServer(implementation, router, ctx, options) {
11
+ const server = new _modelcontextprotocol_server.McpServer(implementation, options);
12
+ require_tools.registerTrpcTools(server, router, ctx);
13
+ return server;
14
+ }
15
+ //#endregion
16
+ exports.createMcpServer = createMcpServer;
17
+
18
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.cjs","names":["McpServer"],"sources":["../src/server.ts"],"sourcesContent":["import {\n McpServer,\n type Implementation,\n type ServerOptions,\n} from \"@modelcontextprotocol/server\";\nimport type { AnyTRPCRouter } from \"@trpc/server\";\n\nimport { registerTrpcTools } from \"./tools\";\nimport type { McpContext } from \"./types\";\n\n/**\n * Creates an `McpServer` with the router's MCP-enabled procedures registered\n * as tools. Connect it to a transport yourself, or return it from the\n * factory you pass to the SDK's `createMcpHandler`.\n */\nexport function createMcpServer<TRouter extends AnyTRPCRouter>(\n implementation: Implementation,\n router: TRouter,\n ctx: McpContext<TRouter>,\n options?: ServerOptions,\n) {\n const server = new McpServer(implementation, options);\n registerTrpcTools(server, router, ctx);\n return server;\n}\n"],"mappings":";;;;;;;;;AAeA,SAAgB,gBACd,gBACA,QACA,KACA,SACA;CACA,MAAM,SAAS,IAAIA,6BAAAA,UAAU,gBAAgB,OAAO;CACpD,cAAA,kBAAkB,QAAQ,QAAQ,GAAG;CACrC,OAAO;AACT"}
@@ -0,0 +1,12 @@
1
+ import { McpContext } from "./types.cjs";
2
+ import { Implementation, McpServer, ServerOptions } from "@modelcontextprotocol/server";
3
+ import { AnyTRPCRouter } from "@trpc/server";
4
+ //#region src/server.d.ts
5
+ /**
6
+ * Creates an `McpServer` with the router's MCP-enabled procedures registered
7
+ * as tools. Connect it to a transport yourself, or return it from the
8
+ * factory you pass to the SDK's `createMcpHandler`.
9
+ */
10
+ export declare function createMcpServer<TRouter extends AnyTRPCRouter>(implementation: Implementation, router: TRouter, ctx: McpContext<TRouter>, options?: ServerOptions): McpServer;
11
+ //#endregion
12
+ //# sourceMappingURL=server.d.cts.map
package/dist/server.d.mts CHANGED
@@ -1,12 +1,12 @@
1
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import { Implementation } from '@modelcontextprotocol/sdk/types.js';
4
- import { RouterRecord, DecorateRouterRecord, AnyRootTypes, Router, MaybePromise } from '@trpc/server/unstable-core-do-not-import';
5
- import { McpTool } from './tools.mjs';
6
- import 'zod/v4';
7
- import './types.mjs';
8
-
9
- declare function setRequestHandler<TRecord extends RouterRecord>(server: Server, tools: McpTool[], trpcCaller: DecorateRouterRecord<TRecord>): void;
10
- declare function createMcpServer<TRoot extends AnyRootTypes, TRecord extends RouterRecord>(implementation: Implementation, appRouter: Router<TRoot, TRecord>, ctx: TRoot["ctx"] | (() => MaybePromise<TRoot["ctx"]>)): McpServer;
11
-
12
- export { createMcpServer, setRequestHandler };
1
+ import { McpContext } from "./types.mjs";
2
+ import { Implementation, McpServer, ServerOptions } from "@modelcontextprotocol/server";
3
+ import { AnyTRPCRouter } from "@trpc/server";
4
+ //#region src/server.d.ts
5
+ /**
6
+ * Creates an `McpServer` with the router's MCP-enabled procedures registered
7
+ * as tools. Connect it to a transport yourself, or return it from the
8
+ * factory you pass to the SDK's `createMcpHandler`.
9
+ */
10
+ export declare function createMcpServer<TRouter extends AnyTRPCRouter>(implementation: Implementation, router: TRouter, ctx: McpContext<TRouter>, options?: ServerOptions): McpServer;
11
+ //#endregion
12
+ //# sourceMappingURL=server.d.mts.map
package/dist/server.mjs CHANGED
@@ -1,4 +1,17 @@
1
- export { createMcpServer, setRequestHandler } from './chunk-7GYUHEUD.mjs';
2
- import './chunk-ULLXW6IN.mjs';
3
- //# sourceMappingURL=server.mjs.map
1
+ import { registerTrpcTools } from "./tools.mjs";
2
+ import { McpServer } from "@modelcontextprotocol/server";
3
+ //#region src/server.ts
4
+ /**
5
+ * Creates an `McpServer` with the router's MCP-enabled procedures registered
6
+ * as tools. Connect it to a transport yourself, or return it from the
7
+ * factory you pass to the SDK's `createMcpHandler`.
8
+ */
9
+ function createMcpServer(implementation, router, ctx, options) {
10
+ const server = new McpServer(implementation, options);
11
+ registerTrpcTools(server, router, ctx);
12
+ return server;
13
+ }
14
+ //#endregion
15
+ export { createMcpServer };
16
+
4
17
  //# sourceMappingURL=server.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"server.mjs"}
1
+ {"version":3,"file":"server.mjs","names":[],"sources":["../src/server.ts"],"sourcesContent":["import {\n McpServer,\n type Implementation,\n type ServerOptions,\n} from \"@modelcontextprotocol/server\";\nimport type { AnyTRPCRouter } from \"@trpc/server\";\n\nimport { registerTrpcTools } from \"./tools\";\nimport type { McpContext } from \"./types\";\n\n/**\n * Creates an `McpServer` with the router's MCP-enabled procedures registered\n * as tools. Connect it to a transport yourself, or return it from the\n * factory you pass to the SDK's `createMcpHandler`.\n */\nexport function createMcpServer<TRouter extends AnyTRPCRouter>(\n implementation: Implementation,\n router: TRouter,\n ctx: McpContext<TRouter>,\n options?: ServerOptions,\n) {\n const server = new McpServer(implementation, options);\n registerTrpcTools(server, router, ctx);\n return server;\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,gBACd,gBACA,QACA,KACA,SACA;CACA,MAAM,SAAS,IAAI,UAAU,gBAAgB,OAAO;CACpD,kBAAkB,QAAQ,QAAQ,GAAG;CACrC,OAAO;AACT"}
package/dist/tools.cjs ADDED
@@ -0,0 +1,121 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_helpers = require("./helpers.cjs");
3
+ let _trpc_server = require("@trpc/server");
4
+ //#region src/tools.ts
5
+ const JSON_SCHEMA_OPTIONS = {
6
+ target: "draft-2020-12",
7
+ libraryOptions: { unrepresentable: "any" }
8
+ };
9
+ function hasJsonSchema(parser) {
10
+ if (typeof parser !== "object" && typeof parser !== "function") return false;
11
+ if (parser === null || !("~standard" in parser)) return false;
12
+ const standard = parser["~standard"];
13
+ return typeof standard === "object" && standard !== null && "jsonSchema" in standard && typeof standard.jsonSchema === "object";
14
+ }
15
+ function isObjectSchema(schema) {
16
+ return schema.type === "object";
17
+ }
18
+ function toInputSchema(inputs, path) {
19
+ const schemas = inputs.map((parser) => {
20
+ if (!hasJsonSchema(parser)) throw new TypeError(`[trpc-to-mcp] The input of "${path}" can't be converted to JSON Schema. Use a validator that implements Standard JSON Schema, such as zod >=4.2, ArkType, or Valibot with toStandardJsonSchema().`);
21
+ const schema = parser["~standard"].jsonSchema.input(JSON_SCHEMA_OPTIONS);
22
+ if (!isObjectSchema(schema)) throw new TypeError(`[trpc-to-mcp] The input of "${path}" must be an object schema, because MCP tool arguments are always an object.`);
23
+ return schema;
24
+ });
25
+ const [first, ...rest] = schemas;
26
+ if (!first) return {
27
+ type: "object",
28
+ properties: {}
29
+ };
30
+ if (rest.length === 0) return first;
31
+ return {
32
+ type: "object",
33
+ properties: Object.assign({}, ...schemas.map((s) => s.properties)),
34
+ required: [...new Set(schemas.flatMap((s) => s.required ?? []))]
35
+ };
36
+ }
37
+ function toOutputSchema(output) {
38
+ if (!hasJsonSchema(output)) return void 0;
39
+ try {
40
+ const schema = output["~standard"].jsonSchema.output(JSON_SCHEMA_OPTIONS);
41
+ return isObjectSchema(schema) ? schema : void 0;
42
+ } catch {
43
+ return;
44
+ }
45
+ }
46
+ /** Lists the MCP-enabled procedures of a router as MCP tool definitions. */
47
+ function extractToolsFromProcedures(router) {
48
+ const procedures = router._def.procedures;
49
+ const tools = [];
50
+ for (const [path, procedure] of Object.entries(procedures)) {
51
+ const { type, inputs, meta } = procedure._def;
52
+ const mcp = meta?.mcp;
53
+ if (!mcp?.enabled) continue;
54
+ if (type === "subscription") throw new TypeError(`[trpc-to-mcp] "${path}" is a subscription. Only queries and mutations can be MCP tools.`);
55
+ tools.push({
56
+ name: mcp.name ?? path.replace(/\./g, "_"),
57
+ title: mcp.title,
58
+ description: mcp.description,
59
+ annotations: type === "query" ? {
60
+ readOnlyHint: true,
61
+ ...mcp.annotations
62
+ } : mcp.annotations,
63
+ inputSchema: toInputSchema(inputs, path),
64
+ outputSchema: "output" in procedure._def ? toOutputSchema(procedure._def.output) : void 0,
65
+ path,
66
+ type,
67
+ transform: require_helpers.getMcpTransform(procedure)
68
+ });
69
+ }
70
+ return tools;
71
+ }
72
+ function advertise(schema) {
73
+ return { "~standard": {
74
+ version: 1,
75
+ vendor: "trpc-to-mcp",
76
+ validate: (value) => ({ value }),
77
+ jsonSchema: {
78
+ input: () => schema,
79
+ output: () => schema
80
+ }
81
+ } };
82
+ }
83
+ /**
84
+ * Registers every MCP-enabled procedure of `router` as a tool on `server`.
85
+ * Calls go through tRPC's normal pipeline (middlewares, input and output
86
+ * validation), and errors come back to the client as `isError` results.
87
+ */
88
+ function registerTrpcTools(server, router, ctx) {
89
+ const createContext = typeof ctx === "function" ? ctx : () => ctx;
90
+ return extractToolsFromProcedures(router).map((tool) => server.registerTool(tool.name, {
91
+ title: tool.title,
92
+ description: tool.description,
93
+ annotations: tool.annotations,
94
+ inputSchema: advertise(tool.inputSchema),
95
+ outputSchema: tool.outputSchema && advertise(tool.outputSchema)
96
+ }, async (args, mcpCtx) => {
97
+ const output = await (0, _trpc_server.callTRPCProcedure)({
98
+ router,
99
+ path: tool.path,
100
+ type: tool.type,
101
+ ctx: await createContext(mcpCtx),
102
+ getRawInput: async () => args,
103
+ signal: mcpCtx.mcpReq.signal,
104
+ batchIndex: 0
105
+ });
106
+ const content = tool.transform ? await tool.transform(output) : [{
107
+ type: "text",
108
+ text: JSON.stringify(output ?? null)
109
+ }];
110
+ if (!tool.outputSchema) return { content };
111
+ return {
112
+ content,
113
+ structuredContent: output
114
+ };
115
+ }));
116
+ }
117
+ //#endregion
118
+ exports.extractToolsFromProcedures = extractToolsFromProcedures;
119
+ exports.registerTrpcTools = registerTrpcTools;
120
+
121
+ //# sourceMappingURL=tools.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.cjs","names":["getMcpTransform","callTRPCProcedure"],"sources":["../src/tools.ts"],"sourcesContent":["import type {\n CallToolResult,\n McpServer,\n ServerContext,\n StandardSchemaWithJSON,\n Tool,\n} from \"@modelcontextprotocol/server\";\nimport {\n callTRPCProcedure,\n type AnyTRPCProcedure,\n type AnyTRPCRouter,\n} from \"@trpc/server\";\n\nimport { getMcpTransform } from \"./helpers\";\nimport type {\n McpContext,\n McpContextFactory,\n McpMeta,\n McpToolTransform,\n} from \"./types\";\n\n/** An MCP tool definition built from a tRPC procedure. */\nexport type McpTool = Pick<\n Tool,\n \"name\" | \"title\" | \"description\" | \"annotations\" | \"inputSchema\"\n> & {\n /** Dotted procedure path, e.g. `user.byId`. */\n path: string;\n type: \"query\" | \"mutation\";\n /** Set when the procedure has an `.output()` validator that describes an object. */\n outputSchema?: Tool[\"outputSchema\"];\n transform?: McpToolTransform;\n};\n\ntype JsonSchema = Record<string, unknown>;\n\n// Target and options passed to the Standard JSON Schema converters.\n// `unrepresentable: \"any\"` keeps zod from throwing on types like `z.date()`.\nconst JSON_SCHEMA_OPTIONS = {\n target: \"draft-2020-12\",\n libraryOptions: { unrepresentable: \"any\" },\n} as const;\n\nfunction hasJsonSchema(parser: unknown): parser is StandardSchemaWithJSON {\n if (typeof parser !== \"object\" && typeof parser !== \"function\") return false;\n if (parser === null || !(\"~standard\" in parser)) return false;\n const standard = parser[\"~standard\"];\n return (\n typeof standard === \"object\" &&\n standard !== null &&\n \"jsonSchema\" in standard &&\n typeof standard.jsonSchema === \"object\"\n );\n}\n\nfunction isObjectSchema(\n schema: JsonSchema,\n): schema is Tool[\"inputSchema\"] & JsonSchema {\n return schema.type === \"object\";\n}\n\n// Builds the tool input schema from the procedure's `.input()` parsers.\n// tRPC merges chained object inputs, so their properties are merged here too.\nfunction toInputSchema(inputs: unknown[], path: string): Tool[\"inputSchema\"] {\n const schemas = inputs.map((parser) => {\n if (!hasJsonSchema(parser)) {\n throw new TypeError(\n `[trpc-to-mcp] The input of \"${path}\" can't be converted to JSON Schema. Use a validator that implements Standard JSON Schema, such as zod >=4.2, ArkType, or Valibot with toStandardJsonSchema().`,\n );\n }\n const schema = parser[\"~standard\"].jsonSchema.input(JSON_SCHEMA_OPTIONS);\n if (!isObjectSchema(schema)) {\n throw new TypeError(\n `[trpc-to-mcp] The input of \"${path}\" must be an object schema, because MCP tool arguments are always an object.`,\n );\n }\n return schema;\n });\n\n const [first, ...rest] = schemas;\n if (!first) return { type: \"object\", properties: {} };\n if (rest.length === 0) return first;\n\n return {\n type: \"object\",\n properties: Object.assign({}, ...schemas.map((s) => s.properties)),\n required: [...new Set(schemas.flatMap((s) => s.required ?? []))],\n };\n}\n\n// Output schemas are optional in MCP, so any parser that can't produce an\n// object schema (for example one with transforms) is skipped.\nfunction toOutputSchema(output: unknown): Tool[\"outputSchema\"] {\n if (!hasJsonSchema(output)) return undefined;\n try {\n const schema = output[\"~standard\"].jsonSchema.output(JSON_SCHEMA_OPTIONS);\n return isObjectSchema(schema) ? schema : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Lists the MCP-enabled procedures of a router as MCP tool definitions. */\nexport function extractToolsFromProcedures(router: AnyTRPCRouter): McpTool[] {\n // `_def.procedures` is flat at runtime, keyed by the dotted procedure path.\n const procedures: Record<string, AnyTRPCProcedure> = router._def.procedures;\n const tools: McpTool[] = [];\n\n for (const [path, procedure] of Object.entries(procedures)) {\n const { type, inputs, meta } = procedure._def;\n // tRPC types procedure meta as `unknown`. It is `McpMeta` when the router\n // was built with `initTRPC.meta<McpMeta>()`.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n const mcp = (meta as McpMeta | undefined)?.mcp;\n if (!mcp?.enabled) continue;\n\n if (type === \"subscription\") {\n throw new TypeError(\n `[trpc-to-mcp] \"${path}\" is a subscription. Only queries and mutations can be MCP tools.`,\n );\n }\n\n tools.push({\n name: mcp.name ?? path.replace(/\\./g, \"_\"),\n title: mcp.title,\n description: mcp.description,\n annotations:\n type === \"query\"\n ? { readOnlyHint: true, ...mcp.annotations }\n : mcp.annotations,\n inputSchema: toInputSchema(inputs, path),\n outputSchema:\n \"output\" in procedure._def\n ? toOutputSchema(procedure._def.output)\n : undefined,\n path,\n type,\n transform: getMcpTransform(procedure),\n });\n }\n\n return tools;\n}\n\n// Registers a JSON Schema with the MCP SDK without validating against it.\n// tRPC runs the procedure's own parsers on every call, and validating twice\n// would apply zod transforms twice.\nfunction advertise(schema: JsonSchema): StandardSchemaWithJSON {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"trpc-to-mcp\",\n validate: (value) => ({ value }),\n jsonSchema: { input: () => schema, output: () => schema },\n },\n };\n}\n\n/**\n * Registers every MCP-enabled procedure of `router` as a tool on `server`.\n * Calls go through tRPC's normal pipeline (middlewares, input and output\n * validation), and errors come back to the client as `isError` results.\n */\nexport function registerTrpcTools<TRouter extends AnyTRPCRouter>(\n server: McpServer,\n router: TRouter,\n ctx: McpContext<TRouter>,\n) {\n // A tRPC context is never a function, so a function here is a context factory.\n const createContext =\n typeof ctx === \"function\" ? (ctx as McpContextFactory<TRouter>) : () => ctx;\n\n return extractToolsFromProcedures(router).map((tool) =>\n server.registerTool(\n tool.name,\n {\n title: tool.title,\n description: tool.description,\n annotations: tool.annotations,\n inputSchema: advertise(tool.inputSchema),\n outputSchema: tool.outputSchema && advertise(tool.outputSchema),\n },\n async (args, mcpCtx: ServerContext): Promise<CallToolResult> => {\n const output: unknown = await callTRPCProcedure({\n router,\n path: tool.path,\n type: tool.type,\n ctx: await createContext(mcpCtx),\n getRawInput: async () => args,\n signal: mcpCtx.mcpReq.signal,\n batchIndex: 0,\n });\n\n const content = tool.transform\n ? await tool.transform(output)\n : [{ type: \"text\" as const, text: JSON.stringify(output ?? null) }];\n\n if (!tool.outputSchema) return { content };\n\n // The procedure's `.output()` validator describes an object, and\n // tRPC ran it before returning.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n const structuredContent = output as Record<string, unknown>;\n return { content, structuredContent };\n },\n ),\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { McpContext, McpToolTransform } from "./types.cjs";
2
+ import { McpServer, Tool } from "@modelcontextprotocol/server";
3
+ import { AnyTRPCRouter } from "@trpc/server";
4
+ //#region src/tools.d.ts
5
+ /** An MCP tool definition built from a tRPC procedure. */
6
+ export type McpTool = Pick<Tool, "name" | "title" | "description" | "annotations" | "inputSchema"> & {
7
+ /** Dotted procedure path, e.g. `user.byId`. */
8
+ path: string;
9
+ type: "query" | "mutation";
10
+ /** Set when the procedure has an `.output()` validator that describes an object. */
11
+ outputSchema?: Tool["outputSchema"];
12
+ transform?: McpToolTransform;
13
+ };
14
+ /** Lists the MCP-enabled procedures of a router as MCP tool definitions. */
15
+ export declare function extractToolsFromProcedures(router: AnyTRPCRouter): McpTool[];
16
+ /**
17
+ * Registers every MCP-enabled procedure of `router` as a tool on `server`.
18
+ * Calls go through tRPC's normal pipeline (middlewares, input and output
19
+ * validation), and errors come back to the client as `isError` results.
20
+ */
21
+ export declare function registerTrpcTools<TRouter extends AnyTRPCRouter>(server: McpServer, router: TRouter, ctx: McpContext<TRouter>): import("@modelcontextprotocol/server").RegisteredTool[];
22
+ //#endregion
23
+ //# sourceMappingURL=tools.d.cts.map
package/dist/tools.d.mts CHANGED
@@ -1,16 +1,23 @@
1
- import { AnyRootTypes, RouterRecord, Router } from '@trpc/server/unstable-core-do-not-import';
2
- import { z } from 'zod/v4';
3
- import { TransformMcpProcedureFunction } from './types.mjs';
4
- import '@modelcontextprotocol/sdk/types.js';
5
-
6
- type McpTool = {
7
- name: string;
8
- description: string;
9
- pathInRouter: string[];
10
- inputSchema?: z.core.JSONSchema.JSONSchema;
11
- transformMcpProcedure?: TransformMcpProcedureFunction;
1
+ import { McpContext, McpToolTransform } from "./types.mjs";
2
+ import { McpServer, Tool } from "@modelcontextprotocol/server";
3
+ import { AnyTRPCRouter } from "@trpc/server";
4
+ //#region src/tools.d.ts
5
+ /** An MCP tool definition built from a tRPC procedure. */
6
+ export type McpTool = Pick<Tool, "name" | "title" | "description" | "annotations" | "inputSchema"> & {
7
+ /** Dotted procedure path, e.g. `user.byId`. */
8
+ path: string;
9
+ type: "query" | "mutation";
10
+ /** Set when the procedure has an `.output()` validator that describes an object. */
11
+ outputSchema?: Tool["outputSchema"];
12
+ transform?: McpToolTransform;
12
13
  };
13
- declare function mergeInputs(inputs: z.ZodObject[]): z.ZodObject<z.core.$ZodLooseShape, z.core.$strip>;
14
- declare function extractToolsFromProcedures<TRoot extends AnyRootTypes, TRecord extends RouterRecord>(appRouter: Router<TRoot, TRecord>, currentPath?: string[]): McpTool[];
15
-
16
- export { type McpTool, extractToolsFromProcedures, mergeInputs };
14
+ /** Lists the MCP-enabled procedures of a router as MCP tool definitions. */
15
+ export declare function extractToolsFromProcedures(router: AnyTRPCRouter): McpTool[];
16
+ /**
17
+ * Registers every MCP-enabled procedure of `router` as a tool on `server`.
18
+ * Calls go through tRPC's normal pipeline (middlewares, input and output
19
+ * validation), and errors come back to the client as `isError` results.
20
+ */
21
+ export declare function registerTrpcTools<TRouter extends AnyTRPCRouter>(server: McpServer, router: TRouter, ctx: McpContext<TRouter>): import("@modelcontextprotocol/server").RegisteredTool[];
22
+ //#endregion
23
+ //# sourceMappingURL=tools.d.mts.map
package/dist/tools.mjs CHANGED
@@ -1,3 +1,119 @@
1
- export { extractToolsFromProcedures, mergeInputs } from './chunk-ULLXW6IN.mjs';
2
- //# sourceMappingURL=tools.mjs.map
1
+ import { getMcpTransform } from "./helpers.mjs";
2
+ import { callTRPCProcedure } from "@trpc/server";
3
+ //#region src/tools.ts
4
+ const JSON_SCHEMA_OPTIONS = {
5
+ target: "draft-2020-12",
6
+ libraryOptions: { unrepresentable: "any" }
7
+ };
8
+ function hasJsonSchema(parser) {
9
+ if (typeof parser !== "object" && typeof parser !== "function") return false;
10
+ if (parser === null || !("~standard" in parser)) return false;
11
+ const standard = parser["~standard"];
12
+ return typeof standard === "object" && standard !== null && "jsonSchema" in standard && typeof standard.jsonSchema === "object";
13
+ }
14
+ function isObjectSchema(schema) {
15
+ return schema.type === "object";
16
+ }
17
+ function toInputSchema(inputs, path) {
18
+ const schemas = inputs.map((parser) => {
19
+ if (!hasJsonSchema(parser)) throw new TypeError(`[trpc-to-mcp] The input of "${path}" can't be converted to JSON Schema. Use a validator that implements Standard JSON Schema, such as zod >=4.2, ArkType, or Valibot with toStandardJsonSchema().`);
20
+ const schema = parser["~standard"].jsonSchema.input(JSON_SCHEMA_OPTIONS);
21
+ if (!isObjectSchema(schema)) throw new TypeError(`[trpc-to-mcp] The input of "${path}" must be an object schema, because MCP tool arguments are always an object.`);
22
+ return schema;
23
+ });
24
+ const [first, ...rest] = schemas;
25
+ if (!first) return {
26
+ type: "object",
27
+ properties: {}
28
+ };
29
+ if (rest.length === 0) return first;
30
+ return {
31
+ type: "object",
32
+ properties: Object.assign({}, ...schemas.map((s) => s.properties)),
33
+ required: [...new Set(schemas.flatMap((s) => s.required ?? []))]
34
+ };
35
+ }
36
+ function toOutputSchema(output) {
37
+ if (!hasJsonSchema(output)) return void 0;
38
+ try {
39
+ const schema = output["~standard"].jsonSchema.output(JSON_SCHEMA_OPTIONS);
40
+ return isObjectSchema(schema) ? schema : void 0;
41
+ } catch {
42
+ return;
43
+ }
44
+ }
45
+ /** Lists the MCP-enabled procedures of a router as MCP tool definitions. */
46
+ function extractToolsFromProcedures(router) {
47
+ const procedures = router._def.procedures;
48
+ const tools = [];
49
+ for (const [path, procedure] of Object.entries(procedures)) {
50
+ const { type, inputs, meta } = procedure._def;
51
+ const mcp = meta?.mcp;
52
+ if (!mcp?.enabled) continue;
53
+ if (type === "subscription") throw new TypeError(`[trpc-to-mcp] "${path}" is a subscription. Only queries and mutations can be MCP tools.`);
54
+ tools.push({
55
+ name: mcp.name ?? path.replace(/\./g, "_"),
56
+ title: mcp.title,
57
+ description: mcp.description,
58
+ annotations: type === "query" ? {
59
+ readOnlyHint: true,
60
+ ...mcp.annotations
61
+ } : mcp.annotations,
62
+ inputSchema: toInputSchema(inputs, path),
63
+ outputSchema: "output" in procedure._def ? toOutputSchema(procedure._def.output) : void 0,
64
+ path,
65
+ type,
66
+ transform: getMcpTransform(procedure)
67
+ });
68
+ }
69
+ return tools;
70
+ }
71
+ function advertise(schema) {
72
+ return { "~standard": {
73
+ version: 1,
74
+ vendor: "trpc-to-mcp",
75
+ validate: (value) => ({ value }),
76
+ jsonSchema: {
77
+ input: () => schema,
78
+ output: () => schema
79
+ }
80
+ } };
81
+ }
82
+ /**
83
+ * Registers every MCP-enabled procedure of `router` as a tool on `server`.
84
+ * Calls go through tRPC's normal pipeline (middlewares, input and output
85
+ * validation), and errors come back to the client as `isError` results.
86
+ */
87
+ function registerTrpcTools(server, router, ctx) {
88
+ const createContext = typeof ctx === "function" ? ctx : () => ctx;
89
+ return extractToolsFromProcedures(router).map((tool) => server.registerTool(tool.name, {
90
+ title: tool.title,
91
+ description: tool.description,
92
+ annotations: tool.annotations,
93
+ inputSchema: advertise(tool.inputSchema),
94
+ outputSchema: tool.outputSchema && advertise(tool.outputSchema)
95
+ }, async (args, mcpCtx) => {
96
+ const output = await callTRPCProcedure({
97
+ router,
98
+ path: tool.path,
99
+ type: tool.type,
100
+ ctx: await createContext(mcpCtx),
101
+ getRawInput: async () => args,
102
+ signal: mcpCtx.mcpReq.signal,
103
+ batchIndex: 0
104
+ });
105
+ const content = tool.transform ? await tool.transform(output) : [{
106
+ type: "text",
107
+ text: JSON.stringify(output ?? null)
108
+ }];
109
+ if (!tool.outputSchema) return { content };
110
+ return {
111
+ content,
112
+ structuredContent: output
113
+ };
114
+ }));
115
+ }
116
+ //#endregion
117
+ export { extractToolsFromProcedures, registerTrpcTools };
118
+
3
119
  //# sourceMappingURL=tools.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"tools.mjs"}
1
+ {"version":3,"file":"tools.mjs","names":[],"sources":["../src/tools.ts"],"sourcesContent":["import type {\n CallToolResult,\n McpServer,\n ServerContext,\n StandardSchemaWithJSON,\n Tool,\n} from \"@modelcontextprotocol/server\";\nimport {\n callTRPCProcedure,\n type AnyTRPCProcedure,\n type AnyTRPCRouter,\n} from \"@trpc/server\";\n\nimport { getMcpTransform } from \"./helpers\";\nimport type {\n McpContext,\n McpContextFactory,\n McpMeta,\n McpToolTransform,\n} from \"./types\";\n\n/** An MCP tool definition built from a tRPC procedure. */\nexport type McpTool = Pick<\n Tool,\n \"name\" | \"title\" | \"description\" | \"annotations\" | \"inputSchema\"\n> & {\n /** Dotted procedure path, e.g. `user.byId`. */\n path: string;\n type: \"query\" | \"mutation\";\n /** Set when the procedure has an `.output()` validator that describes an object. */\n outputSchema?: Tool[\"outputSchema\"];\n transform?: McpToolTransform;\n};\n\ntype JsonSchema = Record<string, unknown>;\n\n// Target and options passed to the Standard JSON Schema converters.\n// `unrepresentable: \"any\"` keeps zod from throwing on types like `z.date()`.\nconst JSON_SCHEMA_OPTIONS = {\n target: \"draft-2020-12\",\n libraryOptions: { unrepresentable: \"any\" },\n} as const;\n\nfunction hasJsonSchema(parser: unknown): parser is StandardSchemaWithJSON {\n if (typeof parser !== \"object\" && typeof parser !== \"function\") return false;\n if (parser === null || !(\"~standard\" in parser)) return false;\n const standard = parser[\"~standard\"];\n return (\n typeof standard === \"object\" &&\n standard !== null &&\n \"jsonSchema\" in standard &&\n typeof standard.jsonSchema === \"object\"\n );\n}\n\nfunction isObjectSchema(\n schema: JsonSchema,\n): schema is Tool[\"inputSchema\"] & JsonSchema {\n return schema.type === \"object\";\n}\n\n// Builds the tool input schema from the procedure's `.input()` parsers.\n// tRPC merges chained object inputs, so their properties are merged here too.\nfunction toInputSchema(inputs: unknown[], path: string): Tool[\"inputSchema\"] {\n const schemas = inputs.map((parser) => {\n if (!hasJsonSchema(parser)) {\n throw new TypeError(\n `[trpc-to-mcp] The input of \"${path}\" can't be converted to JSON Schema. Use a validator that implements Standard JSON Schema, such as zod >=4.2, ArkType, or Valibot with toStandardJsonSchema().`,\n );\n }\n const schema = parser[\"~standard\"].jsonSchema.input(JSON_SCHEMA_OPTIONS);\n if (!isObjectSchema(schema)) {\n throw new TypeError(\n `[trpc-to-mcp] The input of \"${path}\" must be an object schema, because MCP tool arguments are always an object.`,\n );\n }\n return schema;\n });\n\n const [first, ...rest] = schemas;\n if (!first) return { type: \"object\", properties: {} };\n if (rest.length === 0) return first;\n\n return {\n type: \"object\",\n properties: Object.assign({}, ...schemas.map((s) => s.properties)),\n required: [...new Set(schemas.flatMap((s) => s.required ?? []))],\n };\n}\n\n// Output schemas are optional in MCP, so any parser that can't produce an\n// object schema (for example one with transforms) is skipped.\nfunction toOutputSchema(output: unknown): Tool[\"outputSchema\"] {\n if (!hasJsonSchema(output)) return undefined;\n try {\n const schema = output[\"~standard\"].jsonSchema.output(JSON_SCHEMA_OPTIONS);\n return isObjectSchema(schema) ? schema : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Lists the MCP-enabled procedures of a router as MCP tool definitions. */\nexport function extractToolsFromProcedures(router: AnyTRPCRouter): McpTool[] {\n // `_def.procedures` is flat at runtime, keyed by the dotted procedure path.\n const procedures: Record<string, AnyTRPCProcedure> = router._def.procedures;\n const tools: McpTool[] = [];\n\n for (const [path, procedure] of Object.entries(procedures)) {\n const { type, inputs, meta } = procedure._def;\n // tRPC types procedure meta as `unknown`. It is `McpMeta` when the router\n // was built with `initTRPC.meta<McpMeta>()`.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n const mcp = (meta as McpMeta | undefined)?.mcp;\n if (!mcp?.enabled) continue;\n\n if (type === \"subscription\") {\n throw new TypeError(\n `[trpc-to-mcp] \"${path}\" is a subscription. Only queries and mutations can be MCP tools.`,\n );\n }\n\n tools.push({\n name: mcp.name ?? path.replace(/\\./g, \"_\"),\n title: mcp.title,\n description: mcp.description,\n annotations:\n type === \"query\"\n ? { readOnlyHint: true, ...mcp.annotations }\n : mcp.annotations,\n inputSchema: toInputSchema(inputs, path),\n outputSchema:\n \"output\" in procedure._def\n ? toOutputSchema(procedure._def.output)\n : undefined,\n path,\n type,\n transform: getMcpTransform(procedure),\n });\n }\n\n return tools;\n}\n\n// Registers a JSON Schema with the MCP SDK without validating against it.\n// tRPC runs the procedure's own parsers on every call, and validating twice\n// would apply zod transforms twice.\nfunction advertise(schema: JsonSchema): StandardSchemaWithJSON {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"trpc-to-mcp\",\n validate: (value) => ({ value }),\n jsonSchema: { input: () => schema, output: () => schema },\n },\n };\n}\n\n/**\n * Registers every MCP-enabled procedure of `router` as a tool on `server`.\n * Calls go through tRPC's normal pipeline (middlewares, input and output\n * validation), and errors come back to the client as `isError` results.\n */\nexport function registerTrpcTools<TRouter extends AnyTRPCRouter>(\n server: McpServer,\n router: TRouter,\n ctx: McpContext<TRouter>,\n) {\n // A tRPC context is never a function, so a function here is a context factory.\n const createContext =\n typeof ctx === \"function\" ? (ctx as McpContextFactory<TRouter>) : () => ctx;\n\n return extractToolsFromProcedures(router).map((tool) =>\n server.registerTool(\n tool.name,\n {\n title: tool.title,\n description: tool.description,\n annotations: tool.annotations,\n inputSchema: advertise(tool.inputSchema),\n outputSchema: tool.outputSchema && advertise(tool.outputSchema),\n },\n async (args, mcpCtx: ServerContext): Promise<CallToolResult> => {\n const output: unknown = await callTRPCProcedure({\n router,\n path: tool.path,\n type: tool.type,\n ctx: await createContext(mcpCtx),\n getRawInput: async () => args,\n signal: mcpCtx.mcpReq.signal,\n batchIndex: 0,\n });\n\n const content = tool.transform\n ? await tool.transform(output)\n : [{ type: \"text\" as const, text: JSON.stringify(output ?? null) }];\n\n if (!tool.outputSchema) return { content };\n\n // The procedure's `.output()` validator describes an object, and\n // tRPC ran it before returning.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n const structuredContent = output as Record<string, unknown>;\n return { content, structuredContent };\n },\n ),\n );\n}\n"],"mappings":";;;AAsCA,MAAM,sBAAsB;CAC1B,QAAQ;CACR,gBAAgB,EAAE,iBAAiB,MAAM;AAC3C;AAEA,SAAS,cAAc,QAAmD;CACxE,IAAI,OAAO,WAAW,YAAY,OAAO,WAAW,YAAY,OAAO;CACvE,IAAI,WAAW,QAAQ,EAAE,eAAe,SAAS,OAAO;CACxD,MAAM,WAAW,OAAO;CACxB,OACE,OAAO,aAAa,YACpB,aAAa,QACb,gBAAgB,YAChB,OAAO,SAAS,eAAe;AAEnC;AAEA,SAAS,eACP,QAC4C;CAC5C,OAAO,OAAO,SAAS;AACzB;AAIA,SAAS,cAAc,QAAmB,MAAmC;CAC3E,MAAM,UAAU,OAAO,KAAK,WAAW;EACrC,IAAI,CAAC,cAAc,MAAM,GACvB,MAAM,IAAI,UACR,+BAA+B,KAAK,+JACtC;EAEF,MAAM,SAAS,OAAO,YAAY,CAAC,WAAW,MAAM,mBAAmB;EACvE,IAAI,CAAC,eAAe,MAAM,GACxB,MAAM,IAAI,UACR,+BAA+B,KAAK,6EACtC;EAEF,OAAO;CACT,CAAC;CAED,MAAM,CAAC,OAAO,GAAG,QAAQ;CACzB,IAAI,CAAC,OAAO,OAAO;EAAE,MAAM;EAAU,YAAY,CAAC;CAAE;CACpD,IAAI,KAAK,WAAW,GAAG,OAAO;CAE9B,OAAO;EACL,MAAM;EACN,YAAY,OAAO,OAAO,CAAC,GAAG,GAAG,QAAQ,KAAK,MAAM,EAAE,UAAU,CAAC;EACjE,UAAU,CAAC,GAAG,IAAI,IAAI,QAAQ,SAAS,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;CACjE;AACF;AAIA,SAAS,eAAe,QAAuC;CAC7D,IAAI,CAAC,cAAc,MAAM,GAAG,OAAO,KAAA;CACnC,IAAI;EACF,MAAM,SAAS,OAAO,YAAY,CAAC,WAAW,OAAO,mBAAmB;EACxE,OAAO,eAAe,MAAM,IAAI,SAAS,KAAA;CAC3C,QAAQ;EACN;CACF;AACF;;AAGA,SAAgB,2BAA2B,QAAkC;CAE3E,MAAM,aAA+C,OAAO,KAAK;CACjE,MAAM,QAAmB,CAAC;CAE1B,KAAK,MAAM,CAAC,MAAM,cAAc,OAAO,QAAQ,UAAU,GAAG;EAC1D,MAAM,EAAE,MAAM,QAAQ,SAAS,UAAU;EAIzC,MAAM,MAAO,MAA8B;EAC3C,IAAI,CAAC,KAAK,SAAS;EAEnB,IAAI,SAAS,gBACX,MAAM,IAAI,UACR,kBAAkB,KAAK,kEACzB;EAGF,MAAM,KAAK;GACT,MAAM,IAAI,QAAQ,KAAK,QAAQ,OAAO,GAAG;GACzC,OAAO,IAAI;GACX,aAAa,IAAI;GACjB,aACE,SAAS,UACL;IAAE,cAAc;IAAM,GAAG,IAAI;GAAY,IACzC,IAAI;GACV,aAAa,cAAc,QAAQ,IAAI;GACvC,cACE,YAAY,UAAU,OAClB,eAAe,UAAU,KAAK,MAAM,IACpC,KAAA;GACN;GACA;GACA,WAAW,gBAAgB,SAAS;EACtC,CAAC;CACH;CAEA,OAAO;AACT;AAKA,SAAS,UAAU,QAA4C;CAC7D,OAAO,EACL,aAAa;EACX,SAAS;EACT,QAAQ;EACR,WAAW,WAAW,EAAE,MAAM;EAC9B,YAAY;GAAE,aAAa;GAAQ,cAAc;EAAO;CAC1D,EACF;AACF;;;;;;AAOA,SAAgB,kBACd,QACA,QACA,KACA;CAEA,MAAM,gBACJ,OAAO,QAAQ,aAAc,YAA2C;CAE1E,OAAO,2BAA2B,MAAM,CAAC,CAAC,KAAK,SAC7C,OAAO,aACL,KAAK,MACL;EACE,OAAO,KAAK;EACZ,aAAa,KAAK;EAClB,aAAa,KAAK;EAClB,aAAa,UAAU,KAAK,WAAW;EACvC,cAAc,KAAK,gBAAgB,UAAU,KAAK,YAAY;CAChE,GACA,OAAO,MAAM,WAAmD;EAC9D,MAAM,SAAkB,MAAM,kBAAkB;GAC9C;GACA,MAAM,KAAK;GACX,MAAM,KAAK;GACX,KAAK,MAAM,cAAc,MAAM;GAC/B,aAAa,YAAY;GACzB,QAAQ,OAAO,OAAO;GACtB,YAAY;EACd,CAAC;EAED,MAAM,UAAU,KAAK,YACjB,MAAM,KAAK,UAAU,MAAM,IAC3B,CAAC;GAAE,MAAM;GAAiB,MAAM,KAAK,UAAU,UAAU,IAAI;EAAE,CAAC;EAEpE,IAAI,CAAC,KAAK,cAAc,OAAO,EAAE,QAAQ;EAMzC,OAAO;GAAE;GAAS,mBAAA;EAAkB;CACtC,CACF,CACF;AACF"}
package/dist/types.cjs ADDED
File without changes
@@ -0,0 +1,31 @@
1
+ import { ContentBlock, ServerContext, ToolAnnotations } from "@modelcontextprotocol/server";
2
+ import { AnyTRPCRouter, inferRouterContext } from "@trpc/server";
3
+ //#region src/types.d.ts
4
+ export type MaybePromise<T> = T | Promise<T>;
5
+ /**
6
+ * Procedure meta read by trpc-to-mcp. Pass it to `initTRPC.meta<McpMeta>()`
7
+ * and set `mcp.enabled` on each procedure you want to expose as a tool.
8
+ */
9
+ export type McpMeta = {
10
+ mcp?: {
11
+ enabled?: boolean;
12
+ /** Tool name. Defaults to the procedure path with dots replaced by underscores. */
13
+ name?: string;
14
+ /** Human-readable name shown by MCP clients. */
15
+ title?: string;
16
+ description?: string;
17
+ /** Hints for MCP clients. Queries get `readOnlyHint: true` unless you override it. */
18
+ annotations?: ToolAnnotations;
19
+ };
20
+ };
21
+ /** Turns a procedure's output into MCP content. Set with `transformMcpProcedure`. */
22
+ export type McpToolTransform = (output: unknown) => MaybePromise<ContentBlock[]>;
23
+ /**
24
+ * Creates the tRPC context for a tool call. It receives the MCP request
25
+ * context, so it can read `ctx.http?.authInfo` and `ctx.http?.req`.
26
+ */
27
+ export type McpContextFactory<TRouter extends AnyTRPCRouter> = (ctx: ServerContext) => MaybePromise<inferRouterContext<TRouter>>;
28
+ /** The tRPC context for tool calls: a fixed value or a per-call factory. */
29
+ export type McpContext<TRouter extends AnyTRPCRouter> = inferRouterContext<TRouter> | McpContextFactory<TRouter>;
30
+ //#endregion
31
+ //# sourceMappingURL=types.d.cts.map
package/dist/types.d.mts CHANGED
@@ -1,14 +1,31 @@
1
- import { ContentBlock } from '@modelcontextprotocol/sdk/types.js';
2
- import { inferProcedureOutput, AnyProcedure, MaybePromise } from '@trpc/server/unstable-core-do-not-import';
3
-
4
- type McpMeta = {
5
- mcp?: {
6
- enabled?: boolean;
7
- description?: string;
8
- name?: string;
9
- transformMcpProcedure?: TransformMcpProcedureFunction;
10
- };
1
+ import { ContentBlock, ServerContext, ToolAnnotations } from "@modelcontextprotocol/server";
2
+ import { AnyTRPCRouter, inferRouterContext } from "@trpc/server";
3
+ //#region src/types.d.ts
4
+ export type MaybePromise<T> = T | Promise<T>;
5
+ /**
6
+ * Procedure meta read by trpc-to-mcp. Pass it to `initTRPC.meta<McpMeta>()`
7
+ * and set `mcp.enabled` on each procedure you want to expose as a tool.
8
+ */
9
+ export type McpMeta = {
10
+ mcp?: {
11
+ enabled?: boolean;
12
+ /** Tool name. Defaults to the procedure path with dots replaced by underscores. */
13
+ name?: string;
14
+ /** Human-readable name shown by MCP clients. */
15
+ title?: string;
16
+ description?: string;
17
+ /** Hints for MCP clients. Queries get `readOnlyHint: true` unless you override it. */
18
+ annotations?: ToolAnnotations;
19
+ };
11
20
  };
12
- type TransformMcpProcedureFunction = (output: inferProcedureOutput<AnyProcedure>) => MaybePromise<ContentBlock[]>;
13
-
14
- export type { McpMeta, TransformMcpProcedureFunction };
21
+ /** Turns a procedure's output into MCP content. Set with `transformMcpProcedure`. */
22
+ export type McpToolTransform = (output: unknown) => MaybePromise<ContentBlock[]>;
23
+ /**
24
+ * Creates the tRPC context for a tool call. It receives the MCP request
25
+ * context, so it can read `ctx.http?.authInfo` and `ctx.http?.req`.
26
+ */
27
+ export type McpContextFactory<TRouter extends AnyTRPCRouter> = (ctx: ServerContext) => MaybePromise<inferRouterContext<TRouter>>;
28
+ /** The tRPC context for tool calls: a fixed value or a per-call factory. */
29
+ export type McpContext<TRouter extends AnyTRPCRouter> = inferRouterContext<TRouter> | McpContextFactory<TRouter>;
30
+ //#endregion
31
+ //# sourceMappingURL=types.d.mts.map
package/dist/types.mjs CHANGED
@@ -1,3 +1 @@
1
- import './chunk-KIQOUUEZ.mjs';
2
- //# sourceMappingURL=types.mjs.map
3
- //# sourceMappingURL=types.mjs.map
1
+ export {};