forked from smart-mcp-proxy/mcpproxy-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtypes.go
More file actions
840 lines (743 loc) · 38.7 KB
/
types.go
File metadata and controls
840 lines (743 loc) · 38.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
// Package contracts defines typed data transfer objects for API communication
package contracts
import (
"time"
)
// APIResponse is the standard wrapper for all API responses
type APIResponse struct {
Success bool `json:"success"`
Data interface{} `json:"data,omitempty" swaggertype:"object"`
Error string `json:"error,omitempty"`
RequestID string `json:"request_id,omitempty"`
}
// Server represents an upstream MCP server configuration and status
type Server struct {
ID string `json:"id"`
Name string `json:"name"`
URL string `json:"url,omitempty"`
Protocol string `json:"protocol"`
Command string `json:"command,omitempty"`
Args []string `json:"args,omitempty"`
WorkingDir string `json:"working_dir,omitempty"`
Env map[string]string `json:"env,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
OAuth *OAuthConfig `json:"oauth,omitempty"`
Enabled bool `json:"enabled"`
Quarantined bool `json:"quarantined"`
Connected bool `json:"connected"`
Connecting bool `json:"connecting"`
Status string `json:"status"`
LastError string `json:"last_error,omitempty"`
ConnectedAt *time.Time `json:"connected_at,omitempty"`
LastReconnectAt *time.Time `json:"last_reconnect_at,omitempty"`
ReconnectCount int `json:"reconnect_count"`
ToolCount int `json:"tool_count"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Isolation *IsolationConfig `json:"isolation,omitempty"`
// IsolationDefaults exposes the resolved baseline values that
// would apply when no per-server override is set. Populated on
// list/get responses; never consumed on PATCH requests.
IsolationDefaults *IsolationDefaults `json:"isolation_defaults,omitempty"`
Authenticated bool `json:"authenticated"` // OAuth authentication status
OAuthStatus string `json:"oauth_status,omitempty"` // OAuth status: "authenticated", "expired", "error", "none"
TokenExpiresAt *time.Time `json:"token_expires_at,omitempty"` // When the OAuth token expires (ISO 8601)
ToolListTokenSize int `json:"tool_list_token_size,omitempty"` // Token size for this server's tools
ShouldRetry bool `json:"should_retry,omitempty"`
RetryCount int `json:"retry_count,omitempty"`
LastRetryTime *time.Time `json:"last_retry_time,omitempty"`
UserLoggedOut bool `json:"user_logged_out,omitempty"` // True if user explicitly logged out (prevents auto-reconnection)
Health *HealthStatus `json:"health,omitempty"` // Unified health status calculated by the backend
Quarantine *QuarantineStats `json:"quarantine,omitempty"` // Tool quarantine metrics for this server
ReconnectOnUse bool `json:"reconnect_on_use,omitempty"` // Attempt reconnection when a tool call targets this disconnected server
SecurityScan *SecurityScanSummary `json:"security_scan,omitempty"` // Latest security scan results summary
// Spec 044 — structured diagnostic error and stable error code. Both
// are populated when the server is in a failed state and the error
// has been classified by internal/diagnostics. Healthy servers omit
// these fields.
Diagnostic *Diagnostic `json:"diagnostic,omitempty"`
ErrorCode string `json:"error_code,omitempty"`
}
// Diagnostic is the REST-API representation of a classified server failure.
// It is additive: clients that pre-date spec 044 simply ignore it.
type Diagnostic struct {
Code string `json:"code"`
Severity string `json:"severity"`
Cause string `json:"cause,omitempty"`
DetectedAt *time.Time `json:"detected_at,omitempty"`
UserMessage string `json:"user_message,omitempty"`
FixSteps []DiagnosticFixStep `json:"fix_steps,omitempty"`
DocsURL string `json:"docs_url,omitempty"`
}
// DiagnosticFixStep mirrors internal/diagnostics.FixStep for the REST API.
type DiagnosticFixStep struct {
Type string `json:"type"`
Label string `json:"label"`
Command string `json:"command,omitempty"`
URL string `json:"url,omitempty"`
FixerKey string `json:"fixer_key,omitempty"`
Destructive bool `json:"destructive,omitempty"`
}
// SecurityScanSummary provides a compact scan status for the server list view.
type SecurityScanSummary struct {
LastScanAt *time.Time `json:"last_scan_at,omitempty"`
RiskScore int `json:"risk_score"` // 0-100
Status string `json:"status"` // "clean", "warnings", "dangerous", "failed", "not_scanned", "scanning"
FindingCounts *FindingCounts `json:"finding_counts,omitempty"`
}
// FindingCounts groups findings by user-facing threat category.
type FindingCounts struct {
Dangerous int `json:"dangerous"` // Tool poisoning, active prompt injection
Warning int `json:"warning"` // Rug pull, supply chain CVEs with exploits
Info int `json:"info"` // Low-severity CVEs, informational
Total int `json:"total"`
}
// QuarantineStats represents tool quarantine metrics for a server.
type QuarantineStats struct {
PendingCount int `json:"pending_count"` // Number of newly discovered tools awaiting approval
ChangedCount int `json:"changed_count"` // Number of tools whose description/schema changed since approval
BlockedCount int `json:"blocked_count"` // Number of disabled (blocked) tools
}
// OAuthConfig represents OAuth configuration for a server
type OAuthConfig struct {
AuthURL string `json:"auth_url"`
TokenURL string `json:"token_url"`
ClientID string `json:"client_id"`
Scopes []string `json:"scopes,omitempty"`
ExtraParams map[string]string `json:"extra_params,omitempty"`
RedirectPort int `json:"redirect_port,omitempty"`
PKCEEnabled bool `json:"pkce_enabled,omitempty"`
TokenExpiresAt *time.Time `json:"token_expires_at,omitempty"` // When the OAuth token expires
TokenValid bool `json:"token_valid,omitempty"` // Whether token is currently valid
}
// IsolationConfig represents Docker isolation configuration as it is
// exposed over the REST API. Mirrors the per-server overrides in
// config.IsolationConfig so the web UI and native tray can both edit
// these fields without reaching into config-file internals.
type IsolationConfig struct {
Enabled bool `json:"enabled"`
Image string `json:"image,omitempty"`
NetworkMode string `json:"network_mode,omitempty"`
ExtraArgs []string `json:"extra_args,omitempty"`
MemoryLimit string `json:"memory_limit,omitempty"`
CPULimit string `json:"cpu_limit,omitempty"`
WorkingDir string `json:"working_dir,omitempty"`
Timeout string `json:"timeout,omitempty"`
}
// IsolationDefaults reports the resolved baseline Docker isolation
// settings for a server's detected runtime. UI clients (web UI, macOS
// tray) use this to render meaningful placeholders for the override
// fields — e.g. when a Python/uvx server has no Image override, the
// placeholder shows the actual image (`ghcr.io/astral-sh/uv:python3.13-...`)
// that will be used. This makes the "empty = inherit" semantic
// discoverable instead of mysterious.
//
// All fields are read-only outputs; clients must not echo them back on
// PATCH requests. They are computed from the global DockerIsolationConfig
// + the server's command (via runtime detection) on every server-list
// response.
type IsolationDefaults struct {
RuntimeType string `json:"runtime_type,omitempty"`
Image string `json:"image,omitempty"`
NetworkMode string `json:"network_mode,omitempty"`
ExtraArgs []string `json:"extra_args,omitempty"`
WorkingDir string `json:"working_dir,omitempty"`
}
// ToolAnnotation represents MCP tool behavior hints
type ToolAnnotation struct {
Title string `json:"title,omitempty"`
ReadOnlyHint *bool `json:"readOnlyHint,omitempty"`
DestructiveHint *bool `json:"destructiveHint,omitempty"`
IdempotentHint *bool `json:"idempotentHint,omitempty"`
OpenWorldHint *bool `json:"openWorldHint,omitempty"`
}
// MCPSession represents a client session with MCPProxy
type MCPSession struct {
ID string `json:"id"`
ClientName string `json:"client_name,omitempty"`
ClientVersion string `json:"client_version,omitempty"`
Status string `json:"status"`
StartTime time.Time `json:"start_time"`
EndTime *time.Time `json:"end_time,omitempty"`
LastActivity time.Time `json:"last_activity"`
ToolCallCount int `json:"tool_call_count"`
TotalTokens int `json:"total_tokens"`
// MCP Client Capabilities
HasRoots bool `json:"has_roots,omitempty"`
HasSampling bool `json:"has_sampling,omitempty"`
Experimental []string `json:"experimental,omitempty"`
}
// Tool represents an MCP tool with its metadata
type Tool struct {
Name string `json:"name"`
ServerName string `json:"server_name"`
Description string `json:"description"`
Schema map[string]interface{} `json:"schema,omitempty" swaggertype:"object"`
Usage int `json:"usage"`
LastUsed *time.Time `json:"last_used,omitempty"`
Annotations *ToolAnnotation `json:"annotations,omitempty"`
ApprovalStatus string `json:"approval_status,omitempty"`
// Disabled mirrors ToolApprovalRecord.Disabled so per-tool enable state is
// available without a second round-trip to the approvals endpoint. Absent
// in the JSON when false (default) to keep responses compact.
Disabled bool `json:"disabled,omitempty"`
// ConfigDenied is true when the tool is denied by the server's static
// enabled_tools / disabled_tools config. The user cannot override this toggle.
ConfigDenied bool `json:"config_denied,omitempty"`
}
// SearchResult represents a search result for tools
type SearchResult struct {
Tool Tool `json:"tool"`
Score float64 `json:"score"`
Snippet string `json:"snippet,omitempty"`
Matches int `json:"matches"`
}
// ServerStats represents aggregated statistics about servers
type ServerStats struct {
TotalServers int `json:"total_servers"`
ConnectedServers int `json:"connected_servers"`
QuarantinedServers int `json:"quarantined_servers"`
TotalTools int `json:"total_tools"`
DockerContainers int `json:"docker_containers"`
TokenMetrics *ServerTokenMetrics `json:"token_metrics,omitempty"`
}
// ServerTokenMetrics represents token usage and savings metrics
type ServerTokenMetrics struct {
TotalServerToolListSize int `json:"total_server_tool_list_size"` // All upstream tools combined (tokens)
AverageQueryResultSize int `json:"average_query_result_size"` // Typical retrieve_tools output (tokens)
SavedTokens int `json:"saved_tokens"` // Difference
SavedTokensPercentage float64 `json:"saved_tokens_percentage"` // Percentage saved
PerServerToolListSizes map[string]int `json:"per_server_tool_list_sizes"` // Token size per server
}
// LogEntry represents a single log entry
type LogEntry struct {
Timestamp time.Time `json:"timestamp"`
Level string `json:"level"`
Message string `json:"message"`
Server string `json:"server,omitempty"`
Fields map[string]interface{} `json:"fields,omitempty" swaggertype:"object"`
}
// SystemStatus represents the overall system status
type SystemStatus struct {
Phase string `json:"phase"`
Message string `json:"message"`
Uptime time.Duration `json:"uptime"`
StartedAt time.Time `json:"started_at"`
ConfigPath string `json:"config_path"`
LogDir string `json:"log_dir"`
Runtime RuntimeStatus `json:"runtime"`
Servers ServerStats `json:"servers"`
}
// RuntimeStatus represents runtime-specific status information
type RuntimeStatus struct {
Version string `json:"version"`
GoVersion string `json:"go_version"`
BuildTime string `json:"build_time,omitempty"`
IndexStatus string `json:"index_status"`
StorageStatus string `json:"storage_status"`
LastConfigLoad time.Time `json:"last_config_load"`
}
// ToolCallRequest represents a request to call a tool
type ToolCallRequest struct {
ToolName string `json:"tool_name"`
Args map[string]interface{} `json:"args" swaggertype:"object"`
}
// ToolCallResponse represents the response from a tool call
type ToolCallResponse struct {
ToolName string `json:"tool_name"`
ServerName string `json:"server_name"`
Result interface{} `json:"result" swaggertype:"object"`
Error string `json:"error,omitempty"`
Duration string `json:"duration"`
Timestamp time.Time `json:"timestamp"`
}
// Event represents a system event for SSE streaming
type Event struct {
Type string `json:"type"`
Data interface{} `json:"data" swaggertype:"object"`
Server string `json:"server,omitempty"`
Timestamp time.Time `json:"timestamp"`
Metadata map[string]interface{} `json:"metadata,omitempty" swaggertype:"object"`
}
// API Request/Response DTOs
// GetServersResponse is the response for GET /api/v1/servers
type GetServersResponse struct {
Servers []Server `json:"servers"`
Stats ServerStats `json:"stats"`
}
// GetServerToolsResponse is the response for GET /api/v1/servers/{id}/tools
type GetServerToolsResponse struct {
ServerName string `json:"server_name"`
Tools []Tool `json:"tools"`
Count int `json:"count"`
}
// SearchToolsResponse is the response for GET /api/v1/index/search
type SearchToolsResponse struct {
Query string `json:"query"`
Results []SearchResult `json:"results"`
Total int `json:"total"`
Took string `json:"took"`
}
// GetServerLogsResponse is the response for GET /api/v1/servers/{id}/logs
type GetServerLogsResponse struct {
ServerName string `json:"server_name"`
Logs []LogEntry `json:"logs"`
Count int `json:"count"`
}
// ServerActionResponse is the response for server enable/disable/restart actions
type ServerActionResponse struct {
Server string `json:"server"`
Action string `json:"action"`
Success bool `json:"success"`
Async bool `json:"async,omitempty"`
}
// QuarantinedServersResponse is the response for quarantined servers
type QuarantinedServersResponse struct {
Servers []Server `json:"servers"`
Count int `json:"count"`
}
// Secret management DTOs
// Ref represents a reference to a secret value
type Ref struct {
Type string `json:"type"` // "env", "keyring", etc.
Name string `json:"name"` // The secret name/key
Original string `json:"original"` // Original reference string like "${env:API_KEY}"
}
// MigrationCandidate represents a potential secret that could be migrated to secure storage
type MigrationCandidate struct {
Field string `json:"field"` // Field path in configuration
Value string `json:"value"` // Masked value for display
Suggested string `json:"suggested"` // Suggested secret reference
Confidence float64 `json:"confidence"` // Confidence score (0.0 to 1.0)
}
// MigrationAnalysis represents the result of analyzing configuration for potential secrets
type MigrationAnalysis struct {
Candidates []MigrationCandidate `json:"candidates"`
TotalFound int `json:"total_found"`
}
// GetRefsResponse is the response for GET /api/v1/secrets/refs
type GetRefsResponse struct {
Refs []Ref `json:"refs"`
}
// GetMigrationAnalysisResponse is the response for POST /api/v1/secrets/migrate
type GetMigrationAnalysisResponse struct {
Analysis MigrationAnalysis `json:"analysis"`
}
// Diagnostics types
// DiagnosticIssue represents a single diagnostic issue
type DiagnosticIssue struct {
Type string `json:"type"` // error, warning, info
Category string `json:"category"` // oauth, connection, secrets, config
Server string `json:"server,omitempty"` // Associated server (if any)
Title string `json:"title"` // Short title
Message string `json:"message"` // Detailed message
Timestamp time.Time `json:"timestamp"` // When detected
Severity string `json:"severity"` // critical, high, medium, low
Metadata map[string]interface{} `json:"metadata,omitempty" swaggertype:"object"` // Additional context
}
// MissingSecret represents an unresolved secret reference
type MissingSecret struct {
Name string `json:"name"` // Variable/secret name
Reference string `json:"reference"` // Original reference (e.g., "${env:API_KEY}")
Server string `json:"server"` // Which server needs it
Type string `json:"type"` // env, keyring, etc.
}
// DiagnosticsResponse represents the aggregated diagnostics
type DiagnosticsResponse struct {
UpstreamErrors []DiagnosticIssue `json:"upstream_errors"`
OAuthRequired []string `json:"oauth_required"` // Server names
MissingSecrets []MissingSecret `json:"missing_secrets"`
RuntimeWarnings []DiagnosticIssue `json:"runtime_warnings"`
TotalIssues int `json:"total_issues"`
LastUpdated time.Time `json:"last_updated"`
}
// Diagnostics represents aggregated health information from all MCPProxy components.
// This is the new unified diagnostics format for the management service.
type Diagnostics struct {
TotalIssues int `json:"total_issues"`
UpstreamErrors []UpstreamError `json:"upstream_errors"`
OAuthRequired []OAuthRequirement `json:"oauth_required"`
OAuthIssues []OAuthIssue `json:"oauth_issues"` // OAuth parameter mismatches
MissingSecrets []MissingSecretInfo `json:"missing_secrets"` // Renamed to avoid conflict
RuntimeWarnings []string `json:"runtime_warnings"`
DeprecatedConfigs []DeprecatedConfigWarning `json:"deprecated_configs,omitempty"` // Deprecated config fields found
DockerStatus *DockerStatus `json:"docker_status,omitempty"`
Timestamp time.Time `json:"timestamp"`
}
// DeprecatedConfigWarning represents a deprecated configuration field found in the config file.
type DeprecatedConfigWarning struct {
Field string `json:"field"`
Message string `json:"message"`
Replacement string `json:"replacement,omitempty"`
}
// UpstreamError represents a connection or runtime error from an upstream MCP server.
type UpstreamError struct {
ServerName string `json:"server_name"`
ErrorMessage string `json:"error_message"`
Timestamp time.Time `json:"timestamp"`
}
// OAuthRequirement represents an OAuth authentication requirement for a server.
type OAuthRequirement struct {
ServerName string `json:"server_name"`
State string `json:"state"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Message string `json:"message"`
}
// OAuthIssue represents an OAuth configuration issue (e.g., missing parameters).
type OAuthIssue struct {
ServerName string `json:"server_name"`
Issue string `json:"issue"`
Error string `json:"error"`
MissingParams []string `json:"missing_params,omitempty"`
Resolution string `json:"resolution"`
DocumentationURL string `json:"documentation_url,omitempty"`
}
// MissingSecretInfo represents a secret referenced in configuration but not found.
// This is used by the new Diagnostics type to avoid field name conflicts.
type MissingSecretInfo struct {
SecretName string `json:"secret_name"`
UsedBy []string `json:"used_by"`
}
// DockerStatus represents the availability of Docker daemon for stdio server isolation.
type DockerStatus struct {
Available bool `json:"available"`
Version string `json:"version,omitempty"`
Error string `json:"error,omitempty"`
}
// AuthStatus represents detailed OAuth authentication status for a single server.
type AuthStatus struct {
ServerName string `json:"server_name"`
State string `json:"state"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
TokenType string `json:"token_type,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Message string `json:"message"`
}
// OAuthStartResponse is returned by POST /api/v1/servers/{id}/login when OAuth flow starts successfully.
// Spec 020: OAuth Login Error Feedback
type OAuthStartResponse struct {
Success bool `json:"success"` // Always true for successful start
ServerName string `json:"server_name"` // Name of the server being authenticated
CorrelationID string `json:"correlation_id"` // UUID for tracking this flow
AuthURL string `json:"auth_url,omitempty"` // Authorization URL (always included for manual use)
BrowserOpened bool `json:"browser_opened"` // Whether browser launch succeeded
BrowserError string `json:"browser_error,omitempty"` // Error message if browser launch failed
Message string `json:"message"` // Human-readable status message
}
// OAuthValidationError is returned for pre-flight validation failures before OAuth is attempted.
// Returned with HTTP 400.
// Implements the error interface so it can be returned as an error while carrying structured data.
// Spec 020: OAuth Login Error Feedback
type OAuthValidationError struct {
Success bool `json:"success"` // Always false
ErrorType string `json:"error_type"` // Category of validation failure
ServerName string `json:"server_name"` // Requested server name
Message string `json:"message"` // Human-readable error description
Suggestion string `json:"suggestion"` // Actionable remediation hint
AvailableServers []string `json:"available_servers,omitempty"` // List of valid server names (for server_not_found)
CorrelationID string `json:"correlation_id,omitempty"` // Existing flow ID (for flow_in_progress)
}
// Error implements the error interface for OAuthValidationError.
func (e *OAuthValidationError) Error() string {
return e.Message
}
// NewOAuthValidationError creates a new OAuthValidationError with the given parameters.
func NewOAuthValidationError(serverName, errorType, message, suggestion string) *OAuthValidationError {
return &OAuthValidationError{
Success: false,
ServerName: serverName,
ErrorType: errorType,
Message: message,
Suggestion: suggestion,
}
}
// OAuthFlowError is returned for OAuth runtime failures (after validation passes but before browser opens).
// Examples: metadata discovery failure, DCR failure, authorization URL construction failure.
// Implements the error interface so it can be returned as an error while carrying structured data.
// Spec 020: OAuth Login Error Feedback
type OAuthFlowError struct {
Success bool `json:"success"` // Always false
ErrorType string `json:"error_type"` // Category of OAuth runtime failure
ErrorCode string `json:"error_code"` // Machine-readable error code (e.g., OAUTH_NO_METADATA)
ServerName string `json:"server_name"` // Server that failed OAuth
CorrelationID string `json:"correlation_id"` // Flow tracking ID for log correlation
RequestID string `json:"request_id"` // HTTP request ID (from PR #237)
Message string `json:"message"` // Human-readable error description
Details *OAuthErrorDetails `json:"details,omitempty"` // Structured discovery/failure details
Suggestion string `json:"suggestion"` // Actionable remediation hint
DebugHint string `json:"debug_hint"` // CLI command for log lookup
}
// Error implements the error interface for OAuthFlowError.
func (e *OAuthFlowError) Error() string {
return e.Message
}
// NewOAuthFlowError creates a new OAuthFlowError with the given parameters.
func NewOAuthFlowError(serverName, errorType, errorCode, message, suggestion string) *OAuthFlowError {
return &OAuthFlowError{
Success: false,
ServerName: serverName,
ErrorType: errorType,
ErrorCode: errorCode,
Message: message,
Suggestion: suggestion,
DebugHint: "For logs: mcpproxy upstream logs " + serverName,
}
}
// OAuthErrorDetails contains structured discovery/failure details for OAuth errors.
type OAuthErrorDetails struct {
ServerURL string `json:"server_url"`
ProtectedResourceMetadata *MetadataStatus `json:"protected_resource_metadata,omitempty"`
AuthorizationServerMetadata *MetadataStatus `json:"authorization_server_metadata,omitempty"`
DCRStatus *DCRStatus `json:"dcr_status,omitempty"`
}
// MetadataStatus represents the status of OAuth metadata discovery.
type MetadataStatus struct {
Found bool `json:"found"`
URLChecked string `json:"url_checked"`
Error string `json:"error,omitempty"`
AuthorizationServers []string `json:"authorization_servers,omitempty"`
}
// DCRStatus represents the status of Dynamic Client Registration.
type DCRStatus struct {
Attempted bool `json:"attempted"`
Success bool `json:"success"`
StatusCode int `json:"status_code,omitempty"`
Error string `json:"error,omitempty"`
}
// OAuth validation error type constants
const (
OAuthValidationServerNotFound = "server_not_found"
OAuthValidationServerDisabled = "server_disabled"
OAuthValidationServerQuarantined = "server_quarantined"
OAuthValidationNotSupported = "oauth_not_supported"
OAuthValidationFlowInProgress = "flow_in_progress"
)
// OAuth flow error type constants
const (
OAuthErrorMetadataMissing = "oauth_metadata_missing"
OAuthErrorMetadataInvalid = "oauth_metadata_invalid"
OAuthErrorResourceMismatch = "oauth_resource_mismatch"
OAuthErrorClientIDRequired = "oauth_client_id_required"
OAuthErrorDCRFailed = "oauth_dcr_failed"
OAuthErrorFlowFailed = "oauth_flow_failed"
)
// OAuth flow error code constants (machine-readable)
const (
OAuthCodeNoMetadata = "OAUTH_NO_METADATA"
OAuthCodeBadMetadata = "OAUTH_BAD_METADATA"
OAuthCodeResourceMismatch = "OAUTH_RESOURCE_MISMATCH"
OAuthCodeNoClientID = "OAUTH_NO_CLIENT_ID"
OAuthCodeDCRFailed = "OAUTH_DCR_FAILED"
OAuthCodeFlowFailed = "OAUTH_FLOW_FAILED"
)
// OAuth Authentication State Constants
const (
AuthStateAuthenticated = "authenticated"
AuthStateUnauthenticated = "unauthenticated"
AuthStateExpired = "expired"
AuthStateRefreshing = "refreshing"
)
// Tool Call History types
// TokenMetrics represents token usage statistics for a tool call
type TokenMetrics struct {
InputTokens int `json:"input_tokens"` // Tokens in the request
OutputTokens int `json:"output_tokens"` // Tokens in the response
TotalTokens int `json:"total_tokens"` // Total tokens (input + output)
Model string `json:"model"` // Model used for tokenization
Encoding string `json:"encoding"` // Encoding used (e.g., cl100k_base)
EstimatedCost float64 `json:"estimated_cost,omitempty"` // Optional cost estimate
TruncatedTokens int `json:"truncated_tokens,omitempty"` // Tokens removed by truncation
WasTruncated bool `json:"was_truncated"` // Whether response was truncated
}
// ToolCallRecord represents a single recorded tool call with full context
type ToolCallRecord struct {
ID string `json:"id"` // Unique identifier
ServerID string `json:"server_id"` // Server identity hash
ServerName string `json:"server_name"` // Human-readable server name
ToolName string `json:"tool_name"` // Tool name (without server prefix)
Arguments map[string]interface{} `json:"arguments" swaggertype:"object"` // Tool arguments
Response interface{} `json:"response,omitempty" swaggertype:"object"` // Tool response (success only)
Error string `json:"error,omitempty"` // Error message (failure only)
Duration int64 `json:"duration"` // Duration in nanoseconds
Timestamp time.Time `json:"timestamp"` // When the call was made
ConfigPath string `json:"config_path"` // Active config file path
RequestID string `json:"request_id,omitempty"` // Request correlation ID
Metrics *TokenMetrics `json:"metrics,omitempty"` // Token usage metrics (nil for older records)
ParentCallID string `json:"parent_call_id,omitempty"` // Links nested calls to parent code_execution
ExecutionType string `json:"execution_type,omitempty"` // "direct" or "code_execution"
MCPSessionID string `json:"mcp_session_id,omitempty"` // MCP session identifier
MCPClientName string `json:"mcp_client_name,omitempty"` // MCP client name from InitializeRequest
MCPClientVersion string `json:"mcp_client_version,omitempty"` // MCP client version
Annotations *ToolAnnotation `json:"annotations,omitempty"` // Tool behavior hints snapshot
}
// GetToolCallsResponse is the response for GET /api/v1/tool-calls
type GetToolCallsResponse struct {
ToolCalls []ToolCallRecord `json:"tool_calls"`
Total int `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
}
// GetToolCallDetailResponse is the response for GET /api/v1/tool-calls/{id}
type GetToolCallDetailResponse struct {
ToolCall ToolCallRecord `json:"tool_call"`
}
// GetServerToolCallsResponse is the response for GET /api/v1/servers/{name}/tool-calls
type GetServerToolCallsResponse struct {
ServerName string `json:"server_name"`
ToolCalls []ToolCallRecord `json:"tool_calls"`
Total int `json:"total"`
}
// GetSessionsResponse is the response for GET /api/v1/sessions
type GetSessionsResponse struct {
Sessions []MCPSession `json:"sessions"`
Total int `json:"total"`
Limit int `json:"limit"`
Offset int `json:"offset"`
}
// GetSessionDetailResponse is the response for GET /api/v1/sessions/{id}
type GetSessionDetailResponse struct {
Session MCPSession `json:"session"`
}
// Configuration management types
// ValidationError represents a single configuration validation error
type ValidationError struct {
Field string `json:"field"`
Message string `json:"message"`
}
// ConfigApplyResult represents the result of applying a configuration change
type ConfigApplyResult struct {
Success bool `json:"success"`
AppliedImmediately bool `json:"applied_immediately"`
RequiresRestart bool `json:"requires_restart"`
RestartReason string `json:"restart_reason,omitempty"`
ValidationErrors []ValidationError `json:"validation_errors,omitempty"`
ChangedFields []string `json:"changed_fields,omitempty"`
}
// GetConfigResponse is the response for GET /api/v1/config
type GetConfigResponse struct {
Config interface{} `json:"config" swaggertype:"object"` // The configuration object
ConfigPath string `json:"config_path"` // Path to config file
}
// ValidateConfigRequest is the request for POST /api/v1/config/validate
type ValidateConfigRequest struct {
Config interface{} `json:"config" swaggertype:"object"` // The configuration to validate
}
// ValidateConfigResponse is the response for POST /api/v1/config/validate
type ValidateConfigResponse struct {
Valid bool `json:"valid"`
Errors []ValidationError `json:"errors,omitempty"`
}
// ApplyConfigRequest is the request for POST /api/v1/config/apply
type ApplyConfigRequest struct {
Config interface{} `json:"config" swaggertype:"object"` // The new configuration to apply
}
// Tool call replay types
// ReplayToolCallRequest is the request for POST /api/v1/tool-calls/{id}/replay
type ReplayToolCallRequest struct {
Arguments map[string]interface{} `json:"arguments" swaggertype:"object"` // Modified arguments for replay
}
// ReplayToolCallResponse is the response for POST /api/v1/tool-calls/{id}/replay
type ReplayToolCallResponse struct {
Success bool `json:"success"`
NewCallID string `json:"new_call_id"` // ID of the newly created call
NewToolCall ToolCallRecord `json:"new_tool_call"` // The new tool call record
ReplayedFrom string `json:"replayed_from"` // Original call ID
Error string `json:"error,omitempty"` // Error if replay failed
}
// Registry browsing types (Phase 7)
// Registry represents an MCP server registry
type Registry struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
URL string `json:"url"`
ServersURL string `json:"servers_url,omitempty"`
Tags []string `json:"tags,omitempty"`
Protocol string `json:"protocol,omitempty"`
Count interface{} `json:"count,omitempty" swaggertype:"primitive,string"` // number or string
}
// RepositoryInfo represents detected repository type information
type RepositoryInfo struct {
NPM *NPMPackageInfo `json:"npm,omitempty"`
// Future: PyPI, Docker Hub, etc.
}
// NPMPackageInfo represents NPM package information
type NPMPackageInfo struct {
Exists bool `json:"exists"`
InstallCmd string `json:"install_cmd"`
}
// RepositoryServer represents an MCP server from a registry
type RepositoryServer struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
URL string `json:"url,omitempty"` // MCP endpoint for remote servers only
SourceCodeURL string `json:"source_code_url,omitempty"` // Source repository URL
InstallCmd string `json:"install_cmd,omitempty"` // Installation command
ConnectURL string `json:"connect_url,omitempty"` // Alternative connection URL
UpdatedAt string `json:"updated_at,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
Registry string `json:"registry,omitempty"` // Which registry this came from
RepositoryInfo *RepositoryInfo `json:"repository_info,omitempty"` // Detected package info
}
// GetRegistriesResponse is the response for GET /api/v1/registries
type GetRegistriesResponse struct {
Registries []Registry `json:"registries"`
Total int `json:"total"`
}
// SearchRegistryServersResponse is the response for GET /api/v1/registries/{id}/servers
type SearchRegistryServersResponse struct {
RegistryID string `json:"registry_id"`
Servers []RepositoryServer `json:"servers"`
Total int `json:"total"`
Query string `json:"query,omitempty"`
Tag string `json:"tag,omitempty"`
}
// SuccessResponse is the standard success response wrapper for API endpoints.
type SuccessResponse struct {
Success bool `json:"success"`
Data interface{} `json:"data" swaggertype:"object"`
}
// ErrorResponse is the standard error response for API endpoints.
// All error responses include a request_id for log correlation.
type ErrorResponse struct {
Success bool `json:"success"`
Error string `json:"error"`
RequestID string `json:"request_id,omitempty"`
}
// HealthStatus represents the unified health status of an upstream MCP server.
// Calculated once in the backend and rendered identically by all interfaces.
type HealthStatus struct {
// Level indicates the health level: "healthy", "degraded", or "unhealthy"
Level string `json:"level"`
// AdminState indicates the admin state: "enabled", "disabled", or "quarantined"
AdminState string `json:"admin_state"`
// Summary is a human-readable status message (e.g., "Connected (5 tools)")
Summary string `json:"summary"`
// Detail is an optional longer explanation of the status
Detail string `json:"detail,omitempty"`
// Action is the suggested fix action: "login", "restart", "enable", "approve", "view_logs", "set_secret", "configure", or "" (none)
Action string `json:"action,omitempty"`
}
// UpdateInfo represents version update check information
type UpdateInfo struct {
Available bool `json:"available"` // Whether an update is available
LatestVersion string `json:"latest_version,omitempty"` // Latest version available (e.g., "v1.2.3")
ReleaseURL string `json:"release_url,omitempty"` // URL to the release page
CheckedAt *time.Time `json:"checked_at,omitempty"` // When the update check was performed
IsPrerelease bool `json:"is_prerelease,omitempty"` // Whether the latest version is a prerelease
CheckError string `json:"check_error,omitempty"` // Error message if update check failed
}
// InfoEndpoints represents the available API endpoints
type InfoEndpoints struct {
HTTP string `json:"http"` // HTTP endpoint address (e.g., "127.0.0.1:8080")
Socket string `json:"socket"` // Unix socket path (empty if disabled)
}
// InfoResponse is the response for GET /api/v1/info
type InfoResponse struct {
Version string `json:"version"` // Current MCPProxy version
WebUIURL string `json:"web_ui_url"` // URL to access the web control panel
ListenAddr string `json:"listen_addr"` // Listen address (e.g., "127.0.0.1:8080")
Endpoints InfoEndpoints `json:"endpoints"` // Available API endpoints
Update *UpdateInfo `json:"update,omitempty"` // Update information (if available)
}