Remote MCP Server
Create a remote MCP server for an API with authentication and additional security policies.
Remote MCP Server#
This example creates a remote Model Context Protocol (MCP) server for a Todo List API (powered by JSON Placeholder).
It implements:
- A
/mcp
path that MCP compatible clients can use to work with the server - MCP compatible tools for creating, updating, and deleting todos
- API security policies on all inbound routes
- Additional outbound safety measures using the Prompt Injection Detection and Secret Masking policies
Prerequisites#
API Key Authentication#
All routes, including the MCP server route, are protected using API Key authentication. To enable this in your Zuplo project, follow the steps in the API Key Auth documentation.
OpenAI API Key#
By default the Prompt Injection Detection policy uses the OpenAI API and their gpt-3.5-turbo
model. In order to use this you will need to set up an OPENAI_API_KEY
environment variable in your project settings.
See the Environment Variables documentation for more information on how to do this.
If working locally you can update the env.example
file with your OPENAI_API_KEY
.
Note: If you don't want to use OpenAI for the Prompt Injection Detection policy, see the Working Locally with Ollama section below.
Local Development#
To work with this project locally you can create a new Zuplo project using this template with our CLI:
npx create-zuplo-api@latest my-api --example remote-mcp-server
Then run:
npm install
In order to work with the API key authentication service locally, you'll need to link your Zuplo account by running:
npx zuplo link
Then you can start running the project with:
npm run dev
This will start the Zuplo Gateway, and the Route Designer where you can check how the routes and policies in this project are wired together.
To see the setup for the MCP server, open the mcp.oas.json
file in the Route Designer.
Making Requests to the MCP Server#
With the project running locally, you can test the MCP server using the Model Context Protocol Inspector.
Inspector can be run locally:
npx @modelcontextprotocol/inspector
Open the Inspector using the URL that it outputs to your terminal and set the server connection as follows:
- Transport Type: Streamable HTTP
- URL:
https://localhost:9000/mcp
- Authentication Header Name:
Authorization
- Bearer Token: The API Key you created.
Then click on Connect.
Once the server is connected, you should be able to List Tools to see, and work with, the various tools the MCP server exposes for the Todo List API.
Secret Masking in Action#
In order to demonstrate Secret Masking, this project includes a transformer that adds an "exposed" API key into the list of Todos (it's number 3). The file can be found at modules/transform-body-outbound.ts
.
When running the get_todos
tool in the Inspector, you will see that todo ID 3 is set to:
{
userId: 1,
id: 3,
title: "Update API key to [REDACTED]",
completed:false
}
This is the Secret Masking policy in action. If you remove the policy from the /mcp
route in mcp.oas.json
and run the tool again, you will now see the API token exposed in plain sight.
Prompt Injection Detection#
This policy is set to check all responses for poisonous injections that could cause the LLMs underlying the service you connect your MCP server to to behave strangely, share information they aren't supposed to, or just quack like a duck.
The policy runs a simple agent on whatever model you specify that checks for likely prompt injection, and if discovered, it will fail the response with a 400 error.
For more on how this works, see the Prompt Injection Detection documentation.
Prompt Injection Detection: Working Locally with Ollama#
When working locally, if you don't want to use OpenAI as the service behind the Prompt Injection Detection policy, you can use Ollama to serve whatever model you wish to use locally.
The model must be OpenAI API compatible and support tool/function calling. Our recommendation is the small qwen3:0.6b
model.
Run the model locally:
ollama serve qwen3:0.6b
Then update the handler for the PromptInjectionDetectionOutboundPolicy
in config/policies.json
to:
"handler": {
"module": "$import(@zuplo/runtime)",
"export": "PromptInjectionDetectionOutboundPolicy",
"options": {
"apiKey": "na",
"baseUrl": "http://localhost:11434/v1",
"model": "qwen3:0.6b"
}
}
Discover More Examples
API Linting
See how to use API linting to enforce api consistency and require Zuplo features like policies.
Backend for Frontend (BFF) Auth
Optimize UX and security in web applications with this approach.
Custom Rate Limiting
Invoke the Rate Limit policy programatically and then modify the 429 response.
Custom Modules
How to bundle custom node modules to use in your Zuplo project.