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).
You can install the server in one of two ways:
If you have Go installed, run:
go install github.com/AdamShannag/api-mcp-server/cmd/[email protected]Download a binary from the Releases page.
| 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 |
| 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 |
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.
"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=supersecret123When 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.jsonIncoming SSE connections must then provide the matching token in the Authorization header.
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
descriptionshown to the LLM - A
requestobject describing the HTTP call - A list of
argsto define expected inputs
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
The host is the target API domain (e.g., gitlab.com).
"host": "{{env GITLAB_API_HOST:gitlab.com}}"The HTTP method (GET, POST, PUT, etc.).
"method": "POST"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
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
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.
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"
}If secure: true, the request uses https. If omitted or false, it uses http.
{
"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>
This repository includes several example tool configurations to demonstrate different use cases. These are not ready-to-use APIs but serve as references:
-
GitLab Issues Tools for listing and creating issues in a GitLab project. See examples/gitlab
-
JSONPlaceholder Todos Tools interacting with the JSONPlaceholder public API. See examples/jsonplaceholder
If you have any questions or want to contribute, feel free to open an issue or PR.