Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

Commit 71ce33d

Browse files
Merging 81ad90f into trunk-temp/pr-3643/74a61602-4d3f-4a86-81fc-715743ce25ca
2 parents 4cf4612 + 81ad90f commit 71ce33d

58 files changed

Lines changed: 9942 additions & 50 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/LOCAL-DEVELOPMENT.md‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,59 @@ region you pick at login.
127127
128128
## Troubleshooting
129129

130+
### Feature flags never enabled (flag-gated UI missing)
131+
132+
If flag-gated surfaces (e.g. the MCP gateway behind `mcp-gateway`) never show up
133+
even though the flag is enabled in your PostHog project, check
134+
`VITE_POSTHOG_API_HOST` in `.env`: it must include the scheme
135+
(`http://localhost:8010`, not `localhost:8010`). posthog-js concatenates the
136+
host into request URLs verbatim, so a scheme-less value produces URLs like
137+
`localhost:8010/flags/…` that the browser rejects as an invalid protocol —
138+
every flag fetch fails silently and `isFeatureEnabled` returns `undefined` for
139+
everything (flags never loaded). Prefer `node scripts/use-local-posthog.mjs`
140+
over hand-editing; it writes the correct form.
141+
142+
To confirm what the running app sees, run in the renderer console (or via CDP):
143+
144+
```js
145+
posthog.config.api_host; // must start with http:// or https://
146+
posthog.isFeatureEnabled("mcp-gateway"); // undefined ⇒ flags never loaded
147+
```
148+
149+
`.env` changes need a dev-server restart (`pnpm dev`) to take effect.
150+
130151
### "Invalid client_id" error during OAuth
131152

132153
The OAuth application in your local PostHog must have the client ID `DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ`. Verify at http://localhost:8010/admin/posthog/oauthapplication/.
133154

155+
### "OAuth error: invalid_scope"
156+
157+
PostHog Code requests the wildcard scope `*` (see `OAUTH_SCOPES` in
158+
`packages/shared/src/oauth.ts`). PostHog's OAuth server only grants `*` at
159+
`/authorize` when the OAuth application's **scope ceiling is empty** — this is
160+
the grandfathering path for the PostHog Code client. If the application has any
161+
explicit `scopes` or `optional_scopes` configured, the wildcard is rejected with
162+
`invalid_scope`.
163+
164+
Fix: clear the scope ceiling on your local OAuth application so it matches the
165+
production app. Either edit it at
166+
http://localhost:8010/admin/posthog/oauthapplication/ (empty the **Scopes** and
167+
**Optional scopes** fields), or run in your PostHog repo:
168+
169+
```bash
170+
python manage.py shell -c "
171+
from posthog.models.oauth import OAuthApplication
172+
app = OAuthApplication.objects.get(client_id='DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ')
173+
app.scopes = []
174+
app.optional_scopes = []
175+
app.save()
176+
print('cleared scope ceiling for', app.client_id)
177+
"
178+
```
179+
180+
Then retry login. (Do not add `*` to the ceiling — an explicit ceiling never
181+
grants the wildcard, even if `*` is listed.)
182+
134183
### "Redirect URI mismatch"
135184

136185
Make sure the OAuth application's redirect URIs include `http://localhost:8237/callback` and `http://localhost:8239/callback`. Check for trailing slashes.
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
// Types for the team MCP gateway API (`/api/projects/{id}/mcp_gateway/*`).
2+
// Hand-written mirrors of the Django serializers in
3+
// products/mcp_store/backend/presentation/gateway_views.py — these endpoints
4+
// ship behind the `mcp-gateway` flag and are not in the generated OpenAPI
5+
// client yet.
6+
import type { Schemas } from "./generated";
7+
import type { McpApprovalState, McpAuthType, McpCategory } from "./types";
8+
9+
export type McpGatewayUser = Schemas.UserBasic;
10+
11+
export type McpGatewayScopeType = "team" | "member" | "agent";
12+
export type McpServiceAccountStatus = "active" | "paused";
13+
export type McpAuditDecision = "auto" | "approved" | "pending" | "blocked";
14+
export type McpAuditQuickFilter = "all" | "agents" | "approvals" | "blocked";
15+
export type McpPolicyDecidedBy =
16+
| "rule"
17+
| "scope"
18+
| "team"
19+
| "preset"
20+
| "legacy"
21+
| "default";
22+
23+
/** One member's connection to a gateway server. */
24+
export interface McpGatewayConnection {
25+
installation_id: string;
26+
user: McpGatewayUser;
27+
last_used_at: string | null;
28+
pending_oauth: boolean;
29+
needs_reauth: boolean;
30+
}
31+
32+
/** The requesting user's own connection to a gateway server. */
33+
export interface McpGatewayYourConnection {
34+
installation_id: string;
35+
/** Per-connection switch — false when self-disabled. */
36+
is_enabled: boolean;
37+
pending_oauth: boolean;
38+
needs_reauth: boolean;
39+
last_used_at: string | null;
40+
}
41+
42+
/** One agent's access to a gateway server. */
43+
export interface McpGatewayAgentAccess {
44+
service_account_id: string;
45+
name: string;
46+
/** Agent identity handle, e.g. posthog-support. */
47+
handle: string;
48+
status: McpServiceAccountStatus;
49+
last_active_at: string | null;
50+
granted_by: McpGatewayUser | null;
51+
}
52+
53+
/** A server registered in the team's gateway, with connection summary. */
54+
export interface McpGatewayServer {
55+
id: string;
56+
name: string;
57+
url: string;
58+
description: string;
59+
category: McpCategory;
60+
is_team_enabled: boolean;
61+
icon_key: string;
62+
docs_url: string;
63+
template_id: string | null;
64+
/**
65+
* Fixed authentication type for catalog templates. Null for custom
66+
* servers, where each member chooses when connecting.
67+
*/
68+
template_auth_type: McpAuthType | null;
69+
tool_count: number;
70+
/** Members with a connection to this server. Admin-only; empty for members. */
71+
connections: McpGatewayConnection[];
72+
your_connection: McpGatewayYourConnection | null;
73+
agents: McpGatewayAgentAccess[];
74+
/** Ids of members whose access an admin has turned off. */
75+
revoked_user_ids: number[];
76+
is_revoked_for_you: boolean;
77+
created_by: McpGatewayUser | null;
78+
created_at: string;
79+
updated_at: string;
80+
}
81+
82+
export interface McpGatewayServerUpdate {
83+
name?: string;
84+
description?: string;
85+
category?: McpCategory;
86+
/** Master switch — off means members and agents can neither see nor call the server. */
87+
is_team_enabled?: boolean;
88+
}
89+
90+
/** Which policy scope a tools query or policy upsert targets. */
91+
export interface McpGatewayPolicyScope {
92+
scope_type?: McpGatewayScopeType;
93+
/** Member scope target. Defaults to the requesting user. */
94+
scope_user_id?: number;
95+
/** Agent scope target. Required when scope_type is "agent". */
96+
scope_service_account_id?: string;
97+
}
98+
99+
export interface McpToolPolicyEntry {
100+
tool_name: string;
101+
policy_state: McpApprovalState;
102+
}
103+
104+
/** One tool with its effective policy for the requested scope. */
105+
export interface McpResolvedToolPolicy {
106+
tool_name: string;
107+
description: string;
108+
input_schema: unknown;
109+
policy_state: McpApprovalState;
110+
/** What the team-level chain yields, ignoring the scope. Null when the team imposes nothing. */
111+
team_state: McpApprovalState | null;
112+
/** True when a rule or Blocked team ceiling leaves no editable state. */
113+
locked: boolean;
114+
decided_by: McpPolicyDecidedBy;
115+
/** Matching org rule name, when decided_by is "rule". */
116+
rule_name: string;
117+
rule_description: string;
118+
}
119+
120+
export interface McpServiceAccount {
121+
id: string;
122+
name: string;
123+
description: string;
124+
/** Stable identity handle the agent authenticates as, e.g. posthog-support. */
125+
handle: string;
126+
status: McpServiceAccountStatus;
127+
/** Masked bearer token; the full token is only shown once. */
128+
token_mask: string;
129+
server_ids: string[];
130+
last_active_at: string | null;
131+
created_at: string;
132+
updated_at: string;
133+
}
134+
135+
export interface McpServiceAccountWithToken extends McpServiceAccount {
136+
/** The full bearer token. Returned exactly once — on creation. */
137+
token: string;
138+
}
139+
140+
export interface McpAuditActorServiceAccount {
141+
id: string;
142+
name: string;
143+
handle: string;
144+
}
145+
146+
export interface McpAuditEvent {
147+
id: string;
148+
created_at: string;
149+
server_name: string;
150+
tool_name: string;
151+
decision: McpAuditDecision;
152+
actor_user: McpGatewayUser | null;
153+
actor_service_account: McpAuditActorServiceAccount | null;
154+
/** Denormalized actor label (email or handle) that survives deletion. */
155+
actor_label: string;
156+
}
157+
158+
export interface McpAuditCounts {
159+
all: number;
160+
agents: number;
161+
approvals: number;
162+
blocked: number;
163+
}
164+
165+
export interface McpAuditPage {
166+
count: number;
167+
results: McpAuditEvent[];
168+
}
169+
170+
export interface TeamMcpGatewayConfig {
171+
allow_custom_servers: boolean;
172+
/** Whether members may share MCP connections with agents and manage agent tool policies. */
173+
allow_member_agent_access: boolean;
174+
/**
175+
* Whether catalog servers the team never touched (no gateway row) are
176+
* enabled. Covers templates published after the admin last curated.
177+
*/
178+
default_servers_enabled: boolean;
179+
/** Whether the requesting user can administer the gateway. */
180+
is_admin: boolean;
181+
}
182+
183+
export interface TeamMcpGatewayConfigUpdate {
184+
allow_custom_servers?: boolean;
185+
allow_member_agent_access?: boolean;
186+
default_servers_enabled?: boolean;
187+
}
188+
189+
/** One team member's gateway posture (admin overview). */
190+
export interface McpGatewayMemberSummary {
191+
user: McpGatewayUser;
192+
is_org_admin: boolean;
193+
/** Gateway servers the member has a personal connection to. */
194+
connected_server_ids: string[];
195+
/** Gateway servers an admin turned off for this member. */
196+
revoked_server_ids: string[];
197+
}
198+
199+
/**
200+
* Gateway options accepted by install_custom / install_template. Credentials
201+
* are always personal to the installer; agents reach them through grants.
202+
*/
203+
export interface McpGatewayInstallSharingOptions {
204+
/** Whether the server starts enabled for the whole team. */
205+
team_enabled?: boolean;
206+
/** Service accounts to grant the server to at install time, when team settings allow it. */
207+
agent_ids?: string[];
208+
}

0 commit comments

Comments
 (0)