How Response Schemas Are Defined and Returned in the MCP OpenAPI Server
Response schemas in the castrozan/tcc MCP server are derived directly from the OpenAPI specification, inlined during load time, and returned as JSON objects through the GET-API-ENDPOINT-SCHEMA meta-tool execution.
The castrozan/tcc repository implements a Model Context Protocol (MCP) server that bridges OpenAPI-compliant REST APIs with AI clients. Understanding how response schemas are defined and returned is essential for developers integrating external APIs through this middleware, as it determines how tool inputs are validated and how response structures are communicated to downstream consumers.
Loading and Inlining OpenAPI Specifications
The foundation of response schema handling begins with the OpenAPISpecLoader class in src/openapi-loader.ts, which processes the OpenAPI specification at server startup.
Fetching and Parsing the Spec
The OpenAPISpecLoader.loadOpenAPISpec method fetches the specification from various sources—URL, file path, stdin, or inline JSON. Once loaded, parseOpenAPISpec walks through each path-operation pair in the specification to identify available endpoints.
For each discovered operation, the system creates a corresponding tool. Meta-tools are generated via ToolsManager.createDynamicTools, while standard endpoint tools are created individually for each API path.
Resolving Schema References
Before schemas can be used, all $ref references must be resolved. The OpenAPISpecLoader.inlineSchema method recursively processes the OpenAPI components, inlining external references to produce self-contained JSON Schema objects. This ensures that each tool's schema is complete and portable, without dependencies on external component definitions.
Converting OpenAPI Schemas to MCP Tool InputSchemas
Once inlined, the schemas are integrated into the MCP tool definitions that the server exposes to clients.
Tool Creation Process
The ToolsManager in src/tools-manager.ts handles the conversion of OpenAPI operations into MCP tools. For each endpoint, it extracts parameter schemas and request body definitions, applying the inlined JSON Schema objects created during the loading phase. This process ensures that the inputSchema for each tool accurately reflects the API's expected request structure.
Schema Storage in Tool Definitions
The processed schemas are stored in each tool's inputSchema property as standard JSON Schema objects. These objects specify type: "object" with defined properties and optional required arrays, providing MCP clients with the metadata necessary to validate arguments before executing tool calls.
Retrieving Response Schemas via Meta-Tools
While inputSchema defines what goes into an API call, response schemas describing the API's output are accessed through a dedicated meta-tool mechanism.
The GET-API-ENDPOINT-SCHEMA Tool
Defined in src/tools-manager.ts (lines 34-42), the GET-API-ENDPOINT-SCHEMA meta-tool provides a mechanism to retrieve the JSON Schema for any specific API endpoint. Its inputSchema requires a single endpoint string parameter, which identifies the target API path.
Execution Flow and API Client Integration
When a client invokes this meta-tool, the OpenAPIServer registered in src/server.ts (lines 45-73) handles the tools/execute request. Rather than treating this as a static lookup, the server forwards the call to ApiClient.executeApiCall in src/api-client.ts.
Because the endpoint parameter maps to a real API route that returns OpenAPI component schemas (such as /schemas/{name}), the underlying API returns the JSON schema definition. The MCP server then wraps this response in a JSON-RPC message, returning the schema as a pretty-printed text block within the content array of the tool execution result.
Practical Examples
List All Available Tools
Retrieve the complete tool catalog, including meta-tools and endpoint-specific tools:
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Result (truncated):
{
"jsonrpc":"2.0",
"id":1,
"result":{
"tools":[
{"id":"LIST-API-ENDPOINTS","name":"list-api-endpoints"},
{"id":"GET-API-ENDPOINT-SCHEMA","name":"get-api-endpoint-schema"},
{"id":"INVOKE-API-ENDPOINT","name":"invoke-api-endpoint"}
]
}
}
Retrieve a Specific Endpoint Schema
Request the JSON schema for the /users/{id} endpoint:
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":2,
"method":"tools/execute",
"params":{
"name":"get-api-endpoint-schema",
"arguments":{"endpoint":"/users/{id}"}
}
}'
Result:
{
"jsonrpc":"2.0",
"id":2,
"result":{
"content":[
{
"type":"text",
"text":"{\
\"type\":\"object\",\
\"properties\":{\
\"id\":{\"type\":\"string\",\"description\":\"User identifier\"},\
\"includeDetails\":{\"type\":\"boolean\",\"default\":false}\
},\
\"required\":[\"id\"]\
}"
}
]
}
}
Invoke an API Endpoint
Execute the /users endpoint with parameters:
curl -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":3,
"method":"tools/execute",
"params":{
"name":"invoke-api-endpoint",
"arguments":{
"endpoint":"/users",
"params":{"name":"Alice","email":"alice@example.com"}
}
}
}'
Result:
{
"jsonrpc":"2.0",
"id":3,
"result":{
"content":[
{
"type":"text",
"text":"{\n \"id\": \"123\",\n \"name\": \"Alice\",\n \"email\": \"alice@example.com\"\n}"
}
]
}
}
Summary
- Response schemas originate from the OpenAPI specification loaded at server startup via
OpenAPISpecLoader.loadOpenAPISpec. - The
OpenAPISpecLoader.inlineSchemamethod recursively resolves all$refreferences to create self-contained JSON Schema objects. - Processed schemas are stored in each tool's
inputSchemaproperty withinToolsManager, defining valid inputs for API endpoints. - The
GET-API-ENDPOINT-SCHEMAmeta-tool retrieves specific endpoint schemas by executing against the underlying API viaApiClient.executeApiCall. - Schema responses are returned as pretty-printed JSON text blocks within the MCP protocol's
contentarray, wrapped in standard JSON-RPC messages.
Frequently Asked Questions
How does the server handle circular references in OpenAPI schemas?
The inlineSchema method in src/openapi-loader.ts recursively resolves $ref references during the loading phase. While the implementation flattens schema structures to create self-contained JSON Schema objects, developers should verify that their OpenAPI specifications do not contain unresolvable circular dependencies that could cause infinite recursion during the inlining process.
What is the difference between inputSchema and the response returned by GET-API-ENDPOINT-SCHEMA?
The inputSchema attached to each tool defines the parameters required to invoke that specific API endpoint—including query parameters, path parameters, and request body structures. In contrast, the GET-API-ENDPOINT-SCHEMA meta-tool returns the JSON Schema that describes the structure of the API's response payload, which typically differs from the input parameters and represents the data returned by the underlying REST API.
Can I retrieve response schemas for endpoints that use complex nested objects?
Yes. Because OpenAPISpecLoader.inlineSchema recursively processes all schema components during the initial loading phase, nested objects, arrays, and complex types are fully expanded and preserved. When you invoke the GET-API-ENDPOINT-SCHEMA tool, the server returns the complete, inlined schema including all nested property definitions.
Where is the schema execution logic handled when a meta-tool is invoked?
The execution logic resides in src/server.ts (lines 45-73) where OpenAPIServer registers the JSON-RPC handler for tools/execute requests. When the GET-API-ENDPOINT-SCHEMA meta-tool is called, the server forwards the request to ApiClient.executeApiCall in src/api-client.ts, which makes the actual HTTP request to the underlying API endpoint that returns the schema definition.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →