# How to Create a New API Endpoint in Palmier Pro: The Complete Guide

> Learn to create a new API endpoint in Palmier Pro by implementing async handlers registering URL paths and testing locally. Get the complete guide now.

- Repository: [Palmier/palmier-pro](https://github.com/palmier-io/palmier-pro)
- Tags: how-to-guide
- Published: 2026-06-21

---

**Creating a new API endpoint in Palmier Pro requires implementing an async handler method in [`MCPHTTPServer.swift`](https://github.com/palmier-io/palmier-pro/blob/main/MCPHTTPServer.swift), registering the URL path in the `handle(data:connection:transport:)` dispatcher, and testing against `http://127.0.0.1:<port>/your-path` since the application runs a local MCP HTTP server instead of a traditional REST API.**

Palmier Pro is a macOS application that exposes functionality through a lightweight **MCP (Mac Control Protocol) HTTP server** rather than a conventional REST API. If you are extending the `palmier-io/palmier-pro` codebase to add custom functionality, you must create a new API endpoint within this actor-based Swift architecture. This guide provides the exact implementation details, including specific file paths and method signatures from the source code.

## Understanding the MCP HTTP Server Architecture

Palmier Pro does not expose a traditional REST API. Instead, it runs a tiny **MCP HTTP server** that listens on `127.0.0.1` and handles requests under specific paths. The server is implemented as a Swift actor, which means all request handling must use `async`/`await` patterns to maintain thread safety.

The central request dispatcher is the `handle(data:connection:transport:)` method located in [`Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift). This method parses incoming HTTP requests and routes them to the appropriate handlers based on the URL path.

## Step 1: Create the Handler Method in MCPHTTPServer.swift

Open [`Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift) and add a private helper method that constructs the `HTTPResponse`. This method should perform your business logic—such as querying the current project or triggering a tool—and return a properly encoded response.

For example, to create an endpoint that returns the current project title as JSON:

```swift
private func handleProjectTitle() async -> HTTPResponse {
    // The project registry is the single source of truth for open projects.
    let title = await ProjectRegistry.shared.current?.title ?? "Untitled"
    let json = try! JSONEncoder().encode(["title": title])
    return HTTPResponse(
        statusCode: 200,
        headers: ["Content-Type": "application/json"],
        bodyData: json
    )
}

```

All request parsing and response generation happen in this file, making it the required location for any new endpoint logic.

## Step 2: Register the New Path in the Request Dispatcher

Inside the same file, locate the `handle(data:connection:transport:)` method (approximately lines 66-89). You must add a path check that recognizes your new endpoint URL and invokes the handler you created in Step 1.

Insert the following logic after the existing `guard request.path == "/mcp" || request.path == "/" else` check:

```swift
if request.path == "/my-new-endpoint" {
    let response = await handleProjectTitle()
    writeResponse(response, on: connection, transport: transport)
    return
}

```

The final structure should look like this:

```swift
guard request.path == "/mcp" || request.path == "/" else {
    sendRaw("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n", on: connection, keepAlive: false)
    return
}

// New endpoint registration
if request.path == "/my-new-endpoint" {
    let response = await handleProjectTitle()
    writeResponse(response, on: connection, transport: transport)
    return
}

// Existing GET handling for the generic "/mcp" endpoint
if request.method.uppercased() == "GET" {
    // ...
}

```

Because the server runs as an actor, you must call your handler with `await` and use the existing `writeResponse(_:on:transport:)` helper to send data back to the client.

## Step 3: Test the Endpoint Locally

Run the application with `swift run` and identify the port number from the console output (`Log.mcp.info("listener start port=…")`). Alternatively, read the port from macOS defaults:

```bash
curl http://127.0.0.1:$(defaults read com.palmier.pro MCPPort)/my-new-endpoint

```

You should receive a JSON response:

```json
{ "title": "My Awesome Video" }

```

If the request returns a 404 error, verify that the path string matches exactly—including the leading slash—and that the server has finished initializing.

## Optional: Add Client-Side Integration and UI Styling

If your endpoint will be called from the Agent UI or a custom script, construct the URL using the same port logic:

```swift
let port = try! MCPPortProvider.shared.port
let url = URL(string: "http://127.0.0.1:\(port)/my-new-endpoint")!
let data = try! Data(contentsOf: url)
print(String(decoding: data, as: UTF8.self))

```

When adding UI elements that trigger this endpoint, use the design constants defined in [`Sources/PalmierPro/UI/AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/AppTheme.swift) to maintain consistent spacing, colors, and fonts across the application.

## Summary

- **Palmier Pro uses an MCP HTTP server** running on `127.0.0.1` rather than a traditional REST API, requiring actor-safe `async` handlers.
- **New endpoints require two changes** to [`Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift): create a private handler method that returns `HTTPResponse`, and register the path in `handle(data:connection:transport:)`.
- **Testing uses `curl`** with the port retrieved from `com.palmier.pro` defaults or the console logs.
- **Optional UI integration** should leverage [`AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.swift) for styling consistency.

## Frequently Asked Questions

### Does Palmier Pro expose a traditional REST API?

No. According to the Palmier Pro source code, the application runs a lightweight **MCP (Mac Control Protocol) HTTP server** that listens on localhost (`127.0.0.1`). This architecture uses Swift actors and `async`/`await` patterns rather than traditional synchronous REST controllers.

### What file contains the MCP HTTP server implementation?

The core implementation lives in [`Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Agent/MCP/MCPHTTPServer.swift). This file contains the `MCPHTTPServer` actor class and the `handle(data:connection:transport:)` method that serves as the central request dispatcher for all endpoints.

### Why must new endpoint handlers be marked as `async`?

The `MCPHTTPServer` is implemented as a **Swift actor**, which isolates its state to prevent data races. All methods that interact with the server's internal state, including request handlers, must be `async` to allow the actor to serialize access. The handler must also be called with `await` from the dispatcher.

### How do I determine the port number for the MCP server?

The port is dynamically assigned and stored in macOS defaults under the key `MCPPort` for the bundle identifier `com.palmier.pro`. Retrieve it using `defaults read com.palmier.pro MCPPort` in the terminal, or programmatically via `MCPPortProvider.shared.port` in Swift code.