Understanding MCP and the tool ecosystem

tech
prompt-engineering
github-copilot
concepts
mcp
Understand the Model Context Protocol, how the two-level tool architecture works, what tool categories exist, and when to build an MCP server vs. use built-in tools or extensions.
Author

Dario Airoldi

Published

March 1, 2026

Understanding MCP and the tool ecosystem

An agent without tools can only think. It can reason about code, generate text, and answer questions β€” but it can’t search your codebase, edit files, run terminal commands, or call external APIs. Tools are what transform a language model from a sophisticated text generator into a capable coding assistant.

GitHub Copilot’s tool ecosystem has three layers: built-in tools that ship with VS Code, extension-contributed tools from the marketplace, and Model Context Protocol (MCP) servers that you build or install to add custom capabilities. This article explains how these layers work together, how the two-level tool architecture connects your YAML declarations to runtime execution, and when to reach for each type of tool.

Table of contents


🎯 Why tools matter

Consider this prompt: β€œFind all usages of the UserService class and update them to use the new AuthenticatedUserService interface.”

Without tools, Copilot can reason about what should happen β€” but it can’t search your codebase, read the actual files, or make changes. With tools, it can:

  1. Search β€” semantic_search and grep_search find every file that references UserService
  2. Read β€” read_file loads each file to understand the usage context
  3. Edit β€” replace_string_in_file makes the actual changes
  4. Validate β€” get_errors checks for compile errors after each change
  5. Confirm β€” ask_questions verifies ambiguous cases with you

Tools are the mechanism that closes the gap between β€œthinking about code” and β€œchanging code.”


πŸ—οΈ The two-level tool architecture

GitHub Copilot’s tool system operates at two distinct levels. Understanding this separation is essential β€” confusing Level 1 and Level 2 is the most common source of tool-related mistakes in prompt engineering.

You write (Level 1)                    The model calls (Level 2)
──────────────────                     ──────────────────────────
tools: ['codebase']          ────►     semantic_search()
                                       grep_search()
                                       file_search()
                                       read_file()

tools: ['editor']            ────►     create_file()
                                       replace_string_in_file()
                                       multi_replace_string_in_file()
                                       read_file()

tools: ['filesystem']        ────►     list_dir()
                                       file_search()
                                       read_file()
Level What you write What happens Example
Level 1 β€” YAML declarations tools: field in frontmatter Grants permission to use tool categories codebase, editor, fetch
Level 2 β€” Runtime tool calls Model decides during execution Actual operations on your workspace read_file(), grep_search(), create_file()

The relationship is hierarchical: Level 1 declarations enable groups of Level 2 runtime tools. When you write tools: ['editor'] in YAML, you’re granting permission to use create_file, replace_string_in_file, and multi_replace_string_in_file. You’re not calling those tools directly β€” the model decides which runtime tools to call and when, based on the task.

Why the separation matters

This two-level design serves different audiences:

  • Level 1 is for prompt authors β€” you decide what categories of operations an agent can perform
  • Level 2 is for the model β€” the model decides what specific operations to perform within those categories

This means you control the β€œsafety perimeter” through Level 1 declarations (an agent with only ['codebase'] can’t edit files), while the model handles the tactical decisions (which search tool is best for this specific query).


πŸ“‹ Level 1: YAML capability declarations

Level 1 tools are what you write in the tools field of prompt and agent YAML frontmatter. They control what categories of operations an agent can perform.

Core built-in capabilities

Capability What it enables Read-only? Network?
codebase Semantic search across workspace Yes No
editor File creation, modification, deletion No No
filesystem Directory navigation, file metadata Yes No
fetch Retrieve content from web URLs Yes Yes
web_search Search the internet Yes Yes
search Workspace text search (exact/regex) Yes No
usages Code references, call hierarchies Yes No
problems Compile errors, lint warnings Yes No
changes Git changes and diffs Yes No

Tool sets (predefined groups)

VS Code provides predefined groups for convenience:

Tool set Includes Use case
#edit editor, filesystem Code modification workflows
#search codebase, search, usages Code discovery and analysis
#reader codebase, problems, changes, usages Context gathering without modification

MCP server tools in YAML

Tools from MCP servers use the @server-name prefix:

tools: ['codebase', '@github/*']      # All tools from GitHub MCP server
tools: ['editor', '@azure/deploy']     # Specific Azure tool only
tools: ['#search', '@company-wiki/*']  # Search + custom MCP

Common capability profiles

Profile Capabilities Use case
Read-only ['codebase', 'filesystem', 'search'] Code review, planning, research
Local edit ['codebase', 'editor', 'filesystem'] Refactoring, code generation
Research ['codebase', 'fetch', 'web_search'] Documentation, best practices
Full local ['codebase', 'editor', 'filesystem', 'search', 'usages', 'problems'] Implementation agents
Unrestricted [] or omit field All available tools enabled

βš™οΈ Level 2: Runtime tool calls

Level 2 is where tools actually do things. The model decides which runtime tools to call based on the task, your instructions, and the available capabilities. Here’s the catalog organized by what they do.

Always-available tools

Some runtime tools are always available regardless of your YAML tools field:

Tool Purpose
manage_todo_list Track task progress in structured lists
ask_questions Present structured questions to the user
runSubagent Delegate work to other agents
tool_search_tool_regex Discover deferred tools from MCP/extensions

This means even an agent restricted to tools: ['codebase'] can still track progress, ask for clarification, delegate to subagents, and discover MCP tools. You can’t create a truly passive agent.

Key runtime tools by category

Search tools:

Tool What it does Best for
semantic_search Natural language search using embeddings Discovering conceptually related code
grep_search Exact text/regex search across workspace Finding specific strings, function names
file_search Find files by glob pattern (paths only) Locating files before reading them
read_file Read file contents by line range Loading specific sections of code

Edit tools:

Tool What it does Best for
create_file Create new files with content Scaffolding new files
replace_string_in_file Replace exact text in a file Targeted edits with context
multi_replace_string_in_file Batch replacements across files Refactoring multiple locations

Execution tools:

Tool What it does Best for
run_in_terminal Execute shell commands Building, testing, running scripts
get_terminal_output Check output from background processes Monitoring long-running tasks

Interaction tools:

Tool What it does Best for
ask_questions Present structured choices to users Disambiguation, confirmation
manage_todo_list Track multi-step task progress Complex workflows with visibility

Delegation tools:

Tool What it does Best for
runSubagent Spawn a subagent for isolated work Parallel research, complex subtasks
search_subagent Launch a search-focused subagent Deep codebase exploration

Tool token costs

Every tool call consumes tokens β€” both for the function signature in the system prompt and for the results returned. Here’s a rough guide:

Tool category Signature cost Typical result cost
Search tools ~200 tokens each 500–2,000 tokens per call
Edit tools ~300 tokens each 100–500 tokens per call
Execution tools ~200 tokens each Variable (command output)
Interaction tools ~150 tokens each 200–500 tokens per call

More tools enabled means a larger system prompt (more function signatures). This is why tool restriction in agents isn’t just about safety β€” it’s also about token efficiency.


πŸ”Œ Tool sources: built-in, MCP, and extensions

Tools come from three sources, each with different characteristics:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Copilot Chat (the client)                   β”‚
β”‚                                                                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Built-in    β”‚  β”‚  Extension   β”‚  β”‚  MCP Server Tools    β”‚  β”‚
β”‚  β”‚  Tools       β”‚  β”‚  Tools       β”‚  β”‚                      β”‚  β”‚
β”‚  β”‚              β”‚  β”‚              β”‚  β”‚  @github (built-in)  β”‚  β”‚
β”‚  β”‚  read_file   β”‚  β”‚  From VS     β”‚  β”‚  @azure  (built-in)  β”‚  β”‚
β”‚  β”‚  grep_search β”‚  β”‚  Code        β”‚  β”‚  @your-server        β”‚  β”‚
β”‚  β”‚  create_file β”‚  β”‚  extensions  β”‚  β”‚  (custom)            β”‚  β”‚
β”‚  β”‚  run_in_     β”‚  β”‚  in the      β”‚  β”‚                      β”‚  β”‚
β”‚  β”‚  terminal    β”‚  β”‚  marketplace β”‚  β”‚  Runs as separate    β”‚  β”‚
β”‚  β”‚  ...         β”‚  β”‚              β”‚  β”‚  processes           β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Built-in tools

Ship with VS Code’s Copilot integration. Always present, no configuration needed.

  • Advantages: Zero setup, stable APIs, tightly integrated with the editor
  • Limitations: Fixed capabilities β€” you can’t add new built-in tools
  • Control: YAML tools field enables/disables categories

Extension-contributed tools

VS Code extensions can contribute tools to Copilot. These show up alongside built-in tools when the extension is installed.

  • Advantages: Easy installation from marketplace, curated quality
  • Limitations: Only available in VS Code (not CLI or coding agent), depend on extension activation
  • Control: Extensions must be installed and enabled; some contribute tools automatically

MCP server tools

External processes that communicate with Copilot through the Model Context Protocol. Run as separate processes, never loaded in-process.

  • Advantages: Any language, any capability, cross-platform, shareable
  • Limitations: Requires configuration (mcp.json), process management overhead
  • Control: @server-name prefix in YAML tool declarations

🌐 Understanding the Model Context Protocol

MCP (Model Context Protocol) is an open standard that defines how AI assistants communicate with external tools and data sources. It’s the β€œUSB-C for AI tools” β€” rather than building custom integrations for each AI assistant, you build one MCP server that works with any MCP-compatible client.

Core concepts

Concept What it is
MCP Server A process that provides tools, resources, and prompts to AI clients
MCP Client An AI assistant (like Copilot) that connects to servers
Tools Functions the AI can call to perform actions
Resources Data sources the AI can read
Transport Communication channel β€” stdio (local) or HTTP/SSE (remote)

How MCP servers work

1. DISCOVERY
   VS Code reads mcp.json β†’ finds server definitions
       β”‚
       β–Ό
2. INITIALIZATION
   VS Code spawns server process β†’ exchanges capabilities
       β”‚
       β–Ό
3. RUNTIME
   Model calls tool β†’ VS Code forwards to MCP server β†’
   Server executes β†’ Returns structured result
       β”‚
       β–Ό
4. SHUTDOWN
   Session ends β†’ VS Code terminates server process

All MCP servers run as separate processes β€” they’re never loaded in-process into VS Code. This provides language independence (write in TypeScript, C#, Python, or anything else), isolation (server crashes don’t affect the editor), and security (servers run with their own permissions).

Transport options

Transport Use case How it works
stdio Local servers VS Code spawns the server as a subprocess, communicates via stdin/stdout
HTTP/SSE Remote servers Server runs as an HTTP endpoint, accessible over the network

For GitHub Copilot integration, stdio is the default and recommended transport. HTTP/SSE is used when the server runs remotely or needs to serve multiple clients.

Configuration

MCP servers are configured in .vscode/mcp.json (workspace-level) or VS Code settings (user-level):

{
  "servers": {
    "my-server": {
      "type": "stdio",
      "command": "node",
      "args": ["./path/to/server.js"]
    }
  }
}

SDK implementations

MCP servers can be built in any language with an MCP SDK. All SDKs implement the same specification β€” the client doesn’t know or care what language the server is written in:

Aspect TypeScript C# (.NET) Python
Runtime Node.js .NET 8.0+ Python 3.10+
Style Functional Attribute-based Decorator-based
Best for Web integrations, npm ecosystem Enterprise, existing .NET apps AI/ML, data science

MCP Registry and discovery

The MCP Registry provides a centralized catalog of available MCP servers:

  • GitHub MCP Server (@github) β€” issues, pull requests, repository operations
  • Azure MCP Server (@azure) β€” Azure resources, documentation, queries
  • Community servers β€” Hundreds of community-built servers for databases, APIs, and services

VS Code includes a built-in gallery for discovering and installing MCP servers. The tool_search_tool_regex runtime tool also lets agents discover available MCP tools dynamically at runtime β€” this is how agents find and use β€œdeferred” tools that aren’t pre-loaded.


πŸ“Š Tool categories: what tools can do

Regardless of source (built-in, MCP, or extension), all tools fall into five functional categories:

Category Purpose Examples
Search Find information in the workspace or web semantic_search, grep_search, file_search, fetch_webpage
Edit Modify files in the workspace create_file, replace_string_in_file, multi_replace_string_in_file
Execute Run commands and programs run_in_terminal, get_terminal_output
Interact Communicate with users ask_questions, manage_todo_list
Delegate Orchestrate other agents runSubagent, search_subagent

This categorization matters for two reasons:

  1. Safety design β€” you control categories, not individual tools. An agent restricted to search tools can explore but can’t change anything.
  2. Prompt strategy β€” different categories have different token costs and reliability characteristics. Search tools return variable-size results; edit tools require precise input.

Understanding these categories helps you design agents with appropriate capability profiles. A code reviewer needs search + interact. A refactoring agent needs search + edit + execute. An orchestrator needs search + interact + delegate.


βœ… Decision framework: choosing the right tool source

What capability do you need?
β”‚
β”œβ”€ Already available as a built-in tool?
β”‚   └─ Yes β†’ Use built-in (no setup needed)
β”‚
β”œβ”€ Available as a VS Code extension?
β”‚   └─ Yes β†’ Is it VS Code-only acceptable?
β”‚       β”œβ”€ Yes β†’ Install the extension
β”‚       └─ No β†’ Continue to MCP
β”‚
β”œβ”€ Available as a community MCP server?
β”‚   └─ Yes β†’ Install and configure in mcp.json
β”‚
└─ None of the above
    └─ Build your own MCP server

When to build a custom MCP server

Build an MCP server when you need to:

  • Query external systems β€” databases, APIs, internal services
  • Perform complex computations β€” data processing, analysis, transformations
  • Access live data β€” real-time metrics, monitoring, dashboards
  • Enforce business logic β€” validation rules, compliance checks
  • Share capabilities across projects β€” reusable tooling for teams
  • Work cross-platform β€” tools that work in VS Code, CLI, and the coding agent

When NOT to build an MCP server

  • A prompt file can accomplish the task through existing tools
  • You only need coding standards β†’ use instruction files
  • You only need templates alongside instructions β†’ use skills
  • Existing tools (built-in or community) already provide the capability
  • The task is one-off and doesn’t justify the development overhead

⚠️ Tool restrictions and safety

Default behavior

When you omit the tools field in a prompt or agent file, all available tools are enabled β€” including built-in tools, extension tools, and all configured MCP servers. This is the maximum capability (and maximum token cost) configuration.

When you provide an empty array (tools: []), you get only the always-available tools (manage_todo_list, ask_questions, runSubagent, tool_search_tool_regex).

Safety through restriction

Tool restriction is your primary safety mechanism. It’s more reliable than natural language instructions because it’s enforced at the system level:

Instruction Reliability
β€œDon’t modify any files” (in agent instructions) Medium β€” model might ignore it
tools: ['codebase', 'search'] (no editor capability) High β€” edit tools aren’t available
Hook blocking PreToolUse Highest β€” code runs deterministically

For the strongest enforcement, combine tool restrictions (Level 1 YAML) with agent hooks (PreToolUse event). Tool restrictions remove the capability entirely; hooks provide programmatic validation of individual operations.


🎯 Conclusion

The tool ecosystem is what transforms GitHub Copilot from a text generator into a capable coding assistant. Built-in tools handle the common operations (search, edit, execute), extensions add specialized capabilities from the marketplace, and MCP servers let you build custom integrations that work across any MCP-compatible client.

Key takeaways

  • The two-level architecture separates your intent (Level 1 YAML declarations) from the model’s decisions (Level 2 runtime calls)
  • Level 1 capabilities enable groups of Level 2 runtime tools β€” writing tools: ['editor'] enables create_file, replace_string_in_file, and others
  • Four tools are always available regardless of restrictions: manage_todo_list, ask_questions, runSubagent, tool_search_tool_regex
  • MCP is the universal adapter β€” build once, use with any MCP-compatible AI client
  • All MCP servers run as separate processes (out-of-process), providing language independence and isolation
  • Tool restriction through YAML declarations is more reliable than natural language instructions for controlling agent behavior
  • Every tool adds token cost β€” both for its signature in the system prompt and its results in the conversation

Next steps


πŸ“š References

Model Context Protocol Specification [πŸ“˜ Official] The open standard defining MCP. Covers the complete protocol specification including tool definitions, resource access, transport mechanisms, and JSON-RPC 2.0 message format.

VS Code Copilot Custom Tools Documentation [πŸ“˜ Official] Microsoft’s documentation for tool capability declarations, MCP server configuration, and the built-in tool catalog. Covers both Level 1 YAML declarations and Level 2 runtime tools.

VS Code MCP Server Configuration [πŸ“˜ Official] Official guide for configuring MCP servers in VS Code β€” mcp.json format, transport options, environment variables, and the built-in MCP server gallery.

MCP Registry (mcp.so) [πŸ“— Verified Community] Community-maintained catalog of available MCP servers across categories β€” search providers, databases, cloud services, development tools, and more.