frontmcp 0.8.0 → 0.9.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
CHANGED
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
</picture>
|
|
8
8
|
<hr>
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
_Made with ❤️ for TypeScript developers_
|
|
10
|
+
**The TypeScript way to build MCP servers with decorators, DI, and Streamable HTTP.**
|
|
13
11
|
|
|
14
12
|
[](https://www.npmjs.com/package/@frontmcp/sdk)
|
|
15
13
|
[](https://nodejs.org)
|
|
16
14
|
[](https://github.com/agentfront/frontmcp/blob/main/LICENSE)
|
|
17
15
|
[](https://snyk.io/test/github/agentfront/frontmcp)
|
|
18
16
|
|
|
17
|
+
[Docs][docs-home] • [Quickstart][docs-quickstart] • [API Reference][docs-sdk-ref] • [Discord](https://discord.gg/frontmcp)
|
|
18
|
+
|
|
19
19
|
</div>
|
|
20
20
|
|
|
21
21
|
---
|
|
@@ -24,13 +24,12 @@ FrontMCP is a **TypeScript-first framework** for the [Model Context Protocol (MC
|
|
|
24
24
|
You write clean, typed code; FrontMCP handles the protocol, transport, DI, session/auth, and execution flow.
|
|
25
25
|
|
|
26
26
|
```ts
|
|
27
|
-
// src/main.ts
|
|
28
27
|
import 'reflect-metadata';
|
|
29
28
|
import { FrontMcp, LogLevel } from '@frontmcp/sdk';
|
|
30
29
|
import HelloApp from './hello.app';
|
|
31
30
|
|
|
32
31
|
@FrontMcp({
|
|
33
|
-
info: { name: 'Demo
|
|
32
|
+
info: { name: 'Demo', version: '0.1.0' },
|
|
34
33
|
apps: [HelloApp],
|
|
35
34
|
http: { port: 3000 },
|
|
36
35
|
logging: { level: LogLevel.Info },
|
|
@@ -38,424 +37,99 @@ import HelloApp from './hello.app';
|
|
|
38
37
|
export default class Server {}
|
|
39
38
|
```
|
|
40
39
|
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
<!-- omit in toc -->
|
|
44
|
-
|
|
45
|
-
## Table of Contents
|
|
46
|
-
|
|
47
|
-
- [Why FrontMCP?](#why-frontmcp)
|
|
48
|
-
- [Installation](#installation)
|
|
49
|
-
- [Quickstart](#quickstart)
|
|
50
|
-
- [1) Create Your FrontMCP Server](#1-create-your-frontmcp-server)
|
|
51
|
-
- [2) Define an App](#2-define-an-app)
|
|
52
|
-
- [3) Add Your First Tool](#3-add-your-first-tool)
|
|
53
|
-
- [4) Run It](#4-run-it)
|
|
54
|
-
- [Function and Class Tools](#function-and-class-tools)
|
|
55
|
-
- [Scripts & tsconfig](#scripts--tsconfig)
|
|
56
|
-
- [Inspector](#inspector)
|
|
57
|
-
- [Core Concepts](#core-concepts)
|
|
58
|
-
- [Servers](#servers)
|
|
59
|
-
- [Apps](#apps)
|
|
60
|
-
- [Tools](#tools)
|
|
61
|
-
- [Resources](#resources)
|
|
62
|
-
- [Prompts](#prompts)
|
|
63
|
-
- [Providers / Adapters / Plugins](#providers--adapters--plugins)
|
|
64
|
-
- [Authentication](#authentication)
|
|
65
|
-
- [Remote OAuth](#remote-oauth)
|
|
66
|
-
- [Local OAuth](#local-oauth)
|
|
67
|
-
- [Sessions & Transport](#sessions--transport)
|
|
68
|
-
- [Deployment](#deployment)
|
|
69
|
-
- [Local Dev](#local-dev)
|
|
70
|
-
- [Production](#production)
|
|
71
|
-
- [Version Alignment](#version-alignment)
|
|
72
|
-
- [Contributing](#contributing)
|
|
73
|
-
- [License](#license)
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## Why FrontMCP?
|
|
78
|
-
|
|
79
|
-
- **TypeScript-native DX** — decorators, Zod, and strong typing end-to-end
|
|
80
|
-
- **Scoped invoker + DI** — secure, composable execution with hooks
|
|
81
|
-
- **Adapters & Plugins** — extend your server without boilerplate
|
|
82
|
-
- **Spec-aligned transport** — Streamable HTTP for modern MCP clients
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
40
|
## Installation
|
|
87
41
|
|
|
88
|
-
**
|
|
89
|
-
|
|
90
|
-
- **Node.js**: Minimum version 22 (LTS) | Recommended version 24 (Active LTS)
|
|
91
|
-
- _This framework is developed and tested on Node.js 24_
|
|
92
|
-
- **npm**: ≥ 10 (or pnpm/yarn equivalent)
|
|
93
|
-
|
|
94
|
-
For detailed setup instructions, see the [Installation Guide][1].
|
|
95
|
-
|
|
96
|
-
### Option A — New project (recommended)
|
|
42
|
+
**Node.js 22+** required (24 recommended).
|
|
97
43
|
|
|
98
44
|
```bash
|
|
45
|
+
# New project (recommended)
|
|
99
46
|
npx frontmcp create my-app
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
This scaffolds a FrontMCP project, writes a modern ESM `tsconfig.json` for decorators, adds helpful package scripts, and
|
|
103
|
-
installs required dev deps. ([Installation - FrontMCP][1])
|
|
104
47
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```bash
|
|
48
|
+
# Existing project
|
|
108
49
|
npm i -D frontmcp @types/node@^22
|
|
109
50
|
npx frontmcp init
|
|
110
51
|
```
|
|
111
52
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
// src/tools/greet.tool.ts
|
|
156
|
-
import { Tool } from '@frontmcp/sdk';
|
|
157
|
-
import { z } from 'zod';
|
|
158
|
-
|
|
159
|
-
@Tool({
|
|
160
|
-
name: 'greet',
|
|
161
|
-
description: 'Greets a user by name',
|
|
162
|
-
inputSchema: { name: z.string() },
|
|
163
|
-
})
|
|
164
|
-
export default class GreetTool {
|
|
165
|
-
async execute({ name }: { name: string }) {
|
|
166
|
-
return `Hello, ${name}!`;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### 4) Run It
|
|
172
|
-
|
|
173
|
-
Add scripts (if you didn't use `frontmcp create`):
|
|
174
|
-
|
|
175
|
-
```json
|
|
176
|
-
{
|
|
177
|
-
"scripts": {
|
|
178
|
-
"dev": "frontmcp dev",
|
|
179
|
-
"build": "frontmcp build",
|
|
180
|
-
"start": "node dist/main.js"
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
Then:
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
npm run dev
|
|
189
|
-
# Server listening on http://localhost:3000
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
> **Tip:** FrontMCP speaks **MCP Streamable HTTP**. Connect any MCP-capable client and call `greet` with
|
|
193
|
-
> `{"name": "Ada"}`. ([Quickstart - FrontMCP][2])
|
|
194
|
-
|
|
195
|
-
### Function and Class Tools
|
|
196
|
-
|
|
197
|
-
Tools are typed actions with Zod schemas. Implement them as classes with `@Tool({...})` or inline via `tool()`. Pass
|
|
198
|
-
**Zod fields directly** (no `z.object({...})`). ([Tools - FrontMCP][4])
|
|
199
|
-
|
|
200
|
-
**Function tool**
|
|
201
|
-
|
|
202
|
-
```ts
|
|
203
|
-
import { tool } from '@frontmcp/sdk';
|
|
204
|
-
import { z } from 'zod';
|
|
205
|
-
|
|
206
|
-
export default tool({
|
|
207
|
-
name: 'greet',
|
|
208
|
-
description: 'Greets a user by name',
|
|
209
|
-
inputSchema: { name: z.string() }, // shape, not z.object
|
|
210
|
-
})(({ name }) => `Hello, ${name}!`);
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
**Class tool**
|
|
214
|
-
|
|
215
|
-
```ts
|
|
216
|
-
import { Tool } from '@frontmcp/sdk';
|
|
217
|
-
import { z } from 'zod';
|
|
218
|
-
|
|
219
|
-
@Tool({
|
|
220
|
-
name: 'add',
|
|
221
|
-
description: 'Add two numbers',
|
|
222
|
-
inputSchema: { a: z.number(), b: z.number() },
|
|
223
|
-
})
|
|
224
|
-
export default class AddTool {
|
|
225
|
-
async execute({ a, b }: { a: number; b: number }) {
|
|
226
|
-
return a + b;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Scripts & tsconfig
|
|
232
|
-
|
|
233
|
-
After `create` or `init`, you’ll have:
|
|
234
|
-
|
|
235
|
-
```json
|
|
236
|
-
{
|
|
237
|
-
"scripts": {
|
|
238
|
-
"dev": "frontmcp dev",
|
|
239
|
-
"build": "frontmcp build",
|
|
240
|
-
"inspect": "frontmcp inspector",
|
|
241
|
-
"doctor": "frontmcp doctor"
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
These map to dev watch, production build, zero‑setup Inspector launch, and environment checks. ([Installation -
|
|
247
|
-
FrontMCP][1])
|
|
248
|
-
|
|
249
|
-
**Recommended `tsconfig.json` (ESM + decorators)**
|
|
250
|
-
|
|
251
|
-
```json
|
|
252
|
-
{
|
|
253
|
-
"compilerOptions": {
|
|
254
|
-
"target": "es2021",
|
|
255
|
-
"module": "esnext",
|
|
256
|
-
"lib": ["es2021"],
|
|
257
|
-
"moduleResolution": "bundler",
|
|
258
|
-
"rootDir": "src",
|
|
259
|
-
"outDir": "dist",
|
|
260
|
-
"strict": true,
|
|
261
|
-
"esModuleInterop": true,
|
|
262
|
-
"resolveJsonModule": true,
|
|
263
|
-
"skipLibCheck": true,
|
|
264
|
-
"experimentalDecorators": true,
|
|
265
|
-
"emitDecoratorMetadata": true,
|
|
266
|
-
"sourceMap": true
|
|
267
|
-
},
|
|
268
|
-
"include": ["src/**/*.ts"],
|
|
269
|
-
"exclude": ["**/*.test.ts", "**/__tests__/**"]
|
|
270
|
-
}
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
This mirrors what `init` writes for you. ([Local Dev Server - FrontMCP][3])
|
|
274
|
-
|
|
275
|
-
**Optional `tsconfig.build.json`**
|
|
276
|
-
|
|
277
|
-
```json
|
|
278
|
-
{
|
|
279
|
-
"extends": "./tsconfig.json",
|
|
280
|
-
"compilerOptions": {
|
|
281
|
-
"declaration": true,
|
|
282
|
-
"sourceMap": false
|
|
283
|
-
},
|
|
284
|
-
"exclude": ["**/*.test.ts", "**/__tests__/**", "src/**/*.dev.ts"]
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### Inspector
|
|
289
|
-
|
|
290
|
-
Run a browser UI to exercise tools and messages:
|
|
291
|
-
|
|
292
|
-
```bash
|
|
293
|
-
npm run inspect
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
This launches the MCP Inspector; point it at your local server (e.g., `http://localhost:3000`). ([Local Dev Server -
|
|
297
|
-
FrontMCP][3])
|
|
298
|
-
|
|
299
|
-
---
|
|
300
|
-
|
|
301
|
-
## Core Concepts
|
|
302
|
-
|
|
303
|
-
### Servers
|
|
304
|
-
|
|
305
|
-
The FrontMCP server is defined with a single decorator: `@FrontMcp({...})`. It configures **info**, **apps**, **http**,
|
|
306
|
-
**logging**, **session**, and optional **auth**. Start minimal and scale up with providers and plugins.
|
|
307
|
-
([The FrontMCP Server - FrontMCP][5])
|
|
308
|
-
|
|
309
|
-
### Apps
|
|
310
|
-
|
|
311
|
-
Apps are the **organizational units** for capabilities. Each app groups related **tools**, **resources**, and **prompts**
|
|
312
|
-
into a cohesive domain, along with **providers**, **adapters**, and **plugins**. With `splitByApp: true`, apps get
|
|
313
|
-
isolated scopes and auth surfaces. ([Apps - FrontMCP][6])
|
|
314
|
-
|
|
315
|
-
### Tools
|
|
316
|
-
|
|
317
|
-
Tools are **typed actions** that execute operations with side effects. They're the primary way to enable an AI model to
|
|
318
|
-
interact with external systems—calling APIs, modifying data, performing calculations, or triggering workflows. Use the
|
|
319
|
-
class `@Tool` decorator or inline `tool({...})(handler)` with Zod schemas. ([Tools - FrontMCP][4])
|
|
320
|
-
|
|
321
|
-
### Resources
|
|
322
|
-
|
|
323
|
-
Resources expose **readable data** to an AI model's context. Unlike tools that execute actions with side effects,
|
|
324
|
-
resources are designed for read-only data retrieval—configuration files, user profiles, documents, or any content
|
|
325
|
-
the model needs to reference. ([Resources - FrontMCP][7])
|
|
326
|
-
|
|
327
|
-
### Prompts
|
|
328
|
-
|
|
329
|
-
Prompts provide **reusable message templates** for AI interactions. They return MCP `GetPromptResult` with typed
|
|
330
|
-
arguments, enabling consistent conversation patterns. ([Prompts - FrontMCP][8])
|
|
331
|
-
|
|
332
|
-
### Providers / Adapters / Plugins
|
|
333
|
-
|
|
334
|
-
Inject shared services, generate tools from OpenAPI specs, and add cross‑cutting behavior like caching and hooks.
|
|
335
|
-
([Add OpenAPI Adapter - FrontMCP][9])
|
|
336
|
-
|
|
337
|
-
---
|
|
338
|
-
|
|
339
|
-
## Authentication
|
|
340
|
-
|
|
341
|
-
Configure auth at the **server** (shared) or **per app** (isolated). With `splitByApp: true`, define auth **per app**
|
|
342
|
-
(server‑level `auth` is disallowed). ([Authentication - FrontMCP][10])
|
|
343
|
-
|
|
344
|
-
### Remote OAuth
|
|
345
|
-
|
|
346
|
-
```ts
|
|
347
|
-
auth: {
|
|
348
|
-
type: 'remote',
|
|
349
|
-
name: 'frontegg',
|
|
350
|
-
baseUrl: 'https://idp.example.com',
|
|
351
|
-
dcrEnabled?: boolean,
|
|
352
|
-
clientId?: string | ((info: { clientId: string }) => string),
|
|
353
|
-
mode?: 'orchestrated' | 'transparent',
|
|
354
|
-
allowAnonymous?: boolean,
|
|
355
|
-
consent?: boolean,
|
|
356
|
-
scopes?: string[],
|
|
357
|
-
grantTypes?: ('authorization_code' | 'refresh_token')[],
|
|
358
|
-
authEndpoint?: string,
|
|
359
|
-
tokenEndpoint?: string,
|
|
360
|
-
registrationEndpoint?: string,
|
|
361
|
-
userInfoEndpoint?: string,
|
|
362
|
-
jwks?: JSONWebKeySet,
|
|
363
|
-
jwksUri?: string
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
See **Authentication → Remote OAuth** for full details and DCR vs non‑DCR. ([Remote OAuth - FrontMCP][11])
|
|
368
|
-
|
|
369
|
-
### Local OAuth
|
|
370
|
-
|
|
371
|
-
```ts
|
|
372
|
-
auth: {
|
|
373
|
-
type: 'local',
|
|
374
|
-
id: 'local',
|
|
375
|
-
name: 'Local Auth',
|
|
376
|
-
scopes?: string[],
|
|
377
|
-
grantTypes?: ('authorization_code' | 'refresh_token')[],
|
|
378
|
-
allowAnonymous?: boolean, // default true
|
|
379
|
-
consent?: boolean,
|
|
380
|
-
jwks?: JSONWebKeySet,
|
|
381
|
-
signKey?: JWK | Uint8Array
|
|
382
|
-
}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
Use per‑app when isolating scopes. ([Local OAuth - FrontMCP][12])
|
|
386
|
-
|
|
387
|
-
---
|
|
388
|
-
|
|
389
|
-
## Sessions & Transport
|
|
390
|
-
|
|
391
|
-
```ts
|
|
392
|
-
session: {
|
|
393
|
-
sessionMode?: 'stateful' | 'stateless' | ((issuer) => ...), // default 'stateless'
|
|
394
|
-
transportIdMode?: 'uuid' | 'jwt' | ((issuer) => ...), // default 'uuid'
|
|
395
|
-
}
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
- **Stateful**: server‑side store (e.g., Redis); supports refresh; best for short‑lived upstream tokens.
|
|
399
|
-
- **Stateless**: embeds session in JWT; simpler but no silent refresh.
|
|
400
|
-
- **Transport IDs**: `uuid` (per node) or `jwt` (signed; distributed setups). ([The FrontMCP Server - FrontMCP][5])
|
|
401
|
-
|
|
402
|
-
---
|
|
403
|
-
|
|
404
|
-
## Deployment
|
|
405
|
-
|
|
406
|
-
### Local Dev
|
|
407
|
-
|
|
408
|
-
```bash
|
|
409
|
-
npm run dev
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
- Default HTTP port: `3000` unless configured
|
|
413
|
-
- `npm run doctor` checks Node/npm versions, `tsconfig`, and scripts. ([Local Dev Server - FrontMCP][3])
|
|
414
|
-
|
|
415
|
-
### Production
|
|
416
|
-
|
|
417
|
-
```bash
|
|
418
|
-
npm run build
|
|
419
|
-
NODE_ENV=production PORT=8080 npm start
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
Builds to `dist/` (uses `tsconfig.build.json`). Consider a process manager and reverse proxy; align all `@frontmcp/*`
|
|
423
|
-
versions. ([Production Build - FrontMCP][13])
|
|
424
|
-
|
|
425
|
-
---
|
|
53
|
+
> Full setup guide: [Installation][docs-install]
|
|
54
|
+
|
|
55
|
+
## Capabilities
|
|
56
|
+
|
|
57
|
+
| Capability | Description | Docs |
|
|
58
|
+
| -------------------- | ------------------------------------------------------------------------------- | ------------------------------- |
|
|
59
|
+
| **@FrontMcp Server** | Decorator-configured server with info, apps, HTTP, logging, session, auth | [Server][docs-server] |
|
|
60
|
+
| **@App** | Organizational units grouping tools, resources, prompts with optional isolation | [Apps][docs-apps] |
|
|
61
|
+
| **@Tool** | Typed actions with Zod schemas — class or function style | [Tools][docs-tools] |
|
|
62
|
+
| **@Resource** | Read-only data exposure with static and template URIs | [Resources][docs-resources] |
|
|
63
|
+
| **@Prompt** | Reusable message templates returning `GetPromptResult` | [Prompts][docs-prompts] |
|
|
64
|
+
| **@Agent** | Orchestrated multi-step tool chains | [Agents][docs-agents] |
|
|
65
|
+
| **Elicitation** | Request structured user input mid-flow | [Elicitation][docs-elicitation] |
|
|
66
|
+
| **Skills** | HTTP-discoverable tool manifests for agent marketplaces | [Skills][docs-skills] |
|
|
67
|
+
| **Discovery** | Automatic capability advertisement for MCP clients | [Discovery][docs-discovery] |
|
|
68
|
+
| **Authentication** | Remote OAuth, Local OAuth, JWKS, DCR, per-app auth | [Authentication][docs-auth] |
|
|
69
|
+
| **Sessions** | Stateful/stateless session modes with JWT or UUID transport IDs | [Server][docs-server] |
|
|
70
|
+
| **Direct Client** | In-process `create()`, `connect()`, `connectOpenAI()`, `connectClaude()` | [Direct Client][docs-direct] |
|
|
71
|
+
| **Transport** | Streamable HTTP + SSE with session headers | [Transport][docs-transport] |
|
|
72
|
+
| **Ext-Apps** | Mount external MCP servers as sub-apps | [Ext-Apps][docs-ext-apps] |
|
|
73
|
+
| **Hooks** | 5 hook families: tool, list-tools, HTTP, resource, prompt | [Hooks][docs-hooks] |
|
|
74
|
+
| **Providers / DI** | Scoped dependency injection with GLOBAL and CONTEXT scopes | [Providers][docs-providers] |
|
|
75
|
+
| **Plugins** | Cache, Remember, CodeCall, Dashboard — or build your own | [Plugins][docs-plugins] |
|
|
76
|
+
| **Adapters** | Generate tools from OpenAPI specs | [Adapters][docs-adapters] |
|
|
77
|
+
| **Testing** | E2E fixtures, matchers, HTTP mocking for MCP servers | [Testing][docs-testing] |
|
|
78
|
+
| **UI Library** | HTML/React widgets, SSR, MCP Bridge, web components | [UI][docs-ui] |
|
|
79
|
+
| **CLI** | `create`, `init`, `dev`, `build`, `inspector`, `doctor` | [CLI][docs-install] |
|
|
80
|
+
| **Deployment** | Local dev, production builds, version alignment | [Deployment][docs-deploy] |
|
|
81
|
+
|
|
82
|
+
## Packages
|
|
83
|
+
|
|
84
|
+
| Package | Description |
|
|
85
|
+
| ------------------------------------- | ------------------------------------------------------ |
|
|
86
|
+
| [`@frontmcp/sdk`](libs/sdk) | Core framework — decorators, DI, flows, transport |
|
|
87
|
+
| [`@frontmcp/cli`](libs/cli) | CLI tooling (`frontmcp create`, `dev`, `build`) |
|
|
88
|
+
| [`@frontmcp/auth`](libs/auth) | Authentication, OAuth, JWKS, credential vault |
|
|
89
|
+
| [`@frontmcp/adapters`](libs/adapters) | OpenAPI adapter for auto-generating tools |
|
|
90
|
+
| [`@frontmcp/plugins`](libs/plugins) | Official plugins: Cache, Remember, CodeCall, Dashboard |
|
|
91
|
+
| [`@frontmcp/testing`](libs/testing) | E2E test framework with fixtures and matchers |
|
|
92
|
+
| [`@frontmcp/ui`](libs/ui) | React components, hooks, SSR renderers |
|
|
93
|
+
| [`@frontmcp/uipack`](libs/uipack) | React-free themes, build tools, platform adapters |
|
|
94
|
+
| [`@frontmcp/di`](libs/di) | Dependency injection container (internal) |
|
|
95
|
+
| [`@frontmcp/utils`](libs/utils) | Shared utilities — naming, URI, crypto, FS (internal) |
|
|
426
96
|
|
|
427
97
|
## Version Alignment
|
|
428
98
|
|
|
429
|
-
|
|
430
|
-
([Production Build - FrontMCP][13])
|
|
431
|
-
|
|
432
|
-
---
|
|
99
|
+
Keep all `@frontmcp/*` packages on the same version. A clear **"version mismatch"** error is thrown at boot if versions drift. ([Production Build][docs-production])
|
|
433
100
|
|
|
434
101
|
## Contributing
|
|
435
102
|
|
|
436
|
-
|
|
437
|
-
checklist.
|
|
438
|
-
- Keep changes focused, add/adjust Jest specs, and update docs/snippets when behavior changes.
|
|
439
|
-
- Before opening a PR run `yarn nx run-many -t lint,test,build`, `npx frontmcp doctor`, and verify the demo/Inspector
|
|
440
|
-
flows relevant to your change.
|
|
441
|
-
- Align `@frontmcp/*` versions in examples to avoid runtime version mismatches.
|
|
442
|
-
|
|
443
|
-
---
|
|
103
|
+
PRs welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow, coding standards, and the PR checklist.
|
|
444
104
|
|
|
445
105
|
## License
|
|
446
106
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
[
|
|
452
|
-
[
|
|
453
|
-
[
|
|
454
|
-
[
|
|
455
|
-
[
|
|
456
|
-
[
|
|
457
|
-
[
|
|
458
|
-
[
|
|
459
|
-
[
|
|
460
|
-
[
|
|
461
|
-
[
|
|
107
|
+
[Apache-2.0](./LICENSE)
|
|
108
|
+
|
|
109
|
+
<!-- docs links -->
|
|
110
|
+
|
|
111
|
+
[docs-home]: https://docs.agentfront.dev/frontmcp 'FrontMCP Docs'
|
|
112
|
+
[docs-install]: https://docs.agentfront.dev/frontmcp/getting-started/installation 'Installation'
|
|
113
|
+
[docs-quickstart]: https://docs.agentfront.dev/frontmcp/getting-started/quickstart 'Quickstart'
|
|
114
|
+
[docs-sdk-ref]: https://docs.agentfront.dev/frontmcp/sdk-reference/overview 'SDK Reference'
|
|
115
|
+
[docs-server]: https://docs.agentfront.dev/frontmcp/servers/server 'The FrontMCP Server'
|
|
116
|
+
[docs-apps]: https://docs.agentfront.dev/frontmcp/servers/apps 'Apps'
|
|
117
|
+
[docs-tools]: https://docs.agentfront.dev/frontmcp/servers/tools 'Tools'
|
|
118
|
+
[docs-resources]: https://docs.agentfront.dev/frontmcp/servers/resources 'Resources'
|
|
119
|
+
[docs-prompts]: https://docs.agentfront.dev/frontmcp/servers/prompts 'Prompts'
|
|
120
|
+
[docs-agents]: https://docs.agentfront.dev/frontmcp/servers/agents 'Agents'
|
|
121
|
+
[docs-elicitation]: https://docs.agentfront.dev/frontmcp/servers/elicitation 'Elicitation'
|
|
122
|
+
[docs-skills]: https://docs.agentfront.dev/frontmcp/servers/skills 'Skills'
|
|
123
|
+
[docs-discovery]: https://docs.agentfront.dev/frontmcp/servers/discovery 'Discovery'
|
|
124
|
+
[docs-auth]: https://docs.agentfront.dev/frontmcp/authentication/overview 'Authentication'
|
|
125
|
+
[docs-direct]: https://docs.agentfront.dev/frontmcp/deployment/direct-client 'Direct Client'
|
|
126
|
+
[docs-transport]: https://docs.agentfront.dev/frontmcp/deployment/transport 'Transport'
|
|
127
|
+
[docs-ext-apps]: https://docs.agentfront.dev/frontmcp/servers/ext-apps 'Ext-Apps'
|
|
128
|
+
[docs-hooks]: https://docs.agentfront.dev/frontmcp/extensibility/hooks 'Hooks'
|
|
129
|
+
[docs-providers]: https://docs.agentfront.dev/frontmcp/extensibility/providers 'Providers'
|
|
130
|
+
[docs-plugins]: https://docs.agentfront.dev/frontmcp/plugins/overview 'Plugins'
|
|
131
|
+
[docs-adapters]: https://docs.agentfront.dev/frontmcp/adapters/overview 'Adapters'
|
|
132
|
+
[docs-testing]: https://docs.agentfront.dev/frontmcp/testing/overview 'Testing'
|
|
133
|
+
[docs-ui]: https://docs.agentfront.dev/frontmcp/ui/overview 'UI Library'
|
|
134
|
+
[docs-deploy]: https://docs.agentfront.dev/frontmcp/deployment/local-dev-server 'Deployment'
|
|
135
|
+
[docs-production]: https://docs.agentfront.dev/frontmcp/deployment/production-build 'Production Build'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontmcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "FrontMCP command line interface",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"node": ">=22.0.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@frontmcp/utils": "0.
|
|
32
|
+
"@frontmcp/utils": "0.9.0",
|
|
33
33
|
"tslib": "^2.3.0",
|
|
34
34
|
"@rspack/core": "^1.3.12"
|
|
35
35
|
},
|
|
@@ -49,10 +49,13 @@ class HttpClient {
|
|
|
49
49
|
baseHeaders["Content-Type"] = baseHeaders["Content-Type"] ?? "application/json";
|
|
50
50
|
}
|
|
51
51
|
if (this.ctx.logDebug) {
|
|
52
|
+
// Redact sensitive headers to prevent credential leakage in logs
|
|
53
|
+
const SENSITIVE_HEADERS = ['authorization', 'x-api-key', 'cookie', 'x-auth-token'];
|
|
54
|
+
const sanitizedHeaders = Object.fromEntries(Object.entries(baseHeaders).map(([k, v]) => [k, SENSITIVE_HEADERS.includes(k.toLowerCase()) ? '[REDACTED]' : v]));
|
|
52
55
|
console.debug("[HttpClient] Request", {
|
|
53
56
|
url: url.toString(),
|
|
54
57
|
method: options.method,
|
|
55
|
-
headers:
|
|
58
|
+
headers: sanitizedHeaders,
|
|
56
59
|
body: options.bodyJson
|
|
57
60
|
});
|
|
58
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../../../../src/templates/3rd-party-integration/src/http-client.ts"],"names":[],"mappings":";;;AAiBA,MAAa,UAAU;IACD;IAApB,YAAoB,GAAmB;QAAnB,QAAG,GAAH,GAAG,CAAgB;IAAG,CAAC;IAEnC,iBAAiB;QACvB,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;QAC1B,IAAI,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;YAC7B,OAAO,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QAChE,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;YACvB,OAAO,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;QAC1D,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;YACvB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC;YACnD,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7C,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAA2B;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEpD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnD,IAAI,CAAC,KAAK,SAAS;oBAAE,SAAS;gBAC9B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAA2B;YAC1C,MAAM,EAAE,kBAAkB;YAC1B,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,GAAG,IAAI,CAAC,iBAAiB,EAAE;YAC3B,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;SAC3B,CAAC;QAEF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,KAAK,CAAC;QAC9C,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;QAE1D,MAAM,IAAI,GAAgB;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,WAAW;YACpB,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC;QAEF,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC7C,WAAW,CAAC,cAAc,CAAC,GAAG,WAAW,CAAC,cAAc,CAAC,IAAI,kBAAkB,CAAC;QAClF,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE;gBACpC,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;gBACnB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../../../../src/templates/3rd-party-integration/src/http-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { ExecuteContext } from \"./mcp-http-types\";\n\nexport interface HttpRequestOptions {\n method: string;\n path: string; // already resolved (including path params)\n query?: Record<string, string | number | boolean | undefined>;\n headers?: Record<string, string>;\n bodyJson?: unknown;\n}\n\nexport interface HttpResponseRaw {\n status: number;\n headers: Record<string, string>;\n json?: any;\n text?: string;\n}\n\nexport class HttpClient {\n constructor(private ctx: ExecuteContext) {}\n\n private resolveAuthHeader(): Record<string, string> {\n const { auth } = this.ctx;\n if (auth.oauth2?.accessToken) {\n return { Authorization: `Bearer ${auth.oauth2.accessToken}` };\n }\n if (auth.bearer?.token) {\n return { Authorization: `Bearer ${auth.bearer.token}` };\n }\n if (auth.apiKey?.value) {\n const headerName = auth.apiKey.name ?? \"X-API-Key\";\n return { [headerName]: auth.apiKey.value };\n }\n return {};\n }\n\n async request(options: HttpRequestOptions): Promise<HttpResponseRaw> {\n const fetchImpl = this.ctx.fetch ?? fetch;\n const url = new URL(options.path, this.ctx.baseUrl);\n\n if (options.query) {\n for (const [k, v] of Object.entries(options.query)) {\n if (v === undefined) continue;\n url.searchParams.set(k, String(v));\n }\n }\n\n const baseHeaders: Record<string, string> = {\n Accept: \"application/json\",\n ...(this.ctx.requestId ? { \"X-Request-Id\": this.ctx.requestId } : {}),\n ...this.resolveAuthHeader(),\n ...(options.headers ?? {})\n };\n\n const controller = new AbortController();\n const timeoutMs = this.ctx.timeoutMs ?? 15000;\n const t = setTimeout(() => controller.abort(), timeoutMs);\n\n const init: RequestInit = {\n method: options.method,\n headers: baseHeaders,\n signal: controller.signal\n };\n\n if (options.bodyJson !== undefined) {\n init.body = JSON.stringify(options.bodyJson);\n baseHeaders[\"Content-Type\"] = baseHeaders[\"Content-Type\"] ?? \"application/json\";\n }\n\n if (this.ctx.logDebug) {\n // Redact sensitive headers to prevent credential leakage in logs\n const SENSITIVE_HEADERS = ['authorization', 'x-api-key', 'cookie', 'x-auth-token'];\n const sanitizedHeaders = Object.fromEntries(\n Object.entries(baseHeaders).map(([k, v]) =>\n [k, SENSITIVE_HEADERS.includes(k.toLowerCase()) ? '[REDACTED]' : v]\n )\n );\n console.debug(\"[HttpClient] Request\", {\n url: url.toString(),\n method: options.method,\n headers: sanitizedHeaders,\n body: options.bodyJson\n });\n }\n\n try {\n const res = await fetchImpl(url.toString(), init);\n const headersObj = Object.fromEntries(res.headers.entries());\n\n let json: any | undefined;\n let text: string | undefined;\n const contentType = res.headers.get(\"content-type\") || \"\";\n\n if (contentType.includes(\"application/json\")) {\n try {\n json = await res.json();\n } catch {\n json = undefined;\n }\n } else {\n try {\n text = await res.text();\n } catch {\n text = undefined;\n }\n }\n\n if (this.ctx.logDebug) {\n console.debug(\"[HttpClient] Response\", {\n status: res.status,\n headers: headersObj,\n json,\n text\n });\n }\n\n return {\n status: res.status,\n headers: headersObj,\n json,\n text\n };\n } finally {\n clearTimeout(t);\n }\n }\n}\n"]}
|