import 'dotenv/config'
import { Server } from '@modelcontextprotocol/sdk/server/index'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio'
import {
CallToolRequestSchema,
ListToolsRequestSchema,
Tool,
} from '@modelcontextprotocol/sdk/types'
import { createSolvaPay, PaywallError } from '@solvapay/server'
// Initialize SolvaPay
const solvaPay = createSolvaPay({
apiKey: process.env.SOLVAPAY_SECRET_KEY,
})
// Create payable handler
const payable = solvaPay.payable({
product: 'prd_myapi',
plan: 'pln_premium',
})
// Define tools
const tools: Tool[] = [
{
name: 'create_task',
description: 'Create a new task (requires purchase)',
inputSchema: {
type: 'object',
properties: {
title: {
type: 'string',
description: 'Title of the task',
},
description: {
type: 'string',
description: 'Optional description of the task',
},
auth: {
type: 'object',
description: 'Authentication information',
properties: {
customer_ref: { type: 'string' },
},
required: ['customer_ref'],
},
},
required: ['title', 'auth'],
},
},
{
name: 'get_task',
description: 'Get a task by ID (requires purchase)',
inputSchema: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'ID of the task to retrieve',
},
auth: {
type: 'object',
description: 'Authentication information',
properties: {
customer_ref: { type: 'string' },
},
required: ['customer_ref'],
},
},
required: ['id', 'auth'],
},
},
{
name: 'list_tasks',
description: 'List all tasks (requires purchase)',
inputSchema: {
type: 'object',
properties: {
limit: {
type: 'number',
description: 'Maximum number of tasks to return (default: 10)',
},
offset: {
type: 'number',
description: 'Number of tasks to skip (default: 0)',
},
auth: {
type: 'object',
description: 'Authentication information',
properties: {
customer_ref: { type: 'string' },
},
required: ['customer_ref'],
},
},
},
},
]
// Business logic functions
async function createTask(args: {
title: string
description?: string
auth: { customer_ref: string }
}) {
const { title, description } = args
const task = {
id: Date.now().toString(),
title,
description,
createdAt: new Date().toISOString(),
}
return {
success: true,
message: 'Task created successfully',
task,
}
}
async function getTask(args: { id: string; auth: { customer_ref: string } }) {
const { id } = args
// Simulate fetching from database
const task = {
id,
title: 'Sample Task',
description: 'Task description',
createdAt: new Date().toISOString(),
}
return {
success: true,
task,
}
}
async function listTasks(args: {
limit?: number
offset?: number
auth: { customer_ref: string }
}) {
const { limit = 10, offset = 0 } = args
// Simulate fetching from database
const tasks = Array.from({ length: limit }, (_, i) => ({
id: (offset + i + 1).toString(),
title: `Task ${offset + i + 1}`,
description: `Description for task ${offset + i + 1}`,
createdAt: new Date().toISOString(),
}))
return {
success: true,
tasks,
total: tasks.length,
limit,
offset,
}
}
// Create MCP server
const server = new Server(
{
name: 'solvapay-protected-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
},
)
// Handle tool listing
server.setRequestHandler(ListToolsRequestSchema, async () => {
return { tools }
})
// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async request => {
const { name, arguments: args } = request.params
try {
switch (name) {
case 'create_task': {
const handler = payable.mcp(createTask)
const result = await handler(args)
return {
content: [
{
type: 'text',
text: JSON.stringify(result),
},
],
}
}
case 'get_task': {
const handler = payable.mcp(getTask)
const result = await handler(args)
return {
content: [
{
type: 'text',
text: JSON.stringify(result),
},
],
}
}
case 'list_tasks': {
const handler = payable.mcp(listTasks)
const result = await handler(args)
return {
content: [
{
type: 'text',
text: JSON.stringify(result),
},
],
}
}
default:
throw new Error(`Unknown tool: ${name}`)
}
} catch (error) {
if (error instanceof PaywallError) {
// Return paywall error in MCP format
return {
content: [
{
type: 'text',
text: JSON.stringify({
error: 'Payment required',
message: error.message,
checkoutUrl: error.structuredContent.checkoutUrl,
product: error.structuredContent.product,
}),
},
],
isError: true,
}
}
// Re-throw other errors
throw error
}
})
// Start the server
async function main() {
const transport = new StdioServerTransport()
await server.connect(transport)
console.error('SolvaPay Protected MCP Server started')
console.error('Available tools: create_task, get_task, list_tasks')
console.error('Paywall protection enabled')
}
main().catch(error => {
console.error('Failed to start MCP server:', error)
process.exit(1)
})