Skip to content

Commit f337b72

Browse files
committed
make mcp config registration private
1 parent 9f3898c commit f337b72

3 files changed

Lines changed: 82 additions & 3 deletions

File tree

packages/workspace-server/src/services/agent/agent.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ function createMockDependencies() {
164164
getPluginPath: vi.fn(() => "/mock/plugin"),
165165
},
166166
agentAuthAdapter: {
167+
getCurrentCredentials: vi.fn().mockResolvedValue(null),
167168
ensureGatewayProxy: vi.fn().mockResolvedValue("http://127.0.0.1:9999"),
168169
configureProcessEnv: vi.fn().mockResolvedValue(undefined),
169170
createPosthogConfig: vi.fn((credentials) => ({
@@ -277,6 +278,62 @@ describe("AgentService", () => {
277278
vi.unstubAllGlobals();
278279
});
279280

281+
describe("mcp-apps config resolver", () => {
282+
function registeredResolver(): (serverName: string) => Promise<void> {
283+
const call = deps.mcpAppsService.setConfigResolver.mock.calls[0];
284+
expect(call).toBeDefined();
285+
return call[0];
286+
}
287+
288+
it("registers server configs from the current credentials", async () => {
289+
deps.agentAuthAdapter.getCurrentCredentials.mockResolvedValue({
290+
apiHost: "https://app.posthog.com",
291+
projectId: 1,
292+
});
293+
deps.agentAuthAdapter.buildMcpServers.mockResolvedValue({
294+
servers: [
295+
{
296+
name: "posthog",
297+
type: "http",
298+
url: "https://mcp.posthog.com/mcp",
299+
headers: [
300+
{ name: "Authorization", value: "Bearer token" },
301+
{ name: "x-posthog-mcp-consumer", value: "posthog-code" },
302+
],
303+
},
304+
],
305+
toolApprovals: {},
306+
toolInstallations: {},
307+
});
308+
309+
await registeredResolver()("posthog");
310+
311+
expect(deps.agentAuthAdapter.buildMcpServers).toHaveBeenCalledWith({
312+
apiHost: "https://app.posthog.com",
313+
projectId: 1,
314+
});
315+
expect(deps.mcpAppsService.addServerConfigs).toHaveBeenCalledWith([
316+
{
317+
name: "posthog",
318+
url: "https://mcp.posthog.com/mcp",
319+
headers: {
320+
Authorization: "Bearer token",
321+
"x-posthog-mcp-consumer": "posthog-code",
322+
},
323+
},
324+
]);
325+
});
326+
327+
it("no-ops when there are no current credentials", async () => {
328+
deps.agentAuthAdapter.getCurrentCredentials.mockResolvedValue(null);
329+
330+
await registeredResolver()("posthog");
331+
332+
expect(deps.agentAuthAdapter.buildMcpServers).not.toHaveBeenCalled();
333+
expect(deps.mcpAppsService.addServerConfigs).not.toHaveBeenCalled();
334+
});
335+
});
336+
280337
describe("MCP servers", () => {
281338
it("marks desktop sessions as local even though they have a taskRunId", async () => {
282339
await service.startSession({

packages/workspace-server/src/services/agent/agent.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -714,10 +714,12 @@ If a repository IS genuinely required, attach one in this priority order:
714714
* service without starting an agent session. A cloud run's agent lives in the
715715
* sandbox, so getOrCreateSession never runs on the desktop and the mcp-apps
716716
* service has no config to fetch a UI-app resource through — the review card
717-
* then fails with "No server config for: posthog" and renders as text. The
718-
* task view calls this when a cloud-run tool result carries a UI app.
717+
* then fails with "No server config for: posthog" and renders as text.
718+
* Invoked via the config resolver registered in the constructor.
719719
*/
720-
async ensureMcpAppsServerConfigs(credentials: Credentials): Promise<void> {
720+
private async ensureMcpAppsServerConfigs(
721+
credentials: Credentials,
722+
): Promise<void> {
721723
const { servers } =
722724
await this.agentAuthAdapter.buildMcpServers(credentials);
723725
this.mcpAppsService.addServerConfigs(

packages/workspace-server/src/services/agent/auth-adapter.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ function createDependencies() {
2626
accessToken: "fresh-access-token",
2727
apiHost: "https://app.posthog.com",
2828
}),
29+
getState: vi.fn((): { currentProjectId: number | null } => ({
30+
currentProjectId: 1,
31+
})),
2932
authenticatedFetch: vi
3033
.fn()
3134
.mockImplementation(
@@ -82,6 +85,23 @@ describe("AgentAuthAdapter", () => {
8285
vi.restoreAllMocks();
8386
});
8487

88+
describe("getCurrentCredentials", () => {
89+
it("returns the auth host and selected project", async () => {
90+
deps.authService.getState.mockReturnValue({ currentProjectId: 42 });
91+
92+
await expect(adapter.getCurrentCredentials()).resolves.toEqual({
93+
apiHost: "https://app.posthog.com",
94+
projectId: 42,
95+
});
96+
});
97+
98+
it("returns null when no project is selected", async () => {
99+
deps.authService.getState.mockReturnValue({ currentProjectId: null });
100+
101+
await expect(adapter.getCurrentCredentials()).resolves.toBeNull();
102+
});
103+
});
104+
85105
it("builds the default PostHog MCP server routed through the local proxy", async () => {
86106
const { servers } = await adapter.buildMcpServers(baseCredentials);
87107

0 commit comments

Comments
 (0)