This guide explains how to configure pdf-forge with mcp-openapi-proxy, the default MCP integration for this repo.
mcp-openapi-proxy reads an OpenAPI 3.x spec and exposes a lightweight MCP navigator/executor surface.
For pdf-forge, the default MCP server is:
- server name:
pdf-forge - tool prefix:
pf
The proxy registers exactly 3 tools:
pf_list_endpointspf_describe_endpointpf_call_endpoint
It does not register one MCP tool per endpoint. Each API operation is represented by a stable toolName passed into pf_describe_endpoint and pf_call_endpoint.
Examples:
pf_get_api_v1_content_templatespf_get_api_v1_content_templates_templateIdpf_post_api_v1_workspace_document_types_code_renderpf_post_api_v1_workspace_templates_versions_versionId_render
mcp-openapi-proxy requires OpenAPI 3.x.
This repo still generates Swagger 2.0 for Swagger UI, and make swagger now also converts it to:
core/docs/openapi.yaml← canonical spec for MCP
Default committed MCP config points to the GitHub raw URL:
https://raw.githubusercontent.com/rendis/pdf-forge/main/core/docs/openapi.yaml
That default is intentionally machine-agnostic. If you are working with local, uncommitted API changes, regenerate the spec and temporarily point MCP_SPEC to ./core/docs/openapi.yaml.
-
Go 1.25+
-
Install the proxy binary
go install github.com/rendis/mcp-openapi-proxy/cmd/mcp-openapi-proxy@latest
-
Regenerate specs after API changes
make swagger
| Variable | Description | Default |
|---|---|---|
MCP_SPEC |
OpenAPI 3.x spec URL or local path | https://raw.githubusercontent.com/rendis/pdf-forge/main/core/docs/openapi.yaml |
MCP_BASE_URL |
Base URL for API calls | http://localhost:8080 |
MCP_TOOL_PREFIX |
Prefix for registered MCP tools and endpoint toolName values |
pf |
MCP_AUTH_TOKEN |
Static bearer token fallback | unset |
MCP_OIDC_ISSUER |
OIDC issuer URL for protected environments | unset |
MCP_OIDC_CLIENT_ID |
OIDC client ID | unset |
MCP_EXTRA_HEADERS |
Comma-separated headers applied to every request | unset |
The repo includes a versioned .mcp.json, so Claude Code can auto-detect the MCP server when the project is opened.
Verify:
claude mcp list
claude mcp get pdf-forgeThe repo includes a versioned ../../.codex/config.toml with a project-local MCP entry:
[mcp_servers.pdf-forge]
command = "mcp-openapi-proxy"
args = []
[mcp_servers.pdf-forge.env]
MCP_SPEC = "https://raw.githubusercontent.com/rendis/pdf-forge/main/core/docs/openapi.yaml"
MCP_BASE_URL = "http://localhost:8080"
MCP_TOOL_PREFIX = "pf"If you prefer a global Codex config instead:
codex mcp add pdf-forge --command mcp-openapi-proxy \
--env MCP_SPEC=https://raw.githubusercontent.com/rendis/pdf-forge/main/core/docs/openapi.yaml \
--env MCP_BASE_URL=http://localhost:8080 \
--env MCP_TOOL_PREFIX=pfEdit ~/.gemini/settings.json (global) or .gemini/settings.json (project):
{
"mcpServers": {
"pdf-forge": {
"command": "mcp-openapi-proxy",
"args": [],
"env": {
"MCP_SPEC": "https://raw.githubusercontent.com/rendis/pdf-forge/main/core/docs/openapi.yaml",
"MCP_BASE_URL": "http://localhost:8080",
"MCP_TOOL_PREFIX": "pf"
}
}
}
}This is the part people usually miss: the proxy can call the API just fine, but pdf-forge is multi-tenant, so many routes require contextual headers.
Usually require:
X-Tenant-IDX-Workspace-ID
Require:
X-Tenant-CodeX-Workspace-CodeX-Environment(devorprod)
You can pass them:
- per request in
pf_call_endpoint.headers - globally via
MCP_EXTRA_HEADERS
Example:
{
"toolName": "pf_get_api_v1_content_templates",
"headers": {
"X-Tenant-ID": "<tenant-uuid>",
"X-Workspace-ID": "<workspace-uuid>"
}
}In dummy mode, JWT validation is bypassed, so you usually do not need MCP_AUTH_TOKEN.
Run the backend in dev dummy mode:
make dev DUMMY=1or omit the auth section in core/settings/app.yaml.
For protected environments:
mcp-openapi-proxy login pdf-forge
mcp-openapi-proxy status
mcp-openapi-proxy logoutIf you want Codex to read the repo-local config explicitly:
mcp-openapi-proxy login --codex-config ./.codex/config.toml --server pdf-forge- Call
pf_list_endpoints - Pick the endpoint
toolName - Call
pf_describe_endpointif you need the exact contract - Call
pf_call_endpoint
If the task involves editing template documents or contentStructure, do not stop at the generic MCP setup. Continue with:
../../skills/pdf-forge/SKILL.md../../skills/pdf-forge/editor-capability-matrix.md../../skills/pdf-forge/portable-document-contract.md../../skills/pdf-forge/typst-rendering-boundaries.md../../skills/pdf-forge/mcp-editor-workflows.md
Those references are the authoritative source for what agents can safely edit today.
Example discovery flow:
{ "q": "templates", "path_prefix": "/api/v1/content" }Example call:
{
"toolName": "pf_get_api_v1_content_templates",
"headers": {
"X-Tenant-ID": "<tenant-uuid>",
"X-Workspace-ID": "<workspace-uuid>"
},
"query": {
"page": 1,
"perPage": 20
}
}-
Verify the binary is in
PATH:which mcp-openapi-proxy
-
If missing, install it:
go install github.com/rendis/mcp-openapi-proxy/cmd/mcp-openapi-proxy@latest
-
Check the raw URL:
curl -I https://raw.githubusercontent.com/rendis/pdf-forge/main/core/docs/openapi.yaml
-
Or verify the local file:
ls -la core/docs/openapi.yaml
-
Regenerate if needed:
make swagger
-
In dummy mode, make sure the backend is actually running without OIDC
-
In OIDC mode, run:
mcp-openapi-proxy status
-
Verify required tenant/workspace headers are present
The committed default MCP config uses the raw GitHub spec from main. If you're working on local API changes, regenerate the local spec and temporarily override MCP_SPEC=./core/docs/openapi.yaml.