fa-mcp-sdk 0.4.70 → 0.4.71
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/cli-template/.claude/skills/upgrade-guide/SKILL.md +10 -5
- package/cli-template/package.json +2 -2
- package/cli-template/r/{update-doc.js.xml → update-sdk.js.xml} +5 -5
- package/config/_local.yaml +20 -18
- package/config/local.yaml +3 -4
- package/package.json +1 -1
- package/scripts/update-sdk.js +111 -0
- package/scripts/update-doc.js +0 -36
|
@@ -110,10 +110,15 @@ Wait for completion. If it fails, report the error and stop.
|
|
|
110
110
|
|
|
111
111
|
Run:
|
|
112
112
|
```bash
|
|
113
|
-
node ./node_modules/fa-mcp-sdk/scripts/update-
|
|
113
|
+
node ./node_modules/fa-mcp-sdk/scripts/update-sdk.js
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
This copies the latest `FA-MCP-SDK-DOC/` from the SDK into the project.
|
|
116
|
+
This copies the latest `FA-MCP-SDK-DOC/` and `.claude/` from the SDK into the project.
|
|
117
|
+
|
|
118
|
+
**Pinned folders.** Any folder under the project's `.claude/` that contains a direct file named
|
|
119
|
+
`pin` is preserved as-is — the script neither deletes it nor overwrites it with template content.
|
|
120
|
+
Drop a `pin` file into `.claude/skills/<your-skill>/` (or any other `.claude/` subdirectory) to
|
|
121
|
+
protect local customizations from being reset on upgrade.
|
|
117
122
|
|
|
118
123
|
## Step 4: Analyze Changes in SDK Between Versions
|
|
119
124
|
|
|
@@ -187,7 +192,7 @@ Map of template file → project file (the CLI `bin/fa-mcp.js` applies these tra
|
|
|
187
192
|
| `node_modules/fa-mcp-sdk/cli-template/.claude/skills/<skill>/` | `.claude/skills/<skill>/` | overwrite unless locally customized |
|
|
188
193
|
| `node_modules/fa-mcp-sdk/cli-template/r/<name>.xml` | `.run/<name>.run.xml` | **Renamed** — see rule below |
|
|
189
194
|
| `node_modules/fa-mcp-sdk/cli-template/gitignore` | `.gitignore` | source has no leading dot |
|
|
190
|
-
| `node_modules/fa-mcp-sdk/cli-template/FA-MCP-SDK-DOC/` | `FA-MCP-SDK-DOC/` | auto-updated by `update-
|
|
195
|
+
| `node_modules/fa-mcp-sdk/cli-template/FA-MCP-SDK-DOC/` | `FA-MCP-SDK-DOC/` | auto-updated by `update-sdk.js` |
|
|
191
196
|
|
|
192
197
|
#### Rule: package.json — ADD ONLY new dependencies, do NOT touch anything else
|
|
193
198
|
|
|
@@ -286,7 +291,7 @@ Generated: <timestamp>
|
|
|
286
291
|
### New Configuration Keys
|
|
287
292
|
|
|
288
293
|
<For each new key, provide:>
|
|
289
|
-
- Key path (e.g., `webServer.
|
|
294
|
+
- Key path (e.g., `webServer.auth.enabled`)
|
|
290
295
|
- Default value
|
|
291
296
|
- Description
|
|
292
297
|
- Whether it needs to be added to the project's config
|
|
@@ -403,7 +408,7 @@ changes specifically affect THIS project. Add a section to the guide:
|
|
|
403
408
|
- When comparing YAML configs, preserve comments and structure.
|
|
404
409
|
- **Correlate config file changes**: when `config/default.yaml` changes, ALWAYS also check `config/_local.yaml` in the SDK. Report whether `_local.yaml` has analogous changes or needs manual updates. Also advise checking the project's `config/local.yaml` for stale overrides that may conflict with the new defaults.
|
|
405
410
|
- **Do not forget `config/local.yaml` in the project**: the project's `config/local.yaml` overrides `config/default.yaml`. When new keys are added or sections restructured in `default.yaml`, explicitly instruct the user to verify that their `config/local.yaml` doesn't have stale overrides that conflict with the new structure, and to add any new keys there too if they want non-default values.
|
|
406
|
-
- Do not modify project files other than `package.json` (via yarn add) and `FA-MCP-SDK-DOC/` (via update-
|
|
411
|
+
- Do not modify project files other than `package.json` (via yarn add) and `FA-MCP-SDK-DOC/` (via update-sdk.js) unless the user explicitly asks.
|
|
407
412
|
- The migration guide must contain ACTIONABLE instructions with exact code/config snippets — not vague recommendations.
|
|
408
413
|
- If GitHub API is unavailable or rate-limited, fall back to comparing files directly from `node_modules/fa-mcp-sdk/` against project files.
|
|
409
414
|
- Write the guide in the language detected from the user's arguments (default: **English**). Translate all headings, prose, and descriptions. Keep file paths, YAML keys, code blocks, and shell commands in English.
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"generate-token": "node node_modules/fa-mcp-sdk/dist/core/auth/token-generator/server.js",
|
|
23
23
|
"dead:exports": "ts-prune",
|
|
24
24
|
"dead:files": "knip",
|
|
25
|
-
"update-sdk-docs": "node ../scripts/update-
|
|
25
|
+
"update-sdk-docs": "node ../scripts/update-sdk.js",
|
|
26
26
|
"postinstall": "node ../scripts/npm/patch_node_modules.js",
|
|
27
27
|
"check-llm": "node node_modules/fa-mcp-sdk/dist/core/agent-tester/check-llm.js",
|
|
28
28
|
"consul:unreg": "node node_modules/fa-mcp-sdk/dist/core/consul/deregister.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
52
52
|
"dotenv": "^17.4.1",
|
|
53
|
-
"fa-mcp-sdk": "^0.4.
|
|
53
|
+
"fa-mcp-sdk": "^0.4.71"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/express": "^5.0.6",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<component name="ProjectRunConfigurationManager">
|
|
2
|
-
<configuration default="false" name="update-
|
|
3
|
-
<method v="2" />
|
|
4
|
-
</configuration>
|
|
5
|
-
</component>
|
|
1
|
+
<component name="ProjectRunConfigurationManager">
|
|
2
|
+
<configuration default="false" name="update-sdk.js" type="NodeJSConfigurationType" nameIsGenerated="true" path-to-js-file="scripts/update-sdk.js" working-dir="$PROJECT_DIR$">
|
|
3
|
+
<method v="2" />
|
|
4
|
+
</configuration>
|
|
5
|
+
</component>
|
package/config/_local.yaml
CHANGED
|
@@ -24,6 +24,26 @@
|
|
|
24
24
|
# #> Override the Consul service name to look up (defaults to the alias key)
|
|
25
25
|
# consulServiceName: <consulServiceName>
|
|
26
26
|
|
|
27
|
+
#> ========================================================================
|
|
28
|
+
#> ADMIN PANEL
|
|
29
|
+
#> Token generation & validation UI served at /admin.
|
|
30
|
+
#> Supports 4 authentication methods: permanentServerTokens, basic, jwtToken, ntlm.
|
|
31
|
+
#> ========================================================================
|
|
32
|
+
adminPanel:
|
|
33
|
+
#> Enable/disable admin panel. false — /admin is not mounted at all.
|
|
34
|
+
enabled: true
|
|
35
|
+
#> Authentication type: 'permanentServerTokens' | 'basic' | 'jwtToken' | 'ntlm' | 'none'
|
|
36
|
+
#> Accepts a single type (string) or multiple types (array):
|
|
37
|
+
#> authType: 'basic'
|
|
38
|
+
#> authType: ['jwtToken', 'basic']
|
|
39
|
+
#> 'none' / null / empty array / not set → panel opens WITHOUT authentication
|
|
40
|
+
#> (convenience for local development and debugging; do NOT use in production).
|
|
41
|
+
#> For permanentServerTokens, basic, jwtToken — uses credentials from webServer.auth section.
|
|
42
|
+
#> For ntlm — uses AD configuration from ad.domains section.
|
|
43
|
+
#> When multiple types are set (e.g. ['jwtToken', 'basic']), the login page shows tabs
|
|
44
|
+
#> to choose between Token and Login (username/password) authentication.
|
|
45
|
+
authType: 'basic'
|
|
46
|
+
|
|
27
47
|
#> Active Directory / LDAP settings.
|
|
28
48
|
#> Used for authentication/authorization (e.g., NTLM in admin panel) and checking user membership in AD groups.
|
|
29
49
|
ad:
|
|
@@ -325,21 +345,3 @@ webServer:
|
|
|
325
345
|
#> Requires valid Authorization header (any method configured in webServer.auth).
|
|
326
346
|
#> ========================================================================
|
|
327
347
|
genJwtApiEnable: false
|
|
328
|
-
|
|
329
|
-
#> ========================================================================
|
|
330
|
-
#> ADMIN PANEL AUTHENTICATION
|
|
331
|
-
#> Token generation page available at /admin endpoint
|
|
332
|
-
#> Supports 4 authentication methods: permanentServerTokens, basic, jwtToken, ntlm
|
|
333
|
-
#> ========================================================================
|
|
334
|
-
adminAuth:
|
|
335
|
-
#> Enable/disable admin panel
|
|
336
|
-
enabled: true
|
|
337
|
-
#> Authentication type for admin panel: 'permanentServerTokens' | 'basic' | 'jwtToken' | 'ntlm'
|
|
338
|
-
#> Accepts a single type (string) or multiple types (array):
|
|
339
|
-
#> type: 'basic'
|
|
340
|
-
#> type: ['jwtToken', 'basic']
|
|
341
|
-
#> For permanentServerTokens, basic, jwtToken — uses credentials from webServer.auth section
|
|
342
|
-
#> For ntlm — uses AD configuration from ad.domains section (no additional credentials needed)
|
|
343
|
-
#> When multiple types are set (e.g. ['jwtToken', 'basic']), the login page shows tabs
|
|
344
|
-
#> to choose between Token and Login (username/password) authentication.
|
|
345
|
-
type: 'basic'
|
package/config/local.yaml
CHANGED
|
@@ -11,6 +11,9 @@ agentTester:
|
|
|
11
11
|
baseURL: https://litellm.finam.ru/v1
|
|
12
12
|
exposeToClient: true
|
|
13
13
|
|
|
14
|
+
adminPanel:
|
|
15
|
+
enabled: true
|
|
16
|
+
authType: [ 'permanentServerTokens', 'basic', 'jwtToken' ]
|
|
14
17
|
|
|
15
18
|
ad:
|
|
16
19
|
domains:
|
|
@@ -104,7 +107,3 @@ webServer:
|
|
|
104
107
|
|
|
105
108
|
|
|
106
109
|
genJwtApiEnable: false
|
|
107
|
-
adminAuth:
|
|
108
|
-
enabled: true
|
|
109
|
-
# 'permanentServerTokens' | 'basic' | 'jwtToken' | 'ntlm'
|
|
110
|
-
type: [ 'permanentServerTokens', 'basic', 'jwtToken' ]
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fa-mcp-sdk",
|
|
3
3
|
"productName": "FA MCP SDK",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.71",
|
|
5
5
|
"description": "Core infrastructure and templates for building Model Context Protocol (MCP) servers with TypeScript",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/core/index.js",
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'fs';
|
|
3
|
+
import { basename, dirname, join, relative, sep } from 'path';
|
|
4
|
+
|
|
5
|
+
const templateDir = join(process.cwd(), './node_modules/fa-mcp-sdk/cli-template');
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
|
|
8
|
+
const targets = [
|
|
9
|
+
{ name: 'FA-MCP-SDK-DOC', src: join(templateDir, 'FA-MCP-SDK-DOC'), dest: join(cwd, 'FA-MCP-SDK-DOC') },
|
|
10
|
+
{
|
|
11
|
+
name: '.claude',
|
|
12
|
+
src: join(templateDir, '.claude'),
|
|
13
|
+
dest: join(cwd, '.claude'),
|
|
14
|
+
preserve: ['settings.json'],
|
|
15
|
+
respectPin: true,
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
// A folder containing a direct file named `pin` is preserved untouched —
|
|
20
|
+
// it is neither deleted nor overwritten with new content from the template.
|
|
21
|
+
function findPinnedFolders (rootDir) {
|
|
22
|
+
const pinned = new Set();
|
|
23
|
+
if (!existsSync(rootDir)) {return pinned;}
|
|
24
|
+
const walk = (currentDir) => {
|
|
25
|
+
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
26
|
+
if (entries.some((e) => e.isFile() && e.name === 'pin')) {
|
|
27
|
+
const rel = relative(rootDir, currentDir);
|
|
28
|
+
if (rel) {pinned.add(rel);}
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
if (entry.isDirectory()) {walk(join(currentDir, entry.name));}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
walk(rootDir);
|
|
36
|
+
return pinned;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isInsidePinned (relPath, pinned) {
|
|
40
|
+
if (!relPath) {return false;}
|
|
41
|
+
if (pinned.has(relPath)) {return true;}
|
|
42
|
+
for (const p of pinned) {
|
|
43
|
+
if (relPath.startsWith(p + sep)) {return true;}
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function cleanExceptPinned (rootDir, pinned) {
|
|
49
|
+
if (!existsSync(rootDir)) {return;}
|
|
50
|
+
const walk = (currentDir) => {
|
|
51
|
+
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
const full = join(currentDir, entry.name);
|
|
54
|
+
const fullRel = relative(rootDir, full);
|
|
55
|
+
if (pinned.has(fullRel)) {continue;}
|
|
56
|
+
const hasPinnedDescendant = [...pinned].some((p) => p.startsWith(fullRel + sep));
|
|
57
|
+
if (entry.isDirectory() && hasPinnedDescendant) {
|
|
58
|
+
walk(full);
|
|
59
|
+
} else {
|
|
60
|
+
rmSync(full, { recursive: true, force: true });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
walk(rootDir);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const { name, src, dest, preserve = [], respectPin = false } of targets) {
|
|
68
|
+
if (!existsSync(src)) {
|
|
69
|
+
console.error('Source not found:', src);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
const saved = {};
|
|
73
|
+
for (const file of preserve) {
|
|
74
|
+
const p = join(dest, file);
|
|
75
|
+
if (existsSync(p)) {saved[file] = readFileSync(p);}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const pinned = respectPin ? findPinnedFolders(dest) : new Set();
|
|
79
|
+
|
|
80
|
+
if (existsSync(dest)) {
|
|
81
|
+
if (pinned.size > 0) {
|
|
82
|
+
cleanExceptPinned(dest, pinned);
|
|
83
|
+
} else {
|
|
84
|
+
rmSync(dest, { recursive: true });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
cpSync(src, dest, {
|
|
89
|
+
recursive: true,
|
|
90
|
+
filter: (srcPath) => {
|
|
91
|
+
if (preserve.includes(basename(srcPath))) {return false;}
|
|
92
|
+
if (respectPin && pinned.size > 0) {
|
|
93
|
+
const rel = relative(src, srcPath);
|
|
94
|
+
if (isInsidePinned(rel, pinned)) {return false;}
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
for (const [file, content] of Object.entries(saved)) {
|
|
101
|
+
const p = join(dest, file);
|
|
102
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
103
|
+
writeFileSync(p, content);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (pinned.size > 0) {
|
|
107
|
+
console.log(`${name} updated (pinned folders preserved: ${[...pinned].join(', ')})`);
|
|
108
|
+
} else {
|
|
109
|
+
console.log(`${name} updated`);
|
|
110
|
+
}
|
|
111
|
+
}
|
package/scripts/update-doc.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs';
|
|
3
|
-
import { basename, dirname, join } from 'path';
|
|
4
|
-
|
|
5
|
-
const templateDir = join(process.cwd(), './node_modules/fa-mcp-sdk/cli-template');
|
|
6
|
-
const cwd = process.cwd();
|
|
7
|
-
|
|
8
|
-
const targets = [
|
|
9
|
-
{ name: 'FA-MCP-SDK-DOC', src: join(templateDir, 'FA-MCP-SDK-DOC'), dest: join(cwd, 'FA-MCP-SDK-DOC') },
|
|
10
|
-
{ name: '.claude', src: join(templateDir, '.claude'), dest: join(cwd, '.claude'), preserve: ['settings.json'] },
|
|
11
|
-
];
|
|
12
|
-
|
|
13
|
-
for (const { name, src, dest, preserve = [] } of targets) {
|
|
14
|
-
if (!existsSync(src)) {
|
|
15
|
-
console.error('Source not found:', src);
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
const saved = {};
|
|
19
|
-
for (const file of preserve) {
|
|
20
|
-
const p = join(dest, file);
|
|
21
|
-
if (existsSync(p)) saved[file] = readFileSync(p);
|
|
22
|
-
}
|
|
23
|
-
if (existsSync(dest)) {
|
|
24
|
-
rmSync(dest, { recursive: true });
|
|
25
|
-
}
|
|
26
|
-
cpSync(src, dest, {
|
|
27
|
-
recursive: true,
|
|
28
|
-
filter: (srcPath) => !preserve.includes(basename(srcPath)),
|
|
29
|
-
});
|
|
30
|
-
for (const [file, content] of Object.entries(saved)) {
|
|
31
|
-
const p = join(dest, file);
|
|
32
|
-
mkdirSync(dirname(p), { recursive: true });
|
|
33
|
-
writeFileSync(p, content);
|
|
34
|
-
}
|
|
35
|
-
console.log(`${name} updated`);
|
|
36
|
-
}
|