diff --git a/extension/loc/xlf/aspire-vscode.xlf b/extension/loc/xlf/aspire-vscode.xlf
index 4b741264196..8855e802d27 100644
--- a/extension/loc/xlf/aspire-vscode.xlf
+++ b/extension/loc/xlf/aspire-vscode.xlf
@@ -7,6 +7,9 @@
Add an integration
+
+ Aspire
+
Aspire
@@ -415,11 +418,12 @@
Update integrations
-
- Verify Aspire CLI installation
Use the system default browser (cannot auto-close).
+
+ Verify Aspire CLI installation
+
View logs
@@ -429,6 +433,9 @@
Welcome to Aspire
+
+ Whether to the Aspire MCP server when a workspace is open.
+
Yes
diff --git a/extension/package.json b/extension/package.json
index fcec1af019c..773c83e6f66 100644
--- a/extension/package.json
+++ b/extension/package.json
@@ -37,6 +37,12 @@
"main": "./dist/extension.js",
"l10n": "./l10n",
"contributes": {
+ "mcpServerDefinitionProviders": [
+ {
+ "id": "aspire-mcp-server",
+ "label": "Aspire"
+ }
+ ],
"viewsContainers": {
"activitybar": [
{
@@ -461,6 +467,12 @@
"default": true,
"description": "%configuration.aspire.enableDebugConfigEnvironmentLogging%",
"scope": "window"
+ },
+ "aspire.registerMcpServerInWorkspace": {
+ "type": "boolean",
+ "default": false,
+ "description": "%configuration.aspire.registerMcpServerInWorkspace%",
+ "scope": "window"
}
}
},
diff --git a/extension/package.nls.json b/extension/package.nls.json
index e16757faed7..12e8365175f 100644
--- a/extension/package.nls.json
+++ b/extension/package.nls.json
@@ -32,6 +32,7 @@
"configuration.aspire.dashboardBrowser.debugFirefox": "Launch Firefox as a debug session (requires Firefox Debugger extension).",
"configuration.aspire.closeDashboardOnDebugEnd": "Close the dashboard browser when the debug session ends. Works with debug browser options (Chrome, Edge, Firefox).",
"configuration.aspire.enableDebugConfigEnvironmentLogging": "Include environment variables when logging debug session configurations. This can help diagnose environment-related issues but may expose sensitive information in logs.",
+ "configuration.aspire.registerMcpServerInWorkspace": "Whether to register the Aspire MCP server when a workspace is open.",
"command.runAppHost": "Run Aspire apphost",
"command.debugAppHost": "Debug Aspire apphost",
"aspire-vscode.strings.noCsprojFound": "No apphost found in the current workspace.",
@@ -146,5 +147,6 @@
"walkthrough.getStarted.dashboard.title": "Explore the dashboard",
"walkthrough.getStarted.dashboard.description": "The Aspire Dashboard shows your resources, endpoints, logs, traces, and metrics — all in one place.\n\n[Open dashboard](command:aspire-vscode.openDashboard)",
"walkthrough.getStarted.nextSteps.title": "Next steps",
- "walkthrough.getStarted.nextSteps.description": "You're all set! Add integrations for databases, messaging, and cloud services, or deploy your app to production.\n\n[Add an integration](command:aspire-vscode.add)\n\n[Open Aspire docs](https://aspire.dev/docs/)"
+ "walkthrough.getStarted.nextSteps.description": "You're all set! Add integrations for databases, messaging, and cloud services, or deploy your app to production.\n\n[Add an integration](command:aspire-vscode.add)\n\n[Open Aspire docs](https://aspire.dev/docs/)",
+ "mcpServerDefinitionProviders.aspire.label": "Aspire"
}
diff --git a/extension/src/extension.ts b/extension/src/extension.ts
index 2bc9d56cf5c..81fa003e360 100644
--- a/extension/src/extension.ts
+++ b/extension/src/extension.ts
@@ -29,6 +29,7 @@ import { AspireEditorCommandProvider } from './editor/AspireEditorCommandProvide
import { AspireAppHostTreeProvider } from './views/AspireAppHostTreeProvider';
import { installCliStableCommand, installCliDailyCommand, verifyCliInstalledCommand } from './commands/walkthroughCommands';
import { AspireStatusBarProvider } from './views/AspireStatusBarProvider';
+import { AspireMcpServerDefinitionProvider } from './mcp/AspireMcpServerDefinitionProvider';
let aspireExtensionContext = new AspireExtensionContext();
@@ -119,6 +120,15 @@ export async function activate(context: vscode.ExtensionContext) {
aspireExtensionContext.initialize(rpcServer, context, debugConfigProvider, dcpServer, terminalProvider, editorCommandProvider);
+ // Register Aspire MCP server definition provider so the Aspire MCP server
+ // appears automatically in VS Code's MCP tools list for Aspire workspaces.
+ const mcpProvider = new AspireMcpServerDefinitionProvider();
+ if (typeof vscode.lm?.registerMcpServerDefinitionProvider === 'function') {
+ context.subscriptions.push(vscode.lm.registerMcpServerDefinitionProvider('aspire-mcp-server', mcpProvider));
+ context.subscriptions.push(mcpProvider);
+ mcpProvider.refresh();
+ }
+
const getEnableSettingsFileCreationPromptOnStartup = () => vscode.workspace.getConfiguration('aspire').get('enableSettingsFileCreationPromptOnStartup', true);
const setEnableSettingsFileCreationPromptOnStartup = async (value: boolean) => await vscode.workspace.getConfiguration('aspire').update('enableSettingsFileCreationPromptOnStartup', value, vscode.ConfigurationTarget.Workspace);
const appHostDisposablePromise = checkForExistingAppHostPathInWorkspace(
diff --git a/extension/src/mcp/AspireMcpServerDefinitionProvider.ts b/extension/src/mcp/AspireMcpServerDefinitionProvider.ts
new file mode 100644
index 00000000000..aee79824805
--- /dev/null
+++ b/extension/src/mcp/AspireMcpServerDefinitionProvider.ts
@@ -0,0 +1,83 @@
+import * as vscode from 'vscode';
+import { resolveCliPath } from '../utils/cliPath';
+import { extensionLogOutputChannel } from '../utils/logging';
+import { getRegisterMcpServerInWorkspace, registerMcpServerInWorkspaceSetting } from '../utils/settings';
+
+/**
+ * Provides the Aspire MCP server definition to VS Code so it appears
+ * automatically in the MCP tools list when the Aspire CLI is available
+ * and the workspace contains an Aspire project.
+ */
+export class AspireMcpServerDefinitionProvider implements vscode.McpServerDefinitionProvider {
+ private readonly _onDidChange = new vscode.EventEmitter();
+ readonly onDidChangeMcpServerDefinitions = this._onDidChange.event;
+
+ private _cliPath: string | undefined;
+ private _cliAvailable: boolean = false;
+ private _shouldProvide: boolean = false;
+ private _configChangeDisposable: vscode.Disposable | undefined;
+ private _workspaceFolderChangeDisposable: vscode.Disposable | undefined;
+
+ constructor() {
+ // Re-evaluate when the setting changes
+ this._configChangeDisposable = vscode.workspace.onDidChangeConfiguration(e => {
+ if (e.affectsConfiguration(registerMcpServerInWorkspaceSetting)) {
+ this.refresh();
+ }
+ });
+
+ // Re-evaluate when workspace folders change
+ this._workspaceFolderChangeDisposable = vscode.workspace.onDidChangeWorkspaceFolders(() => {
+ this.refresh();
+ });
+ }
+
+ async refresh(): Promise {
+ const [cliResult, shouldProvide] = await Promise.all([
+ resolveCliPath(),
+ checkShouldProvideMcpServer(),
+ ]);
+
+ const changed =
+ this._cliAvailable !== cliResult.available ||
+ this._cliPath !== cliResult.cliPath ||
+ this._shouldProvide !== shouldProvide;
+
+ this._cliAvailable = cliResult.available;
+ this._cliPath = cliResult.cliPath;
+ this._shouldProvide = shouldProvide;
+
+ if (changed) {
+ extensionLogOutputChannel.info(`Aspire MCP server definition changed: cliAvailable=${cliResult.available}, shouldProvide=${shouldProvide}`);
+ this._onDidChange.fire();
+ }
+ }
+
+ provideMcpServerDefinitions(_token: vscode.CancellationToken): vscode.ProviderResult {
+ if (!this._cliAvailable || !this._shouldProvide || !this._cliPath) {
+ return [];
+ }
+
+ return [new vscode.McpStdioServerDefinition('Aspire', this._cliPath, ['agent', 'mcp'])];
+ }
+
+ dispose(): void {
+ this._configChangeDisposable?.dispose();
+ this._workspaceFolderChangeDisposable?.dispose();
+ this._onDidChange.dispose();
+ }
+}
+
+/**
+ * Determines whether the Aspire MCP server should be provided.
+ *
+ * The server is provided only when workspace folders are open and the
+ * "aspire.registerMcpServerInWorkspace" setting is enabled.
+ */
+async function checkShouldProvideMcpServer(): Promise {
+ if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) {
+ return false;
+ }
+
+ return getRegisterMcpServerInWorkspace();
+}
diff --git a/extension/src/utils/settings.ts b/extension/src/utils/settings.ts
new file mode 100644
index 00000000000..6c1c8263617
--- /dev/null
+++ b/extension/src/utils/settings.ts
@@ -0,0 +1,17 @@
+import * as vscode from 'vscode';
+
+const aspireConfigSection = 'aspire';
+
+const registerMcpServerInWorkspaceSettingName = 'registerMcpServerInWorkspace';
+export const registerMcpServerInWorkspaceSetting = `${aspireConfigSection}.${registerMcpServerInWorkspaceSettingName}`;
+
+/**
+ * Returns the Aspire extension configuration object.
+ */
+function getAspireConfig(): vscode.WorkspaceConfiguration {
+ return vscode.workspace.getConfiguration(aspireConfigSection);
+}
+
+export function getRegisterMcpServerInWorkspace(): boolean {
+ return getAspireConfig().get(registerMcpServerInWorkspaceSettingName, false);
+}
diff --git a/extension/src/vscode.proposed.mcpServerDefinitions.d.ts b/extension/src/vscode.proposed.mcpServerDefinitions.d.ts
new file mode 100644
index 00000000000..33402753140
--- /dev/null
+++ b/extension/src/vscode.proposed.mcpServerDefinitions.d.ts
@@ -0,0 +1,40 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+// Type declarations for the vscode proposed API: mcpServerDefinitions
+// https://github.com/microsoft/vscode/blob/main/src/vscode-dts/vscode.proposed.mcpServerDefinitions.d.ts
+
+declare module 'vscode' {
+
+ export class McpStdioServerDefinition {
+ readonly label: string;
+ cwd?: Uri;
+ command: string;
+ args: string[];
+ env: Record;
+ version?: string;
+ constructor(label: string, command: string, args?: string[], env?: Record, version?: string);
+ }
+
+ export class McpHttpServerDefinition {
+ readonly label: string;
+ uri: Uri;
+ headers: Record;
+ version?: string;
+ constructor(label: string, uri: Uri, headers?: Record, version?: string);
+ }
+
+ export type McpServerDefinition = McpStdioServerDefinition | McpHttpServerDefinition;
+
+ export interface McpServerDefinitionProvider {
+ readonly onDidChangeMcpServerDefinitions?: Event;
+ provideMcpServerDefinitions(token: CancellationToken): ProviderResult;
+ resolveMcpServerDefinition?(server: T, token: CancellationToken): ProviderResult;
+ }
+
+ export namespace lm {
+ export function registerMcpServerDefinitionProvider(id: string, provider: McpServerDefinitionProvider): Disposable;
+ }
+}