File size: 4,615 Bytes
cd8bd0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/**
 * MCP Authorization Scopes — Defines permission scopes for each MCP tool.
 *
 * Each tool requires specific scopes to execute. API keys can be configured
 * with a subset of scopes to limit tool access (least-privilege).
 */

// ============ Scope Definitions ============

/** All available MCP scopes */
export const MCP_SCOPE_LIST = [
  "read:health",
  "read:combos",
  "write:combos",
  "read:quota",
  "read:usage",
  "read:models",
  "execute:completions",
  "execute:search",
  "write:budget",
  "write:resilience",
  "pricing:write",
  "read:cache",
  "write:cache",
  "read:compression",
  "write:compression",
  "read:proxies",
] as const;

export type McpScope = (typeof MCP_SCOPE_LIST)[number];

// ============ Tool → Scope Mapping ============

/** Maps each MCP tool to its required scopes */
export const MCP_TOOL_SCOPES: Record<string, readonly McpScope[]> = {
  // Phase 1: Essential Tools
  omniroute_get_health: ["read:health"],
  omniroute_list_combos: ["read:combos"],
  omniroute_get_combo_metrics: ["read:combos"],
  omniroute_switch_combo: ["write:combos"],
  omniroute_check_quota: ["read:quota"],
  omniroute_route_request: ["execute:completions"],
  omniroute_web_search: ["execute:search"],
  omniroute_web_fetch: ["execute:search"],
  omniroute_cost_report: ["read:usage"],
  omniroute_list_models_catalog: ["read:models"],

  // Phase 2: Advanced Tools
  omniroute_simulate_route: ["read:health", "read:combos"],
  omniroute_set_budget_guard: ["write:budget"],
  omniroute_set_resilience_profile: ["write:resilience"],
  omniroute_test_combo: ["execute:completions", "read:combos"],
  omniroute_get_provider_metrics: ["read:health"],
  omniroute_best_combo_for_task: ["read:combos", "read:health"],
  omniroute_explain_route: ["read:health", "read:usage"],
  omniroute_get_session_snapshot: ["read:usage"],
  omniroute_db_health_check: ["read:health", "write:resilience"],
  omniroute_sync_pricing: ["pricing:write"],
  omniroute_cache_stats: ["read:cache"],
  omniroute_cache_flush: ["write:cache"],
  omniroute_compression_status: ["read:compression"],
  omniroute_compression_configure: ["write:compression"],
  omniroute_set_compression_engine: ["write:compression"],
  omniroute_list_compression_combos: ["read:compression"],
  omniroute_compression_combo_stats: ["read:compression"],
  omniroute_oneproxy_fetch: ["read:proxies"],
  omniroute_oneproxy_rotate: ["read:proxies"],
  omniroute_oneproxy_stats: ["read:proxies"],

  // Web-session pool observability (read) + lifecycle (write)
  omniroute_pool_status: ["read:health"],
  omniroute_pool_sessions: ["read:health"],
  omniroute_pool_health: ["read:health"],
  omniroute_pool_reset: ["write:resilience"],
  omniroute_pool_warm: ["write:resilience"],
  // Stealth browser pool observability (#3368 PR7)
  omniroute_browser_pool_status: ["read:health"],
} as const;

// ============ Scope Groups ============

/** Preset scope bundles for common use cases */
export const MCP_SCOPE_PRESETS = {
  /** Read-only access to all health, combo, quota, and usage data */
  readonly: [
    "read:health",
    "read:combos",
    "read:quota",
    "read:usage",
    "read:models",
    "read:cache",
    "read:compression",
  ] as const satisfies readonly McpScope[],

  /** Full access including writes and execution */
  full: [...MCP_SCOPE_LIST] as McpScope[],

  /** Monitoring only — health and metrics */
  monitor: [
    "read:health",
    "read:quota",
    "read:usage",
    "read:cache",
    "read:compression",
  ] as const satisfies readonly McpScope[],

  /** Agent — can execute completions and read state */
  agent: [
    "read:health",
    "read:combos",
    "read:quota",
    "read:usage",
    "read:models",
    "read:cache",
    "read:compression",
    "execute:completions",
    "execute:search",
  ] as const satisfies readonly McpScope[],
} as const;

// ============ Helpers ============

/**
 * Check if a set of granted scopes satisfies the required scopes for a tool.
 */
export function hasRequiredScopes(grantedScopes: readonly string[], toolName: string): boolean {
  const required = MCP_TOOL_SCOPES[toolName];
  if (!required) return false;
  const granted = new Set(grantedScopes);
  return required.every((scope) => granted.has(scope));
}

/**
 * Get the list of missing scopes for a tool given granted scopes.
 */
export function getMissingScopes(grantedScopes: readonly string[], toolName: string): string[] {
  const required = MCP_TOOL_SCOPES[toolName];
  if (!required) return [];
  const granted = new Set(grantedScopes);
  return required.filter((scope) => !granted.has(scope));
}