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
- <strong>The TypeScript way to build MCP servers with decorators, DI, and Streamable HTTP.</strong>
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
  [![NPM - @frontmcp/sdk](https://img.shields.io/npm/v/@frontmcp/sdk.svg?v=2)](https://www.npmjs.com/package/@frontmcp/sdk)
15
13
  [![Node](https://img.shields.io/badge/node-%3E%3D22-339933?logo=node.js&logoColor=white)](https://nodejs.org)
16
14
  [![License](https://img.shields.io/github/license/agentfront/frontmcp.svg?v=1)](https://github.com/agentfront/frontmcp/blob/main/LICENSE)
17
15
  [![Snyk](https://snyk.io/test/github/agentfront/frontmcp/badge.svg)](https://snyk.io/test/github/agentfront/frontmcp)
18
16
 
17
+ [Docs][docs-home] &bull; [Quickstart][docs-quickstart] &bull; [API Reference][docs-sdk-ref] &bull; [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 🚀', version: '0.1.0' },
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
- **Prerequisites:**
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
- ### Option B — Add to an existing project
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
- `init` adds scripts, verifies your `tsconfig.json`, and checks layout. No need to install `@frontmcp/sdk` directly—the
113
- CLI bundles a compatible SDK for you. ([Installation - FrontMCP][1])
114
-
115
- ---
116
-
117
- ## Quickstart
118
-
119
- If you haven’t installed FrontMCP yet, follow the [installation guide][1] first.
120
-
121
- ### 1) Create Your FrontMCP Server
122
-
123
- ```ts
124
- // src/main.ts
125
- import { FrontMcp, LogLevel } from '@frontmcp/sdk';
126
- import HelloApp from './hello.app';
127
-
128
- @FrontMcp({
129
- info: { name: 'Hello MCP', version: '0.1.0' },
130
- apps: [HelloApp],
131
- http: { port: 3000 },
132
- logging: { level: LogLevel.INFO },
133
- })
134
- export default class HelloServer {}
135
- ```
136
-
137
- ### 2) Define an App
138
-
139
- ```ts
140
- // src/hello.app.ts
141
- import { App } from '@frontmcp/sdk';
142
- import GreetTool from './tools/greet.tool';
143
-
144
- @App({
145
- id: 'hello',
146
- name: 'Hello App',
147
- tools: [GreetTool],
148
- })
149
- export default class HelloApp {}
150
- ```
151
-
152
- ### 3) Add Your First Tool
153
-
154
- ```ts
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
- If versions drift, the runtime will throw a clear **“version mismatch”** at boot. Keep `@frontmcp/*` versions aligned.
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
- - PRs welcome! Read the full [CONTRIBUTING.md](./CONTRIBUTING.md) for workflow details, coding standards, and the PR
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
- See [LICENSE](./LICENSE).
448
-
449
- [1]: https://docs.agentfront.dev/docs/getting-started/installation 'Installation - FrontMCP'
450
- [2]: https://docs.agentfront.dev/docs/getting-started/quickstart 'Quickstart - FrontMCP'
451
- [3]: https://docs.agentfront.dev/docs/deployment/local-dev-server 'Local Dev Server - FrontMCP'
452
- [4]: https://docs.agentfront.dev/docs/servers/tools 'Tools - FrontMCP'
453
- [5]: https://docs.agentfront.dev/docs/servers/server 'The FrontMCP Server - FrontMCP'
454
- [6]: https://docs.agentfront.dev/docs/servers/apps 'Apps - FrontMCP'
455
- [7]: https://docs.agentfront.dev/docs/servers/resources 'Resources - FrontMCP'
456
- [8]: https://docs.agentfront.dev/docs/servers/prompts 'Prompts - FrontMCP'
457
- [9]: https://docs.agentfront.dev/docs/guides/add-openapi-adapter 'Add OpenAPI Adapter - FrontMCP'
458
- [10]: https://docs.agentfront.dev/docs/authentication/overview 'Authentication - FrontMCP'
459
- [11]: https://docs.agentfront.dev/docs/authentication/remote 'Remote OAuth - FrontMCP'
460
- [12]: https://docs.agentfront.dev/docs/authentication/local 'Local OAuth - FrontMCP'
461
- [13]: https://docs.agentfront.dev/docs/deployment/production-build 'Production Build - FrontMCP'
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.8.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.8.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: baseHeaders,
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":"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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 console.debug(\"[HttpClient] Request\", {\n url: url.toString(),\n method: options.method,\n headers: baseHeaders,\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"]}
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"]}