fa-mcp-sdk 0.4.76 → 0.4.77

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 (198) hide show
  1. package/README.md +319 -314
  2. package/bin/fa-mcp.js +85 -68
  3. package/cli-template/.claude/agents/javascript-pro.md +276 -276
  4. package/cli-template/.claude/settings.json +50 -50
  5. package/cli-template/.claude/skills/upgrade-guide/SKILL.md +2 -1
  6. package/cli-template/.oxfmtrc.json +41 -0
  7. package/cli-template/.oxlintrc.json +120 -0
  8. package/cli-template/CLAUDE.md +358 -355
  9. package/cli-template/FA-MCP-SDK-DOC/00-FA-MCP-SDK-index.md +132 -132
  10. package/cli-template/FA-MCP-SDK-DOC/01-getting-started.md +146 -146
  11. package/cli-template/FA-MCP-SDK-DOC/02-1-tools-and-api.md +431 -431
  12. package/cli-template/FA-MCP-SDK-DOC/02-2-prompts-and-resources.md +201 -201
  13. package/cli-template/FA-MCP-SDK-DOC/03-configuration.md +384 -384
  14. package/cli-template/FA-MCP-SDK-DOC/04-authentication.md +412 -412
  15. package/cli-template/FA-MCP-SDK-DOC/05-ad-authorization.md +196 -196
  16. package/cli-template/FA-MCP-SDK-DOC/06-utilities.md +163 -163
  17. package/cli-template/FA-MCP-SDK-DOC/07-testing-and-operations.md +127 -127
  18. package/cli-template/jest.config.js +27 -30
  19. package/cli-template/package.json +10 -5
  20. package/cli-template/prompt-example-new-MCP.md +101 -101
  21. package/cli-template/readme-docs/SKILLS.md +1 -1
  22. package/cli-template/tsconfig.json +58 -58
  23. package/cli-template/update.cjs +41 -38
  24. package/config/custom-environment-variables.yaml +63 -63
  25. package/config/development.yaml +4 -4
  26. package/config/production.yaml +4 -4
  27. package/config/test.yaml +26 -26
  28. package/dist/core/_types_/TNtlm.d.ts.map +1 -1
  29. package/dist/core/_types_/active-directory-config.d.ts.map +1 -1
  30. package/dist/core/_types_/config.d.ts.map +1 -1
  31. package/dist/core/_types_/types.d.ts.map +1 -1
  32. package/dist/core/ad/group-checker.d.ts.map +1 -1
  33. package/dist/core/ad/group-checker.js.map +1 -1
  34. package/dist/core/agent-tester/agent-tester-router.d.ts.map +1 -1
  35. package/dist/core/agent-tester/agent-tester-router.js +6 -6
  36. package/dist/core/agent-tester/agent-tester-router.js.map +1 -1
  37. package/dist/core/agent-tester/check-llm.d.ts.map +1 -1
  38. package/dist/core/agent-tester/check-llm.js.map +1 -1
  39. package/dist/core/agent-tester/services/SummaryMemory.d.ts.map +1 -1
  40. package/dist/core/agent-tester/services/SummaryMemory.js +3 -9
  41. package/dist/core/agent-tester/services/SummaryMemory.js.map +1 -1
  42. package/dist/core/agent-tester/services/TesterAgentService.d.ts.map +1 -1
  43. package/dist/core/agent-tester/services/TesterAgentService.js +25 -27
  44. package/dist/core/agent-tester/services/TesterAgentService.js.map +1 -1
  45. package/dist/core/agent-tester/services/TesterMcpClientService.d.ts.map +1 -1
  46. package/dist/core/agent-tester/services/TesterMcpClientService.js +26 -25
  47. package/dist/core/agent-tester/services/TesterMcpClientService.js.map +1 -1
  48. package/dist/core/auth/admin-auth.d.ts.map +1 -1
  49. package/dist/core/auth/admin-auth.js +5 -5
  50. package/dist/core/auth/admin-auth.js.map +1 -1
  51. package/dist/core/auth/agent-tester-auth.d.ts.map +1 -1
  52. package/dist/core/auth/agent-tester-auth.js +1 -6
  53. package/dist/core/auth/agent-tester-auth.js.map +1 -1
  54. package/dist/core/auth/basic.d.ts.map +1 -1
  55. package/dist/core/auth/basic.js.map +1 -1
  56. package/dist/core/auth/ip-check.d.ts.map +1 -1
  57. package/dist/core/auth/ip-check.js +1 -1
  58. package/dist/core/auth/ip-check.js.map +1 -1
  59. package/dist/core/auth/jwt.d.ts.map +1 -1
  60. package/dist/core/auth/jwt.js +1 -1
  61. package/dist/core/auth/jwt.js.map +1 -1
  62. package/dist/core/auth/middleware.d.ts.map +1 -1
  63. package/dist/core/auth/middleware.js +9 -6
  64. package/dist/core/auth/middleware.js.map +1 -1
  65. package/dist/core/auth/multi-auth.d.ts.map +1 -1
  66. package/dist/core/auth/multi-auth.js +6 -6
  67. package/dist/core/auth/multi-auth.js.map +1 -1
  68. package/dist/core/auth/revocation.d.ts.map +1 -1
  69. package/dist/core/auth/revocation.js +2 -6
  70. package/dist/core/auth/revocation.js.map +1 -1
  71. package/dist/core/auth/token-generator/ntlm/ntlm-auth-options.d.ts.map +1 -1
  72. package/dist/core/auth/token-generator/ntlm/ntlm-auth-options.js +2 -2
  73. package/dist/core/auth/token-generator/ntlm/ntlm-auth-options.js.map +1 -1
  74. package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.js +1 -1
  75. package/dist/core/auth/token-generator/ntlm/ntlm-domain-config.js.map +1 -1
  76. package/dist/core/auth/token-generator/ntlm/ntlm-integration.d.ts.map +1 -1
  77. package/dist/core/auth/token-generator/ntlm/ntlm-integration.js +4 -2
  78. package/dist/core/auth/token-generator/ntlm/ntlm-integration.js.map +1 -1
  79. package/dist/core/auth/token-generator/server.d.ts.map +1 -1
  80. package/dist/core/auth/token-generator/server.js.map +1 -1
  81. package/dist/core/bootstrap/init-config.d.ts.map +1 -1
  82. package/dist/core/bootstrap/init-config.js +2 -2
  83. package/dist/core/bootstrap/init-config.js.map +1 -1
  84. package/dist/core/bootstrap/startup-info.d.ts.map +1 -1
  85. package/dist/core/bootstrap/startup-info.js +3 -7
  86. package/dist/core/bootstrap/startup-info.js.map +1 -1
  87. package/dist/core/cache/cache.d.ts.map +1 -1
  88. package/dist/core/cache/cache.js +2 -2
  89. package/dist/core/cache/cache.js.map +1 -1
  90. package/dist/core/consul/deregister.d.ts.map +1 -1
  91. package/dist/core/consul/deregister.js.map +1 -1
  92. package/dist/core/consul/get-consul-api.d.ts.map +1 -1
  93. package/dist/core/consul/get-consul-api.js +1 -2
  94. package/dist/core/consul/get-consul-api.js.map +1 -1
  95. package/dist/core/db/pg-db.d.ts.map +1 -1
  96. package/dist/core/db/pg-db.js +3 -3
  97. package/dist/core/db/pg-db.js.map +1 -1
  98. package/dist/core/debug.d.ts.map +1 -1
  99. package/dist/core/debug.js.map +1 -1
  100. package/dist/core/errors/BaseMcpError.d.ts.map +1 -1
  101. package/dist/core/errors/BaseMcpError.js.map +1 -1
  102. package/dist/core/errors/ValidationError.d.ts.map +1 -1
  103. package/dist/core/errors/ValidationError.js.map +1 -1
  104. package/dist/core/errors/errors.d.ts.map +1 -1
  105. package/dist/core/errors/errors.js +1 -1
  106. package/dist/core/errors/errors.js.map +1 -1
  107. package/dist/core/index.d.ts +6 -6
  108. package/dist/core/index.d.ts.map +1 -1
  109. package/dist/core/index.js +5 -5
  110. package/dist/core/index.js.map +1 -1
  111. package/dist/core/init-mcp-server.d.ts.map +1 -1
  112. package/dist/core/init-mcp-server.js.map +1 -1
  113. package/dist/core/logger.d.ts.map +1 -1
  114. package/dist/core/logger.js +1 -1
  115. package/dist/core/logger.js.map +1 -1
  116. package/dist/core/mcp/create-mcp-server.d.ts.map +1 -1
  117. package/dist/core/mcp/create-mcp-server.js +1 -1
  118. package/dist/core/mcp/create-mcp-server.js.map +1 -1
  119. package/dist/core/mcp/prompts.d.ts.map +1 -1
  120. package/dist/core/mcp/prompts.js.map +1 -1
  121. package/dist/core/mcp/readme-assembler.d.ts.map +1 -1
  122. package/dist/core/mcp/readme-assembler.js +3 -1
  123. package/dist/core/mcp/readme-assembler.js.map +1 -1
  124. package/dist/core/mcp/resources.d.ts.map +1 -1
  125. package/dist/core/mcp/resources.js.map +1 -1
  126. package/dist/core/mcp/server-stdio.d.ts.map +1 -1
  127. package/dist/core/utils/formatToolResult.d.ts.map +1 -1
  128. package/dist/core/utils/formatToolResult.js.map +1 -1
  129. package/dist/core/utils/port-checker.d.ts.map +1 -1
  130. package/dist/core/utils/port-checker.js.map +1 -1
  131. package/dist/core/utils/rate-limit.d.ts.map +1 -1
  132. package/dist/core/utils/rate-limit.js +2 -8
  133. package/dist/core/utils/rate-limit.js.map +1 -1
  134. package/dist/core/utils/testing/BaseMcpClient.d.ts.map +1 -1
  135. package/dist/core/utils/testing/BaseMcpClient.js.map +1 -1
  136. package/dist/core/utils/testing/McpHttpClient.d.ts.map +1 -1
  137. package/dist/core/utils/testing/McpHttpClient.js +2 -2
  138. package/dist/core/utils/testing/McpHttpClient.js.map +1 -1
  139. package/dist/core/utils/testing/McpSseClient.d.ts.map +1 -1
  140. package/dist/core/utils/testing/McpSseClient.js +3 -8
  141. package/dist/core/utils/testing/McpSseClient.js.map +1 -1
  142. package/dist/core/utils/testing/McpStdioClient.d.ts.map +1 -1
  143. package/dist/core/utils/testing/McpStdioClient.js.map +1 -1
  144. package/dist/core/utils/testing/McpStreamableHttpClient.d.ts.map +1 -1
  145. package/dist/core/utils/testing/McpStreamableHttpClient.js +7 -8
  146. package/dist/core/utils/testing/McpStreamableHttpClient.js.map +1 -1
  147. package/dist/core/utils/utils.d.ts.map +1 -1
  148. package/dist/core/utils/utils.js +3 -5
  149. package/dist/core/utils/utils.js.map +1 -1
  150. package/dist/core/web/admin-router.d.ts.map +1 -1
  151. package/dist/core/web/admin-router.js +3 -3
  152. package/dist/core/web/admin-router.js.map +1 -1
  153. package/dist/core/web/cors.d.ts.map +1 -1
  154. package/dist/core/web/cors.js.map +1 -1
  155. package/dist/core/web/favicon-svg.d.ts.map +1 -1
  156. package/dist/core/web/favicon-svg.js +1 -5
  157. package/dist/core/web/favicon-svg.js.map +1 -1
  158. package/dist/core/web/home-api.d.ts.map +1 -1
  159. package/dist/core/web/home-api.js +7 -8
  160. package/dist/core/web/home-api.js.map +1 -1
  161. package/dist/core/web/openapi.d.ts.map +1 -1
  162. package/dist/core/web/openapi.js +1 -3
  163. package/dist/core/web/openapi.js.map +1 -1
  164. package/dist/core/web/server-http.d.ts.map +1 -1
  165. package/dist/core/web/server-http.js +4 -4
  166. package/dist/core/web/server-http.js.map +1 -1
  167. package/dist/core/web/static/agent-tester/index.html +323 -323
  168. package/dist/core/web/static/agent-tester/script.js +311 -200
  169. package/dist/core/web/static/agent-tester/styles.css +1840 -1840
  170. package/dist/core/web/static/home/index.html +220 -220
  171. package/dist/core/web/static/home/script.js +72 -43
  172. package/dist/core/web/static/styles.css +927 -927
  173. package/dist/core/web/static/token-gen/index.html +136 -136
  174. package/dist/core/web/static/token-gen/script.js +58 -56
  175. package/dist/core/web/svg-icons.d.ts.map +1 -1
  176. package/dist/core/web/svg-icons.js +1 -5
  177. package/dist/core/web/svg-icons.js.map +1 -1
  178. package/package.json +10 -5
  179. package/{cli-template/.claude/hooks/eslint-fix.cjs → scripts/cc-hook-oxlint-oxfmt-fix.cjs} +109 -100
  180. package/scripts/generate-jwt.js +5 -9
  181. package/scripts/kill-port.js +5 -2
  182. package/scripts/npm/run.js +1 -2
  183. package/scripts/remove-nul.js +1 -1
  184. package/scripts/update-sdk.js +36 -14
  185. package/src/template/api/router.ts +3 -3
  186. package/src/template/prompts/agent-brief.ts +0 -1
  187. package/src/template/start.ts +3 -8
  188. package/src/template/tools/handle-tool-call.ts +3 -3
  189. package/src/template/tools/tools.ts +3 -7
  190. package/src/tests/jest-simple-reporter.js +1 -1
  191. package/src/tests/mcp/sse/mcp-sse-client-handling.md +111 -111
  192. package/src/tests/mcp/sse/test-sse-npm-package.js +2 -3
  193. package/src/tests/mcp/test-cases.js +6 -7
  194. package/src/tests/mcp/test-http.js +2 -2
  195. package/src/tests/mcp/test-sse.js +9 -7
  196. package/src/tests/mcp/test-stdio.js +12 -8
  197. package/src/tests/utils.ts +4 -3
  198. package/cli-template/eslint.config.js +0 -27
@@ -1,355 +1,358 @@
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 # eslint
20
- yarn lint:fix # eslint --fix
21
- yarn typecheck # tsc --noEmit
22
-
23
- # Tests
24
- yarn test # jest (all tests)
25
- yarn test:mcp # STDIO transport tests
26
- yarn test:mcp-http # HTTP transport tests
27
- yarn test:mcp-sse # SSE transport tests
28
- npx jest tests/path/to/file.test.ts # single test file
29
-
30
- # Utilities
31
- yarn check-llm # Validate OpenAI API key for Agent Tester
32
- yarn generate-token # JWT token generator UI
33
-
34
- # JWT token generation (CLI)
35
- node scripts/generate-jwt.js -u <username> -ttl <duration> [-s <service>] [-p <params>]
36
- # duration: <N>s | <N>m | <N>d | <N>y
37
- # example: node scripts/generate-jwt.js -u admin -ttl 30d -s my-mcp -p "role=admin;team=ops"
38
-
39
- # JWT generation API (HTTP endpoint, requires webServer.genJwtApiEnable: true)
40
- # POST /gen-jwt {"username":"user","ttl":"30d","service":"svc","params":"key=val"}
41
-
42
- yarn consul:unreg # deregister from Consul
43
- ```
44
-
45
- ## JWT Token Generation (Skill /gen-jwt)
46
-
47
- Generate JWT tokens for MCP server authentication using the `/gen-jwt` skill.
48
- Triggers: user asks to generate/create a JWT token, mentions "jwt", "token for user", "токен для", "сгенерируй токен для".
49
-
50
- **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>`.
51
-
52
- **Server endpoints** (HTTP mode): `/mcp/*` (MCP protocol), `/docs` (Swagger UI), `/admin` (token generator), `/health`, `/agent-tester` (chat UI for testing tools).
53
-
54
- ## Architecture
55
-
56
- ```
57
- src/
58
- ├── start.ts # Entry point — calls initMcpServer()
59
- ├── _types_/custom-config.ts # Custom AppConfig extensions
60
- ├── tools/
61
- ├── tools.ts # Tool[] definitions (name, inputSchema)
62
- │ └── handle-tool-call.ts # Tool execution logic (switch on name)
63
- ├── prompts/
64
- ├── agent-brief.ts # Short agent description
65
- ├── agent-prompt.ts # Full system prompt
66
- └── custom-prompts.ts # Additional IPromptData[]
67
- ├── api/router.ts # REST endpoints (tsoa decorators)
68
- └── custom-resources.ts # MCP resources (IResourceData[])
69
-
70
- config/
71
- ├── default.yaml # Base config
72
- ├── development.yaml # Dev overrides
73
- ├── production.yaml # Prod overrides
74
- ├── local.yaml # Local secrets (gitignored)
75
- └── custom-environment-variables.yaml # Env var → config mapping
76
-
77
- tests/mcp/ # MCP tool tests (STDIO, HTTP, SSE)
78
- ```
79
-
80
- 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.
81
-
82
- ### Key Patterns
83
-
84
- ```typescript
85
- // All imports from fa-mcp-sdk use .js extensions (ESM)
86
- import { initMcpServer, appConfig, formatToolResult, ToolExecutionError } from 'fa-mcp-sdk';
87
-
88
- // Tool handler receives headers and JWT payload
89
- export const handleToolCall = async (params: IToolHandlerParams): Promise<any> => {
90
- const { name, arguments: args, headers, payload, transport } = params;
91
- // payload.user available when JWT auth enabled
92
- };
93
-
94
- // REST API uses tsoa decorators
95
- @Route('api') export class MyController { @Get('endpoint') ... }
96
- ```
97
-
98
- ### Config System
99
-
100
- 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`.
101
-
102
- ### Auth Order
103
-
104
- When multiple auth methods configured, detection from `Authorization` header:
105
- 1. `permanentServerTokens` — static tokens (O(1) lookup)
106
- 2. `basic` — base64 username:password
107
- 3. `jwtToken` — encrypted JWT (optional IP restriction via `isCheckIP` + `ip` field in payload)
108
- 4. `custom` — user-defined validator (fallback)
109
-
110
- ## Framework Documentation
111
-
112
- Detailed fa-mcp-sdk docs are in `FA-MCP-SDK-DOC/`:
113
-
114
- | File | When to Read |
115
- |------|-------------|
116
- | `00-FA-MCP-SDK-index.md` | Quick reference, all exports, project structure |
117
- | `01-getting-started.md` | `initMcpServer()`, `McpServerData`, `IToolHandlerParams` |
118
- | `02-1-tools-and-api.md` | Tool definitions, REST API with tsoa |
119
- | `02-2-prompts-and-resources.md` | Prompts, resources, `ITransportContext` |
120
- | `03-configuration.md` | `appConfig`, YAML config, DB, cache |
121
- | `04-authentication.md` | JWT, Basic auth, permanent tokens |
122
- | `05-ad-authorization.md` | AD group authorization, AD config |
123
- | `06-utilities.md` | Error handling, logging, Consul |
124
- | `07-testing-and-operations.md` | Test clients (STDIO, HTTP, SSE, Streamable HTTP) |
125
- | `08-agent-tester-and-headless-api.md` | Agent Tester, Headless API, structured logging, automated testing |
126
-
127
- ## Development and Testing Through Agent Tester
128
-
129
- 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.
130
-
131
- ### Prerequisites
132
-
133
- Agent Tester requires an OpenAI API key to call the LLM. Before using it, ensure the following configuration is in place:
134
-
135
- **Option A** environment variables (`.env` file or shell):
136
- ```
137
- AGENT_TESTER_ENABLED=true
138
- AGENT_TESTER_OPENAI_API_KEY=sk-...
139
- ```
140
-
141
- **Option B** — `config/default.yaml` (or `local.yaml`):
142
- ```yaml
143
- agentTester:
144
- enabled: true
145
- openAi:
146
- apiKey: sk-...
147
- ```
148
-
149
- **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.
150
-
151
- **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.
152
-
153
- ### What Gets Tested
154
-
155
- - **Tool architecture** — correct tool decomposition (split or merge?)
156
- - **Agent prompt** — LLM follows desired conversation style
157
- - **Tool descriptions** — LLM understands when and why to call each tool
158
- - **Parameter design** — names, types, required/optional intuitive for LLM
159
- - **Response format** — `formatToolResult()` output interpretable by LLM
160
- - **Error handling** — agent explains errors clearly
161
- - **Edge cases** — missing params, invalid values, service unavailability
162
-
163
- ### Development Workflow
164
-
165
- Follow this sequence when building or extending an MCP server:
166
-
167
- #### Step 1: Design Tool Set
168
-
169
- Define the tools your server will expose. For each tool, decide:
170
- - **Name** — clear, action-oriented (e.g., `get_currency_rate`, `search_documents`)
171
- - **Description** — what the tool does and when to use it (the LLM reads this to decide whether to call it)
172
- - **Parameters** — name, type, required/optional, description including defaults and constraints
173
- - **Response structure** — what data the tool returns
174
-
175
- Write definitions in `src/tools/tools.ts`. See `02-1-tools-and-api.md`.
176
-
177
- #### Step 2: Write Code
178
-
179
- - `src/tools/handle-tool-call.ts` tool execution logic (switch on tool name)
180
- - `src/custom-resources.ts` — MCP resources (if needed)
181
- - `src/api/router.ts` — REST API endpoints with tsoa decorators (if needed)
182
- - `config/default.yaml` — configuration (DB, auth, access points, etc.)
183
-
184
- See `01-getting-started.md`, `02-1-tools-and-api.md`, `03-configuration.md`.
185
-
186
- #### Step 3: Write Agent Prompt and Brief
187
-
188
- - `src/prompts/agent-brief.ts` short agent description (shown in tool listings)
189
- - `src/prompts/agent-prompt.ts` — full system prompt shaping LLM behavior, tool usage logic, and response style
190
- - `src/prompts/custom-prompts.ts` — additional prompts (if needed)
191
-
192
- The agent prompt is critical it determines how the LLM uses your tools. → See `02-2-prompts-and-resources.md`.
193
-
194
- #### Step 4: Write Tests
195
-
196
- Test files in `tests/mcp/`:
197
- - `test-cases.js` — shared test cases (tool names, arguments, expected results). **This is the main file to edit** when adding tools.
198
- - `test-http.js` HTTP transport tests
199
- - `test-sse.js` — SSE transport tests
200
- - `test-stdio.js` — STDIO transport tests
201
-
202
- What to cover in test cases:
203
- - Happy path for each tool
204
- - Error cases (invalid params, missing required fields, service errors)
205
- - Auth flows (if auth enabled)
206
-
207
- Run tests per transport:
208
- ```bash
209
- yarn test:mcp # STDIO
210
- yarn test:mcp-http # HTTP
211
- yarn test:mcp-sse # SSE
212
- ```
213
-
214
- → See `07-testing-and-operations.md`.
215
-
216
- #### Step 5: Build, Lint, Verify
217
-
218
- ```bash
219
- yarn cb # Clean build — fix all compilation errors
220
- yarn lint:fix # ESLint — fix all lint errors
221
- yarn typecheck # tsc --noEmit — fix all type errors
222
- yarn start # Start server verify clean startup, no runtime errors
223
- yarn test:mcp # STDIO transport tests
224
- yarn test:mcp-http # HTTP transport tests
225
- yarn test:mcp-sse # SSE transport tests
226
- ```
227
-
228
- **Goal**: zero build errors, zero lint errors, zero type errors, clean server startup, all tests green.
229
-
230
- #### Step 6: Iterative Refinement via Agent Tester
231
-
232
- Once the server starts cleanly, move to agent-level testing.
233
- 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:
234
-
235
- - **Tool descriptions** — if the LLM picks the wrong tool or misunderstands its purpose
236
- - **Parameter schemas**if the LLM sends wrong types or misses required params
237
- - **Agent prompt** — if the LLM doesn't follow the desired conversation style
238
- - **Handler logic** — if tool results confuse the LLM or lack needed information
239
- - **Error messages** — if failures produce unhelpful agent responses
240
-
241
- Each iteration: observe diagnose root cause fix `yarn cb && yarn start` → re-test.
242
-
243
- #### Step 7: Development Report
244
-
245
- When all tools are implemented, tests pass, and agent testing is complete, create `claudedocs/dev-report.md`:
246
-
247
- - **What was built** — list of tools, prompts, resources, REST endpoints with brief descriptions
248
- - **Architecture decisions** why tools were decomposed a certain way, key design choices
249
- - **Agent prompt rationale** — what behavior the prompt enforces and why
250
- - **Test coverage** — which scenarios were tested, which transports
251
- - **Agent Tester findings** — what was refined during iterative testing (descriptions, schemas, prompt adjustments) and why
252
- - **Configuration** — required config keys, environment variables, external dependencies
253
- - **Known limitations** — edge cases not covered, planned improvements
254
-
255
- ### Testing via Headless API (Primary Method)
256
-
257
- Direct HTTP calls — no browser needed. Provides structured trace data.
258
-
259
- ```
260
- 1. yarn cb && yarn start
261
- 2. GET /agent-tester/api/mcp/status → verify tools loaded
262
- 3. POST /agent-tester/api/chat/test → send message, get response + trace
263
- 4. Analyze trace: correct tool? correct args? expected result?
264
- 5. Check trace.system_prompt_sent → verify exact prompt sent to LLM
265
- 6. If unclear retry with ?verbose=true
266
- 7. If issue found fix code rebuild → re-test
267
- ```
268
-
269
- Query params: `?verbose=true` (LLM details per turn), `?maxResultChars=8000`, `?maxTraceChars=100000`.
270
-
271
- **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.
272
-
273
- Structured JSON logging: `yarn start --log-json` or `AGENT_TESTER_LOG_JSON=true yarn start` — emits per-event JSON on stdout.
274
-
275
- ### Playwright Testing (Fallback — UI Only)
276
-
277
- Use only for UI-specific verification (page layout, DOM interaction). For tool testing, use the headless API.
278
-
279
- ```
280
- browser_navigate http://localhost:<port>/agent-tester
281
- browser_snapshot → verify page loaded
282
- browser_type → message input
283
- browser_click send button
284
- browser_wait_forassistant response
285
- browser_snapshot verify response
286
- ```
287
-
288
- ### Testing Log
289
-
290
- Maintain `claudedocs/test-log.md` during automated testing — a chronological narrative of actions, expectations, results, and diagnoses.
291
-
292
- ```markdown
293
- # Agent TesterTest Log
294
-
295
- ## Session: 2025-08-15
296
-
297
- ### Iteration 1
298
-
299
- Server running on port 9876. 3 tools detected.
300
-
301
- **Testing get_currency_rate — basic case**
302
- Sending: "What is the exchange rate of EUR to USD?"
303
- Expected: numeric rate, mentions EUR and USD.
304
- Received: "The current EUR/USD exchange rate is 1.0847"
305
- Tools used: get_currency_rate
306
- Result: OK
307
-
308
- **Testing get_currency_rate — invalid currency**
309
- Sending: "Get rate for XYZ to USD"
310
- Expected: error message about unknown currency.
311
- Received: "I couldn't find the exchange rate. The currency code XYZ is not recognized."
312
- Tools used: get_currency_rate
313
- Result: OK
314
-
315
- **Testing get_currency_rate — missing base currency default**
316
- Sending: "What is the rate for THB?"
317
- Expected: THB/USD rate (baseCurrency defaults to USD).
318
- Received: "I need to know which currency you want to convert THB to. Could you specify?"
319
- Tools used: none
320
- Result: FAIL LLM did not use default baseCurrency, asked for clarification instead.
321
-
322
- **Diagnosis**: The tool description says "baseCurrency - optional", but doesn't mention the default value.
323
- **Fix**: Adding "defaults to USD if not specified" to baseCurrency description in tools.ts.
324
-
325
- Stopping server. Rebuilding...
326
- Build OK. Server restarted.
327
-
328
- ### Iteration 2
329
-
330
- **Re-testing get_currency_rate — missing base currency default**
331
- Sending: "What is the rate for THB?"
332
- Received: "The current THB/USD exchange rate is 0.0291"
333
- Tools used: get_currency_rate
334
- Result: OK LLM now uses USD as default.
335
-
336
- ...
337
- ```
338
-
339
- This log serves as:
340
- - **Audit trail** — what was tested, what passed, what failed
341
- - **Decision record** — why each change was made (e.g., "changed description because LLM didn't understand default value")
342
- - **Progress tracker** — which tools/scenarios are covered, which remain
343
- - **Handoff document** — if the session is interrupted, the next session can read the log and continue
344
-
345
- ## Editing files in `.claude/` (Skill /edit-claude-files)
346
-
347
- Any edit or new file under `.claude/**` (SKILL.md, scripts, hooks, agents, `settings.json`) is blocked
348
- by `settings.json` direct `Write`/`Edit` will fail. Invoke the `/edit-claude-files` skill, which
349
- describes the required `scripts/fcp.js` temp-copy protocol.
350
-
351
-
352
- ## Formatting
353
-
354
- MD lines ≤120 chars. Break at 120. Target 100-120. No short lines (60-80). Fill to ~120.
355
- Exceptions: URLs, code blocks, tables — no wrap.
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 { initMcpServer, appConfig, formatToolResult, ToolExecutionError } from 'fa-mcp-sdk';
89
+
90
+ // Tool handler receives headers and JWT payload
91
+ export const handleToolCall = async (params: IToolHandlerParams): Promise<any> => {
92
+ const { name, arguments: args, headers, payload, transport } = params;
93
+ // payload.user available when JWT auth enabled
94
+ };
95
+
96
+ // REST API uses tsoa decorators
97
+ @Route('api') export class MyController { @Get('endpoint') ... }
98
+ ```
99
+
100
+ ### Config System
101
+
102
+ 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`.
103
+
104
+ ### Auth Order
105
+
106
+ When multiple auth methods configured, detection from `Authorization` header:
107
+ 1. `permanentServerTokens` — static tokens (O(1) lookup)
108
+ 2. `basic` — base64 username:password
109
+ 3. `jwtToken` — encrypted JWT (optional IP restriction via `isCheckIP` + `ip` field in payload)
110
+ 4. `custom` — user-defined validator (fallback)
111
+
112
+ ## Framework Documentation
113
+
114
+ Detailed fa-mcp-sdk docs are in `FA-MCP-SDK-DOC/`:
115
+
116
+ | File | When to Read |
117
+ |------|-------------|
118
+ | `00-FA-MCP-SDK-index.md` | Quick reference, all exports, project structure |
119
+ | `01-getting-started.md` | `initMcpServer()`, `McpServerData`, `IToolHandlerParams` |
120
+ | `02-1-tools-and-api.md` | Tool definitions, REST API with tsoa |
121
+ | `02-2-prompts-and-resources.md` | Prompts, resources, `ITransportContext` |
122
+ | `03-configuration.md` | `appConfig`, YAML config, DB, cache |
123
+ | `04-authentication.md` | JWT, Basic auth, permanent tokens |
124
+ | `05-ad-authorization.md` | AD group authorization, AD config |
125
+ | `06-utilities.md` | Error handling, logging, Consul |
126
+ | `07-testing-and-operations.md` | Test clients (STDIO, HTTP, SSE, Streamable HTTP) |
127
+ | `08-agent-tester-and-headless-api.md` | Agent Tester, Headless API, structured logging, automated testing |
128
+
129
+ ## Development and Testing Through Agent Tester
130
+
131
+ 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.
132
+
133
+ ### Prerequisites
134
+
135
+ Agent Tester requires an OpenAI API key to call the LLM. Before using it, ensure the following configuration is in place:
136
+
137
+ **Option A** — environment variables (`.env` file or shell):
138
+ ```
139
+ AGENT_TESTER_ENABLED=true
140
+ AGENT_TESTER_OPENAI_API_KEY=sk-...
141
+ ```
142
+
143
+ **Option B** — `config/default.yaml` (or `local.yaml`):
144
+ ```yaml
145
+ agentTester:
146
+ enabled: true
147
+ openAi:
148
+ apiKey: sk-...
149
+ ```
150
+
151
+ **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.
152
+
153
+ **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.
154
+
155
+ ### What Gets Tested
156
+
157
+ - **Tool architecture** — correct tool decomposition (split or merge?)
158
+ - **Agent prompt** — LLM follows desired conversation style
159
+ - **Tool descriptions** — LLM understands when and why to call each tool
160
+ - **Parameter design** — names, types, required/optional intuitive for LLM
161
+ - **Response format** — `formatToolResult()` output interpretable by LLM
162
+ - **Error handling** — agent explains errors clearly
163
+ - **Edge cases** — missing params, invalid values, service unavailability
164
+
165
+ ### Development Workflow
166
+
167
+ Follow this sequence when building or extending an MCP server:
168
+
169
+ #### Step 1: Design Tool Set
170
+
171
+ Define the tools your server will expose. For each tool, decide:
172
+ - **Name** — clear, action-oriented (e.g., `get_currency_rate`, `search_documents`)
173
+ - **Description** — what the tool does and when to use it (the LLM reads this to decide whether to call it)
174
+ - **Parameters** — name, type, required/optional, description including defaults and constraints
175
+ - **Response structure** what data the tool returns
176
+
177
+ Write definitions in `src/tools/tools.ts`. → See `02-1-tools-and-api.md`.
178
+
179
+ #### Step 2: Write Code
180
+
181
+ - `src/tools/handle-tool-call.ts` — tool execution logic (switch on tool name)
182
+ - `src/custom-resources.ts` — MCP resources (if needed)
183
+ - `src/api/router.ts` — REST API endpoints with tsoa decorators (if needed)
184
+ - `config/default.yaml` configuration (DB, auth, access points, etc.)
185
+
186
+ See `01-getting-started.md`, `02-1-tools-and-api.md`, `03-configuration.md`.
187
+
188
+ #### Step 3: Write Agent Prompt and Brief
189
+
190
+ - `src/prompts/agent-brief.ts` — short agent description (shown in tool listings)
191
+ - `src/prompts/agent-prompt.ts` — full system prompt shaping LLM behavior, tool usage logic, and response style
192
+ - `src/prompts/custom-prompts.ts`additional prompts (if needed)
193
+
194
+ The agent prompt is critical — it determines how the LLM uses your tools. → See `02-2-prompts-and-resources.md`.
195
+
196
+ #### Step 4: Write Tests
197
+
198
+ Test files in `tests/mcp/`:
199
+ - `test-cases.js` — shared test cases (tool names, arguments, expected results). **This is the main file to edit** when adding tools.
200
+ - `test-http.js` — HTTP transport tests
201
+ - `test-sse.js` — SSE transport tests
202
+ - `test-stdio.js` STDIO transport tests
203
+
204
+ What to cover in test cases:
205
+ - Happy path for each tool
206
+ - Error cases (invalid params, missing required fields, service errors)
207
+ - Auth flows (if auth enabled)
208
+
209
+ Run tests per transport:
210
+ ```bash
211
+ yarn test:mcp # STDIO
212
+ yarn test:mcp-http # HTTP
213
+ yarn test:mcp-sse # SSE
214
+ ```
215
+
216
+ See `07-testing-and-operations.md`.
217
+
218
+ #### Step 5: Build, Lint, Verify
219
+
220
+ ```bash
221
+ yarn cb # Clean build — fix all compilation errors
222
+ yarn lint:fix # Oxlintfix all lint errors
223
+ yarn format:fix # Oxfmt format the project
224
+ yarn typecheck # tsc --noEmit — fix all type errors
225
+ yarn start # Start server — verify clean startup, no runtime errors
226
+ yarn test:mcp # STDIO transport tests
227
+ yarn test:mcp-http # HTTP transport tests
228
+ yarn test:mcp-sse # SSE transport tests
229
+ ```
230
+
231
+ **Goal**: zero build errors, zero lint errors, zero type errors, clean server startup, all tests green.
232
+
233
+ #### Step 6: Iterative Refinement via Agent Tester
234
+
235
+ Once the server starts cleanly, move to agent-level testing.
236
+ 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:
237
+
238
+ - **Tool descriptions** — if the LLM picks the wrong tool or misunderstands its purpose
239
+ - **Parameter schemas** — if the LLM sends wrong types or misses required params
240
+ - **Agent prompt** — if the LLM doesn't follow the desired conversation style
241
+ - **Handler logic** if tool results confuse the LLM or lack needed information
242
+ - **Error messages** — if failures produce unhelpful agent responses
243
+
244
+ Each iteration: observe → diagnose root cause → fix → `yarn cb && yarn start` → re-test.
245
+
246
+ #### Step 7: Development Report
247
+
248
+ When all tools are implemented, tests pass, and agent testing is complete, create `claudedocs/dev-report.md`:
249
+
250
+ - **What was built** — list of tools, prompts, resources, REST endpoints with brief descriptions
251
+ - **Architecture decisions** — why tools were decomposed a certain way, key design choices
252
+ - **Agent prompt rationale** — what behavior the prompt enforces and why
253
+ - **Test coverage** — which scenarios were tested, which transports
254
+ - **Agent Tester findings** — what was refined during iterative testing (descriptions, schemas, prompt adjustments) and why
255
+ - **Configuration** required config keys, environment variables, external dependencies
256
+ - **Known limitations** — edge cases not covered, planned improvements
257
+
258
+ ### Testing via Headless API (Primary Method)
259
+
260
+ Direct HTTP calls — no browser needed. Provides structured trace data.
261
+
262
+ ```
263
+ 1. yarn cb && yarn start
264
+ 2. GET /agent-tester/api/mcp/status → verify tools loaded
265
+ 3. POST /agent-tester/api/chat/test send message, get response + trace
266
+ 4. Analyze trace: correct tool? correct args? expected result?
267
+ 5. Check trace.system_prompt_sent → verify exact prompt sent to LLM
268
+ 6. If unclear → retry with ?verbose=true
269
+ 7. If issue found fix code rebuild → re-test
270
+ ```
271
+
272
+ Query params: `?verbose=true` (LLM details per turn), `?maxResultChars=8000`, `?maxTraceChars=100000`.
273
+
274
+ **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.
275
+
276
+ Structured JSON logging: `yarn start --log-json` or `AGENT_TESTER_LOG_JSON=true yarn start` — emits per-event JSON on stdout.
277
+
278
+ ### Playwright Testing (Fallback — UI Only)
279
+
280
+ Use only for UI-specific verification (page layout, DOM interaction). For tool testing, use the headless API.
281
+
282
+ ```
283
+ browser_navigate http://localhost:<port>/agent-tester
284
+ browser_snapshotverify page loaded
285
+ browser_type message input
286
+ browser_click → send button
287
+ browser_wait_for → assistant response
288
+ browser_snapshot verify response
289
+ ```
290
+
291
+ ### Testing Log
292
+
293
+ Maintain `claudedocs/test-log.md` during automated testing a chronological narrative of actions, expectations, results, and diagnoses.
294
+
295
+ ```markdown
296
+ # Agent Tester — Test Log
297
+
298
+ ## Session: 2025-08-15
299
+
300
+ ### Iteration 1
301
+
302
+ Server running on port 9876. 3 tools detected.
303
+
304
+ **Testing get_currency_rate basic case**
305
+ Sending: "What is the exchange rate of EUR to USD?"
306
+ Expected: numeric rate, mentions EUR and USD.
307
+ Received: "The current EUR/USD exchange rate is 1.0847"
308
+ Tools used: get_currency_rate
309
+ Result: OK
310
+
311
+ **Testing get_currency_rate invalid currency**
312
+ Sending: "Get rate for XYZ to USD"
313
+ Expected: error message about unknown currency.
314
+ Received: "I couldn't find the exchange rate. The currency code XYZ is not recognized."
315
+ Tools used: get_currency_rate
316
+ Result: OK
317
+
318
+ **Testing get_currency_rate missing base currency default**
319
+ Sending: "What is the rate for THB?"
320
+ Expected: THB/USD rate (baseCurrency defaults to USD).
321
+ Received: "I need to know which currency you want to convert THB to. Could you specify?"
322
+ Tools used: none
323
+ Result: FAIL LLM did not use default baseCurrency, asked for clarification instead.
324
+
325
+ **Diagnosis**: The tool description says "baseCurrency - optional", but doesn't mention the default value.
326
+ **Fix**: Adding "defaults to USD if not specified" to baseCurrency description in tools.ts.
327
+
328
+ Stopping server. Rebuilding...
329
+ Build OK. Server restarted.
330
+
331
+ ### Iteration 2
332
+
333
+ **Re-testing get_currency_rate — missing base currency default**
334
+ Sending: "What is the rate for THB?"
335
+ Received: "The current THB/USD exchange rate is 0.0291"
336
+ Tools used: get_currency_rate
337
+ Result: OK — LLM now uses USD as default.
338
+
339
+ ...
340
+ ```
341
+
342
+ This log serves as:
343
+ - **Audit trail** — what was tested, what passed, what failed
344
+ - **Decision record** — why each change was made (e.g., "changed description because LLM didn't understand default value")
345
+ - **Progress tracker** which tools/scenarios are covered, which remain
346
+ - **Handoff document** — if the session is interrupted, the next session can read the log and continue
347
+
348
+ ## Editing files in `.claude/` (Skill /edit-claude-files)
349
+
350
+ Any edit or new file under `.claude/**` (SKILL.md, scripts, hooks, agents, `settings.json`) is blocked
351
+ by `settings.json` — direct `Write`/`Edit` will fail. Invoke the `/edit-claude-files` skill, which
352
+ describes the required `scripts/fcp.js` temp-copy protocol.
353
+
354
+
355
+ ## Formatting
356
+
357
+ MD lines ≤120 chars. Break at 120. Target 100-120. No short lines (60-80). Fill to ~120.
358
+ Exceptions: URLs, code blocks, tables — no wrap.