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.
- package/README.md +138 -178
- package/dist/adapters/vercel-mcp-adapter.cjs +19 -0
- package/dist/adapters/vercel-mcp-adapter.cjs.map +1 -0
- package/dist/adapters/vercel-mcp-adapter.d.cts +17 -0
- package/dist/adapters/vercel-mcp-adapter.d.mts +16 -13
- package/dist/adapters/vercel-mcp-adapter.mjs +15 -27
- package/dist/adapters/vercel-mcp-adapter.mjs.map +1 -1
- package/dist/helpers.cjs +20 -0
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +13 -0
- package/dist/helpers.d.mts +13 -6
- package/dist/helpers.mjs +17 -2
- package/dist/helpers.mjs.map +1 -1
- package/dist/index.cjs +9 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -10
- package/dist/index.mjs +5 -6
- package/dist/server.cjs +18 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +12 -0
- package/dist/server.d.mts +12 -12
- package/dist/server.mjs +16 -3
- package/dist/server.mjs.map +1 -1
- package/dist/tools.cjs +121 -0
- package/dist/tools.cjs.map +1 -0
- package/dist/tools.d.cts +23 -0
- package/dist/tools.d.mts +22 -15
- package/dist/tools.mjs +118 -2
- package/dist/tools.mjs.map +1 -1
- package/dist/types.cjs +0 -0
- package/dist/types.d.cts +31 -0
- package/dist/types.d.mts +30 -13
- package/dist/types.mjs +1 -3
- package/package.json +55 -73
- package/dist/adapters/vercel-mcp-adapter.d.ts +0 -14
- package/dist/adapters/vercel-mcp-adapter.js +0 -32
- package/dist/adapters/vercel-mcp-adapter.js.map +0 -1
- package/dist/chunk-55J6XMHW.js +0 -4
- package/dist/chunk-55J6XMHW.js.map +0 -1
- package/dist/chunk-7GYUHEUD.mjs +0 -47
- package/dist/chunk-7GYUHEUD.mjs.map +0 -1
- package/dist/chunk-BTXMEL6M.js +0 -55
- package/dist/chunk-BTXMEL6M.js.map +0 -1
- package/dist/chunk-FIQIIJAT.mjs +0 -11
- package/dist/chunk-FIQIIJAT.mjs.map +0 -1
- package/dist/chunk-FT3KTYAU.js +0 -13
- package/dist/chunk-FT3KTYAU.js.map +0 -1
- package/dist/chunk-KIQOUUEZ.mjs +0 -3
- package/dist/chunk-KIQOUUEZ.mjs.map +0 -1
- package/dist/chunk-RJJMUGXY.js +0 -50
- package/dist/chunk-RJJMUGXY.js.map +0 -1
- package/dist/chunk-ULLXW6IN.mjs +0 -52
- package/dist/chunk-ULLXW6IN.mjs.map +0 -1
- package/dist/helpers.d.ts +0 -6
- package/dist/helpers.js +0 -12
- package/dist/helpers.js.map +0 -1
- package/dist/index.d.ts +0 -10
- package/dist/index.js +0 -31
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/server.d.ts +0 -12
- package/dist/server.js +0 -17
- package/dist/server.js.map +0 -1
- package/dist/tools.d.ts +0 -16
- package/dist/tools.js +0 -16
- package/dist/tools.js.map +0 -1
- package/dist/types.d.ts +0 -14
- package/dist/types.js +0 -6
- package/dist/types.js.map +0 -1
- package/dist/types.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,257 +1,217 @@
|
|
|
1
|
-
|
|
1
|
+
# trpc-to-mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Turn the tRPC procedures you choose into MCP tools.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
- Works with tRPC v11 and `@modelcontextprotocol/server` v2, the MCP TypeScript SDK
|
|
6
|
+
- [Serve tools over stdio or HTTP](#serve-your-tools)
|
|
7
|
+
- [Use the tRPC context and middlewares on every tool call](#context)
|
|
8
|
+
- [Transform outputs into text, images, or other MCP content](#transform-outputs)
|
|
9
|
+
- [Return structured content from procedures with an output schema](#structured-output)
|
|
10
|
+
- [Mount on Next.js and other frameworks with mcp-handler](#mcp-handler)
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
<details>
|
|
13
|
+
<summary>Why only the procedures you choose?</summary>
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
An MCP tool is something a language model decides to call on its own, so expose only the procedures you want a model to use. A model picks a tool based on its name, description, and input schema. Give each exposed procedure a clear name, a description of what it does and when to use it, and a `.describe()` on each input field.
|
|
13
16
|
|
|
14
17
|
</details>
|
|
15
18
|
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
- Support for tRPC v11
|
|
19
|
-
- [Transform your JSON outputs into human-language with custom helpers](#transform-output)
|
|
20
|
-
- [Turn your tRPC router into MCP tools](#to-mcp-tools)
|
|
21
|
-
- [Turn your tRPC router into MCP server](#to-mcp-server)
|
|
22
|
-
- [Turn your tRPC router into @vercel/mcp-adapter handler](#to-vercel-mcp-adapter)
|
|
23
|
-
|
|
24
|
-
## Usage
|
|
25
|
-
|
|
26
|
-
1. Install trpc-to-mcp
|
|
19
|
+
## Install
|
|
27
20
|
|
|
28
21
|
```bash
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
pnpm add trpc-to-mcp
|
|
22
|
+
pnpm add trpc-to-mcp @modelcontextprotocol/server
|
|
23
|
+
```
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
`@trpc/server` 11 and `@modelcontextprotocol/server` 2 are peer dependencies. Node.js 20 or later is required.
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
```
|
|
27
|
+
## Usage
|
|
37
28
|
|
|
38
|
-
|
|
29
|
+
1. Add `McpMeta` to your tRPC instance.
|
|
39
30
|
|
|
40
31
|
```typescript
|
|
41
32
|
import { initTRPC } from "@trpc/server";
|
|
42
33
|
import { type McpMeta } from "trpc-to-mcp";
|
|
43
34
|
|
|
44
|
-
const t = initTRPC.meta<McpMeta>().create();
|
|
35
|
+
const t = initTRPC.context<Context>().meta<McpMeta>().create();
|
|
45
36
|
```
|
|
46
37
|
|
|
47
|
-
|
|
38
|
+
2. Enable `mcp` on the procedures you want as tools.
|
|
48
39
|
|
|
49
40
|
```typescript
|
|
41
|
+
import { z } from "zod";
|
|
42
|
+
|
|
50
43
|
export const appRouter = t.router({
|
|
51
44
|
hello: t.procedure
|
|
52
45
|
.meta({
|
|
53
46
|
mcp: {
|
|
54
47
|
enabled: true,
|
|
55
|
-
description: "Say hello to
|
|
56
|
-
//
|
|
57
|
-
//
|
|
48
|
+
description: "Say hello to someone",
|
|
49
|
+
// Optional. Defaults to the procedure path with dots replaced by
|
|
50
|
+
// underscores, e.g. "hello" or "user_byId".
|
|
58
51
|
name: "say_hello",
|
|
59
52
|
},
|
|
60
53
|
})
|
|
61
|
-
.input(
|
|
62
|
-
|
|
63
|
-
name: z.string(),
|
|
64
|
-
}),
|
|
65
|
-
)
|
|
66
|
-
.query(({ input }) => {
|
|
67
|
-
return { greeting: `Hello ${input.name}` };
|
|
68
|
-
}),
|
|
54
|
+
.input(z.object({ name: z.string().describe("Who to greet") }))
|
|
55
|
+
.query(({ input }) => `Hello ${input.name}`),
|
|
69
56
|
});
|
|
70
57
|
```
|
|
71
58
|
|
|
72
|
-
|
|
59
|
+
Inputs must be object schemas from a validator that implements [Standard JSON Schema](https://standardschema.dev), such as zod 4.2 or later, ArkType, or Valibot with `toStandardJsonSchema()`. Chained `.input()` calls are merged into one tool input schema. Subscriptions can't be tools.
|
|
73
60
|
|
|
74
|
-
|
|
61
|
+
tRPC validates input on every call, so your zod transforms and refinements run as usual. Errors thrown by a procedure, including `TRPCError`, come back to the client as a tool result with `isError: true`.
|
|
75
62
|
|
|
76
|
-
|
|
63
|
+
`meta.mcp` also takes `title` and `annotations`. Queries get `readOnlyHint: true` unless you set it yourself.
|
|
77
64
|
|
|
78
|
-
|
|
79
|
-
import { initTRPC } from "@trpc/server";
|
|
80
|
-
import { z } from "zod";
|
|
65
|
+
## Serve your tools
|
|
81
66
|
|
|
82
|
-
|
|
67
|
+
`createMcpServer` returns an `McpServer` with your tools registered. You can register more tools, prompts, and resources on it.
|
|
83
68
|
|
|
84
|
-
|
|
69
|
+
Over stdio:
|
|
85
70
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
.meta({
|
|
90
|
-
mcp: {
|
|
91
|
-
enabled: true,
|
|
92
|
-
description: "Send a message",
|
|
93
|
-
name: "send_message",
|
|
94
|
-
},
|
|
95
|
-
})
|
|
96
|
-
.input(
|
|
97
|
-
z.object({
|
|
98
|
-
message: z.string(),
|
|
99
|
-
}),
|
|
100
|
-
)
|
|
101
|
-
.query(({ input }) => {
|
|
102
|
-
return {
|
|
103
|
-
payload: {
|
|
104
|
-
from: "trpc",
|
|
105
|
-
message: input.message,
|
|
106
|
-
array: [{ a: 1 }, { b: 2 }],
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
}),
|
|
110
|
-
(output) => {
|
|
111
|
-
return [
|
|
112
|
-
...output.payload.array.map((item) => {
|
|
113
|
-
const [name, value] = Object.entries(item);
|
|
114
|
-
return {
|
|
115
|
-
type: "text" as const,
|
|
116
|
-
text: `${name} is ${value} letter of alphabet`,
|
|
117
|
-
};
|
|
118
|
-
}),
|
|
119
|
-
{
|
|
120
|
-
type: "image",
|
|
121
|
-
data: "...",
|
|
122
|
-
mimeType: "",
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
type: "audio", // or even "resource" | "resource_link"
|
|
126
|
-
data: "...",
|
|
127
|
-
mimeType: "",
|
|
128
|
-
},
|
|
129
|
-
];
|
|
130
|
-
},
|
|
131
|
-
),
|
|
132
|
-
});
|
|
133
|
-
```
|
|
71
|
+
```typescript
|
|
72
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
73
|
+
import { createMcpServer } from "trpc-to-mcp";
|
|
134
74
|
|
|
135
|
-
|
|
75
|
+
serveStdio(() =>
|
|
76
|
+
createMcpServer({ name: "my-app", version: "1.0.0" }, appRouter, { db }),
|
|
77
|
+
);
|
|
78
|
+
```
|
|
136
79
|
|
|
137
|
-
|
|
80
|
+
Over HTTP, with the SDK's `createMcpHandler` on any runtime with web-standard `Request` and `Response`:
|
|
138
81
|
|
|
139
82
|
```typescript
|
|
140
|
-
import {
|
|
141
|
-
import {
|
|
83
|
+
import { createMcpHandler } from "@modelcontextprotocol/server";
|
|
84
|
+
import { createMcpServer } from "trpc-to-mcp";
|
|
142
85
|
|
|
143
|
-
const
|
|
86
|
+
const handler = createMcpHandler(() =>
|
|
87
|
+
createMcpServer({ name: "my-app", version: "1.0.0" }, appRouter, { db }),
|
|
88
|
+
);
|
|
144
89
|
|
|
145
|
-
|
|
90
|
+
export default { fetch: handler.fetch };
|
|
91
|
+
```
|
|
146
92
|
|
|
147
|
-
|
|
148
|
-
{
|
|
149
|
-
name: "Tool name",
|
|
150
|
-
description: "Description of the tool",
|
|
151
|
-
pathInRouter: [...],
|
|
152
|
-
inputSchema: JSONSchema // this if full JSON schema from your zod schema
|
|
153
|
-
},
|
|
154
|
-
...
|
|
155
|
-
]
|
|
93
|
+
To add tools to an `McpServer` you created yourself, call `registerTrpcTools(server, appRouter, ctx)`.
|
|
156
94
|
|
|
157
|
-
|
|
95
|
+
## Context
|
|
96
|
+
|
|
97
|
+
The third argument is the tRPC context. Pass a value, or a function that creates the context on each tool call. The function receives the MCP request context, so it can read the HTTP request and the auth info from your auth middleware.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
createMcpServer({ name: "my-app", version: "1.0.0" }, appRouter, (ctx) => ({
|
|
101
|
+
db,
|
|
102
|
+
headers: ctx.http?.req?.headers,
|
|
103
|
+
auth: ctx.http?.authInfo,
|
|
104
|
+
}));
|
|
158
105
|
```
|
|
159
106
|
|
|
160
|
-
|
|
107
|
+
Tool calls run through your tRPC middlewares, so auth checks in a `protectedProcedure` apply to MCP clients too.
|
|
161
108
|
|
|
162
|
-
|
|
109
|
+
## Transform outputs
|
|
110
|
+
|
|
111
|
+
By default a tool returns the procedure output as JSON text. To return something easier for a model to read, wrap the procedure with `transformMcpProcedure` and return MCP content blocks. The `output` argument is typed from the procedure.
|
|
163
112
|
|
|
164
113
|
```typescript
|
|
165
|
-
import {
|
|
166
|
-
import { createMcpServer } from "trpc-to-mcp";
|
|
114
|
+
import { transformMcpProcedure } from "trpc-to-mcp";
|
|
167
115
|
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
116
|
+
export const appRouter = t.router({
|
|
117
|
+
weather: transformMcpProcedure(
|
|
118
|
+
t.procedure
|
|
119
|
+
.meta({
|
|
120
|
+
mcp: { enabled: true, description: "Current weather in a city" },
|
|
121
|
+
})
|
|
122
|
+
.input(z.object({ city: z.string() }))
|
|
123
|
+
.query(({ input }) => getWeather(input.city)),
|
|
124
|
+
(output) => [
|
|
125
|
+
{ type: "text", text: `${output.city}: ${output.temperature}°C` },
|
|
126
|
+
{ type: "image", data: output.radarPng, mimeType: "image/png" },
|
|
127
|
+
],
|
|
128
|
+
),
|
|
129
|
+
});
|
|
130
|
+
```
|
|
173
131
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
132
|
+
The content types are `text`, `image`, `audio`, `resource`, and `resource_link`. The procedure still returns its normal output to tRPC clients.
|
|
133
|
+
|
|
134
|
+
## Structured output
|
|
135
|
+
|
|
136
|
+
If a procedure has an `.output()` validator that describes an object, the tool advertises it as an `outputSchema` and returns the output as `structuredContent` next to the text content.
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
t.procedure
|
|
140
|
+
.meta({ mcp: { enabled: true, description: "Look up a user" } })
|
|
141
|
+
.input(z.object({ id: z.string() }))
|
|
142
|
+
.output(z.object({ id: z.string(), name: z.string() }))
|
|
143
|
+
.query(({ input }) => db.user.find(input.id));
|
|
180
144
|
```
|
|
181
145
|
|
|
182
|
-
##
|
|
146
|
+
## mcp-handler
|
|
183
147
|
|
|
184
|
-
|
|
148
|
+
[mcp-handler](https://github.com/vercel/mcp-handler) turns an MCP server into a `(Request) => Promise<Response>` handler for Next.js, Nuxt, SvelteKit, Hono, and other frameworks. Install `mcp-handler` 2, then:
|
|
185
149
|
|
|
186
150
|
```typescript
|
|
187
|
-
// app/api/
|
|
151
|
+
// app/api/mcp/route.ts
|
|
188
152
|
import { trpcToMcpHandler } from "trpc-to-mcp/adapters/vercel-mcp-adapter";
|
|
189
153
|
|
|
190
|
-
const handler =
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
verboseLogs: true,
|
|
196
|
-
maxDuration: 60,
|
|
154
|
+
const handler = trpcToMcpHandler(appRouter, createContext, {
|
|
155
|
+
// mcp-handler options
|
|
156
|
+
serverOptions: {
|
|
157
|
+
serverInfo: { name: "my-app", version: "1.0.0" },
|
|
158
|
+
verboseLogs: process.env.NODE_ENV === "development",
|
|
197
159
|
},
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
callback: (server) => {
|
|
201
|
-
// You can modify the McpServer instance
|
|
202
|
-
}
|
|
160
|
+
// Register extra tools, prompts, or resources
|
|
161
|
+
callback: (server) => {},
|
|
203
162
|
});
|
|
204
163
|
|
|
205
|
-
export { handler as
|
|
164
|
+
export { handler as GET, handler as POST };
|
|
206
165
|
```
|
|
207
166
|
|
|
167
|
+
mcp-handler serves requests without sessions, so there is no Redis setup and no `basePath`. Mount the handler at any route.
|
|
168
|
+
|
|
208
169
|
## Use with better-auth
|
|
209
170
|
|
|
210
|
-
|
|
171
|
+
The [`@better-auth/mcp`](https://www.better-auth.com/docs/plugins/mcp) plugin makes your better-auth app an OAuth authorization server for MCP clients. Put your handler behind `requireMcpAuth`, and read the user ID from the access token claims.
|
|
211
172
|
|
|
212
173
|
```typescript
|
|
213
|
-
// app/api/
|
|
214
|
-
|
|
215
|
-
import {
|
|
216
|
-
import {
|
|
174
|
+
// app/api/mcp/route.ts
|
|
175
|
+
import { requireMcpAuth } from "@better-auth/mcp";
|
|
176
|
+
import { createMcpHandler } from "@modelcontextprotocol/server";
|
|
177
|
+
import { createMcpServer } from "trpc-to-mcp";
|
|
217
178
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
// Retrieve the session from database via userId inside mcpSession
|
|
228
|
-
const session = await getSession(mcpSession);
|
|
229
|
-
|
|
230
|
-
const handler = trpcToMcpHandler(
|
|
231
|
-
appRouter,
|
|
232
|
-
// Pass your tRPC context here
|
|
233
|
-
{
|
|
234
|
-
db,
|
|
235
|
-
headers: request.headers,
|
|
236
|
-
session: session?.session,
|
|
237
|
-
user: session?.user,
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
config: {
|
|
241
|
-
basePath: "/api",
|
|
242
|
-
// Disable in production
|
|
243
|
-
verboseLogs: true,
|
|
244
|
-
maxDuration: 60,
|
|
245
|
-
},
|
|
246
|
-
},
|
|
179
|
+
export const POST = requireMcpAuth(auth, (request, claims) => {
|
|
180
|
+
const handler = createMcpHandler(
|
|
181
|
+
() =>
|
|
182
|
+
createMcpServer({ name: "my-app", version: "1.0.0" }, appRouter, {
|
|
183
|
+
db,
|
|
184
|
+
userId: claims.sub,
|
|
185
|
+
}),
|
|
186
|
+
// @better-auth/mcp recommends serving only the 2026-07-28 protocol.
|
|
187
|
+
{ legacy: "reject" },
|
|
247
188
|
);
|
|
248
189
|
|
|
249
|
-
return
|
|
190
|
+
return handler.fetch(request);
|
|
250
191
|
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## List tools without a server
|
|
251
195
|
|
|
252
|
-
|
|
196
|
+
`extractToolsFromProcedures` returns the tool definitions, including JSON input schemas, without creating a server.
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
import { extractToolsFromProcedures } from "trpc-to-mcp";
|
|
200
|
+
|
|
201
|
+
const tools = extractToolsFromProcedures(appRouter);
|
|
202
|
+
// [{ name: "say_hello", description: "...", path: "hello", type: "query", inputSchema: {...} }]
|
|
253
203
|
```
|
|
254
204
|
|
|
205
|
+
## Upgrading from 1.x
|
|
206
|
+
|
|
207
|
+
- Replace `@modelcontextprotocol/sdk` with `@modelcontextprotocol/server` 2, and upgrade `mcp-handler` to 2 if you use the adapter.
|
|
208
|
+
- In `trpcToMcpHandler`, remove `config`. Move `verboseLogs` into `serverOptions`, and mount the handler at the route you want.
|
|
209
|
+
- Use zod 4.2 or later, or another validator with Standard JSON Schema support.
|
|
210
|
+
- Replace `setRequestHandler(server.server, tools, caller)` with `registerTrpcTools(server, appRouter, ctx)`.
|
|
211
|
+
- `McpTool.pathInRouter` is now `McpTool.path`, a dotted string.
|
|
212
|
+
|
|
213
|
+
See [CHANGELOG.md](./CHANGELOG.md) for the full list.
|
|
214
|
+
|
|
255
215
|
## Result
|
|
256
216
|
|
|
257
217
|
Now you can chill and add MCP to your VC-backed startup so your investors won't worry, and profit
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_tools = require("../tools.cjs");
|
|
3
|
+
let mcp_handler = require("mcp-handler");
|
|
4
|
+
//#region src/adapters/vercel-mcp-adapter.ts
|
|
5
|
+
/**
|
|
6
|
+
* Creates an `mcp-handler` request handler, a `(Request) => Promise<Response>`
|
|
7
|
+
* you can mount as a Next.js route or in any Fetch-compatible framework.
|
|
8
|
+
* Use `callback` to register extra tools, prompts, or resources.
|
|
9
|
+
*/
|
|
10
|
+
function trpcToMcpHandler(router, ctx, options = {}) {
|
|
11
|
+
return (0, mcp_handler.createMcpHandler)(async (server) => {
|
|
12
|
+
require_tools.registerTrpcTools(server, router, ctx);
|
|
13
|
+
await options.callback?.(server);
|
|
14
|
+
}, options.serverOptions);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
exports.trpcToMcpHandler = trpcToMcpHandler;
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=vercel-mcp-adapter.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vercel-mcp-adapter.cjs","names":["createMcpHandler"],"sources":["../../src/adapters/vercel-mcp-adapter.ts"],"sourcesContent":["import type { McpServer } from \"@modelcontextprotocol/server\";\nimport type { AnyTRPCRouter } from \"@trpc/server\";\nimport { createMcpHandler, type McpHandlerOptions } from \"mcp-handler\";\n\nimport { registerTrpcTools } from \"../tools\";\nimport type { MaybePromise, McpContext } from \"../types\";\n\nexport type { McpHandlerOptions };\n\n/**\n * Creates an `mcp-handler` request handler, a `(Request) => Promise<Response>`\n * you can mount as a Next.js route or in any Fetch-compatible framework.\n * Use `callback` to register extra tools, prompts, or resources.\n */\nexport function trpcToMcpHandler<TRouter extends AnyTRPCRouter>(\n router: TRouter,\n ctx: McpContext<TRouter>,\n options: {\n serverOptions?: McpHandlerOptions;\n callback?: (server: McpServer) => MaybePromise<void>;\n } = {},\n) {\n return createMcpHandler(async (server) => {\n registerTrpcTools(server, router, ctx);\n await options.callback?.(server);\n }, options.serverOptions);\n}\n"],"mappings":";;;;;;;;;AAcA,SAAgB,iBACd,QACA,KACA,UAGI,CAAC,GACL;CACA,QAAA,GAAOA,YAAAA,iBAAAA,CAAiB,OAAO,WAAW;EACxC,cAAA,kBAAkB,QAAQ,QAAQ,GAAG;EACrC,MAAM,QAAQ,WAAW,MAAM;CACjC,GAAG,QAAQ,aAAa;AAC1B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { MaybePromise, McpContext } from "../types.cjs";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
3
|
+
import { AnyTRPCRouter } from "@trpc/server";
|
|
4
|
+
import { McpHandlerOptions } from "mcp-handler";
|
|
5
|
+
//#region src/adapters/vercel-mcp-adapter.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Creates an `mcp-handler` request handler, a `(Request) => Promise<Response>`
|
|
8
|
+
* you can mount as a Next.js route or in any Fetch-compatible framework.
|
|
9
|
+
* Use `callback` to register extra tools, prompts, or resources.
|
|
10
|
+
*/
|
|
11
|
+
export declare function trpcToMcpHandler<TRouter extends AnyTRPCRouter>(router: TRouter, ctx: McpContext<TRouter>, options?: {
|
|
12
|
+
serverOptions?: McpHandlerOptions;
|
|
13
|
+
callback?: (server: McpServer) => MaybePromise<void>;
|
|
14
|
+
}): (request: Request) => Promise<Response>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export type { McpHandlerOptions };
|
|
17
|
+
//# sourceMappingURL=vercel-mcp-adapter.d.cts.map
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { MaybePromise, McpContext } from "../types.mjs";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
3
|
+
import { AnyTRPCRouter } from "@trpc/server";
|
|
4
|
+
import { McpHandlerOptions } from "mcp-handler";
|
|
5
|
+
//#region src/adapters/vercel-mcp-adapter.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Creates an `mcp-handler` request handler, a `(Request) => Promise<Response>`
|
|
8
|
+
* you can mount as a Next.js route or in any Fetch-compatible framework.
|
|
9
|
+
* Use `callback` to register extra tools, prompts, or resources.
|
|
10
|
+
*/
|
|
11
|
+
export declare function trpcToMcpHandler<TRouter extends AnyTRPCRouter>(router: TRouter, ctx: McpContext<TRouter>, options?: {
|
|
12
|
+
serverOptions?: McpHandlerOptions;
|
|
13
|
+
callback?: (server: McpServer) => MaybePromise<void>;
|
|
12
14
|
}): (request: Request) => Promise<Response>;
|
|
13
|
-
|
|
14
|
-
export
|
|
15
|
+
//#endregion
|
|
16
|
+
export type { McpHandlerOptions };
|
|
17
|
+
//# sourceMappingURL=vercel-mcp-adapter.d.mts.map
|
|
@@ -1,30 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
// Leave it empty because we list tools manually
|
|
18
|
-
capabilities: {
|
|
19
|
-
tools: {}
|
|
20
|
-
},
|
|
21
|
-
...serverOptions
|
|
22
|
-
},
|
|
23
|
-
config
|
|
24
|
-
);
|
|
25
|
-
return handler;
|
|
1
|
+
import { registerTrpcTools } from "../tools.mjs";
|
|
2
|
+
import { createMcpHandler } from "mcp-handler";
|
|
3
|
+
//#region src/adapters/vercel-mcp-adapter.ts
|
|
4
|
+
/**
|
|
5
|
+
* Creates an `mcp-handler` request handler, a `(Request) => Promise<Response>`
|
|
6
|
+
* you can mount as a Next.js route or in any Fetch-compatible framework.
|
|
7
|
+
* Use `callback` to register extra tools, prompts, or resources.
|
|
8
|
+
*/
|
|
9
|
+
function trpcToMcpHandler(router, ctx, options = {}) {
|
|
10
|
+
return createMcpHandler(async (server) => {
|
|
11
|
+
registerTrpcTools(server, router, ctx);
|
|
12
|
+
await options.callback?.(server);
|
|
13
|
+
}, options.serverOptions);
|
|
26
14
|
}
|
|
27
|
-
|
|
15
|
+
//#endregion
|
|
28
16
|
export { trpcToMcpHandler };
|
|
29
|
-
|
|
17
|
+
|
|
30
18
|
//# sourceMappingURL=vercel-mcp-adapter.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"vercel-mcp-adapter.mjs","names":[],"sources":["../../src/adapters/vercel-mcp-adapter.ts"],"sourcesContent":["import type { McpServer } from \"@modelcontextprotocol/server\";\nimport type { AnyTRPCRouter } from \"@trpc/server\";\nimport { createMcpHandler, type McpHandlerOptions } from \"mcp-handler\";\n\nimport { registerTrpcTools } from \"../tools\";\nimport type { MaybePromise, McpContext } from \"../types\";\n\nexport type { McpHandlerOptions };\n\n/**\n * Creates an `mcp-handler` request handler, a `(Request) => Promise<Response>`\n * you can mount as a Next.js route or in any Fetch-compatible framework.\n * Use `callback` to register extra tools, prompts, or resources.\n */\nexport function trpcToMcpHandler<TRouter extends AnyTRPCRouter>(\n router: TRouter,\n ctx: McpContext<TRouter>,\n options: {\n serverOptions?: McpHandlerOptions;\n callback?: (server: McpServer) => MaybePromise<void>;\n } = {},\n) {\n return createMcpHandler(async (server) => {\n registerTrpcTools(server, router, ctx);\n await options.callback?.(server);\n }, options.serverOptions);\n}\n"],"mappings":";;;;;;;;AAcA,SAAgB,iBACd,QACA,KACA,UAGI,CAAC,GACL;CACA,OAAO,iBAAiB,OAAO,WAAW;EACxC,kBAAkB,QAAQ,QAAQ,GAAG;EACrC,MAAM,QAAQ,WAAW,MAAM;CACjC,GAAG,QAAQ,aAAa;AAC1B"}
|
package/dist/helpers.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/helpers.ts
|
|
3
|
+
const transforms = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
/**
|
|
5
|
+
* Wraps a procedure so its MCP tool returns `transform(output)` as content
|
|
6
|
+
* instead of the JSON-serialized output. The procedure itself is unchanged.
|
|
7
|
+
*/
|
|
8
|
+
function transformMcpProcedure(procedure, transform) {
|
|
9
|
+
transforms.set(procedure, transform);
|
|
10
|
+
return procedure;
|
|
11
|
+
}
|
|
12
|
+
/** @internal Used by `extractToolsFromProcedures`. */
|
|
13
|
+
function getMcpTransform(procedure) {
|
|
14
|
+
return transforms.get(procedure);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
exports.getMcpTransform = getMcpTransform;
|
|
18
|
+
exports.transformMcpProcedure = transformMcpProcedure;
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=helpers.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.cjs","names":[],"sources":["../src/helpers.ts"],"sourcesContent":["import type { ContentBlock } from \"@modelcontextprotocol/server\";\nimport type { AnyTRPCProcedure, inferProcedureOutput } from \"@trpc/server\";\n\nimport type { MaybePromise, McpToolTransform } from \"./types\";\n\n// Keyed by procedure instead of stored in meta: procedures built from the same\n// base procedure share one `meta.mcp` object, so writing to it would leak the\n// transform into sibling procedures.\nconst transforms = new WeakMap<AnyTRPCProcedure, McpToolTransform>();\n\n/**\n * Wraps a procedure so its MCP tool returns `transform(output)` as content\n * instead of the JSON-serialized output. The procedure itself is unchanged.\n */\nexport function transformMcpProcedure<TProcedure extends AnyTRPCProcedure>(\n procedure: TProcedure,\n transform: (\n output: inferProcedureOutput<TProcedure>,\n ) => MaybePromise<ContentBlock[]>,\n): TProcedure {\n // The map only hands this transform the output of `procedure`.\n transforms.set(procedure, transform as McpToolTransform);\n return procedure;\n}\n\n/** @internal Used by `extractToolsFromProcedures`. */\nexport function getMcpTransform(procedure: AnyTRPCProcedure) {\n return transforms.get(procedure);\n}\n"],"mappings":";;AAQA,MAAM,6BAAa,IAAI,QAA4C;;;;;AAMnE,SAAgB,sBACd,WACA,WAGY;CAEZ,WAAW,IAAI,WAAW,SAA6B;CACvD,OAAO;AACT;;AAGA,SAAgB,gBAAgB,WAA6B;CAC3D,OAAO,WAAW,IAAI,SAAS;AACjC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { MaybePromise, McpToolTransform } from "./types.cjs";
|
|
2
|
+
import { ContentBlock } from "@modelcontextprotocol/server";
|
|
3
|
+
import { AnyTRPCProcedure, inferProcedureOutput } from "@trpc/server";
|
|
4
|
+
//#region src/helpers.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Wraps a procedure so its MCP tool returns `transform(output)` as content
|
|
7
|
+
* instead of the JSON-serialized output. The procedure itself is unchanged.
|
|
8
|
+
*/
|
|
9
|
+
export declare function transformMcpProcedure<TProcedure extends AnyTRPCProcedure>(procedure: TProcedure, transform: (output: inferProcedureOutput<TProcedure>) => MaybePromise<ContentBlock[]>): TProcedure;
|
|
10
|
+
/** @internal Used by `extractToolsFromProcedures`. */
|
|
11
|
+
export declare function getMcpTransform(procedure: AnyTRPCProcedure): McpToolTransform | undefined;
|
|
12
|
+
//#endregion
|
|
13
|
+
//# sourceMappingURL=helpers.d.cts.map
|
package/dist/helpers.d.mts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { MaybePromise, McpToolTransform } from "./types.mjs";
|
|
2
|
+
import { ContentBlock } from "@modelcontextprotocol/server";
|
|
3
|
+
import { AnyTRPCProcedure, inferProcedureOutput } from "@trpc/server";
|
|
4
|
+
//#region src/helpers.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Wraps a procedure so its MCP tool returns `transform(output)` as content
|
|
7
|
+
* instead of the JSON-serialized output. The procedure itself is unchanged.
|
|
8
|
+
*/
|
|
9
|
+
export declare function transformMcpProcedure<TProcedure extends AnyTRPCProcedure>(procedure: TProcedure, transform: (output: inferProcedureOutput<TProcedure>) => MaybePromise<ContentBlock[]>): TProcedure;
|
|
10
|
+
/** @internal Used by `extractToolsFromProcedures`. */
|
|
11
|
+
export declare function getMcpTransform(procedure: AnyTRPCProcedure): McpToolTransform | undefined;
|
|
12
|
+
//#endregion
|
|
13
|
+
//# sourceMappingURL=helpers.d.mts.map
|
package/dist/helpers.mjs
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region src/helpers.ts
|
|
2
|
+
const transforms = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
/**
|
|
4
|
+
* Wraps a procedure so its MCP tool returns `transform(output)` as content
|
|
5
|
+
* instead of the JSON-serialized output. The procedure itself is unchanged.
|
|
6
|
+
*/
|
|
7
|
+
function transformMcpProcedure(procedure, transform) {
|
|
8
|
+
transforms.set(procedure, transform);
|
|
9
|
+
return procedure;
|
|
10
|
+
}
|
|
11
|
+
/** @internal Used by `extractToolsFromProcedures`. */
|
|
12
|
+
function getMcpTransform(procedure) {
|
|
13
|
+
return transforms.get(procedure);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { getMcpTransform, transformMcpProcedure };
|
|
17
|
+
|
|
3
18
|
//# sourceMappingURL=helpers.mjs.map
|
package/dist/helpers.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"helpers.mjs","names":[],"sources":["../src/helpers.ts"],"sourcesContent":["import type { ContentBlock } from \"@modelcontextprotocol/server\";\nimport type { AnyTRPCProcedure, inferProcedureOutput } from \"@trpc/server\";\n\nimport type { MaybePromise, McpToolTransform } from \"./types\";\n\n// Keyed by procedure instead of stored in meta: procedures built from the same\n// base procedure share one `meta.mcp` object, so writing to it would leak the\n// transform into sibling procedures.\nconst transforms = new WeakMap<AnyTRPCProcedure, McpToolTransform>();\n\n/**\n * Wraps a procedure so its MCP tool returns `transform(output)` as content\n * instead of the JSON-serialized output. The procedure itself is unchanged.\n */\nexport function transformMcpProcedure<TProcedure extends AnyTRPCProcedure>(\n procedure: TProcedure,\n transform: (\n output: inferProcedureOutput<TProcedure>,\n ) => MaybePromise<ContentBlock[]>,\n): TProcedure {\n // The map only hands this transform the output of `procedure`.\n transforms.set(procedure, transform as McpToolTransform);\n return procedure;\n}\n\n/** @internal Used by `extractToolsFromProcedures`. */\nexport function getMcpTransform(procedure: AnyTRPCProcedure) {\n return transforms.get(procedure);\n}\n"],"mappings":";AAQA,MAAM,6BAAa,IAAI,QAA4C;;;;;AAMnE,SAAgB,sBACd,WACA,WAGY;CAEZ,WAAW,IAAI,WAAW,SAA6B;CACvD,OAAO;AACT;;AAGA,SAAgB,gBAAgB,WAA6B;CAC3D,OAAO,WAAW,IAAI,SAAS;AACjC"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_helpers = require("./helpers.cjs");
|
|
3
|
+
const require_tools = require("./tools.cjs");
|
|
4
|
+
const require_server = require("./server.cjs");
|
|
5
|
+
require("./types.cjs");
|
|
6
|
+
exports.createMcpServer = require_server.createMcpServer;
|
|
7
|
+
exports.extractToolsFromProcedures = require_tools.extractToolsFromProcedures;
|
|
8
|
+
exports.registerTrpcTools = require_tools.registerTrpcTools;
|
|
9
|
+
exports.transformMcpProcedure = require_helpers.transformMcpProcedure;
|