- Multi-tenant MCP Server
Multi-tenant MCP Server
Multi-tenant MCP Server
A multi-tenant Model Context Protocol (MCP) server that enables multiple tenants to connect to Integration App's MCP server with their own credentials.
Features
- Multi-tenant support with isolated connections
- Database persistence for tenant information
- Live tool discovery from Integration App
- Audit logging
- Rate limiting and security middleware
- Health check endpoint
- Graceful shutdown handling
Prerequisites
- Node.js >= 18.0.0
- PostgreSQL database
- Integration App account and credentials
Environment Variables
Create a .env file with the following variables:
# Server Configuration
PORT=3000
NODE_ENV=development
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/mcp_service"
# Security
ADMIN_API_KEY="your-admin-api-key"
Installation
- Clone the repository:
git clone <repository-url>
cd mcp-service
- Install dependencies:
npm install
- Run database migrations:
npm run migrate
- Start the server:
npm start
For development:
npm run dev
API Endpoints
Health Check
GET /health
Create Tenant
POST /api/tenants
Authorization: Bearer <admin-api-key>
{
"integrationKey": "hubspot|notion|etc",
"integrationAppToken": "your-integration-app-token"
}
List Tools
POST /api/tenant/:tenantId/tool
Authorization: Bearer <tenant-token>
{
"method": "listTools"
}
Execute Tool
POST /api/tenant/:tenantId/tool
Authorization: Bearer <tenant-token>
{
"method": "tool-name",
"params": {
// tool parameters
}
}
Deployment
Heroku
- Create a new Heroku app:
heroku create
- Add PostgreSQL addon:
heroku addons:create heroku-postgresql:hobby-dev
- Set environment variables:
heroku config:set NODE_ENV=production
heroku config:set ADMIN_API_KEY=your-admin-api-key
- Deploy:
git push heroku main
Docker
- Build the image:
docker build -t mcp-service .
- Run the container:
docker run -p 3000:3000 \
-e DATABASE_URL=postgresql://user:password@host.docker.internal:5432/mcp_service \
-e ADMIN_API_KEY=your-admin-api-key \
mcp-service
Development
Database Migrations
Create a new migration:
npx prisma migrate dev --name migration-name
Apply migrations:
npm run migrate
Testing
Run tests:
npm test
Run linter:
npm run lint
Architecture
The server acts as a multi-tenant proxy between MCP clients and Integration App's MCP server:
MCP Client -> Multi-tenant Server -> Integration App MCP Server
(proxy/router)
Each tenant gets:
- Isolated MCP client connection
- Separate Integration App credentials
- Independent tool discovery
- Audit logging
Security
- Rate limiting per tenant
- CORS protection
- Helmet security headers
- Request ID tracking
- Audit logging
- Token-based authentication
Monitoring
The /health endpoint provides:
- Server status
- Active tenant count
- Database connection status
- Memory usage
- Uptime
License
MIT
MCP Service Documentation
Overview
This service provides a multi-tenant API for managing integrations and tools via the Model Context Protocol (MCP). Each tenant is isolated and can access only their own tools and data.
1. Creating a Tenant
To create a new tenant, you must have an admin token. Use the following steps:
Step 1: Obtain an Admin Token
Send a POST request to /api/auth/token with your admin API key:
curl -X POST https://<your-app-url>/api/auth/token \
-H "Content-Type: application/json" \
-d '{"key": "<ADMIN_API_KEY>"}'
Response:
{"token": "<ADMIN_JWT_TOKEN>"}
Step 2: Create the Tenant
Send a POST request to /api/tenants with the admin token in the Authorization header:
curl -X POST https://<your-app-url>/api/tenants \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <ADMIN_JWT_TOKEN>" \
-d '{
"name": "<Tenant Name>",
"integrationKey": "<integration-key>",
"integrationAppToken": "<integration-app-token>"
}'
Response:
{
"tenantId": "tenant-xxxxxxx",
"apiKey": "<TENANT_API_KEY>",
...
}
2. Generating a Tenant Token
To interact with the API as a tenant, you need a tenant JWT token. Generate it using the tenant's API key:
curl -X POST https://<your-app-url>/api/auth/tenant-token \
-H "Content-Type: application/json" \
-H "x-api-key: <TENANT_API_KEY>"
Response:
{"token": "<TENANT_JWT_TOKEN>"}
3. Listing Tools for a Tenant
To list the tools available to a tenant, use the following endpoint with both the tenant API key and JWT token:
curl -X POST https://<your-app-url>/api/tenant/<tenantId>/tool \
-H "Content-Type: application/json" \
-H "x-api-key: <TENANT_API_KEY>" \
-H "Authorization: Bearer <TENANT_JWT_TOKEN>" \
-d '{"method": "listTools"}'
Response:
{
"tools": [
{ "name": "create-contact", ... },
...
]
}
4. Executing a Tool as a Tenant
To execute a tool (e.g., create a contact):
curl -X POST https://<your-app-url>/api/tenant/<tenantId>/tool \
-H "Content-Type: application/json" \
-H "x-api-key: <TENANT_API_KEY>" \
-H "Authorization: Bearer <TENANT_JWT_TOKEN>" \
-d '{
"method": "create-contact",
"params": {
"email": "test.user@example.com",
"fullName": "Test User"
}
}'
Response:
{
"content": [
{ "type": "text", "text": "{\"id\":\"120688589560\"}" }
],
"isError": false
}
5. Connecting an MCP Client Application
To connect an MCP client as a tenant:
- Use the tenant's
integrationKeyandintegrationAppToken(from the tenant creation response) to initialize the client. - Authenticate API requests with both the tenant API key and the tenant JWT token as shown above.
Example Client Initialization:
const client = new IntegrationAppClient({
token: '<integrationAppToken>'
});
const integration = await client.integration('<integrationKey>').get();
// ...
6. Troubleshooting
- Ensure you use the correct tenant
idand nottenantIdfor foreign key references in the database. - Both the tenant API key and JWT token are required for all tenant-specific API calls.
- If you see foreign key errors, check your database schema and migrations.
- For rate limiting issues, consider setting
app.set('trust proxy', 1)if running behind a proxy (see Express rate-limit docs).
7. Example .env File
DATABASE_URL=postgresql://user:password@host:port/dbname
ADMIN_API_KEY=your_admin_api_key
8. Useful Endpoints
POST /api/auth/token— Get admin tokenPOST /api/tenants— Create tenant (admin only)POST /api/auth/tenant-token— Get tenant JWT tokenPOST /api/tenant/:tenantId/tool— List or execute tools as a tenant
For more details, see the code in src/server.ts and src/api/auth.ts.