PulseMCP Server
by orliesaurus
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ErrorCode,
ListToolsRequestSchema,
McpError,
} from "@modelcontextprotocol/sdk/types.js";
import axios from "axios";
const API_BASE_URL = "https://api.pulsemcp.com/v0beta";
interface ListServersArgs {
query?: string;
integrations?: string[];
count_per_page?: number;
offset?: number;
}
interface ListServersResponse {
servers: Array<{
name: string;
url: string;
external_url?: string;
short_description?: string;
source_code_url?: string;
github_stars?: number;
package_registry?: string;
package_name?: string;
package_download_count?: number;
EXPERIMENTAL_ai_generated_description?: string;
integrations: Array<{
name: string;
slug: string;
url: string;
}>;
}>;
next?: string;
total_count: number;
}
interface ListIntegrationsResponse {
integrations: Array<{
name: string;
slug: string;
url: string;
}>;
}
const isListServersArgs = (args: any): args is ListServersArgs => {
if (typeof args !== "object" || args === null) return false;
if ("query" in args && typeof args.query !== "string") return false;
if ("integrations" in args && !Array.isArray(args.integrations)) return false;
if ("count_per_page" in args && typeof args.count_per_page !== "number")
return false;
if ("offset" in args && typeof args.offset !== "number") return false;
return true;
};
class PulseMcpServer {
private server: Server;
private axiosInstance;
constructor() {
this.server = new Server(
{
name: "pulse-mcp",
version: "0.1.0",
},
{
capabilities: {
tools: {},
},
}
);
this.axiosInstance = axios.create({
baseURL: API_BASE_URL,
});
this.setupToolHandlers();
// Error handling
this.server.onerror = (error) => console.error("[MCP Error]", error);
process.on("SIGINT", async () => {
await this.server.close();
process.exit(0);
});
}
private setupToolHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "list_servers",
description: "List MCP servers with optional filtering",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "Search term to filter servers",
},
integrations: {
type: "array",
items: {
type: "string",
},
description: "Filter by integration slugs",
},
count_per_page: {
type: "number",
description: "Number of results per page (maximum: 5000)",
maximum: 5000,
},
offset: {
type: "number",
description: "Number of results to skip for pagination",
},
},
},
},
{
name: "list_integrations",
description: "List all available integrations",
inputSchema: {
type: "object",
properties: {},
},
},
],
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case "list_servers": {
if (!isListServersArgs(request.params.arguments)) {
throw new McpError(
ErrorCode.InvalidParams,
"Invalid arguments for list_servers"
);
}
try {
const response = await this.axiosInstance.get<ListServersResponse>(
"/servers",
{
params: {
query: request.params.arguments.query,
"integrations[]": request.params.arguments.integrations,
count_per_page: request.params.arguments.count_per_page,
offset: request.params.arguments.offset,
},
}
);
return {
content: [
{
type: "text",
text: JSON.stringify(response.data, null, 2),
},
],
};
} catch (error) {
if (axios.isAxiosError(error)) {
return {
content: [
{
type: "text",
text: `API Error: ${
error.response?.data?.error?.message ?? error.message
}`,
},
],
isError: true,
};
}
throw error;
}
}
case "list_integrations": {
try {
const response =
await this.axiosInstance.get<ListIntegrationsResponse>(
"/integrations"
);
return {
content: [
{
type: "text",
text: JSON.stringify(response.data, null, 2),
},
],
};
} catch (error) {
if (axios.isAxiosError(error)) {
return {
content: [
{
type: "text",
text: `API Error: ${
error.response?.data?.error?.message ?? error.message
}`,
},
],
isError: true,
};
}
throw error;
}
}
default:
throw new McpError(
ErrorCode.MethodNotFound,
`Unknown tool: ${request.params.name}`
);
}
});
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error("Pulse MCP server running on stdio");
}
}
const server = new PulseMcpServer();
server.run().catch(console.error);