Skip to content

Add OpenAI-compatible /v1/tools REST endpoints alongside MCP#4

Merged
BillJr99 merged 1 commit into
mainfrom
claude/sweet-tesla-0M3wm
May 25, 2026
Merged

Add OpenAI-compatible /v1/tools REST endpoints alongside MCP#4
BillJr99 merged 1 commit into
mainfrom
claude/sweet-tesla-0M3wm

Conversation

@BillJr99

Copy link
Copy Markdown
Owner

Summary

This PR adds OpenAI-compatible REST endpoints (GET /v1/tools and POST /v1/tools/{name}/invoke) to the frontend UI server, allowing tools to be listed and invoked without speaking the MCP protocol. The MCP endpoint and all existing functionality remain completely unchanged.

Key Changes

  • New tool_registry.py module: A shared in-process tool store that both server.py and frontend/app.py can access. server.py populates it during tool registration; frontend/app.py reads from it to serve the OpenAI endpoints.

  • OpenAI-compatible endpoints in frontend/app.py:

    • GET /v1/tools — returns all registered tools in OpenAI function-calling schema format
    • POST /v1/tools/{tool_name}/invoke — invokes a tool with {"arguments": {...}} and returns a normalized tool_result response
    • Result normalization: strings are wrapped in a text content block; dicts with a content key pass through; other dicts are JSON-serialized; lists are used directly
    • Error handling: tool not found → HTTP 404; handler exceptions → HTTP 200 with is_error: true so LLM callers see errors as tool results
  • Updated server.py: Calls tool_registry.register() inside register_tool() for every enabled tool, populating the shared registry.

  • Enhanced tests/test_mcp_client.sh:

    • Added protocol mode selection (MCP vs OpenAI) before tool listing
    • Conditional logic to use either JSON-RPC /mcp calls or REST /v1/tools calls based on selected mode
    • Both modes converge to the same tool selection and result display logic
    • File listing step (mcpproxy__listfiles / mcpproxy__getfile) works with both protocols
  • New test file tests/test_openai_api.py: Comprehensive test suite for the OpenAI endpoints covering:

    • Tool listing (empty registry, single/multiple tools, schema validation)
    • Tool invocation (success cases, result normalization, error handling)
    • Handler context passing and exception safety
  • New tests in tests/test_server.py: Unit tests for the tool_registry module (register, get, get_all, clear, overwrite behavior).

Implementation Details

  • The shared registry uses a plain module-level dict since both server.py and frontend/app.py run in the same Python process.
  • The OpenAI endpoints are a pure addition — the MCP protocol path is completely unaffected.
  • Handler invocation passes ctx=None to the dynamic_tool callable, which is safe for tools that don't use MCP context features.
  • The test script now supports both MODE=1 (MCP) and MODE=2 (OpenAI) environment variable overrides to skip the interactive mode menu.

https://claude.ai/code/session_01V9SNVHv8uhS8pejXW9Dt7m

- New tool_registry.py: module-level dict shared between server.py and
  frontend/app.py; populated at startup, read at request time.

- server.py: one-line addition in register_tool() to mirror every MCP
  tool registration into tool_registry. No other changes.

- frontend/app.py: two new endpoints on port 8889 (existing UI port):
    GET  /v1/tools                    — tool list in OpenAI function-calling schema
    POST /v1/tools/{tool_name}/invoke — invoke with {"arguments": {...}}
  Result normalisation handles str / list / dict-with-content / plain-dict.
  Handler exceptions surface as is_error:true (HTTP 200) so LLMs see them.

- tests/test_server.py: add TestToolRegistry (register, get, get_all,
  overwrite, copy isolation, clear).

- tests/test_openai_api.py: 25 new tests covering GET /v1/tools schema
  shape, parameter passthrough, all result-normalisation branches,
  404 on unknown tool, error handling, and empty-body tolerance.

- tests/test_mcp_client.sh: add MODE selector (1=MCP, 2=OpenAI) after
  Ollama model selection. MCP path unchanged; OpenAI path uses
  GET /v1/tools for listing and POST /v1/tools/{name}/invoke for calls.
  File-listing step (mcpproxy__listfiles/getfile) branches on mode too.
  MODE env var skips the menu (mirrors OLLAMA_MODEL pattern).

All 232 tests pass (214 pre-existing + 18 new).

https://claude.ai/code/session_01V9SNVHv8uhS8pejXW9Dt7m
@BillJr99 BillJr99 merged commit d609f1f into main May 25, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants