@prefecthq/fastmcp-ts 0.0.2-alpha.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 +309 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/cli/index.cjs +45522 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/client.d.ts +543 -0
- package/dist/client.js +1758 -0
- package/dist/client.js.map +1 -0
- package/dist/server.d.ts +1023 -0
- package/dist/server.js +2863 -0
- package/dist/server.js.map +1 -0
- package/dist/zod-P5QUYVPB.js +14015 -0
- package/dist/zod-P5QUYVPB.js.map +1 -0
- package/package.json +110 -0
package/README.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# fastmcp-ts
|
|
2
|
+
|
|
3
|
+
The TypeScript framework for building [Model Context Protocol](https://modelcontextprotocol.io) servers, clients, and apps. The official TypeScript counterpart to [FastMCP for Python](https://github.com/PrefectHQ/fastmcp) - built and maintained with đź’™ by the same team at [Prefect](https://prefect.io).
|
|
4
|
+
|
|
5
|
+
Built on the official [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol/typescript-sdk).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install fastmcp-ts
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Servers
|
|
16
|
+
|
|
17
|
+
Turn TypeScript functions into MCP tools, resources, and prompts. Input schemas are inferred automatically from any [Standard Schema](https://standardschema.dev)-compatible library: Zod, Valibot, ArkType, and others.
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { FastMCP } from 'fastmcp-ts/server'
|
|
21
|
+
import { z } from 'zod'
|
|
22
|
+
|
|
23
|
+
const server = new FastMCP({ name: 'my-server', version: '1.0.0' })
|
|
24
|
+
|
|
25
|
+
server.tool(
|
|
26
|
+
{
|
|
27
|
+
name: 'add',
|
|
28
|
+
description: 'Add two numbers',
|
|
29
|
+
input: z.object({ a: z.number(), b: z.number() }),
|
|
30
|
+
},
|
|
31
|
+
({ a, b }) => a + b
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
server.resource(
|
|
35
|
+
{ uri: 'config://settings', description: 'App configuration' },
|
|
36
|
+
() => JSON.stringify({ theme: 'dark', lang: 'en' })
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
server.resource(
|
|
40
|
+
{ uri: 'user://{id}', description: 'User by ID' },
|
|
41
|
+
({ id }) => `User #${id}`
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
server.prompt(
|
|
45
|
+
{
|
|
46
|
+
name: 'review_code',
|
|
47
|
+
description: 'Review code for quality and correctness',
|
|
48
|
+
arguments: [
|
|
49
|
+
{ name: 'code', required: true },
|
|
50
|
+
{ name: 'language', required: false },
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
({ code, language }) =>
|
|
54
|
+
`Review this ${language ?? 'code'} for quality and correctness:\n\n${code}`
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
await server.run() // stdio (default)
|
|
58
|
+
// await server.run({ transport: 'http', port: 3000 })
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Context
|
|
62
|
+
|
|
63
|
+
Handlers access logging, progress, LLM sampling, user elicitation, and per-session state through an ambient context with no prop-drilling.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { FastMCP } from 'fastmcp-ts/server'
|
|
67
|
+
import { z } from 'zod'
|
|
68
|
+
|
|
69
|
+
const server = new FastMCP({ name: 'assistant' })
|
|
70
|
+
|
|
71
|
+
server.tool(
|
|
72
|
+
{
|
|
73
|
+
name: 'summarize',
|
|
74
|
+
description: 'Summarize a document',
|
|
75
|
+
input: z.object({ text: z.string() }),
|
|
76
|
+
},
|
|
77
|
+
async ({ text }) => {
|
|
78
|
+
const ctx = server.getContext()
|
|
79
|
+
|
|
80
|
+
await ctx.info('Sending document to LLM')
|
|
81
|
+
await ctx.reportProgress(0, 1, 'Sampling…')
|
|
82
|
+
|
|
83
|
+
const { content } = await ctx.sample({
|
|
84
|
+
messages: [{ role: 'user', content: { type: 'text', text: `Summarize:\n${text}` } }],
|
|
85
|
+
maxTokens: 512,
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
return content.text
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Middleware & Auth
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { FastMCP, LoggingMiddleware, RateLimitingMiddleware, jwtVerifier } from 'fastmcp-ts/server'
|
|
97
|
+
|
|
98
|
+
const server = new FastMCP({
|
|
99
|
+
name: 'secure-server',
|
|
100
|
+
auth: jwtVerifier({
|
|
101
|
+
jwksUri: 'https://auth.example.com/.well-known/jwks.json',
|
|
102
|
+
issuer: 'https://auth.example.com',
|
|
103
|
+
audience: 'my-mcp-server',
|
|
104
|
+
}),
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
server.use(new LoggingMiddleware())
|
|
108
|
+
server.use(new RateLimitingMiddleware(100, 60_000)) // 100 requests per minute
|
|
109
|
+
|
|
110
|
+
await server.run({ transport: 'http', port: 3000 })
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Composition
|
|
114
|
+
|
|
115
|
+
Mount child servers onto a parent with optional name-prefix namespacing.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { FastMCP, createProxy } from 'fastmcp-ts/server'
|
|
119
|
+
|
|
120
|
+
const weather = new FastMCP({ name: 'weather' })
|
|
121
|
+
weather.tool({ name: 'forecast', description: 'Get a forecast', input: z.object({ city: z.string() }) }, ({ city }) => `Forecast for ${city}`)
|
|
122
|
+
|
|
123
|
+
// Wrap a remote server as a mountable instance
|
|
124
|
+
const maps = await createProxy({ transport: 'http', url: 'http://maps-service/mcp' })
|
|
125
|
+
|
|
126
|
+
const gateway = new FastMCP({ name: 'gateway' })
|
|
127
|
+
gateway.mount(weather, 'weather') // → weather_forecast
|
|
128
|
+
gateway.mount(maps, 'maps') // → maps_<tool_name>
|
|
129
|
+
|
|
130
|
+
await gateway.run({ transport: 'http', port: 3000 })
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Clients
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { Client } from 'fastmcp-ts/client'
|
|
139
|
+
|
|
140
|
+
const client = await Client.connect('http://localhost:3000')
|
|
141
|
+
|
|
142
|
+
const tools = await client.listTools()
|
|
143
|
+
const resources = await client.listResources()
|
|
144
|
+
const prompts = await client.listPrompts()
|
|
145
|
+
|
|
146
|
+
const result = await client.callTool('add', { a: 1, b: 2 })
|
|
147
|
+
const config = await client.readResource('config://settings')
|
|
148
|
+
const review = await client.getPrompt('review_code', { code: 'const x = 1' })
|
|
149
|
+
|
|
150
|
+
await client.close()
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Use `await using` for automatic cleanup:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
await using client = await Client.connect('http://localhost:3000')
|
|
157
|
+
const result = await client.callTool('add', { a: 1, b: 2 })
|
|
158
|
+
// client closed automatically on scope exit
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Sampling Adapters
|
|
162
|
+
|
|
163
|
+
Forward LLM sampling requests from servers to your AI provider with a single line:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { Client, AnthropicSamplingAdapter } from 'fastmcp-ts/client'
|
|
167
|
+
import Anthropic from '@anthropic-ai/sdk'
|
|
168
|
+
|
|
169
|
+
const client = await Client.connect('http://localhost:3000', {
|
|
170
|
+
handlers: {
|
|
171
|
+
sampling: (params) => new AnthropicSamplingAdapter(new Anthropic()).handleSampling(params),
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Also ships with `OpenAISamplingAdapter` and `GoogleSamplingAdapter`.
|
|
177
|
+
|
|
178
|
+
### Multi-Server
|
|
179
|
+
|
|
180
|
+
Connect to multiple servers from a single client. Tools, resources, and prompts are namespaced by server name automatically.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { Client } from 'fastmcp-ts/client'
|
|
184
|
+
|
|
185
|
+
const client = await Client.connect({
|
|
186
|
+
mcpServers: {
|
|
187
|
+
weather: { url: 'http://localhost:3001' },
|
|
188
|
+
maps: { url: 'http://localhost:3002' },
|
|
189
|
+
},
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
// tool names become weather_forecast, maps_geocode, …
|
|
193
|
+
const forecast = await client.callTool('weather_forecast', { city: 'New York' })
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Apps
|
|
199
|
+
|
|
200
|
+
FastMCP ships a server-side component library for building interactive UIs rendered directly in MCP host conversations.
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { FastMCPApp, Column, Row, Text, Input, Button, Table } from 'fastmcp-ts/server'
|
|
204
|
+
import { z } from 'zod'
|
|
205
|
+
|
|
206
|
+
const app = new FastMCPApp({ name: 'search-app', version: '1.0.0' })
|
|
207
|
+
|
|
208
|
+
// Entry-point tool: visible to the LLM, auto-linked to a ui:// resource
|
|
209
|
+
app.entrypoint(
|
|
210
|
+
{ name: 'search', description: 'Search the product catalog' },
|
|
211
|
+
() =>
|
|
212
|
+
Column({}, [
|
|
213
|
+
Text('Product Search'),
|
|
214
|
+
Row({}, [
|
|
215
|
+
Input({ name: 'query', placeholder: 'Search products…' }),
|
|
216
|
+
Button({ label: 'Search', actionRef: 'run_search' }),
|
|
217
|
+
]),
|
|
218
|
+
])
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
// Backend tool: hidden from the LLM, callable only from within the rendered UI
|
|
222
|
+
app.backendTool(
|
|
223
|
+
{
|
|
224
|
+
name: 'run_search',
|
|
225
|
+
description: 'Execute the search query',
|
|
226
|
+
input: z.object({ query: z.string() }),
|
|
227
|
+
},
|
|
228
|
+
async ({ query }) => {
|
|
229
|
+
const rows = await db.search(query)
|
|
230
|
+
return Table({ columns: ['Name', 'Price', 'Stock'], rows })
|
|
231
|
+
}
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
await app.server.run({ transport: 'http', port: 3000 })
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Built-in Providers
|
|
238
|
+
|
|
239
|
+
Ready-to-mount interactive primitives:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { FastMCP, Approval, Choice, FileUpload, FormInput } from 'fastmcp-ts/server'
|
|
243
|
+
import { z } from 'zod'
|
|
244
|
+
|
|
245
|
+
const server = new FastMCP({ name: 'my-server' })
|
|
246
|
+
|
|
247
|
+
server.addProvider(new Approval()) // confirm/deny card injected back into the conversation
|
|
248
|
+
server.addProvider(new Choice()) // clickable option list
|
|
249
|
+
server.addProvider(new FileUpload()) // drag-and-drop file picker; file bytes never pass through the LLM
|
|
250
|
+
server.addProvider(new FormInput()) // auto-generated validated form from any Standard Schema
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Generative UI
|
|
254
|
+
|
|
255
|
+
Let the LLM compose component trees at runtime:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import { FastMCP, GenerativeUI } from 'fastmcp-ts/server'
|
|
259
|
+
|
|
260
|
+
const server = new FastMCP({ name: 'my-server' })
|
|
261
|
+
server.addProvider(new GenerativeUI())
|
|
262
|
+
// registers generate_ui and search_components tools
|
|
263
|
+
|
|
264
|
+
await server.run()
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## CLI
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
# Start a server
|
|
273
|
+
fastmcp run server.ts
|
|
274
|
+
fastmcp run server.ts --transport http --port 3000
|
|
275
|
+
|
|
276
|
+
# Inspect a server's tools, resources, and prompts
|
|
277
|
+
fastmcp inspect --file server.ts
|
|
278
|
+
fastmcp inspect --url http://localhost:3000
|
|
279
|
+
fastmcp inspect --file server.ts --json
|
|
280
|
+
|
|
281
|
+
# Call a tool, read a resource, or get a prompt
|
|
282
|
+
fastmcp call add --file server.ts a=1 b=2
|
|
283
|
+
fastmcp call config://settings --url http://localhost:3000
|
|
284
|
+
|
|
285
|
+
# Connect to a running server and list its components
|
|
286
|
+
fastmcp list --url http://localhost:3000
|
|
287
|
+
fastmcp list --url http://localhost:3000 --resources --prompts --json
|
|
288
|
+
|
|
289
|
+
# Open the MCP Inspector UI with file-watch reload
|
|
290
|
+
fastmcp dev inspector server.ts
|
|
291
|
+
|
|
292
|
+
# Install into editor/client configs
|
|
293
|
+
fastmcp install claude-code server.ts
|
|
294
|
+
fastmcp install cursor server.ts
|
|
295
|
+
fastmcp install claude-desktop server.ts
|
|
296
|
+
|
|
297
|
+
# Find locally configured MCP servers
|
|
298
|
+
fastmcp discover
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Ecosystem
|
|
304
|
+
|
|
305
|
+
| Package | Role |
|
|
306
|
+
|---|---|
|
|
307
|
+
| [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) | Official low-level MCP protocol implementation — this library's foundation |
|
|
308
|
+
| [`fastmcp` (PyPI)](https://github.com/PrefectHQ/fastmcp) | The Python original this project models its API after |
|
|
309
|
+
| [`@modelcontextprotocol/ext-apps`](https://github.com/modelcontextprotocol/ext-apps) | Official MCP Apps extension — foundation for the Apps pillar |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|