Integration Guide
Integrate MCP.do with Claude, AI models, and applications
Comprehensive guide to integrating MCP.do with AI models, applications, and development tools.
Claude Desktop Integration
Integration Architecture
graph LR
subgraph "AI Clients"
CLAUDE[Claude Desktop]
CODE[Claude Code]
CHAT[ChatGPT]
CUSTOM[Custom Apps]
end
subgraph "MCP Transport"
SSE[SSE Transport<br/>Long-lived]
HTTP[HTTP JSON-RPC<br/>Request/Response]
end
subgraph "MCP.do Server"
AUTH[Authentication]
TOOLS[do + elicit Tools]
EXEC[Execution Engine]
end
subgraph "Platform"
SDK[SDK Primitives]
PAYLOAD[Payload CMS]
WORKERS[90+ Workers]
end
CLAUDE --> SSE
CODE --> SSE
CHAT --> HTTP
CUSTOM --> HTTP
SSE --> AUTH
HTTP --> AUTH
AUTH --> TOOLS
TOOLS --> EXEC
EXEC --> SDK
SDK --> PAYLOAD
SDK --> WORKERS
Configuration
Add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"do": {
"url": "https://mcp.do",
"type": "sse",
"headers": {
"Authorization": "Bearer sk_live_xxxxx"
}
}
}
}OAuth Flow (Recommended)
{
"mcpServers": {
"do": {
"url": "https://mcp.do",
"type": "sse",
"oauth": {
"authorizationServer": "https://oauth.do",
"clientId": "your_client_id",
"scopes": ["mcp:tools", "mcp:resources"]
}
}
}
}Usage in Claude
User: List all businesses in the platform
Claude: I'll use the do tool to query businesses.
[Uses do tool with script: await db.list('Business')]
Found 15 businesses:
1. Acme Corp
2. Widget Inc
...Claude Code Integration
Direct SDK Integration
import { MCPClient } from '@modelcontextprotocol/sdk/client/index.js'
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
// Create transport
const transport = new SSEClientTransport(new URL('https://mcp.do'), {
headers: {
Authorization: 'Bearer sk_live_xxxxx',
},
})
// Create client
const client = new MCPClient({ name: 'my-app', version: '1.0.0' }, {})
// Connect
await client.connect(transport)
// List available tools
const { tools } = await client.listTools()
console.log('Tools:', tools)
// Execute operations
const result = await client.callTool('do', {
script: 'await db.list("Business")',
})
console.log('Result:', result.content[0].text)Helper Class
class DoClient {
private client: MCPClient
private constructor(apiKey: string) {
const transport = new SSEClientTransport(new URL('https://mcp.do'), { headers: { Authorization: `Bearer ${apiKey}` } })
this.client = new MCPClient({ name: 'do-client', version: '1.0.0' }, {})
}
static async create(apiKey: string): Promise<DoClient> {
const client = new DoClient(apiKey)
await client.client.connect(client.client['transport'])
return client
}
async execute(script: string) {
const result = await this.client.callTool('do', { script })
return JSON.parse(result.content[0].text)
}
async elicit(message: string, schema: object) {
const result = await this.client.callTool('elicit', {
message,
schema,
})
return JSON.parse(result.content[0].text)
}
async close() {
await this.client.close()
}
}
// Usage
const client = await DoClient.create(process.env.DO_API_KEY!)
const businesses = await client.execute('await db.list("Business")')
console.log(businesses)
await client.close()Node.js Application
Basic Integration
import { MCPClient } from '@modelcontextprotocol/sdk'
// Initialize client
const client = new MCPClient({
serverUrl: 'https://mcp.do',
apiKey: process.env.DO_API_KEY,
transport: 'sse',
})
// Execute operations
async function createOrder(customerEmail: string, items: any[]) {
try {
const result = await client.useTool('do', {
script: `
const customers = await db.list('Customer', { email: \`${customerEmail}\` })
if (customers.length === 0) {
throw new Error('Customer not found')
}
const customer = customers[0]
const order = await db.create('Order', {
customer: customer,
items: ${JSON.stringify(items)},
status: 'pending'
})
await send($.Email.send, {
to: customer.email,
subject: 'Order Confirmation',
body: \`Order #\${order.id} created\`
})
return order
`,
})
if (result.isError) {
throw new Error(result.content[0].text)
}
return result
} catch (error) {
console.error('Failed to create order:', error)
throw error
}
}
// Use with async/await
const order = await createOrder('[email protected]', [{ product: 'widget', quantity: 2 }])Express.js Middleware
import express from 'express'
import { MCPClient } from '@modelcontextprotocol/sdk'
const app = express()
const mcpClient = new MCPClient({
serverUrl: 'https://mcp.do',
apiKey: process.env.DO_API_KEY,
})
// Middleware to attach MCP client
app.use((req, res, next) => {
req.mcp = mcpClient
next()
})
// Route using MCP
app.post('/api/orders', async (req, res) => {
try {
const order = await req.mcp.useTool('do', {
script: `
await db.create('Order', ${JSON.stringify(req.body)})
`,
})
res.json(order)
} catch (error) {
res.status(500).json({ error: error.message })
}
})
app.listen(3000)Python Integration
Using MCP SDK
from mcp import Client
import asyncio
import os
async def main():
# Create client
client = Client(
server_url="https://mcp.do",
api_key=os.environ['DO_API_KEY'],
transport='sse'
)
# Connect
await client.connect()
# List tools
tools = await client.list_tools()
print(f"Available tools: {tools}")
# Execute operation
result = await client.call_tool('do', {
'script': 'await db.list("Business")'
})
print(f"Result: {result}")
# Close connection
await client.close()
# Run
asyncio.run(main())FastAPI Integration
from fastapi import FastAPI, Depends
from mcp import Client
import os
app = FastAPI()
# MCP client dependency
async def get_mcp_client():
client = Client(
server_url="https://mcp.do",
api_key=os.environ['DO_API_KEY']
)
await client.connect()
try:
yield client
finally:
await client.close()
@app.post("/api/orders")
async def create_order(
order_data: dict,
mcp: Client = Depends(get_mcp_client)
):
result = await mcp.call_tool('do', {
'script': f'await db.create("Order", {order_data})'
})
return resultLangChain Integration
Custom Tool
import { Tool } from 'langchain/tools'
import { MCPClient } from '@modelcontextprotocol/sdk'
class DoTool extends Tool {
name = 'do'
description = 'Execute TypeScript against the .do platform SDK'
private client: MCPClient
constructor() {
super()
this.client = new MCPClient({
serverUrl: 'https://mcp.do',
apiKey: process.env.DO_API_KEY,
})
}
async _call(script: string): Promise<string> {
const result = await this.client.useTool('do', { script })
return result.content[0].text
}
}
// Use with LangChain agent
import { initializeAgentExecutorWithOptions } from 'langchain/agents'
import { ChatOpenAI } from 'langchain/chat_models/openai'
const tools = [new DoTool()]
const model = new ChatOpenAI({ temperature: 0 })
const executor = await initializeAgentExecutorWithOptions(tools, model, { agentType: 'chat-conversational-react-description' })
const result = await executor.call({
input: 'List all businesses and create a summary report',
})React Application
Custom Hook
import { useState, useEffect } from 'react'
import { MCPClient } from '@modelcontextprotocol/sdk'
export function useMCP(apiKey: string) {
const [client, setClient] = useState<MCPClient | null>(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<Error | null>(null)
useEffect(() => {
let mounted = true
let mcpClient: MCPClient | null = null
const initClient = async () => {
try {
mcpClient = new MCPClient({
serverUrl: 'https://mcp.do',
apiKey
})
await mcpClient.connect()
if (mounted) {
setClient(mcpClient)
setLoading(false)
}
} catch (err) {
if (mounted) {
setError(err instanceof Error ? err : new Error('Failed to connect'))
setLoading(false)
}
}
}
initClient()
return () => {
mounted = false
mcpClient?.close()
}
}, [apiKey])
const execute = async (script: string) => {
if (!client) throw new Error('Client not initialized')
return await client.useTool('do', { script })
}
const elicit = async (message: string, schema: object) => {
if (!client) throw new Error('Client not initialized')
return await client.useTool('elicit', { message, schema })
}
return { client, loading, error, execute, elicit }
}
// Usage in component
function BusinessList() {
const { execute, loading } = useMCP(process.env.REACT_APP_DO_API_KEY!)
const [businesses, setBusinesses] = useState([])
useEffect(() => {
if (!loading) {
execute('await db.list("Business")').then(result => {
setBusinesses(JSON.parse(result.content[0].text))
})
}
}, [loading])
return (
<ul>
{businesses.map(b => <li key={b.id}>{b.name}</li>)}
</ul>
)
}REST API Wrapper
Create HTTP Gateway
import express from 'express'
import { MCPClient } from '@modelcontextprotocol/sdk'
const app = express()
app.use(express.json())
// MCP client
const mcp = new MCPClient({
serverUrl: 'https://mcp.do',
apiKey: process.env.DO_API_KEY,
})
// Execute endpoint
app.post('/api/execute', async (req, res) => {
try {
const { script } = req.body
const result = await mcp.useTool('do', { script })
res.json(result)
} catch (error) {
res.status(500).json({ error: error.message })
}
})
// Elicit endpoint
app.post('/api/elicit', async (req, res) => {
try {
const { message, schema, uiType } = req.body
const result = await mcp.useTool('elicit', {
message,
schema,
uiType,
})
res.json(result)
} catch (error) {
res.status(500).json({ error: error.message })
}
})
app.listen(3000)CI/CD Integration
GitHub Actions
name: Deploy with MCP
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy via MCP
run: |
npx tsx deploy.ts
env:
DO_API_KEY: ${{ secrets.DO_API_KEY }}deploy.ts:
import { MCPClient } from '@modelcontextprotocol/sdk'
const client = new MCPClient({
serverUrl: 'https://mcp.do',
apiKey: process.env.DO_API_KEY!,
})
await client.connect()
// Deploy worker
await client.useTool('do', {
script: `
const code = await api.fetch('https://raw.githubusercontent.com/...')
await send($.Worker.deploy, { name: 'api', code })
`,
})
console.log('Deployment complete')
await client.close()Best Practices
1. Connection Management
// ✅ Reuse connection
const client = new MCPClient({ ... })
await client.connect()
// Multiple operations
await client.useTool('do', { ... })
await client.useTool('do', { ... })
await client.close()
// ❌ Don't create new connection per request
async function execute(script) {
const client = new MCPClient({ ... })
await client.connect()
const result = await client.useTool('do', { script })
await client.close()
return result
}2. Error Handling
try {
const result = await client.useTool('do', { script })
if (result.isError) {
console.error('Execution error:', result.content[0].text)
}
} catch (error) {
if (error.status === 429) {
// Rate limit - retry with backoff
} else if (error.status === 401) {
// Auth failed - refresh token
} else {
throw error
}
}3. Type Safety
// Define types for results
interface Business {
id: string
name: string
email: string
}
async function getBusinesses(): Promise<Business[]> {
const result = await client.useTool('do', {
script: 'await db.list("Business")',
})
return JSON.parse(result.content[0].text) as Business[]
}4. Security
// ❌ Don't expose API key
const client = new MCPClient({
apiKey: 'sk_live_xxxxx', // Hardcoded!
})
// ✅ Use environment variables
const client = new MCPClient({
apiKey: process.env.DO_API_KEY,
})
// ✅ Use OAuth for user-facing apps
const client = new MCPClient({
serverUrl: 'https://mcp.do',
oauth: {
authorizationServer: 'https://oauth.do',
clientId: process.env.OAUTH_CLIENT_ID,
},
})Next Steps
- The
doTool - Tool reference - The
elicitTool - Human-in-the-loop - Authentication - Security configuration
- Debugging - Troubleshooting