Skip to content

AdamShannag/api-mcp-server

Repository files navigation

API MCP Server

A lightweight and extensible server for defining and executing API tools using the MCP protocol. Supports dynamic HTTP requests, typed arguments, and multiple transports (stdio, sse).

GitHub Workflow Status Go Version Trivy Scan GitHub Release License: MIT

Installation

You can install the server in one of two ways:

1. Install via go install

If you have Go installed, run:

go install github.com/AdamShannag/api-mcp-server/cmd/[email protected]

2. Download a pre-built binary

Download a binary from the Releases page.

CLI Flags

Flag Description Default
--transport, -t Transport type: stdio or sse stdio
--config, -c Path to JSON tool configuration ./config.json
--version, -v API MCP Server version -
--metrics, -m Enable Prometheus metrics and health check server -
--metrics-port Metrics and health check server port 8080

Environment Variables

Variable Description Default
API_MCP_HOST SSE host to bind to 127.0.0.1
API_MCP_PORT SSE port to bind to 13080
API_MCP_SSE_API_KEY Optional Bearer token for auth (none)
LOG_LEVEL Sets the minimum logging level (DEBUG, INFO, WARN, ERROR) INFO

Tool Config Placeholders

The tool configuration file supports environment variable substitution using the syntax:

{{env VAR_NAME:default_value}}

At runtime, placeholders are replaced with the corresponding environment variable. If the variable is not set, the default_value is used instead.

Examples

"host": "{{env API_HOST:jsonplaceholder.typicode.com}}"

Uses the value of API_HOST if set, otherwise falls back to the default.

"Authorization": "Bearer {{env API_KEY:not-set}}"

Uses API_KEY or "not-set" if not defined.

Before running the server, set any required environment variables:

export API_HOST=myapi.example.com
export API_KEY=supersecret123

Authentication

When using the SSE transport, you can optionally secure the endpoint using a Bearer token by setting the API_MCP_SSE_API_KEY environment variable.

Example:

export API_MCP_SSE_API_KEY="your-secret-key"
api-mcp-server --transport sse --config ./demo.tools.json

Incoming SSE connections must then provide the matching token in the Authorization header.

Tool Configuration (JSON)

The server accepts a JSON configuration file defining one or more tools. Each tool includes metadata (name, description), HTTP request information, and a list of args that define the input values required from the LLM.

Each tool config includes:

  • A unique name
  • A description shown to the LLM
  • A request object describing the HTTP call
  • A list of args to define expected inputs

Tool Arguments (args)

Arguments are inputs collected from the LLM. Each one may be used in one or more parts of the request:

  • Path Parameters → replaced directly inside the endpoint
  • Query Parameters → automatically added to the URL
  • Body → inserted as the raw request body string

Host (host)

The host is the target API domain (e.g., gitlab.com).

"host": "{{env GITLAB_API_HOST:gitlab.com}}"

Method (method)

The HTTP method (GET, POST, PUT, etc.).

"method": "POST"

Path Parameters (pathParams)

Used to replace variables in the endpoint. For example:

"endpoint": "/api/v4/projects/:project_id/pipeline",
"pathParams": ["project_id"]

With project_id = "MyProject/test", the final endpoint becomes:

/api/v4/projects/MyProject%2Ftest/pipeline

Query Parameters (queryParams)

Keys listed here are automatically appended to the endpoint as query string parameters:

"endpoint": "/api/v4/projects/:project_id/pipeline",
"queryParams": ["ref"]

With ref = "main", the result is:

/api/v4/projects/MyProject%2Ftest/pipeline?ref=main

Request Body (body)

The body field maps to a single argument name. Its value will be used as the raw request body string.

Example:

"body": "issue_payload"

Given this argument:

{
  "name": "issue_payload",
  "type": "string",
  "required": true,
  "description": "A JSON object like {\"title\": \"Bug report\"}"
}

The body sent to the server will be the exact string value of issue_payload.

Headers (headers)

Define static or dynamic HTTP headers to include in the request, e.g., tokens or content type:

"headers": {
"PRIVATE-TOKEN": "{{env GITLAB_TOKEN:not-set}}",
"Content-Type": "application/json"
}

Secure (secure)

If secure: true, the request uses https. If omitted or false, it uses http.

Full Example

{
  "name": "TriggerPipeline",
  "description": "Triggers a pipeline in GitLab for a specific project and branch.",
  "request": {
    "host": "{{env GITLAB_API_HOST:gitlab.com}}",
    "method": "POST",
    "secure": true,
    "endpoint": "/api/v4/projects/:project_id/pipeline",
    "headers": {
      "PRIVATE-TOKEN": "{{env GITLAB_TOKEN:not-set}}"
    },
    "queryParams": [
      "ref"
    ],
    "pathParams": [
      "project_id"
    ]
  },
  "args": [
    {
      "name": "project_id",
      "type": "string",
      "required": true,
      "description": "..."
    },
    {
      "name": "ref",
      "type": "string",
      "required": true,
      "description": "..."
    }
  ]
}

If project_id = "MyProject/test" and ref = "main", the final HTTP request is:

POST https://gitlab.com/api/v4/projects/MyProject%2Ftest/pipeline?ref=main
Headers:
  PRIVATE-TOKEN: <value from GITLAB_TOKEN>

Examples

This repository includes several example tool configurations to demonstrate different use cases. These are not ready-to-use APIs but serve as references:

License

MIT

Contribution

If you have any questions or want to contribute, feel free to open an issue or PR.