MCP Integration

Connect to Model Context Protocol (MCP) servers to instantly add capabilities from the MCP ecosystem. No code required—just configure and connect.

What is MCP?

The Model Context Protocol is an open standard for connecting AI models to external tools and data sources. MCP servers expose tools that any MCP client can use.

jaato includes a built-in MCP client that can connect to any MCP server, automatically discovering and exposing its tools to the model.

Benefits

  • Ecosystem — Use existing MCP servers
  • No code — Just configure connections
  • Auto-discovery — Tools detected automatically
  • Multi-server — Connect to multiple servers
Quick example
# .mcp.json - configure MCP servers
{
  "mcpServers": {
    "filesystem": {
      "type": "stdio",
      "command": "mcp-server-filesystem",
      "args": ["/home/user/projects"]
    },
    "github": {
      "type": "stdio",
      "command": "mcp-server-github"
    }
  }
}
Use in jaato
from jaato import JaatoClient, PluginRegistry

client = JaatoClient()
client.connect()  # Reads JAATO_PROVIDER and MODEL_NAME from env

registry = PluginRegistry(model_name=client.model_name)
registry.discover()

# Expose MCP plugin - connects to all servers
registry.expose_tool("mcp")

client.configure_tools(registry)

# Now model can use tools from MCP servers
response = client.send_message(
    "List files in the projects directory",
    on_output=handler
)

Configuration

MCP servers are configured in .mcp.json at your project root. This file defines which servers to connect to and how to start them.

Server Types

Type Description
stdio Server communicates via stdin/stdout
sse Server-Sent Events over HTTP

Server Configuration

Field Description
type Connection type (stdio or sse)
command Executable to run (stdio only)
args Command line arguments (optional)
env Environment variables (optional)
url Server URL (sse only)
.mcp.json structure
{
  "mcpServers": {
    "server-name": {
      "type": "stdio",
      "command": "executable-name",
      "args": ["arg1", "arg2"],
      "env": {
        "API_KEY": "your-key"
      }
    }
  }
}
Multiple servers
{
  "mcpServers": {
    "atlassian": {
      "type": "stdio",
      "command": "mcp-atlassian",
      "env": {
        "ATLASSIAN_URL": "https://company.atlassian.net",
        "ATLASSIAN_EMAIL": "user@company.com",
        "ATLASSIAN_TOKEN": "${ATLASSIAN_TOKEN}"
      }
    },
    "slack": {
      "type": "stdio",
      "command": "mcp-server-slack",
      "env": {
        "SLACK_TOKEN": "${SLACK_TOKEN}"
      }
    },
    "postgres": {
      "type": "stdio",
      "command": "mcp-server-postgres",
      "args": ["postgresql://localhost/mydb"]
    }
  }
}

Here are some commonly used MCP servers you can integrate:

Server Provides
mcp-server-filesystem File operations (read, write, list)
mcp-server-github GitHub repos, issues, PRs
mcp-server-postgres PostgreSQL database queries
mcp-server-sqlite SQLite database access
mcp-atlassian Jira, Confluence integration
mcp-server-slack Slack messaging
mcp-server-fetch HTTP requests, web scraping
Finding MCP Servers
Browse the MCP servers repository for a full list of available servers.
Install MCP servers
# Most MCP servers are npm packages
npm install -g @modelcontextprotocol/server-filesystem
npm install -g @modelcontextprotocol/server-github

# Some are Python packages
pip install mcp-atlassian

# Or use uvx for Python servers
# (no install needed, runs directly)
uvx mcp-server-fetch
Example: Filesystem server
# .mcp.json
{
  "mcpServers": {
    "files": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/home/user/projects"
      ]
    }
  }
}

# Tools provided:
# - read_file: Read file contents
# - write_file: Write to a file
# - list_directory: List directory contents
# - create_directory: Create a new directory
# - move_file: Move/rename a file
# - search_files: Search for files
# - get_file_info: Get file metadata

Tool Discovery

When you expose the MCP plugin, jaato automatically:

  1. Reads .mcp.json
  2. Starts configured servers
  3. Queries each server for available tools
  4. Registers all tools with the model

Tool Naming

Tools are namespaced by server name to avoid conflicts:

  • filesystem__read_file
  • github__create_issue
  • postgres__query

Checking Available Tools

You can inspect which tools are available from your MCP servers.

List MCP tools
from jaato import PluginRegistry

registry = PluginRegistry()
registry.discover()
registry.expose_tool("mcp")

# Get the MCP plugin
mcp_plugin = registry.get_plugin("mcp")

# List all tools from all servers
tools = mcp_plugin.get_tool_schemas()
for tool in tools:
    print(f"{tool.name}: {tool.description}")
Example output
# Output:
# filesystem__read_file: Read the contents of a file
# filesystem__write_file: Write content to a file
# filesystem__list_directory: List directory contents
# github__create_issue: Create a new issue
# github__list_repos: List repositories
# github__search_code: Search code in repos
# ...
Check specific server
# Get tools from a specific server
from shared.mcp_context_manager import MCPClientManager

manager = MCPClientManager()
await manager.connect_from_config(".mcp.json")

# List tools from one server
filesystem_tools = await manager.list_tools("filesystem")
for tool in filesystem_tools:
    print(f"  {tool.name}")

Using MCP Tools

Once configured, MCP tools work like any other jaato tool. The model sees them in its tool list and can call them as needed.

Automatic Routing

When the model calls an MCP tool, jaato automatically:

  1. Parses the tool name to find the server
  2. Forwards the call to the correct server
  3. Returns the result to the model

Error Handling

If a server is unavailable or a tool call fails, the error is returned to the model so it can adapt.

Model using MCP tools
from jaato import JaatoClient, PluginRegistry

client = JaatoClient()
client.connect()  # Reads JAATO_PROVIDER and MODEL_NAME from env

registry = PluginRegistry(model_name=client.model_name)
registry.discover()
registry.expose_tool("mcp")
client.configure_tools(registry)

# Model can now use MCP tools
response = client.send_message(
    "Read the README.md file and summarize it",
    on_output=lambda s, t, m: print(t, end="")
)

# Behind the scenes:
# 1. Model decides to call filesystem__read_file
# 2. jaato routes to filesystem server
# 3. Server reads the file
# 4. Result returned to model
# 5. Model generates summary
Multi-server workflow
# With both filesystem and github configured,
# the model can combine tools:

response = client.send_message(
    """
    Read the TODO.md file, then create a
    GitHub issue for each incomplete item.
    """,
    on_output=handler
)

# Model might:
# 1. Call filesystem__read_file("TODO.md")
# 2. Parse the TODO items
# 3. Call github__create_issue for each one
# 4. Report what it created

Environment Variables

Many MCP servers need credentials or configuration. You can pass these via environment variables in the config.

Direct Values

You can put values directly in .mcp.json, but this isn't recommended for secrets.

Variable Substitution

Use ${VAR_NAME} syntax to reference environment variables from your shell or .env file.

Security
Never commit secrets to .mcp.json. Use environment variable substitution and keep secrets in .env (which should be in .gitignore).
.mcp.json with env vars
{
  "mcpServers": {
    "github": {
      "type": "stdio",
      "command": "mcp-server-github",
      "env": {
        "GITHUB_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "postgres": {
      "type": "stdio",
      "command": "mcp-server-postgres",
      "args": ["${DATABASE_URL}"]
    }
  }
}
.env file
# .env (add to .gitignore!)
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
DATABASE_URL=postgresql://user:pass@localhost/db
ATLASSIAN_TOKEN=ATATTxxxxxxxxxxxxxxxx
SLACK_TOKEN=xoxb-xxxxxxxxxxxx
Load in your app
from dotenv import load_dotenv

# Load .env before creating registry
load_dotenv()

# Now MCP plugin will substitute env vars
registry = PluginRegistry()
registry.discover()
registry.expose_tool("mcp")

Troubleshooting

Server Won't Start

  • Check the command is installed and in PATH
  • Verify args are correct
  • Check server logs for errors

Tools Not Appearing

  • Ensure .mcp.json is in project root
  • Check server name matches config
  • Verify server exposes tools (not all do)

Authentication Errors

  • Check environment variables are set
  • Verify token/credentials are valid
  • Check server-specific auth requirements
Debug MCP connections
# Enable verbose logging
import logging
logging.basicConfig(level=logging.DEBUG)

# Check if servers connected
from shared.mcp_context_manager import MCPClientManager

manager = MCPClientManager()
await manager.connect_from_config(".mcp.json")

# List connected servers
for name, client in manager.clients.items():
    print(f"{name}: connected")

# Test a specific tool
result = await manager.call_tool_auto(
    "filesystem__read_file",
    {"path": "README.md"}
)
print(result)
Test server manually
# Run server directly to see output
$ mcp-server-filesystem /home/user

# For npm servers
$ npx @modelcontextprotocol/server-filesystem /home/user

# Check for error messages in output

Next Steps

Complete MCP setup
# 1. Install MCP servers
npm install -g @modelcontextprotocol/server-filesystem
pip install mcp-atlassian

# 2. Create .mcp.json
{
  "mcpServers": {
    "files": {
      "type": "stdio",
      "command": "mcp-server-filesystem",
      "args": ["."]
    },
    "jira": {
      "type": "stdio",
      "command": "mcp-atlassian",
      "env": {
        "ATLASSIAN_URL": "${ATLASSIAN_URL}",
        "ATLASSIAN_EMAIL": "${ATLASSIAN_EMAIL}",
        "ATLASSIAN_TOKEN": "${ATLASSIAN_TOKEN}"
      }
    }
  }
}

# 3. Set up .env
ATLASSIAN_URL=https://company.atlassian.net
ATLASSIAN_EMAIL=you@company.com
ATLASSIAN_TOKEN=your-token

# 4. Use in code
from dotenv import load_dotenv
load_dotenv()

registry.discover()
registry.expose_tool("mcp")
client.configure_tools(registry)

# Ready to use!