# Repository

Repository-based custom apps can either be deployed from an existing Docker container image or generate one from the repository’s source code.

### Dockerfile

Building using a Dockerfile simplifies the process for deploying MCP servers. The following conditions must be met for using Dockerfile builds

1. Dockerfile:
   * The working directory must contain a file named Dockerfile (with no file extension)
   * This file must include the full instructions to build the server’s Docker image
2. Host:
   * The server must listen to all the interfaces at 0.0.0.0 so that the requests to the server can reach the container. Listening to the localhost interface will not work since the requests can’t be forwarded to the container in that case
3. Port:
   * To start correctly, the server must listen on a valid port. This must happen in one of three ways.
     * The server should listen on the port defined in the $PORT environment variable (recommended).
     * Or, if the Dockerfile specifies an EXPOSE instruction, the server should listen on that port. If there is more than one port mentioned in EXPOSE instruction, the default port 8080 will be used to listen to the server
     * By default, the port 8080 is used to forward the requests to the server, so the server should listen on port 8080, if no other port is specified

### Source Code

Natoma supports deploying custom apps from repositories using either NodeJS or Python.

#### NodeJS

**Dependencies**

The working directory must contain a package.json file. By default, npm is used to install the dependencies

1. If the user wants to use yarn for installing the packages, there should be a yarn.lock file in the working directory
2. If the user wants to use pnpm for installing dependencies, there should be a pnpm-lock.yaml file in the working directory

**Build**

The package.json file should contain a `build` script, if there are any necessary build steps

**Start**

The startup command for the server must be one of the following

1. The `package.json` file contains a `start` script, for starting the MCP server
2. There is a Procfile in the working directory, with a command for starting the web server. For example:

```python
web: node build/index.js
```

**Configuration**

The server program should be able to take in the environment variable `$PORT` as input, and the server must listen for requests in that port. Otherwise, the server must listen for requests at port `8080`.

**Optional**

1. Specific versions for node, npm, yarn, pnpm, and other engines can be configured in `package.json`

```
{
   // rest of the configuration
   // ...
  "engines": {
        "node": "a.b.c",
        "npm": "d.e.f",
        "pnpm": "g.h.i",
        "yarn": "i.j.k"
    }
   // ... 
   // rest of the configuration
}
```

#### Python

**Dependencies**

The dependencies are installed using pip. The working directory must contain a `requirements.txt` file for installing the dependencies.

Other package managers such as uv and conda are not supported currently.

**Build**

No additional required steps

**Start**

In order to start the web server in Python, there must be a Procfile in the working directory with the command to start the web server. The Procfile must contain the command for starting a web server, in the following format:

```python
web: COMMAND
```

For example:

If you are running a WSGI server (such as gunicorn), the Procfile could look like the following

```python
web: gunicorn module:wsgi_app --bind 0.0.0.0:$PORT --forwarded-allow-ips="*"
```

If you are running a ASGI server (such as uvicorn), the Procfile could look like the following

```python
web: uvicorn module:application --host 0.0.0.0 --port $PORT --proxy-headers --forwarded-allow-ips="*"
```

If the application already supports running a ASGI / WSGI web server, the startup command could simply be running the Python file directly as follows:

```
web: python app.py
```

**Configuration**

1. The web server (WSGI or ASGI) must listen to the interface `0.0.0.0` for receiving the requests
2. The web server (WSGI or ASGI) must listen either to the port specified using the `$PORT` environment variable or `8080`
3. The web server should forward attached proxy headers to the web application. This ensures the right protocol is used for any redirects

#### **Code Samples**

**FastMCP**

[FastMCP](https://github.com/jlowin/fastmcp) is one of the standard frameworks for working with model context protocol, and is actively maintained. It is a ASGI web application and can be deployed using an ASGI server such as uvicorn.

**Recommendations:**

1. Use the latest version of FastMCP to have fixes for streamable HTTP servers. At time of writing, the latest version is `v.2.14.3`
2. Use `requirements.txt` to store the dependencies for your MCP server
3. Create a Procfile to define the start command for your MCP server

Example:

The below code snippet describes the creation of a FastMCP application:

```python
from fastmcp import FastMCP

mcp = FastMCP()

application = mcp.streamable_http_app() # ASGI compatible web application
```

\
The corresponding Procfile using uvicorn as the ASGI server would be:

```python
web: uvicorn module:application --host 0.0.0.0 --port $PORT --proxy-headers --forwarded-allow-ips="*"
```

with the following parameter values:

**module:**

* The name of the python module containing the application

**application:**

* The web application created by FastMCP, which supports streamable HTTP

**host:**

* The network interface where the ASGI server binds to for handling HTTP requests. We bind to all network interfaces

**port:**

* The port to listen to for requests

**proxy-headers:**

* To enable parsing of proxy headers (such as X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host)

**forwarded-allow-ips:**

* To allow all IPs to send forwarded headers. This is safe because Google Cloud's load balancer is the trusted proxy sending these headers.

For this sample, running the uvicorn ASGI server within code would look as follows:

```python
File: server.py
from fastmcp import FastMCP
import os


import uvicorn



port = os.getenv("PORT", 8080)
mcp = FastMCP()
application = mcp.streamable_http_app(path="/mcp")


if __name__ == "__main__":
    uvicorn.run(application,   # Web application
                host="0.0.0.0",  # Bind to all interfaces
                port=port,       # Use the port from the environment variable
                proxy_headers=True,  # Enable proxy headers
                forwarded_allow_ips="*" # Allow all IPs to forward proxy headers
            ) 
```

The Procfile would be:

```
web: python server.py
```

**Official Python SDK**

The [official Python SDK](https://github.com/modelcontextprotocol/python-sdk) supports the full MCP specification, making it easy to implement MCP servers and clients. It uses the FastMCP library under the hood. It is a ASGI web application and can be deployed using an ASGI server such as uvicorn.

Recommendations:

1. Use the latest version of the python SDK to have fixes for streamable HTTP servers. At time of writing, the latest version is `v.1.25.0`
2. Use requirements.txt to store the dependencies for your MCP server
3. Create a Procfile to define the start command for your MCP server

Consider the following application created using the Python SDK:

```python
from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")
app = mcp.streamable_http_app()
```

The corresponding Procfile would be:

```python
web: uvicorn module:application --host 0.0.0.0 --port $PORT --proxy-headers --forwarded-allow-ips="*"
```

For this sample, running the uvicorn ASGI server within code would look as follows:

```python
File: app.py

import os
from mcp.server.fastmcp import FastMCP
import uvicorn


mcp = FastMCP("Demo")            # MCP server instance
app = mcp.streamable_http_app()  # The web application
port = os.getenv("PORT", "8080") # Get port value from environment


if __name__ == "__main__":
    uvicorn.run(
        app,                       # Web application
        host="0.0.0.0",            # Listen on all interfaces
        port=port,                 # Port to listen on
        forwarded_allow_ips="*",   # Allow all IPs to forward proxy headers
        proxy_headers=True)        # Enable proxy headers for forwarded requests
```

The Procfile would be:

```
web: python app.py
```

**Optional**

A specific Python version can be specified by creating a `.python-version` file in the root directory, with the version number.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.natoma.ai/docs/custom-apps/repository.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
