Skip to main content

Custom Integration

Learn how to integrate ToolBoost MCPs into your own applications using the MCP protocol directly.

Overview

This guide is for developers building custom applications that need to connect to MCP servers hosted on ToolBoost. You'll learn how to make HTTP requests to ToolBoost's MCP endpoints and handle responses.

Prerequisites

  • Programming knowledge (examples in JavaScript/TypeScript, Python, cURL)
  • A ToolBoost account with deployed MCPs
  • Your project's API key
  • Basic understanding of HTTP and JSON

Connection Details

Base URL Structure

https://toolboost.dev/server/{author}/{mcp-slug}/mcp

Authentication

All requests require your API key in the query parameter:

?api_key=YOUR_API_KEY

Full URL Example:

https://toolboost.dev/server/github/github-mcp-server/mcp?api_key=tb_abc123

Transport Protocol

ToolBoost uses HTTP with Server-Sent Events (SSE) for MCP communication:

  • Protocol: HTTP/1.1 or HTTP/2
  • Content-Type: application/json
  • Streaming: Server-Sent Events (SSE) for real-time updates

Quick Start Examples

cURL

Test your connection with cURL:

curl -X POST "https://toolboost.dev/server/github/github-mcp-server/mcp?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'

JavaScript/TypeScript

Using the official MCP SDK:

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";

// Create transport
const transport = new SSEClientTransport(
new URL("https://toolboost.dev/server/github/github-mcp-server/mcp?api_key=YOUR_API_KEY")
);

// Create client
const client = new Client({
name: "my-app",
version: "1.0.0",
}, {
capabilities: {
tools: {},
},
});

// Connect
await client.connect(transport);

// List available tools
const tools = await client.listTools();
console.log(tools);

// Call a tool
const result = await client.callTool({
name: "list_repos",
arguments: {
username: "octocat"
}
});

console.log(result);

// Close connection
await client.close();

Python

Using the MCP Python SDK:

import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.sse import sse_client

async def main():
# Create SSE transport
async with sse_client(
"https://toolboost.dev/server/github/github-mcp-server/mcp?api_key=YOUR_API_KEY"
) as (read, write):
# Create client session
async with ClientSession(read, write) as session:
# Initialize
await session.initialize()

# List tools
tools = await session.list_tools()
print(f"Available tools: {tools}")

# Call a tool
result = await session.call_tool("list_repos", {
"username": "octocat"
})
print(f"Result: {result}")

# Run
asyncio.run(main())

MCP Protocol Reference

Initialize Connection

Request:

{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"clientInfo": {
"name": "my-app",
"version": "1.0.0"
}
}
}

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "github-mcp-server",
"version": "1.0.0"
}
}
}

List Tools

Request:

{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}

Response:

{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "list_repos",
"description": "List GitHub repositories for a user",
"inputSchema": {
"type": "object",
"properties": {
"username": {
"type": "string",
"description": "GitHub username"
}
},
"required": ["username"]
}
}
]
}
}

Call Tool

Request:

{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "list_repos",
"arguments": {
"username": "octocat"
}
}
}

Response:

{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Found 15 repositories for octocat:\n1. Hello-World\n2. ..."
}
]
}
}

Authentication Methods

Include API key in the URL:

https://toolboost.dev/server/author/mcp/mcp?api_key=YOUR_API_KEY

Authorization Header

Alternatively, use the Authorization header:

curl -X POST "https://toolboost.dev/server/author/mcp/mcp" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", ...}'

Complete Integration Example

Node.js/TypeScript Application

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";

class ToolBoostMCPClient {
private client: Client;
private transport: SSEClientTransport;

constructor(
private mcpUrl: string,
private apiKey: string
) {
// Add API key to URL
const url = new URL(this.mcpUrl);
url.searchParams.set('api_key', this.apiKey);

// Create transport
this.transport = new SSEClientTransport(url);

// Create client
this.client = new Client({
name: "my-application",
version: "1.0.0",
}, {
capabilities: {
tools: {},
resources: {},
prompts: {},
},
});
}

async connect() {
await this.client.connect(this.transport);
console.log("Connected to MCP server");
}

async listTools() {
const result = await this.client.listTools();
return result.tools;
}

async callTool(name: string, args: Record<string, unknown>) {
const result = await this.client.callTool({ name, arguments: args });
return result;
}

async listResources() {
const result = await this.client.listResources();
return result.resources;
}

async readResource(uri: string) {
const result = await this.client.readResource({ uri });
return result;
}

async disconnect() {
await this.client.close();
console.log("Disconnected from MCP server");
}
}

// Usage
async function main() {
const client = new ToolBoostMCPClient(
"https://toolboost.dev/server/github/github-mcp-server/mcp",
"tb_your_api_key"
);

try {
// Connect
await client.connect();

// List available tools
const tools = await client.listTools();
console.log("Available tools:", tools.map(t => t.name));

// Call a tool
const repos = await client.callTool("list_repos", {
username: "octocat"
});
console.log("Repositories:", repos);

// List resources
const resources = await client.listResources();
console.log("Available resources:", resources);

} catch (error) {
console.error("Error:", error);
} finally {
await client.disconnect();
}
}

main();

Python Application

import asyncio
import os
from mcp import ClientSession
from mcp.client.sse import sse_client

class ToolBoostMCPClient:
def __init__(self, mcp_url: str, api_key: str):
self.mcp_url = f"{mcp_url}?api_key={api_key}"
self.session = None

async def __aenter__(self):
self.transport = sse_client(self.mcp_url)
self.read, self.write = await self.transport.__aenter__()
self.session = ClientSession(self.read, self.write)
await self.session.__aenter__()
await self.session.initialize()
return self

async def __aexit__(self, exc_type, exc_val, exc_tb):
if self.session:
await self.session.__aexit__(exc_type, exc_val, exc_tb)
if self.transport:
await self.transport.__aexit__(exc_type, exc_val, exc_tb)

async def list_tools(self):
"""List all available tools"""
return await self.session.list_tools()

async def call_tool(self, name: str, arguments: dict):
"""Call a specific tool"""
return await self.session.call_tool(name, arguments)

async def list_resources(self):
"""List all available resources"""
return await self.session.list_resources()

async def read_resource(self, uri: str):
"""Read a specific resource"""
return await self.session.read_resource(uri)

# Usage
async def main():
mcp_url = "https://toolboost.dev/server/github/github-mcp-server/mcp"
api_key = os.getenv("TOOLBOOST_API_KEY", "tb_your_key")

async with ToolBoostMCPClient(mcp_url, api_key) as client:
# List tools
tools = await client.list_tools()
print(f"Available tools: {[t.name for t in tools.tools]}")

# Call a tool
result = await client.call_tool("list_repos", {
"username": "octocat"
})
print(f"Result: {result}")

# List resources
resources = await client.list_resources()
print(f"Resources: {resources}")

if __name__ == "__main__":
asyncio.run(main())

Error Handling

Common Error Codes

CodeMeaningSolution
401UnauthorizedCheck API key is correct
403ForbiddenVerify MCP is deployed and accessible
404Not FoundCheck MCP URL and slug are correct
429Rate LimitUpgrade plan or reduce request frequency
500Server ErrorCheck ToolBoost status, retry with backoff

Error Response Format

{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "Invalid Request",
"data": {
"details": "Missing required parameter"
}
}
}

Retry Strategy

Implement exponential backoff:

async function callWithRetry(fn: () => Promise<any>, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error: any) {
if (error.code === 429 && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}

Security Best Practices

1. Never Expose API Keys

❌ Don't do this:

// DON'T hardcode API keys in client-side code
const apiKey = "tb_abc123"; // NEVER do this!

✅ Do this:

// Use environment variables
const apiKey = process.env.TOOLBOOST_API_KEY;

// Or server-side proxy
const response = await fetch('/api/mcp-proxy', {
method: 'POST',
body: JSON.stringify({ tool: 'list_repos', args: { username: 'octocat' }})
});

2. Use HTTPS Only

Always use https:// URLs:

✅ https://toolboost.dev/server/...
❌ http://toolboost.dev/server/...

3. Validate Input

Validate all user input before passing to MCPs:

function validateUsername(username: string): boolean {
return /^[a-zA-Z0-9-]+$/.test(username);
}

if (!validateUsername(userInput)) {
throw new Error("Invalid username");
}

4. Handle Sensitive Data

Never log API keys or sensitive responses:

// ❌ Don't log full responses
console.log(response); // May contain sensitive data

// ✅ Log only what's needed
console.log(`Tool ${toolName} completed successfully`);

Rate Limits

ToolBoost enforces rate limits based on your plan:

PlanRequests/MonthRate Limit
Free10,00010 req/sec
Pro100,00050 req/sec
EnterpriseCustomCustom

Handle Rate Limits

if (error.code === 429) {
const retryAfter = error.headers?.['retry-after'] || 60;
await sleep(retryAfter * 1000);
// Retry request
}

Testing

Unit Tests

import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
import { ToolBoostMCPClient } from './mcp-client';

describe('MCP Client', () => {
let client: ToolBoostMCPClient;

beforeAll(async () => {
client = new ToolBoostMCPClient(
process.env.MCP_URL!,
process.env.API_KEY!
);
await client.connect();
});

afterAll(async () => {
await client.disconnect();
});

it('should list tools', async () => {
const tools = await client.listTools();
expect(tools).toBeInstanceOf(Array);
expect(tools.length).toBeGreaterThan(0);
});

it('should call tool successfully', async () => {
const result = await client.callTool('list_repos', {
username: 'octocat'
});
expect(result.content).toBeDefined();
});
});

Monitoring & Observability

Log MCP Calls

class InstrumentedMCPClient extends ToolBoostMCPClient {
async callTool(name: string, args: Record<string, unknown>) {
const start = Date.now();
try {
const result = await super.callTool(name, args);
const duration = Date.now() - start;

console.log({
event: 'mcp_tool_call',
tool: name,
duration_ms: duration,
status: 'success'
});

return result;
} catch (error) {
const duration = Date.now() - start;

console.error({
event: 'mcp_tool_call',
tool: name,
duration_ms: duration,
status: 'error',
error: error.message
});

throw error;
}
}
}

Next Steps

Resources

Need Help?