Model Context Protocol

A year later

 

 

Tomasz Godzik VirtusLab

Who am I

Team leader of Scala Open Source Team

Coordinator and VirtusLab representative in Scala Core Team

Open source

Metals

You probably heard of Metals, right?

Metals is a language server protocol server.

Metals is a model context protocol server.

Why do it in Metals?

Metals has the exact data to serve both purposes and makes it easier for people who already use it.

Model View Protocol

 

Model Context Protocol is very similar to Language Server Protocol, but instead of people it's for agents.

Host with MCP Client

MCP protocol

MCP protocol

MCP protocol

MCP Server 1

MCP Server 2

MCP Server 2

Local Data Source 1

Local Data Source 2

Web API

Why do we even need Model Context Protocol?

AI can sometimes go bonkers

Hallucinations are a problem, we want to reduce the amount of non-determinism in your tools

MCP provides information to your AI coding agent that it can use to verify and enrich its responses

 

But it's also a way to better query your information

Core MCP Concepts

MCP uses Json RPC, so each possible request and definition is represented by json schema

Core MCP Concepts

Resources

 

Tools

 

Prompts

Agents can ask the server for static content (resources) that might be useful for the current context

 

resources/list - list all available resource 
resources/read - read specific resource

Resources

{
  uri: string;           // Unique identifier for the resource
  name: string;          // Human-readable name
  description?: string;  // Optional description
  mimeType?: string;     // Optional MIME type
}

Resources

Example

{
  uri: "file:///logs/app.log",
  name: "Application Logs",
  mimeType: "text/plain"
}

 Agents interact with external systems, perform computations, and take actions in the real world.

 

tools/list - list all the tools available on the server

tools/call - invoke the tool

Tools

{
  name: string;          // Unique identifier for the tool
  description?: string;  // Human-readable description
  inputSchema: {         // JSON Schema for the tool's parameters
    type: "object",
    properties: { ... }  // Tool-specific parameters
  },
  annotations?: {}       // Optional hints about tool behavior
}

Tools

Example

{
  "name" : "compile-file",
  "description": "Compile a chosen Scala file",
  "schema" : {
    "type": "object",
    "properties": {
      "fileInFocus": {
         "type": "string",
         "description": "The file to compile..."
      }
    }
  }
}

- reusable prompt templates and workflows

- standardize and share common LLM interactions

- prompts/list and prompts/get requests

Prompts

{
  name: string;              // Unique identifier for the prompt
  description?: string;      // Human-readable description
  arguments?: [              // Optional list of arguments
    {
      name: string;          // Argument identifier
      description?: string;  // Argument description
      required?: boolean;    // Whether argument is required
    }
  ]
}

Prompts

Example

{
  name: "explain-code",
  description: "Explain how code works",
    arguments: [
      {
        name: "code",
        description: "Code to explain",
        required: true
      },
      {
        name: "language",
        description: "Programming language",
        required: false
      }
    ]
}

 

Who uses MCP?

 

- Vs Code with Copilot

- Cursor

- Windsurf

- probably more!

How does it look currently?


To minimize amount of dependencies we use the default Java SDK - https://github.com/modelcontextprotocol/java-sdk

 

We start an additional HTTP server within Metals

compile-full: Compile the entire Scala project.

Metals Tools

{
  "name" : "compile-full",
  "description": "Compile the whole Scala project",
  "schema" : { "type": "object", "properties": {} }  
}
compile-file: Compile a specific file.

Metals Tools

{
  "name" : "compile-file",
  "description": "Compile a chosen Scala file",
  "schema" : {
    "type": "object",
    "properties": {
      "fileInFocus": {
         "type": "string",
         "description": "The file to compile..."
      }
    }
  }
}
test: Run a Scala test suite.

Metals Tools

{
  "name" : "test",
  "description": "Run Scala test suite",
  "schema" : {
    "type": "object",
    "properties": {
      "testFile": {
        "type": "string",
        "description": "The file containing the test suite, if empty we will try to detect it"
      },
      "testClass": {
        "type": "string",
        "description": "Fully qualified name of the test class to run"
      },
      "verbose": {
        "type": "boolean",
        "description": "Print all output from the test suite, otherwise prints only errors and summary",
        "default": false
      }
    },
    "required": ["testClass"]
  }
}
glob-search: Search for symbols using a glob pattern.

Metals Tools

{
  "name" : "glob-search",
  "description": "Search for symbols using glob pattern",
  "schema" : {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "Substring of the symbol to search for"
      },
      "fileInFocus": {
        "type": "string",
        "description": "The current file in focus for context..."
      }
    },
    "required": ["query"]
  }
}
typed-glob-search: Search for symbols by type.

Metals Tools

{
  "name" : "typed-glob-search",
  "description": "Search for symbols by type using glob pattern",
  "schema" : {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "Substring of the symbol to search for"
      },
      "symbolType": {
        "type": "array",
        "items": {
          "type": "string",
          "enum": ["package", "class", "object", "function", "method", "trait"]
        },
        "description": "The type of symbol to search for"
      },
      "fileInFocus": {
        "type": "string",
        "description": "The current file in focus for context..."
      }
    },
    "required": ["query", "symbolType"]
  }
}
inspect: Inspect a symbol for members, signatures...

Metals Tools

{
  "name" : "inspect",
  "description": "Inspect a chosen Scala symbol.",
  "schema" : {
    "type": "object",
    "properties": {
      "fqcn": {
        "type": "string",
        "description": "Fully qualified name of the symbol to inspect"
      },
      "fileInFocus": {
        "type": "string",
        "description": "The current file in focus for context..."
      }
    },
    "required": ["fqcn"]
  }
}
get-docs: Retrieve documentation for a symbol.

Metals Tools

{
  "name" : "get-docs",
  "description": "Get documentation for a chosen Scala symbol",
  "schema" : {
    "type": "object",
    "properties": {
      "fqcn": {
        "type": "string",
        "description": "Fully qualified name of the symbol to get documentation for"
      }
    },
    "required": ["fqcn"]
  }
}
get-usages: Find usages of a symbol.

Metals Tools

{
  "name" : "get-usages",
  "description": "Get usages for a chosen Scala symbol.",
  "schema" : {
    "type": "object",
    "properties": {
      "fqcn": { 
        "type": "string",
        "description": "Fully qualified name of the symbol to get usages for"
      },
      "fileInFocus": {
        "type": "string",
        "description": "The current file in focus for context..."
      }
    },
    "required": ["fqcn"]
  }
}
import-build: Trigger a build import in the IDE.

Metals Tools

{
  "name" : "import-build",
  "description": "Import the build to IDE",
  "schema" : {"type": "object", "properties": {} }
}

 

 

We can add more! This is just the base idea.

 

Metals Tools

How can you use it?

Make sure you use newest Metals and enable the proper setting

 

Cursor and VS Code settings will be automatically set up for you

Editor settings

{
  "metals.startMcpServer" : true
}

Make sure that you use the Agent chat, this is the default in Cursor but not in VS Code

 

And you might sometimes need to force the agent to use MCP

Editor settings

Cursor

Cursor

VS Code Copilot

Demo!

In case I forget to show you the inspector

MCP inspector!

Future Ideas

Future Ideas

This is still new so there is a lot of possible improvements

 

Their aim is to increase your productiveness 

Suggest better prompts

Resources allow us to support certain scenarios like different libraries

When suggesting code take into account cats documentation as primary inspiration:

Concepts
Cats Effect introduces a large number of concepts which, 
while very general and individually simple, can seem 
foreign and intimidating if you're new to the space. 
This also brings along with it a set of terminology 
for describing concepts and scenarios which can be 
significantly different from that which is used in 
other asynchronous frameworks (such as Akka or Vert.x). 
This page is an attempt todescribe the Cats Effect 
runtime at a high level, introducing the concepts and terminology which is 
often assumed in discussions about the various details.
....
find-dep: Coursier dependency resolution

More Tools

{
  "name" : "find-dep",
  "description": "Use coursier to find a dependency",
  "schema" : {
    "type": "object",
    "properties": {
      "organization": {
        "type": "string",
        "description": "Organization to search for or its prefix"
      },
      "name": {
        "type": "string",
        "description": "Dependency name to search for or its prefix"
      },
      "version": {
        "type": "string",
        "description": "Version to search for or its prefix"
      }
    }
  }
}
run-diagnostics: Run diagnostics and debug metals

More Tools

{
  "name" : "run-diagnostics",
  "description": "Access information about the current state of metals...",
  "schema" : {"type": "object", "properties": {} }
}

More Tools

{
  "name" : "buildTarget/sources",
  "description": "Build target sources...",
  "schema" : {
    "type": "array", 
    "items": {
      "type": "string",
    }
}

Automatically provide LSP / BSP methods as possible MCP tools.

Everything that you ask and LLM guesses wrong, we might be able to provide a tool to minimize those cases

More Tools

You can write your own server!

 

There are some Scala MCP SDKs, you can use the to write things (or help out developing them)

 

There is even a prompt to help out  https://modelcontextprotocol.io/llms-full.txt and copy the full documentation text

More Tools

You can write your own server! There is Scala SDKs

 

https://github.com/windymelt/mcp-scala

https://github.com/indoorvivants/mcp

More Tools

There is probably a lot to improve, though now when we improve metals we improve your mcp experience as well

 

It's quite experimental, try it out!

More Tools

Let me know about new ones!

 

https://github.com/keynmol/scaladex-mcp

Other MCP Servers

Presentation

Questions?

Social media:

Bluesky:      @tgodzik.bsky.social 

Mastodon:  fosstodon.org/@tgodzik

Discord:       tgodzik

 

Contact as at VirtusLab: tgodzik@virtuslab.com

Why not focus on bugfixes?

Copy of Metals - Model Context Protocol

By Tomek Godzik

Copy of Metals - Model Context Protocol

  • 11