xero-mcp
Version:
A Model Context Protocol server allows Clients to interact with Xero
88 lines (87 loc) • 3.97 kB
JavaScript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { CallToolRequestSchema, ErrorCode, ListResourceTemplatesRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { McpToolsFactory } from "./Tools/McpToolsFactory.js";
import { XeroAuthMiddleware } from "./Middlewares/XeroAuthMiddleware.js";
import { AuditMiddleware } from "./Middlewares/AuditMiddleware.js";
import { ErrorMiddleware } from "./Middlewares/ErrorMiddleware.js";
import { XeroAccountingApiSchema } from "./Resources/xero_accounting.js";
const ACCOUNTING_OPENAPI_RESOURCE_URI = "xero-mcp://accounting/openapi.json";
export class XeroMcpServer {
mcpServer;
constructor() {
this.mcpServer = new Server({
name: "Xero-MCP-Server",
version: "1.0.0",
}, {
capabilities: {
tools: {},
resources: {},
},
});
}
async start() {
this.configureTools();
this.configureResources();
const transport = new StdioServerTransport();
await this.mcpServer.connect(transport);
console.error("Xero MCP server running on stdio");
}
configureTools() {
this.mcpServer.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: McpToolsFactory.getAllTools().map((tool) => tool.requestSchema),
};
});
this.mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
return await ErrorMiddleware(request, async (request) => {
return await AuditMiddleware(request, async (request) => {
return await XeroAuthMiddleware(request, async (request) => {
const { name } = request.params;
const mcpTool = McpToolsFactory.findToolByName(name);
if (mcpTool) {
return await mcpTool.requestHandler(request);
}
else {
return {
content: [
{
type: "text",
text: `Error: Tool not found: ${name}`,
},
],
};
}
});
});
});
});
}
configureResources() {
this.mcpServer.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [
{
uri: ACCOUNTING_OPENAPI_RESOURCE_URI,
name: "Xero Accounting API (OpenAPI)",
description: "OpenAPI 3.0 document for the Xero Accounting API (paths, operations, schemas). Use when you need request/response shapes or endpoint details beyond the bundled tools.",
mimeType: "application/json",
},
],
}));
this.mcpServer.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({ resourceTemplates: [] }));
this.mcpServer.setRequestHandler(ReadResourceRequestSchema, async (request) => {
if (request.params.uri !== ACCOUNTING_OPENAPI_RESOURCE_URI) {
throw new McpError(ErrorCode.InvalidParams, `Resource not found: ${request.params.uri}`);
}
return {
contents: [
{
uri: ACCOUNTING_OPENAPI_RESOURCE_URI,
mimeType: "application/json",
text: JSON.stringify(XeroAccountingApiSchema),
},
],
};
});
}
}