fa-mcp-sdk 0.4.93 → 0.4.96

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 (33) hide show
  1. package/cli-template/.claude/skills/readme-generator/reference/satellite-templates.md +1 -1
  2. package/cli-template/.claude/skills/upgrade-sdk/SKILL.md +554 -0
  3. package/cli-template/CLAUDE.md +1 -1
  4. package/cli-template/FA-MCP-SDK-DOC/03-configuration.md +9 -5
  5. package/cli-template/FA-MCP-SDK-DOC/04-authentication.md +4 -4
  6. package/cli-template/FA-MCP-SDK-DOC/08-agent-tester-and-headless-api.md +1 -1
  7. package/cli-template/package.json +1 -1
  8. package/config/_local.yaml +13 -6
  9. package/config/custom-environment-variables.yaml +1 -0
  10. package/config/default.yaml +14 -6
  11. package/dist/core/_types_/config.d.ts +1 -0
  12. package/dist/core/_types_/config.d.ts.map +1 -1
  13. package/dist/core/auth/admin-auth.d.ts.map +1 -1
  14. package/dist/core/auth/admin-auth.js +9 -10
  15. package/dist/core/auth/admin-auth.js.map +1 -1
  16. package/dist/core/auth/jwt.d.ts +18 -9
  17. package/dist/core/auth/jwt.d.ts.map +1 -1
  18. package/dist/core/auth/jwt.js +185 -51
  19. package/dist/core/auth/jwt.js.map +1 -1
  20. package/dist/core/auth/multi-auth.d.ts +4 -2
  21. package/dist/core/auth/multi-auth.d.ts.map +1 -1
  22. package/dist/core/auth/multi-auth.js +43 -31
  23. package/dist/core/auth/multi-auth.js.map +1 -1
  24. package/dist/core/auth/revocation.d.ts +1 -0
  25. package/dist/core/auth/revocation.d.ts.map +1 -1
  26. package/dist/core/auth/revocation.js +9 -2
  27. package/dist/core/auth/revocation.js.map +1 -1
  28. package/dist/core/auth/types.d.ts +5 -0
  29. package/dist/core/auth/types.d.ts.map +1 -1
  30. package/package.json +6 -2
  31. package/scripts/generate-jwt.js +61 -35
  32. package/scripts/update-sdk.js +16 -0
  33. package/cli-template/.claude/skills/upgrade-guide/SKILL.md +0 -456
@@ -30,7 +30,7 @@ Configured under `webServer.auth` in `config/*.yaml`. Supported methods:
30
30
 
31
31
  - **Permanent server tokens** — O(1) set lookup, for service-to-service callers
32
32
  - **Basic** — `Authorization: Basic base64(user:pass)`
33
- - **JWT** — `Authorization: Bearer <token>`; AES-256-CTR-encrypted payload; optional IP restriction
33
+ - **JWT** — `Authorization: Bearer <token>`; standard signed JWT (HS256); optional IP restriction
34
34
  - **Custom validator** — project-defined fallback
35
35
 
36
36
  JWT tokens can be minted via:
@@ -0,0 +1,554 @@
1
+ ---
2
+ name: upgrade-sdk
3
+ description: "Upgrade fa-mcp-sdk in the current project end-to-end: analyze the version diff, present an actionable execution plan, get user confirmation, then apply the upgrade automatically (deps, configs, code) — asking the user inline for any choices or values it needs. Falls back to a manual checklist only for items the LLM genuinely cannot perform. Use when user asks to upgrade/update fa-mcp-sdk, mentions 'обновить sdk', 'upgrade sdk', 'обновление fa-mcp-sdk', 'обнови sdk', or supplies versions to upgrade between."
4
+ disable-model-invocation: true
5
+ allowed-tools: Bash(yarn *) Bash(npm *) Bash(node *) Bash(git *) Bash(cat *) Bash(diff *) Bash(ls *) Bash(find *) Bash(mkdir *) Bash(cp *) Bash(mv *) Bash(rm *) Read Write Edit MultiEdit Glob Grep WebFetch Agent
6
+ argument-hint: "[from-version] [to-version] [language hint]"
7
+ ---
8
+
9
+ # FA-MCP-SDK Upgrader
10
+
11
+ Execute an end-to-end upgrade of the `fa-mcp-sdk` dependency in the current project: analyze the diff between two
12
+ versions, present an actionable execution plan, get user confirmation, apply the changes automatically (asking for any
13
+ inputs needed along the way), verify, and report.
14
+
15
+ ## Operating principle
16
+
17
+ **Maximize automation.** Do as much as possible inside this skill. The only items that should end up on a "manual"
18
+ checklist are those the LLM genuinely cannot perform from within this session (e.g. they depend on production secrets it
19
+ has no way to obtain, or on coordination with humans in external systems). When the LLM **can** perform a step but needs
20
+ information from the user — a credential, a config value with no sensible default, a choice between alternatives,
21
+ confirmation about overwriting a locally-customized file — it must **ask the user inline** rather than punt the task
22
+ to the manual list.
23
+
24
+ The user expects: confirm the plan → upgrade is fully done by the time the skill finishes. Failures must be reported
25
+ with concrete next-step options (retry, fix, roll back, leave-as-is) — never silently swallowed.
26
+
27
+ ## Workflow at a glance
28
+
29
+ ```
30
+ 1. Parse arguments → resolve FROM/TO refs
31
+ 2. Validate refs → fail fast on bogus versions
32
+ 3. Preflight safety → branch + uncommitted-changes check
33
+ 4. Install TO into project → `yarn add fa-mcp-sdk@<TO>` (first mutation)
34
+ 5. Analyze diff → categorize every change as Auto / Needs-Input / Manual
35
+ 6. Build execution plan
36
+ 7. PRESENT PLAN + CONFIRM ← blocking gate; nothing else mutates until user says go
37
+ 8. Execute Auto items, ask user inline for Needs-Input items as we reach them
38
+ 9. Verify (build, lint, typecheck, tests, clean startup)
39
+ 10. Report (chat + claudedocs/upgrade-sdk-<FROM>-to-<TO>.md)
40
+ ```
41
+
42
+ ## Step 1: Argument parsing
43
+
44
+ Parse `$ARGUMENTS` to extract a target version and an optional language hint.
45
+
46
+ ### Language detection
47
+
48
+ Look anywhere in the arguments for a natural-language phrase indicating the desired output language:
49
+ - "на русском", "по-русски", "in Russian", "ru" → Russian
50
+ - "in English", "en" → English
51
+ - Any similar phrase or ISO 639-1 code.
52
+
53
+ Strip the language hint from the arguments before parsing versions. **Default: English** if no hint is found.
54
+
55
+ The detected language controls ALL human-readable text in the plan and the report (headings, prose, recommendations).
56
+ Technical content (file paths, YAML keys, code snippets, shell commands) stays as-is regardless of language.
57
+
58
+ ### Version/commit references
59
+
60
+ After stripping the language hint, the remaining arguments are version or commit references.
61
+
62
+ An argument is a **commit hash** if it contains 7+ hex characters and does not match a semver pattern. Otherwise it is
63
+ a **version** (with or without `v` prefix — `0.4.30` and `v0.4.30` are equivalent).
64
+
65
+ #### Scope of references: PROJECT (default) vs SDK
66
+
67
+ **By default, versions and commit hashes refer to THIS project** (the repository where the skill is invoked), NOT to
68
+ fa-mcp-sdk. A reference is SDK-scoped ONLY if the user's phrasing explicitly says so. Trigger phrases (case-insensitive,
69
+ English or Russian):
70
+ - "sdk", "fa-mcp-sdk", "of sdk", "sdk commit", "sdk version"
71
+ - "sdk", "fa-mcp-sdk", "версия sdk", "комит sdk", "коммит sdk", "хеш sdk"
72
+
73
+ Examples:
74
+ - `/upgrade-sdk 1.2.3 1.2.7` → project versions (look up the SDK version pinned in each)
75
+ - `/upgrade-sdk от версии 0.2.3 SDK до 0.4.5 SDK` → SDK versions directly
76
+ - `/upgrade-sdk от комита sdk abc1234 до комита sdk def5678` → SDK commits directly
77
+ - `/upgrade-sdk abc1234 def5678` → project commits (look up the SDK version pinned in each)
78
+
79
+ #### Resolving PROJECT references to SDK versions
80
+
81
+ When a reference is PROJECT-scoped (the default), resolve it to an SDK version/commit before computing the diff:
82
+
83
+ 1. **Project commit hash** — run `git show <hash>:package.json` and extract `fa-mcp-sdk` from `dependencies`.
84
+ 2. **Project version** (e.g. `1.2.3`) — find the project git tag (`v1.2.3` or `1.2.3`), then `git show <tag>:package.json`.
85
+ 3. If the dependency value is semver (`^0.4.30`, `~0.4.30`, `0.4.30`), strip range operators → exact SDK version.
86
+ 4. If the dependency value is a git URL with a commit hash (e.g. `github:Bazilio-san/fa-mcp-sdk#abc1234`), extract the
87
+ commit hash as the SDK ref.
88
+ 5. If the project tag/commit cannot be found, report and stop.
89
+
90
+ Show the resolution result before proceeding:
91
+ ```
92
+ Resolved project references to SDK:
93
+ FROM: project <ref> → SDK <version-or-commit>
94
+ TO: project <ref> → SDK <version-or-commit>
95
+ ```
96
+
97
+ #### Argument count
98
+
99
+ **Two arguments** — explicit FROM and TO (resolved per scope rules above).
100
+
101
+ **One argument** — it is treated as **FROM**; TO defaults to the **latest published fa-mcp-sdk** (fetched via
102
+ `yarn info fa-mcp-sdk version` or `npm view fa-mcp-sdk version`). Goal: upgrade to the newest existing release.
103
+
104
+ **Alternative TO=HEAD mode.** If the user explicitly says "to HEAD", "до HEAD", "до последнего коммита SDK",
105
+ "to latest commit", "до master", or supplies the literal `HEAD`/`master` as the second argument, TO becomes the
106
+ **tip of `master` on `Bazilio-san/fa-mcp-sdk`** (resolved via
107
+ `https://api.github.com/repos/Bazilio-san/fa-mcp-sdk/commits/master`) instead of the latest **published** version.
108
+ In this mode `yarn add` must use the git-URL form with the resolved commit hash (see Step 4).
109
+
110
+ **No arguments** — FROM is the currently installed SDK version (from the project's current `package.json`); TO is the
111
+ latest published SDK version.
112
+
113
+ ## Step 2: Validate refs (fail fast)
114
+
115
+ Read the project's `package.json` for the default FROM, fetch the latest published version for the default TO, then
116
+ apply argument-parsing rules to determine FROM and TO. Before any analysis or mutation, **validate both SDK refs
117
+ actually exist** — fail fast with a clear message rather than letting a later GitHub API call return 404. For each ref:
118
+
119
+ - If it's a **version** (`0.4.30` / `v0.4.30`) — probe
120
+ `https://api.github.com/repos/Bazilio-san/fa-mcp-sdk/git/refs/tags/v<version>` (also try without `v`).
121
+ Fall back to `yarn info fa-mcp-sdk@<version> version` — if that also fails, report
122
+ `Cannot resolve SDK version <X>: not found on GitHub or npm` and stop.
123
+ - If it's a **commit hash** — probe `https://api.github.com/repos/Bazilio-san/fa-mcp-sdk/commits/<hash>`.
124
+ On 404, report `Cannot resolve SDK commit <hash>: not found in repo` and stop.
125
+ - If GitHub API is rate-limited, fall back to `git ls-remote https://github.com/Bazilio-san/fa-mcp-sdk.git` for
126
+ tag/branch existence, and skip commit-hash validation with a warning.
127
+
128
+ If FROM == TO, inform the user (e.g. "Both project commits pin the same SDK version X.Y.Z — nothing to do") and stop.
129
+
130
+ Display:
131
+ ```
132
+ From: <project or SDK ref> → SDK <version-or-commit> ✓ validated
133
+ To: <project or SDK ref> → SDK <version-or-commit> ✓ validated
134
+ ```
135
+
136
+ ## Step 3: Preflight safety
137
+
138
+ This is the last point before mutating the project. Run these checks and **ask the user inline** when relevant:
139
+
140
+ 1. **Branch check.** Run `git rev-parse --abbrev-ref HEAD`. If the user is on `main`/`master`/`prod`/`production`, ask:
141
+ "You're on `<branch>`. I recommend creating `upgrade/sdk-<TO>` before mutating anything. Create it? (yes/no)"
142
+ On yes, run `git checkout -b upgrade/sdk-<TO>`. On no, proceed but note it in the report so rollback expectations
143
+ are clear.
144
+ 2. **Uncommitted changes.** Run `git status --short`. If non-empty, ask:
145
+ "I see N uncommitted changes. To stay safe I can: (1) stash them, (2) require you to commit first, (3) proceed
146
+ anyway (rollback will affect your in-flight work). Pick one." Apply the user's choice.
147
+ 3. **Capture rollback info.** Record:
148
+ - current commit hash: `git rev-parse HEAD`
149
+ - prior installed SDK version: from the current `package.json`
150
+
151
+ These go into the final report's rollback section regardless of outcome.
152
+
153
+ ## Step 4: Install the target SDK version
154
+
155
+ This is the first mutating action. From here on, we're committed to either finishing the upgrade or rolling back.
156
+
157
+ If TO is a published version:
158
+ ```bash
159
+ yarn add fa-mcp-sdk@<TO-version>
160
+ ```
161
+
162
+ If TO is a commit hash:
163
+ ```bash
164
+ yarn add fa-mcp-sdk@https://github.com/Bazilio-san/fa-mcp-sdk#<TO-commit>
165
+ ```
166
+
167
+ Wait for completion. If `yarn add` fails, show the error verbatim and ask the user how to proceed (retry, switch to a
168
+ different TO ref, or abort).
169
+
170
+ Then run:
171
+ ```bash
172
+ node ./node_modules/fa-mcp-sdk/scripts/update-sdk.js
173
+ ```
174
+ This copies the latest `FA-MCP-SDK-DOC/` and `.claude/` content from the SDK into the project. Pinned folders (any
175
+ folder under the project's `.claude/` containing a direct file named `pin`) are preserved by the script as-is.
176
+
177
+ ## Step 5: Analyze the diff
178
+
179
+ Use `https://github.com/Bazilio-san/fa-mcp-sdk` (public repo) to inspect what changed between FROM and TO. **Read
180
+ actual content — do not guess.**
181
+
182
+ ### 5.1 Commit log
183
+
184
+ Fetch:
185
+ ```
186
+ https://api.github.com/repos/Bazilio-san/fa-mcp-sdk/compare/<FROM-ref>...<TO-ref>
187
+ ```
188
+ The `commits[]` array carries the **why** of each change (motivation, fixed issue) that file diffs alone don't show.
189
+ Extract `commit.message` (subject + body) for every commit. Use these to:
190
+ - Spot intent — flag any conventional-commit `BREAKING CHANGE:` markers prominently.
191
+ - Group related file changes under a single narrative.
192
+ - Note "rationale unclear — check commit `<hash>` directly" for non-obvious diffs with terse messages.
193
+
194
+ If the compare endpoint is rate-limited, fall back to paged commits:
195
+ `https://api.github.com/repos/Bazilio-san/fa-mcp-sdk/commits?sha=<TO>&since=<FROM-date>&until=<TO-date>`.
196
+
197
+ Include a "Changelog" list (short hash + first line) in the report.
198
+
199
+ ### 5.2 Config files
200
+
201
+ These SDK config files may have changed and require corresponding updates in the project:
202
+
203
+ - `config/default.yaml` — main configuration defaults
204
+ - `config/_local.yaml` — template for the project's `config/_local.yaml` (CLI derives `config/local.yaml` from this
205
+ with `{{param}}` substitutions)
206
+ - `config/custom-environment-variables.yaml` — env var mappings
207
+ - `config/development.yaml`, `config/production.yaml` — env overrides
208
+ - `config/local.yaml` (SDK's own) — reference only, not shipped
209
+
210
+ For each, compare the SDK's version (`node_modules/fa-mcp-sdk/config/<file>`) with the project's version
211
+ (`config/<file>`). Identify: new keys, removed keys, changed defaults, new sections.
212
+
213
+ **Correlate `default.yaml` ⇄ `_local.yaml`.** When `default.yaml` has structural changes (new keys, restructured
214
+ sections, changed defaults), also check `_local.yaml` for analogous changes — `_local.yaml` mirrors `default.yaml`'s
215
+ structure with override values. If `default.yaml` changed but `_local.yaml` did NOT, flag this: the project's
216
+ `config/_local.yaml` may need manual updates to stay consistent.
217
+
218
+ **Config file mapping (SDK source → project destination):**
219
+
220
+ | SDK source (in `config/`) | Project destination | Action |
221
+ |--------------------------------------------|----------------------------------------------|--------|
222
+ | `config/default.yaml` | `config/default.yaml` | Add new keys; do NOT remove existing keys the project may have customized |
223
+ | `config/_local.yaml` | `config/_local.yaml` | Update to match SDK — this is the template `local.yaml` is derived from |
224
+ | `config/_local.yaml` (via CLI) | `config/local.yaml` | Derived by CLI from `_local.yaml` with `{{param}}` substitutions |
225
+ | `config/custom-environment-variables.yaml` | `config/custom-environment-variables.yaml` | Add new env var mappings |
226
+ | `config/local.yaml` (SDK's own) | *(not shipped — reference only)* | Use as reference for what the SDK itself overrides locally |
227
+
228
+ ### 5.3 cli-template files
229
+
230
+ After `yarn add fa-mcp-sdk@<TO>`, the SDK ships its template at `node_modules/fa-mcp-sdk/cli-template/`. This is the
231
+ canonical source for any template files in the project.
232
+
233
+ | Template (source of truth) | Project (destination) | Notes |
234
+ |------------------------------------------------------------------|-------------------------------|-------|
235
+ | `node_modules/fa-mcp-sdk/cli-template/package.json` | `package.json` | **Merge carefully** — see rule below |
236
+ | `node_modules/fa-mcp-sdk/cli-template/tsconfig.json` | `tsconfig.json` | Overwrite unless customized |
237
+ | `node_modules/fa-mcp-sdk/cli-template/.oxlintrc.json` | `.oxlintrc.json` | Overwrite unless customized |
238
+ | `node_modules/fa-mcp-sdk/cli-template/.oxfmtrc.json` | `.oxfmtrc.json` | Overwrite unless customized |
239
+ | `node_modules/fa-mcp-sdk/cli-template/CLAUDE.md` | `CLAUDE.md` | Merge — project may add custom sections |
240
+ | `node_modules/fa-mcp-sdk/cli-template/jest.config.js` | `jest.config.js` | Overwrite unless customized |
241
+ | `node_modules/fa-mcp-sdk/cli-template/deploy/` | `deploy/` | Merge per file |
242
+ | `node_modules/fa-mcp-sdk/cli-template/.claude/skills/<skill>/` | `.claude/skills/<skill>/` | Overwrite unless locally customized |
243
+ | `node_modules/fa-mcp-sdk/cli-template/r/<name>.xml` | `.run/<name>.run.xml` | **Renamed** — see rule below |
244
+ | `node_modules/fa-mcp-sdk/cli-template/gitignore` | `.gitignore` | Source has no leading dot |
245
+ | `node_modules/fa-mcp-sdk/cli-template/FA-MCP-SDK-DOC/` | `FA-MCP-SDK-DOC/` | Auto-updated by `update-sdk.js` in Step 4 |
246
+
247
+ #### Rule: `package.json` — ADD ONLY new dependencies
248
+
249
+ The project's `package.json` has evolved since generation (project-specific name, version, scripts, team-added deps).
250
+ When the SDK's template `package.json` changes:
251
+
252
+ 1. Diff `node_modules/fa-mcp-sdk/cli-template/package.json` (TO) against the same file at the FROM version.
253
+ 2. Identify ONLY dependencies/devDependencies that were **added** (not version-changed, not removed).
254
+ 3. Apply additions to the project's `package.json` under the matching section.
255
+ 4. Do NOT touch `name`, `version`, `scripts`, `engines`, `type`, or any other field.
256
+ 5. If a dep was **removed** from the template, mention it in the report as informational only — do not delete it from
257
+ the project (it may still be in use).
258
+
259
+ #### Rule: `r/` → `.run/` with filename transformation
260
+
261
+ The project has no `r/` directory — it was renamed to `.run/` at generation, and each `<name>.xml` was renamed to
262
+ `<name>.run.xml`. For new or changed files in `cli-template/r/`:
263
+ - Source: `node_modules/fa-mcp-sdk/cli-template/r/<name>.xml`
264
+ - Destination: `.run/<name>.run.xml`
265
+ - NEW file → copy with rename.
266
+ - CHANGED file → if the project's existing `.run.xml` is untouched (matches the FROM template), overwrite. If it has
267
+ local customizations, treat as Needs-Input (ask the user: overwrite / merge / skip).
268
+ - REMOVED file → informational only; do not delete the project's `.run/<name>.run.xml`.
269
+
270
+ #### Rule: `.claude/` files — use fcp.js
271
+
272
+ `.claude/**` is denied for direct `Write`/`Edit` in the project's `settings.json`. To update any file under
273
+ `.claude/` (skills, scripts, hooks, agents, settings.json) use the project's `scripts/fcp.js` workflow described in
274
+ the `edit-claude-files` skill — write the new content to a temp file, then
275
+ `node scripts/fcp.js .claude/<path> <temp-file>` to install it atomically. This applies to every cli-template
276
+ `.claude/` entry being copied into the project.
277
+
278
+ For any other changed template file: source path under `node_modules/fa-mcp-sdk/cli-template/...`, destination in the
279
+ project, action = overwrite or merge (depending on local customization).
280
+
281
+ ### 5.4 Scripts
282
+
283
+ The CLI copies scripts from `node_modules/fa-mcp-sdk/scripts/` (NOT from `cli-template/scripts/`) into the project's
284
+ `scripts/`, then removes `copy-static.js`, `publish.js`, and `scripts/publish-README.md` (SDK-internal, not shipped).
285
+
286
+ - Canonical source: `node_modules/fa-mcp-sdk/scripts/<name>.js`
287
+ - Project destination: `scripts/<name>.js`
288
+ - Exclude: `copy-static.js`, `publish.js`, `publish-README.md`
289
+
290
+ ### 5.5 Core library exports
291
+
292
+ **Prefer the TypeScript source over compiled output.** Fetch `src/core/index.ts` (and any re-exported `_types_/`
293
+ files it references) at both FROM and TO via GitHub raw:
294
+ ```
295
+ https://raw.githubusercontent.com/Bazilio-san/fa-mcp-sdk/<FROM-ref>/src/core/index.ts
296
+ https://raw.githubusercontent.com/Bazilio-san/fa-mcp-sdk/<TO-ref>/src/core/index.ts
297
+ ```
298
+ Compare to identify: new exports, removed/renamed exports, changed type signatures, type-level changes (generics,
299
+ conditional types, union narrowing) that don't survive `.d.ts` emission cleanly.
300
+
301
+ Why source over `dist/`:
302
+ - Original JSDoc comments and inline rationale preserved in `.ts`, stripped/compressed in `dist/*.js`.
303
+ - Renames visible as renames in source diff; in `dist/` they may appear as unrelated add+remove pairs.
304
+ - `export *` chains resolve naturally in source; in `.d.ts` they may be flattened.
305
+
306
+ **Fallback** — if GitHub raw is unavailable, use `node_modules/fa-mcp-sdk/dist/core/index.js` and the matching `.d.ts`.
307
+ State explicitly in the report that analysis was made from compiled artifacts and double-check via the GitHub source
308
+ viewer for any flagged change.
309
+
310
+ ### 5.6 Project code scan
311
+
312
+ Scan the project's `src/`, `config/`, and `tests/` for:
313
+ - Imports from `fa-mcp-sdk` referencing removed/renamed exports
314
+ - Usage of deprecated APIs
315
+ - Config keys that were renamed or restructured
316
+
317
+ For each hit, capture file:line and the exact replacement plan — needed for Step 6 categorization.
318
+
319
+ ## Step 6: Categorize and build the execution plan
320
+
321
+ For every change found in Step 5, assign one of three categories:
322
+
323
+ ### Auto — LLM applies without asking
324
+ - `yarn add fa-mcp-sdk@<TO>` (already done in Step 4)
325
+ - `node ./node_modules/fa-mcp-sdk/scripts/update-sdk.js` (already done in Step 4)
326
+ - Adding a brand-new config key to `config/default.yaml` when the project doesn't override it
327
+ - Adding new env var mappings to `config/custom-environment-variables.yaml`
328
+ - Adding a missing dependency to `package.json` under `dependencies`/`devDependencies`
329
+ - Copying a new template file the project doesn't have yet (scripts, `.run/` entries, new skill folders)
330
+ - Applying a mechanical rename of a renamed SDK export across the project's `src/` when there's exactly one
331
+ unambiguous replacement
332
+ - Updating SDK-shipped skill files via the `.claude/` fcp.js protocol when the project hasn't customized them
333
+
334
+ ### Needs-Input — LLM applies, but needs user input
335
+ - A locally-customized file conflicts with the new template — ask: overwrite / merge / skip
336
+ - A new config key has no sensible default — ask for the value
337
+ - A breaking change has multiple plausible API replacements — ask which one fits the project's intent
338
+ - A `BREAKING CHANGE:` marker that the LLM can apply mechanically but wants explicit confirmation
339
+ - The project's `config/local.yaml` has stale overrides for keys that changed structure — ask whether to drop them,
340
+ port to the new structure, or leave them and warn
341
+
342
+ ### Manual — LLM cannot perform
343
+ Reserve this only for things the LLM truly cannot do in this session. Examples:
344
+ - Rotating production secrets in a secrets manager outside this repo
345
+ - Deploying to staging/production environments
346
+ - Communicating with third-party services or teammates
347
+
348
+ **If a step could be automated in principle but requires human judgment, prefer Needs-Input over Manual.**
349
+
350
+ Build the plan as three lists with item counts and concrete actions.
351
+
352
+ ## Step 7: Present the plan and ASK FOR CONFIRMATION
353
+
354
+ Render the plan in the conversation in the detected language:
355
+
356
+ ```markdown
357
+ ## Upgrade plan: fa-mcp-sdk v<FROM> → v<TO>
358
+
359
+ ### 🤖 I will do automatically (N items)
360
+ 1. ✅ yarn add fa-mcp-sdk@<TO> [already done]
361
+ 2. ✅ node ./node_modules/fa-mcp-sdk/scripts/update-sdk.js [already done]
362
+ 3. Add new key `webServer.foo` (default `bar`) to `config/default.yaml`
363
+ 4. Copy new template file `.run/new-task.run.xml` (renamed from `r/new-task.xml`)
364
+ 5. Add dep `some-pkg@^1.2.3` to package.json `dependencies`
365
+ 6. Apply rename `oldFn` → `newFn` in src/foo.ts:42, src/bar.ts:17, src/baz.ts:55
366
+ 7. Run verification: `oxlint --fix . && oxfmt . && rimraf dist && tsc` + project tests + clean startup
367
+
368
+ ### ❓ I need your input on (M items)
369
+ 1. `config/local.yaml` overrides `webServer.auth` which restructured in v<TO>. Options:
370
+ (a) port overrides to new structure (b) drop overrides (c) leave + warn
371
+ 2. New config key `someService.apiKey` has no default. What value should I set?
372
+ 3. Project's `.claude/skills/upgrade-sdk/SKILL.md` is locally customized. Overwrite with new template,
373
+ merge non-conflicting parts only, or skip?
374
+
375
+ ### 👋 You'll need to do manually (K items)
376
+ - [empty if everything is in Auto or Needs-Input]
377
+
378
+ ### Rollback info
379
+ - Pre-upgrade commit: <hash>
380
+ - Prior SDK version: v<FROM>
381
+ - Branch: <branch>
382
+ ```
383
+
384
+ Then ask **explicitly**:
385
+
386
+ > "Confirm — apply the Auto items now and prompt you inline for the Needs-Input items as I reach them? (yes/no)"
387
+
388
+ Wait for explicit confirmation. If the user declines, stop and leave the project as it is after Step 4 (note this in
389
+ the final report). If the user confirms, proceed to Step 8.
390
+
391
+ ## Step 8: Execute
392
+
393
+ Apply each Auto item in order. For each Needs-Input item, ask the user **at the moment you reach it** (one question
394
+ at a time so the user can reason — don't batch). Apply with the answer, then move on.
395
+
396
+ Be transparent about state — after each item is applied, output a one-line acknowledgment so the user can follow
397
+ along, e.g. `✓ Added webServer.foo to config/default.yaml`.
398
+
399
+ When touching files under `.claude/`, always use the project's `scripts/fcp.js` workflow (see Step 5.3 → "Rule:
400
+ `.claude/` files — use fcp.js" and the project's `edit-claude-files` skill).
401
+
402
+ Maintain an in-memory execution log so the final report can list exactly what was done and what required input.
403
+
404
+ ## Step 9: Verify
405
+
406
+ After all items are applied, run the verification chain in this exact order. Record pass/fail for each step.
407
+
408
+ ### 9.1 Lint + format + clean build (fixed chain)
409
+
410
+ Run this single command chain — same shape regardless of project:
411
+
412
+ ```bash
413
+ npx oxlint --fix . && npx oxfmt . && npx rimraf dist && npx tsc
414
+ ```
415
+
416
+ (Use `npx` to invoke the tools directly so the chain doesn't depend on yarn script wrappers, which may differ between
417
+ projects. If the project clearly pins these tools as direct `node_modules/.bin/` binaries, those work too.)
418
+
419
+ - `oxlint --fix .` — auto-fix lint issues across the whole project
420
+ - `oxfmt .` — format the whole project
421
+ - `rimraf dist` — wipe stale build output
422
+ - `tsc` — typecheck + compile
423
+
424
+ If any step fails, stop the chain and trigger the failure-handling flow below.
425
+
426
+ ### 9.2 Project tests (whatever is wired in `package.json`)
427
+
428
+ **Do not hard-code a test command.** Read the project's `package.json` `scripts` section and run whatever test scripts
429
+ the project actually defines. Common patterns to look for, in order of preference:
430
+
431
+ 1. `test:mcp`, `test:mcp-http`, `test:mcp-sse`, `test:mcp-streamable` — MCP transport tests (run all that exist)
432
+ 2. `test` — top-level test runner (usually `jest`)
433
+ 3. Any other script whose name starts with `test:` or contains `test`
434
+
435
+ Run all relevant test scripts; the project may need just one of them or several. Record pass/fail per script.
436
+
437
+ If no test scripts are defined, note it in the report ("project has no test scripts — verification skipped tests").
438
+
439
+ ### 9.3 Clean startup
440
+
441
+ Briefly start the server, confirm it boots without errors, then stop it:
442
+
443
+ ```bash
444
+ yarn start & # or `npm start` — match the project
445
+ # wait ~3-5s for startup logs
446
+ node scripts/kill-port.js <port> # port from config/default.yaml → webServer.port
447
+ ```
448
+
449
+ A "clean startup" means: no exceptions in logs, server reports it's listening on the configured port. If startup
450
+ fails, treat it as a verification failure.
451
+
452
+ ### On verification failure
453
+
454
+ Do NOT silently proceed and do NOT silently roll back. Present the failing step, the error output, and the diff of
455
+ the likely-causing file(s), then ask the user to choose:
456
+
457
+ > "Verification failed at <step>. Options:
458
+ > - **fix**: I diagnose the root cause and fix it (may need more input from you)
459
+ > - **retry**: just rerun the verification step (useful for flaky tests)
460
+ > - **rollback**: revert to the pre-upgrade state (commit `<hash>`, SDK v`<FROM>`) and stop
461
+ > - **leave-as-is**: keep current state, surface the failure in the final report, and stop
462
+ > Pick one."
463
+
464
+ Apply the user's choice:
465
+ - **fix** → diagnose, apply a fix (asking inline for any info needed), re-run verification. Loop if it fails again.
466
+ - **retry** → rerun the failing step once. If it fails again, present the same four options.
467
+ - **rollback** → run `yarn add fa-mcp-sdk@<FROM>` (or git-URL form), `git checkout <pre-upgrade-hash> -- .`,
468
+ `node ./node_modules/fa-mcp-sdk/scripts/update-sdk.js` if needed. If the user stashed changes in Step 3, restore
469
+ them with `git stash pop`. Report what was rolled back.
470
+ - **leave-as-is** → no further changes. Final report will clearly mark the failure and what remains unverified.
471
+
472
+ ## Step 10: Report
473
+
474
+ Produce a final report in **two places**:
475
+ 1. **In the chat**, immediately at the end of the skill run.
476
+ 2. **In a file** at `claudedocs/upgrade-sdk-<FROM>-to-<TO>.md` (overwrite if it exists from a previous run).
477
+
478
+ Both copies use this structure (in the detected language):
479
+
480
+ ```markdown
481
+ # Upgrade report: fa-mcp-sdk v<FROM> → v<TO>
482
+
483
+ Generated: <ISO timestamp>
484
+ Branch: <branch>
485
+ Pre-upgrade commit: <hash>
486
+
487
+ ## Outcome
488
+
489
+ <one of: ✅ completed | ⚠️ completed with issues | ❌ rolled back | ⏸ stopped at user request>
490
+
491
+ ## Changelog (commits between FROM and TO)
492
+
493
+ - `<short-hash>` <first line>
494
+ - ...
495
+
496
+ ## ✓ Done automatically
497
+
498
+ - Item 1
499
+ - Item 2
500
+ - ...
501
+
502
+ ## ✓ Done with your input
503
+
504
+ - `config/local.yaml`: chose (a) port to new structure — applied N keys
505
+ - `someService.apiKey`: set to `<value-you-provided>`
506
+ - `oldFn` → `newFn` rename: applied to src/foo.ts:42, src/bar.ts:17, src/baz.ts:55
507
+ - ...
508
+
509
+ ## 👋 Still on your plate
510
+
511
+ - [empty if nothing manual remains]
512
+
513
+ ## Verification
514
+
515
+ - `oxlint --fix .`: ✅ / ❌ (<error excerpt>)
516
+ - `oxfmt .`: ✅ / ❌
517
+ - `rimraf dist`: ✅ / ❌
518
+ - `tsc`: ✅ / ❌ (<error excerpt>)
519
+ - tests (<list scripts run>): ✅ / ❌ (<n>/<m> passed)
520
+ - clean startup: ✅ / ❌
521
+
522
+ ## Rollback info
523
+
524
+ - Pre-upgrade commit: `<hash>`
525
+ - Prior SDK version: `v<FROM>`
526
+ - To roll back manually:
527
+ ```bash
528
+ yarn add fa-mcp-sdk@<FROM>
529
+ git checkout <hash> -- .
530
+ node ./node_modules/fa-mcp-sdk/scripts/update-sdk.js
531
+ ```
532
+
533
+ ## Notes
534
+
535
+ <anything noteworthy: rate limits hit, fallbacks used, files with rationale-unclear diffs flagged for review, etc.>
536
+ ```
537
+
538
+ Make sure `claudedocs/` exists (`mkdir -p claudedocs`) before writing.
539
+
540
+ ## Important rules
541
+
542
+ - Always read actual files; never guess what changed.
543
+ - Treat user customizations as inviolable unless the user explicitly says "overwrite" in response to a Needs-Input
544
+ prompt.
545
+ - Never modify `package.json` other than to ADD new deps; do not change `name`, `version`, `scripts`, `engines`,
546
+ `type`, or any other field.
547
+ - Don't skip verification. If it fails, surface it via the 4-option prompt — don't smuggle failures past the user.
548
+ - All `.claude/` writes go through `scripts/fcp.js` (per the `edit-claude-files` protocol).
549
+ - Write all human-readable text in the detected language (default: English). Keep paths, YAML keys, and shell
550
+ commands in English regardless.
551
+ - Correlate config files: when `default.yaml` changes, always check `_local.yaml` for analogous changes and flag
552
+ stale `local.yaml` overrides explicitly.
553
+ - If GitHub API is unavailable or rate-limited, fall back to comparing files directly from `node_modules/fa-mcp-sdk/`
554
+ against project files, and note the fallback in the report.
@@ -106,7 +106,7 @@ Priority: environment variables > local.yaml > {NODE_ENV}.yaml > default.yaml. A
106
106
  When multiple auth methods configured, detection from `Authorization` header:
107
107
  1. `permanentServerTokens` — static tokens (O(1) lookup)
108
108
  2. `basic` — base64 username:password
109
- 3. `jwtToken` — encrypted JWT (optional IP restriction via `isCheckIP` + `ip` field in payload)
109
+ 3. `jwtToken` — standard signed JWT, HS256 (optional IP restriction via `isCheckIP` + `ip` field in payload; legacy `<expire>.<hex>` tokens still accepted for backward compatibility)
110
110
  4. `custom` — user-defined validator (fallback)
111
111
 
112
112
  ## Framework Documentation
@@ -155,21 +155,25 @@ webServer:
155
155
  permanentServerTokens: [ ] # Add your server tokens here: ['token1', 'token2']
156
156
 
157
157
  # ========================================================================
158
- # JWT TOKEN WITH SYMMETRIC ENCRYPTION
159
- # Custom JWT tokens with AES-256 encryption
160
- # CPU cost: Medium - decryption + JSON parsing
158
+ # JWT TOKEN standard signed JWT (HS256)
159
+ # Tokens issued by this SDK are standard 3-segment JWTs `header.payload.signature`.
160
+ # The verifier also temporarily accepts pre-migration legacy tokens
161
+ # (`<expire_ms>.<hex>` AES-256-CTR format) for backward compatibility.
162
+ # CPU cost: Medium - signature verification + JSON parsing
161
163
  #
162
164
  # To enable this authentication, you need to set auth.enabled = true and set
163
- # encryptKey to at least 20 characters
165
+ # encryptKey to at least 8 characters (used as the HS256 signing secret).
164
166
  # ========================================================================
165
167
  jwtToken:
166
- # Symmetric encryption key to generate a token for this MCP (minimum 8 chars)
168
+ # HS256 signing secret used to sign/verify tokens for this MCP (minimum 8 chars)
167
169
  encryptKey: '***'
168
170
  # If webServer.auth.enabled and the parameter true, the service name and the service specified in the token will be checked
169
171
  checkMCPName: true
170
172
  # If true and JWT token contains non-empty 'ip' field,
171
173
  # the client IP will be checked against the allowed list in the token
172
174
  isCheckIP: false
175
+ # Optional JWT `iss` claim. When non-empty, the generator stamps it and the verifier requires it.
176
+ issuer: ''
173
177
 
174
178
  # ========================================================================
175
179
  # Basic Authentication - Base64 encoded username:password
@@ -74,8 +74,8 @@ For `ntlm` — uses AD configuration from `ad.domains` section.
74
74
 
75
75
  When `jwtToken` is used to authenticate into the admin panel (`/admin`), the decoded
76
76
  payload **must** contain `allow: 'gen-token'`. Any JWT without this claim is rejected
77
- with `401` even if it decrypts and is not expired. This prevents short-lived JWTs
78
- issued for other purposes (e.g. the Agent Tester page auto-fills a JWT into its
77
+ with `401` even if its signature verifies and it is not expired. This prevents short-lived
78
+ JWTs issued for other purposes (e.g. the Agent Tester page auto-fills a JWT into its
79
79
  `Authorization` header — TTL is configurable via `agentTester.tokenTTLSec`, default
80
80
  30 min) from being replayed against `/admin` to mint arbitrary long-lived tokens.
81
81
 
@@ -311,7 +311,7 @@ node scripts/generate-jwt.js -u <username> -ttl <duration> [-s <service>] [-p <p
311
311
  | `-s`, `--service-name` | `JWT_PAYLOAD_SERVICE_NAME` | Service name (optional) |
312
312
  | `-p`, `--params` | `JWT_PAYLOAD_PARAMS` | Extra payload `key=value;key=value` (optional) |
313
313
 
314
- The `encryptKey` is read from config `webServer.auth.jwtToken.encryptKey` (via `config/local.yaml` or ENV `WS_TOKEN_ENCRYPT_KEY`).
314
+ The HS256 signing secret is read from config `webServer.auth.jwtToken.encryptKey` (via `config/local.yaml` or ENV `WS_TOKEN_ENCRYPT_KEY`). Generated tokens are standard 3-segment JWTs.
315
315
 
316
316
  **Examples:**
317
317
 
@@ -388,7 +388,7 @@ curl -X POST http://localhost:3000/gen-jwt \
388
388
  ```json
389
389
  {
390
390
  "success": true,
391
- "token": "1718000000000.a1b2c3...",
391
+ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0dXNlciJ9.signature",
392
392
  "user": "testuser",
393
393
  "expire": "2025-07-10T12:00:00.000Z",
394
394
  "ttlSeconds": 2592000
@@ -130,7 +130,7 @@ When `useAuth` is `true`, a successful browser login creates a server-side sessi
130
130
 
131
131
  When the MCP server requires authentication (`webServer.auth.enabled: true`) and the chat UI is configured to send the `Authorization` header, the page does **not** ask the user to type a token — it issues one for itself by calling `GET /api/auth-token` on load. The endpoint returns a header value derived from the configured method, in priority order:
132
132
 
133
- 1. **`jwtToken`** — `Bearer <encrypted JWT>` issued by the server with `sub: 'agentTester'`, `service: <appConfig.name>`, and TTL = `agentTester.tokenTTLSec` (default 1800 sec / 30 min). The response also includes `ttlSec` so the client can plan refresh.
133
+ 1. **`jwtToken`** — `Bearer <standard signed JWT>` issued by the server with `sub: 'agentTester'`, `aud: <appConfig.name>`, and TTL = `agentTester.tokenTTLSec` (default 1800 sec / 30 min). The response also includes `ttlSec` so the client can plan refresh.
134
134
  2. **`basic`** — `Basic <base64(user:password)>` from `webServer.auth.basic`.
135
135
  3. **`permanentServerTokens`** — `Bearer <first configured token>`.
136
136
 
@@ -54,7 +54,7 @@
54
54
  "dependencies": {
55
55
  "@modelcontextprotocol/sdk": "^1.29.0",
56
56
  "dotenv": "^17.4.1",
57
- "fa-mcp-sdk": "^0.4.93"
57
+ "fa-mcp-sdk": "^0.4.96"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/express": "^5.0.6",