MCP Oracle Server
A production-grade Node.js MCP server for Oracle Database with HTTP transport, enabling SQL query execution, table listing, schema retrieval, and natural language to SQL conversion via MCP tools.
README
MCP Oracle Server (HTTP Transport)
A production-grade Node.js Model Context Protocol (MCP) server for Oracle Database with HTTP transport for Telnyx AI Agent compatibility. This server exposes MCP tools over HTTP/JSON-RPC, enabling integration with Telnyx and other HTTP-based MCP clients.
Features
- ✅ HTTP-based MCP Protocol: Full HTTP/JSON-RPC implementation (not STDIO)
- ✅ Telnyx Compatible: Designed for Telnyx AI Agent MCP integration
- ✅ Oracle Database Integration: Connection pooling with
oracledbdriver - ✅ API Key Authentication: Secure
/mcpendpoint with API key validation - ✅ MCP Tools:
runQuery: Execute SQL queries with bind parameterslistTables: List all tables in the databasegetSchema: Get detailed table schema informationnl2sql: Convert natural language to SQL using external service
- ✅ Web Server: Express server with
/health,/ready,/metrics,/webhook/telnyx - ✅ Production Ready: Logging, error handling, connection pooling, graceful shutdown
- ✅ Dockerized: Fully containerized with Docker Compose
Project Structure
mcp-oracle/
├── src/
│ ├── server.js # Main entrypoint: HTTP server + MCP setup
│ ├── oracle.js # Oracle connection pool management
│ ├── auth.js # API key authentication middleware
│ ├── web.js # Express app and routes
│ ├── mcpTransport.js # HTTP transport wrapper for MCP
│ ├── logger.js # Winston logger with file rotation
│ └── tools/
│ ├── runQuery.js # Execute SQL queries
│ ├── listTables.js # List database tables
│ ├── getSchema.js # Get table schema
│ └── nl2sql.js # Natural language to SQL
├── tests/
│ ├── integration.test.sh # Integration test script
│ └── lint-setup.md # Linting setup guide
├── package.json
├── Dockerfile
├── docker-compose.yml
├── .env.example
└── README.md
Prerequisites
- Node.js 20+ (for local development)
- Docker and Docker Compose (for containerized deployment)
- Oracle Database (accessible via network)
- Oracle Instant Client (handled automatically in Docker)
Quick Start
1. Setup Environment
# Copy environment file
cp .env.example .env
# Edit .env with your Oracle credentials
nano .env
Required environment variables:
ORACLE_USER: Oracle database usernameORACLE_PASS: Oracle database passwordORACLE_CONN: Connection string (format:host:port/service)MCP_API_KEY: API key for/mcpendpoint authentication (recommended)
2. Run with Docker Compose
# Build and start all services
docker-compose up --build
# Run in detached mode
docker-compose up -d
# View logs
docker-compose logs -f mcp-oracle
3. Run Locally (Development)
# Install dependencies
npm install
# Set environment variables (or use .env file)
export ORACLE_USER=your_user
export ORACLE_PASS=your_password
export ORACLE_CONN=host:1521/XEPDB1
export MCP_API_KEY=your_api_key
# Start the server
npm start
Configuration
Environment Variables
See .env.example for all available configuration options:
Required:
ORACLE_USER: Oracle database usernameORACLE_PASS: Oracle database passwordORACLE_CONN: Oracle connection string (format:host:port/service)
Recommended:
MCP_API_KEY: API key for/mcpendpoint (if not set, allows unauthenticated requests in dev mode)
Optional:
PORT: HTTP server port (default:3000)NL2SQL_URL: URL of NL2SQL service (default:http://nl2sql-service:8500/query)LOG_LEVEL: Logging level (default:info)CORS_ORIGIN: CORS origin (default:*)MAX_REQUEST_SIZE: Maximum request size (default:10mb)
Oracle Connection Pool
Configure pool settings via environment variables:
ORACLE_POOL_MIN: Minimum pool size (default:2)ORACLE_POOL_MAX: Maximum pool size (default:10)ORACLE_POOL_INCREMENT: Pool increment (default:1)ORACLE_POOL_TIMEOUT: Pool timeout in seconds (default:60)
API Endpoints
MCP Endpoint
POST /mcp
Main MCP protocol endpoint. Accepts JSON-RPC 2.0 requests.
Authentication:
- Header:
x-mcp-api-key: <your-api-key> - Or:
Authorization: Bearer <your-api-key>
Request Format:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
Response Format:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [...]
}
}
Health & Monitoring
- GET
/health: Basic health check - GET
/ready: Readiness check (verifies DB pool) - GET
/metrics: Prometheus-formatted metrics - POST
/webhook/telnyx: Telnyx webhook handler
MCP Tools
1. runQuery
Execute a SQL query against the Oracle database.
Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "runQuery",
"arguments": {
"sql": "SELECT * FROM employees WHERE department_id = :dept_id",
"binds": { "dept_id": 10 },
"maxRows": 100
}
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{
"type": "text",
"text": "{\"success\":true,\"data\":{\"rows\":[...],\"rowCount\":5}}"
}]
}
}
2. listTables
List all tables in the database.
Request:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "listTables",
"arguments": {
"schema": "HR"
}
}
}
3. getSchema
Get detailed schema information for a table.
Request:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "getSchema",
"arguments": {
"tableName": "employees",
"schema": "HR"
}
}
}
4. nl2sql
Convert natural language query to SQL.
Request:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "nl2sql",
"arguments": {
"query": "Show me all customers from New York"
}
}
}
Telnyx Configuration
Setting up Telnyx AI Agent
-
Configure MCP URL:
- In Telnyx AI Agent settings, set the MCP URL to:
https://<your-host>:<port>/mcp - Example:
https://mcp.example.com:3000/mcp
- In Telnyx AI Agent settings, set the MCP URL to:
-
Configure API Key:
- In Telnyx AI Agent MCP configuration, set the API key to match your
MCP_API_KEYenvironment variable - The agent should send requests with header:
x-mcp-api-key: <your-api-key>
- In Telnyx AI Agent MCP configuration, set the API key to match your
-
Example Telnyx Configuration JSON:
{
"mcp": {
"url": "https://your-server.com:3000/mcp",
"apiKey": "your-secure-api-key-here",
"transport": "http"
}
}
Testing Telnyx Integration
# Test MCP endpoint with API key
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "x-mcp-api-key: your-api-key" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
Example curl Commands
List Available Tools
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "x-mcp-api-key: changeme" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
Execute a Query
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "x-mcp-api-key: changeme" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "runQuery",
"arguments": {
"sql": "SELECT table_name FROM user_tables WHERE ROWNUM <= 5"
}
}
}'
Health Check
curl http://localhost:3000/health
Telnyx Webhook
curl -X POST http://localhost:3000/webhook/telnyx \
-H "Content-Type: application/json" \
-d '{
"event_type": "message.received",
"data": {
"from": "+1234567890",
"to": "+0987654321",
"text": "Hello"
}
}'
Running Tests
Integration Tests
The project includes a bash integration test script:
# Make script executable
chmod +x tests/integration.test.sh
# Run tests (defaults to http://localhost:3000)
./tests/integration.test.sh
# Run with custom URL and API key
BASE_URL=http://your-server:3000 MCP_API_KEY=your-key ./tests/integration.test.sh
The test script validates:
- Health endpoint
- Readiness endpoint
- Metrics endpoint
- MCP authentication
- MCP tools/list
- MCP tools/call (listTables)
Docker Services
mcp-oracle
The main MCP server container:
- Runs HTTP server on port 3000
- Exposes MCP endpoint at
/mcp - Mounts logs directory
- Connects to Oracle database
nl2sql-service
FastAPI service for natural language to SQL conversion:
- Placeholder implementation included
- Exposes API on port 8500
- Replace with your actual NL2SQL service by updating the
imageindocker-compose.yml
oracle-db (Optional)
Local Oracle database for testing:
- Uses
gvenzl/oracle-freeimage - Exposes port 1521
- Data persisted in Docker volume
- Commented out by default - uncomment in
docker-compose.ymlif needed
Logging
Logs are written to:
- Console: Structured JSON logs with timestamps
- Files: Rotating log files in
logs/directory- Format:
mcp-oracle-YYYY-MM-DD.log - Max size: 20MB per file
- Retention: 14 days
- Format:
Security
API Key Authentication
The /mcp endpoint requires API key authentication:
- Set
MCP_API_KEYenvironment variable - Send requests with header:
x-mcp-api-key: <key>orAuthorization: Bearer <key> - If
MCP_API_KEYis not set, requests are allowed but a warning is logged (development mode)
TLS/HTTPS
For production, enable TLS:
-
Option 1: Application-level TLS (not recommended)
- Set
TLS_CERTandTLS_KEYenvironment variables - Update server code to use HTTPS
- Set
-
Option 2: Reverse Proxy (recommended)
- Use nginx, traefik, or similar
- Handle TLS termination at the proxy
- Forward requests to the application on port 3000
Request Limits
- Maximum request size: 10MB (configurable via
MAX_REQUEST_SIZE) - Request timeout: 30 seconds (configurable via
MCP_REQUEST_TIMEOUT) - CORS: Configurable via
CORS_ORIGIN
Troubleshooting
Oracle Connection Issues
- Check connection string format:
host:port/service - Verify network connectivity:
telnet host 1521 - Check Oracle Instant Client: Ensure it's installed in Docker
- Review logs: Check
logs/directory for detailed error messages
MCP Endpoint Issues
- Authentication errors: Verify
MCP_API_KEYmatches in request header - Timeout errors: Increase
MCP_REQUEST_TIMEOUTif queries are slow - Connection refused: Ensure service is running and port is exposed
NL2SQL Service Issues
- Verify service is running:
curl http://nl2sql-service:8500/health - Check network: Ensure services are on the same Docker network
- Review timeout: Default is 30 seconds
Design Notes / Choices
This section documents key design decisions and tradeoffs made during implementation:
1. HTTP Transport Implementation
Decision: Implemented custom HTTP transport wrapper instead of using SDK's STDIO transport.
Rationale:
- The MCP SDK (
@modelcontextprotocol/sdk) primarily supports STDIO transport - Telnyx and other HTTP-based clients require HTTP/JSON-RPC endpoints
- Created a wrapper that routes JSON-RPC requests to MCP Server's internal request handlers
- This allows the server to work with HTTP clients while maintaining compatibility with MCP protocol
Tradeoff:
- Requires manual routing of requests to handlers
- May need updates if SDK adds native HTTP transport in the future
- Benefits: Works with Telnyx and any HTTP client
2. API Key Authentication Pattern
Decision: Simple API key authentication via header, with development mode fallback.
Rationale:
- Telnyx requires API key-based authentication
- Supports both
x-mcp-api-keyheader andAuthorization: Bearerfor flexibility - If
MCP_API_KEYis not set, allows requests but logs warning (useful for local development) - Simple to implement and understand
Tradeoff:
- Not as secure as JWT with expiration, but sufficient for API-to-API communication
- Can be enhanced with JWT support in the future (stub provided in
auth.js)
3. Request Timeout Handling
Decision: 30-second default timeout with configurable value.
Rationale:
- Prevents hanging requests from consuming resources
- SQL queries can be slow, but 30 seconds is reasonable for most cases
- Configurable via
MCP_REQUEST_TIMEOUTfor different use cases - Returns proper JSON-RPC error response on timeout
Tradeoff:
- May timeout on very large/complex queries
- Users can increase timeout or optimize queries
4. Streaming Support
Decision: Implemented request-response pattern without streaming.
Rationale:
- MCP SDK's streaming is designed for STDIO
- HTTP request-response is simpler and more compatible
- Large result sets can be paginated using
maxRowsparameter - Can be enhanced with Server-Sent Events (SSE) or WebSockets if needed
Tradeoff:
- Large result sets must be paginated
- No real-time streaming of results
- Benefits: Simpler implementation, better compatibility
5. Error Handling and Response Format
Decision: All errors return JSON-RPC 2.0 compliant responses with proper error codes.
Rationale:
- Maintains JSON-RPC 2.0 protocol compliance
- Provides structured error information
- Tool errors are wrapped in MCP content format
- Database errors are caught and returned as JSON
Tradeoff:
- Error information is nested (JSON-RPC error → MCP content → tool error)
- Benefits: Protocol compliance, structured errors, easier debugging
License
MIT
Contributing
Contributions welcome! Please ensure:
- Code follows existing style
- All tools return consistent JSON responses
- Error handling is comprehensive
- Logging is appropriate
- Tests are updated
Support
For issues and questions:
- Check logs in
logs/directory - Review Docker Compose logs:
docker-compose logs - Verify environment variables
- Test Oracle connectivity independently
- Run integration tests:
./tests/integration.test.sh
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.