@frontmcp/sdk 0.1.0 → 0.1.2
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 +433 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,438 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# FrontMCP 🚀
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<strong>The TypeScript-first way to build production-grade MCP servers.</strong>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
*Made with ❤️ for TypeScript developers*
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
[](https://www.npmjs.com/package/@frontmcp/sdk)
|
|
10
|
+
[](https://nodejs.org)
|
|
11
|
+
[](https://github.com/agentfront/frontmcp/blob/main/LICENSE)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
FrontMCP is a **TypeScript-first framework** for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io).
|
|
18
|
+
You describe servers, apps, tools, resources, and prompts with decorators; FrontMCP handles protocol, transport, DI,
|
|
19
|
+
session/auth, and execution flow.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// src/main.ts
|
|
23
|
+
import {FrontMcp, LogLevel} from '@frontmcp/sdk';
|
|
24
|
+
import HelloApp from './hello.app';
|
|
25
|
+
|
|
26
|
+
@FrontMcp({
|
|
27
|
+
info: {name: 'Demo 🚀', version: '0.1.0'},
|
|
28
|
+
apps: [HelloApp],
|
|
29
|
+
http: {port: 3001},
|
|
30
|
+
logging: {level: LogLevel.Info},
|
|
31
|
+
})
|
|
32
|
+
export default class Server {
|
|
33
|
+
}
|
|
34
|
+
````
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
<!-- omit in toc -->
|
|
39
|
+
|
|
40
|
+
## Table of Contents
|
|
41
|
+
|
|
42
|
+
- [Why FrontMCP?](#why-frontmcp)
|
|
43
|
+
- [Installation](#installation)
|
|
44
|
+
- [Quickstart](#quickstart)
|
|
45
|
+
- [Minimal Server & App](#minimal-server--app)
|
|
46
|
+
- [Function and Class Tools](#function-and-class-tools)
|
|
47
|
+
- [Scripts & tsconfig](#scripts--tsconfig)
|
|
48
|
+
- [MCP Inspector](#mcp-inspector)
|
|
49
|
+
- [Core Concepts](#core-concepts)
|
|
50
|
+
- [Servers](#servers)
|
|
51
|
+
- [Apps](#apps)
|
|
52
|
+
- [Tools](#tools)
|
|
53
|
+
- [Resources](#resources)
|
|
54
|
+
- [Prompts](#prompts)
|
|
55
|
+
- [Providers](#providers)
|
|
56
|
+
- [Adapters](#adapters)
|
|
57
|
+
- [Plugins](#plugins)
|
|
58
|
+
- [Authentication](#authentication)
|
|
59
|
+
- [Remote OAuth](#remote-oauth)
|
|
60
|
+
- [Local OAuth](#local-oauth)
|
|
61
|
+
- [Sessions & Transport](#sessions--transport)
|
|
62
|
+
- [Logging Transports](#logging-transports)
|
|
63
|
+
- [Deployment](#deployment)
|
|
64
|
+
- [Local Dev](#local-dev)
|
|
65
|
+
- [Production](#production)
|
|
66
|
+
- [Version Alignment](#version-alignment)
|
|
67
|
+
- [Contributing](#contributing)
|
|
68
|
+
- [License](#license)
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Why FrontMCP?
|
|
73
|
+
|
|
74
|
+
* **TypeScript-native DX** — decorators, Zod validation, strong typing end-to-end
|
|
75
|
+
* **Spec-aligned transports** — Streamable HTTP (GET/POST), streaming, sessions
|
|
76
|
+
* **Scoped invoker + DI** — secure, composable execution with hooks
|
|
77
|
+
* **Adapters & Plugins** — generate tools from OpenAPI; add cross-cutting behavior
|
|
78
|
+
* **Auth** — remote OAuth (external IdP) or built-in local OAuth
|
|
79
|
+
* **Logging** — pluggable log transports (console, JSONL, HTTP batch, …)
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Installation
|
|
84
|
+
|
|
85
|
+
Choose your package manager:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# npm
|
|
89
|
+
npm i -E @frontmcp/sdk @frontmcp/core zod reflect-metadata
|
|
90
|
+
npm i -D typescript tsx @types/node rimraf @modelcontextprotocol/inspector
|
|
91
|
+
|
|
92
|
+
# yarn
|
|
93
|
+
yarn add -E @frontmcp/sdk @frontmcp/core zod reflect-metadata
|
|
94
|
+
yarn add -D typescript tsx @types/node rimraf @modelcontextprotocol/inspector
|
|
95
|
+
|
|
96
|
+
# pnpm
|
|
97
|
+
pnpm add -E @frontmcp/sdk @frontmcp/core zod reflect-metadata
|
|
98
|
+
pnpm add -D typescript tsx @types/node rimraf @modelcontextprotocol/inspector
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> Requires **Node 20+**.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Quickstart
|
|
106
|
+
|
|
107
|
+
### Minimal Server & App
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
src/
|
|
111
|
+
main.ts
|
|
112
|
+
hello.app.ts
|
|
113
|
+
tools/
|
|
114
|
+
greet.tool.ts
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**`src/main.ts`**
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import 'reflect-metadata';
|
|
121
|
+
import {FrontMcp, LogLevel} from '@frontmcp/sdk';
|
|
122
|
+
import HelloApp from './hello.app';
|
|
123
|
+
|
|
124
|
+
@FrontMcp({
|
|
125
|
+
info: {name: 'Hello MCP', version: '0.1.0'},
|
|
126
|
+
apps: [HelloApp],
|
|
127
|
+
http: {port: Number(process.env.PORT) || 3001},
|
|
128
|
+
logging: {level: LogLevel.Info},
|
|
129
|
+
})
|
|
130
|
+
export default class Server {
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**`src/hello.app.ts`**
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import {App} from '@frontmcp/sdk';
|
|
138
|
+
import GreetTool from './tools/greet.tool';
|
|
139
|
+
|
|
140
|
+
@App({id: 'hello', name: 'Hello', tools: [GreetTool]})
|
|
141
|
+
export default class HelloApp {
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Function and Class Tools
|
|
146
|
+
|
|
147
|
+
**Function tool**
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import {tool} from '@frontmcp/sdk';
|
|
151
|
+
import {z} from 'zod';
|
|
152
|
+
|
|
153
|
+
export default tool({
|
|
154
|
+
name: 'greet',
|
|
155
|
+
description: 'Greets a user by name',
|
|
156
|
+
inputSchema: z.object({name: z.string()}),
|
|
157
|
+
})(({name}) => `Hello, ${name}!`);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Class tool**
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import {Tool} from '@frontmcp/sdk';
|
|
164
|
+
import {z} from 'zod';
|
|
165
|
+
|
|
166
|
+
@Tool({
|
|
167
|
+
name: 'add',
|
|
168
|
+
description: 'Add two numbers',
|
|
169
|
+
inputSchema: z.object({a: z.number(), b: z.number()}),
|
|
170
|
+
})
|
|
171
|
+
export default class AddTool {
|
|
172
|
+
execute({a, b}: { a: number; b: number }) {
|
|
173
|
+
return a + b;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Scripts & tsconfig
|
|
179
|
+
|
|
180
|
+
**`tsconfig.json`**
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"compilerOptions": {
|
|
185
|
+
"target": "ES2020",
|
|
186
|
+
"module": "CommonJS",
|
|
187
|
+
"lib": [
|
|
188
|
+
"ES2020"
|
|
189
|
+
],
|
|
190
|
+
"rootDir": "src",
|
|
191
|
+
"outDir": "dist",
|
|
192
|
+
"moduleResolution": "Node",
|
|
193
|
+
"strict": true,
|
|
194
|
+
"esModuleInterop": true,
|
|
195
|
+
"forceConsistentCasingInFileNames": true,
|
|
196
|
+
"skipLibCheck": true,
|
|
197
|
+
"resolveJsonModule": true,
|
|
198
|
+
"experimentalDecorators": true,
|
|
199
|
+
"emitDecoratorMetadata": true,
|
|
200
|
+
"sourceMap": true
|
|
201
|
+
},
|
|
202
|
+
"include": [
|
|
203
|
+
"src/**/*.ts"
|
|
204
|
+
],
|
|
205
|
+
"exclude": [
|
|
206
|
+
"**/*.test.ts",
|
|
207
|
+
"**/__tests__/**"
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**`tsconfig.build.json`**
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"extends": "./tsconfig.json",
|
|
217
|
+
"compilerOptions": {
|
|
218
|
+
"declaration": true,
|
|
219
|
+
"sourceMap": false
|
|
220
|
+
},
|
|
221
|
+
"exclude": [
|
|
222
|
+
"**/*.test.ts",
|
|
223
|
+
"**/__tests__/**",
|
|
224
|
+
"src/**/*.dev.ts"
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**`package.json` (scripts)**
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"scripts": {
|
|
234
|
+
"dev": "tsx watch src/main.ts",
|
|
235
|
+
"start:dev": "tsx src/main.ts",
|
|
236
|
+
"build": "tsc -p tsconfig.build.json",
|
|
237
|
+
"start": "node dist/main.js",
|
|
238
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
239
|
+
"clean": "rimraf dist",
|
|
240
|
+
"inspect:dev": "npx @modelcontextprotocol/inspector tsx src/main.ts",
|
|
241
|
+
"inspect:dist": "npx @modelcontextprotocol/inspector node dist/main.js"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
> Always import **`reflect-metadata` first** in your entry to enable decorator metadata.
|
|
247
|
+
|
|
248
|
+
### MCP Inspector
|
|
249
|
+
|
|
250
|
+
Debug your server with a browser UI:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# Dev (runs TS)
|
|
254
|
+
npm run inspect:dev
|
|
255
|
+
# Dist (runs built JS)
|
|
256
|
+
npm run inspect:dist
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Core Concepts
|
|
262
|
+
|
|
263
|
+
### Servers
|
|
264
|
+
|
|
265
|
+
The decorated entry (`@FrontMcp`) defines server **info**, **apps**, **http**, **logging**, **session**, optional **auth
|
|
266
|
+
**, and shared **providers**.
|
|
267
|
+
|
|
268
|
+
### Apps
|
|
269
|
+
|
|
270
|
+
Use `@App` to group **tools**, **resources**, **prompts**, **providers**, **adapters**, and **plugins**. With
|
|
271
|
+
`splitByApp: true`, each app has its own scope/base path and (optionally) its own auth.
|
|
272
|
+
|
|
273
|
+
### Tools
|
|
274
|
+
|
|
275
|
+
Active actions with input/output schemas. Use class tools (`@Tool`) or function tools (`tool({...})(handler)`).
|
|
276
|
+
|
|
277
|
+
### Resources
|
|
278
|
+
|
|
279
|
+
Expose read-only data by URI. Define with `@Resource` or `resource(...)` (see docs).
|
|
280
|
+
|
|
281
|
+
### Prompts
|
|
282
|
+
|
|
283
|
+
Reusable prompt templates (`@Prompt` / `prompt(...)`) supplying arguments for LLM interactions.
|
|
284
|
+
|
|
285
|
+
### Providers
|
|
286
|
+
|
|
287
|
+
Dependency-injected singletons for config/DB/Redis/KMS/etc., with scopes: **GLOBAL**, **SESSION**, **REQUEST**.
|
|
288
|
+
|
|
289
|
+
### Adapters
|
|
290
|
+
|
|
291
|
+
Generate tools/resources/prompts from external definitions (e.g., **OpenAPI**).
|
|
292
|
+
|
|
293
|
+
### Plugins
|
|
294
|
+
|
|
295
|
+
Cross-cutting behavior (caching, tracing, policy). Plugins can contribute providers/adapters/tools/resources/prompts.
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Authentication
|
|
300
|
+
|
|
301
|
+
You can configure auth on the server (multi-app shared) or per app (isolated scopes).
|
|
302
|
+
|
|
303
|
+
### Remote OAuth
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
auth: {
|
|
307
|
+
type: 'remote',
|
|
308
|
+
name: 'frontegg',
|
|
309
|
+
baseUrl: 'https://idp.example.com',
|
|
310
|
+
dcrEnabled ? : boolean,
|
|
311
|
+
clientId ? : string | ((info: { clientId: string }) => string),
|
|
312
|
+
mode ? : 'orchestrated' | 'transparent',
|
|
313
|
+
allowAnonymous ? : boolean,
|
|
314
|
+
consent ? : boolean,
|
|
315
|
+
scopes ? : string[],
|
|
316
|
+
grantTypes ? : ('authorization_code' | 'refresh_token')[],
|
|
317
|
+
authEndpoint ? : string,
|
|
318
|
+
tokenEndpoint ? : string,
|
|
319
|
+
registrationEndpoint ? : string,
|
|
320
|
+
userInfoEndpoint ? : string,
|
|
321
|
+
jwks ? : JSONWebKeySet,
|
|
322
|
+
jwksUri ? : string
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Local OAuth
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
{
|
|
330
|
+
auth: {
|
|
331
|
+
type: 'local',
|
|
332
|
+
id: 'local',
|
|
333
|
+
name: 'Local Auth',
|
|
334
|
+
scopes?: string[],
|
|
335
|
+
grantTypes?: ('authorization_code' | 'refresh_token')[],
|
|
336
|
+
allowAnonymous?: boolean, // default true
|
|
337
|
+
consent?: boolean,
|
|
338
|
+
jwks?: JSONWebKeySet,
|
|
339
|
+
signKey?: JWK | Uint8Array
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
> With `splitByApp: true`, define auth **per `@App`** (server-level `auth` is disallowed).
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Sessions & Transport
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
session: {
|
|
351
|
+
sessionMode ? : 'stateful' | 'stateless' | ((issuer) =>
|
|
352
|
+
...), // default 'stateless'
|
|
353
|
+
transportIdMode ? : 'uuid' | 'jwt' | ((issuer) =>
|
|
354
|
+
...), // default 'uuid'
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
* **Stateful**: server-side store for tokens; enables refresh; recommended for short-lived upstream tokens.
|
|
359
|
+
* **Stateless**: tokens embedded in JWT; simpler but no silent refresh.
|
|
360
|
+
* **Transport IDs**: `uuid` (per node) or `jwt` (signed; distributed setups).
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Logging Transports
|
|
365
|
+
|
|
366
|
+
Add custom log sinks via `@LogTransport`:
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
import {LogTransport, LogTransportInterface, LogRecord} from '@frontmcp/sdk';
|
|
370
|
+
|
|
371
|
+
@LogTransport({name: 'StructuredJson', description: 'JSONL to stdout'})
|
|
372
|
+
export class StructuredJsonTransport extends LogTransportInterface {
|
|
373
|
+
log(rec: LogRecord): void {
|
|
374
|
+
try {
|
|
375
|
+
process.stdout.write(JSON.stringify({
|
|
376
|
+
ts: rec.timestamp.toISOString(),
|
|
377
|
+
level: rec.levelName,
|
|
378
|
+
msg: String(rec.message),
|
|
379
|
+
prefix: rec.prefix || undefined,
|
|
380
|
+
args: (rec.args || []).map(String),
|
|
381
|
+
}) + '\n');
|
|
382
|
+
} catch {
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Register:
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
logging: {
|
|
392
|
+
level: LogLevel.Info,
|
|
393
|
+
enableConsole: false,
|
|
394
|
+
transports : [StructuredJsonTransport],
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Deployment
|
|
401
|
+
|
|
402
|
+
### Local Dev
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
# npm
|
|
406
|
+
npm run dev
|
|
407
|
+
# yarn
|
|
408
|
+
yarn dev
|
|
409
|
+
# pnpm
|
|
410
|
+
pnpm dev
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
* HTTP default: `http.port` (e.g., 3001)
|
|
414
|
+
* `http.entryPath` defaults to `''` (set to `/mcp` if you prefer)
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Version Alignment
|
|
419
|
+
|
|
420
|
+
If versions drift, the runtime may throw a "version mismatch" error at boot. Keep `@frontmcp/sdk` and `@frontmcp/core`
|
|
421
|
+
on the **same version** across your workspace.
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## Contributing
|
|
426
|
+
|
|
427
|
+
PRs welcome! Please:
|
|
428
|
+
|
|
429
|
+
* Keep changes focused and tested
|
|
430
|
+
* Run `typecheck`, `build`, and try **MCP Inspector** locally
|
|
431
|
+
* Align `@frontmcp/*` versions in examples
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## License
|
|
436
|
+
|
|
437
|
+
See [LICENSE](./LICENSE).
|
|
10
438
|
|
|
11
|
-
Run `nx test common` to execute the unit tests via [Jest](https://jestjs.io).
|