Skip to content

Commit c77adba

Browse files
authored
Merge pull request #285 from deploystackio/main
docs: Update event system and tool discovery
2 parents d41f018 + 7dbbfa9 commit c77adba

File tree

9 files changed

+254
-19
lines changed

9 files changed

+254
-19
lines changed

development/backend/mcp-configuration-architecture.mdx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,20 @@ The catalog defines the configuration structure for each MCP server type:
9191
-- Template Level (with lock controls)
9292
template_args: text('template_args') -- [{value, locked, description}]
9393
template_env: text('template_env') -- Fixed environment variables
94-
template_headers: text('template_headers') -- Fixed HTTP headers (for remotes)
94+
template_headers: text('template_headers') -- Fixed HTTP headers (for HTTP/SSE)
95+
template_url_query_params: text('template_url_query_params') -- Fixed URL query params (for HTTP/SSE)
9596

96-
-- Team Schema (with lock/visibility controls)
97+
-- Team Schema (with lock/visibility controls)
9798
team_args_schema: text('team_args_schema') -- Schema with lock controls
9899
team_env_schema: text('team_env_schema') -- [{name, type, required, default_team_locked, visible_to_users}]
99-
team_headers_schema: text('team_headers_schema') -- HTTP headers schema
100+
team_headers_schema: text('team_headers_schema') -- HTTP headers schema (for HTTP/SSE)
101+
team_url_query_params_schema: text('team_url_query_params_schema') -- URL query params schema (for HTTP/SSE)
100102

101103
-- User Schema
102104
user_args_schema: text('user_args_schema') -- User-configurable argument schema
103105
user_env_schema: text('user_env_schema') -- User-configurable environment schema
104-
user_headers_schema: text('user_headers_schema') -- User HTTP headers schema
106+
user_headers_schema: text('user_headers_schema') -- User HTTP headers schema (for HTTP/SSE)
107+
user_url_query_params_schema: text('user_url_query_params_schema') -- User URL query params schema (for HTTP/SSE)
105108
```
106109

107110
**Transport Configuration:**
@@ -139,6 +142,8 @@ Team installations manage shared configurations:
139142
installation_name: text('installation_name') -- Team-friendly name
140143
team_args: text('team_args') -- Team-level arguments (JSON array)
141144
team_env: text('team_env') -- Team environment variables (JSON object)
145+
team_headers: text('team_headers') -- Team HTTP headers (JSON object, for HTTP/SSE)
146+
team_url_query_params: text('team_url_query_params') -- Team URL query params (JSON object, for HTTP/SSE)
142147
```
143148

144149
### Tier 3: User Configuration (`mcpUserConfigurations`)
@@ -151,6 +156,8 @@ user_id: text('user_id') -- User who owns this config
151156

152157
user_args: text('user_args') -- User arguments (JSON array)
153158
user_env: text('user_env') -- User environment variables (JSON object)
159+
user_headers: text('user_headers') -- User HTTP headers (JSON object, for HTTP/SSE)
160+
user_url_query_params: text('user_url_query_params') -- User URL query params (JSON object, for HTTP/SSE)
154161
```
155162

156163
## Configuration Flow
@@ -270,6 +277,8 @@ Automatically mapped to:
270277
- URL → `template_env` or embedded in remotes config (locked)
271278
- Authentication headers → `team_headers_schema` (secrets)
272279
- Optional headers → `user_headers_schema` (personal preferences)
280+
- API keys in URL query params → `team_url_query_params_schema` (secrets)
281+
- User preferences in query params → `user_url_query_params_schema` (customization)
273282

274283
The transformation layer (`officialRegistryTransforms.ts`) handles all automatic mapping without admin intervention.
275284

development/satellite/architecture.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ The satellite service has completed **Phase 1: MCP Transport Implementation** an
450450
- **Command Processing**: HTTP MCP server management (spawn/kill/restart/health_check)
451451
- **Heartbeat Service**: Process status reporting and system metrics
452452
- **Configuration Sync**: Real-time MCP server configuration updates
453-
- **Event System**: Real-time event emission with automatic batching (10 event types)
453+
- **Event System**: Real-time event emission with automatic batching (13 event types including tool metadata)
454454

455455
**Foundation Infrastructure:**
456456
- **HTTP Server**: Fastify with Swagger documentation

development/satellite/event-system.mdx

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Satellite Components EventBus Backend
6565
**Naming Convention**: All event data fields use **snake_case** (e.g., `server_id`, `team_id`, `spawn_duration_ms`) to match the backend API convention.
6666
</Note>
6767

68-
The satellite emits 12 event types across 4 categories:
68+
The satellite emits 13 event types across 4 categories:
6969

7070
### MCP Server Lifecycle
7171

@@ -226,21 +226,40 @@ Emitted when SSE connection closes (client disconnect, timeout, or error).
226226
### Tool Discovery
227227

228228
#### `mcp.tools.discovered`
229-
Emitted after successful tool discovery from HTTP or stdio MCP server.
229+
Emitted after successful tool discovery from HTTP or stdio MCP server with complete tool metadata and token consumption.
230230

231231
**Data Structure:**
232232
```typescript
233233
{
234-
server_id: string;
235-
server_slug: string;
234+
installation_id: string;
235+
installation_name: string;
236236
team_id: string;
237-
tool_count: number;
238-
tool_names: string[];
239-
discovery_duration_ms: number;
240-
previous_tool_count: number;
237+
server_slug: string;
238+
tool_count: number; // Total tools discovered
239+
total_tokens: number; // Sum of all tool token counts
240+
tools: Array<{
241+
tool_name: string;
242+
description: string;
243+
input_schema: Record<string, unknown>;
244+
token_count: number; // Tokens for this specific tool
245+
}>;
246+
discovered_at: string; // ISO 8601 timestamp
241247
}
242248
```
243249

250+
**Purpose:**
251+
- Store tool metadata in backend database (`mcpToolMetadata` table)
252+
- Calculate hierarchical router token savings (traditional vs 2-meta-tool approach)
253+
- Enable frontend tool catalog display with token consumption metrics
254+
- Provide analytics on MCP server complexity and context window usage
255+
256+
**Emission Timing:**
257+
- stdio servers: After handshake completion and tool caching
258+
- HTTP/SSE servers: After startup tool discovery and caching
259+
260+
**Token Calculation:**
261+
Uses `token-counter.ts` utility to estimate tokens for each tool based on name, description, and input schema JSON.
262+
244263
#### `mcp.tools.updated`
245264
Emitted when tool list changes during configuration refresh.
246265

development/satellite/logging.mdx

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,109 @@ server.log.warn({
323323
- **Add performance metrics**: Duration, resource usage, counts
324324
- **Use consistent naming**: camelCase and standard field names
325325

326+
## Secret Masking in Logs
327+
328+
The satellite automatically protects sensitive credentials in log output through selective secret masking. This prevents API keys, tokens, and passwords from appearing in plain text in log files or monitoring systems.
329+
330+
### How Secret Masking Works
331+
332+
**Automatic Detection:**
333+
- Backend sends metadata with MCP server configurations identifying which fields are secrets
334+
- Satellite receives `secret_metadata` with lists of secret query parameters, headers, and environment variables
335+
- Masking utilities automatically apply to fields marked as secrets
336+
337+
**Masking Pattern:**
338+
- First 3 characters remain visible followed by `*****` (e.g., `sk_abc123xyz789` becomes `sk_*****`)
339+
- Values shorter than 3 characters are fully masked as `***`
340+
- Non-secret values remain fully visible for debugging
341+
342+
### Using the Log Masker Utility
343+
344+
The log masking utilities are located in `src/utils/log-masker.ts` and provide three functions for masking different configuration types:
345+
346+
```typescript
347+
import { maskUrlForLogging, maskHeadersForLogging, maskEnvForLogging } from '../utils/log-masker';
348+
349+
// Example: Mask URL with secret query parameters
350+
const maskedUrl = maskUrlForLogging(
351+
'https://api.example.com?token=sk_abc123&region=us-east',
352+
['token'] // Only 'token' is marked as secret
353+
);
354+
// Result: 'https://api.example.com?token=sk_*****&region=us-east'
355+
356+
// Example: Mask HTTP headers
357+
const maskedHeaders = maskHeadersForLogging(
358+
{ 'Authorization': 'Bearer sk_abc123', 'Content-Type': 'application/json' },
359+
['Authorization'] // Only 'Authorization' is marked as secret
360+
);
361+
// Result: { 'Authorization': 'Bea*****', 'Content-Type': 'application/json' }
362+
```
363+
364+
### Best Practices for Secret Protection
365+
366+
**✅ DO: Use Masking Functions for URLs with Credentials**
367+
368+
```typescript
369+
// ✅ Good - URLs with query parameters masked
370+
server.log.info({
371+
operation: 'mcp_server_connect',
372+
serverId: config.server_slug,
373+
url: maskUrlForLogging(config.url, config.secret_metadata?.query_params),
374+
transport: config.transport_type
375+
}, 'Connecting to MCP server');
376+
```
377+
378+
**✅ DO: Mask Headers Containing Authentication**
379+
380+
```typescript
381+
// ✅ Good - Headers masked before logging
382+
server.log.debug({
383+
operation: 'http_request',
384+
url: maskUrlForLogging(config.url, config.secret_metadata?.query_params),
385+
headers: maskHeadersForLogging(config.headers, config.secret_metadata?.headers)
386+
}, 'Making HTTP request to MCP server');
387+
```
388+
389+
**❌ DON'T: Log Raw Credentials**
390+
391+
```typescript
392+
// ❌ Bad - Exposes credentials in logs
393+
server.log.info({
394+
operation: 'mcp_server_connect',
395+
url: config.url, // Contains API key in query param!
396+
headers: config.headers // Contains Authorization token!
397+
}, 'Connecting to MCP server');
398+
```
399+
400+
### Implementation Locations
401+
402+
Secret masking is implemented in these satellite components:
403+
404+
- **Dynamic Config Manager** (`src/services/dynamic-config-manager.ts`) - 5 locations where MCP server URLs are logged
405+
- **Command Processor** (`src/services/command-processor.ts`) - MCP server spawn and configuration logging
406+
- **HTTP Proxy Manager** (`src/process/http-proxy-manager.ts`) - HTTP/SSE transport logging
407+
- **MCP Server Wrapper** (`src/core/mcp-server-wrapper.ts`) - Server connection and lifecycle logging
408+
- **Remote Tool Discovery** (`src/services/remote-tool-discovery-manager.ts`) - Tool discovery from HTTP servers
409+
410+
### Debugging with Masked Logs
411+
412+
When troubleshooting authentication issues:
413+
414+
1. **Partial visibility helps identify credentials**: First 3 characters show which credential was used
415+
2. **Compare prefixes**: Verify the correct API key/token is being applied
416+
3. **Check non-secret params**: Regular parameters remain visible for debugging
417+
4. **Use secret metadata**: Confirm which fields are marked as secrets in configuration
418+
419+
**Example masked log output:**
420+
421+
```
422+
[INFO] Connecting to MCP server
423+
operation: "mcp_server_connect"
424+
serverId: "brightdata-scraping"
425+
url: "https://mcp-server.brightdata.com?token=sk_*****&region=us-east-1"
426+
headers: {"Authorization":"Bea*****","Content-Type":"application/json"}
427+
```
428+
326429
## Environment-Specific Configuration
327430

328431
### Development Environment

development/satellite/tool-discovery.mdx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,58 @@ stdio tools persist in cache for optimal performance:
231231
**Idle Process Management**: stdio processes that remain inactive for the configured idle timeout (default: 3 minutes) are automatically terminated to save memory. However, **tools remain cached** so when a client requests them, the process respawns instantly without needing to rediscover tools. This reduces respawn time from 1-3 seconds to 1-2 seconds. See [Idle Process Management](/development/satellite/idle-process-management) for details.
232232
</Info>
233233

234+
## Tool Metadata Collection
235+
236+
After tool discovery completes, the satellite emits tool metadata to the backend for storage and analysis.
237+
238+
### Event Emission (Post-Discovery)
239+
240+
Following successful tool discovery (both HTTP/SSE and stdio), the satellite:
241+
242+
1. **Calculates token consumption** using the `token-counter.ts` utility
243+
2. **Builds event payload** with tool metadata including per-tool token counts
244+
3. **Emits `mcp.tools.discovered` event** to backend via EventBus
245+
4. **Backend stores metadata** in `mcpToolMetadata` table for team visibility
246+
247+
**Event Payload Structure:**
248+
```typescript
249+
{
250+
installation_id: string;
251+
installation_name: string;
252+
team_id: string;
253+
server_slug: string;
254+
tool_count: number; // Total tools discovered
255+
total_tokens: number; // Sum of all tool token counts
256+
tools: Array<{
257+
tool_name: string;
258+
description: string;
259+
input_schema: Record<string, unknown>;
260+
token_count: number; // Tokens for this specific tool
261+
}>;
262+
discovered_at: string; // ISO 8601 timestamp
263+
}
264+
```
265+
266+
**Integration Points:**
267+
- `StdioToolDiscoveryManager`: Emits after stdio tool discovery completes
268+
- `RemoteToolDiscoveryManager`: Emits after HTTP/SSE tool discovery completes
269+
- `EventBus`: Batches events every 3 seconds for efficient transmission
270+
- Backend handler: Stores tools with delete-then-insert strategy
271+
272+
**Token Calculation:**
273+
The satellite uses `estimateMcpServerTokens()` from `token-counter.ts` to calculate:
274+
- Per-tool tokens: `name` + `description` + `JSON.stringify(inputSchema)`
275+
- Total server tokens: Sum of all tool tokens
276+
- Uses `gpt-tokenizer` library (provider-agnostic)
277+
278+
**Purpose:**
279+
- Store tool metadata in backend database for team visibility
280+
- Calculate hierarchical router token savings (traditional vs 2-meta-tool approach)
281+
- Enable frontend tool catalog display with token consumption metrics
282+
- Provide analytics on MCP server complexity and context window usage
283+
284+
See [Event System](/development/satellite/event-system) for event batching and delivery details.
285+
234286
## Development Considerations
235287

236288
### Debugging Support

general/mcp-configuration.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,9 @@ Servers synced from the official MCP Registry can use different transport mechan
221221
Servers that run as local processes using standard input/output. Arguments are configured in the template level (locked), with runtime arguments at team/user levels.
222222

223223
**HTTP/SSE Transport (via remotes):**
224-
Servers accessed via HTTP endpoints. Headers are mapped to appropriate tiers - authentication headers at team level, optional headers at user level.
224+
Servers accessed via HTTP endpoints. Both headers and URL query parameters are mapped to appropriate tiers:
225+
- **HTTP Headers** - Authentication headers at team level, optional headers at user level
226+
- **URL Query Parameters** - API keys and tokens at team level, personal preferences at user level
225227

226228
The three-tier system adapts automatically based on the transport type detected from the official registry.
227229

general/security.mdx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,45 @@ DeployStack automatically protects sensitive MCP configuration values through a
7878
- **Audit Safe**: Logs and interfaces never contain actual secret values
7979
- **Team Security**: Team members use secrets without seeing actual values
8080

81+
### Satellite Log Masking
82+
83+
DeployStack satellites automatically protect sensitive values in log files and monitoring systems through selective secret masking:
84+
85+
**Automatic Secret Detection:**
86+
- **Backend Metadata**: Control plane identifies which configuration fields contain secrets based on schema definitions
87+
- **Secret Transmission**: Backend sends metadata to satellites indicating which query parameters, headers, and environment variables are secrets
88+
- **Selective Masking**: Satellites mask only fields marked as secrets, leaving regular configuration visible for debugging
89+
90+
**Masking Pattern:**
91+
- **Partial Visibility**: First 3 characters of secret values remain visible (e.g., `sk_*****`)
92+
- **Short Values**: Values shorter than 3 characters are fully masked as `***`
93+
- **Context Preservation**: Masked logs still show which parameters were used without exposing actual values
94+
95+
**What Gets Masked in Logs:**
96+
- URL query parameters containing API keys or tokens
97+
- HTTP headers with authentication credentials
98+
- Environment variables marked as secret type
99+
- Any configuration field transmitted with secret metadata
100+
101+
**What Doesn't Get Masked:**
102+
- Regular configuration values (debug flags, URLs without secrets)
103+
- Server names and installation identifiers
104+
- Non-sensitive query parameters and headers
105+
- Status codes and timing information
106+
107+
**Security Benefits:**
108+
- **Log Safety**: Satellite logs can be safely shared for debugging without exposing credentials
109+
- **Monitoring Protection**: Log aggregation systems won't capture plaintext secrets
110+
- **Audit Trail**: Logs show which credentials were used without revealing actual values
111+
- **Incident Response**: Security teams can analyze logs without credential exposure risk
112+
113+
**Example Masked Log Output:**
114+
```
115+
[INFO] Connecting to MCP server: brightdata-scraping-browser
116+
URL: https://mcp-server.brightdata.com?token=sk_*****&region=us-east-1
117+
Headers: Authorization=Bea*****
118+
```
119+
81120
### Global Settings Encryption
82121
Your global configuration data is protected with encryption:
83122

package-lock.json

Lines changed: 15 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
},
1212
"dependencies": {},
1313
"devDependencies": {
14-
"@semantic-release/github": "^12.0.1",
14+
"@semantic-release/github": "^12.0.2",
1515
"@types/node": "24.9.1",
1616
"markdownlint-cli": "^0.45.0",
1717
"markdownlint-cli2": "^0.18.1",

0 commit comments

Comments
 (0)