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.
- package/README.md +1 -1
- package/cli-template/.claude/settings.json +3 -1
- package/cli-template/.claude/skills/edit-claude-files/SKILL.md +46 -0
- package/cli-template/.claude/skills/readme-generator/README.md +1 -0
- package/cli-template/.claude/skills/readme-generator/SKILL.md +237 -0
- package/cli-template/.claude/skills/readme-generator/reference/best-practices.md +218 -0
- package/cli-template/.claude/skills/readme-generator/reference/satellite-templates.md +534 -0
- package/cli-template/.claude/skills/readme-generator/reference/templates.md +385 -0
- package/cli-template/CLAUDE.md +5 -19
- package/cli-template/FA-MCP-SDK-DOC/00-FA-MCP-SDK-index.md +1 -1
- package/cli-template/FA-MCP-SDK-DOC/02-1-tools-and-api.md +60 -0
- package/cli-template/FA-MCP-SDK-DOC/04-authentication.md +10 -8
- package/cli-template/README.md +2 -1
- package/cli-template/SKILL_README.md +40 -0
- package/cli-template/package.json +1 -1
- package/cli-template/prompt-example-new-MCP.md +3 -2
- package/config/custom-environment-variables.yaml +4 -3
- package/config/default.yaml +20 -18
- package/config/local-test.yaml +44 -0
- package/dist/core/_types_/config.d.ts +8 -5
- package/dist/core/_types_/config.d.ts.map +1 -1
- package/dist/core/auth/admin-auth.d.ts +12 -5
- package/dist/core/auth/admin-auth.d.ts.map +1 -1
- package/dist/core/auth/admin-auth.js +37 -25
- package/dist/core/auth/admin-auth.js.map +1 -1
- package/dist/core/bootstrap/startup-info.d.ts.map +1 -1
- package/dist/core/bootstrap/startup-info.js +13 -5
- package/dist/core/bootstrap/startup-info.js.map +1 -1
- package/dist/core/mcp/readme-assembler.d.ts +20 -0
- package/dist/core/mcp/readme-assembler.d.ts.map +1 -0
- package/dist/core/mcp/readme-assembler.js +88 -0
- package/dist/core/mcp/readme-assembler.js.map +1 -0
- package/dist/core/mcp/resources.d.ts.map +1 -1
- package/dist/core/mcp/resources.js +2 -1
- package/dist/core/mcp/resources.js.map +1 -1
- package/dist/core/web/admin-router.js +2 -2
- package/dist/core/web/admin-router.js.map +1 -1
- package/dist/core/web/home-api.d.ts.map +1 -1
- package/dist/core/web/home-api.js +13 -5
- package/dist/core/web/home-api.js.map +1 -1
- package/dist/core/web/server-http.d.ts.map +1 -1
- package/dist/core/web/server-http.js +1 -2
- package/dist/core/web/server-http.js.map +1 -1
- package/dist/core/web/static/home/index.html +2 -2
- package/dist/core/web/static/home/script.js +2 -2
- 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
|
+
```
|