#
tokens: 24294/50000 27/27 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── .vscode
│   ├── extensions.json
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── .vscode-test.mjs
├── .vscodeignore
├── CHANGELOG.md
├── eslint.config.mjs
├── example.bifrost.config.json
├── example.mdc
├── ExampleCursorRules.md
├── icon.png
├── icon.txt
├── LICENSE
├── package-lock.json
├── package.json
├── placeholder.txt
├── README.md
├── src
│   ├── config.ts
│   ├── debugPanel.ts
│   ├── extension.ts
│   ├── globals.ts
│   ├── helpers.ts
│   ├── images
│   │   ├── commands.png
│   │   ├── cursor.png
│   │   └── debug_panel.png
│   ├── mcpresponses.ts
│   ├── rosyln.ts
│   ├── test
│   │   └── extension.test.ts
│   ├── toolRunner.ts
│   ├── tools.ts
│   └── webview.ts
├── tsconfig.json
├── vsc-extension-quickstart.md
└── webpack.config.js
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
out
dist
node_modules
.vscode-test/
*.vsix
*/debug-profile
```

--------------------------------------------------------------------------------
/.vscode-test.mjs:
--------------------------------------------------------------------------------

```
import { defineConfig } from '@vscode/test-cli';

export default defineConfig({
	files: 'out/test/**/*.test.js',
});

```

--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------

```
.vscode/**
.vscode-test/**
out/**
node_modules/**
src/**
.gitignore
.yarnrc
webpack.config.js
vsc-extension-quickstart.md
**/tsconfig.json
**/eslint.config.mjs
**/*.map
**/*.ts
**/.vscode-test.*

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Bifrost - VSCode Dev Tools MCP Server
<a href="https://marketplace.visualstudio.com/items?itemName=ConnorHallman.bifrost-mcp">
  <img src="https://img.shields.io/visual-studio-marketplace/d/ConnorHallman.bifrost-mcp?label=VSCode%20Extension%20Downloads&cacheSeconds=3600" 
       alt="VSCode Extension Downloads" 
       width="250">
</a>

This VS Code extension provides a Model Context Protocol (MCP) server that exposes VSCode's powerful development tools and language features to AI tools. It enables advanced code navigation, analysis, and manipulation capabilities when using AI coding assistants that support the MCP protocol.

![image](https://raw.githubusercontent.com/biegehydra/BifrostMCP/refs/heads/master/src/images/cursor.png)

## Table of Contents
- [Features](#features)
- [Installation/Usage](#usage)
- [Multi-Project Support](#multiple-project-support)
- [Available Tools](#available-tools)
- [Available Commands](#available-commands)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [Debugging](#debugging)
- [License](#license)

## Features

- **Language Server Integration**: Access VSCode's language server capabilities for any supported language
- **Code Navigation**: Find references, definitions, implementations, and more
- **Symbol Search**: Search for symbols across your workspace
- **Code Analysis**: Get semantic tokens, document symbols, and type information
- **Smart Selection**: Use semantic selection ranges for intelligent code selection
- **Code Actions**: Access refactoring suggestions and quick fixes
- **HTTP/SSE Server**: Exposes language features over an MCP-compatible HTTP server
- **AI Assistant Integration**: Ready to work with AI assistants that support the MCP protocol

## Usage

### Installation

1. Install [the extension](https://marketplace.visualstudio.com/items?itemName=ConnorHallman.bifrost-mcp) from the VS Code marketplace
2. Install any language-specific extensions you need for your development
3. Open your project in VS Code

### Configuration

The extension will automatically start an MCP server when activated. To configure an AI assistant to use this server:

1. The server runs on port 8008 by default (configurable with `bifrost.config.json`)
2. Configure your MCP-compatible AI assistant to connect to:
   - SSE endpoint: `http://localhost:8008/sse`
   - Message endpoint: `http://localhost:8008/message`

### LLM Rules
I have also provided sample rules that can be used in .cursorrules files for better results.

[Example Cursor Rules](https://github.com/biegehydra/BifrostMCP/blob/master/ExampleCursorRules.md)

[Example MDC Rules](https://github.com/biegehydra/BifrostMCP/blob/master/example.mdc)

### Cline Installation
- Step 1. Install [Supergateway](https://github.com/supercorp-ai/supergateway)
- Step 2. Add config to cline
- Step 3. It will show up red but seems to work fine

#### Windows Config
```json
{
  "mcpServers": {
    "Bifrost": {
      "command": "cmd",
      "args": [
        "/c",
        "npx",
        "-y",
        "supergateway",
        "--sse",
        "http://localhost:8008/sse"
      ],
      "disabled": false,
      "autoApprove": [],
      "timeout": 600
    }
  }
}
```

#### Mac/Linux Config
```json
{
  "mcpServers": {
    "Bifrost": {
      "command": "npx",
      "args": [
        "-y",
        "supergateway",
        "--sse",
        "http://localhost:8008/sse"
      ],
      "disabled": false,
      "autoApprove": [],
      "timeout": 600
    }
  }
}
```

### Roo Code Installation
- Step 1: Add the SSE config to your global or project-based MCP configuration
```json
{
  "mcpServers": {
    "Bifrost": {
      "url": "http://localhost:8008/sse"
    }
  }
}
```

![Screenshot_78](https://github.com/user-attachments/assets/55588c9e-7f88-4830-b87f-184018873ca1)

Follow this video to install and use with cursor

#### FOR NEW VERSIONS OF CURSOR, USE THIS CODE
```json
{
  "mcpServers": {
    "Bifrost": {
      "url": "http://localhost:8008/sse"
    }
  }
}
```

## Multiple Project Support

When working with multiple projects, each project can have its own dedicated MCP server endpoint and port. This is useful when you have multiple VS Code windows open or are working with multiple projects that need language server capabilities.

### Project Configuration

Create a `bifrost.config.json` file in your project root:

```json
{
    "projectName": "MyProject",
    "description": "Description of your project",
    "path": "/my-project",
    "port": 5642
}
```

The server will use this configuration to:
- Create project-specific endpoints (e.g., `http://localhost:5642/my-project/sse`)
- Provide project information to AI assistants
- Use a dedicated port for each project
- Isolate project services from other running instances

### Example Configurations

1. Backend API Project:
```json
{
    "projectName": "BackendAPI",
    "description": "Node.js REST API with TypeScript",
    "path": "/backend-api",
    "port": 5643
}
```

2. Frontend Web App:
```json
{
    "projectName": "FrontendApp",
    "description": "React frontend application",
    "path": "/frontend-app",
    "port": 5644
}
```

### Port Configuration

Each project should specify its own unique port to avoid conflicts when multiple VS Code instances are running:

- The `port` field in `bifrost.config.json` determines which port the server will use
- If no port is specified, it defaults to 8008 for backwards compatibility
- Choose different ports for different projects to ensure they can run simultaneously
- The server will fail to start if the configured port is already in use, requiring you to either:
  - Free up the port
  - Change the port in the config
  - Close the other VS Code instance using that port

### Connecting to Project-Specific Endpoints

Update your AI assistant configuration to use the project-specific endpoint and port:

```json
{
  "mcpServers": {
    "BackendAPI": {
      "url": "http://localhost:5643/backend-api/sse"
    },
    "FrontendApp": {
      "url": "http://localhost:5644/frontend-app/sse"
    }
  }
}
```

### Backwards Compatibility

If no `bifrost.config.json` is present, the server will use the default configuration:
- Port: 8008
- SSE endpoint: `http://localhost:8008/sse`
- Message endpoint: `http://localhost:8008/message`

This maintains compatibility with existing configurations and tools.

## Available Tools

The extension provides access to many VSCode language features including:

* **find\_usages**: Locate all symbol references.
* **go\_to\_definition**: Jump to symbol definitions instantly.
* **find\_implementations**: Discover implementations of interfaces/abstract methods.
* **get\_hover\_info**: Get rich symbol docs on hover.
* **get\_document\_symbols**: Outline all symbols in a file.
* **get\_completions**: Context-aware auto-completions.
* **get\_signature\_help**: Function parameter hints and overloads.
* **get\_rename\_locations**: Safely get location of places to perform a rename across the project.
* **rename**: Perform rename on a symbol
* **get\_code\_actions**: Quick fixes, refactors, and improvements.
* **get\_semantic\_tokens**: Enhanced highlighting data.
* **get\_call\_hierarchy**: See incoming/outgoing call relationships.
* **get\_type\_hierarchy**: Visualize class and interface inheritance.
* **get\_code\_lens**: Inline insights (references, tests, etc.).
* **get\_selection\_range**: Smart selection expansion for code blocks.
* **get\_type\_definition**: Jump to underlying type definitions.
* **get\_declaration**: Navigate to symbol declarations.
* **get\_document\_highlights**: Highlight all occurrences of a symbol.
* **get\_workspace\_symbols**: Search symbols across your entire workspace.

## Requirements

- Visual Studio Code version 1.93.0 or higher
- Appropriate language extensions for the languages you want to work with (e.g., C# extension for C# files)

### Available Commands

- `Bifrost MCP: Start Server` - Manually start the MCP server on port 8008
- `Bifrost MCP: Start Server on port` - Manually start the MCP server on specified port
- `Bifrost MCP: Stop Server` - Stop the running MCP server
- `Bifrost MCP: Open Debug Panel` - Open the debug panel to test available tools

![image](https://raw.githubusercontent.com/biegehydra/BifrostMCP/refs/heads/master/src/images/commands.png)

## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=biegehydra/BifrostMCP&type=Date)](https://star-history.com/#biegehydra/BifrostMCP&Date)

## Example Tool Usage

### Find References
```json
{
  "name": "find_usages",
  "arguments": {
    "textDocument": {
      "uri": "file:///path/to/your/file"
    },
    "position": {
      "line": 10,
      "character": 15
    },
    "context": {
      "includeDeclaration": true
    }
  }
}
```

### Workspace Symbol Search
```json
{
  "name": "get_workspace_symbols",
  "arguments": {
    "query": "MyClass"
  }
}
```

## Troubleshooting

If you encounter issues:

1. Ensure you have the appropriate language extensions installed for your project
2. Check that your project has loaded correctly in VSCode
3. Verify that port 8008 is available on your system
4. Check the VSCode output panel for any error messages

## Contributing
Here are [Vscodes commands](https://github.com/microsoft/vscode-docs/blob/main/api/references/commands.md?plain=1) if you want to add additional functionality go ahead. I think we still need rename and a few others.
Please feel free to submit issues or pull requests to the [GitHub repository](https://github.com/biegehydra/csharplangmcpserver).

`vsce package`

## Debugging
Use the `MCP: Open Debug Panel` command
![image](https://raw.githubusercontent.com/biegehydra/BifrostMCP/refs/heads/master/src/images/debug_panel.png)

## License

This extension is licensed under the APGL-3.0 License.

```

--------------------------------------------------------------------------------
/src/mcpresponses.ts:
--------------------------------------------------------------------------------

```typescript
import { ReferencesAndPreview } from "./rosyln";

export type FindUsagesResponse = {
    references: ReferencesAndPreview[];
};
```

--------------------------------------------------------------------------------
/example.bifrost.config.json:
--------------------------------------------------------------------------------

```json
{
    "projectName": "MyProject",
    "description": "A sample project using the Bifrost MCP server",
    "path": "/my-project"
} 
```

--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------

```json
{
  // See http://go.microsoft.com/fwlink/?LinkId=827846
  // for the documentation about the extensions.json format
  "recommendations": ["dbaeumer.vscode-eslint", "amodio.tsl-problem-matcher", "ms-vscode.extension-test-runner"]
}

```

--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# Change Log

All notable changes to the "csharplangmcpserver" extension will be documented in this file.

Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.

## [Unreleased]

- Initial release
```

--------------------------------------------------------------------------------
/src/globals.ts:
--------------------------------------------------------------------------------

```typescript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import type { Server as HttpServer } from 'http';

export let mcpServer: Server | undefined;
export let httpServer: HttpServer | undefined;

export const setMcpServer = (server: Server | undefined) => {
    mcpServer = server;
}

export const setHttpServer = (server: HttpServer | undefined) => {
    httpServer = server;
}

```

--------------------------------------------------------------------------------
/src/test/extension.test.ts:
--------------------------------------------------------------------------------

```typescript
import * as assert from 'assert';

// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
// import * as myExtension from '../../extension';

suite('Extension Test Suite', () => {
	vscode.window.showInformationMessage('Start all tests.');

	test('Sample test', () => {
		assert.strictEqual(-1, [1, 2, 3].indexOf(5));
		assert.strictEqual(-1, [1, 2, 3].indexOf(0));
	});
});

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
	"compilerOptions": {
		"module": "Node16",
		"target": "ES2022",
		"lib": [
			"ES2022"
		],
		"sourceMap": true,
		"rootDir": "src",
		"strict": true,   /* enable all strict type-checking options */
		/* Additional Checks */
		// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
		// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
		// "noUnusedParameters": true,  /* Report errors on unused parameters. */
	}
}

```

--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------

```json
// Place your settings in this file to overwrite default and user settings.
{
	"files.exclude": {
		"out": false, // set this to true to hide the "out" folder with the compiled JS files
		"dist": false // set this to true to hide the "dist" folder with the compiled JS files
	},
	"search.exclude": {
		"out": true, // set this to false to include "out" folder in search results
		"dist": true // set this to false to include "dist" folder in search results
	},
	// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
	"typescript.tsc.autoDetect": "off"
}

```

--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------

```json
// A launch configuration that compiles the extension and then opens it inside a new window
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
	"version": "0.2.0",
	"configurations": [
		{
			"name": "Run Extension",
			"type": "extensionHost",
			"request": "launch",
			"args": [
				"--extensionDevelopmentPath=${workspaceFolder}"
			],
			"outFiles": [
				"${workspaceFolder}/dist/**/*.js"
			],
			"preLaunchTask": "${defaultBuildTask}"
		}
	]
}

```

--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------

```
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";

export default [{
    files: ["**/*.ts"],
}, {
    plugins: {
        "@typescript-eslint": typescriptEslint,
    },

    languageOptions: {
        parser: tsParser,
        ecmaVersion: 2022,
        sourceType: "module",
    },

    rules: {
        "@typescript-eslint/naming-convention": ["warn", {
            selector: "import",
            format: ["camelCase", "PascalCase"],
        }],

        curly: "warn",
        eqeqeq: "warn",
        "no-throw-literal": "warn",
        semi: "warn",
    },
}];
```

--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------

```json
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "npm",
			"script": "watch",
			"problemMatcher": "$ts-webpack-watch",
			"isBackground": true,
			"presentation": {
				"reveal": "never",
				"group": "watchers"
			},
			"group": {
				"kind": "build",
				"isDefault": true
			}
		},
		{
			"type": "npm",
			"script": "watch-tests",
			"problemMatcher": "$tsc-watch",
			"isBackground": true,
			"presentation": {
				"reveal": "never",
				"group": "watchers"
			},
			"group": "build"
		},
		{
			"label": "tasks: watch-tests",
			"dependsOn": [
				"npm: watch",
				"npm: watch-tests"
			],
			"problemMatcher": []
		}
	]
}

```

--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------

```javascript
//@ts-check

'use strict';

const path = require('path');

//@ts-check
/** @typedef {import('webpack').Configuration} WebpackConfig **/

/** @type WebpackConfig */
const extensionConfig = {
  target: 'node', // VS Code extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
	mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')

  entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
  output: {
    // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
    path: path.resolve(__dirname, 'dist'),
    filename: 'extension.js',
    libraryTarget: 'commonjs2'
  },
  externals: {
    vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
    // modules added here also need to be added in the .vscodeignore file
  },
  resolve: {
    // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
    extensions: ['.ts', '.js']
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'ts-loader'
          }
        ]
      }
    ]
  },
  devtool: 'nosources-source-map',
  infrastructureLogging: {
    level: "log", // enables logging required for problem matchers
  },
};
module.exports = [ extensionConfig ];
```

--------------------------------------------------------------------------------
/src/rosyln.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Matches the C# `ReferenceParams` class, which extends TextDocumentPositionParams
 * and adds:
 *   - context (ReferenceContext)
 *   - workDoneToken? (IProgress<WorkDoneProgress>)
 *   - partialResultToken? (IProgress<Location[]>)
 */
export interface ReferenceParams extends TextDocumentPositionParams {
    /**
     * Matches C# `ReferenceParams.Context`.
     */
    context: ReferenceContext;
}

/**
 * Matches the C# `ReferenceContext` class
 */
export interface ReferenceContext {
    /**
     * Include the declaration of the current symbol.
     */
    includeDeclaration: boolean;
}

/**
 * Matches the C# `TextDocumentPositionParams` base class,
 * which has a TextDocumentIdentifier and a Position.
 */
export interface TextDocumentPositionParams {
    /**
     * Matches C# `TextDocumentPositionParams.TextDocument`
     */
    textDocument: TextDocumentIdentifier;

    /**
     * Matches C# `TextDocumentPositionParams.Position`
     */
    position: Position;
}

/**
 * Matches the C# `TextDocumentIdentifier` with its `uri` property.
 */
export interface TextDocumentIdentifier {
    /**
     * The URI of the text document (C# `Uri Uri`).
     */
    uri: string;
}

/**
 * Matches C# `Position`, which contains a `Line` and `Character`.
 */
export interface Position {
    line: number;
    character: number;
}

export interface Range {
    start: Position;
    end: Position;
}

export interface ReferencesResponse {
    uri: string;
    range: Range;
}

export interface ReferencesAndPreview extends ReferencesResponse {
    preview: string;
}

export interface RenameEdit {
    uri: string;
    edits: {
        range: {
            start: { line: number; character: number; };
            end: { line: number; character: number; };
        };
        newText: string;
    }[];
}
```

--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------

```typescript
import * as vscode from 'vscode';
import * as path from 'path';

export interface BifrostConfig {
    projectName: string;
    description: string;
    path: string;
    port: number;
}

export const DEFAULT_CONFIG: BifrostConfig = {
    projectName: "language-tools",
    description: "Language tools and code analysis",
    path: "",  // Empty path for backwards compatibility
    port: 8008 // Default port for backwards compatibility
};

export async function findBifrostConfig(workspaceFolder: vscode.WorkspaceFolder): Promise<BifrostConfig> {
    const configPath = path.join(workspaceFolder.uri.fsPath, 'bifrost.config.json');
    
    try {
        // Check if config file exists and read it
        const configFile = await vscode.workspace.fs.readFile(vscode.Uri.file(configPath));
        const configContent = Buffer.from(configFile).toString('utf8');
        const config: BifrostConfig = JSON.parse(configContent);
        
        // Validate config
        if (!config.projectName || !config.description || config.path === undefined) {
            throw new Error('Invalid bifrost.config.json: missing required fields');
        }

        // Use default port if not specified
        if (config.port === undefined) {
            config.port = DEFAULT_CONFIG.port;
        }
        
        return {
            projectName: config.projectName,
            description: config.description,
            path: config.path,
            port: config.port
        };
    } catch (error) {
        console.log(`No valid bifrost.config.json found in ${workspaceFolder.name}, using default config`);
        return DEFAULT_CONFIG;
    }
}

export function getProjectBasePath(config: BifrostConfig): string {
    // For backwards compatibility, if path is empty, return empty string (root path)
    if (!config.path) {
        return '';
    }
    if (!config.path.startsWith('/')) {
        config.path = '/' + config.path;
    }
    return `${config.path}`;
} 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "bifrost-mcp",
  "displayName": "Bifrost - VSCode Dev Tools MCP Server",
  "description": "An MCP server that exposes features of VSCode dev tools to the MCP clients",
  "version": "0.0.14",
  "publisher": "ConnorHallman",
  "icon": "icon.png",
  "repository": {
    "type": "git",
    "url": "https://github.com/biegehydra/csharplangmcpserver"
  },
  "engines": {
    "vscode": "^1.93.0"
  },
  "categories": [
    "Other",
    "Programming Languages",
    "Language Packs"
  ],
  "keywords": [
    "C#",
    "MCP",
    "dotnet",
    "AI",
    "find references"
  ],
  "activationEvents": [
    "onStartupFinished"
  ],
  "main": "./dist/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "bifrost-mcp.startServer",
        "title": "Bifrost MCP: Start Server"
      },
      {
        "command": "bifrost-mcp.startServerOnPort",
        "title": "Bifrost MCP: Start Server on Port"
      },
      {
        "command": "bifrost-mcp.stopServer",
        "title": "Bifrost MCP: Stop Server"
      },
      {
        "command": "bifrost-mcp.openDebugPanel",
        "title": "Bifrost MCP: Open Debug Panel"
      }
    ]
  },
  "scripts": {
    "vscode:prepublish": "npm run package",
    "compile": "webpack",
    "watch": "webpack --watch",
    "package": "webpack --mode production --devtool hidden-source-map",
    "compile-tests": "tsc -p . --outDir out",
    "watch-tests": "tsc -p . -w --outDir out",
    "pretest": "npm run compile-tests && npm run compile && npm run lint",
    "lint": "eslint src",
    "test": "vscode-test"
  },
  "devDependencies": {
    "@types/mocha": "^10.0.10",
    "@types/node": "20.x",
    "@types/vscode": "^1.93.0",
    "@typescript-eslint/eslint-plugin": "^8.25.0",
    "@typescript-eslint/parser": "^8.25.0",
    "@vscode/test-cli": "^0.0.10",
    "@vscode/test-electron": "^2.4.1",
    "eslint": "^9.21.0",
    "ts-loader": "^9.5.2",
    "typescript": "^5.7.3",
    "vscode-languageclient": "^9.0.1",
    "webpack": "^5.98.0",
    "webpack-cli": "^6.0.1"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.6.1",
    "@types/cors": "^2.8.17",
    "@types/express": "^5.0.0",
    "cors": "^2.8.5",
    "express": "^5.0.1"
  }
}

```

--------------------------------------------------------------------------------
/vsc-extension-quickstart.md:
--------------------------------------------------------------------------------

```markdown
# Welcome to your VS Code Extension

## What's in the folder

* This folder contains all of the files necessary for your extension.
* `package.json` - this is the manifest file in which you declare your extension and command.
  * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
* `src/extension.ts` - this is the main file where you will provide the implementation of your command.
  * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
  * We pass the function containing the implementation of the command as the second parameter to `registerCommand`.

## Setup

* install the recommended extensions (amodio.tsl-problem-matcher, ms-vscode.extension-test-runner, and dbaeumer.vscode-eslint)


## Get up and running straight away

* Press `F5` to open a new window with your extension loaded.
* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`.
* Set breakpoints in your code inside `src/extension.ts` to debug your extension.
* Find output from your extension in the debug console.

## Make changes

* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`.
* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.


## Explore the API

* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`.

## Run tests

* Install the [Extension Test Runner](https://marketplace.visualstudio.com/items?itemName=ms-vscode.extension-test-runner)
* Run the "watch" task via the **Tasks: Run Task** command. Make sure this is running, or tests might not be discovered.
* Open the Testing view from the activity bar and click the Run Test" button, or use the hotkey `Ctrl/Cmd + ; A`
* See the output of the test result in the Test Results view.
* Make changes to `src/test/extension.test.ts` or create new test files inside the `test` folder.
  * The provided test runner will only consider files matching the name pattern `**.test.ts`.
  * You can create folders inside the `test` folder to structure your tests any way you want.

## Go further

* Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension).
* [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VS Code extension marketplace.
* Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).

```

--------------------------------------------------------------------------------
/ExampleCursorRules.md:
--------------------------------------------------------------------------------

```markdown
# Cursor Agent Rules for Code Modification

## 1. Pre-Edit Analysis Requirements
BEFORE making any code changes, MUST:
- Use `mcp__get_document_symbols` on the target file to understand its structure
- Use `mcp__find_usages` on any symbol being modified to identify all affected locations
- Use `mcp__get_type_definition` and/or `mcp__go_to_definition` for any types or symbols being modified
- Use `mcp__get_hover_info` to verify function signatures and type information

## 2. Impact Analysis Rules
BEFORE proceeding with changes:
1. If `mcp__find_usages` reveals usage in multiple files:
   - Must analyze each usage context
   - Must verify type compatibility across all uses
   - Must plan changes for all affected locations

2. If modifying interfaces or types:
   - Must use `mcp__find_implementations` to locate all implementations
   - Must ensure changes won't break implementing classes
   - Must verify backward compatibility or plan updates for all implementations

## 3. Type Safety Rules
MUST maintain type safety by:
1. Using `mcp__get_type_definition` for:
   - All modified parameters
   - Return types
   - Interface members
   - Generic constraints

2. Using `mcp__get_hover_info` to verify:
   - Function signatures
   - Type constraints
   - Optional vs required properties

## 4. Code Modification Sequence
When making changes:
1. First gather context:
```typescript
// Example sequence
await mcp__get_document_symbols(file)
await mcp__find_usages(symbol)
await mcp__get_type_definition(symbol)
await mcp__get_hover_info(symbol)
```

2. Then analyze impact:
```typescript
// For each usage found
await mcp__get_hover_info(usage)
await mcp__get_type_definition(relatedTypes)
```

3. Only then use `edit_file`

## 5. Post-Edit Verification
After making changes:
1. Use `mcp__get_document_symbols` to verify file structure remains valid
2. Use `mcp__find_usages` to verify all usages are still compatible
3. Use `mcp__get_hover_info` to verify new type signatures

## 6. Special Cases

### When Modifying React Components:
1. Must use `mcp__find_usages` to:
   - Find all component instances
   - Verify prop usage
   - Check for defaultProps and propTypes

2. Must use `mcp__get_type_definition` for:
   - Prop interfaces
   - State types
   - Context types

### When Modifying APIs/Functions:
1. Must use `mcp__get_call_hierarchy` to:
   - Understand the call chain
   - Identify dependent functions
   - Verify changes won't break callers

### When Modifying Types/Interfaces:
1. Must use `mcp__find_implementations` to:
   - Locate all implementing classes
   - Verify compatibility
   - Plan updates if needed

## 7. Error Prevention Rules

1. NEVER modify a symbol without first:
```typescript
await mcp__find_usages(symbol)
await mcp__get_type_definition(symbol)
```

2. NEVER modify a type without:
```typescript
await mcp__find_implementations(type)
await mcp__get_hover_info(type)
```

3. NEVER modify a function signature without:
```typescript
await mcp__get_call_hierarchy(function)
await mcp__find_usages(function)
```

## 8. Documentation Requirements

When explaining changes, must reference:
1. What tools were used to analyze the code
2. What usages were found
3. What type information was verified
4. What impact analysis was performed

Example:
```markdown
I analyzed the code using:
1. mcp__find_usages to locate all 5 usages of handleSubmit
2. mcp__get_type_definition to verify the function signature
3. mcp__get_hover_info to check parameter types
4. mcp__get_document_symbols to understand the component structure
```

## 9. Change Abort Conditions

Must ABORT changes if:
1. `mcp__find_usages` reveals unexpected usages
2. `mcp__get_type_definition` shows incompatible types
3. `mcp__find_implementations` shows breaking changes
4. Unable to verify full impact using available tools

## 10. Tool Priority Order

When analyzing code, use tools in this order:
1. `mcp__get_document_symbols` (understand structure)
2. `mcp__find_usages` (understand impact)
3. `mcp__get_type_definition` (verify types)
4. `mcp__get_hover_info` (verify signatures)
5. Additional tools as needed

```

--------------------------------------------------------------------------------
/src/helpers.ts:
--------------------------------------------------------------------------------

```typescript
import * as vscode from 'vscode';
export interface DocumentSymbolResult {
    name: string;
    detail: string;
    kind: string;
    range: {
        start: { line: number; character: number };
        end: { line: number; character: number };
    };
    selectionRange: {
        start: { line: number; character: number };
        end: { line: number; character: number };
    };
    children: DocumentSymbolResult[];
}

export function convertSymbol(symbol: vscode.DocumentSymbol): DocumentSymbolResult {
    return {
        name: symbol.name,
        detail: symbol.detail,
        kind: getSymbolKindString(symbol.kind),
        range: {
            start: {
                line: symbol.range.start.line,
                character: symbol.range.start.character
            },
            end: {
                line: symbol.range.end.line,
                character: symbol.range.end.character
            }
        },
        selectionRange: {
            start: {
                line: symbol.selectionRange.start.line,
                character: symbol.selectionRange.start.character
            },
            end: {
                line: symbol.selectionRange.end.line,
                character: symbol.selectionRange.end.character
            }
        },
        children: symbol.children.map(convertSymbol)
    };
}

export function getSymbolKindString(kind: vscode.SymbolKind): string {
    return vscode.SymbolKind[kind];
}

export async function getPreview(uri: vscode.Uri, line: number | undefined): Promise<string> {
    if (line === null || line === undefined) {
        return "";
    }
    try{
        const document = await vscode.workspace.openTextDocument(uri);
        const lineText = document.lineAt(line).text.trim();
        return lineText;
    } catch (error) {
        console.error(`Error getting preview for ${uri}: ${error}`);
        return "Failed to get preview";
    }
}
 
export function createVscodePosition(line: number, character: number): vscode.Position | undefined {
    if (line === null || line === undefined) {
        return undefined;
    }
    if (character === null || character === undefined) {
        return undefined;
    }
    return new vscode.Position(
        Math.max(line, 0),
        Math.max(character, 0)
    );
}

export async function asyncMap<T, R>(array: T[], asyncCallback: (item: T) => Promise<R>): Promise<R[]> {
    return Promise.all(array.map(asyncCallback));
}

export function convertSemanticTokens(semanticTokens: vscode.SemanticTokens, document: vscode.TextDocument): any {
    const tokens: any[] = [];
    let prevLine = 0;
    let prevChar = 0;

    // Token types and modifiers from VS Code
    const tokenTypes = [
        'namespace', 'type', 'class', 'enum', 'interface',
        'struct', 'typeParameter', 'parameter', 'variable', 'property',
        'enumMember', 'event', 'function', 'method', 'macro',
        'keyword', 'modifier', 'comment', 'string', 'number',
        'regexp', 'operator', 'decorator'
    ];

    const tokenModifiers = [
        'declaration', 'definition', 'readonly', 'static',
        'deprecated', 'abstract', 'async', 'modification',
        'documentation', 'defaultLibrary'
    ];

    // Process tokens in groups of 5 (format: deltaLine, deltaStartChar, length, tokenType, tokenModifiers)
    for (let i = 0; i < semanticTokens.data.length; i += 5) {
        const deltaLine = semanticTokens.data[i];
        const deltaStartChar = semanticTokens.data[i + 1];
        const length = semanticTokens.data[i + 2];
        const tokenType = tokenTypes[semanticTokens.data[i + 3]] || 'unknown';
        const tokenModifiersBitset = semanticTokens.data[i + 4];

        // Calculate absolute position
        const line = prevLine + deltaLine;
        const startChar = deltaLine === 0 ? prevChar + deltaStartChar : deltaStartChar;

        // Get the actual text content
        const tokenText = document.lineAt(line).text.substr(startChar, length);

        // Convert token modifiers bitset to array of strings
        const modifiers = tokenModifiers.filter((_, index) => tokenModifiersBitset & (1 << index));

        tokens.push({
            line,
            startCharacter: startChar,
            length,
            tokenType,
            modifiers,
            text: tokenText
        });

        prevLine = line;
        prevChar = startChar;
    }

    return tokens;
}

export const transformSingleLocation = async (loc: vscode.Location | vscode.LocationLink): Promise<any> => {
    const uri = 'targetUri' in loc ? loc.targetUri : loc.uri;
    const range = 'targetRange' in loc ? loc.targetRange : loc.range;
    
    return {
        uri: uri.toString(),
        range: range ? {
            start: {
                line: range.start.line,
                character: range.start.character
            },
            end: {
                line: range.end.line,
                character: range.end.character
            }
        } : undefined,
        preview: await getPreview(uri, range?.start.line)
    };
};

export const transformLocations = async (locations: (vscode.Location | vscode.LocationLink)[]): Promise<any[]> => {
    if (!locations) {
        return [];
    }
    return asyncMap(locations, transformSingleLocation);
};


```

--------------------------------------------------------------------------------
/src/debugPanel.ts:
--------------------------------------------------------------------------------

```typescript
import * as vscode from 'vscode';
import { webviewHtml } from './webview';
import { mcpServer } from './globals';
import { runTool } from './toolRunner';
let debugPanel: vscode.WebviewPanel | undefined;
export function createDebugPanel(context: vscode.ExtensionContext) {
    if (debugPanel) {
        debugPanel.reveal();
        return;
    }

    debugPanel = vscode.window.createWebviewPanel(
        'mcpDebug',
        'MCP Debug Panel',
        vscode.ViewColumn.Two,
        {
            enableScripts: true
        }
    );

    // Get workspace files for autocomplete
    async function getWorkspaceFiles(): Promise<string[]> {
        const workspaceFolders = vscode.workspace.workspaceFolders;
        if (!workspaceFolders) return [];

        const files: string[] = [];
        for (const folder of workspaceFolders) {
            const pattern = new vscode.RelativePattern(folder, '**/*');
            const uris = await vscode.workspace.findFiles(pattern);
            files.push(...uris.map(uri => uri.toString()));
        }
        return files;
    }

    // Send initial file list and set up file watcher
    getWorkspaceFiles().then(files => {
        debugPanel?.webview.postMessage({ type: 'files', files });
    });

    const fileWatcher = vscode.workspace.createFileSystemWatcher('**/*');
    fileWatcher.onDidCreate(() => {
        getWorkspaceFiles().then(files => {
            debugPanel?.webview.postMessage({ type: 'files', files });
        });
    });
    fileWatcher.onDidDelete(() => {
        getWorkspaceFiles().then(files => {
            debugPanel?.webview.postMessage({ type: 'files', files });
        });
    });

    debugPanel.onDidDispose(() => {
        fileWatcher.dispose();
        debugPanel = undefined;
    });
    debugPanel.webview.html = webviewHtml;

    // Handle messages from the webview
    debugPanel.webview.onDidReceiveMessage(async message => {
        if (message.command === 'getCurrentFile') {
            const editor = vscode.window.activeTextEditor;
            if (editor) {
                const uri = editor.document.uri;
                debugPanel?.webview.postMessage({
                    type: 'currentFile',
                    tool: message.tool,
                    uri: uri.toString()
                });
            } else {
                debugPanel?.webview.postMessage({
                    type: 'currentFile',
                    tool: message.tool,
                    error: 'No active editor found'
                });
                vscode.window.showInformationMessage('Please open a file in the editor to use this feature');
            }
        } else if (message.command === 'execute' && mcpServer) {
            try {
                // Create a request handler function that matches our server's handlers
                const handleRequest = async (request: { params: { name: string; arguments: any } }) => {
                    try {
                        const { name, arguments: args } = request.params;
                        let result: any;
                        
                        // Verify file exists for commands that require it
                        if (args && typeof args === 'object' && 'textDocument' in args && 
                            args.textDocument && typeof args.textDocument === 'object' && 
                            'uri' in args.textDocument && typeof args.textDocument.uri === 'string') {
                            const uri = vscode.Uri.parse(args.textDocument.uri);
                            try {
                                await vscode.workspace.fs.stat(uri);
                            } catch (error) {
                                return {
                                    content: [{ 
                                        type: "text", 
                                        text: `Error: File not found - ${uri.fsPath}` 
                                    }],
                                    isError: true
                                };
                            }
                        }
                        
                        result = await runTool(name, args);

                        return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
                    } catch (error) {
                        const errorMessage = error instanceof Error ? error.message : String(error);
                        return {
                            content: [{ type: "text", text: `Error: ${errorMessage}` }],
                            isError: true,
                        };
                    }
                };

                const result = await handleRequest({
                    params: {
                        name: message.tool,
                        arguments: message.params
                    }
                });

                debugPanel?.webview.postMessage({
                    type: 'result',
                    tool: message.tool,
                    result: result
                });
            } catch (error) {
                debugPanel?.webview.postMessage({
                    type: 'result',
                    tool: message.tool,
                    result: { error: String(error) }
                });
            }
        }
    });
}

```

--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------

```typescript
import * as vscode from 'vscode';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import { 
    CallToolRequestSchema, 
    ListResourcesRequestSchema, 
    ListResourceTemplatesRequestSchema, 
    ListToolsRequestSchema 
} from '@modelcontextprotocol/sdk/types.js';
import express from 'express';
import cors from 'cors';
import type { Server as HttpServer } from 'http';
import { Request, Response } from 'express';
import { mcpTools } from './tools';
import { createDebugPanel } from './debugPanel';
import { mcpServer, httpServer, setMcpServer, setHttpServer } from './globals';
import { runTool } from './toolRunner';
import { findBifrostConfig, BifrostConfig, getProjectBasePath } from './config';

export async function activate(context: vscode.ExtensionContext) {
    let currentConfig: BifrostConfig | null = null;

    // Handle workspace folder changes
    context.subscriptions.push(
        vscode.workspace.onDidChangeWorkspaceFolders(async () => {
            await restartServerWithConfig();
        })
    );

    // Initial server start with config
    await restartServerWithConfig();

    // Register debug panel command
    context.subscriptions.push(
        vscode.commands.registerCommand('bifrost-mcp.openDebugPanel', () => {
            createDebugPanel(context);
        })
    );

    // Register commands
    context.subscriptions.push(
        vscode.commands.registerCommand('bifrost-mcp.startServer', async () => {
            try {
                if (httpServer) {
                    vscode.window.showInformationMessage(`MCP server is already running for project ${currentConfig?.projectName || 'unknown'}`);
                    return;
                }
                await restartServerWithConfig();
            } catch (error) {
                const errorMsg = error instanceof Error ? error.message : String(error);
                vscode.window.showErrorMessage(`Failed to start MCP server: ${errorMsg}`);
            }
        }),
        vscode.commands.registerCommand('bifrost-mcp.stopServer', async () => {
            if (!httpServer && !mcpServer) {
                vscode.window.showInformationMessage('No MCP server is currently running');
                return;
            }
            
            if (mcpServer) {
                mcpServer.close();
                setMcpServer(undefined);
            }
            
            if (httpServer) {
                httpServer.close();
                setHttpServer(undefined);
            }
            
            vscode.window.showInformationMessage('MCP server stopped');
        })
    );

    async function restartServerWithConfig() {
        // Stop existing server if running
        if (mcpServer) {
            mcpServer.close();
            setMcpServer(undefined);
        }
        if (httpServer) {
            httpServer.close();
            setHttpServer(undefined);
        }

        // Get workspace folder
        const workspaceFolders = vscode.workspace.workspaceFolders;
        if (!workspaceFolders || workspaceFolders.length === 0) {
            console.log('No workspace folder found');
            return;
        }

        // Find config in current workspace - will return DEFAULT_CONFIG if none found
        const config = await findBifrostConfig(workspaceFolders[0]);
        currentConfig = config!; // We know this is never null since findBifrostConfig always returns DEFAULT_CONFIG
        await startMcpServer(config!);
    }

    async function startMcpServer(config: BifrostConfig): Promise<{ mcpServer: Server, httpServer: HttpServer, port: number }> {
        // Create an MCP Server with project-specific info
        setMcpServer(new Server(
            {
                name: config.projectName,
                version: "0.1.0",
                description: config.description
            },
            {
                capabilities: {
                    tools: {},
                    resources: {},
                }
            }
        ));

        // Add tools handlers
        mcpServer!.setRequestHandler(ListToolsRequestSchema, async () => ({
            tools: mcpTools
        }));

        mcpServer!.setRequestHandler(ListResourcesRequestSchema, async () => ({
            resources: []
        }));

        mcpServer!.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
            templates: []
        }));

        // Add call tool handler
        mcpServer!.setRequestHandler(CallToolRequestSchema, async (request) => {
            try {
                const { name, arguments: args } = request.params;
                let result: any;
                
                // Verify file exists for commands that require it
                if (args && typeof args === 'object' && 'textDocument' in args && 
                    args.textDocument && typeof args.textDocument === 'object' && 
                    'uri' in args.textDocument && typeof args.textDocument.uri === 'string') {
                    const uri = vscode.Uri.parse(args.textDocument.uri);
                    try {
                        await vscode.workspace.fs.stat(uri);
                    } catch (error) {
                        return {
                            content: [{ 
                                type: "text", 
                                text: `Error: File not found - ${uri.fsPath}` 
                            }],
                            isError: true
                        };
                    }
                }
                
                result = await runTool(name, args);

                return { content: [{ type: "text", text: JSON.stringify(result) }] };
            } catch (error) {
                const errorMessage = error instanceof Error ? error.message : String(error);
                return {
                    content: [{ type: "text", text: `Error: ${errorMessage}` }],
                    isError: true,
                };
            }
        });

        // Set up Express app
        const app = express();
        app.use(cors());
        app.use(express.json());

        // Track active transports by session ID
        const transports: { [sessionId: string]: SSEServerTransport } = {};

        const basePath = getProjectBasePath(config);

        // Create project-specific SSE endpoint
        app.get(`${basePath}/sse`, async (req: Request, res: Response) => {
            console.log(`New SSE connection attempt for project ${config.projectName}`);
            
            req.socket.setTimeout(0);
            req.socket.setNoDelay(true);
            req.socket.setKeepAlive(true);
            
            try {
                // Create transport with project-specific message endpoint path
                const transport = new SSEServerTransport(`${basePath}/message`, res);
                const sessionId = transport.sessionId;
                transports[sessionId] = transport;

                const keepAliveInterval = setInterval(() => {
                    if (res.writable) {
                        res.write(': keepalive\n\n');
                    }
                }, 30000);

                if (mcpServer) {
                    await mcpServer.connect(transport);
                    console.log(`Server connected to SSE transport with session ID: ${sessionId} for project ${config.projectName}`);
                    
                    req.on('close', () => {
                        console.log(`SSE connection closed for session ${sessionId}`);
                        clearInterval(keepAliveInterval);
                        delete transports[sessionId];
                        transport.close().catch(err => {
                            console.error('Error closing transport:', err);
                        });
                    });
                } else {
                    console.error('MCP Server not initialized');
                    res.status(500).end();
                    return;
                }
            } catch (error) {
                console.error('Error in SSE connection:', error);
                res.status(500).end();
            }
        });
        
        // Create project-specific message endpoint
        app.post(`${basePath}/message`, async (req: Request, res: Response) => {
            const sessionId = req.query.sessionId as string;
            console.log(`Received message for session ${sessionId} in project ${config.projectName}:`, req.body?.method);
            
            const transport = transports[sessionId];
            if (!transport) {
                console.error(`No transport found for session ${sessionId}`);
                res.status(400).json({
                    jsonrpc: "2.0",
                    id: req.body?.id,
                    error: {
                        code: -32000,
                        message: "No active session found"
                    }
                });
                return;
            }
            
            try {
                await transport.handlePostMessage(req, res, req.body);
                console.log('Message handled successfully');
            } catch (error) {
                console.error('Error handling message:', error);
                res.status(500).json({
                    jsonrpc: "2.0",
                    id: req.body?.id,
                    error: {
                        code: -32000,
                        message: String(error)
                    }
                });
            }
        });
        
        // Add project-specific health check endpoint
        app.get(`${basePath}/health`, (req: Request, res: Response) => {
            res.status(200).json({ 
                status: 'ok',
                project: config.projectName,
                description: config.description
            });
        });

        try {
            const serv = app.listen(config.port);
            setHttpServer(serv);
            vscode.window.showInformationMessage(`MCP server listening on http://localhost:${config.port}${basePath}`);
            console.log(`MCP Server for project ${config.projectName} listening on http://localhost:${config.port}${basePath}`);
            return {
                mcpServer: mcpServer!,
                httpServer: httpServer!,
                port: config.port
            };
        } catch (error) {
            const errorMsg = error instanceof Error ? error.message : String(error);
            vscode.window.showErrorMessage(`Failed to start server on configured port ${config.port}${basePath}. Please check if the port is available or configure a different port in bifrost.config.json. Error: ${errorMsg}`);
            throw new Error(`Failed to start server on configured port ${config.port}. Please check if the port is available or configure a different port in bifrost.config.json. Error: ${errorMsg}`);
        }
    }
}

export function deactivate() {
    if (mcpServer) {
        mcpServer.close();
    }
    if (httpServer) {
        httpServer.close();
    }
}
```

--------------------------------------------------------------------------------
/src/webview.ts:
--------------------------------------------------------------------------------

```typescript
import { toolsDescriptions } from './tools';
const onlyUriTools = ['get_semantic_tokens', 'get_document_symbols', 'get_code_lens', 'get_workspace_symbols'];
const noUriTools = ['get_workspace_symbols'];

export const webviewHtml = `
    <!DOCTYPE html>
    <html>
    <head>
        <style>
            body { 
                padding: 20px;
                font-family: var(--vscode-font-family);
                color: var(--vscode-foreground);
            }
            .tool-section {
                margin-bottom: 20px;
                padding: 10px;
                border: 1px solid var(--vscode-panel-border);
                border-radius: 4px;
            }
            .tool-title {
                font-weight: bold;
                margin-bottom: 10px;
            }
            input, button {
                margin: 5px 0;
                padding: 5px;
                background: var(--vscode-input-background);
                color: var(--vscode-input-foreground);
                border: 1px solid var(--vscode-input-border);
            }
            button {
                cursor: pointer;
                background: var(--vscode-button-background);
                color: var(--vscode-button-foreground);
                border: none;
                padding: 8px 12px;
                border-radius: 2px;
            }
            button:hover {
                background: var(--vscode-button-hoverBackground);
            }
            pre {
                background: var(--vscode-textCodeBlock-background);
                padding: 10px;
                overflow-x: auto;
                margin-top: 10px;
                color: var(--vscode-foreground);
            }
            .error-message {
                color: var(--vscode-errorForeground);
            }
            .success-message {
                color: var(--vscode-terminal-ansiGreen);
            }
            .autocomplete-container {
                position: relative;
                width: 100%;
            }
            .autocomplete-list {
                position: absolute;
                top: 100%;
                left: 0;
                right: 0;
                max-height: 200px;
                overflow-y: auto;
                background: var(--vscode-input-background);
                border: 1px solid var(--vscode-input-border);
                z-index: 1000;
                display: none;
            }
            .autocomplete-item {
                padding: 5px 10px;
                cursor: pointer;
            }
            .autocomplete-item:hover {
                background: var(--vscode-list-hoverBackground);
            }
            .autocomplete-item.selected {
                background: var(--vscode-list-activeSelectionBackground);
                color: var(--vscode-list-activeSelectionForeground);
            }
            .current-file-button {
                margin-left: 5px;
            }
            .tool-inputs {
                margin: 10px 0;
            }
        </style>
    </head>
    <body>
        ${toolsDescriptions.map(tool => `
            <div class="tool-section">
                <div class="tool-title">${tool.name}</div>
                <div>${tool.description}</div>
                ${!noUriTools.includes(tool.name) ? `
                <div class="autocomplete-container">
                    <div style="display: flex; align-items: center;">
                        <input type="text" id="uri-${tool.name}" class="file-input" placeholder="Start typing to search files..." style="flex: 1;">
                        <button class="current-file-button" onclick="useCurrentFile('${tool.name}')">Use Current File</button>
                    </div>
                    <div id="autocomplete-${tool.name}" class="autocomplete-list"></div>
                </div>
                ` : ''}
                <div class="tool-inputs">
                    ${!onlyUriTools.includes(tool.name) ? `
                        <input type="number" id="line-${tool.name}" placeholder="Line number" style="width: 100px">
                        <input type="number" id="char-${tool.name}" placeholder="Character" style="width: 100px">
                    ` : ''}
                    ${tool.name === 'get_completions' ? `
                        <input type="text" id="trigger-${tool.name}" placeholder="Trigger character" style="width: 50px" maxlength="1">
                    ` : ''}
                    ${tool.name === 'get_rename_locations' || tool.name === 'rename' ? `
                        <input type="text" id="newname-${tool.name}" placeholder="New name" style="width: 150px">
                    ` : ''}
                    ${tool.name === 'get_workspace_symbols' ? `
                        <input type="text" id="query-${tool.name}" placeholder="Search symbols..." style="width: 200px">
                    ` : ''}
                </div>
                <button onclick="executeTool('${tool.name}')">Execute</button>
                <pre id="result-${tool.name}">Results will appear here...</pre>
            </div>
        `).join('')}
        <script>
            const vscode = acquireVsCodeApi();
            let workspaceFiles = [];
            
            // File autocomplete functionality
            function setupFileAutocomplete(toolName) {
                if (${JSON.stringify(noUriTools)}.includes(toolName)) {
                    return;
                }
                const input = document.getElementById('uri-' + toolName);
                const autocompleteList = document.getElementById('autocomplete-' + toolName);
                let selectedIndex = -1;

                input.addEventListener('input', () => {
                    const value = input.value.toLowerCase();
                    const matches = workspaceFiles.filter(file => 
                        file.toLowerCase().includes(value)
                    ).slice(0, 10);

                    if (matches.length && value) {
                        autocompleteList.innerHTML = matches
                            .map((file, index) => \`
                                <div class="autocomplete-item" data-index="\${index}">
                                    \${file}
                                </div>
                            \`).join('');
                        autocompleteList.style.display = 'block';
                    } else {
                        autocompleteList.style.display = 'none';
                    }
                    selectedIndex = -1;
                });

                input.addEventListener('keydown', (e) => {
                    const items = autocompleteList.getElementsByClassName('autocomplete-item');
                    
                    if (e.key === 'ArrowDown') {
                        e.preventDefault();
                        selectedIndex = Math.min(selectedIndex + 1, items.length - 1);
                        updateSelection();
                    } else if (e.key === 'ArrowUp') {
                        e.preventDefault();
                        selectedIndex = Math.max(selectedIndex - 1, -1);
                        updateSelection();
                    } else if (e.key === 'Enter' && selectedIndex >= 0) {
                        e.preventDefault();
                        if (items[selectedIndex]) {
                            input.value = items[selectedIndex].textContent.trim();
                            autocompleteList.style.display = 'none';
                        }
                    } else if (e.key === 'Escape') {
                        autocompleteList.style.display = 'none';
                        selectedIndex = -1;
                    }
                });

                function updateSelection() {
                    const items = autocompleteList.getElementsByClassName('autocomplete-item');
                    for (let i = 0; i < items.length; i++) {
                        items[i].classList.toggle('selected', i === selectedIndex);
                    }
                    if (selectedIndex >= 0 && items[selectedIndex]) {
                        items[selectedIndex].scrollIntoView({ block: 'nearest' });
                    }
                }

                autocompleteList.addEventListener('click', (e) => {
                    const item = e.target.closest('.autocomplete-item');
                    if (item) {
                        input.value = item.textContent.trim();
                        autocompleteList.style.display = 'none';
                    }
                });

                document.addEventListener('click', (e) => {
                    if (!e.target.closest('.autocomplete-container')) {
                        autocompleteList.style.display = 'none';
                    }
                });
            }

            tools = ${JSON.stringify(toolsDescriptions)};
            tools.forEach(tool => {
                setupFileAutocomplete(tool.name);
            });

            function useCurrentFile(toolName) {
                if (${JSON.stringify(noUriTools)}.includes(toolName)) {
                    return;
                }
                vscode.postMessage({
                    command: 'getCurrentFile',
                    tool: toolName
                });
            }

            function executeTool(toolName) {
                const params = {};
                
                if (!${JSON.stringify(noUriTools)}.includes(toolName)) {
                    const uri = document.getElementById('uri-' + toolName).value;
                    params.textDocument = { uri };
                }

                if (!${JSON.stringify(onlyUriTools)}.includes(toolName)) {
                    const line = document.getElementById('line-' + toolName)?.value;
                    const char = document.getElementById('char-' + toolName)?.value;
                    params.position = {
                        line: parseInt(line),
                        character: parseInt(char)
                    };
                }

                if (toolName === 'get_completions') {
                    const trigger = document.getElementById('trigger-' + toolName)?.value;
                    if (trigger) {
                        params.triggerCharacter = trigger;
                    }
                }

                if (toolName === 'get_rename_locations' || toolName === 'rename') {
                    const newName = document.getElementById('newname-' + toolName)?.value;
                    if (newName) {
                        params.newName = newName;
                    }
                }

                if (toolName === 'get_workspace_symbols') {
                    const query = document.getElementById('query-' + toolName)?.value;
                    params.query = query || '';
                }

                vscode.postMessage({
                    command: 'execute',
                    tool: toolName,
                    params
                });
            }

            window.addEventListener('message', event => {
                const message = event.data;
                if (message.type === 'files') {
                    workspaceFiles = message.files;
                } else if (message.type === 'currentFile') {
                    const input = document.getElementById('uri-' + message.tool);
                    const resultElement = document.getElementById('result-' + message.tool);
                    if (message.error) {
                        resultElement.textContent = message.error + '. Please open a file in the editor first.';
                        resultElement.className = 'error-message';
                        input.value = '';
                    } else if (message.uri) {
                        input.value = message.uri;
                        resultElement.textContent = 'Current file selected: ' + message.uri;
                        resultElement.className = 'success-message';
                    }
                } else if (message.type === 'result') {
                    const resultElement = document.getElementById('result-' + message.tool);
                    try {
                        let resultText = '';
                        if (message.result?.content?.[0]?.type === 'text') {
                            const innerContent = message.result.content[0].text;
                            try {
                                const parsedJson = JSON.parse(innerContent);
                                resultText = JSON.stringify(parsedJson, null, 2);
                            } catch {
                                resultText = JSON.stringify(message.result, null, 2);
                            }
                        } else {
                            resultText = JSON.stringify(message.result, null, 2);
                        }
                        resultElement.textContent = resultText;
                        resultElement.className = ''; // Remove any special styling for results
                    } catch (error) {
                        resultElement.textContent = JSON.stringify(message.result, null, 2);
                        resultElement.className = ''; // Remove any special styling for results
                    }
                }
            });
        </script>
    </body>
    </html>
`;
```

--------------------------------------------------------------------------------
/src/toolRunner.ts:
--------------------------------------------------------------------------------

```typescript
import * as vscode from 'vscode';
import { createVscodePosition, getPreview, convertSymbol, asyncMap, convertSemanticTokens, getSymbolKindString, transformLocations, transformSingleLocation } from './helpers';
import { ReferencesAndPreview, RenameEdit } from './rosyln';
import { mcpTools } from './tools';

const toolNames = mcpTools.map((tool) => tool.name);

export const runTool = async (name: string, args: any) => {
    let result: any;
    if (!toolNames.includes(name)) {
        throw new Error(`Unknown tool: ${name}`);
    }
    // Verify file exists before proceeding
    const uri = vscode.Uri.parse(args?.textDocument?.uri ?? '');
    try {
        await vscode.workspace.fs.stat(uri);
    } catch (error) {
        return {
            content: [{ 
                type: "text", 
                text: `Error: File not found - ${uri.fsPath}` 
            }],
            isError: true
        };
    }

    const position = args?.position ? createVscodePosition(
        args.position.line,
        args.position.character
    ) : undefined;

    let command: string;
    let commandResult: any;
    
    switch (name) {
        case "find_usages":
            command = 'vscode.executeReferenceProvider';
            const locations = await vscode.commands.executeCommand<vscode.Location[]>(
                command,
                uri,
                position
            );

            if (!locations) {
                result = [];
                break;
            }
            const references: ReferencesAndPreview[] = await asyncMap(
                locations,
                transformSingleLocation
            );
            result = references;
            break;

        case "go_to_definition":
            command = 'vscode.executeDefinitionProvider';
            commandResult = await vscode.commands.executeCommand(command, uri, position);
            result = await transformLocations(commandResult);
            break;

        case "find_implementations":
            command = 'vscode.executeImplementationProvider';
            commandResult = await vscode.commands.executeCommand(command, uri, position);
            result = await transformLocations(commandResult);
            break;

        case "get_hover_info":
            command = 'vscode.executeHoverProvider';
            commandResult = await vscode.commands.executeCommand(command, uri, position);
            result = await asyncMap(commandResult, async (hover: vscode.Hover) => ({
                contents: hover.contents.map(content => 
                    typeof content === 'string' ? content : content.value
                ),
                range: hover.range ? {
                    start: {
                        line: hover.range.start.line,
                        character: hover.range.start.character
                    },
                    end: {
                        line: hover.range.end.line,
                        character: hover.range.end.character
                    }
                } : undefined,
                preview: await getPreview(uri, hover.range?.start.line)
            }));
            break;

        case "get_document_symbols":
            command = 'vscode.executeDocumentSymbolProvider';
            commandResult = await vscode.commands.executeCommand(command, uri);
            result = commandResult?.map(convertSymbol);
            break;

        case "get_completions":
            const completions = await vscode.commands.executeCommand<vscode.CompletionList>(
                'vscode.executeCompletionItemProvider',
                uri,
                position,
                args?.triggerCharacter
            );
            result = completions?.items.map(item => ({
                label: item.label,
                kind: item.kind,
                detail: item.detail,
                documentation: item.documentation,
                sortText: item.sortText,
                filterText: item.filterText,
                insertText: item.insertText,
                range: item.range && ('start' in item.range) ? {
                    start: {
                        line: item.range.start.line,
                        character: item.range.start.character
                    },
                    end: {
                        line: item.range.end.line,
                        character: item.range.end.character
                    }
                } : undefined
            }));
            break;

        case "get_signature_help":
            const signatureHelp = await vscode.commands.executeCommand<vscode.SignatureHelp>(
                'vscode.executeSignatureHelpProvider',
                uri,
                position
            );
            result = signatureHelp?.signatures.map(sig => ({
                label: sig.label,
                documentation: sig.documentation,
                parameters: sig.parameters?.map(param => ({
                    label: param.label,
                    documentation: param.documentation
                })),
                activeParameter: signatureHelp.activeParameter,
                activeSignature: signatureHelp.activeSignature
            }));
            break;

        case "get_rename_locations": {
            const newName = args?.newName || "newName";
            const renameEdits = await vscode.commands.executeCommand<vscode.WorkspaceEdit>(
                'vscode.executeDocumentRenameProvider',
                uri,
                position,
                newName
            );
            if (renameEdits) {
                const entries: RenameEdit[] = [];
                for (const [editUri, edits] of renameEdits.entries()) {
                    entries.push({
                        uri: editUri.toString(),
                        edits: edits.map(edit => ({
                            range: {
                                start: {
                                    line: edit.range.start.line,
                                    character: edit.range.start.character
                                },
                                end: {
                                    line: edit.range.end.line,
                                    character: edit.range.end.character
                                }
                            },
                            newText: edit.newText
                        }))
                    });
                }
                result = entries;
            } else {
                result = [];
            }
            break;
        }
       
        case "rename": {
            const newName = args?.newName || "newName";
            const renameEdits = await vscode.commands.executeCommand<vscode.WorkspaceEdit>(
                'vscode.executeDocumentRenameProvider',
                uri,
                position,
                newName
            );
            if (renameEdits) {
                const success = await vscode.workspace.applyEdit(renameEdits);
                return {
                    content: [{
                        type: "text",
                        text: success ? "Symbol renamed successfully" : "Symbol renaming failed"
                    }],
                    isError: false
                };
            } else {
                return {
                    content: [{
                        type: "text",
                        text: "Symbol to rename not found"
                    }],
                    isError: false
                };
            }
            break;
        }

        case "get_code_actions":
            const codeActions = await vscode.commands.executeCommand<vscode.CodeAction[]>(
                'vscode.executeCodeActionProvider',
                uri,
                position ? new vscode.Range(position, position) : undefined
            );
            result = codeActions?.map(action => ({
                title: action.title,
                kind: action.kind?.value,
                isPreferred: action.isPreferred,
                diagnostics: action.diagnostics?.map(diag => ({
                    message: diag.message,
                    severity: diag.severity,
                    range: {
                        start: {
                            line: diag.range.start.line,
                            character: diag.range.start.character
                        },
                        end: {
                            line: diag.range.end.line,
                            character: diag.range.end.character
                        }
                    }
                }))
            }));
            break;

        case "get_code_lens":
            const codeLensUri = vscode.Uri.parse((args as any).textDocument?.uri);
            try {
                const codeLensResult = await vscode.commands.executeCommand<vscode.CodeLens[]>(
                    'vscode.executeCodeLensProvider',
                    codeLensUri
                );

                if (!codeLensResult || codeLensResult.length === 0) {
                    return {
                        content: [{ 
                            type: "text", 
                            text: "No CodeLens items found in document" 
                        }],
                        isError: false
                    };
                }

                result = codeLensResult.map(lens => ({
                    range: {
                        start: {
                            line: lens.range.start.line,
                            character: lens.range.start.character
                        },
                        end: {
                            line: lens.range.end.line,
                            character: lens.range.end.character
                        }
                    },
                    command: lens.command ? {
                        title: lens.command.title,
                        command: lens.command.command,
                        arguments: lens.command.arguments
                    } : undefined
                }));
            } catch (error) {
                return {
                    content: [{ 
                        type: "text", 
                        text: `Error executing CodeLens provider: ${error}` 
                    }],
                    isError: true
                };
            }
            break;
    
        case "get_selection_range":
            const selectionRanges = await vscode.commands.executeCommand<vscode.SelectionRange[]>(
                'vscode.executeSelectionRangeProvider',
                uri,
                [position]
            );
            result = selectionRanges?.map(range => ({
                range: {
                    start: {
                        line: range.range.start.line,
                        character: range.range.start.character
                    },
                    end: {
                        line: range.range.end.line,
                        character: range.range.end.character
                    }
                },
                parent: range.parent ? {
                    range: {
                        start: {
                            line: range.parent.range.start.line,
                            character: range.parent.range.start.character
                        },
                        end: {
                            line: range.parent.range.end.line,
                            character: range.parent.range.end.character
                        }
                    }
                } : undefined
            }));
            break;

        case "get_type_definition":
            command = 'vscode.executeTypeDefinitionProvider';
            commandResult = await vscode.commands.executeCommand(command, uri, position);
            result = await transformLocations(commandResult);
            break;

        case "get_declaration":
            command = 'vscode.executeDeclarationProvider';
            commandResult = await vscode.commands.executeCommand(command, uri, position);
            result = await transformLocations(commandResult);
            break;

        case "get_document_highlights":
            const highlights = await vscode.commands.executeCommand<vscode.DocumentHighlight[]>(
                'vscode.executeDocumentHighlights',
                uri,
                position
            );
            result = highlights?.map(highlight => ({
                range: {
                    start: {
                        line: highlight.range.start.line,
                        character: highlight.range.start.character
                    },
                    end: {
                        line: highlight.range.end.line,
                        character: highlight.range.end.character
                    }
                },
                kind: highlight.kind
            }));
            break;

        case "get_workspace_symbols":
            const query = args.query || '';
            const symbols = await vscode.commands.executeCommand<vscode.SymbolInformation[]>(
                'vscode.executeWorkspaceSymbolProvider',
                query
            );
            result = symbols?.map(symbol => ({
                name: symbol.name,
                kind: symbol.kind,
                location: {
                    uri: symbol.location.uri.toString(),
                    range: {
                        start: {
                            line: symbol.location.range.start.line,
                            character: symbol.location.range.start.character
                        },
                        end: {
                            line: symbol.location.range.end.line,
                            character: symbol.location.range.end.character
                        }
                    }
                },
                containerName: symbol.containerName
            }));
            break;

        case "get_semantic_tokens":
            const semanticTokensUri = vscode.Uri.parse((args as any).textDocument?.uri);
            
            // Check if semantic tokens provider is available
            const providers = await vscode.languages.getLanguages();
            const document = await vscode.workspace.openTextDocument(semanticTokensUri);
            const hasSemanticTokens = providers.includes(document.languageId);
            
            if (!hasSemanticTokens) {
                return {
                    content: [{ 
                        type: "text", 
                        text: `Semantic tokens not supported for language: ${document.languageId}` 
                    }],
                    isError: true
                };
            }

            try {
                const semanticTokens = await vscode.commands.executeCommand<vscode.SemanticTokens>(
                    'vscode.provideDocumentSemanticTokens',
                    semanticTokensUri
                );

                if (!semanticTokens) {
                    return {
                        content: [{ 
                            type: "text", 
                            text: "No semantic tokens found in document" 
                        }],
                        isError: false
                    };
                }

                // Convert to human-readable format
                const readableTokens = convertSemanticTokens(semanticTokens, document);
                
                result = {
                    resultId: semanticTokens.resultId,
                    tokens: readableTokens
                };
            } catch (error) {
                // If the command is not found, try alternative approach
                const tokenTypes = [
                    'namespace', 'class', 'enum', 'interface',
                    'struct', 'typeParameter', 'type', 'parameter',
                    'variable', 'property', 'enumMember', 'decorator',
                    'event', 'function', 'method', 'macro', 'keyword',
                    'modifier', 'comment', 'string', 'number', 'regexp',
                    'operator'
                ];
                
                // Use document symbols as fallback
                const symbols = await vscode.commands.executeCommand<vscode.DocumentSymbol[]>(
                    'vscode.executeDocumentSymbolProvider',
                    semanticTokensUri
                );

                if (symbols) {
                    result = {
                        fallback: "Using document symbols as fallback",
                        symbols: symbols.map(symbol => ({
                            name: symbol.name,
                            kind: symbol.kind,
                            range: {
                                start: {
                                    line: symbol.range.start.line,
                                    character: symbol.range.start.character
                                },
                                end: {
                                    line: symbol.range.end.line,
                                    character: symbol.range.end.character
                                }
                            },
                            tokenType: tokenTypes[symbol.kind] || 'unknown'
                        }))
                    };
                } else {
                    return {
                        content: [{ 
                            type: "text", 
                            text: "Semantic tokens provider not available and fallback failed" 
                        }],
                        isError: true
                    };
                }
            }
            break;

        case "get_call_hierarchy":
            const callHierarchyItems = await vscode.commands.executeCommand<vscode.CallHierarchyItem[]>(
                'vscode.prepareCallHierarchy',
                uri,
                position
            );
            
            if (callHierarchyItems?.[0]) {
                const [incomingCalls, outgoingCalls] = await Promise.all([
                    vscode.commands.executeCommand<vscode.CallHierarchyIncomingCall[]>(
                        'vscode.executeCallHierarchyIncomingCalls',
                        callHierarchyItems[0]
                    ),
                    vscode.commands.executeCommand<vscode.CallHierarchyOutgoingCall[]>(
                        'vscode.executeCallHierarchyOutgoingCalls',
                        callHierarchyItems[0]
                    )
                ]);

                result = {
                    item: {
                        name: callHierarchyItems[0].name,
                        kind: getSymbolKindString(callHierarchyItems[0].kind),
                        detail: callHierarchyItems[0].detail,
                        uri: callHierarchyItems[0].uri.toString(),
                        range: {
                            start: {
                                line: callHierarchyItems[0].range.start.line,
                                character: callHierarchyItems[0].range.start.character
                            },
                            end: {
                                line: callHierarchyItems[0].range.end.line,
                                character: callHierarchyItems[0].range.end.character
                            }
                        }
                    },
                    incomingCalls: incomingCalls?.map(call => ({
                        from: {
                            name: call.from.name,
                            kind: getSymbolKindString(call.from.kind),
                            uri: call.from.uri.toString(),
                            range: {
                                start: {
                                    line: call.from.range.start.line,
                                    character: call.from.range.start.character
                                },
                                end: {
                                    line: call.from.range.end.line,
                                    character: call.from.range.end.character
                                }
                            }
                        },
                        fromRanges: call.fromRanges.map(range => ({
                            start: {
                                line: range.start.line,
                                character: range.start.character
                            },
                            end: {
                                line: range.end.line,
                                character: range.end.character
                            }
                        }))
                    })),
                    outgoingCalls: outgoingCalls?.map(call => ({
                        to: {
                            name: call.to.name,
                            kind: getSymbolKindString(call.to.kind),
                            uri: call.to.uri.toString(),
                            range: {
                                start: {
                                    line: call.to.range.start.line,
                                    character: call.to.range.start.character
                                },
                                end: {
                                    line: call.to.range.end.line,
                                    character: call.to.range.end.character
                                }
                            }
                        },
                        fromRanges: call.fromRanges.map(range => ({
                            start: {
                                line: range.start.line,
                                character: range.start.character
                            },
                            end: {
                                line: range.end.line,
                                character: range.end.character
                            }
                        }))
                    }))
                };
            }
            break;

        case "get_type_hierarchy":
            const typeHierarchyItems = await vscode.commands.executeCommand<vscode.TypeHierarchyItem[]>(
                'vscode.prepareTypeHierarchy',
                uri,
                position
            );
            
            if (typeHierarchyItems?.[0]) {
                const [supertypes, subtypes] = await Promise.all([
                    vscode.commands.executeCommand<vscode.TypeHierarchyItem[]>(
                        'vscode.executeTypeHierarchySupertypeCommand',
                        typeHierarchyItems[0]
                    ),
                    vscode.commands.executeCommand<vscode.TypeHierarchyItem[]>(
                        'vscode.executeTypeHierarchySubtypeCommand',
                        typeHierarchyItems[0]
                    )
                ]);

                result = {
                    item: {
                        name: typeHierarchyItems[0].name,
                        kind: getSymbolKindString(typeHierarchyItems[0].kind),
                        detail: typeHierarchyItems[0].detail,
                        uri: typeHierarchyItems[0].uri.toString(),
                        range: {
                            start: {
                                line: typeHierarchyItems[0].range.start.line,
                                character: typeHierarchyItems[0].range.start.character
                            },
                            end: {
                                line: typeHierarchyItems[0].range.end.line,
                                character: typeHierarchyItems[0].range.end.character
                            }
                        }
                    },
                    supertypes: supertypes?.map(type => ({
                        name: type.name,
                        kind: getSymbolKindString(type.kind),
                        detail: type.detail,
                        uri: type.uri.toString(),
                        range: {
                            start: {
                                line: type.range.start.line,
                                character: type.range.start.character
                            },
                            end: {
                                line: type.range.end.line,
                                character: type.range.end.character
                            }
                        }
                    })),
                    subtypes: subtypes?.map(type => ({
                        name: type.name,
                        kind: getSymbolKindString(type.kind),
                        detail: type.detail,
                        uri: type.uri.toString(),
                        range: {
                            start: {
                                line: type.range.start.line,
                                character: type.range.start.character
                            },
                            end: {
                                line: type.range.end.line,
                                character: type.range.end.character
                            }
                        }
                    }))
                };
            }
            break;
    
        default:
            throw new Error(`Unknown tool: ${name}`);
    }
    return result;
}

```

--------------------------------------------------------------------------------
/src/tools.ts:
--------------------------------------------------------------------------------

```typescript
export const mcpTools = [
    {
        name: "find_usages",
        description: 
            "Finds all references to a symbol at a specified location in code. This tool helps you identify where functions, variables, types, or other symbols are used throughout the codebase. " +
            "It performs a deep semantic analysis to find true references, not just text matches. " +
            "The results include:\n" +
            "- Complete file path for each reference\n" +
            "- Precise location (line and character position)\n" +
            "- Context preview showing how the symbol is used\n" +
            "- Optional inclusion of the symbol's declaration\n\n" +
            "This is particularly useful for:\n" +
            "- Understanding dependencies between different parts of the code\n" +
            "- Safely planning refactoring operations\n" +
            "- Analyzing the impact of potential changes\n" +
            "- Tracing data flow through the application\n\n" +
            "Note: Line numbers are 0-based (first line is 0), while character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the symbol",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document (file:///path/to/file format)"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol",
                    properties: {
                        line: {
                            type: "number",
                            description: "One-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                },
                context: {
                    type: "object",
                    description: "Additional context for the request",
                    properties: {
                        includeDeclaration: {
                            type: "boolean",
                            description: "Whether to include the declaration of the symbol in the results",
                            default: true
                        }
                    }
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "go_to_definition",
        description: "Navigates to the original definition of a symbol at a specified location in code. " +
            "This tool performs semantic analysis to find the true source definition, not just matching text. It can locate:\n" +
            "- Function/method declarations\n" +
            "- Class/interface definitions\n" +
            "- Variable declarations\n" +
            "- Type definitions\n" +
            "- Import/module declarations\n\n" +
            "The tool is essential for:\n" +
            "- Understanding where code elements are defined\n" +
            "- Navigating complex codebases\n" +
            "- Verifying the actual implementation of interfaces/abstractions\n\n" +
            "Note: Line numbers are 0-based (first line is 0), while character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the symbol",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol",
                    properties: {
                        line: {
                            type: "number",
                            description: "One-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "find_implementations",
        description: "Discovers all concrete implementations of an interface, abstract class, or abstract method in the codebase. " +
            "This tool performs deep semantic analysis to find all places where:\n" +
            "- Interfaces are implemented by classes\n" +
            "- Abstract classes are extended\n" +
            "- Abstract methods are overridden\n" +
            "- Virtual methods are overridden\n\n" +
            "This is particularly valuable for:\n" +
            "- Understanding polymorphic behavior in the codebase\n" +
            "- Finding all concrete implementations of an interface\n" +
            "- Analyzing inheritance hierarchies\n" +
            "- Verifying contract implementations\n\n" +
            "Note: Line numbers are 0-based (first line is 0), while character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the symbol",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol",
                    properties: {
                        line: {
                            type: "number",
                            description: "One-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_hover_info",
        description: "Retrieves comprehensive information about a symbol when hovering over it in code. " +
            "This tool provides rich contextual details including:\n" +
            "- Full type information and signatures\n" +
            "- Documentation comments and summaries\n" +
            "- Return types and parameter descriptions\n" +
            "- Type constraints and generic parameters\n" +
            "- Deprecation notices and version information\n\n" +
            "This is especially useful for:\n" +
            "- Understanding API usage and requirements\n" +
            "- Viewing documentation without leaving the context\n" +
            "- Verifying type information during development\n" +
            "- Quick access to symbol metadata\n\n" +
            "Note: Line numbers are 0-based (first line is 0), while character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the symbol",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol",
                    properties: {
                        line: {
                            type: "number",
                            description: "One-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_document_symbols",
        description: "Analyzes and returns a hierarchical list of all symbols defined within a document. " +
            "This tool provides a comprehensive overview of the code structure by identifying:\n" +
            "- Classes and interfaces\n" +
            "- Methods and functions\n" +
            "- Properties and fields\n" +
            "- Namespaces and modules\n" +
            "- Constants and enumerations\n\n" +
            "The symbols are returned in a structured format that preserves their relationships and scope. " +
            "This is particularly useful for:\n" +
            "- Understanding the overall structure of a file\n" +
            "- Creating code outlines and documentation\n" +
            "- Navigating large files efficiently\n" +
            "- Analyzing code organization and architecture",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document to analyze",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                }
            },
            required: ["textDocument"]
        }
    },
    {
        name: "get_completions",
        description: "Provides intelligent code completion suggestions based on the current context and cursor position. " +
            "This tool analyzes the code to offer relevant suggestions including:\n" +
            "- Variable and function names\n" +
            "- Class and type names\n" +
            "- Property and method completions\n" +
            "- Import statements\n" +
            "- Snippets and common patterns\n\n" +
            "The suggestions are context-aware and can be triggered by:\n" +
            "- Typing part of a symbol name\n" +
            "- Accessing object properties (.)\n" +
            "- Opening brackets or parentheses\n" +
            "- Language-specific triggers\n\n" +
            "Note: Line numbers are 0-based (first line is 0), and character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document to get completions for",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position to get completions at",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                },
                triggerCharacter: {
                    type: "string",
                    description: "Optional trigger character that caused completion"
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_signature_help",
        description: "Provides detailed information about function signatures as you type function calls. " +
            "This tool offers real-time assistance with:\n" +
            "- Parameter names and types\n" +
            "- Parameter documentation\n" +
            "- Overload information\n" +
            "- Return type details\n" +
            "- Generic type constraints\n\n" +
            "The signature help is context-sensitive and updates as you type, showing:\n" +
            "- Currently active parameter\n" +
            "- Available overloads\n" +
            "- Type compatibility information\n" +
            "- Optional and default values\n\n" +
            "Note: Line numbers are 0-based (first line is 0), and character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document to get signature help for",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position to get signature help at",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_rename_locations",
        description: "Identifies all locations that need to be updated when renaming a symbol. " +
            "This tool performs a comprehensive analysis to ensure safe and accurate renaming by:\n" +
            "- Finding all references to the symbol\n" +
            "- Checking for naming conflicts\n" +
            "- Analyzing scope boundaries\n" +
            "- Identifying related declarations\n\n" +
            "The tool is particularly valuable for:\n" +
            "- Safe refactoring operations\n" +
            "- Cross-file symbol renaming\n" +
            "- Impact analysis before renaming\n" +
            "- Maintaining code consistency\n\n" +
            "Note: Line numbers are 0-based (first line is 0), and character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the symbol to rename",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol to rename",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                },
                newName: {
                    type: "string",
                    description: "The new name for the symbol"
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "rename",
        description: "Identifies all locations that need to be updated when renaming a symbol, and performs the renaming. " +
            "This tool performs a comprehensive analysis to ensure safe and accurate renaming by:\n" +
            "- Finding all references to the symbol\n" +
            "- Checking for naming conflicts\n" +
            "- Analyzing scope boundaries\n" +
            "- Identifying related declarations\n\n" +
            "The tool is particularly valuable for:\n" +
            "- Safe refactoring operations\n" +
            "- Cross-file symbol renaming\n" +
            "- Maintaining code consistency\n\n" +
            "- Renaming without the need to generate code\n\n" +
            "Note: Line numbers are 0-based (first line is 0), and character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the symbol to rename",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol to rename",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                },
                newName: {
                    type: "string",
                    description: "The new name for the symbol"
                }
            },
            required: ["textDocument", "position", "newName"]
        }
    },
    {
        name: "get_code_actions",
        description: "Provides context-aware code actions and refactoring suggestions at a specified location. " +
            "This tool analyzes the code to offer intelligent improvements such as:\n" +
            "- Quick fixes for errors and warnings\n" +
            "- Code refactoring options\n" +
            "- Import management suggestions\n" +
            "- Code style improvements\n" +
            "- Performance optimizations\n\n" +
            "Available actions may include:\n" +
            "- Extract method/variable/constant\n" +
            "- Implement interface members\n" +
            "- Add missing imports\n" +
            "- Convert code constructs\n" +
            "- Fix code style issues\n\n" +
            "Note: Line numbers are 0-based (first line is 0), and character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document to get code actions for",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position to get code actions at",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument"]
        }
    },
    {
        name: "get_semantic_tokens",
        description: "Provides detailed semantic token information for enhanced code understanding and highlighting. " +
            "This tool performs deep analysis to identify and classify code elements:\n" +
            "- Variables and their scopes\n" +
            "- Function and method names\n" +
            "- Type names and annotations\n" +
            "- Keywords and operators\n" +
            "- Comments and documentation\n\n" +
            "The semantic information enables:\n" +
            "- Precise syntax highlighting\n" +
            "- Code navigation improvements\n" +
            "- Better code understanding\n" +
            "- Accurate symbol classification\n" +
            "- Enhanced code analysis",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document to get semantic tokens for",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                }
            },
            required: ["textDocument"]
        }
    },
    {
        name: "get_call_hierarchy",
        description: "Analyzes and visualizes the call relationships between functions and methods in the codebase. " +
            "This tool builds a comprehensive call graph showing:\n" +
            "- Incoming calls (who calls this function)\n" +
            "- Outgoing calls (what this function calls)\n" +
            "- Call chains and dependencies\n" +
            "- Recursive call patterns\n\n" +
            "This information is invaluable for:\n" +
            "- Understanding code flow and dependencies\n" +
            "- Analyzing impact of changes\n" +
            "- Debugging complex call chains\n" +
            "- Optimizing function relationships\n" +
            "- Identifying potential refactoring targets\n\n" +
            "Note: Line numbers are 0-based (first line is 0), and character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the function",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the function",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_type_hierarchy",
        description: "Analyzes and visualizes the inheritance and implementation relationships between types. " +
            "This tool creates a comprehensive type hierarchy showing:\n" +
            "- Parent classes and interfaces\n" +
            "- Child classes and implementations\n" +
            "- Interface inheritance chains\n" +
            "- Mixin and trait relationships\n\n" +
            "The hierarchy information is crucial for:\n" +
            "- Understanding class relationships\n" +
            "- Analyzing inheritance patterns\n" +
            "- Planning class structure changes\n" +
            "- Identifying potential abstraction opportunities\n" +
            "- Verifying type system design\n\n" +
            "Note: Line numbers are 0-based (first line is 0), and character positions are 0-based (first character is 0).",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the type",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the type",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_code_lens",
        description: "Gets CodeLens information for a document, showing actionable contextual information inline with code",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document to get CodeLens for",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                }
            },
            required: ["textDocument"]
        }
    },
    {
        name: "get_selection_range",
        description: "Gets selection ranges for a position in a document. This helps in smart selection expansion based on semantic document structure.",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document to analyze",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position to get selection ranges for",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_type_definition",
        description: "Finds type definitions of a symbol at a specified location. This is particularly useful for finding the underlying type definitions of variables, interfaces, and classes.",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the symbol",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_declaration",
        description: "Finds declarations of a symbol at a specified location. This helps in navigating to where symbols are declared, particularly useful for imported symbols.",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document containing the symbol",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_document_highlights",
        description: "Finds all highlights of a symbol in a document. This is useful for highlighting all occurrences of a symbol within the current document.",
        inputSchema: {
            type: "object",
            properties: {
                textDocument: {
                    type: "object",
                    description: "The document to analyze",
                    properties: {
                        uri: {
                            type: "string",
                            description: "URI of the document"
                        }
                    },
                    required: ["uri"]
                },
                position: {
                    type: "object",
                    description: "The position of the symbol",
                    properties: {
                        line: {
                            type: "number",
                            description: "Zero-based line number"
                        },
                        character: {
                            type: "number",
                            description: "Zero-based character position"
                        }
                    },
                    required: ["line", "character"]
                }
            },
            required: ["textDocument", "position"]
        }
    },
    {
        name: "get_workspace_symbols",
        description: "Searches for symbols across the entire workspace. This is useful for finding symbols by name across all files. Especially useful for finding the file and positions of a symbol to use in other tools.",
        inputSchema: {
            type: "object",
            properties: {
                query: {
                    type: "string",
                    description: "The search query for finding symbols"
                }
            },
            required: ["query"]
        }
    }
];

export const toolsDescriptions = [
    {
        name: "find_usages",
        description: "Find all references to a symbol"
    },
    {
        name: "go_to_definition",
        description: "Find definition of a symbol"
    },
    {
        name: "find_implementations",
        description: "Find implementations of interface/abstract method"
    },
    {
        name: "get_hover_info",
        description: "Get hover information for a symbol"
    },
    {
        name: "get_document_symbols",
        description: "Get all symbols in document"
    },
    {
        name: "get_completions",
        description: "Get code completion suggestions at a position"
    },
    {
        name: "get_signature_help",
        description: "Get function signature information"
    },
    {
        name: "get_rename_locations",
        description: "Get all locations that would be affected by renaming a symbol"
    },
    {
        name: "rename",
        description: "Rename a symbol"
    },
    {
        name: "get_code_actions",
        description: "Get available code actions and refactorings"
    },
    {
        name: "get_semantic_tokens",
        description: "Get semantic token information for code understanding"
    },
    {
        name: "get_call_hierarchy",
        description: "Get incoming and outgoing call hierarchy"
    },
    {
        name: "get_type_hierarchy",
        description: "Get type hierarchy information"
    },
    {
        name: "get_code_lens",
        description: "Gets CodeLens information for a document, showing actionable contextual information inline with code"
    },
    {
        name: "get_selection_range",
        description: "Gets selection ranges for smart selection expansion"
    },
    {
        name: "get_type_definition",
        description: "Find type definitions of symbols"
    },
    {
        name: "get_declaration",
        description: "Find declarations of symbols"
    },
    {
        name: "get_document_highlights",
        description: "Find all highlights of a symbol in document"
    },
    {
        name: "get_workspace_symbols",
        description: "Search for symbols across the workspace"
    }
];
```