Skip to main content
Glama
cyclomax-x

mcp-openai-platform

by cyclomax-x

mcp-openai-platform

A local MCP (Model Context Protocol) server exposing the OpenAI platform REST API as tools — files, fine-tuning, inference, images, audio, batch, and organization usage/costs.

Built for this project after doing a full fine-tuning run by hand with curl; the tool descriptions encode the gotchas found along the way (see Notable behaviours) so they don't have to be rediscovered.

What this is (and isn't)

This is: a stdio MCP server that your MCP client (Claude Code, etc.) runs locally. The client calls these tools; the tools call OpenAI's REST API.

Claude Code (MCP client)
  → mcp-openai-platform (local stdio server)
    → https://api.openai.com/v1/...

This is not: a server for OpenAI's models to call. OpenAI's own docs on MCP and connectors and Secure MCP Tunnels describe the opposite direction — the Responses API consuming a remote MCP server over the network, with OAuth and tunnels. None of that applies here; this is a plain local server and needs no OAuth, no tunnel, no public URL.

Related MCP server: OpenAI API MCP Server

Install

Requires Node.js 18+ (uses built-in fetch and FormData; developed on Node 24).

cd mcp-openai
npm install
npm run build          # compiles src/ → dist/

Verify the build produced dist/index.js:

ls dist/               # index.js, openai-client.js

The server is now runnable but does nothing on its own — it speaks MCP over stdio and needs a client to drive it. Register it using one of the methods below.

Adding it to an agent / MCP client

The server is a stdio MCP server, so registration is the same shape everywhere: command = node, args = absolute path to dist/index.js, env = your API keys.

Use the absolute path — MCP clients don't reliably resolve relative paths, and the working directory at launch isn't guaranteed.

Claude Code — CLI (quickest)

claude mcp add openai-platform \
  --env OPENAI_API_KEY=sk-proj-... \
  --env OPENAI_ADMIN_API_KEY=sk-admin-... \
  -- node /absolute/path/to/mcp-openai/dist/index.js

On Windows, use the Windows-style absolute path:

claude mcp add openai-platform ^
  --env OPENAI_API_KEY=sk-proj-... ^
  -- node E:\wamp64\www\Ticketing_new\mcp-openai\dist\index.js

Add --scope project to write it into the project's .mcp.json (shared with the repo) instead of your personal config. Then:

claude mcp list           # confirm it's registered
claude mcp get openai-platform

Claude Code — project config file

Edit .mcp.json at the project root (this is what this project uses):

{
  "mcpServers": {
    "openai-platform": {
      "type": "stdio",
      "command": "node",
      "args": ["E:\\wamp64\\www\\Ticketing_new\\mcp-openai\\dist\\index.js"],
      "env": {
        "OPENAI_API_KEY": "sk-proj-...",
        "OPENAI_ADMIN_API_KEY": "sk-admin-..."
      }
    }
  }
}

Note the escaped backslashes — .mcp.json is JSON, so Windows paths need \\. Forward slashes also work on Windows if you prefer.

Claude Desktop

Edit the config file directly, then fully quit and reopen the app:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

Same mcpServers block as above.

Other MCP clients

Anything that speaks MCP over stdio works — Cursor, Windsurf, Zed, Continue, or a custom client built on the MCP SDK. The config key names vary slightly by app, but all of them need the same three things:

command: node
args:    ["<absolute path>/mcp-openai/dist/index.js"]
env:     { OPENAI_API_KEY: "...", OPENAI_ADMIN_API_KEY: "..." }

Verifying it works

After registering, restart the client and ask it to list your fine-tuning jobs, or check the tool list directly. In Claude Code:

/mcp

You should see openai-platform as connected with 31 tools. If it shows as failed, see Troubleshooting.

Restart the client after every rebuild — the server process is spawned at client startup, so a recompiled dist/ won't be picked up until it relaunches.

Troubleshooting

Symptom

Cause

Fix

Server shows "failed" / exits immediately

OPENAI_API_KEY not set

The server exits at startup without it. Check the env block spelling

Cannot find module .../dist/index.js

Not built, or wrong path

Run npm run build; use an absolute path in the config

Tools missing after a code change

Client still running the old process

Restart the MCP client

403 Missing scopes: api.usage.read

Using a project key for org tools

Set OPENAI_ADMIN_API_KEY to an Admin key — see Authentication

429 insufficient_quota on every call

Account balance/billing, not code

Check platform.openai.com/settings/organization/billing

Windows path errors in JSON

Unescaped backslashes

Use \\ or forward slashes in .mcp.json

Why a local path instead of npm

Deliberate. Publishing would mean a version bump + republish for every tweak, and npx -y <pkg> re-resolves from the registry on each launch. A direct node dist/index.js path skips all of that, and the project-specific guidance baked into tool descriptions isn't meaningful to anyone else. If this ever needs to run on other machines, publishing is a small step to take then.

Authentication — two keys, two tiers

Env var

Used for

Where to get it

OPENAI_API_KEY

Files, fine-tuning, inference, images, audio, batch

Project API key, platform.openai.com/api-keys

OPENAI_ADMIN_API_KEY

openai_get_org_costs, openai_get_org_usage*

Admin key, platform.openai.com/settings/organization/admin-keys, needs the api.usage.read scope

OPENAI_API_KEY is required — the server exits at startup without it. OPENAI_ADMIN_API_KEY is optional; only the three org tools need it, and they return a clear error explaining what's missing if it isn't set.

These are genuinely different credential types. A project key — even one with full permissions inside its project — gets 403 Missing scopes: api.usage.read on the /organization/* endpoints. That's by design, not a misconfiguration.

Tools (31)

Files

Tool

Notes

openai_upload_file

Local path + purpose (fine-tune, batch, assistants, …) → file ID

openai_list_files

Optional purpose filter

openai_get_file

Metadata for one file

openai_download_file_content

Pass decode_base64: true for fine-tuning result files

openai_delete_file

Irreversible

Models

Tool

Notes

openai_list_models

filter does a case-insensitive substring match on model IDs

openai_get_model

Details for one model

Fine-tuning

Tool

Notes

openai_create_finetune_job

Costs real money — see Cost

openai_get_finetune_job

Status, trained_tokens, fine_tuned_model, result_files

openai_list_finetune_jobs

openai_cancel_finetune_job

openai_pause_finetune_job / openai_resume_finetune_job

openai_list_finetune_events

Step-by-step log — the place to look when a job fails

openai_list_finetune_checkpoints

Intermediate models, each a usable model ID

Inference

Tool

Notes

openai_chat_completion

Works with fine-tuned models (ft:...). Supports response_format structured outputs. No streaming — see below

openai_create_embedding

openai_create_moderation

input accepts a string or an array of text/image parts

Images

openai_generate_image, openai_edit_image (local file paths + optional mask), openai_create_image_variation (dall-e-2 only, per OpenAI).

Audio

Tool

Notes

openai_create_speech

Writes the audio to output_path, returns path + byte count

openai_transcribe_audio

timestamp_granularities requires response_format: "verbose_json"

openai_translate_audio

Translates to English

Batch

openai_create_batch, openai_get_batch, openai_list_batches, openai_cancel_batch. Discounted vs. synchronous calls; results arrive within the completion window (default 24h).

Organization — requires admin key

Tool

Notes

openai_get_org_costs

Daily aggregate spend

openai_get_org_usage_completions

Token usage, optionally grouped by model

openai_get_org_usage

Usage for embeddings / images / moderations / audio / vector stores / etc.

Notable behaviours

Things that cost real debugging time and are now encoded in the tool descriptions:

  • No fine-tuning usage endpoint exists. OpenAI provides /organization/usage/{completions,embeddings,images,moderations,audio_*,vector_stores,…} — but nothing for fine-tuning training. Training cost only appears folded into the daily total from openai_get_org_costs, so you infer it from a spike on the training day.

  • Fine-tuning result files may come back base64-encoded. The training-metrics CSV downloaded raw looks like garbage and wc -l reports 0 lines. openai_download_file_content takes decode_base64: true for this.

  • Bare model aliases can reject fine-tuning. gpt-4o-mini returned model_not_available, while the dated snapshot gpt-4o-mini-2024-07-18 was fine. Use openai_list_models with a ft: filter to see which base models already have working fine-tunes on the account.

  • insufficient_quota (429) is an account problem, not a code problem. If openai_list_models works but every inference call 429s, it's billing/balance — not scopes, not rate limits. A single fine-tuning job can exhaust a small balance and take unrelated production traffic down with it.

  • Streaming is intentionally not exposed. An MCP tool result is a single payload, so a streamed body would only be reassembled before returning.

  • TLS note (PHP callers, not this server). Node's fetch uses the system trust store and works fine. The PHP scripts in ../pnr_finetune/ needed an explicit CA bundle because that install has curl.cainfo unset — the fix there was CURLOPT_CAINFO, not disabling verification.

Cost

openai_create_finetune_job spends money. Confirmed against a real bill: fine-tuning gpt-4o-2024-08-06 is $25 per 1M trained tokens — a 1,603,698-token job produced a $40.09 charge against a $40.15 daily total (the remainder being that day's inference).

Check the account's balance/limit before starting a job. Inference tools cost per-token at each model's own rate.

Development

npm run build     # compile once
npm run dev       # tsc --watch

Adding a tool means four edits, all in the obvious places:

  1. A method on OpenAIClient in src/openai-client.ts

  2. A zod schema in src/index.ts

  3. An entry in the TOOLS array

  4. A case in dispatch()

Rebuild and restart the MCP client to pick up changes.

Manual smoke test

node -e "
const {spawn}=require('child_process');
process.env.OPENAI_API_KEY='sk-...';
const p=spawn('node',['dist/index.js'],{env:process.env});
let b=''; p.stdout.on('data',d=>b+=d);
setTimeout(()=>p.stdin.write(JSON.stringify({jsonrpc:'2.0',id:1,method:'initialize',params:{protocolVersion:'2024-11-05',capabilities:{},clientInfo:{name:'t',version:'1'}}})+'\n'),300);
setTimeout(()=>p.stdin.write(JSON.stringify({jsonrpc:'2.0',id:2,method:'tools/list',params:{}})+'\n'),800);
setTimeout(()=>{console.log(b);p.kill();},2000);
"

Security

  • .mcp.json holds keys in plaintext. It matches how the other servers in this project are configured, but treat the file accordingly and keep it out of anywhere it'd be shared.

  • Never paste an API key — especially an Admin key — into a chat or terminal session that gets logged. If that happens, rotate it immediately at the admin-keys page; assume it's compromised regardless of how briefly it was used.

  • openai_delete_file and openai_cancel_* are destructive and take effect immediately.

  • ../pnr_finetune/ — the dataset builder and evaluation scripts this server was extracted from

  • ../docs/openai-fine-tuning-guide.md — full walkthrough of the fine-tuning run, with curl equivalents

  • ../docs/openai-fine-tuning-general-guide.md — task-agnostic fine-tuning playbook

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyclomax-x/open_ai_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server