fa-mcp-sdk 0.4.52 → 0.4.54

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 (46) hide show
  1. package/README.md +1 -1
  2. package/cli-template/.claude/settings.json +3 -1
  3. package/cli-template/.claude/skills/edit-claude-files/SKILL.md +46 -0
  4. package/cli-template/.claude/skills/readme-generator/README.md +1 -0
  5. package/cli-template/.claude/skills/readme-generator/SKILL.md +237 -0
  6. package/cli-template/.claude/skills/readme-generator/reference/best-practices.md +218 -0
  7. package/cli-template/.claude/skills/readme-generator/reference/satellite-templates.md +534 -0
  8. package/cli-template/.claude/skills/readme-generator/reference/templates.md +385 -0
  9. package/cli-template/CLAUDE.md +5 -19
  10. package/cli-template/FA-MCP-SDK-DOC/00-FA-MCP-SDK-index.md +1 -1
  11. package/cli-template/FA-MCP-SDK-DOC/02-1-tools-and-api.md +60 -0
  12. package/cli-template/FA-MCP-SDK-DOC/04-authentication.md +10 -8
  13. package/cli-template/README.md +2 -1
  14. package/cli-template/SKILL_README.md +40 -0
  15. package/cli-template/package.json +1 -1
  16. package/cli-template/prompt-example-new-MCP.md +3 -2
  17. package/config/custom-environment-variables.yaml +4 -3
  18. package/config/default.yaml +20 -18
  19. package/config/local-test.yaml +44 -0
  20. package/dist/core/_types_/config.d.ts +8 -5
  21. package/dist/core/_types_/config.d.ts.map +1 -1
  22. package/dist/core/auth/admin-auth.d.ts +12 -5
  23. package/dist/core/auth/admin-auth.d.ts.map +1 -1
  24. package/dist/core/auth/admin-auth.js +37 -25
  25. package/dist/core/auth/admin-auth.js.map +1 -1
  26. package/dist/core/bootstrap/startup-info.d.ts.map +1 -1
  27. package/dist/core/bootstrap/startup-info.js +13 -5
  28. package/dist/core/bootstrap/startup-info.js.map +1 -1
  29. package/dist/core/mcp/readme-assembler.d.ts +20 -0
  30. package/dist/core/mcp/readme-assembler.d.ts.map +1 -0
  31. package/dist/core/mcp/readme-assembler.js +88 -0
  32. package/dist/core/mcp/readme-assembler.js.map +1 -0
  33. package/dist/core/mcp/resources.d.ts.map +1 -1
  34. package/dist/core/mcp/resources.js +2 -1
  35. package/dist/core/mcp/resources.js.map +1 -1
  36. package/dist/core/web/admin-router.js +2 -2
  37. package/dist/core/web/admin-router.js.map +1 -1
  38. package/dist/core/web/home-api.d.ts.map +1 -1
  39. package/dist/core/web/home-api.js +13 -5
  40. package/dist/core/web/home-api.js.map +1 -1
  41. package/dist/core/web/server-http.d.ts.map +1 -1
  42. package/dist/core/web/server-http.js +1 -2
  43. package/dist/core/web/server-http.js.map +1 -1
  44. package/dist/core/web/static/home/index.html +2 -2
  45. package/dist/core/web/static/home/script.js +2 -2
  46. package/package.json +1 -1
@@ -0,0 +1,534 @@
1
+ # Satellite Templates (`readme-docs/*.md`)
2
+
3
+ Skeletons for common satellite Markdown files referenced from the main README. Each skeleton ends
4
+ with the values a skill should fill in from the actual project. **Create a satellite only when the
5
+ feature is enabled in the project; do not emit stubs for disabled subsystems.**
6
+
7
+ All files live under `readme-docs/` in the project root. Naming: kebab-case by topic
8
+ (`authentication.md`, `active-directory.md`, `admin-panel.md`, …).
9
+
10
+ The folder name `readme-docs/` is **not arbitrary** — the fa-mcp-sdk `doc://readme` MCP resource
11
+ looks for exactly this folder and inlines every file linked from the main README. Any other name
12
+ (`docs/`, `readme-parts/`, etc.) will be ignored by the SDK and the content will not reach the RAG
13
+ index of the MCP registry.
14
+
15
+ ---
16
+
17
+ ## `readme-docs/authentication.md`
18
+
19
+ Use when auth is non-trivial (multiple methods, header-based override, impersonation, etc.).
20
+
21
+ ```markdown
22
+ # Authentication
23
+
24
+ This document covers both the MCP server's own auth (who may call the server) and the upstream
25
+ auth (how the server authenticates to <upstream system>).
26
+
27
+ ## MCP server auth
28
+
29
+ Configured under `webServer.auth` in `config/*.yaml`. Supported methods:
30
+
31
+ - **Permanent server tokens** — O(1) set lookup, for service-to-service callers
32
+ - **Basic** — `Authorization: Basic base64(user:pass)`
33
+ - **JWT** — `Authorization: Bearer <token>`; AES-256-CTR-encrypted payload; optional IP restriction
34
+ - **Custom validator** — project-defined fallback
35
+
36
+ JWT tokens can be minted via:
37
+
38
+ - `/admin` — web UI (requires `adminPanel.enabled: true`)
39
+ - `POST /gen-jwt` — HTTP endpoint (requires `webServer.genJwtApiEnable: true`)
40
+ - `node scripts/generate-jwt.js -u <username> -ttl <duration>` — CLI
41
+
42
+ ## Per-request `x-<prefix>-*` headers
43
+
44
+ Callers can override server config with per-request headers:
45
+
46
+ | Header | Purpose |
47
+ |--------------------------|------------------------------------------|
48
+ | `x-<prefix>-token` | Personal Access Token (Bearer) |
49
+ | `x-<prefix>-username` | Basic auth username (pair with password) |
50
+ | `x-<prefix>-password` | Basic auth password (pair with username) |
51
+ | `x-on-behalf-of-user` | Impersonation proxy target (if enabled) |
52
+
53
+ When `x-<prefix>-*` credentials are present, the server's own auth check is bypassed (callers
54
+ supply their own identity).
55
+
56
+ ## Resolution order (outgoing request to <upstream>)
57
+
58
+ `authenticationHeaders()` picks the first matching rule:
59
+
60
+ | # | Source | Condition | Outgoing `Authorization` |
61
+ |---|----------------------------------------------------|------------------------------------|------------------------------------------|
62
+ | 1 | Headers `x-<prefix>-username` + `x-<prefix>-password` | both present | `Basic base64(user:pass)` → `directApi` |
63
+ | 2 | Header `x-<prefix>-token` | present | `Bearer <token>` → `directApi` |
64
+ | 3 | Config `directApi.auth.basic` | `username` + `password` populated | `Basic` from config → `directApi` |
65
+ | 4 | Config `directApi.auth.pat` | non-empty | `Bearer <pat>` → `directApi` |
66
+ | 5 | Config `directApi.auth.oauth2` | `accessToken` + client creds set | `Bearer <accessToken>` → `directApi` |
67
+ | 6 | Header `x-on-behalf-of-user` | present (impersonation enabled) | Auth from `impersonalizationPlugin.auth` |
68
+
69
+ ## Invariants
70
+
71
+ - `x-<prefix>-username` and `x-<prefix>-password` are honoured **only as a pair**.
72
+ - **Own credentials ⇒ no impersonation.** When `x-<prefix>-username/password` or
73
+ `x-<prefix>-token` is present, the `x-on-behalf-of-user` header is stripped.
74
+ - The server attaches `x-<prefix>-actual-user` to outgoing requests to record the effective user.
75
+
76
+ ## Related
77
+
78
+ - Admin panel for token generation: [Admin Panel](./admin-panel.md)
79
+ - `/gen-jwt` skill: [SKILL_README.md](../SKILL_README.md)
80
+ ```
81
+
82
+ ---
83
+
84
+ ## `readme-docs/testing.md`
85
+
86
+ Use when `agentTester.enabled: true` or a Headless test skill is present.
87
+
88
+ ```markdown
89
+ # Testing
90
+
91
+ Two ways to exercise the MCP server end-to-end with a real LLM:
92
+
93
+ 1. **Agent Tester UI** — browser chat UI at `/agent-tester`
94
+ 2. **Headless Agent Tester API** — curl-friendly HTTP endpoint at `/agent-tester/api/chat/test`
95
+
96
+ Both paths run the same agent pipeline: user message → LLM picks MCP tool → tool runs → LLM
97
+ formats response.
98
+
99
+ ## Agent Tester UI
100
+
101
+ Open `http://<host>:<port>/agent-tester` in a browser. Supply credentials in the UI (Basic / PAT /
102
+ impersonation), then chat naturally — each tool invocation is shown with arguments and raw JSON
103
+ response.
104
+
105
+ Configuration under `agentTester.*`:
106
+
107
+ | Key | Description |
108
+ |----------------------------------|--------------------------------------------------------------|
109
+ | `agentTester.enabled` | Master on/off |
110
+ | `agentTester.useAuth` | Require MCP-server auth to access the UI |
111
+ | `agentTester.sessionTtlMs` | Chat session retention |
112
+ | `agentTester.openAi.apiKey` | LLM API key (OpenAI-compatible) |
113
+ | `agentTester.openAi.baseURL` | LLM endpoint (set for Anthropic / local models) |
114
+ | `agentTester.httpHeaders.*` | Custom headers forwarded to MCP |
115
+
116
+ ## Headless Agent Tester API
117
+
118
+ Run tests without a browser. POST a message, get the agent's full trace back as JSON.
119
+
120
+ ```bash
121
+ curl -X POST http://<host>:<port>/agent-tester/api/chat/test \
122
+ -H "Content-Type: application/json" \
123
+ -H "x-<prefix>-token: <pat>" \
124
+ -d '{"message": "List my open issues"}'
125
+ ```
126
+
127
+ Response shape:
128
+
129
+ ```json
130
+ {
131
+ "messages": [ { "role": "assistant", "content": "..." } ],
132
+ "toolCalls": [ { "tool": "<name>", "arguments": {}, "response": {} } ]
133
+ }
134
+ ```
135
+
136
+ ## `/headless-test` skill
137
+
138
+ Runs intelligent tests against all tools in a controlled scope (project / space / etc.) and writes
139
+ a Markdown report to `claudedocs/test-report-{RUN_ID}.md`. See [SKILL_README.md](../SKILL_README.md).
140
+ ```
141
+
142
+ ---
143
+
144
+ ## `readme-docs/webhooks.md`
145
+
146
+ Use when the server uses `x-web-hook` or tool handlers return `hook`.
147
+
148
+ ```markdown
149
+ # Webhook Callback (`x-web-hook`)
150
+
151
+ After every tool invocation the server can POST the result to an external URL. Useful for audit,
152
+ real-time dashboards, chaining MCP calls into pipelines.
153
+
154
+ ## How to use
155
+
156
+ Pass `x-web-hook: <http(s) URL>` with any MCP tool call. After the tool finishes, the server fires
157
+ a fire-and-forget POST (10 s timeout; errors are logged but never fail the tool call).
158
+
159
+ ## Request body
160
+
161
+ ```json
162
+ {
163
+ "mcpName": "<name>",
164
+ "tool": "<tool_name>",
165
+ "user": "<acting user or omitted>",
166
+ "response": { "...": "..." }
167
+ }
168
+ ```
169
+
170
+ | Field | Description |
171
+ |------------|-----------------------------------------------------------------------------------------------|
172
+ | `mcpName` | MCP server name from config (`name`) |
173
+ | `tool` | Name of the tool that was invoked |
174
+ | `user` | Acting <upstream> user (from `x-<prefix>-actual-user` logic). Omitted if not determinable. |
175
+ | `response` | Full JSON result returned by the tool handler |
176
+
177
+ ## Per-tool hooks
178
+
179
+ A tool handler may return `{ hook: "<url>" }` in its `IToolResponse`. That per-tool URL takes
180
+ precedence over the `x-web-hook` header. If neither is present, no webhook fires.
181
+
182
+ ## Examples
183
+
184
+ ```bash
185
+ # via HTTP MCP endpoint
186
+ curl -X POST http://<host>:<port>/mcp \
187
+ -H "Content-Type: application/json" \
188
+ -H "x-web-hook: https://hooks.my-ci.com/events" \
189
+ -d '{"tool": "<tool_name>", "arguments": {...}}'
190
+
191
+ # via Headless Agent Tester
192
+ curl -X POST http://<host>:<port>/agent-tester/api/chat/test \
193
+ -H "Content-Type: application/json" \
194
+ -H "x-web-hook: https://log-collector.internal/mcp-events" \
195
+ -d '{"message": "..."}'
196
+ ```
197
+ ```
198
+
199
+ ---
200
+
201
+ ## `readme-docs/consul.md`
202
+
203
+ Use when `consul.service.enable: true`.
204
+
205
+ ```markdown
206
+ # Consul Service Discovery
207
+
208
+ Server registers itself on startup and deregisters on SIGTERM. Health check path: `/health`.
209
+
210
+ ## Configuration
211
+
212
+ ```yaml
213
+ consul:
214
+ agent:
215
+ prd:
216
+ dc: <dc>
217
+ host: <consul-host>
218
+ port: 443
219
+ secure: true
220
+ token: <agent-token>
221
+ service:
222
+ enable: true
223
+ name: <service-name>
224
+ instance: ${SERVICE_INSTANCE}
225
+ version: <version>
226
+ tags: []
227
+ meta:
228
+ who: 'http://{address}:{port}/'
229
+ check:
230
+ interval: '10s'
231
+ timeout: '5s'
232
+ deregistercriticalserviceafter: '3m'
233
+ ```
234
+
235
+ ## Environment selection
236
+
237
+ `consul.envCode.*` picks which agent block is active. Typical values: `dev`, `prd`, `reg`.
238
+
239
+ ## Access-point updater
240
+
241
+ `accessPointUpdater` (from `fa-mcp-sdk`) can periodically refresh service endpoints from Consul for
242
+ outbound calls. See `src/core/consul/access-points-updater.ts` for the contract.
243
+ ```
244
+
245
+ ---
246
+
247
+ ## `readme-docs/active-directory.md`
248
+
249
+ Use when `ad.domains.*` is populated.
250
+
251
+ ```markdown
252
+ # Active Directory
253
+
254
+ Tools can gate access by AD group membership via `group-checker` from `fa-mcp-sdk`.
255
+
256
+ ## Configuration
257
+
258
+ ```yaml
259
+ ad:
260
+ domains:
261
+ MYDOMAIN:
262
+ default: true
263
+ controllers:
264
+ - ldap://dc1.mycorp.local
265
+ - ldap://dc2.mycorp.local
266
+ username: <service-account>
267
+ password: <password>
268
+ ```
269
+
270
+ ## Usage in tools
271
+
272
+ ```typescript
273
+ import { checkUserInGroup } from 'fa-mcp-sdk';
274
+
275
+ const allowed = await checkUserInGroup({
276
+ username: ctx.user,
277
+ group: 'mcp-admins',
278
+ domain: 'MYDOMAIN',
279
+ });
280
+ ```
281
+
282
+ Caching and group lookup semantics: see `src/core/ad/group-checker.ts`.
283
+ ```
284
+
285
+ ---
286
+
287
+ ## `readme-docs/database.md`
288
+
289
+ Use when `db.*` is populated and `pg-db.js` helpers are imported.
290
+
291
+ ```markdown
292
+ # Database (PostgreSQL)
293
+
294
+ The server uses `fa-mcp-sdk`'s PostgreSQL helpers for structured persistence. pgvector is supported
295
+ for embedding storage.
296
+
297
+ ## Configuration
298
+
299
+ ```yaml
300
+ db:
301
+ MAIN:
302
+ host: <host>
303
+ port: 5432
304
+ database: <db>
305
+ user: <user>
306
+ password: <password>
307
+ schema: public
308
+ ```
309
+
310
+ ## Usage
311
+
312
+ ```typescript
313
+ import { queryRsMAIN, oneRowMAIN, execMAIN } from 'fa-mcp-sdk';
314
+
315
+ const rows = await queryRsMAIN<MyRow>('SELECT * FROM t WHERE id = $1', [id]);
316
+ ```
317
+
318
+ Connection pool and retry semantics: `src/core/db/pg-db.ts`.
319
+
320
+ ## Health
321
+
322
+ The `/health` endpoint includes DB reachability when the `db` block is configured.
323
+ ```
324
+
325
+ ---
326
+
327
+ ## `readme-docs/configuration.md`
328
+
329
+ Use when the config reference is > ~15 parameters or overlaps multiple subsystems.
330
+
331
+ ```markdown
332
+ # Configuration
333
+
334
+ Priority: env vars > `config/local.yaml` > `config/{NODE_ENV}.yaml` > `config/default.yaml`.
335
+
336
+ ## Global
337
+
338
+ | Key | Description | Default |
339
+ |---------------------------------------|-----------------------------------------|-----------|
340
+ | `name` | MCP server name | — |
341
+ | `version` | Server version | — |
342
+
343
+ ## Web server
344
+
345
+ | Key | Description | Default |
346
+ |---------------------------------------|-----------------------------------------|-----------|
347
+ | `webServer.port` | HTTP listen port | `<PORT>` |
348
+ | `webServer.host` | Bind host | `0.0.0.0` |
349
+ | `webServer.auth.enabled` | Require MCP auth | `false` |
350
+ | `webServer.auth.jwt.secret` | JWT AES key | — |
351
+ | `webServer.genJwtApiEnable` | Expose `POST /gen-jwt` | `false` |
352
+
353
+ ## MCP
354
+
355
+ | Key | Description | Default |
356
+ |---------------------------------------|-----------------------------------------|-----------|
357
+ | `mcp.toolAnswerAs` | Response format (`text` / `json`) | `text` |
358
+ | `mcp.name` | Name returned to MCP clients | — |
359
+
360
+ ## Upstream `<prefix>`
361
+
362
+ | Key | Description | Default |
363
+ |---------------------------------------|-----------------------------------------|-----------|
364
+ | `<upstream>.url` | Upstream base URL | — |
365
+ | `<upstream>.auth.pat` | Personal Access Token | — |
366
+ | `<upstream>.auth.basic.username` | Basic auth username | — |
367
+ | `<upstream>.auth.basic.password` | Basic auth password | — |
368
+ | `<upstream>.usedInstruments.include` | Allow-list (`ALL` or tool names) | `ALL` |
369
+ | `<upstream>.usedInstruments.exclude` | Deny-list | `[]` |
370
+
371
+ Fill in subsystem sections (`consul.*`, `ad.*`, `db.*`, `agentTester.*`, etc.) as needed.
372
+ ```
373
+
374
+ ---
375
+
376
+ ## `readme-docs/admin-panel.md`
377
+
378
+ Use when `adminPanel.enabled: true` and the feature is worth a dedicated page (otherwise inline a
379
+ single paragraph in the main README).
380
+
381
+ ```markdown
382
+ # Admin Panel
383
+
384
+ Web UI at `/admin` for generating and inspecting JWT tokens.
385
+
386
+ ## Configuration
387
+
388
+ ```yaml
389
+ adminPanel:
390
+ enabled: true
391
+ authType: basic
392
+ username: <admin>
393
+ password: <secret>
394
+ ```
395
+
396
+ ## What you can do
397
+
398
+ - Generate a JWT for a given username, TTL, optional `request` scope and IP allow-list
399
+ - Inspect the decoded payload
400
+ - Copy the generated token to clipboard
401
+
402
+ Tokens generated here are interchangeable with those produced by `scripts/generate-jwt.js` and the
403
+ `/gen-jwt` skill.
404
+ ```
405
+
406
+ ---
407
+
408
+ ## `readme-docs/impersonation.md`
409
+
410
+ Use when `impersonalizationPlugin.*` is configured.
411
+
412
+ ```markdown
413
+ # Impersonation (`x-on-behalf-of-user`)
414
+
415
+ When the server has access to a service account with elevated privileges, callers can request
416
+ actions on behalf of another user via the `x-on-behalf-of-user` header.
417
+
418
+ ## How it works
419
+
420
+ 1. Client sends the MCP request with `x-on-behalf-of-user: <target-username>` — and **no own
421
+ credentials**.
422
+ 2. The server authenticates to the impersonation proxy using
423
+ `impersonalizationPlugin.auth` from config.
424
+ 3. The proxy performs the upstream action as the target user.
425
+ 4. The server tags the outbound request with `x-<prefix>-actual-user: <target-username>` for audit.
426
+
427
+ ## Invariant
428
+
429
+ **Own credentials ⇒ no impersonation.** If any of `x-<prefix>-username/password` or
430
+ `x-<prefix>-token` is present in the request, `x-on-behalf-of-user` is stripped and the request
431
+ goes to `directApi.url` instead of the impersonation proxy.
432
+
433
+ ## Configuration
434
+
435
+ ```yaml
436
+ <upstream>:
437
+ impersonalizationPlugin:
438
+ url: https://impersonation-proxy.corp/api
439
+ auth:
440
+ basic:
441
+ username: <service-account>
442
+ password: <secret>
443
+ ```
444
+ ```
445
+
446
+ ---
447
+
448
+ ## `readme-docs/debugging.md`
449
+
450
+ Use when the server has namespace-based DEBUG logging (most fa-mcp-sdk projects do).
451
+
452
+ ```markdown
453
+ # Debug Logging
454
+
455
+ Namespace-based logs via the `DEBUG` environment variable.
456
+
457
+ | Namespace | What it logs |
458
+ |-------------------------------|--------------------------------------------------------|
459
+ | `<prefix>-api-request-curl` | Outgoing HTTP requests to upstream as reproducible curl |
460
+ | `<prefix>-api-response-2-console` | Upstream API responses on console |
461
+ | `<prefix>-api-response-2-file` | Upstream API responses to file |
462
+ | `tool-response` | Final result of each MCP tool call |
463
+
464
+ Examples:
465
+
466
+ ```bash
467
+ DEBUG=<prefix>-api-request-curl npm start
468
+ DEBUG=tool-response npm start
469
+ DEBUG=<prefix>-api-*,tool-response npm start
470
+ ```
471
+
472
+ On upstream HTTP request errors, the reproducible curl is always printed to console (unsuppressable
473
+ safety net in `src/lib/axios-error-handler.ts`).
474
+ ```
475
+
476
+ ---
477
+
478
+ ## `readme-docs/api.md`
479
+
480
+ Use only when the project ships a custom REST API beyond `/mcp`.
481
+
482
+ ```markdown
483
+ # REST API
484
+
485
+ Base URL: `/api/v1/<scope>` · Auth: `Bearer <token>` · Envelope: `{ success, data, meta }`.
486
+
487
+ | Method | Path | Description |
488
+ |--------|--------------------------------------------|----------------------------------|
489
+ | GET | `/api/v1/<scope>/<resource>?...` | <What it returns> |
490
+ | POST | `/api/v1/<scope>/<resource>` | <What it creates> |
491
+
492
+ Full OpenAPI spec: [`swagger/openapi.yaml`](../swagger/openapi.yaml). Also available on the running
493
+ server at `/docs` (Swagger UI), `/api/openapi.json`, `/api/openapi.yaml`.
494
+
495
+ ## Error codes
496
+
497
+ `<CODE_1>`, `<CODE_2>`, `<CODE_3>`, `ACCESS_DENIED`, `INVALID_INPUT`, `INTERNAL_ERROR`.
498
+ ```
499
+
500
+ ---
501
+
502
+ ## Project-specific satellite template
503
+
504
+ For capabilities unique to a project (fuzzy resolution, caching strategy, batch limits, content
505
+ conversion, etc.), compose a satellite with this shape:
506
+
507
+ ```markdown
508
+ # <Feature Name>
509
+
510
+ <One-sentence summary — the feature opened standalone still makes sense.>
511
+
512
+ ## Overview
513
+
514
+ <Why it exists. What problem it solves.>
515
+
516
+ ## How it works
517
+
518
+ <Mechanism. Diagrams or pseudocode as needed. Reference the relevant `src/` path.>
519
+
520
+ ## Configuration
521
+
522
+ ```yaml
523
+ <subsystem>:
524
+ <key>: <value>
525
+ ```
526
+
527
+ ## Examples
528
+
529
+ <One or two minimal, runnable examples.>
530
+
531
+ ## Caveats
532
+
533
+ <Limits, failure modes, invariants.>
534
+ ```