home / mcp / paprika mcp server
Provides a SQL database interface for Claude to execute queries and explore schemas in real time.
Configuration
View docs{
"mcpServers": {
"jonaheaton-paprika_mcp_server": {
"command": "paprika-mcp-server",
"args": [],
"env": {
"DATABASE_PATH": "./default.db"
}
}
}
}You can connect Claude to your own SQL database through an MCP server extension, allowing real-time querying, schema exploration, and data analysis during conversations. This enables seamless data access and interactive data-driven prompts without leaving your workspace.
Set up the MCP server and configure your Claude client to connect to it. Once active, you can ask Claude to list available tables, inspect table schemas, run safe SQL queries, and view results directly in the chat. Use the following practical workflows to get started: create a connection to your SQLite database, explore the database schema, execute read-only queries, and review results in a readable format.
Prerequisites: you need Node.js installed on your machine. You should also have a database driver ready for your chosen database (SQLite is used in the example). Follow these steps to install and run the MCP server.
cd /Users/jonaheaton/Documents/paprika_mcp_server
npm init -ynpm install @modelcontextprotocol/sdk
npm install better-sqlite3 # For SQLite
# OR for other databases:
# npm install mysql2 # For MySQL
# npm install pg # For PostgreSQLCreate a file named server.js that implements the MCP server and its SQL tools. The server exposes tools to query SQL, describe tables, and get table schemas.
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import Database from 'better-sqlite3'; // For SQLite
class SQLMCPServer {
constructor() {
this.server = new Server(
{
name: 'paprika-sql-server',
version: '0.1.0',
},
{
capabilities: {
tools: {},
},
}
);
// Initialize your database connection
this.db = new Database('path/to/your/database.db'); // Update with your database path
this.setupToolHandlers();
}
setupToolHandlers() {
// List available tools
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'query_sql',
description: 'Execute a SQL query on the database',
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'SQL query to execute',
},
},
required: ['query'],
},
},
{
name: 'describe_tables',
description: 'Get schema information for all tables',
inputSchema: {
type: 'object',
properties: {},
},
},
{
name: 'get_table_schema',
description: 'Get detailed schema for a specific table',
inputSchema: {
type: 'object',
properties: {
table_name: {
type: 'string',
description: 'Name of the table to describe',
},
},
required: ['table_name'],
},
},
],
};
});
// Handle tool calls
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'query_sql':
return await this.executeQuery(args.query);
case 'describe_tables':
return await this.describeTables();
case 'get_table_schema':
return await this.getTableSchema(args.table_name);
default:
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
return {
content: [
{
type: 'text',
text: `Error: ${error.message}`,
},
],
};
}
});
}
async executeQuery(query) {
try {
// Prevent destructive operations if needed
const lowerQuery = query.toLowerCase().trim();
if (lowerQuery.startsWith('drop') || lowerQuery.startsWith('delete') || lowerQuery.startsWith('truncate')) {
throw new Error('Destructive operations are not allowed');
}
const result = this.db.prepare(query).all();
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
} catch (error) {
throw new Error(`SQL execution failed: ${error.message}`);
}
}
async describeTables() {
try {
const tables = this.db.prepare(`
SELECT name FROM sqlite_master
WHERE type='table' AND name NOT LIKE 'sqlite_%'
`).all();
return {
content: [
{
type: 'text',
text: `Available tables: ${tables.map(t => t.name).join(', ')}`,
},
],
};
} catch (error) {
throw new Error(`Failed to describe tables: ${error.message}`);
}
}
async getTableSchema(tableName) {
try {
const schema = this.db.prepare(`PRAGMA table_info(${tableName})`).all();
return {
content: [
{
type: 'text',
text: JSON.stringify(schema, null, 2),
},
],
};
} catch (error) {
throw new Error(`Failed to get schema for ${tableName}: ${error.message}`);
}
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
}
}
const server = new SQLMCPServer();
server.run().catch(console.error);Update your package manifest to define the server entry point and a startup script.
{
"name": "paprika-mcp-server",
"version": "1.0.0",
"type": "module",
"main": "server.js",
"bin": {
"paprika-mcp-server": "./server.js"
},
"scripts": {
"start": "node server.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.1.0",
"better-sqlite3": "^8.7.0"
}
}Start the MCP server locally and connect Claude to it via the client configuration.
npm install
node server.jsCreate or edit the Claude desktop configuration to point at your local MCP server so Claude can discover and use the tools.
{
"mcpServers": {
"paprika-database": {
"command": "paprika-mcp-server",
"args": []
}
}
}Execute a SQL query on the database
Get schema information for all tables
Get detailed schema for a specific table