@access-mcp/shared
Version:
Shared utilities for ACCESS-CI MCP servers
108 lines (107 loc) • 3.87 kB
JavaScript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
import axios from "axios";
export class BaseAccessServer {
serverName;
version;
baseURL;
server;
transport;
_httpClient;
constructor(serverName, version, baseURL = "https://support.access-ci.org/api") {
this.serverName = serverName;
this.version = version;
this.baseURL = baseURL;
this.server = new Server({
name: serverName,
version: version,
}, {
capabilities: {
resources: {},
tools: {},
},
});
this.transport = new StdioServerTransport();
this.setupHandlers();
}
get httpClient() {
if (!this._httpClient) {
const headers = {
"User-Agent": `${this.serverName}/${this.version}`,
};
// Add authentication if API key is provided
const apiKey = process.env.ACCESS_CI_API_KEY;
if (apiKey) {
headers["Authorization"] = `Bearer ${apiKey}`;
}
this._httpClient = axios.create({
baseURL: this.baseURL,
timeout: 5000,
headers,
validateStatus: () => true, // Don't throw on HTTP errors
});
}
return this._httpClient;
}
setupHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
try {
return { tools: this.getTools() };
}
catch (error) {
// Silent error handling for MCP compatibility
return { tools: [] };
}
});
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
try {
return { resources: this.getResources() };
}
catch (error) {
// Silent error handling for MCP compatibility
return { resources: [] };
}
});
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
return await this.handleToolCall(request);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error("Error handling tool call:", errorMessage);
return {
content: [
{
type: "text",
text: `Error: ${errorMessage}`,
},
],
};
}
});
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
try {
return await this.handleResourceRead(request);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error("Error reading resource:", errorMessage);
return {
contents: [
{
uri: request.params.uri,
mimeType: "text/plain",
text: `Error: ${errorMessage}`,
},
],
};
}
});
}
async start() {
await this.server.connect(this.transport);
// MCP servers should not output anything to stderr/stdout when running
// as it interferes with JSON-RPC communication
}
}