MCP Server for OpenProject with Netlify Express
View the deployed MCP function endpoint: https://gilded-fudge-69ca2e.netlify.app/mcp (Note: This endpoint is intended for MCP clients, not direct browser access).
About this MCP Server
This project provides a Model Context Protocol (MCP) server, built with Express and deployed as a Netlify Function. It allows AI agents (like Langflow agents, Claude, Cursor, etc.) to interact with a self-hosted OpenProject instance via defined tools.
This example demonstrates:
- Setting up an MCP server using
@modelcontextprotocol/sdk
. - Integrating with an external API (OpenProject).
- Deploying the MCP server serverlessly using Netlify Functions.
- Handling environment variables securely in Netlify.
- Providing a bridge for remote SSE clients (like cloud-hosted Langflow) to connect to the stateless Netlify function via
mcp-proxy
andngrok
. - Model Context Protocol (MCP)
- Docs: Netlify Functions
Implemented OpenProject Tools
The server exposes the following tools for interacting with OpenProject:
- Projects:
openproject-create-project
: Creates a new project.openproject-get-project
: Retrieves a specific project by ID.openproject-list-projects
: Lists all projects (supports pagination).openproject-update-project
: Updates an existing project's details.openproject-delete-project
: Deletes a project.
- Tasks (Work Packages):
openproject-create-task
: Creates a new task within a project.openproject-get-task
: Retrieves a specific task by ID.openproject-list-tasks
: Lists tasks, optionally filtered by project ID (supports pagination).openproject-update-task
: Updates an existing task (requireslockVersion
).openproject-delete-task
: Deletes a task.
Prerequisites
- Node.js (v18 or later recommended)
- npm
- Netlify CLI (
npm install -g netlify-cli
) - Python 3.10 or later (required for the
mcp-proxy
tool used for SSE bridging) pip
(Python package installer)- An OpenProject instance accessible via URL.
- An OpenProject API Key.
- (Optional)
ngrok
account and CLI for testing remote SSE clients.
Setup Instructions
- Clone the repository:
- Install Node.js dependencies:
- Install Python
mcp-proxy
: (Ensure you have Python 3.10+ active)
Local Development
- Create Environment File:
- Create a file named
.env
in the project root. - Add your OpenProject details:
- (Important): Ensure
.env
is listed in your.gitignore
file to avoid committing secrets.
- Create a file named
- Run Netlify Dev Server:
- This command starts a local server, loads variables from
.env
, and makes your function available.
- Your local MCP endpoint will typically be available at
http://localhost:8888/mcp
.
- This command starts a local server, loads variables from
- Test Locally with MCP Inspector:
- In a separate terminal, run the MCP Inspector, pointing it to your local server via
mcp-remote
:
- Open the Inspector URL (usually
http://localhost:6274
) in your browser. - Connect and use the "Tools" tab to test the OpenProject CRUD operations.
- In a separate terminal, run the MCP Inspector, pointing it to your local server via
Deployment to Netlify
- Set Environment Variables in Netlify UI:
- Go to your site's dashboard on Netlify (
https://app.netlify.com/sites/gilded-fudge-69ca2e/configuration/env
). - Under "Environment variables", add the following variables (ensure they are available to "Functions"):
OPENPROJECT_API_KEY
: Your OpenProject API key.OPENPROJECT_URL
: Your OpenProject instance URL (e.g.,https://project.bautistavirtualrockstars.com
).OPENPROJECT_API_VERSION
:v3
- (Security): The code in
netlify/mcp-server/index.ts
reads these fromprocess.env
. The hardcoded values should be removed (already done in our steps).
- Go to your site's dashboard on Netlify (
- Deploy via Git:
- Commit your code changes:
- Push to the branch Netlify is configured to deploy (e.g.,
main
):
- Netlify will automatically build and deploy the new version. Monitor progress in the "Deploys" section of your Netlify dashboard.
Testing Deployed Version
- Using MCP Inspector:
- Run the inspector, pointing
mcp-remote
to your live Netlify function URL:
- Open the Inspector URL and test the tools. Check Netlify function logs if errors occur.
- Run the inspector, pointing
- Connecting Remote SSE Clients (e.g., Cloud-Hosted Langflow):
- Since the Netlify function is stateless (doesn't handle SSE connections directly via GET), and remote clients like Langflow often prefer SSE, you need a bridge. We use the Python
mcp-proxy
tool combined with the JSmcp-remote
tool, andngrok
for a public tunnel. - Step A: Start the Proxy Bridge Locally:
- Run this command in a terminal on your local machine (ensure Python 3.10+ is active and
mcp-proxy
is installed):
- Keep this terminal running. Check its output to ensure it started listening and spawned the
npx
command.
- Run this command in a terminal on your local machine (ensure Python 3.10+ is active and
- Step B: Create a Public Tunnel with
ngrok
:- In a separate terminal, run
ngrok
to expose the local portmcp-proxy
is listening on:
ngrok
will display a public "Forwarding" URL (e.g.,https://<random-string>.ngrok-free.app
). Copy this HTTPS URL.
- In a separate terminal, run
- Step C: Configure Langflow:
- In your Langflow MCP Connection component (running on
https://lang.singforhope.org/
):- Mode:
SSE
- MCP SSE URL: Paste the full
ngrok
public URL including the/sse
path required bymcp-proxy
(e.g.,https://<random-string>.ngrok-free.app/sse
).
- Mode:
- Langflow should now be able to connect and use the tools via the
ngrok
->mcp-proxy
->mcp-remote
-> Netlify chain.
- In your Langflow MCP Connection component (running on
- (Note): This
ngrok
setup is for testing/development. For a permanent solution, deploy themcp-proxy
bridge to a persistent public server.
- Since the Netlify function is stateless (doesn't handle SSE connections directly via GET), and remote clients like Langflow often prefer SSE, you need a bridge. We use the Python
Netlify Function Configuration (netlify.toml
)
Ensure your netlify.toml
correctly redirects requests to the /mcp
path to your Express function handler:
(Adjust redirects as needed based on your Express routing)