fa-mcp-sdk 0.4.13 → 0.4.14

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 (36) hide show
  1. package/cli-template/CLAUDE.md +1 -1
  2. package/cli-template/FA-MCP-SDK-DOC/00-FA-MCP-SDK-index.md +1 -1
  3. package/cli-template/FA-MCP-SDK-DOC/01-getting-started.md +1 -0
  4. package/cli-template/FA-MCP-SDK-DOC/03-configuration.md +5 -0
  5. package/cli-template/FA-MCP-SDK-DOC/04-authentication.md +19 -0
  6. package/cli-template/FA-MCP-SDK-DOC/08-agent-tester-and-headless-api.md +311 -8
  7. package/cli-template/package.json +1 -1
  8. package/config/_local.yaml +15 -3
  9. package/config/custom-environment-variables.yaml +3 -0
  10. package/config/default.yaml +10 -1
  11. package/config/local_.yaml +112 -0
  12. package/dist/core/_types_/config.d.ts +12 -2
  13. package/dist/core/_types_/config.d.ts.map +1 -1
  14. package/dist/core/agent-tester/agent-tester-router.d.ts.map +1 -1
  15. package/dist/core/agent-tester/agent-tester-router.js +39 -1
  16. package/dist/core/agent-tester/agent-tester-router.js.map +1 -1
  17. package/dist/core/auth/agent-tester-auth.d.ts +42 -0
  18. package/dist/core/auth/agent-tester-auth.d.ts.map +1 -0
  19. package/dist/core/auth/agent-tester-auth.js +166 -0
  20. package/dist/core/auth/agent-tester-auth.js.map +1 -0
  21. package/dist/core/auth/middleware.d.ts.map +1 -1
  22. package/dist/core/auth/middleware.js +4 -0
  23. package/dist/core/auth/middleware.js.map +1 -1
  24. package/dist/core/bootstrap/init-config.d.ts.map +1 -1
  25. package/dist/core/bootstrap/init-config.js +3 -0
  26. package/dist/core/bootstrap/init-config.js.map +1 -1
  27. package/dist/core/web/home-api.d.ts.map +1 -1
  28. package/dist/core/web/home-api.js +7 -1
  29. package/dist/core/web/home-api.js.map +1 -1
  30. package/dist/core/web/server-http.d.ts.map +1 -1
  31. package/dist/core/web/server-http.js +6 -6
  32. package/dist/core/web/server-http.js.map +1 -1
  33. package/dist/core/web/static/agent-tester/index.html +94 -47
  34. package/dist/core/web/static/agent-tester/script.js +192 -21
  35. package/dist/core/web/static/agent-tester/styles.css +156 -0
  36. package/package.json +1 -1
@@ -133,7 +133,7 @@ agentTester:
133
133
 
134
134
  **IMPORTANT for Claude Code**: When the development prompt or instructions mention testing with Headless API or Agent Tester, run `npm run 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.
135
135
 
136
- **Disabled state**: If `agentTester.enabled` is `false`, the server returns HTTP 403 on any `/agent-tester/*` request (including the Headless API) with a JSON message explaining how to enable it. When you receive this 403 response, do **NOT** enable Agent Tester yourself — only inform the developer that Agent Tester is currently 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.
136
+ **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.
137
137
 
138
138
  ### What Gets Tested
139
139
 
@@ -20,7 +20,7 @@ npm install fa-mcp-sdk
20
20
  | [05-ad-authorization](05-ad-authorization.md) | AD group authorization at HTTP/tool levels | AD group restrictions |
21
21
  | [06-utilities](06-utilities.md) | `ServerError`, `normalizeHeaders`, logging, Consul, graceful shutdown | Error handling, utilities |
22
22
  | [07-testing-and-operations](07-testing-and-operations.md) | Test clients (STDIO, HTTP, SSE, Streamable HTTP) | Testing, deployment |
23
- | [08-agent-tester-and-headless-api](08-agent-tester-and-headless-api.md) | Agent Tester, Headless API, structured logging, automated testing | Agent-driven tool development, CLI automation |
23
+ | [08-agent-tester-and-headless-api](08-agent-tester-and-headless-api.md) | Agent Tester, Headless API, structured logging, automated testing, UI `data-testid` reference | Agent-driven tool development, CLI automation, UI E2E tests |
24
24
 
25
25
  ## Key Exports
26
26
 
@@ -125,6 +125,7 @@ const dbEnabled = appConfig.isMainDBUsed;
125
125
  | `logger` | Logging config |
126
126
  | `ad` | Active Directory config |
127
127
  | `consul` | Service discovery settings |
128
+ | `homePage` | Home page footer settings (help link) |
128
129
 
129
130
  ### getProjectData(): McpServerData
130
131
 
@@ -119,6 +119,11 @@ swagger:
119
119
  - url: https://{{mcp.domain}}
120
120
  description: "PROD server"
121
121
 
122
+ homePage:
123
+ helpLink:
124
+ url: '' # If empty — help link is not shown in footer
125
+ label: 'Help' # Link text (default: "Help")
126
+
122
127
  uiColor:
123
128
  # Font color of the header and a number of interface elements on the HOME page
124
129
  primary: '#0f65dc'
@@ -150,6 +150,25 @@ const serviceHeadersValidator: CustomAuthValidator = (req) => {
150
150
  > `authInfo` is **not** set on `req` when the validator runs — it is set by the middleware only after
151
151
  > successful authentication completes.
152
152
 
153
+ ## Agent Tester Authentication
154
+
155
+ Protect the Agent Tester (`/agent-tester/*`) with `agentTester.useAuth`:
156
+
157
+ ```yaml
158
+ agentTester:
159
+ useAuth: true # Require authentication for Agent Tester
160
+ webServer:
161
+ auth:
162
+ enabled: true
163
+ permanentServerTokens: ['my-secret-token']
164
+ ```
165
+
166
+ Or via ENV: `AGENT_TESTER_USE_AUTH=true`
167
+
168
+ When `useAuth` is `true`, the full multi-auth middleware is applied to Agent Tester routes — the same authentication used for MCP endpoints (`permanentServerTokens` / `basic` / `jwtToken` / `custom`). Browser users see a login dialog; headless clients pass `Authorization` header directly.
169
+
170
+ See [Agent Tester docs](08-agent-tester-and-headless-api.md#authentication-agenttesteruseauth) for details on the login flow, session management, and API endpoints.
171
+
153
172
  ## AD Group Checking
154
173
 
155
174
  ### Configuration
@@ -49,17 +49,114 @@ Root cause categories:
49
49
  - **Handler logic** — tool results confuse the LLM
50
50
  - **Error messages** — failures produce unhelpful responses
51
51
 
52
+ ## Authentication (`agentTester.useAuth`)
53
+
54
+ When `agentTester.useAuth` is `true`, the Agent Tester is protected by the full multi-auth middleware — the same authentication chain used for MCP endpoints (`permanentServerTokens` / `basic` / `jwtToken` / `custom`).
55
+
56
+ ### How It Works
57
+
58
+ **Browser access:** When a user opens `/agent-tester` in a browser, the page loads normally (static assets are served without auth). The frontend checks `GET /api/auth/status` and displays a **login dialog** if the user is not authenticated. The dialog adapts to configured auth methods:
59
+
60
+ - If `permanentServerTokens` or `jwtToken` is configured — shows a "Token" input
61
+ - If `basic` auth is configured — shows "Username" + "Password" inputs
62
+ - If both are configured — shows tabs to switch between methods
63
+
64
+ After successful login via `POST /api/auth/login`, the server issues an httpOnly session cookie (`__at_sid`). All subsequent API requests from the browser include this cookie automatically. The session is valid for the configured TTL (default: 8 hours — see [Session Lifetime](#session-lifetime) below). A logout button appears in the header.
65
+
66
+ **Headless / CLI access:** Headless API consumers (curl, scripts, Claude Code) bypass the login dialog entirely. They pass an `Authorization` header with each request, which is validated by the standard `authMW`. No session cookie is needed.
67
+
68
+ ### Configuration
69
+
70
+ ```yaml
71
+ agentTester:
72
+ useAuth: true # Show login screen for browser, require auth for API
73
+ sessionTtlMs: 28800000 # Browser session lifetime in ms (default: 8h)
74
+
75
+ webServer:
76
+ auth:
77
+ enabled: true
78
+ permanentServerTokens: ['my-secret-token']
79
+ # and/or basic, jwtToken — any configured method will be available
80
+ ```
81
+
82
+ Environment variables:
83
+
84
+ - `AGENT_TESTER_USE_AUTH=true`
85
+ - `AGENT_TESTER_SESSION_TTL_MS=28800000`
86
+
87
+ When `useAuth` is `false` (default), the Agent Tester is accessible without any authentication and `sessionTtlMs` has no effect.
88
+
89
+ ### Session Lifetime
90
+
91
+ When `useAuth` is `true`, a successful browser login creates a server-side session and sets an httpOnly cookie (`__at_sid`) scoped to `/agent-tester`. Both the in-memory entry and the cookie's `Max-Age` use the same TTL from `agentTester.sessionTtlMs`.
92
+
93
+ **Where sessions live**: an in-memory `Map` inside the server process (`src/core/auth/agent-tester-auth.ts`). There is no disk or Redis persistence — this is intentional because Agent Tester is a development tool, not a production auth system.
94
+
95
+ **Default TTL**: 8 hours (`28_800_000` ms). Override by setting `agentTester.sessionTtlMs` in `config/default.yaml` (or any environment-specific override file), or via `AGENT_TESTER_SESSION_TTL_MS`. Values are in milliseconds; any non-positive or non-finite value falls back to the 8h default.
96
+
97
+ **Cleanup**: a background sweep runs every 30 minutes and drops expired entries from the map. Expired entries are also evicted lazily on access.
98
+
99
+ **Impact of closing the browser or restarting the server**:
100
+
101
+ | Scenario | Re-login required? |
102
+ |---|---|
103
+ | Close tab, reopen within TTL | No — cookie is persistent, server session still live |
104
+ | Close entire browser, reopen within TTL | No — cookie is persistent, server session still live |
105
+ | TTL elapsed since last login | Yes — server drops the entry, responds 401 |
106
+ | Server restart (Ctrl+C, deploy, crash) | Yes — in-memory map is cleared; browser presents an unknown `__at_sid` and the login overlay reappears |
107
+ | User clicks the Logout button | Yes — `POST /api/auth/logout` deletes the entry and clears the cookie |
108
+
109
+ **Tuning guidance**:
110
+
111
+ - **Shorter TTL (e.g. 1 hour = `3600000`)**: more frequent logins, smaller exposure if a workstation is left unlocked.
112
+ - **Longer TTL (e.g. 24 hours = `86400000`)**: fewer interruptions during long development sessions.
113
+ - **Do not set TTL to 0 or a negative value** — the server will silently fall back to the 8h default.
114
+
115
+ > **Note**: the TTL only affects the browser login flow. Headless API access via `Authorization` header is stateless and completely bypasses sessions; it is unaffected by `sessionTtlMs`.
116
+
117
+ ### Auth API Endpoints
118
+
119
+ | Endpoint | Method | Description |
120
+ |----------|--------|-------------|
121
+ | `/api/auth/status` | GET | Returns `{ authRequired, authenticated, methods }` |
122
+ | `/api/auth/login` | POST | Validates credentials, sets session cookie |
123
+ | `/api/auth/logout` | POST | Destroys session, clears cookie |
124
+
125
+ **Login request body:**
126
+
127
+ ```json
128
+ // Token-based (permanent token or JWT)
129
+ { "token": "my-secret-token" }
130
+
131
+ // Basic auth
132
+ { "username": "admin", "password": "secret" }
133
+ ```
134
+
135
+ ### Headless Client Example
136
+
137
+ ```bash
138
+ # Access Agent Tester API with token (no login needed)
139
+ curl -H "Authorization: Bearer my-secret-token" http://localhost:9876/agent-tester/api/mcp/status
140
+
141
+ # Headless test with token
142
+ curl -X POST http://localhost:9876/agent-tester/api/chat/test \
143
+ -H "Authorization: Bearer my-secret-token" \
144
+ -H "Content-Type: application/json" \
145
+ -d '{"message":"Hello","mcpConfig":{"url":"http://localhost:9876/mcp","transport":"http"}}'
146
+ ```
147
+
52
148
  ## Disabled State
53
149
 
54
- When `agentTester.enabled` is `false` (or not set), all `/agent-tester/*` endpoints — including the Headless API — return HTTP 403:
150
+ When `agentTester.enabled` is `false` (or not set), all `/agent-tester/*` endpoints — including the Headless API — return HTTP 404:
55
151
 
56
152
  ```json
57
153
  {
58
- "error": "Agent Tester is disabled",
59
- "message": "The Agent Tester and Headless API are not available because agentTester.enabled is set to false..."
154
+ "error": "Not found"
60
155
  }
61
156
  ```
62
157
 
158
+ This prevents disclosing the existence of the Agent Tester to external users.
159
+
63
160
  To enable, developer can use one of:
64
161
 
65
162
  - **ENV**: `AGENT_TESTER_ENABLED=true`
@@ -69,7 +166,19 @@ To enable, developer can use one of:
69
166
  enabled: true
70
167
  ```
71
168
 
72
- **For Claude Code**: When you receive this 403 response, do **not** enable Agent Tester yourself — only inform the developer that it is disabled and how to enable it. The developer decides whether to turn it on. If the developer's prompt or instructions explicitly say not to mention Agent Tester enablement, respect that and stay silent.
169
+ ### Hiding Footer Link Without Disabling Tester
170
+
171
+ To keep the Agent Tester functional (accessible directly by URL) but hide the link from the home page footer, use `showFooterLink: false`:
172
+
173
+ ```yaml
174
+ agentTester:
175
+ enabled: true
176
+ showFooterLink: false # Tester works, but footer link is hidden
177
+ ```
178
+
179
+ When `showFooterLink` is omitted or `true` (default), the footer link is shown as usual.
180
+
181
+ **For Claude Code**: When you receive a 404 response on `/agent-tester/*`, the Agent Tester may be disabled. Inform the developer and suggest enabling it via `agentTester.enabled: true` in `config/local.yaml` or ENV `AGENT_TESTER_ENABLED=true`. The developer decides whether to turn it on. If the developer's prompt or instructions explicitly say not to mention Agent Tester enablement, respect that and stay silent.
73
182
 
74
183
  ## LLM Availability Check
75
184
 
@@ -269,17 +378,25 @@ Compare `system_prompt_sent` and agent responses between variations to find the
269
378
 
270
379
  The headless API shares sessions with the chat UI. To start a fresh conversation, omit `sessionId`. To continue an existing conversation, pass `sessionId` from a previous response.
271
380
 
272
- ## Structured JSON Logging
381
+ ## Structured JSON Logging (`agentTester.logJson`)
382
+
383
+ When `agentTester.logJson` is `true`, each agent event is emitted as a single-line JSON object on stdout — useful for real-time monitoring, debugging, and log aggregation.
384
+
385
+ Enable via config, CLI flag, or environment variable:
273
386
 
274
- For real-time monitoring of agent events during testing, start the server with the `--log-json` flag:
387
+ ```yaml
388
+ # config/local.yaml
389
+ agentTester:
390
+ logJson: true
391
+ ```
275
392
 
276
393
  ```bash
277
394
  npm start -- --log-json
278
- # or via environment variable:
395
+ # or
279
396
  AGENT_TESTER_LOG_JSON=true npm start
280
397
  ```
281
398
 
282
- Each agent event is emitted as a single-line JSON object on stdout:
399
+ Event types emitted:
283
400
 
284
401
  ```
285
402
  {"event":"tool_call","name":"get_currency_rate","arguments":{"quoteCurrency":"EUR"},"timestamp":"2025-08-15T14:32:00.000Z"}
@@ -322,3 +439,189 @@ The Headless API is designed for CLI automation tools like Claude Code. The typi
322
439
  The Agent Tester also provides a web UI at `/agent-tester` for interactive testing. The UI auto-connects to the local MCP server and auto-fills auth headers if configured.
323
440
 
324
441
  The chat UI uses `POST /api/chat/message` (which returns only the final response). The headless API uses `POST /api/chat/test` (which returns the response plus full trace data). Both share the same underlying agent logic and session storage.
442
+
443
+ ## UI Test Selectors (`data-testid`)
444
+
445
+ For UI automation (Playwright, Cypress, Selenium) the Agent Tester page is annotated with stable `data-testid` attributes. Prefer these over CSS classes, DOM IDs, or label text — they are the documented contract and won't change with styling or copy edits.
446
+
447
+ ### Naming Convention
448
+
449
+ All selectors use the `at-` prefix (short for "agent tester") in kebab-case:
450
+
451
+ ```
452
+ at-<area>-<element>[-<modifier>]
453
+ ```
454
+
455
+ Example: `at-auth-token-input`, `at-server-url`, `at-message-user`, `at-toast-success`.
456
+
457
+ Dynamic elements that map 1:1 to runtime data append the runtime key:
458
+
459
+ ```
460
+ at-header-row-<headerName> e.g. at-header-row-Authorization
461
+ at-header-input-<headerName> e.g. at-header-input-X-Session-Id
462
+ at-message-<sender> e.g. at-message-user, at-message-assistant
463
+ at-toast-<type> e.g. at-toast-success, at-toast-error
464
+ ```
465
+
466
+ ### Selector Reference
467
+
468
+ **Auth overlay (shown when `agentTester.useAuth: true`)**
469
+
470
+ | testid | Element |
471
+ |---|---|
472
+ | `at-auth-overlay` | Root login overlay container |
473
+ | `at-auth-tabs` | Tab switcher (only rendered when multiple methods configured) |
474
+ | `at-auth-tab-token` | "Token" tab button |
475
+ | `at-auth-tab-basic` | "Login" tab button |
476
+ | `at-auth-token-form` | Token login form |
477
+ | `at-auth-token-input` | Token input field |
478
+ | `at-auth-token-submit` | Token submit button |
479
+ | `at-auth-basic-form` | Basic auth form |
480
+ | `at-auth-username` | Username input |
481
+ | `at-auth-password` | Password input |
482
+ | `at-auth-basic-submit` | Basic submit button |
483
+ | `at-auth-error` | Error message container |
484
+
485
+ **App shell**
486
+
487
+ | testid | Element |
488
+ |---|---|
489
+ | `at-app` | Root app container (hidden until authenticated) |
490
+ | `at-sidebar` | Sidebar (configuration panel) |
491
+ | `at-main` | Main chat area |
492
+ | `at-chat-header` | Chat header bar |
493
+
494
+ **Sidebar — connection form**
495
+
496
+ | testid | Element |
497
+ |---|---|
498
+ | `at-connection-form` | MCP connection form |
499
+ | `at-server-url` | MCP server URL input |
500
+ | `at-server-url-dropdown` | Saved URLs dropdown toggle |
501
+ | `at-server-url-dropdown-list` | Saved URLs dropdown panel |
502
+ | `at-server-url-add-new` | "Add new URL" menu item |
503
+ | `at-saved-urls-list` | Container for saved URL items |
504
+ | `at-saved-url-item` | Each saved URL row (dynamic) |
505
+ | `at-saved-url-text` | Clickable URL text within a row |
506
+ | `at-saved-url-delete` | Delete button for a saved URL |
507
+ | `at-transport` | Transport `<select>` (http / sse) |
508
+ | `at-connect-btn` | Connect button |
509
+ | `at-connected-servers` | Connection status bar container |
510
+ | `at-server-status-row` | Status row (dynamic, rendered after connect attempt) |
511
+ | `at-server-status-connected` | "X tools connected" badge |
512
+ | `at-server-status-disconnected` | "Disconnected" badge |
513
+ | `at-disconnect-btn` | Disconnect button |
514
+ | `at-reconnect-btn` | Reconnect button |
515
+
516
+ **Sidebar — HTTP headers section**
517
+
518
+ | testid | Element |
519
+ |---|---|
520
+ | `at-headers-section` | Headers section container |
521
+ | `at-dynamic-headers` | Headers list container |
522
+ | `at-header-row-<name>` | Row for a specific header (e.g. `at-header-row-Authorization`) |
523
+ | `at-header-input-<name>` | Input for a specific header value |
524
+
525
+ **Sidebar — model settings**
526
+
527
+ | testid | Element |
528
+ |---|---|
529
+ | `at-model-section` | Model section container |
530
+ | `at-model-select` | Model `<select>` |
531
+ | `at-custom-model-settings` | "Other..." custom model panel |
532
+ | `at-custom-base-url` | Custom base URL input |
533
+ | `at-custom-api-key` | Custom API key input |
534
+ | `at-custom-model-name` | Custom model name input |
535
+ | `at-model-temperature` | Temperature input |
536
+ | `at-model-max-tokens` | Max tokens input |
537
+ | `at-model-max-turns` | Max turns input |
538
+ | `at-tool-result-limit` | Tool result char limit input |
539
+
540
+ **Sidebar — prompts**
541
+
542
+ | testid | Element |
543
+ |---|---|
544
+ | `at-system-prompt` | Agent (system) prompt `<textarea>` |
545
+ | `at-system-prompt-enlarge` | Enlarge button for agent prompt |
546
+ | `at-custom-prompt` | Custom prompt `<textarea>` |
547
+ | `at-custom-prompt-enlarge` | Enlarge button for custom prompt |
548
+
549
+ **Chat header**
550
+
551
+ | testid | Element |
552
+ |---|---|
553
+ | `at-sidebar-toggle-mobile` | Mobile sidebar toggle |
554
+ | `at-default-format` | Default display format `<select>` (HTML / MD) |
555
+ | `at-theme-toggle` | Light/dark theme toggle |
556
+ | `at-clear-chat` | Clear chat button |
557
+ | `at-logout-btn` | Logout button (visible only when `useAuth` is true) |
558
+
559
+ **Chat area**
560
+
561
+ | testid | Element |
562
+ |---|---|
563
+ | `at-chat-messages` | Messages scroll container |
564
+ | `at-welcome-message` | Initial welcome card |
565
+ | `at-message-user` | User message bubble (one per message) |
566
+ | `at-message-assistant` | Assistant message bubble |
567
+ | `at-message-text-user` | Inner text element of a user message |
568
+ | `at-message-text-assistant` | Inner text element of an assistant message |
569
+ | `at-message-format-toggle` | HTML/MD format toggle on an assistant message |
570
+ | `at-typing-indicator` | Typing indicator (shown during LLM response) |
571
+ | `at-message-input` | Chat input `<textarea>` |
572
+ | `at-char-count` | Character counter span |
573
+ | `at-send-btn` | Send button |
574
+
575
+ **Modals and overlays**
576
+
577
+ | testid | Element |
578
+ |---|---|
579
+ | `at-prompt-modal` | Prompt enlarge modal overlay |
580
+ | `at-prompt-modal-title` | Modal title |
581
+ | `at-prompt-modal-textarea` | Modal text area |
582
+ | `at-prompt-modal-save` | Apply button |
583
+ | `at-prompt-modal-close` | Close button |
584
+ | `at-loading-overlay` | Global loading overlay |
585
+ | `at-header-tooltip` | Floating header description tooltip |
586
+ | `at-toast-container` | Toast notifications container |
587
+ | `at-toast-success` / `at-toast-error` / `at-toast-warning` / `at-toast-info` | Individual toast (dynamic) |
588
+
589
+ ### Usage Examples
590
+
591
+ **Playwright**
592
+
593
+ ```js
594
+ await page.goto('http://localhost:9876/agent-tester');
595
+
596
+ // Login when useAuth is enabled
597
+ await page.getByTestId('at-auth-token-input').fill(process.env.MCP_TOKEN);
598
+ await page.getByTestId('at-auth-token-submit').click();
599
+
600
+ // Wait for main app
601
+ await page.getByTestId('at-app').waitFor();
602
+
603
+ // Send a chat message
604
+ await page.getByTestId('at-message-input').fill('List all tools');
605
+ await page.getByTestId('at-send-btn').click();
606
+
607
+ // Assert an assistant reply appeared
608
+ await page.getByTestId('at-message-assistant').first().waitFor();
609
+ ```
610
+
611
+ **Cypress**
612
+
613
+ ```js
614
+ cy.visit('/agent-tester');
615
+ cy.get('[data-testid=at-auth-token-input]').type(Cypress.env('MCP_TOKEN'));
616
+ cy.get('[data-testid=at-auth-token-submit]').click();
617
+ cy.get('[data-testid=at-server-status-connected]').should('be.visible');
618
+ ```
619
+
620
+ ### Stability Guarantee
621
+
622
+ These test-ids are part of the public contract of the Agent Tester UI. Once added, a given id is not renamed or removed without a changelog entry. New elements are added with new ids as the UI grows. When authoring tests, prefer `data-testid` over:
623
+
624
+ - DOM `id` (may be shared with form `<label for>` pairs and collide across scopes)
625
+ - CSS class names (used for styling — may be renamed or removed during refactors)
626
+ - Visible text (localized / editable copy — changes break tests)
627
+ - XPath or positional selectors (brittle to layout changes)
@@ -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.13"
53
+ "fa-mcp-sdk": "^0.4.14"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/express": "^5.0.6",
@@ -14,10 +14,17 @@ ad:
14
14
 
15
15
  agentTester:
16
16
  enabled: true
17
- useAuth: false
17
+ showFooterLink: true # true (default) — show Agent Tester link in home page footer; false — hide link without disabling tester
18
+ useAuth: false # true — apply full multi-auth middleware (permanentTokens/basic/JWT/custom) to /agent-tester routes, same as MCP endpoints
19
+ sessionTtlMs: 28800000 # Browser login session lifetime in milliseconds. Default: 28800000 (8 hours). Applies only when useAuth is true. Sessions are in-memory on the server — lost on restart.
20
+ logJson: false # true — emit structured JSON events (tool_call, tool_result, llm_response, response) to stdout during agent execution
18
21
  openAi:
19
- apiKey: '***'
20
- # baseURL:
22
+ apiKey: ''
23
+ # baseURL: ''
24
+ httpHeaders:
25
+ # Key-value pairs for HTTP requests that should be auto-populated in agentTester
26
+ # Example: X-User-Id: 12345
27
+
21
28
 
22
29
  # --------------------------------------------------
23
30
  # CACHING Reduces API calls by caching responses
@@ -61,6 +68,11 @@ db:
61
68
  # usedExtensions:
62
69
  # - pgvector
63
70
 
71
+ homePage:
72
+ helpLink:
73
+ url: '' # If empty — help link is not shown in footer
74
+ label: 'Help' # Link text (default: "Help")
75
+
64
76
  logger:
65
77
  level: info
66
78
  useFileLogger: {{logger.useFileLogger}} # To use or not to use logging to a file
@@ -1,6 +1,9 @@
1
1
  agentTester:
2
2
  enabled: AGENT_TESTER_ENABLED
3
3
  useAuth: AGENT_TESTER_USE_AUTH
4
+ sessionTtlMs:
5
+ __name: AGENT_TESTER_SESSION_TTL_MS
6
+ __format: number
4
7
  openAi:
5
8
  apiKey: AGENT_TESTER_OPENAI_API_KEY
6
9
  baseURL: AGENT_TESTER_OPENAI_BASE_URL
@@ -35,7 +35,10 @@ ad:
35
35
 
36
36
  agentTester:
37
37
  enabled: true
38
- useAuth: false
38
+ showFooterLink: true # true (default) — show Agent Tester link in home page footer; false — hide link without disabling tester
39
+ useAuth: false # true — protect Agent Tester with full multi-auth (permanentTokens/basic/JWT/custom); browser users see a login dialog, headless clients pass Authorization header
40
+ sessionTtlMs: 28800000 # Browser login session lifetime in milliseconds. Default: 28800000 (8 hours). Applies only when useAuth is true. Sessions are in-memory on the server — lost on restart.
41
+ logJson: false # true — emit structured JSON events (tool_call, tool_result, llm_response, response) to stdout during agent execution
39
42
  openAi:
40
43
  apiKey: ''
41
44
  # baseURL: ''
@@ -138,6 +141,11 @@ swagger:
138
141
  - url: https://{{mcp.domain}}
139
142
  description: "PROD server"
140
143
 
144
+ homePage:
145
+ helpLink:
146
+ url: '' # If empty — help link is not shown in footer
147
+ label: 'Help' # Link text (default: "Help")
148
+
141
149
  uiColor:
142
150
  # Font color of the header and a number of interface elements on the HOME page
143
151
  primary: '#0f65dc'
@@ -201,3 +209,4 @@ webServer:
201
209
  # For permanentServerTokens, basic, jwtToken - uses credentials from webServer.auth section
202
210
  # For ntlm - uses AD configuration from ad.domains section (no additional credentials needed)
203
211
  type: 'basic'
212
+
@@ -0,0 +1,112 @@
1
+ ---
2
+ agentTester:
3
+ enabled: true
4
+ showFooterLink: true # true (default) — show Agent Tester link in home page footer; false — hide link without disabling tester
5
+ useAuth: true
6
+ openAi:
7
+ apiKey: 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
8
+ apiKeyName: oai-aite-vvmakarov
9
+ baseURL: ''
10
+
11
+ ad:
12
+ domains:
13
+ OFFICE:
14
+ controllers:
15
+ - 'ldap://prdc1.office.finam.ru'
16
+ - 'ldap://prdc2.office.finam.ru'
17
+ default: true
18
+ password: International2025%
19
+ username: aite01-ldap-s
20
+ WTE:
21
+ controllers:
22
+ - 'ldap://prdc1.corp.whotrades.eu'
23
+ - 'ldap://prdc2.corp.whotrades.eu'
24
+ password: International2025%
25
+ username: aite01-ldap-s
26
+
27
+ consul:
28
+ agent:
29
+ dev:
30
+ dc: 'dc-dev'
31
+ host: 'consul.entapp.work'
32
+ token: db56c39b-4b3f-f995-f2e6-6b7c5ab76fa8
33
+ prd:
34
+ dc: 'dc-prd'
35
+ host: 'consul.entapp.work'
36
+ token: 4701c873-9af3-e9a5-cd81-3a0184a5d898
37
+ reg:
38
+ host: MSK-AITE01-AP01.office.finam.ru
39
+ # host: MSK-AITR01-AP01.office.finam.ru
40
+ token: db56c39b-4b3f-f995-f2e6-6b7c5ab76fa8
41
+ service:
42
+ enable: false
43
+ instance: ws1170
44
+ envCode: # Used to generate the service ID
45
+ prod: aitr01
46
+ dev: aite01
47
+
48
+ db:
49
+ postgres:
50
+ dbs:
51
+ main:
52
+ label: 'znayka_dev on DEV-1'
53
+ host: 127.0.0.1
54
+ database: znayka_dev
55
+ port: 5432
56
+ password: Glaui46X49
57
+ user: znayka_dev
58
+ powerPassword: mCyDLHUZhbyj
59
+ powerUser: postgres
60
+ usedExtensions:
61
+ - pgvector
62
+ ssh:
63
+ host: MSK-AITE01-AP01
64
+ port: 22
65
+ username: root
66
+ privateKey: 'C:\Users\vv\.ssh\id_rsa_finam_vvmakarov'
67
+
68
+ homePage:
69
+ helpLink:
70
+ url: 'https://znayka.finam.ru' # If empty — help link is not shown in footer
71
+ label: 'znayka' # Link text (default: "Help")
72
+
73
+ logger:
74
+ level: info
75
+ useFileLogger: false # To use or not to use logging to a file
76
+ dir: ''
77
+
78
+ mcp:
79
+ transportType: http # 'stdio' or 'http'
80
+ toolAnswerAs: text # text | structuredContent
81
+
82
+ swagger:
83
+ servers: # An array of servers that will be added to swagger docs
84
+ - url: http://localhost:9876
85
+ description: "Local server"
86
+
87
+ webServer:
88
+ port: 9876
89
+ auth:
90
+ enabled: true
91
+ # An array of fixed tokens that pass to the MCP (use only for MCPs with green data or for development)
92
+ permanentServerTokens: ['test-perm-token']
93
+ jwtToken:
94
+ # Symmetric encryption key to generate a token for this MCP
95
+ encryptKey: '66666666-7777-8888-9999-000000000000'
96
+ # If webServer.auth.enabled and the parameter true, the service name and the service specified in the token will be checked
97
+ checkMCPName: true
98
+ basic:
99
+ username: vpupkin
100
+ password: '1'
101
+
102
+ # ========================================================================
103
+ # ADMIN PANEL AUTHENTICATION
104
+ # Token generation page available at /admin endpoint
105
+ # Supports 4 authentication methods: permanentServerTokens, basic, jwtToken, ntlm
106
+ # ========================================================================
107
+ adminAuth:
108
+ enabled: false
109
+ # Authentication type for admin panel: 'permanentServerTokens' | 'basic' | 'jwtToken' | 'ntlm'
110
+ # For permanentServerTokens, basic, jwtToken - uses credentials from webServer.auth section
111
+ # For ntlm - uses AD configuration from ad.domains section (no additional credentials needed)
112
+ type: 'jwtToken'
@@ -54,13 +54,23 @@ interface ISwaggerConfig {
54
54
  interface IAgentTesterConfig {
55
55
  agentTester?: {
56
56
  enabled: boolean;
57
+ showFooterLink?: boolean;
57
58
  useAuth: boolean;
59
+ sessionTtlMs?: number;
60
+ logJson?: boolean;
58
61
  openAi?: {
59
62
  apiKey: string;
60
63
  baseURL?: string;
61
64
  };
62
65
  httpHeaders?: Record<string, string>;
63
- logJson?: boolean;
66
+ };
67
+ }
68
+ interface IHomePageConfig {
69
+ homePage?: {
70
+ helpLink?: {
71
+ url: string;
72
+ label?: string;
73
+ };
64
74
  };
65
75
  }
66
76
  interface ICacheConfig {
@@ -69,7 +79,7 @@ interface ICacheConfig {
69
79
  maxItems: 1000;
70
80
  };
71
81
  }
72
- export interface AppConfig extends IADConfig, ICacheConfig, ILoggerConfig, IAFDatabasesConfig, IWebServerConfig, IMCPConfig, ISwaggerConfig, IAgentTesterConfig {
82
+ export interface AppConfig extends IADConfig, ICacheConfig, ILoggerConfig, IAFDatabasesConfig, IWebServerConfig, IMCPConfig, ISwaggerConfig, IAgentTesterConfig, IHomePageConfig {
73
83
  isMainDBUsed: boolean;
74
84
  name: string;
75
85
  shortName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/core/_types_/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/core/_types_/config.ts"],"names":[],"mappings":"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"}