Skip to content

Commit f72ad0e

Browse files
MQ37jirispilkarenovate[bot]github-actions[bot]
authored
feat: add mcp starter templates ts-mcp-server and python-mcp-server and rename the proxy ones to ts-mcp-proxy and python-mcp-proxy (#586)
Changes: - renamed the old mcp servers from `-server` to `-proxy` - added new starter mcp server templates `ts-mcp-server` and `python-mcp-server` --------- Co-authored-by: Jiří Spilka <[email protected]> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com> Co-authored-by: Jiri Spilka <[email protected]>
1 parent d4078ab commit f72ad0e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1858
-11
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ type-check:
2121
uv run mypy templates/python-crawlee-playwright
2222
uv run mypy --ignore-missing-imports templates/python-crawlee-playwright-camoufox
2323
uv run mypy templates/python-empty
24-
uv run mypy templates/python-mcp-server
24+
uv run mypy templates/python-mcp-empty
25+
uv run mypy templates/python-mcp-proxy
2526
uv run mypy templates/python-playwright
2627
uv run mypy templates/python-scrapy
2728
uv run mypy templates/python-selenium

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ warn_unused_ignores = true
9494

9595
[[tool.mypy.overrides]]
9696
module = [
97+
"fastmcp", # Untyped and/or stubs not available
9798
"smolagents", # Untyped and/or stubs not available
9899
]
99100
ignore_missing_imports = true

templates/manifest.json

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,14 @@
298298
"useCases": ["AI"]
299299
},
300300
{
301-
"id": "python-mcp-server",
302-
"name": "python-mcp-server",
303-
"label": "Python MCP server",
301+
"id": "python-mcp-proxy",
302+
"name": "python-mcp-proxy",
303+
"label": "Python MCP proxy",
304304
"category": "python",
305305
"technologies": ["mcp"],
306306
"skipTests": true,
307307
"description": "Demonstrates how to convert a Python stdio, HTTP-streamable, or SSE-based Model Context Protocol server into an Apify Actor.",
308-
"archiveUrl": "https://github.com/apify/actor-templates/blob/master/dist/templates/python-mcp-server.zip?raw=true",
308+
"archiveUrl": "https://github.com/apify/actor-templates/blob/master/dist/templates/python-mcp-proxy.zip?raw=true",
309309
"defaultRunOptions": {
310310
"build": "latest",
311311
"memoryMbytes": 512,
@@ -314,6 +314,23 @@
314314
"showcaseFiles": ["src/main.py", "src/server.py"],
315315
"useCases": ["AI"]
316316
},
317+
{
318+
"id": "python-mcp-empty",
319+
"name": "python-mcp-empty",
320+
"label": "Python MCP server",
321+
"category": "python",
322+
"technologies": ["mcp"],
323+
"skipTests": true,
324+
"description": "Create a Model Context Protocol server using Python and FastMCP with Apify Actor integration for pay-per-event monetization.",
325+
"archiveUrl": "https://github.com/apify/actor-templates/blob/master/dist/templates/python-mcp-empty.zip?raw=true",
326+
"defaultRunOptions": {
327+
"build": "latest",
328+
"memoryMbytes": 512,
329+
"timeoutSecs": 60
330+
},
331+
"showcaseFiles": ["src/main.py"],
332+
"useCases": ["AI"]
333+
},
317334
{
318335
"id": "js-crawlee-cheerio",
319336
"name": "project_cheerio_crawler_js",
@@ -678,13 +695,13 @@
678695
"useCases": ["AI"]
679696
},
680697
{
681-
"id": "ts-mcp-server",
682-
"name": "ts-mcp-server",
683-
"label": "TypeScript MCP server",
698+
"id": "ts-mcp-proxy",
699+
"name": "ts-mcp-proxy",
700+
"label": "TypeScript MCP proxy",
684701
"category": "typescript",
685702
"technologies": ["mcp"],
686703
"description": "Example of how to turn a Model Context Protocol stdio, HTTP Streamable, or SSE server into an Apify Actor.",
687-
"archiveUrl": "https://github.com/apify/actor-templates/blob/master/dist/templates/ts-mcp-server.zip?raw=true",
704+
"archiveUrl": "https://github.com/apify/actor-templates/blob/master/dist/templates/ts-mcp-proxy.zip?raw=true",
688705
"defaultRunOptions": {
689706
"build": "latest",
690707
"memoryMbytes": 512,
@@ -693,6 +710,22 @@
693710
"showcaseFiles": ["src/main.ts", "src/billing.ts"],
694711
"useCases": ["AI"]
695712
},
713+
{
714+
"id": "ts-mcp-empty",
715+
"name": "ts-mcp-empty",
716+
"label": "TypeScript MCP server",
717+
"category": "typescript",
718+
"technologies": ["mcp"],
719+
"description": "Create a Model Context Protocol server using TypeScript and Express with Apify Actor integration for pay-per-event monetization.",
720+
"archiveUrl": "https://github.com/apify/actor-templates/blob/master/dist/templates/ts-mcp-empty.zip?raw=true",
721+
"defaultRunOptions": {
722+
"build": "latest",
723+
"memoryMbytes": 512,
724+
"timeoutSecs": 600
725+
},
726+
"showcaseFiles": ["src/main.ts"],
727+
"useCases": ["AI"]
728+
},
696729
{
697730
"id": "cli-start",
698731
"name": "cli-start",
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"actorSpecification": 1,
3+
"name": "python-mcp-empty",
4+
"title": "Python MCP Server",
5+
"description": "Python Model Context Protocol (MCP) server using FastMCP.",
6+
"version": "0.0",
7+
"buildTag": "latest",
8+
"usesStandbyMode": true,
9+
"meta": {
10+
"templateId": "python-mcp-empty",
11+
"generatedBy": "<FILL-IN-MODEL>"
12+
},
13+
"input": {
14+
"title": "Actor input schema",
15+
"description": "This is Actor input schema",
16+
"type": "object",
17+
"schemaVersion": 1,
18+
"properties": {},
19+
"required": []
20+
},
21+
"dockerfile": "../Dockerfile",
22+
"webServerMcpPath": "/mcp"
23+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"tool-call": {
3+
"eventTitle": "Price for completing a tool call",
4+
"eventDescription": "Flat fee for completing a tool call.",
5+
"eventPriceUsd": 0.05
6+
}
7+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.git
2+
.mise.toml
3+
.nvim.lua
4+
storage
5+
6+
__pycache__/
7+
*.py[cod]
8+
*$py.class
9+
*.so
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
*.egg-info/
24+
.installed.cfg
25+
*.egg
26+
MANIFEST
27+
.coverage
28+
.pytest_cache/
29+
.env
30+
.venv
31+
venv/
32+
ENV/
33+
.idea/
34+
.vscode
35+
.zed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.mise.toml
2+
mise.toml
3+
.nvim.lua
4+
storage
5+
6+
# The rest is copied from https://github.com/github/gitignore/blob/main/Python.gitignore
7+
8+
__pycache__/
9+
*.py[cod]
10+
*$py.class
11+
*.so
12+
.Python
13+
build/
14+
develop-eggs/
15+
dist/
16+
downloads/
17+
eggs/
18+
.eggs/
19+
lib/
20+
lib64/
21+
parts/
22+
sdist/
23+
var/
24+
wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
.coverage
30+
.pytest_cache/
31+
.env
32+
.venv
33+
venv/
34+
ENV/
35+
.idea/
36+
.vscode
37+
.zed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
## MCP server template
2+
3+
<!-- This is an Apify template readme -->
4+
5+
A template for creating a [Model Context Protocol](https://modelcontextprotocol.io) server using [FastMCP](https://docs.fasitmcp.dev/) on [Apify platform](https://docs.apify.com/platform).
6+
7+
This template includes a simple example MCP server with:
8+
9+
- An `add` tool that adds two numbers together with structured output
10+
- A dummy `calculator-info` resource endpoint
11+
- Pay [Per Event monetization](https://docs.apify.com/platform/actors/publishing/monetize#pay-per-event-pricing-model) support
12+
13+
## How to use
14+
15+
1. **Modify the server**: Edit `src/main.py` to add your own tools and resources
16+
2. **Add new tools**: Use the `@server.tool()` decorator to register new tools
17+
3. **Add new resources**: Use the `@server.resource()` decorator to register new resources
18+
4. **Update billing**: Configure billing events in `.actor/pay_per_event.json` and charge for tool calls
19+
20+
The server runs on port 3000 (or APIFY_CONTAINER_PORT if set) and exposes the MCP protocol at the `/mcp` endpoint.
21+
22+
## Running locally
23+
24+
```bash
25+
pip install -r requirements.txt
26+
APIFY_META_ORIGIN=STANDBY python -m src
27+
```
28+
29+
The server will start and listen for MCP requests at `http://localhost:3000/mcp`
30+
31+
## Deploying to Apify
32+
33+
[Push your Actor](https://docs.apify.com/academy/deploying-your-code/deploying) to the Apify platform and configure [standby mode](https://docs.apify.com/platform/actors/development/programming-interface/standby).
34+
35+
Then connect to the Actor endpoint with your MCP client: `https://me--my-mcp-server.apify.actor/mcp` using the [Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http).
36+
37+
**Important:** When connecting to your deployed MCP server, pass your Apify API token in the `Authorization` header as a Bearer token:
38+
39+
```
40+
Authorization: Bearer <YOUR_APIFY_API_TOKEN>
41+
```
42+
43+
### Pay per event
44+
45+
This template uses the [Pay Per Event (PPE)](https://docs.apify.com/platform/actors/publishing/monetize#pay-per-event-pricing-model) monetization model, which provides flexible pricing based on defined events.
46+
47+
To charge users, define events in JSON format and save them on the Apify platform. Here is an example schema with the `tool-call` event:
48+
49+
```json
50+
{
51+
"tool-call": {
52+
"eventTitle": "Price for completing a tool call",
53+
"eventDescription": "Flat fee for completing a tool call.",
54+
"eventPriceUsd": 0.05
55+
}
56+
}
57+
```
58+
59+
In the Actor, trigger the event with:
60+
61+
```python
62+
await Actor.charge(event_name='tool-call')
63+
```
64+
65+
This approach allows you to programmatically charge users directly from your Actor, covering the costs of execution and related services.
66+
67+
To set up the PPE model for this Actor:
68+
69+
- **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 [pay_per_event.json](.actor/pay_per_event.json).
70+
71+
## Resources
72+
73+
- [What is Anthropic's Model Context Protocol?](https://blog.apify.com/what-is-model-context-protocol/)
74+
- [How to use MCP with Apify Actors](https://blog.apify.com/how-to-use-mcp/)
75+
- [FastMCP documentation](https://gofastmcp.com/getting-started/welcome)
76+
- [Python SDK examples](https://github.com/modelcontextprotocol/python-sdk/tree/main)
77+
- [Python tutorials in Academy](https://docs.apify.com/academy/python)
78+
- [Apify SDK documentation](https://docs.apify.com/sdk/python/)
79+
- [Webinar: Building and monetizing MCP servers on Apify](https://www.youtube.com/watch?v=w3AH3jIrXXo)
80+
- [Apify MCP server documentation](https://docs.apify.com/platform/integrations/mcp)
81+
- [Apify MCP server configuration](https://mcp.apify.com/)

0 commit comments

Comments
 (0)