- API Client: Housecall Pro API with auth, pagination, error handling - 47 Tools across 10 categories: - jobs-tools (10): list, get, create, update, complete, cancel, line items, schedule, reschedule - customers-tools (7): list, get, create, update, delete, search, addresses - estimates-tools (8): list, get, create, update, send, approve, decline, convert to job - invoices-tools (6): list, get, create, send, mark paid, list payments - employees-tools (6): list, get, create, update, schedule, time entries - dispatch-tools (3): dispatch board, assign employee, availability - tags-tools (5): list, create, delete, add to job/customer - notifications-tools (3): list, send, mark read - reviews-tools (3): list, get, request review - reporting-tools (3): revenue, job completion, employee performance - 16 React MCP Apps for rich UI: - job-dashboard, job-detail, job-grid - customer-detail, customer-grid - estimate-builder, estimate-grid - invoice-dashboard, invoice-detail - dispatch-board - employee-schedule, employee-performance - review-dashboard, revenue-dashboard - tag-manager, notification-center - Complete types, comprehensive README, full package.json
137 lines
3.5 KiB
TypeScript
137 lines
3.5 KiB
TypeScript
/**
|
|
* Housecall Pro MCP Server
|
|
*/
|
|
|
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
import {
|
|
CallToolRequestSchema,
|
|
ListToolsRequestSchema,
|
|
ListResourcesRequestSchema,
|
|
ReadResourceRequestSchema,
|
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
import { HousecallProClient } from './clients/housecall-pro.js';
|
|
import { registerAllTools } from './tools/index.js';
|
|
|
|
export class HousecallProServer {
|
|
private server: Server;
|
|
private client: HousecallProClient;
|
|
private tools: Record<string, any>;
|
|
|
|
constructor() {
|
|
this.server = new Server(
|
|
{
|
|
name: 'housecall-pro',
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
capabilities: {
|
|
tools: {},
|
|
resources: {},
|
|
},
|
|
}
|
|
);
|
|
|
|
// Initialize client (API key will be set from env var)
|
|
const apiKey = process.env.HOUSECALL_PRO_API_KEY;
|
|
if (!apiKey) {
|
|
throw new Error('HOUSECALL_PRO_API_KEY environment variable is required');
|
|
}
|
|
|
|
this.client = new HousecallProClient({
|
|
apiKey,
|
|
baseUrl: process.env.HOUSECALL_PRO_BASE_URL,
|
|
});
|
|
|
|
// Register all tools
|
|
this.tools = registerAllTools(this.client);
|
|
|
|
this.setupHandlers();
|
|
}
|
|
|
|
private setupHandlers() {
|
|
// List available tools
|
|
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
return {
|
|
tools: Object.entries(this.tools).map(([name, tool]) => ({
|
|
name,
|
|
description: tool.description,
|
|
inputSchema: tool.parameters,
|
|
})),
|
|
};
|
|
});
|
|
|
|
// Handle tool execution
|
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
const { name, arguments: args } = request.params;
|
|
|
|
const tool = this.tools[name];
|
|
if (!tool) {
|
|
throw new Error(`Unknown tool: ${name}`);
|
|
}
|
|
|
|
try {
|
|
const result = await tool.handler(args || {});
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
} catch (error: any) {
|
|
// Handle API errors
|
|
if (error.error === 'APIError') {
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify({
|
|
error: error.error,
|
|
message: error.message,
|
|
status: error.status,
|
|
}, null, 2),
|
|
},
|
|
],
|
|
isError: true,
|
|
};
|
|
}
|
|
|
|
// Handle other errors
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: JSON.stringify({
|
|
error: 'ExecutionError',
|
|
message: error.message || 'Tool execution failed',
|
|
details: error,
|
|
}, null, 2),
|
|
},
|
|
],
|
|
isError: true,
|
|
};
|
|
}
|
|
});
|
|
|
|
// List resources (empty for now, but could include templates, reports, etc.)
|
|
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
return {
|
|
resources: [],
|
|
};
|
|
});
|
|
|
|
// Read resource (empty for now)
|
|
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
throw new Error(`Resource not found: ${request.params.uri}`);
|
|
});
|
|
}
|
|
|
|
async run() {
|
|
const transport = new StdioServerTransport();
|
|
await this.server.connect(transport);
|
|
console.error('Housecall Pro MCP server running on stdio');
|
|
}
|
|
}
|