Skip to content

Commit e619a8e

Browse files
committed
feat: capture MCP client info in User-Agent
When an MCP client (like Claude Desktop or Cursor) connects, we now capture its name and version from the initialize request and include it in the User-Agent string. Format: context-connectors/{version} via:mcp client:{name}/{version} Example: context-connectors/0.1.3 via:mcp client:claude-desktop/1.0.0 Changes: - Add updateClientUserAgent() method to MultiIndexRunner - Handle InitializeRequestSchema in mcp-server.ts to capture client info - Update User-Agent dynamically after receiving MCP client info Agent-Id: agent-0d00d75b-1ac5-4e85-a310-90e1af295ee3
1 parent ac790cd commit e619a8e

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

src/clients/mcp-server.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
3636
import {
3737
CallToolRequestSchema,
3838
ListToolsRequestSchema,
39+
InitializeRequestSchema,
3940
} from "@modelcontextprotocol/sdk/types.js";
4041
import type { IndexStoreReader } from "../stores/types.js";
4142
import { MultiIndexRunner } from "./multi-index-runner.js";
42-
import { buildClientUserAgent } from "../core/utils.js";
43+
import { buildClientUserAgent, type MCPClientInfo } from "../core/utils.js";
4344
import {
4445
SEARCH_DESCRIPTION,
4546
LIST_FILES_DESCRIPTION,
@@ -126,6 +127,35 @@ export async function createMCPServer(
126127
}
127128
);
128129

130+
// Set up a custom initialize handler to capture MCP client info
131+
// We intercept the initialize request to update the User-Agent with client info
132+
server.setRequestHandler(InitializeRequestSchema, async (request) => {
133+
// Extract client info from the initialize request
134+
const clientInfo = request.params.clientInfo;
135+
if (clientInfo) {
136+
const mcpClientInfo: MCPClientInfo = {
137+
name: clientInfo.name,
138+
version: clientInfo.version,
139+
};
140+
// Update the runner's User-Agent with MCP client info
141+
const updatedUserAgent = buildClientUserAgent("mcp", mcpClientInfo);
142+
runner.updateClientUserAgent(updatedUserAgent);
143+
}
144+
145+
// Return the standard initialize response
146+
// The Server class will merge our capabilities with the standard response
147+
return {
148+
protocolVersion: "2024-11-05",
149+
serverInfo: {
150+
name: config.serverName ?? "context-connectors",
151+
version: config.version ?? "0.1.0",
152+
},
153+
capabilities: {
154+
tools: {},
155+
},
156+
};
157+
});
158+
129159
// Define tool type for type safety
130160
type Tool = {
131161
name: string;

src/clients/multi-index-runner.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ async function createSourceFromState(state: IndexStateSearchOnly): Promise<Sourc
7070
export class MultiIndexRunner {
7171
private readonly store: IndexStoreReader;
7272
private readonly searchOnly: boolean;
73-
private readonly clientUserAgent?: string;
73+
private clientUserAgent?: string;
7474
private readonly clientCache = new Map<string, SearchClient>();
7575

7676
/** Available index names */
@@ -143,6 +143,17 @@ export class MultiIndexRunner {
143143
return new MultiIndexRunner(store, validIndexNames, indexes, searchOnly, config.clientUserAgent);
144144
}
145145

146+
147+
/**
148+
* Update the User-Agent string.
149+
*
150+
* Call this after receiving MCP client info to include the client name/version.
151+
* Note: Only affects future client creations, not existing cached clients.
152+
*/
153+
updateClientUserAgent(newUserAgent: string): void {
154+
this.clientUserAgent = newUserAgent;
155+
}
156+
146157
/**
147158
* Get or create a SearchClient for an index.
148159
*/

0 commit comments

Comments
 (0)