Skip to content

feat(tools): add visual studio terminal tools #103

Closed

Description

@CalvinAllen

Part of #95.

Add tools for running commands in the Visual Studio integrated terminal.

Proposed tools

Tool Behavior
terminal_create Create a terminal (optional name, profile, working directory)
terminal_list List open terminal instances
terminal_send Send a command to a terminal
terminal_show Bring a terminal into view
terminal_close Close a terminal

Implementation notes

ITerminalService is a brokered service — moniker Microsoft.VisualStudio.Terminal.TerminalService, obtained via TerminalServiceDescriptors.TerminalServiceDescriptor:

Task<Guid> CreateTerminalAsync(CancellationToken ct, string name, ProfileConfig profile, string workingDirectory);
Task       AttachTerminalStreamAsync(Guid terminalGuid, Stream stream, CancellationToken ct);
Task<IEnumerable<Guid>> GetTerminalGuidsAsync(CancellationToken ct);
Task<...>  GetProfilesAsync(CancellationToken ct);
Task       ShowAsync(Guid terminalGuid, ...);
Task       CloseAsync(Guid terminalGuid, ...);
Task       CloseAllInstancesAsync(CancellationToken ct);
Task       ResizeAsync(Guid terminalGuid, ...);

AttachTerminalStreamAsync gives a bidirectional stream — write commands in, read output back.

Public surface is identical between VS 2022 17.14 and VS 2026 18.0. Microsoft.VisualStudio.Terminal has both a binding redirect and a codeBase entry in devenv.exe.config in both versions, so referencing it from the VS install directory resolves cleanly.

Important limitation

This is a raw PTY stream: ANSI escape sequences, no command boundaries, no exit codes. It is good for "run this and let the user watch it happen in VS" and bad for "run this and tell me whether it succeeded."

Recommendation: treat this as a visibility feature, and add a separate process-execution tool (plain System.Diagnostics.Process) for cases where the agent needs a real exit code and clean stdout/stderr. The original ask in #95 was to run things like OpenCover and read the result — that use case wants the process tool, not this one.

Worth deciding up front whether both ship, or only the process tool. Splitting that out if we go that route.

Activity

  1. CalvinAllen commented on Sep 3, 2026

    @CalvinAllen
    ContributorAuthor

    Correction to my own note above, found while implementing #101/#102 (merged in #105).

    I wrote that Microsoft.VisualStudio.Terminal "has both a binding redirect and a codeBase entry in devenv.exe.config in both versions, so referencing it from the VS install directory resolves cleanly." Those facts are right but they govern runtime assembly resolution — they say nothing about whether the project can compile against the assembly, which is the actual blocker:

    $ dotnet msbuild ...MCPServer.csproj -getProperty:DevEnvDir -getProperty:VsInstallRoot
    { "DevEnvDir": "*Undefined*", "VsInstallRoot": "" }
    

    $(DevEnvDir) is only defined when building from a Visual Studio / developer command prompt context. This repo builds with dotnet build locally and in CI (vsix-build.yml step 3), so a HintPath off $(DevEnvDir) breaks the build outright. Microsoft.VisualStudio.Terminal is also not on NuGet and not in the Microsoft.VisualStudio.SDK metapackage.

    Use the pattern established in #105: resolve ITerminalService by MEF/brokered-service contract name and access it reflectively, per Services/TestExplorerInterop.cs. The alternative considered and rejected was an MSBuild target shelling out to vswhere, which would make a Visual Studio installation a hard build prerequisite — it currently isn't one.

    ITerminalService is a brokered service rather than a MEF export, so it comes through IBrokeredServiceContainer / ServiceRpcDescriptor rather than DefaultExportProvider. The reflection approach is the same shape, but it is not a copy-paste of the stats service — worth budgeting for.

    Everything else in the issue stands: the method signatures, the identical surface across VS 2022 and VS 2026, and the raw-PTY limitation (no exit codes, no command boundaries) that argues for a separate process-execution tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions