Skip to content

Commit c4e007e

Browse files
chore(mcp-server): add support for session id, forward client info
1 parent 937becb commit c4e007e

File tree

4 files changed

+30
-7
lines changed

4 files changed

+30
-7
lines changed

packages/mcp-server/src/docs-search-tool.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,18 @@ async function searchLocal(args: Record<string, unknown>): Promise<unknown> {
7676
}).results;
7777
}
7878

79-
async function searchRemote(
80-
args: Record<string, unknown>,
81-
stainlessApiKey: string | undefined,
82-
): Promise<unknown> {
79+
async function searchRemote(args: Record<string, unknown>, reqContext: McpRequestContext): Promise<unknown> {
8380
const body = args as any;
8481
const query = new URLSearchParams(body).toString();
8582

8683
const startTime = Date.now();
8784
const result = await fetch(`${docsSearchURL}?${query}`, {
8885
headers: {
89-
...(stainlessApiKey && { Authorization: stainlessApiKey }),
86+
...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }),
87+
...(reqContext.mcpSessionId && { 'x-stainless-mcp-session-id': reqContext.mcpSessionId }),
88+
...(reqContext.mcpClientInfo && {
89+
'x-stainless-mcp-client-info': JSON.stringify(reqContext.mcpClientInfo),
90+
}),
9091
},
9192
});
9293

@@ -105,7 +106,7 @@ async function searchRemote(
105106
'Got error response from docs search tool',
106107
);
107108

108-
if (result.status === 404 && !stainlessApiKey) {
109+
if (result.status === 404 && !reqContext.stainlessApiKey) {
109110
throw new Error(
110111
'Could not find docs for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.',
111112
);
@@ -140,7 +141,7 @@ export const handler = async ({
140141
return asTextContentResult(await searchLocal(body));
141142
}
142143

143-
return asTextContentResult(await searchRemote(body, reqContext.stainlessApiKey));
144+
return asTextContentResult(await searchRemote(body, reqContext));
144145
};
145146

146147
export default { metadata, tool, handler };

packages/mcp-server/src/http.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ const newServer = async ({
7878
},
7979
stainlessApiKey: stainlessApiKey,
8080
upstreamClientEnvs,
81+
mcpSessionId: (req as any).mcpSessionId,
82+
mcpClientInfo:
83+
typeof req.body?.params?.clientInfo?.name === 'string' ?
84+
{ name: req.body.params.clientInfo.name, version: String(req.body.params.clientInfo.version ?? '') }
85+
: undefined,
8186
});
8287

8388
return server;
@@ -135,6 +140,17 @@ export const streamableHTTPApp = ({
135140
const app = express();
136141
app.set('query parser', 'extended');
137142
app.use(express.json());
143+
app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
144+
const existing = req.headers['mcp-session-id'];
145+
const sessionId = (Array.isArray(existing) ? existing[0] : existing) || crypto.randomUUID();
146+
(req as any).mcpSessionId = sessionId;
147+
const origWriteHead = res.writeHead.bind(res);
148+
res.writeHead = function (statusCode: number, ...rest: any[]) {
149+
res.setHeader('mcp-session-id', sessionId);
150+
return origWriteHead(statusCode, ...rest);
151+
} as typeof res.writeHead;
152+
next();
153+
});
138154
app.use(
139155
pinoHttp({
140156
logger: getLogger(),

packages/mcp-server/src/server.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export async function initMcpServer(params: {
4747
mcpOptions?: McpOptions;
4848
stainlessApiKey?: string | undefined;
4949
upstreamClientEnvs?: Record<string, string> | undefined;
50+
mcpSessionId?: string | undefined;
51+
mcpClientInfo?: { name: string; version: string } | undefined;
5052
}) {
5153
const server = params.server instanceof McpServer ? params.server.server : params.server;
5254

@@ -136,6 +138,8 @@ export async function initMcpServer(params: {
136138
client,
137139
stainlessApiKey: params.stainlessApiKey ?? params.mcpOptions?.stainlessApiKey,
138140
upstreamClientEnvs: params.upstreamClientEnvs,
141+
mcpSessionId: params.mcpSessionId,
142+
mcpClientInfo: params.mcpClientInfo,
139143
},
140144
args,
141145
});

packages/mcp-server/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export type McpRequestContext = {
4646
client: Finch;
4747
stainlessApiKey?: string | undefined;
4848
upstreamClientEnvs?: Record<string, string> | undefined;
49+
mcpSessionId?: string | undefined;
50+
mcpClientInfo?: { name: string; version: string } | undefined;
4951
};
5052

5153
export type HandlerFunction = ({

0 commit comments

Comments
 (0)