Back to template gallery

TypeScript MCP server

Example of how to Actorize a STDIO Model Context Protocol server.

Language

typescript

Tools

mcp

Features

src/main.ts

src/billing.ts

1/**
2 * ArXiv MCP Server - Main Entry Point
3 *
4 * This file serves as the entry point for the ArXiv MCP Server Actor.
5 * It sets up a proxy server that forwards requests to the locally running
6 * ArXiv MCP server, which provides a Model Context Protocol (MCP) interface
7 * for AI assistants to search and access arXiv papers.
8 */
9
10// Apify SDK - toolkit for building Apify Actors (Read more at https://docs.apify.com/sdk/js/)
11import { Actor, log } from 'apify';
12import { stdioToSse } from './lib/server.js';
13import { getLogger } from './lib/getLogger.js';
14
15// This is an ESM project, and as such, it requires you to specify extensions in your relative imports
16// Read more about this here: https://nodejs.org/docs/latest-v18.x/api/esm.html#mandatory-file-extensions
17// Note that we need to use `.js` even when inside TS files
18// import { router } from './routes.js';
19
20// Configuration constants for the MCP server
21// Command to run the ArXiv MCP server using uv package manager
22// TODO: Do not forget to install the MCP server in the Dockerfile
23const MCP_COMMAND = 'uv tool run arxiv-mcp-server';
24
25// Check if the Actor is running in standby mode
26const STANDBY_MODE = process.env.APIFY_META_ORIGIN === 'STANDBY';
27const SERVER_PORT = parseInt(process.env.ACTOR_WEB_SERVER_PORT || '', 10);
28
29// Logger configuration
30const LOG_LEVEL = 'info';
31const OUTPUT_TRANSPORT = 'sse';
32
33// Initialize the Apify Actor environment
34// The init() call configures the Actor for its environment. It's recommended to start every Actor with an init()
35await Actor.init();
36
37// Charge for Actor start
38await Actor.charge({ eventName: 'actor-start' });
39
40if (!STANDBY_MODE) {
41 // If the Actor is not in standby mode, we should not run the MCP server
42 const msg = 'This Actor is not meant to be run directly. It should be run in standby mode.';
43 log.error(msg);
44 await Actor.exit({ statusMessage: msg });
45}
46
47const logger = getLogger({
48 logLevel: LOG_LEVEL,
49 outputTransport: OUTPUT_TRANSPORT,
50});
51await stdioToSse({
52 port: SERVER_PORT,
53 stdioCmd: MCP_COMMAND,
54 logger,
55});

MCP server template

A template for running and monetizing a Model Context Protocol server over stdio on Apify platform. This allows you to run any stdio MCP server as a standby Actor and connect via SSE transport with an MCP client.

How to use

Change the MCP_COMMAND to spawn your stdio MCP server in src/main.ts, and don't forget to install the required MCP server in the .actor/Dockerfile. Feel free to configure billing logic in .actor/pay_per_event.json and src/billing.ts.

Push your Actor to the Apify platform, configure standby mode, and then connect to the Actor standby URL with your MCP client (e.g., https://me--my-mcp-server.apify.actor/sse).

Pay per event

This template uses the Pay Per Event (PPE) monetization model, which provides flexible pricing based on defined events.

To charge users, define events in JSON format and save them on the Apify platform. Here is an example schema with the tool-request event:

[
{
"tool-request": {
"eventTitle": "Price for completing a tool request",
"eventDescription": "Flat fee for completing a tool request.",
"eventPriceUsd": 0.05
}
}
]

In the Actor, trigger the event with:

await Actor.charge({ eventName: 'tool-request' });

This approach allows you to programmatically charge users directly from your Actor, covering the costs of execution and related services.

To set up the PPE model for this Actor:

  • Configure Pay Per Event: establish the Pay Per Event pricing schema in the Actor's Monetization settings. First, set the Pricing model to Pay per event and add the schema. An example schema can be found in .actor/pay_per_event.json.

Resources

Already have a solution in mind?

Sign up for a free Apify account and deploy your code to the platform in just a few minutes! If you want a head start without coding it yourself, browse our Store of existing solutions.