@frontmcp/sdk 0.3.1 → 0.4.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 (148) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +192 -164
  3. package/package.json +7 -4
  4. package/src/__test-utils__/fixtures/hook.fixtures.d.ts +46 -0
  5. package/src/__test-utils__/fixtures/hook.fixtures.js +114 -0
  6. package/src/__test-utils__/fixtures/hook.fixtures.js.map +1 -0
  7. package/src/__test-utils__/fixtures/index.d.ts +7 -0
  8. package/src/__test-utils__/fixtures/index.js +11 -0
  9. package/src/__test-utils__/fixtures/index.js.map +1 -0
  10. package/src/__test-utils__/fixtures/plugin.fixtures.d.ts +46 -0
  11. package/src/__test-utils__/fixtures/plugin.fixtures.js +127 -0
  12. package/src/__test-utils__/fixtures/plugin.fixtures.js.map +1 -0
  13. package/src/__test-utils__/fixtures/provider.fixtures.d.ts +69 -0
  14. package/src/__test-utils__/fixtures/provider.fixtures.js +131 -0
  15. package/src/__test-utils__/fixtures/provider.fixtures.js.map +1 -0
  16. package/src/__test-utils__/fixtures/scope.fixtures.d.ts +14 -0
  17. package/src/__test-utils__/fixtures/scope.fixtures.js +59 -0
  18. package/src/__test-utils__/fixtures/scope.fixtures.js.map +1 -0
  19. package/src/__test-utils__/fixtures/tool.fixtures.d.ts +36 -0
  20. package/src/__test-utils__/fixtures/tool.fixtures.js +91 -0
  21. package/src/__test-utils__/fixtures/tool.fixtures.js.map +1 -0
  22. package/src/__test-utils__/helpers/assertion.helpers.d.ts +45 -0
  23. package/src/__test-utils__/helpers/assertion.helpers.js +153 -0
  24. package/src/__test-utils__/helpers/assertion.helpers.js.map +1 -0
  25. package/src/__test-utils__/helpers/async.helpers.d.ts +48 -0
  26. package/src/__test-utils__/helpers/async.helpers.js +112 -0
  27. package/src/__test-utils__/helpers/async.helpers.js.map +1 -0
  28. package/src/__test-utils__/helpers/index.d.ts +6 -0
  29. package/src/__test-utils__/helpers/index.js +10 -0
  30. package/src/__test-utils__/helpers/index.js.map +1 -0
  31. package/src/__test-utils__/helpers/setup.helpers.d.ts +54 -0
  32. package/src/__test-utils__/helpers/setup.helpers.js +106 -0
  33. package/src/__test-utils__/helpers/setup.helpers.js.map +1 -0
  34. package/src/__test-utils__/index.d.ts +9 -0
  35. package/src/__test-utils__/index.js +14 -0
  36. package/src/__test-utils__/index.js.map +1 -0
  37. package/src/__test-utils__/mocks/flow-instance.mock.d.ts +50 -0
  38. package/src/__test-utils__/mocks/flow-instance.mock.js +72 -0
  39. package/src/__test-utils__/mocks/flow-instance.mock.js.map +1 -0
  40. package/src/__test-utils__/mocks/hook-registry.mock.d.ts +25 -0
  41. package/src/__test-utils__/mocks/hook-registry.mock.js +65 -0
  42. package/src/__test-utils__/mocks/hook-registry.mock.js.map +1 -0
  43. package/src/__test-utils__/mocks/index.d.ts +8 -0
  44. package/src/__test-utils__/mocks/index.js +12 -0
  45. package/src/__test-utils__/mocks/index.js.map +1 -0
  46. package/src/__test-utils__/mocks/plugin-registry.mock.d.ts +43 -0
  47. package/src/__test-utils__/mocks/plugin-registry.mock.js +70 -0
  48. package/src/__test-utils__/mocks/plugin-registry.mock.js.map +1 -0
  49. package/src/__test-utils__/mocks/provider-registry.mock.d.ts +39 -0
  50. package/src/__test-utils__/mocks/provider-registry.mock.js +72 -0
  51. package/src/__test-utils__/mocks/provider-registry.mock.js.map +1 -0
  52. package/src/__test-utils__/mocks/tool-registry.mock.d.ts +43 -0
  53. package/src/__test-utils__/mocks/tool-registry.mock.js +79 -0
  54. package/src/__test-utils__/mocks/tool-registry.mock.js.map +1 -0
  55. package/src/app/app.utils.js.map +1 -1
  56. package/src/app/instances/app.local.instance.js +8 -11
  57. package/src/app/instances/app.local.instance.js.map +1 -1
  58. package/src/auth/flows/oauth.authorize.flow.d.ts +8 -8
  59. package/src/auth/flows/oauth.register.flow.d.ts +4 -4
  60. package/src/auth/flows/oauth.token.flow.d.ts +4 -4
  61. package/src/auth/flows/well-known.jwks.flow.d.ts +12 -12
  62. package/src/auth/flows/well-known.oauth-authorization-server.flow.d.ts +8 -8
  63. package/src/auth/flows/well-known.prm.flow.d.ts +4 -4
  64. package/src/common/decorators/tool.decorator.d.ts +97 -36
  65. package/src/common/decorators/tool.decorator.js +0 -1
  66. package/src/common/decorators/tool.decorator.js.map +1 -1
  67. package/src/common/entries/tool.entry.d.ts +54 -11
  68. package/src/common/entries/tool.entry.js +19 -0
  69. package/src/common/entries/tool.entry.js.map +1 -1
  70. package/src/common/interfaces/internal/registry.interface.d.ts +10 -2
  71. package/src/common/interfaces/internal/registry.interface.js.map +1 -1
  72. package/src/common/interfaces/plugin.interface.d.ts +1 -1
  73. package/src/common/interfaces/plugin.interface.js.map +1 -1
  74. package/src/common/interfaces/tool.interface.d.ts +12 -7
  75. package/src/common/interfaces/tool.interface.js +1 -1
  76. package/src/common/interfaces/tool.interface.js.map +1 -1
  77. package/src/common/metadata/front-mcp.metadata.d.ts +145 -145
  78. package/src/common/metadata/hook.metadata.d.ts +4 -2
  79. package/src/common/metadata/hook.metadata.js.map +1 -1
  80. package/src/common/metadata/prompt.metadata.d.ts +28 -28
  81. package/src/common/metadata/prompt.metadata.js.map +1 -1
  82. package/src/common/metadata/resource.metadata.d.ts +54 -54
  83. package/src/common/metadata/tool.metadata.d.ts +190 -7
  84. package/src/common/metadata/tool.metadata.js +41 -6
  85. package/src/common/metadata/tool.metadata.js.map +1 -1
  86. package/src/common/schemas/http-output.schema.d.ts +106 -106
  87. package/src/common/tokens/tool.tokens.js.map +1 -1
  88. package/src/common/types/options/logging.options.d.ts +1 -2
  89. package/src/common/types/options/logging.options.js +1 -9
  90. package/src/common/types/options/logging.options.js.map +1 -1
  91. package/src/common/types/options/server-info.options.d.ts +19 -19
  92. package/src/errors/error-handler.d.ts +65 -0
  93. package/src/errors/error-handler.js +107 -0
  94. package/src/errors/error-handler.js.map +1 -0
  95. package/src/errors/index.d.ts +2 -0
  96. package/src/errors/index.js +26 -0
  97. package/src/errors/index.js.map +1 -0
  98. package/src/errors/mcp.error.d.ts +156 -0
  99. package/src/errors/mcp.error.js +243 -0
  100. package/src/errors/mcp.error.js.map +1 -0
  101. package/src/flows/flow.instance.js +7 -6
  102. package/src/flows/flow.instance.js.map +1 -1
  103. package/src/flows/flow.registry.js +1 -1
  104. package/src/flows/flow.registry.js.map +1 -1
  105. package/src/front-mcp/front-mcp.providers.d.ts +20 -20
  106. package/src/hooks/hook.registry.d.ts +5 -3
  107. package/src/hooks/hook.registry.js +13 -1
  108. package/src/hooks/hook.registry.js.map +1 -1
  109. package/src/plugin/plugin.registry.d.ts +7 -2
  110. package/src/plugin/plugin.registry.js +23 -11
  111. package/src/plugin/plugin.registry.js.map +1 -1
  112. package/src/prompt/prompt.registry.js +1 -0
  113. package/src/prompt/prompt.registry.js.map +1 -1
  114. package/src/resource/resource.registry.js +1 -0
  115. package/src/resource/resource.registry.js.map +1 -1
  116. package/src/scope/scope.registry.js +1 -1
  117. package/src/scope/scope.registry.js.map +1 -1
  118. package/src/store/adapters/store.memory.adapter.js +3 -1
  119. package/src/store/adapters/store.memory.adapter.js.map +1 -1
  120. package/src/tool/flows/call-tool.flow.d.ts +1012 -676
  121. package/src/tool/flows/call-tool.flow.js +94 -61
  122. package/src/tool/flows/call-tool.flow.js.map +1 -1
  123. package/src/tool/flows/tools-list.flow.d.ts +347 -590
  124. package/src/tool/flows/tools-list.flow.js +76 -49
  125. package/src/tool/flows/tools-list.flow.js.map +1 -1
  126. package/src/tool/tool.instance.d.ts +27 -8
  127. package/src/tool/tool.instance.js +40 -5
  128. package/src/tool/tool.instance.js.map +1 -1
  129. package/src/tool/tool.registry.js +19 -21
  130. package/src/tool/tool.registry.js.map +1 -1
  131. package/src/tool/tool.utils.d.ts +3 -2
  132. package/src/tool/tool.utils.js +377 -14
  133. package/src/tool/tool.utils.js.map +1 -1
  134. package/src/transport/adapters/transport.sse.adapter.js.map +1 -1
  135. package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
  136. package/src/transport/flows/handle.sse.flow.js +6 -13
  137. package/src/transport/flows/handle.sse.flow.js.map +1 -1
  138. package/src/transport/flows/handle.streamable-http.flow.js +1 -0
  139. package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
  140. package/src/transport/mcp-handlers/call-tool-request.handler.d.ts +1 -1
  141. package/src/transport/mcp-handlers/call-tool-request.handler.js +10 -5
  142. package/src/transport/mcp-handlers/call-tool-request.handler.js.map +1 -1
  143. package/src/transport/mcp-handlers/index.d.ts +151 -268
  144. package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +124 -216
  145. package/src/transport/transport.local.js +1 -0
  146. package/src/transport/transport.local.js.map +1 -1
  147. package/src/utils/string.utils.js +1 -1
  148. package/src/utils/string.utils.js.map +1 -1
package/README.md CHANGED
@@ -1,13 +1,18 @@
1
1
  <div align="center">
2
2
 
3
- # FrontMCP 🚀
3
+ <picture>
4
+ <source width="400" media="(prefers-color-scheme: dark)" srcset="docs/assets/logo/frontmcp.dark.svg">
5
+ <source width="400" media="(prefers-color-scheme: light)" srcset="docs/assets/logo/frontmcp.light.svg">
6
+ <img width="400" alt="FrontMCP Logo" src="docs/assets/logo/frontmcp.light.svg">
7
+ </picture>
8
+ <hr>
4
9
 
5
- <strong>The TypeScript-first way to build production-grade MCP servers.</strong>
10
+ <strong>The TypeScript way to build MCP servers with decorators, DI, and Streamable HTTP.</strong>
6
11
 
7
12
  _Made with ❤️ for TypeScript developers_
8
13
 
9
14
  [![NPM - @frontmcp/sdk](https://img.shields.io/npm/v/@frontmcp/sdk.svg?v=2)](https://www.npmjs.com/package/@frontmcp/sdk)
10
- [![Node](https://img.shields.io/badge/node-%3E%3D20.0.0-339933?logo=node.js&logoColor=white)](https://nodejs.org)
15
+ [![Node](https://img.shields.io/badge/node-%3E%3D22-339933?logo=node.js&logoColor=white)](https://nodejs.org)
11
16
  [![License](https://img.shields.io/github/license/agentfront/frontmcp.svg?v=1)](https://github.com/agentfront/frontmcp/blob/main/LICENSE)
12
17
 
13
18
  </div>
@@ -15,18 +20,18 @@ _Made with ❤️ for TypeScript developers_
15
20
  ---
16
21
 
17
22
  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.
23
+ You write clean, typed code; FrontMCP handles the protocol, transport, DI, session/auth, and execution flow.
20
24
 
21
25
  ```ts
22
26
  // src/main.ts
27
+ import 'reflect-metadata';
23
28
  import { FrontMcp, LogLevel } from '@frontmcp/sdk';
24
29
  import HelloApp from './hello.app';
25
30
 
26
31
  @FrontMcp({
27
32
  info: { name: 'Demo 🚀', version: '0.1.0' },
28
33
  apps: [HelloApp],
29
- http: { port: 3001 },
34
+ http: { port: 3000 },
30
35
  logging: { level: LogLevel.Info },
31
36
  })
32
37
  export default class Server {}
@@ -41,24 +46,24 @@ export default class Server {}
41
46
  - [Why FrontMCP?](#why-frontmcp)
42
47
  - [Installation](#installation)
43
48
  - [Quickstart](#quickstart)
44
- - [Minimal Server & App](#minimal-server--app)
49
+ - [1) Create Your FrontMCP Server](#1-create-your-frontmcp-server)
50
+ - [2) Define an App](#2-define-an-app)
51
+ - [3) Add Your First Tool](#3-add-your-first-tool)
52
+ - [4) Run It](#4-run-it)
45
53
  - [Function and Class Tools](#function-and-class-tools)
46
54
  - [Scripts & tsconfig](#scripts--tsconfig)
47
- - [MCP Inspector](#mcp-inspector)
55
+ - [Inspector](#inspector)
48
56
  - [Core Concepts](#core-concepts)
49
57
  - [Servers](#servers)
50
58
  - [Apps](#apps)
51
59
  - [Tools](#tools)
52
60
  - [Resources](#resources)
53
61
  - [Prompts](#prompts)
54
- - [Providers](#providers)
55
- - [Adapters](#adapters)
56
- - [Plugins](#plugins)
62
+ - [Providers / Adapters / Plugins](#providers--adapters--plugins)
57
63
  - [Authentication](#authentication)
58
64
  - [Remote OAuth](#remote-oauth)
59
65
  - [Local OAuth](#local-oauth)
60
66
  - [Sessions & Transport](#sessions--transport)
61
- - [Logging Transports](#logging-transports)
62
67
  - [Deployment](#deployment)
63
68
  - [Local Dev](#local-dev)
64
69
  - [Production](#production)
@@ -70,73 +75,121 @@ export default class Server {}
70
75
 
71
76
  ## Why FrontMCP?
72
77
 
73
- - **TypeScript-native DX** — decorators, Zod validation, strong typing end-to-end
74
- - **Spec-aligned transports** — Streamable HTTP (GET/POST), streaming, sessions
78
+ - **TypeScript-native DX** — decorators, Zod, and strong typing end-to-end
75
79
  - **Scoped invoker + DI** — secure, composable execution with hooks
76
- - **Adapters & Plugins** — generate tools from OpenAPI; add cross-cutting behavior
77
- - **Auth** — remote OAuth (external IdP) or built-in local OAuth
78
- - **Logging** — pluggable log transports (console, JSONL, HTTP batch, …)
80
+ - **Adapters & Plugins** — extend your server without boilerplate
81
+ - **Spec-aligned transport** — Streamable HTTP for modern MCP clients
79
82
 
80
83
  ---
81
84
 
82
85
  ## Installation
83
86
 
84
- Choose your package manager:
87
+ **Prereqs:** Node.js 22, npm ≥ 10. ([Installation - FrontMCP][1])
88
+
89
+ ### Option A — New project (recommended)
90
+
91
+ ```bash
92
+ npx frontmcp create my-app
93
+ ```
94
+
95
+ This scaffolds a FrontMCP project, writes a modern ESM `tsconfig.json` for decorators, adds helpful package scripts, and
96
+ installs required dev deps. ([Installation - FrontMCP][1])
97
+
98
+ ### Option B — Add to an existing project
85
99
 
86
100
  ```bash
87
- # npm
88
- npm install -S frontmcp @frontmcp/sdk zod reflect-metadata
89
- npm install -D typescript tsx @types/node rimraf @modelcontextprotocol/inspector
101
+ npm i -D frontmcp @types/node@^20
102
+ npx frontmcp init
90
103
  ```
91
104
 
92
- > Requires **Node 20+**.
105
+ `init` adds scripts, verifies your `tsconfig.json`, and checks layout. No need to install `@frontmcp/sdk` directly—the
106
+ CLI bundles a compatible SDK for you. ([Installation - FrontMCP][1])
93
107
 
94
108
  ---
95
109
 
96
110
  ## Quickstart
97
111
 
98
- ### Minimal Server & App
99
-
100
- ```
101
- src/
102
- main.ts
103
- hello.app.ts
104
- tools/
105
- greet.tool.ts
106
- ```
112
+ If you haven’t installed FrontMCP yet, follow the [installation guide][1] first.
107
113
 
108
- **`src/main.ts`**
114
+ ### 1) Create Your FrontMCP Server
109
115
 
110
116
  ```ts
111
- import 'reflect-metadata';
117
+ // src/main.ts
112
118
  import { FrontMcp, LogLevel } from '@frontmcp/sdk';
113
119
  import HelloApp from './hello.app';
114
120
 
115
121
  @FrontMcp({
116
122
  info: { name: 'Hello MCP', version: '0.1.0' },
117
123
  apps: [HelloApp],
118
- http: { port: Number(process.env.PORT) || 3001 },
119
- logging: { level: LogLevel.Info },
124
+ http: { port: 3000 },
125
+ logging: { level: LogLevel.INFO },
120
126
  })
121
- export default class Server {}
127
+ export default class HelloServer {}
122
128
  ```
123
129
 
124
- **`src/hello.app.ts`**
130
+ ### 2) Define an App
125
131
 
126
132
  ```ts
133
+ // src/hello.app.ts
127
134
  import { App } from '@frontmcp/sdk';
128
135
  import GreetTool from './tools/greet.tool';
129
136
 
130
137
  @App({
131
138
  id: 'hello',
132
- name: 'Hello',
139
+ name: 'Hello App',
133
140
  tools: [GreetTool],
134
141
  })
135
142
  export default class HelloApp {}
136
143
  ```
137
144
 
145
+ ### 3) Add Your First Tool
146
+
147
+ ```ts
148
+ // src/tools/greet.tool.ts
149
+ import { Tool } from '@frontmcp/sdk';
150
+ import { z } from 'zod';
151
+
152
+ @Tool({
153
+ name: 'greet',
154
+ description: 'Greets a user by name',
155
+ inputSchema: { name: z.string() },
156
+ })
157
+ export default class GreetTool {
158
+ async execute({ name }: { name: string }) {
159
+ return `Hello, ${name}!`;
160
+ }
161
+ }
162
+ ```
163
+
164
+ ### 4) Run It
165
+
166
+ Add scripts (if you didn't use `frontmcp create`):
167
+
168
+ ```json
169
+ {
170
+ "scripts": {
171
+ "dev": "frontmcp dev",
172
+ "build": "frontmcp build",
173
+ "start": "node dist/main.js"
174
+ }
175
+ }
176
+ ```
177
+
178
+ Then:
179
+
180
+ ```bash
181
+ npm run dev
182
+ # Server listening on http://localhost:3000
183
+ ```
184
+
185
+ > **Tip:** FrontMCP speaks **MCP Streamable HTTP**. Connect any MCP-capable client and call `greet` with
186
+ > `{"name": "Ada"}`. ([Quickstart - FrontMCP][2])
187
+
138
188
  ### Function and Class Tools
139
189
 
190
+ Tools are typed actions with Zod schemas. Implement them as classes with `@Tool({...})` or inline via `tool()`. Pass
191
+ **Zod fields directly** (no `z.object({...})`). ([Tools - FrontMCP][4])
192
+
140
193
  **Function tool**
141
194
 
142
195
  ```ts
@@ -146,7 +199,7 @@ import { z } from 'zod';
146
199
  export default tool({
147
200
  name: 'greet',
148
201
  description: 'Greets a user by name',
149
- inputSchema: z.object({ name: z.string() }),
202
+ inputSchema: { name: z.string() }, // shape, not z.object
150
203
  })(({ name }) => `Hello, ${name}!`);
151
204
  ```
152
205
 
@@ -159,10 +212,10 @@ import { z } from 'zod';
159
212
  @Tool({
160
213
  name: 'add',
161
214
  description: 'Add two numbers',
162
- inputSchema: z.object({ a: z.number(), b: z.number() }),
215
+ inputSchema: { a: z.number(), b: z.number() },
163
216
  })
164
217
  export default class AddTool {
165
- execute({ a, b }: { a: number; b: number }) {
218
+ async execute({ a, b }: { a: number; b: number }) {
166
219
  return a + b;
167
220
  }
168
221
  }
@@ -170,22 +223,37 @@ export default class AddTool {
170
223
 
171
224
  ### Scripts & tsconfig
172
225
 
173
- **`tsconfig.json`**
226
+ After `create` or `init`, you’ll have:
227
+
228
+ ```json
229
+ {
230
+ "scripts": {
231
+ "dev": "frontmcp dev",
232
+ "build": "frontmcp build",
233
+ "inspect": "frontmcp inspector",
234
+ "doctor": "frontmcp doctor"
235
+ }
236
+ }
237
+ ```
238
+
239
+ These map to dev watch, production build, zero‑setup Inspector launch, and environment checks. ([Installation -
240
+ FrontMCP][1])
241
+
242
+ **Recommended `tsconfig.json` (ESM + decorators)**
174
243
 
175
244
  ```json
176
245
  {
177
246
  "compilerOptions": {
178
- "target": "ES2020",
179
- "module": "CommonJS",
180
- "lib": ["ES2020"],
247
+ "target": "es2021",
248
+ "module": "esnext",
249
+ "lib": ["es2021"],
250
+ "moduleResolution": "bundler",
181
251
  "rootDir": "src",
182
252
  "outDir": "dist",
183
- "moduleResolution": "Node",
184
253
  "strict": true,
185
254
  "esModuleInterop": true,
186
- "forceConsistentCasingInFileNames": true,
187
- "skipLibCheck": true,
188
255
  "resolveJsonModule": true,
256
+ "skipLibCheck": true,
189
257
  "experimentalDecorators": true,
190
258
  "emitDecoratorMetadata": true,
191
259
  "sourceMap": true
@@ -195,7 +263,9 @@ export default class AddTool {
195
263
  }
196
264
  ```
197
265
 
198
- **`tsconfig.build.json`**
266
+ This mirrors what `init` writes for you. ([Local Dev Server - FrontMCP][3])
267
+
268
+ **Optional `tsconfig.build.json`**
199
269
 
200
270
  ```json
201
271
  {
@@ -208,79 +278,55 @@ export default class AddTool {
208
278
  }
209
279
  ```
210
280
 
211
- **`package.json` (scripts)**
212
-
213
- ```json
214
- {
215
- "scripts": {
216
- "dev": "tsx watch src/main.ts",
217
- "start:dev": "tsx src/main.ts",
218
- "build": "tsc -p tsconfig.build.json",
219
- "start": "node dist/main.js",
220
- "typecheck": "tsc --noEmit -p tsconfig.json",
221
- "clean": "rimraf dist",
222
- "inspect:dev": "npx @modelcontextprotocol/inspector tsx src/main.ts",
223
- "inspect:dist": "npx @modelcontextprotocol/inspector node dist/main.js"
224
- }
225
- }
226
- ```
227
-
228
- > Always import **`reflect-metadata` first** in your entry to enable decorator metadata.
229
-
230
- ### MCP Inspector
281
+ ### Inspector
231
282
 
232
- Debug your server with a browser UI:
283
+ Run a browser UI to exercise tools and messages:
233
284
 
234
285
  ```bash
235
- # Dev (runs TS)
236
- npm run inspect:dev
237
- # Dist (runs built JS)
238
- npm run inspect:dist
286
+ npm run inspect
239
287
  ```
240
288
 
289
+ This launches the MCP Inspector; point it at your local server (e.g., `http://localhost:3000`). ([Local Dev Server -
290
+ FrontMCP][3])
291
+
241
292
  ---
242
293
 
243
294
  ## Core Concepts
244
295
 
245
296
  ### Servers
246
297
 
247
- The decorated entry (`@FrontMcp`) defines server **info**, **apps**, **http**, **logging**, **session**, optional **auth
248
- **, and shared **providers**.
298
+ `@FrontMcp({...})` defines **info**, **apps**, **http**, **logging**, **session**, and optional **auth**. Keep it
299
+ minimal or scale up with providers and plugins. ([The FrontMCP Server - FrontMCP][5])
249
300
 
250
301
  ### Apps
251
302
 
252
- Use `@App` to group **tools**, **resources**, **prompts**, **providers**, **adapters**, and **plugins**. With
253
- `splitByApp: true`, each app has its own scope/base path and (optionally) its own auth.
303
+ Use `@App` to group **tools**, **resources**, **prompts**, plus **providers**, **adapters**, and **plugins**. With
304
+ `splitByApp: true`, each app gets its own scope/base path and, if needed, its own auth surface. ([Apps - FrontMCP][6])
254
305
 
255
306
  ### Tools
256
307
 
257
- Active actions with input/output schemas. Use class tools (`@Tool`) or function tools (`tool({...})(handler)`).
308
+ Typed actions with schemas (class `@Tool` or inline `tool({...})(handler)`). Use the Zod‑field **shape** style for
309
+ `inputSchema`. ([Tools - FrontMCP][4])
258
310
 
259
311
  ### Resources
260
312
 
261
- Expose read-only data by URI. Define with `@Resource` or `resource(...)` (see docs).
313
+ Readable data by URI or RFC6570 template (see `@Resource` / `@ResourceTemplate`). ([Resources - FrontMCP][7])
262
314
 
263
315
  ### Prompts
264
316
 
265
- Reusable prompt templates (`@Prompt` / `prompt(...)`) supplying arguments for LLM interactions.
317
+ Reusable templates returning MCP `GetPromptResult`, with typed arguments. ([Prompts - FrontMCP][8])
266
318
 
267
- ### Providers
319
+ ### Providers / Adapters / Plugins
268
320
 
269
- Dependency-injected singletons for config/DB/Redis/KMS/etc., with scopes: **GLOBAL**, **SESSION**, **REQUEST**.
270
-
271
- ### Adapters
272
-
273
- Generate tools/resources/prompts from external definitions (e.g., **OpenAPI**).
274
-
275
- ### Plugins
276
-
277
- Cross-cutting behavior (caching, tracing, policy). Plugins can contribute providers/adapters/tools/resources/prompts.
321
+ Inject shared services, generate tools from OpenAPI, and add cross‑cutting behavior like caching and hooks. ([Add
322
+ OpenAPI Adapter - FrontMCP][9])
278
323
 
279
324
  ---
280
325
 
281
326
  ## Authentication
282
327
 
283
- You can configure auth on the server (multi-app shared) or per app (isolated scopes).
328
+ Configure auth at the **server** (shared) or **per app** (isolated). With `splitByApp: true`, define auth **per app**
329
+ (server‑level `auth` is disallowed). ([Authentication - FrontMCP][10])
284
330
 
285
331
  ### Remote OAuth
286
332
 
@@ -289,26 +335,27 @@ auth: {
289
335
  type: 'remote',
290
336
  name: 'frontegg',
291
337
  baseUrl: 'https://idp.example.com',
292
- dcrEnabled ? : boolean,
293
- clientId ? : string | ((info: { clientId: string }) => string),
294
- mode ? : 'orchestrated' | 'transparent',
295
- allowAnonymous ? : boolean,
296
- consent ? : boolean,
297
- scopes ? : string[],
298
- grantTypes ? : ('authorization_code' | 'refresh_token')[],
299
- authEndpoint ? : string,
300
- tokenEndpoint ? : string,
301
- registrationEndpoint ? : string,
302
- userInfoEndpoint ? : string,
303
- jwks ? : JSONWebKeySet,
304
- jwksUri ? : string
338
+ dcrEnabled?: boolean,
339
+ clientId?: string | ((info: { clientId: string }) => string),
340
+ mode?: 'orchestrated' | 'transparent',
341
+ allowAnonymous?: boolean,
342
+ consent?: boolean,
343
+ scopes?: string[],
344
+ grantTypes?: ('authorization_code' | 'refresh_token')[],
345
+ authEndpoint?: string,
346
+ tokenEndpoint?: string,
347
+ registrationEndpoint?: string,
348
+ userInfoEndpoint?: string,
349
+ jwks?: JSONWebKeySet,
350
+ jwksUri?: string
305
351
  }
306
352
  ```
307
353
 
354
+ See **Authentication → Remote OAuth** for full details and DCR vs non‑DCR. ([Remote OAuth - FrontMCP][11])
355
+
308
356
  ### Local OAuth
309
357
 
310
358
  ```ts
311
- {
312
359
  auth: {
313
360
  type: 'local',
314
361
  id: 'local',
@@ -322,7 +369,7 @@ auth: {
322
369
  }
323
370
  ```
324
371
 
325
- > With `splitByApp: true`, define auth **per `@App`** (server-level `auth` is disallowed).
372
+ Use per‑app when isolating scopes. ([Local OAuth - FrontMCP][12])
326
373
 
327
374
  ---
328
375
 
@@ -330,91 +377,72 @@ auth: {
330
377
 
331
378
  ```ts
332
379
  session: {
333
- sessionMode ? : 'stateful' | 'stateless' | ((issuer) =>
334
- ...), // default 'stateless'
335
- transportIdMode ? : 'uuid' | 'jwt' | ((issuer) =>
336
- ...), // default 'uuid'
380
+ sessionMode?: 'stateful' | 'stateless' | ((issuer) => ...), // default 'stateless'
381
+ transportIdMode?: 'uuid' | 'jwt' | ((issuer) => ...), // default 'uuid'
337
382
  }
338
383
  ```
339
384
 
340
- - **Stateful**: server-side store for tokens; enables refresh; recommended for short-lived upstream tokens.
341
- - **Stateless**: tokens embedded in JWT; simpler but no silent refresh.
342
- - **Transport IDs**: `uuid` (per node) or `jwt` (signed; distributed setups).
385
+ - **Stateful**: serverside store (e.g., Redis); supports refresh; best for shortlived upstream tokens.
386
+ - **Stateless**: embeds session in JWT; simpler but no silent refresh.
387
+ - **Transport IDs**: `uuid` (per node) or `jwt` (signed; distributed setups). ([The FrontMCP Server - FrontMCP][5])
343
388
 
344
389
  ---
345
390
 
346
- ## Logging Transports
347
-
348
- Add custom log sinks via `@LogTransport`:
349
-
350
- ```ts
351
- import { LogTransport, LogTransportInterface, LogRecord } from '@frontmcp/sdk';
352
-
353
- @LogTransport({ name: 'StructuredJson', description: 'JSONL to stdout' })
354
- export class StructuredJsonTransport extends LogTransportInterface {
355
- log(rec: LogRecord): void {
356
- try {
357
- process.stdout.write(
358
- JSON.stringify({
359
- ts: rec.timestamp.toISOString(),
360
- level: rec.levelName,
361
- msg: String(rec.message),
362
- prefix: rec.prefix || undefined,
363
- args: (rec.args || []).map(String),
364
- }) + '\n',
365
- );
366
- } catch {}
367
- }
368
- }
369
- ```
391
+ ## Deployment
370
392
 
371
- Register:
393
+ ### Local Dev
372
394
 
373
- ```ts
374
- logging: {
375
- level: LogLevel.Info,
376
- enableConsole: false,
377
- transports : [StructuredJsonTransport],
378
- }
395
+ ```bash
396
+ npm run dev
379
397
  ```
380
398
 
381
- ---
399
+ - Default HTTP port: `3000` unless configured
400
+ - `npm run doctor` checks Node/npm versions, `tsconfig`, and scripts. ([Local Dev Server - FrontMCP][3])
382
401
 
383
- ## Deployment
384
-
385
- ### Local Dev
402
+ ### Production
386
403
 
387
404
  ```bash
388
- # npm
389
- npm run dev
390
- # yarn
391
- yarn dev
392
- # pnpm
393
- pnpm dev
405
+ npm run build
406
+ NODE_ENV=production PORT=8080 npm start
394
407
  ```
395
408
 
396
- - HTTP default: `http.port` (e.g., 3001)
397
- - `http.entryPath` defaults to `''` (set to `/mcp` if you prefer)
409
+ Builds to `dist/` (uses `tsconfig.build.json`). Consider a process manager and reverse proxy; align all `@frontmcp/*`
410
+ versions. ([Production Build - FrontMCP][13])
398
411
 
399
412
  ---
400
413
 
401
414
  ## Version Alignment
402
415
 
403
- If versions drift, the runtime may throw a "version mismatch" error at boot. Keep `@frontmcp/*` on the **same version**
404
- across your workspace.
416
+ If versions drift, the runtime will throw a clear **“version mismatch”** at boot. Keep `@frontmcp/*` versions aligned.
417
+ ([Production Build - FrontMCP][13])
405
418
 
406
419
  ---
407
420
 
408
421
  ## Contributing
409
422
 
410
- PRs welcome! Please:
411
-
412
- - Keep changes focused and tested
413
- - Run `typecheck`, `build`, and try **MCP Inspector** locally
414
- - Align `@frontmcp/*` versions in examples
423
+ - PRs welcome! Read the full [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow details, coding standards, and the PR
424
+ checklist.
425
+ - Keep changes focused, add/adjust Jest specs, and update docs/snippets when behavior changes.
426
+ - Before opening a PR run `yarn nx run-many -t lint,test,build`, `npx frontmcp doctor`, and verify the demo/Inspector
427
+ flows relevant to your change.
428
+ - Align `@frontmcp/*` versions in examples to avoid runtime version mismatches.
415
429
 
416
430
  ---
417
431
 
418
432
  ## License
419
433
 
420
434
  See [LICENSE](./LICENSE).
435
+
436
+ [1]: https://docs.agentfront.dev/docs/getting-started/installation 'Installation - FrontMCP'
437
+ [2]: https://docs.agentfront.dev/docs/getting-started/quickstart 'Quickstart - FrontMCP'
438
+ [3]: https://docs.agentfront.dev/docs/deployment/local-dev-server 'Local Dev Server - FrontMCP'
439
+ [4]: https://docs.agentfront.dev/docs/servers/tools 'Tools - FrontMCP'
440
+ [5]: https://docs.agentfront.dev/docs/servers/server 'The FrontMCP Server - FrontMCP'
441
+ [6]: https://docs.agentfront.dev/docs/servers/apps 'Apps - FrontMCP'
442
+ [7]: https://docs.agentfront.dev/docs/servers/resources 'Resources - FrontMCP'
443
+ [8]: https://docs.agentfront.dev/docs/servers/prompts 'Prompts - FrontMCP'
444
+ [9]: https://docs.agentfront.dev/docs/guides/add-openapi-adapter 'Add OpenAPI Adapter - FrontMCP'
445
+ [10]: https://docs.agentfront.dev/docs/servers/authentication/overview 'Authentication - FrontMCP'
446
+ [11]: https://docs.agentfront.dev/docs/servers/authentication/remote 'Remote OAuth - FrontMCP'
447
+ [12]: https://docs.agentfront.dev/docs/servers/authentication/local 'Local OAuth - FrontMCP'
448
+ [13]: https://docs.agentfront.dev/docs/deployment/production-build 'Production Build - FrontMCP'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/sdk",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "FrontMCP SDK",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",
@@ -33,16 +33,19 @@
33
33
  "default": "./src/index.js"
34
34
  }
35
35
  },
36
+ "peerDependencies": {
37
+ "zod": "^3.25.76"
38
+ },
36
39
  "dependencies": {
37
- "@modelcontextprotocol/sdk": "^1.21.1",
40
+ "@modelcontextprotocol/sdk": "^1.22.0",
38
41
  "axios": "^1.6.0",
39
42
  "ioredis": "^5.8.0",
40
43
  "jose": "^6.1.0",
41
44
  "openapi-mcp-generator": "^3.2.0",
42
45
  "reflect-metadata": "^0.2.2",
43
46
  "rxjs": "^7.8.0",
44
- "zod-from-json-schema": "^0.5.1",
45
- "zod-to-json-schema": "^3.24.6",
47
+ "json-schema-to-zod-v3": "1.0.0",
48
+ "zod-to-json-schema": "^3.25.0",
46
49
  "tslib": "^2.3.0"
47
50
  },
48
51
  "devDependencies": {
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Test fixtures for hooks
3
+ */
4
+ import { HookMetadata } from '../../common/metadata';
5
+ import { Token } from '../../common/interfaces';
6
+ /**
7
+ * Test token for hook target
8
+ */
9
+ export declare const TEST_HOOK_TARGET: Token;
10
+ /**
11
+ * Creates a simple hook metadata object
12
+ */
13
+ export declare function createHookMetadata(overrides?: Partial<HookMetadata>): HookMetadata;
14
+ /**
15
+ * Creates a "will" stage hook metadata
16
+ */
17
+ export declare function createWillHookMetadata(flow?: string, stage?: string): HookMetadata;
18
+ /**
19
+ * Creates a "did" stage hook metadata
20
+ */
21
+ export declare function createDidHookMetadata(flow?: string, stage?: string): HookMetadata;
22
+ /**
23
+ * Creates an "around" stage hook metadata
24
+ */
25
+ export declare function createAroundHookMetadata(flow?: string, stage?: string): HookMetadata;
26
+ /**
27
+ * Mock hook class for testing
28
+ */
29
+ export declare class MockHookClass {
30
+ onExecute: jest.Mock<Promise<void>, [ctx: any], any>;
31
+ willExecute: jest.Mock<Promise<void>, [ctx: any], any>;
32
+ didExecute: jest.Mock<Promise<void>, [ctx: any], any>;
33
+ aroundExecute: jest.Mock<Promise<any>, [ctx: any, next: () => Promise<any>], any>;
34
+ }
35
+ /**
36
+ * Creates a mock hook instance for testing
37
+ */
38
+ export declare function createMockHookInstance(metadata?: Partial<HookMetadata>): {
39
+ metadata: HookMetadata<keyof ExtendFlows, string, any>;
40
+ instance: MockHookClass;
41
+ execute: jest.Mock<Promise<void>, [ctx: any], any>;
42
+ };
43
+ /**
44
+ * Creates multiple hooks with different priorities
45
+ */
46
+ export declare function createPriorityHooks(priorities: number[]): HookMetadata[];