Erstellen von benutzerdefinierten MCP Servern
Erfahren Sie, wie Sie Ihre eigenen MCP Server erstellen, um die Fähigkeiten von TeamDay mit benutzerdefinierten Integrationen und spezialisierten Tools zu erweitern.
Erste Schritte
Voraussetzungen
- Node.js 18+ oder Python 3.8+
- Verständnis von REST APIs und WebSockets
- Vertrautheit mit Ihrer Ziel-Integration
- Zugriff auf TeamDay-Entwicklungsumgebung
Grundlegende MCP Server-Struktur
// Basis Node.js MCP Server
const express = require('express');
const { MCPServer } = require('@teamday/mcp-sdk');
const app = express();
const mcpServer = new MCPServer({
name: 'my-custom-server',
version: '1.0.0',
description: 'Custom integration server'
});
// Tools registrieren
mcpServer.registerTool('my_tool', {
description: 'My custom tool',
parameters: {
input: { type: 'string', required: true }
},
handler: async (params) => {
// Tool-Implementierung
return { result: `Processed: ${params.input}` };
}
});
app.use('/mcp', mcpServer.handler);
app.listen(3000);
Tool-Implementierung
Einfache Tools
// Text-Verarbeitungs-Tool
mcpServer.registerTool('process_text', {
description: 'Process and transform text',
parameters: {
text: { type: 'string', required: true },
operation: { type: 'string', enum: ['uppercase', 'lowercase', 'reverse'] }
},
handler: async ({ text, operation }) => {
switch (operation) {
case 'uppercase': return { result: text.toUpperCase() };
case 'lowercase': return { result: text.toLowerCase() };
case 'reverse': return { result: text.split('').reverse().join('') };
default: throw new Error('Invalid operation');
}
}
});
Datenbank-Tools
// Datenbank-Abfrage-Tool
mcpServer.registerTool('query_database', {
description: 'Execute database queries',
parameters: {
query: { type: 'string', required: true },
params: { type: 'array', default: [] }
},
handler: async ({ query, params }) => {
const db = await getDatabase();
const result = await db.query(query, params);
return { data: result.rows, count: result.rowCount };
}
});
API Integration Tools
// HTTP-Request-Tool
mcpServer.registerTool('http_request', {
description: 'Make HTTP requests to external APIs',
parameters: {
url: { type: 'string', required: true },
method: { type: 'string', default: 'GET' },
headers: { type: 'object', default: {} },
body: { type: 'object' }
},
handler: async ({ url, method, headers, body }) => {
const response = await fetch(url, {
method,
headers,
body: body ? JSON.stringify(body) : undefined
});
return {
status: response.status,
data: await response.json()
};
}
});
Konfiguration und Deployment
Umgebungskonfiguration
// config.js
module.exports = {
port: process.env.PORT || 3000,
database: {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
name: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD
},
apis: {
external_service: {
url: process.env.EXTERNAL_API_URL,
key: process.env.EXTERNAL_API_KEY
}
}
};
Docker-Deployment
FROM node:18-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Docker Compose
version: '3.8'
services:
mcp-server:
build: .
ports:
- "3000:3000"
environment:
- DB_HOST=database
- DB_PASSWORD=${DB_PASSWORD}
depends_on:
- database
database:
image: postgres:15
environment:
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Testen und Validierung
Unit Tests
// tests/tools.test.js
const { MCPServer } = require('@teamday/mcp-sdk');
describe('Custom Tools', () => {
let server;
beforeEach(() => {
server = new MCPServer({ name: 'test-server' });
// Tools registrieren...
});
test('process_text tool', async () => {
const result = await server.callTool('process_text', {
text: 'hello',
operation: 'uppercase'
});
expect(result.result).toBe('HELLO');
});
});
Sicherheit Best Practices
Authentifizierung
// API-Schlüssel-Authentifizierung
const authenticateRequest = (req, res, next) => {
const apiKey = req.headers['x-api-key'];
if (!apiKey || !isValidApiKey(apiKey)) {
return res.status(401).json({ error: 'Invalid API key' });
}
next();
};
app.use('/mcp', authenticateRequest);
Eingabe-Validierung
const { body, validationResult } = require('express-validator');
app.post('/mcp/tools/:tool',
body('parameters').isObject(),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Anfrage verarbeiten...
}
);
Fehlerbehandlung
Strukturierte Fehler-Antworten
class MCPError extends Error {
constructor(code, message, details = null) {
super(message);
this.code = code;
this.details = details;
this.retryable = ['TIMEOUT', 'RATE_LIMIT'].includes(code);
}
}
// Error-Handler-Middleware
app.use((error, req, res, next) => {
if (error instanceof MCPError) {
res.status(400).json({
error: {
code: error.code,
message: error.message,
details: error.details,
retryable: error.retryable
}
});
} else {
res.status(500).json({
error: {
code: 'INTERNAL_ERROR',
message: 'Internal server error',
retryable: false
}
});
}
});
Performance-Optimierung
Caching
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 600 }); // 10 Minuten
mcpServer.registerTool('cached_api_call', {
handler: async ({ url }) => {
const cacheKey = `api:${url}`;
let result = cache.get(cacheKey);
if (!result) {
result = await fetch(url).then(r => r.json());
cache.set(cacheKey, result);
}
return result;
}
});
Connection Pooling
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20,
idleTimeoutMillis: 30000
});
const getDatabase = () => pool;
Monitoring und Protokollierung
Strukturierte Protokollierung
const winston = require('winston');
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'mcp-server.log' }),
new winston.transports.Console()
]
});
// Tool-Ausführungen protokollieren
mcpServer.on('tool_execution', (toolName, params, result, duration) => {
logger.info('Tool executed', {
tool: toolName,
duration,
success: !result.error
});
});
Health Checks
app.get('/health', async (req, res) => {
const health = {
status: 'healthy',
timestamp: new Date().toISOString(),
services: {}
};
try {
// Überprüfen Sie die Datenbank
await pool.query('SELECT 1');
health.services.database = 'healthy';
} catch (error) {
health.services.database = 'unhealthy';
health.status = 'degraded';
}
res.json(health);
});
Veröffentlichung Ihres Servers
NPM-Paket
{
"name": "@yourorg/mcp-custom-server",
"version": "1.0.0",
"description": "Custom MCP server for TeamDay",
"main": "server.js",
"keywords": ["mcp", "teamday", "integration"],
"repository": "https://github.com/yourorg/mcp-custom-server"
}
TeamDay Marketplace
- Testen Sie gründlich in der Entwicklung
- Erstellen Sie umfassende Dokumentation
- Reichen Sie im TeamDay Marketplace ein
- Bieten Sie Support und Wartung an
Nächste Schritte
- Was sind MCP Server
- MCP Server installieren
- [Benutzerdefinierte Tools