Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions packages/agent/src/adapters/claude/claude-agent.refresh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,14 @@ function installFakeSession(
sessionId,
cwd: "/tmp/repo",
model: "claude-sonnet-4-6",
mcpServers: { posthog: { type: "http", url: "https://old" } },
mcpServers: {
posthog: { type: "http", url: "https://old" },
"posthog-code-tools": {
type: "sdk",
name: "posthog-code-tools",
instance: {},
},
},
abortController,
},
input,
Expand Down Expand Up @@ -222,7 +229,8 @@ describe("ClaudeAcpAgent.extMethod refresh_session", () => {
expect(oldQuery.interrupt).toHaveBeenCalledTimes(1);
expect(endSpy).toHaveBeenCalledTimes(1);

// New query was built with resume identity (not sessionId) and new servers
// New query: resume identity (not sessionId), http server refreshed, and
// the in-process local-tools server preserved.
expect(lastQueryCall.options).toMatchObject({
resume: "s-2",
forkSession: false,
Expand All @@ -232,6 +240,11 @@ describe("ClaudeAcpAgent.extMethod refresh_session", () => {
url: "https://fresh",
headers: { "x-foo": "bar" },
},
"posthog-code-tools": {
type: "sdk",
name: "posthog-code-tools",
instance: {},
},
},
});
expect(lastQueryCall.options?.sessionId).toBeUndefined();
Expand Down Expand Up @@ -313,4 +326,25 @@ describe("ClaudeAcpAgent.extMethod refresh_session", () => {
expect(fetchMcpToolMetadataMock).toHaveBeenCalledTimes(1);
expect(fetchMcpToolMetadataMock.mock.calls[0][0]).toBe(createdQueries[0]);
});

it("preserves the in-process local-tools server across refresh", async () => {
const agent = makeAgent();
installFakeSession(agent, "s-inprocess");

// freshMcpServers carries only external (http) servers, so the sdk server
// must be carried over from the previous session options.
await agent.extMethod(POSTHOG_METHODS.REFRESH_SESSION, {
mcpServers: freshMcpServers,
});

const servers = lastQueryCall.options?.mcpServers as Record<
string,
{ type?: string }
>;
expect(servers["posthog-code-tools"]).toEqual({
type: "sdk",
name: "posthog-code-tools",
instance: {},
});
});
});
11 changes: 10 additions & 1 deletion packages/agent/src/adapters/claude/claude-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1111,9 +1111,18 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
// fresh AbortController.
const newAbortController = new AbortController();
const { sessionId: _drop, ...rest } = prev.queryOptions;

// parseMcpServers yields only http/sse/stdio — carry over any in-process
// ("sdk") server so the local-tools server (signed commits) survives.
const preservedInProcess = Object.fromEntries(
Object.entries(prev.queryOptions.mcpServers ?? {}).filter(
([, cfg]) => (cfg as { type?: string }).type === "sdk",
),
);

const newOptions: Options = {
...rest,
mcpServers,
mcpServers: { ...mcpServers, ...preservedInProcess },
resume: this.sessionId,
forkSession: false,
abortController: newAbortController,
Expand Down
Loading