fa-mcp-sdk 0.4.100 → 0.4.103

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -217,6 +217,9 @@ Note: The `dist/` directory (compiled JavaScript) is created after running `npm
217
217
  | `node scripts/generate-jwt.js` | Generate JWT token (CLI) |
218
218
  | `/gen-jwt` | Generate JWT token (Claude Code skill) |
219
219
  | `/upgrade-guide` | Generate upgrade guide for downstream projects (Claude Code skill) |
220
+ | `npm run agents:link` | Share `.claude/skills` with OpenAI Codex (creates `.agents/skills` symlink) |
221
+ | `npm run agents:link:status` | Show current state of the Codex skills link |
222
+ | `npm run agents:link:remove` | Remove the Codex skills link |
220
223
  | `npm run consul:unreg` | Deregister from Consul |
221
224
 
222
225
 
@@ -274,6 +277,24 @@ Output language is English by default. Add a natural-language hint (e.g., "на
274
277
 
275
278
  Skill location: `.claude/skills/upgrade-guide/SKILL.md`
276
279
 
280
+ ## Sharing Skills with OpenAI Codex
281
+
282
+ Claude Code skills (`.claude/skills/*`) can be reused from [OpenAI Codex](https://developers.openai.com/codex/)
283
+ without duplication. Codex officially reads project Skills from `.agents/skills/` and supports symlinked skill
284
+ folders. The bundled `scripts/setup-agent-links.js` creates the symlink (junction on Windows, relative symlink
285
+ on macOS/Linux) so both tools share the same canonical storage in `.claude/skills/`.
286
+
287
+ ```bash
288
+ npm run agents:link # create .agents/skills -> .claude/skills
289
+ npm run agents:link:status # inspect current link state
290
+ npm run agents:link:remove # remove the link
291
+ ```
292
+
293
+ Only **skills** are linked — other Claude Code entities (`.claude/agents/`, `.claude/commands/`, hooks, MCP
294
+ config) use formats that are not compatible with Codex (TOML agents in `.codex/agents/`, MCP servers in
295
+ `.codex/config.toml`) and must be configured separately. For Claude Code's `CLAUDE.md` and Codex's `AGENTS.md`,
296
+ keep a single `AGENTS.md` and import it from `CLAUDE.md` via `@AGENTS.md`.
297
+
277
298
  ## Directory Requirements
278
299
 
279
300
  - Use absolute paths for target directory
@@ -13,13 +13,19 @@ Existing tools get paired with HTML resources that render inline in the host's c
13
13
 
14
14
  ## Getting Reference Code
15
15
 
16
- Clone the MCP Apps SDK repository (`@modelcontextprotocol/ext-apps`) for working examples and API documentation:
16
+ Clone or update the MCP Apps SDK repository (`@modelcontextprotocol/ext-apps`) using the bundled
17
+ helper. The folder `./mcp-ext-apps/` is already in `.gitignore` and is intentionally persistent —
18
+ it serves as the long-lived reference checkout that this skill (and the `mcp-app-create` skill)
19
+ read from. Do not delete it after use.
17
20
 
18
21
  ```bash
19
- git clone --branch "v$(npm view @modelcontextprotocol/ext-apps version)" --depth 1 https://github.com/modelcontextprotocol/ext-apps.git ./mcp-ext-apps
22
+ node scripts/clone-mcp-ext-apps.js --tag latest
20
23
  ```
21
24
 
22
- > Add `mcp-ext-apps/` to the project's `.gitignore` it's a reference clone, not part of the project.
25
+ The script clones into `./mcp-ext-apps/` on first run, pulls the default branch on subsequent
26
+ runs, and (with `--tag latest`) checks out the latest released npm tag so the cloned tree
27
+ matches the published `@modelcontextprotocol/ext-apps` version. Add `--json` to capture machine-
28
+ readable metadata (path, ref, commit) for downstream automation.
23
29
 
24
30
  ### Protocol Specification
25
31
 
@@ -42,13 +42,19 @@ Host calls tool → Host renders resource UI → Server returns result → UI re
42
42
 
43
43
  ## Getting Reference Code
44
44
 
45
- Clone the MCP Apps SDK repository (`@modelcontextprotocol/ext-apps`) for working examples and API documentation:
45
+ Clone or update the MCP Apps SDK repository (`@modelcontextprotocol/ext-apps`) using the bundled
46
+ helper. The folder `./mcp-ext-apps/` is already in `.gitignore` and is intentionally persistent —
47
+ it serves as the long-lived reference checkout that this skill (and the `mcp-app-add-to-server`
48
+ skill) read from. Do not delete it after use.
46
49
 
47
50
  ```bash
48
- git clone --branch "v$(npm view @modelcontextprotocol/ext-apps version)" --depth 1 https://github.com/modelcontextprotocol/ext-apps.git ./mcp-ext-apps
51
+ node scripts/clone-mcp-ext-apps.js --tag latest
49
52
  ```
50
53
 
51
- > Add `mcp-ext-apps/` to the project's `.gitignore` it's a reference clone, not part of the project.
54
+ The script clones into `./mcp-ext-apps/` on first run, pulls the default branch on subsequent
55
+ runs, and (with `--tag latest`) checks out the latest released npm tag so the cloned tree
56
+ matches the published `@modelcontextprotocol/ext-apps` version. Add `--json` to capture machine-
57
+ readable metadata (path, ref, commit) for downstream automation.
52
58
 
53
59
  ### Protocol Specification
54
60
 
@@ -0,0 +1,381 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What This Is
6
+
7
+ An MCP (Model Context Protocol) server built on the `fa-mcp-sdk` framework. It exposes tools, prompts, and resources to AI agents via STDIO or HTTP/SSE transports.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ # Build & run
13
+ yarn build # tsc
14
+ yarn cb # clean dist/ + build
15
+ yarn start # node dist/src/start.js (HTTP mode)
16
+ node dist/src/start.js stdio # STDIO mode (Claude Desktop)
17
+
18
+ # Lint & typecheck
19
+ yarn lint # oxlint
20
+ yarn lint:fix # oxlint --fix
21
+ yarn format # oxfmt --check
22
+ yarn format:fix # oxfmt
23
+ yarn typecheck # tsc --noEmit
24
+
25
+ # Tests
26
+ yarn test # jest (all tests)
27
+ yarn test:mcp # STDIO transport tests
28
+ yarn test:mcp-http # HTTP transport tests
29
+ yarn test:mcp-sse # SSE transport tests
30
+ npx jest tests/path/to/file.test.ts # single test file
31
+
32
+ # Utilities
33
+ yarn check-llm # Validate OpenAI API key for Agent Tester
34
+ yarn generate-token # JWT token generator UI
35
+
36
+ # JWT token generation (CLI)
37
+ node scripts/generate-jwt.js -u <username> -ttl <duration> [-s <service>] [-p <params>]
38
+ # duration: <N>s | <N>m | <N>d | <N>y
39
+ # example: node scripts/generate-jwt.js -u admin -ttl 30d -s my-mcp -p "role=admin;team=ops"
40
+
41
+ # JWT generation API (HTTP endpoint, requires webServer.genJwtApiEnable: true)
42
+ # POST /gen-jwt {"username":"user","ttl":"30d","service":"svc","params":"key=val"}
43
+
44
+ yarn consul:unreg # deregister from Consul
45
+ ```
46
+
47
+ ## JWT Token Generation (Skill /gen-jwt)
48
+
49
+ Generate JWT tokens for MCP server authentication using the `/gen-jwt` skill.
50
+ Triggers: user asks to generate/create a JWT token, mentions "jwt", "token for user", "токен для", "сгенерируй токен для".
51
+
52
+ **Start/stop the server**: `yarn build && yarn start`. Stop with Ctrl+C. Port is in `config/default.yaml` → `webServer.port`. Force stop: `node scripts/kill-port.js <port>`.
53
+
54
+ **Server endpoints** (HTTP mode): `/mcp/*` (MCP protocol), `/docs` (Swagger UI), `/admin` (token generator), `/health`, `/agent-tester` (chat UI for testing tools).
55
+
56
+ ## Architecture
57
+
58
+ ```
59
+ src/
60
+ ├── start.ts # Entry point — calls initMcpServer()
61
+ ├── _types_/custom-config.ts # Custom AppConfig extensions
62
+ ├── tools/
63
+ │ ├── tools.ts # Tool[] definitions (name, inputSchema)
64
+ │ └── handle-tool-call.ts # Tool execution logic (switch on name)
65
+ ├── prompts/
66
+ │ ├── agent-brief.ts # Short agent description
67
+ │ ├── agent-prompt.ts # Full system prompt
68
+ │ └── custom-prompts.ts # Additional IPromptData[]
69
+ ├── api/router.ts # REST endpoints (tsoa decorators)
70
+ └── custom-resources.ts # MCP resources (IResourceData[])
71
+
72
+ config/
73
+ ├── default.yaml # Base config
74
+ ├── development.yaml # Dev overrides
75
+ ├── production.yaml # Prod overrides
76
+ ├── local.yaml # Local secrets (gitignored)
77
+ └── custom-environment-variables.yaml # Env var → config mapping
78
+
79
+ tests/mcp/ # MCP tool tests (STDIO, HTTP, SSE)
80
+ ```
81
+
82
+ This is the default structure generated by the CLI. It can be modified or extended as needed — add directories, split files, introduce layers (services, repositories, etc.) based on the MCP server's requirements.
83
+
84
+ ### Key Patterns
85
+
86
+ ```typescript
87
+ // All imports from fa-mcp-sdk use .js extensions (ESM)
88
+ import {
89
+ initMcpServer, appConfig, formatToolResult, ToolExecutionError,
90
+ IToolHandlerParams, TToolHandlerResponse,
91
+ } from 'fa-mcp-sdk';
92
+
93
+ // Tool handler receives headers and JWT payload; returns TToolHandlerResponse
94
+ // ({ content: [...] } or { structuredContent: {...} }, driven by appConfig.mcp.tools.answerAs).
95
+ export const handleToolCall = async (params: IToolHandlerParams): Promise<TToolHandlerResponse> => {
96
+ const { name, arguments: args, headers, payload, transport } = params;
97
+ // payload.user available when JWT auth enabled
98
+ };
99
+
100
+ // REST API uses tsoa decorators
101
+ @Route('api') export class MyController { @Get('endpoint') ... }
102
+ ```
103
+
104
+ ### Config System
105
+
106
+ Priority: environment variables > local.yaml > {NODE_ENV}.yaml > default.yaml. Access via `appConfig` from `fa-mcp-sdk`. Extend the type in `src/_types_/custom-config.ts`.
107
+
108
+ ### Auth Order
109
+
110
+ When multiple auth methods configured, detection from `Authorization` header:
111
+ 1. `permanentServerTokens` — static tokens (O(1) lookup)
112
+ 2. `basic` — base64 username:password
113
+ 3. `jwtToken` — standard signed JWT, HS256 (optional IP restriction via `isCheckIP` + `ip` field in payload; legacy `<expire>.<hex>` tokens still accepted for backward compatibility)
114
+ 4. `custom` — user-defined validator (fallback)
115
+
116
+ ## Framework Documentation
117
+
118
+ Detailed fa-mcp-sdk docs are in `FA-MCP-SDK-DOC/`:
119
+
120
+ | File | When to Read |
121
+ |------|-------------|
122
+ | `00-FA-MCP-SDK-index.md` | Quick reference, all exports, project structure |
123
+ | `01-getting-started.md` | `initMcpServer()`, `McpServerData`, `IToolHandlerParams` |
124
+ | `02-1-tools-and-api.md` | Tool definitions, REST API with tsoa |
125
+ | `02-2-prompts-and-resources.md` | Prompts, resources, `ITransportContext` |
126
+ | `03-configuration.md` | `appConfig`, YAML config, DB, cache |
127
+ | `04-authentication.md` | JWT, Basic auth, permanent tokens |
128
+ | `05-ad-authorization.md` | AD group authorization, AD config |
129
+ | `06-utilities.md` | Error handling, logging, Consul |
130
+ | `07-testing-and-operations.md` | Test clients (STDIO, HTTP, SSE, Streamable HTTP) |
131
+ | `08-agent-tester-and-headless-api.md` | Agent Tester, Headless API, structured logging, automated testing |
132
+ | `09-database.md` | PostgreSQL sugar layer (`queryMAIN`, `execMAIN`, upserts, `mergeByBatch`), `pgvector`, secondary DBs |
133
+ | `10-mcp-apps.md` | Building / extending MCP Apps (UI-augmented tools) — protocol contract, SDK surface, patterns, pitfalls |
134
+
135
+ ## Development and Testing Through Agent Tester
136
+
137
+ The Agent Tester validates the full agent experience: how the LLM interprets tool descriptions, selects tools, passes arguments, and presents results. → See `08-agent-tester-and-headless-api.md` for complete API reference.
138
+
139
+ ### Prerequisites
140
+
141
+ Agent Tester requires an OpenAI API key to call the LLM. Before using it, ensure the following configuration is in place:
142
+
143
+ **Option A** — environment variables (`.env` file or shell):
144
+ ```
145
+ AGENT_TESTER_ENABLED=true
146
+ AGENT_TESTER_OPENAI_API_KEY=sk-...
147
+ ```
148
+
149
+ **Option B** — `config/default.yaml` (or `local.yaml`):
150
+ ```yaml
151
+ agentTester:
152
+ enabled: true
153
+ openAi:
154
+ apiKey: sk-...
155
+ ```
156
+
157
+ **IMPORTANT for Claude Code**: When the development prompt or instructions mention testing with Headless API or Agent Tester, run `yarn check-llm` before starting any Agent Tester work. This script validates that the OpenAI API key is configured and functional. If it fails (exit code 1 = key missing, exit code 2 = key invalid or API error), inform the user about the issue and ask them to fix the configuration before proceeding with Agent Tester tests. See `08-agent-tester-and-headless-api.md` → "LLM Availability Check" for details.
158
+
159
+ **Disabled state**: If `agentTester.enabled` is `false`, the server returns HTTP 404 on any `/agent-tester/*` request (including the Headless API). When you receive this 404 response, do **NOT** enable Agent Tester yourself — only inform the developer that Agent Tester may be disabled, and that it can be enabled via `agentTester.enabled: true` in `config/local.yaml` or ENV `AGENT_TESTER_ENABLED=true`. The developer decides whether to enable it. However, if the developer's prompt or instructions explicitly state that you should not mention Agent Tester enablement, respect that and do not bring it up.
160
+
161
+ ### What Gets Tested
162
+
163
+ - **Tool architecture** — correct tool decomposition (split or merge?)
164
+ - **Agent prompt** — LLM follows desired conversation style
165
+ - **Tool descriptions** — LLM understands when and why to call each tool
166
+ - **Parameter design** — names, types, required/optional intuitive for LLM
167
+ - **Response format** — `formatToolResult()` output interpretable by LLM
168
+ - **Error handling** — agent explains errors clearly
169
+ - **Edge cases** — missing params, invalid values, service unavailability
170
+
171
+ ### Development Workflow
172
+
173
+ Follow this sequence when building or extending an MCP server:
174
+
175
+ #### Step 1: Design Tool Set
176
+
177
+ Define the tools your server will expose. For each tool, decide:
178
+ - **Name** — clear, action-oriented (e.g., `get_currency_rate`, `search_documents`)
179
+ - **Description** — what the tool does and when to use it (the LLM reads this to decide whether to call it)
180
+ - **Parameters** — name, type, required/optional, description including defaults and constraints
181
+ - **Response structure** — what data the tool returns
182
+
183
+ Write definitions in `src/tools/tools.ts`. → See `02-1-tools-and-api.md`.
184
+
185
+ #### Step 2: Write Code
186
+
187
+ - `src/tools/handle-tool-call.ts` — tool execution logic (switch on tool name)
188
+ - `src/custom-resources.ts` — MCP resources (if needed)
189
+ - `src/api/router.ts` — REST API endpoints with tsoa decorators (if needed)
190
+ - `config/default.yaml` — configuration (DB, auth, access points, etc.)
191
+
192
+ → See `01-getting-started.md`, `02-1-tools-and-api.md`, `03-configuration.md`.
193
+
194
+ #### Step 3: Write Agent Prompt and Brief
195
+
196
+ - `src/prompts/agent-brief.ts` — short agent description (shown in tool listings)
197
+ - `src/prompts/agent-prompt.ts` — full system prompt shaping LLM behavior, tool usage logic, and response style
198
+ - `src/prompts/custom-prompts.ts` — additional prompts (if needed)
199
+
200
+ The agent prompt is critical — it determines how the LLM uses your tools. → See `02-2-prompts-and-resources.md`.
201
+
202
+ #### Step 4: Write Tests
203
+
204
+ Test files in `tests/mcp/`:
205
+ - `test-cases.js` — shared test cases (tool names, arguments, expected results). **This is the main file to edit** when adding tools.
206
+ - `test-http.js` — HTTP transport tests
207
+ - `test-sse.js` — SSE transport tests
208
+ - `test-stdio.js` — STDIO transport tests
209
+
210
+ What to cover in test cases:
211
+ - Happy path for each tool
212
+ - Error cases (invalid params, missing required fields, service errors)
213
+ - Auth flows (if auth enabled)
214
+
215
+ Run tests per transport:
216
+ ```bash
217
+ yarn test:mcp # STDIO
218
+ yarn test:mcp-http # HTTP
219
+ yarn test:mcp-sse # SSE
220
+ ```
221
+
222
+ → See `07-testing-and-operations.md`.
223
+
224
+ #### Step 5: Build, Lint, Verify
225
+
226
+ ```bash
227
+ yarn cb # Clean build — fix all compilation errors
228
+ yarn lint:fix # Oxlint — fix all lint errors
229
+ yarn format:fix # Oxfmt — format the project
230
+ yarn typecheck # tsc --noEmit — fix all type errors
231
+ yarn start # Start server — verify clean startup, no runtime errors
232
+ yarn test:mcp # STDIO transport tests
233
+ yarn test:mcp-http # HTTP transport tests
234
+ yarn test:mcp-sse # SSE transport tests
235
+ ```
236
+
237
+ **Goal**: zero build errors, zero lint errors, zero type errors, clean server startup, all tests green.
238
+
239
+ #### Step 6: Iterative Refinement via Agent Tester
240
+
241
+ Once the server starts cleanly, move to agent-level testing.
242
+ Use `gpt-5.2` as the model in Agent Tester — it provides the best balance of tool-calling accuracy and reasoning for MCP testing. Send real messages through the Headless API, observe how the LLM uses your tools, and refine:
243
+
244
+ - **Tool descriptions** — if the LLM picks the wrong tool or misunderstands its purpose
245
+ - **Parameter schemas** — if the LLM sends wrong types or misses required params
246
+ - **Agent prompt** — if the LLM doesn't follow the desired conversation style
247
+ - **Handler logic** — if tool results confuse the LLM or lack needed information
248
+ - **Error messages** — if failures produce unhelpful agent responses
249
+
250
+ Each iteration: observe → diagnose root cause → fix → `yarn cb && yarn start` → re-test.
251
+
252
+ #### Step 7: Development Report
253
+
254
+ When all tools are implemented, tests pass, and agent testing is complete, create `claudedocs/dev-report.md`:
255
+
256
+ - **What was built** — list of tools, prompts, resources, REST endpoints with brief descriptions
257
+ - **Architecture decisions** — why tools were decomposed a certain way, key design choices
258
+ - **Agent prompt rationale** — what behavior the prompt enforces and why
259
+ - **Test coverage** — which scenarios were tested, which transports
260
+ - **Agent Tester findings** — what was refined during iterative testing (descriptions, schemas, prompt adjustments) and why
261
+ - **Configuration** — required config keys, environment variables, external dependencies
262
+ - **Known limitations** — edge cases not covered, planned improvements
263
+
264
+ ### Testing via Headless API (Primary Method)
265
+
266
+ Direct HTTP calls — no browser needed. Provides structured trace data.
267
+
268
+ ```
269
+ 1. yarn cb && yarn start
270
+ 2. GET /agent-tester/api/mcp/status → verify tools loaded
271
+ 3. POST /agent-tester/api/chat/test → send message, get response + trace
272
+ 4. Analyze trace: correct tool? correct args? expected result?
273
+ 5. Check trace.system_prompt_sent → verify exact prompt sent to LLM
274
+ 6. If unclear → retry with ?verbose=true
275
+ 7. If issue found → fix code → rebuild → re-test
276
+ ```
277
+
278
+ Query params: `?verbose=true` (LLM details per turn), `?maxResultChars=8000`, `?maxTraceChars=100000`.
279
+
280
+ **Prompt control in headless requests.** The `agentPrompt` field sets the system prompt sent to the LLM — when provided, it **replaces** the MCP server's built-in `agent_prompt`. Use it to iterate on prompt variations: read the current `AGENT_PROMPT` from `src/prompts/agent-prompt.ts`, send modified versions via `agentPrompt`, evaluate responses, and write the best variant back. The `customPrompt` field appends additional instructions. The trace response includes `system_prompt_sent` — the exact prompt the LLM received. → See `08-agent-tester-and-headless-api.md` for full prompt assembly logic and examples.
281
+
282
+ Structured JSON logging: `yarn start --log-json` or `AGENT_TESTER_LOG_JSON=true yarn start` — emits per-event JSON on stdout.
283
+
284
+ ### Playwright Testing (Fallback — UI Only)
285
+
286
+ Use only for UI-specific verification (page layout, DOM interaction). For tool testing, use the headless API.
287
+
288
+ ```
289
+ browser_navigate → http://localhost:<port>/agent-tester
290
+ browser_snapshot → verify page loaded
291
+ browser_type → message input
292
+ browser_click → send button
293
+ browser_wait_for → assistant response
294
+ browser_snapshot → verify response
295
+ ```
296
+
297
+ ### Testing Log
298
+
299
+ Maintain `claudedocs/test-log.md` during automated testing — a chronological narrative of actions, expectations, results, and diagnoses.
300
+
301
+ ```markdown
302
+ # Agent Tester — Test Log
303
+
304
+ ## Session: 2025-08-15
305
+
306
+ ### Iteration 1
307
+
308
+ Server running on port 9876. 3 tools detected.
309
+
310
+ **Testing get_currency_rate — basic case**
311
+ Sending: "What is the exchange rate of EUR to USD?"
312
+ Expected: numeric rate, mentions EUR and USD.
313
+ Received: "The current EUR/USD exchange rate is 1.0847"
314
+ Tools used: get_currency_rate
315
+ Result: OK
316
+
317
+ **Testing get_currency_rate — invalid currency**
318
+ Sending: "Get rate for XYZ to USD"
319
+ Expected: error message about unknown currency.
320
+ Received: "I couldn't find the exchange rate. The currency code XYZ is not recognized."
321
+ Tools used: get_currency_rate
322
+ Result: OK
323
+
324
+ **Testing get_currency_rate — missing base currency default**
325
+ Sending: "What is the rate for THB?"
326
+ Expected: THB/USD rate (baseCurrency defaults to USD).
327
+ Received: "I need to know which currency you want to convert THB to. Could you specify?"
328
+ Tools used: none
329
+ Result: FAIL — LLM did not use default baseCurrency, asked for clarification instead.
330
+
331
+ **Diagnosis**: The tool description says "baseCurrency - optional", but doesn't mention the default value.
332
+ **Fix**: Adding "defaults to USD if not specified" to baseCurrency description in tools.ts.
333
+
334
+ Stopping server. Rebuilding...
335
+ Build OK. Server restarted.
336
+
337
+ ### Iteration 2
338
+
339
+ **Re-testing get_currency_rate — missing base currency default**
340
+ Sending: "What is the rate for THB?"
341
+ Received: "The current THB/USD exchange rate is 0.0291"
342
+ Tools used: get_currency_rate
343
+ Result: OK — LLM now uses USD as default.
344
+
345
+ ...
346
+ ```
347
+
348
+ This log serves as:
349
+ - **Audit trail** — what was tested, what passed, what failed
350
+ - **Decision record** — why each change was made (e.g., "changed description because LLM didn't understand default value")
351
+ - **Progress tracker** — which tools/scenarios are covered, which remain
352
+ - **Handoff document** — if the session is interrupted, the next session can read the log and continue
353
+
354
+ ## Editing files in `.claude/` (Skill /edit-claude-files)
355
+
356
+ Any edit or new file under `.claude/**` (SKILL.md, scripts, hooks, agents, `settings.json`) is blocked
357
+ by `settings.json` — direct `Write`/`Edit` will fail. Invoke the `/edit-claude-files` skill, which
358
+ describes the required `scripts/fcp.js` temp-copy protocol.
359
+
360
+ ## MCP Apps Reference Clone (`scripts/clone-mcp-ext-apps.js`)
361
+
362
+ Shared helper used by the `/mcp-app-create` and `/mcp-app-add-to-server` skills. Clones or refreshes
363
+ `https://github.com/modelcontextprotocol/ext-apps.git` into `./mcp-ext-apps/` at the project root
364
+ (already in `.gitignore`, intentionally persistent so the same checkout is reused across runs).
365
+
366
+ ```bash
367
+ node scripts/clone-mcp-ext-apps.js # clone on first run, pull main otherwise
368
+ node scripts/clone-mcp-ext-apps.js --tag latest # also checkout the latest npm tag
369
+ node scripts/clone-mcp-ext-apps.js --tag v1.7.2 # checkout a specific tag
370
+ node scripts/clone-mcp-ext-apps.js --json # JSON output (path, ref, commit, version)
371
+ node scripts/clone-mcp-ext-apps.js --list-examples # include examples/* metadata in JSON
372
+ ```
373
+
374
+ The script never deletes `mcp-ext-apps/`. The two skills above call it before reading sources from
375
+ the cloned tree, so make sure it has run successfully before troubleshooting their behavior.
376
+
377
+
378
+ ## Formatting
379
+
380
+ MD lines ≤120 chars. Break at 120. Target 100-120. No short lines (60-80). Fill to ~120.
381
+ Exceptions: URLs, code blocks, tables — no wrap.