Skip to main content

Custom MCP Servers

ProActions Hub allows you to register and run custom MCP (Model Context Protocol) servers. This enables you to extend the Hub's capabilities with specialized tools, data sources, or workflows written in Node.js, Python, or other languages.

Prerequisites

To run custom scripts, you must make them available to the ProActions Hub container. The recommended approach is to mount a host directory containing your scripts into the container at runtime.

For example, to mount a local directory ./local/scripts to /usr/src/app/custom-scripts in the container:

-v ./local/scripts:/usr/src/app/custom-scripts:ro

Node.js Example

You can run Node.js-based MCP servers using the node executable or npx.

Creating a Simple Server

Here is an example of a simple weather-server.js using the @modelcontextprotocol/sdk.

File: weather-server.js

#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';

const server = new Server(
{
name: 'weather-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
},
);

server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'get_weather',
description: 'Get current weather for a location',
inputSchema: {
type: 'object',
properties: {
location: { type: 'string' },
},
required: ['location'],
},
},
],
};
});

server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === 'get_weather') {
const { location } = request.params.arguments;
return {
content: [{ type: 'text', text: `Sunny in ${location}` }],
};
}
throw new Error('Tool not found');
});

async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}

main().catch(console.error);

Configuration

Add the server to your config.yaml.

Using node for local scripts:

mcp:
servers:
- name: weather
command: node
args:
- /usr/src/app/custom-scripts/weather-server.js

Using npx for published packages:

mcp:
servers:
- name: sqlite
command: npx
args:
- -y
- '@modelcontextprotocol/server-sqlite'
- '--file'
- '/usr/src/app/custom-scripts/my-db.sqlite'

Python Example

For Python servers, we recommend using uv to manage dependencies and execution. This allows you to define dependencies directly in the script.

Creating a Simple Server

Here is an example of an echo.py server using fastmcp.

File: echo.py

# /// script
# dependencies = [
# "mcp[cli]"
# ]
# ///

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Echo")

@mcp.tool()
def echo(message: str) -> str:
"""Echo back the message"""
return f"Echo: {message}"

if __name__ == "__main__":
mcp.run()

Configuration

Configure the server to use uv in config.yaml:

mcp:
servers:
- name: echo
command: uv
args:
- run
- /usr/src/app/custom-scripts/echo.py

Deployment

To deploy with custom servers, run the container with the volume mount:

Docker:

docker run -d \
-p 3000:3000 \
-v ./config/config.yaml:/usr/src/app/dist/config.yaml \
-v ./my-local-scripts:/usr/src/app/custom-scripts:ro \
artifactory.eidosmedia.sh/docker-releases/proactions/proactions-hub:latest

Podman:

podman run -d \
-p 3000:3000 \
-v ./config/config.yaml:/usr/src/app/dist/config.yaml \
-v ./my-local-scripts:/usr/src/app/custom-scripts:ro \
artifactory.eidosmedia.sh/docker-releases/proactions/proactions-hub:latest