> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blaxel.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart: Develop a custom MCP server

> Develop custom MCP servers in TypeScript or Python using Blaxel SDK, with local testing via MCP Inspector and one-command deployment.

MCP servers ([Model Context Protocol](https://github.com/modelcontextprotocol)) provide a toolkit of multiple tools—individual capabilities for accessing specific APIs or databases. These servers can be interacted with using HTTP on the server’s global endpoint.

You can develop custom [MCP servers](https://modelcontextprotocol.io/introduction) in TypeScript or Python and deploy them on Blaxel by integrating a few lines of the Blaxel SDK and leveraging our other developer tools ([Blaxel CLI](../cli-reference/introduction), GitHub action, etc.).

## Quickstart

<Warning>It is required to have *npm* (TypeScript) or *uv* (Python) installed to use the following command.</Warning>

You can quickly **initialize a new MCP server from scratch** by using CLI command `bl new`. This initializes a new pre-scaffolded local repo where your entire code can be added.

```bash theme={null}
bl new mcp
```

You can test it by running the following command which launches **both** the MCP server and a web application to query it ([MCP Inspector](https://github.com/modelcontextprotocol/inspector), managed by MCP) locally.

<CodeGroup>
  ```shell TypeScript theme={null}

  pnpm inspect

  ```

  ```shell Python theme={null}

  BL_DEBUG=true uv run mcp dev src/server.py

  ```
</CodeGroup>

The web application is accessible at: [http://127.0.0.1:6274](http://127.0.0.1:6274/). Alternatively, you can just simply [serve the server](/Functions/Deploy-a-function) locally by running `bl serve --hotreload`.

## Develop the MCP server logic

<AccordionGroup>
  <Accordion title="Develop in TypeScript" icon="js">
    If you open the `src/server.ts` file, you'll see the complete server implementation. It follows the MCP server standard, using streamable HTTP as the transport mechanism.

    The main component you'll need to modify is the tool definition:

    ```typescript server.ts {13-27} theme={null}
    import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
    import "@blaxel/telemetry";
    import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
    import express from 'express';
    import { z } from 'zod';

    // Create an MCP server
    const server = new McpServer({
      name: 'GreetingServer',
      version: '1.0.0',
    });

    server.registerTool(
      'greet',
      {
        description: 'Greet someone by name',
        inputSchema: { name: z.string().optional().default('World')},
        outputSchema: { result: z.string() }
      },
      async ({ name }) => {
        const output = { result: `Hello, ${name}!` };
        return {
          content: [{ type: 'text', text: JSON.stringify(output) }],
          structuredContent: output
        };
      }
    );

    // Set up Express and HTTP transport
    const app = express();
    app.use(express.json());

    app.post('/mcp', async (req, res) => {
      // Create a new transport for each request to prevent request ID collisions
      const transport = new StreamableHTTPServerTransport({
        sessionIdGenerator: undefined,
        enableJsonResponse: true
      });

      res.on('close', () => {
        transport.close();
      });

      await server.connect(transport);
      await transport.handleRequest(req, res, req.body);
    });

    const port = parseInt(process.env.PORT || '80');
    const host = process.env.HOST || '0.0.0.0';

    app.listen(port, () => {
      console.log(`MCP Server running on <http://$>{host}:${port}/mcp`);
    }).on('error', error => {
      console.error('Server error:', error);
      process.exit(1);
    });
    ```

    Remember that the `name`, `description`, and *parameters* are crucial—they help your agent understand how your tool functions.
  </Accordion>

  <Accordion title="Develop in Python" icon="python">
    If you open the `src/server.py` file, you'll see the complete server implementation. It follows the MCP server standard, using streamable HTTP as the transport mechanism.

    The main component you'll need to modify is the tool definition:

    ```python server.py {12-16} theme={null}

    import os
    from mcp.server.fastmcp import FastMCP

    mcp = FastMCP(
        "GreetingServer",
        stateless_http=True,
        host=os.getenv('HOST', "0.0.0.0"),
        port=os.getenv('PORT', "80")
    )

    # Add a simple tool to demonstrate the server
    @mcp.tool()
    def greet(name: str = "World") -> str:
        """Greet someone by name."""
        return f"Hello, {name}!"

    # Run server with streamable_http transport
    if __name__ == "__main__":
        mcp.run(transport="streamable-http")

    ```
  </Accordion>
</AccordionGroup>

<Card title="Deploy your MCP server" icon="rocket" href="/Functions/Deploy-a-function">
  Read our complete guide for deploying your custom MCP server on Blaxel.
</Card>

## Template directory reference

### blaxel.toml

The MCP server deployment can be configured via the ***blaxel.toml*** file in your MCP server directory. This file is not mandatory; if the file is not found or a required option is not set, you will be prompted for the information during deployment.

```toml theme={null}
name = "my-mcp-server"
workspace = "my-workspace"
type = "function"

[env]
DEFAULT_CITY = "San Francisco"

[[triggers]]
  id = "trigger-my-mcp"
  type = "http"
[triggers.configuration]
  path = "functions/my-mcp" # This will create this endpoint on the following base URL: https://run.blaxel.ai/{YOUR-WORKSPACE}/
  authenticationType = "public"
```

* `name`, `workspace`, and `type` fields are optional and serve as default values. Any bl command run in the folder will use these defaults rather than prompting you for input.
* `[env]` section defines environment variables that the MCP server can access via the SDK. Note that these are NOT [secrets](../Agents/Variables-and-secrets).
* `[[triggers]]` and `[triggers.configuration]` sections define ways to send requests to the MCP servers. You can also make them either private (default) or public (`authenticationType = "public"`).

<AccordionGroup>
  <Accordion title="Define entrypoints in Python" icon="python">
    Additionally, when developing in Python, you can define an `[entrypoint]` section to specify how Blaxel is going to start your server.

    ```toml theme={null}
    ...

    [entrypoint]
    prod = ".venv/bin/python3 src/server.py"
    dev = "npx nodemon --exec uv run python src/server.py"

    ...
    ```

    * `prod`:  this is the command that will be used to serve your MCP server

    ```bash theme={null}
    .venv/bin/python3 src/server.py
    ```

    * `dev`: same as prod in dev mode, it will be used with the command `--hotreload`. Example:

    ```bash theme={null}
    npx nodemon --exec uv run python src/server.py
    ```

    This `entrypoint` section is optional. If not specified, Blaxel will automatically detect in the MCP server’s content and configure your server’s startup settings.
  </Accordion>

  <Accordion title="Define entrypoints in TypeScript" icon="js">
    In TypeScript, entrypoints are managed in the `scripts` in the `package.json` file at the root of the directory.

    * `scripts.start` : start the server locally through the TypeScript command, to avoid having to build the project when developing.
    * `scripts.build` : build the project. It is done automatically when deploying.
    * `scripts.prod` : start the server remotely on Blaxel from the dist folder, the project needs to be have been built before.
    * `scripts.dev` : same as start, but with hotreload. It's useful when developing locally, each file change is reflected immediately.

    The remaining fields in *package.json* follow standard JavaScript/TypeScript project conventions. Feel free to add any dependencies you need, but keep in mind that devDependencies are only used during the build process and are removed afterwards.
  </Accordion>
</AccordionGroup>

<Card title="Deploy your MCP server" icon="rocket" href="/Functions/Deploy-a-function">
  Read our complete guide for deploying your custom MCP server on Blaxel.
</Card>
