MCP (Model Context Protocol) Integration
Overview
MCP (Model Context Protocol) is a standard protocol that allows AI agents to communicate with external systems and services. theia AI has built-in support for MCP servers.
What is MCP?
Definition
MCP is an open protocol for connecting AI systems to external data sources and tools:
- Standardized: Common protocol across different AI tools
- Server-based: Run MCP servers that expose functionality
- Tool functions: Agents can call MCP functions like native tools
- Widely adopted: Thousands of MCP servers available
MCP Architecture
┌─────────────┐ ┌──────────────┐ ┌────────────┐
│ AI Agent │◄──────► │ MCP Client │◄──────► │ MCP Server │
│ (theia) │ calls │ (theia AI) │ protocol│ (Remote) │
└─────────────┘ └──────────────┘ └────────────┘
│
▼
┌──────────────┐
│ External │
│ System │
│ (GitHub, DB) │
└──────────────┘
Benefits
- No custom integration code for common services
- Reusable across different AI tools
- Community servers for popular services
- Secure authentication and permissions
Available MCP Servers
Built-in / Common Servers
-
GitHub MCP Server
- Repository operations
- Issue management
- Pull request handling
- Comment creation
- Search functionality
-
Playwright MCP Server
- Browser automation
- Web application testing
- Screenshot capture
- Form interaction
- Navigation control
-
Google Drive MCP Server
- File listing
- Document reading
- Upload/download
- Search documents
-
Slack MCP Server
- Send messages
- Read channels
- User information
- Channel management
-
Database MCP Servers
- PostgreSQL
- MySQL
- MongoDB
- Query execution
Finding MCP Servers
- Official registry: MCP server directory
- GitHub: Search for "MCP server"
- Community: theia community channels
- Create your own: MCP SDK available
Installing MCP Servers
Method 1: UI Configuration
-
Open AI Configuration
Settings → AI Configuration → MCP Servers tab -
Add MCP Server
- Click "Add Server"
- Select type:
- Remote URL
- Local executable
- npm package
-
Configure Connection
Server Name: github-mcp
Type: Remote
URL: https://api.mcp.github.com
Auth: Token
Token: ${GITHUB_TOKEN} -
Test Connection
- Click "Test"
- Verify functions appear
- Check authentication
Method 2: Configuration File
// .theia/mcp-servers.json
{
"servers": {
"github": {
"type": "remote",
"url": "https://api.mcp.github.com",
"auth": {
"type": "token",
"token": "${GITHUB_TOKEN}"
}
},
"playwright": {
"type": "executable",
"command": "npx",
"args": ["@modelcontextprotocol/server-playwright"],
"env": {
"PLAYWRIGHT_BROWSERS_PATH": "${HOME}/.cache/ms-playwright"
}
}
}
}
Method 3: Programmatic Registration
@injectable()
export class MCPServerProvider {
@inject(MCPServerRegistry)
protected registry: MCPServerRegistry;
async registerServers(): Promise<void> {
await this.registry.register({
id: 'github',
name: 'GitHub MCP Server',
url: 'https://api.mcp.github.com',
auth: {
type: 'token',
token: process.env.GITHUB_TOKEN
}
});
}
}
Using MCP in Agents
1. List Available Functions
// In AI Configuration view
MCP Servers → [server-name] → View Functions
// Or programmatically
const functions = await mcpClient.listFunctions('github');
2. Add to Agent Prompt
# In agent system prompt
You have access to GitHub via MCP:
Available functions:
- create_issue(title, body, labels, assignees)
- list_issues(state, labels, author)
- get_issue(issue_number)
- update_issue(issue_number, title, body, state)
- add_comment(issue_number, body)
- create_pull_request(title, body, head, base)
- list_pull_requests(state, author)
- merge_pull_request(pr_number, merge_method)
Repository: ${GITHUB_REPO}
Use these functions to interact with GitHub when needed.
3. Copy Functions to Prompt
In theia IDE:
- Open agent prompt editor
- Go to MCP Servers view
- Select server (e.g., GitHub)
- Click "Copy All Functions"
- Paste into prompt template
4. Agent Automatically Calls MCP
Once functions are in the prompt, the agent will:
- Recognize available MCP functions
- Determine when to use them
- Call them with appropriate parameters
- Process and present results
Example Use Cases
1. GitHub Workflow Automation
# GitHub Assistant Agent
Purpose: Automate GitHub workflows
MCP Server: GitHub
Capabilities:
- Analyze bugs from issues
- Report new bugs
- Review pull requests
- Search code and discussions
- Update project boards
Example workflow:
1. User: "Analyze bug #123"
2. Agent calls: get_issue(123)
3. Agent analyzes issue content
4. Agent calls: list_comments(123)
5. Agent provides analysis
Integration in prompt:
${mcp:github:*}
2. Automated Testing + Bug Reporting
# App Tester Agent
MCP Servers:
- Playwright (browser automation)
- GitHub (bug reporting)
Workflow:
1. Test application using Playwright MCP
- playwright_navigate(url)
- playwright_click(selector)
- playwright_fill(selector, text)
- playwright_screenshot()
2. When bug found:
- github_create_issue(title, body, labels: ['bug'])
- Include screenshot
- Add reproduction steps
3. Continue testing
3. Document Search and Analysis
# Document Assistant Agent
MCP Server: Google Drive
Functions:
- drive_search(query)
- drive_read(file_id)
- drive_list(folder_id)
Example:
User: "Find Q4 reports and summarize key metrics"
Agent:
1. drive_search("Q4 reports 2024")
2. drive_read(file_ids) for top results
3. Extract and summarize metrics
4. Present findings
4. Database Query Assistant
# SQL Assistant Agent
MCP Server: PostgreSQL
Functions:
- postgres_query(sql)
- postgres_tables()
- postgres_schema(table)
Example:
User: "How many active users do we have?"
Agent:
1. postgres_tables() - find user table
2. postgres_schema('users') - check columns
3. postgres_query("SELECT COUNT(*) FROM users WHERE active = true")
4. Present result
MCP Server Configuration
Authentication Patterns
1. Token-Based
{
"auth": {
"type": "token",
"token": "${GITHUB_TOKEN}",
"header": "Authorization",
"prefix": "Bearer"
}
}
2. OAuth
{
"auth": {
"type": "oauth",
"client_id": "${OAUTH_CLIENT_ID}",
"client_secret": "${OAUTH_CLIENT_SECRET}",
"scopes": ["repo", "issues"],
"token_url": "https://github.com/login/oauth/access_token"
}
}
3. API Key
{
"auth": {
"type": "api_key",
"key": "${API_KEY}",
"header": "X-API-Key"
}
}
4. Basic Auth
{
"auth": {
"type": "basic",
"username": "${USERNAME}",
"password": "${PASSWORD}"
}
}
Environment Variables
# .env file
GITHUB_TOKEN=ghp_xxx
GITHUB_REPO=owner/repo
OPENAI_API_KEY=sk-xxx
POSTGRES_CONNECTION=postgresql://user:pass@host/db
// Reference in config
{
"auth": {
"token": "${GITHUB_TOKEN}"
},
"settings": {
"default_repo": "${GITHUB_REPO}"
}
}
Server-Specific Settings
{
"servers": {
"playwright": {
"type": "executable",
"command": "npx",
"args": ["@modelcontextprotocol/server-playwright"],
"settings": {
"headless": true,
"slowMo": 100,
"viewport": {
"width": 1920,
"height": 1080
}
}
}
}
}
Creating Custom MCP Servers
When to Create Custom Server
- Integrate proprietary internal systems
- Wrap legacy APIs for AI access
- Combine multiple services
- Add custom business logic
- Enforce security policies
MCP Server Structure
// server.ts
import { MCPServer, Tool } from '@modelcontextprotocol/sdk';
const server = new MCPServer({
name: 'custom-server',
version: '1.0.0'
});
// Register tools
server.addTool({
name: 'custom_function',
description: 'Does something specific',
parameters: {
type: 'object',
properties: {
param1: {
type: 'string',
description: 'First parameter'
}
},
required: ['param1']
},
execute: async (params) => {
// Implementation
return { result: 'success' };
}
});
// Start server
server.listen(3000);
Example: Internal API MCP Server
import { MCPServer } from '@modelcontextprotocol/sdk';
import axios from 'axios';
const server = new MCPServer({
name: 'internal-api',
version: '1.0.0'
});
// Wrap internal API
server.addTool({
name: 'get_customer_data',
description: 'Retrieve customer information',
parameters: {
type: 'object',
properties: {
customer_id: { type: 'string' }
},
required: ['customer_id']
},
execute: async ({ customer_id }) => {
const response = await axios.get(
`https://internal-api.company.com/customers/${customer_id}`,
{
headers: {
'Authorization': `Bearer ${process.env.INTERNAL_API_TOKEN}`
}
}
);
return response.data;
}
});
server.addTool({
name: 'create_support_ticket',
description: 'Create customer support ticket',
parameters: {
type: 'object',
properties: {
customer_id: { type: 'string' },
title: { type: 'string' },
description: { type: 'string' },
priority: {
type: 'string',
enum: ['low', 'medium', 'high']
}
},
required: ['customer_id', 'title', 'description']
},
execute: async (params) => {
const response = await axios.post(
'https://internal-api.company.com/tickets',
params,
{
headers: {
'Authorization': `Bearer ${process.env.INTERNAL_API_TOKEN}`
}
}
);
return response.data;
}
});
server.listen(process.env.PORT || 3000);
Deploying Custom MCP Server
# Dockerfile
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD ["node", "dist/server.js"]
# docker-compose.yml
version: '3.8'
services:
custom-mcp-server:
build: .
ports:
- "3000:3000"
environment:
- INTERNAL_API_TOKEN=${INTERNAL_API_TOKEN}
restart: unless-stopped
Security Considerations
1. Authentication
- Never hardcode tokens in config files
- Use environment variables
- Rotate tokens regularly
- Scope tokens to minimum permissions
2. Authorization
// In MCP server
const checkPermissions = async (user: string, action: string) => {
// Verify user can perform action
const allowed = await authService.can(user, action);
if (!allowed) {
throw new Error('Unauthorized');
}
};
server.addTool({
name: 'sensitive_operation',
execute: async (params, context) => {
await checkPermissions(context.user, 'sensitive_operation');
// Proceed with operation
}
});
3. Rate Limiting
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use('/mcp', limiter);
4. Input Validation
server.addTool({
name: 'query_database',
execute: async ({ query }) => {
// Validate SQL to prevent injection
if (!isValidSQL(query)) {
throw new Error('Invalid SQL query');
}
// Sanitize input
const sanitized = sanitizeSQL(query);
return await db.query(sanitized);
}
});
5. Audit Logging
server.addMiddleware(async (request, next) => {
// Log all MCP calls
await auditLog.record({
timestamp: new Date(),
user: request.user,
tool: request.tool,
params: request.params,
ip: request.ip
});
const result = await next();
await auditLog.record({
...logEntry,
result: result.success ? 'success' : 'failure',
error: result.error
});
return result;
});
MCP vs Custom Tool Functions
When to Use MCP
✅ Integrating external services ✅ Reusing existing servers ✅ Need authentication/authorization ✅ Want standard protocol ✅ Service used across agents ✅ Community servers available
When to Use Custom Tools
✅ Simple workspace operations ✅ IDE-specific functionality ✅ No external network calls ✅ Agent-specific logic ✅ Performance critical ✅ Complex state management
Hybrid Approach
// Custom tool that uses MCP internally
@injectable()
export class EnhancedGitHubTool implements ToolProvider {
@inject(MCPClient)
protected mcp: MCPClient;
@inject(workspaceService)
protected workspace: workspaceService;
getTool(): Tool {
return {
name: 'analyze_and_report_bug',
description: 'Analyze code and create GitHub issue',
handler: async (args) => {
// Use workspace service (custom)
const code = await this.workspace.readFile(args.file);
const analysis = await this.analyzeCode(code);
// Use MCP for GitHub
const issue = await this.mcp.call('github', 'create_issue', {
title: analysis.title,
body: analysis.description,
labels: analysis.labels
});
return issue;
}
};
}
}
Troubleshooting MCP
Common Issues
-
Connection Failed
Error: Cannot connect to MCP server
Checks:
- Is server running?
- Correct URL/port?
- Firewall blocking?
- Network accessible? -
Authentication Error
Error: 401 Unauthorized
Checks:
- Token valid?
- Correct token format?
- Token not expired?
- Required scopes granted? -
Function Not Found
Error: Function 'xyz' not available
Checks:
- Function name spelled correctly?
- Server provides this function?
- Server version up to date?
- Refresh function list -
Timeout
Error: Request timeout
Checks:
- Server responsive?
- Network latency high?
- Increase timeout setting
- Check server logs
Debug Mode
{
"servers": {
"github": {
"url": "https://api.mcp.github.com",
"debug": true,
"logging": {
"level": "debug",
"file": "/tmp/mcp-github.log"
}
}
}
}
Testing MCP Servers
# Test MCP server directly
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{
"method": "tool_call",
"params": {
"name": "list_issues",
"parameters": {
"state": "open"
}
}
}'
Best Practices
1. Function Naming
// ✅ Good: Clear, action-oriented
'create_issue'
'list_pull_requests'
'get_customer_data'
// ❌ Bad: Ambiguous
'issue'
'prs'
'data'
2. Parameter Documentation
{
name: 'create_issue',
parameters: {
type: 'object',
properties: {
title: {
type: 'string',
description: 'Issue title (required, max 200 chars)'
},
body: {
type: 'string',
description: 'Issue description (markdown supported)'
},
labels: {
type: 'array',
items: { type: 'string' },
description: 'Labels to apply (e.g., ["bug", "high-priority"])'
}
},
required: ['title']
}
}
3. Error Handling
execute: async (params) => {
try {
const result = await externalAPI.call(params);
return {
success: true,
data: result
};
} catch (error) {
return {
success: false,
error: {
message: error.message,
code: error.code,
details: error.response?.data
}
};
}
}
4. Response Formatting
// ✅ Return structured data
{
success: true,
data: {
issue_number: 123,
url: 'https://github.com/...',
created_at: '2024-01-01T12:00:00Z'
}
}
// ❌ Return raw strings
"Issue #123 created"
5. Idempotency
execute: async ({ issue_id, comment }) => {
// Check if comment already added
const existing = await getComments(issue_id);
if (existing.some(c => c.body === comment)) {
return { success: true, message: 'Comment already exists' };
}
// Add comment
return await addComment(issue_id, comment);
}
Summary
MCP integration in theia AI provides:
✅ Standardized way to connect to external systems ✅ Reusable servers across agents and tools ✅ Community ecosystem of available servers ✅ Secure authentication and authorization ✅ Easy to configure and use in agents ✅ Flexible - use existing or create custom servers
Key steps:
- Install/configure MCP server
- Add functions to agent prompt
- Agent automatically calls MCP functions
- Process and present results
Common use cases:
- GitHub workflow automation
- Database queries
- Cloud service integration
- Internal API access
- Browser automation