Skip to content

Conversation

nirinchev
Copy link
Collaborator

Proposed changes

This tweaks slightly some of the API around streamable http runner to allow it to be consumed by the vscode extension. Notably:

  • We add httpHeaders config option that allows consumers to specify required headers the server should check for in the client requests. This will be used by the vscode extension to generate a random header when it starts the server.
  • Exports some more types for consumers (e.g. StreamableHttpRunner and defaultUserConfig)
  • Allows running the http server on a random port and exposes the address of the server.

@Copilot Copilot AI review requested due to automatic review settings August 21, 2025 13:17
@nirinchev nirinchev requested a review from a team as a code owner August 21, 2025 13:17
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds VS Code extension integration support by enhancing the StreamableHttpRunner with header validation, port flexibility, and better type exports.

  • Adds httpHeaders configuration option for server-side header validation
  • Enables random port assignment and exposes server address via getter
  • Exports additional types (StreamableHttpRunner, defaultUserConfig) for external consumption

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/common/config.ts Adds httpHeaders field to config interface and default configuration
src/transports/streamableHttp.ts Implements header validation middleware and address getter for server
src/lib.ts Exports additional types and classes for external consumption
tests/integration/transports/streamableHttp.test.ts Updates tests to validate header functionality with comprehensive test cases

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

* main:
  feat: update connectionString appName param - [MCP-68] (#406)
  chore: remove double occurrence of an object's property (#469)
  chore: add user for the smithery dockerfile (#458)
@nirinchev nirinchev changed the title fix: minor tweaks to enable vscode integration fix: minor tweaks to enable vscode integration MCP-134 Aug 26, 2025
Copy link
Collaborator

@gagik gagik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, one suggestion

Comment on lines 17 to +23
private constructor(logger: LoggerBase, timeout: number = DEVICE_ID_TIMEOUT) {
this.logger = logger;
this.timeout = timeout;
this.getMachineId = (): Promise<string> => nodeMachineId.machineId(true);
this.abortController = new AbortController();

this.deviceIdPromise = DeviceId.UnknownDeviceId;
Copy link
Collaborator

@gagik gagik Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private constructor(logger: LoggerBase, timeout: number = DEVICE_ID_TIMEOUT) {
this.logger = logger;
this.timeout = timeout;
this.getMachineId = (): Promise<string> => nodeMachineId.machineId(true);
this.abortController = new AbortController();
this.deviceIdPromise = DeviceId.UnknownDeviceId;
private constructor({logger, timeout, deviceIdPromise, abortController}: {logger: LoggerBase, timeout: number = DEVICE_ID_TIMEOUT, deviceIdPromise: Promise<string>, abortController: AbortController}) {
this.logger = logger;
this.timeout = timeout;
this.abortController = abortController;
this.deviceIdPromise = deviceIdPromise;

I think this is better because it'd be good to have the Promise resolve to unknown only in the end so we can always have a state of pending -> unknown and not unknown -> pending -> unknown (even though in practice we instantly override this in create right now

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, we can't supply the promise through the constructor since we need the DeviceId instance to construct the promise itself. Technically, the only reason to have it assigned here is to make the types nicer and ensure we don't have to write ? all over the place when we know for sure the field is initialized at this point. So we have 3 options (with no preference which one to go for):

  1. Keep it as is
  2. Suppress the error that we're not initializing a required field
  3. Move the getDeviceId call to the constructor (and close our eyes for the fact it's introducing a side effect)


public static create(logger: LoggerBase, timeout?: number): DeviceId {
Copy link
Collaborator

@gagik gagik Aug 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static create(logger: LoggerBase, timeout?: number): DeviceId {
public static create(logger: LoggerBase, { timeout = DEVICE_ID_TIMEOUT } : { timeout: number} = {}): DeviceId {
const abortController = new AbortController();
const deviceIdPromise = () => getDeviceId({
getMachineId: () => nodeMachineId.machineId(true),
onError: (reason, error) => {
this.handleDeviceIdError(reason, String(error));
},
timeout: this.timeout,
abortSignal: abortController.signal,
});
const instance = new DeviceId({logger, timeout, deviceIdPromise, abortController});

personal preference re: timeout as object because it's one of these things which we basically largely have only for test DI purposes

@nirinchev nirinchev merged commit d261208 into main Aug 28, 2025
17 of 22 checks passed
@nirinchev nirinchev deleted the ni/http-tweaks branch August 28, 2025 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants