adachsoft / open-api-reader-tool
OpenAPI 3 reader tool for the adachsoft/ai-tool-call ecosystem with sandboxed filesystem access.
Requires
- php: >=8.0
- adachsoft/ai-tool-call: ^2.0
- adachsoft/collection: ^3.0
- adachsoft/open-api-reader: ^0.2
- adachsoft/sandbox-contracts: ^0.1.0
- guzzlehttp/guzzle: ^7.10
Requires (Dev)
- adachsoft/php-code-style: ^0.4
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.1
- rector/rector: ^2.4
README
OpenAPI reader tool for the adachsoft/ai-tool-call ecosystem.
This library exposes an AI tool that can read an OpenAPI 3 specification and provide high‑level information about available endpoints, detailed endpoint descriptions, schemas and simple search capabilities. Local specification files are always accessed through a filesystem sandbox defined by configuration.
Installation
composer require adachsoft/open-api-reader-tool
This will also install its runtime dependencies:
adachsoft/open-api-reader– low‑level OpenAPI 3 parseradachsoft/ai-tool-call– SPI for tool definition and executionguzzlehttp/guzzle– HTTP client for fetching remote OpenAPI documentsadachsoft/sandbox-contracts– filesystem sandbox contracts used to scope file access
Configuration
The tool is created via OpenApiToolFactory and expects a configuration map
(ConfigMap) that contains at least the base_path key:
use AdachSoft\AiToolCall\SPI\Collection\ConfigMap;
use AdachSoft\OpenApiReaderTool\OpenApiToolFactory;
$factory = new OpenApiToolFactory();
$config = new ConfigMap([
'base_path' => __DIR__ . '/specs', // sandbox root for local OpenAPI files
]);
$tool = $factory->create($config);
The base_path value is used to build a sandbox (SandboxPath) coming from
adachsoft/sandbox-contracts. Every local file path passed to the tool is resolved
within this sandbox; attempts to escape it (e.g. using ..) are rejected.
Tool definition
The exported tool is named openapi_reader and exposes one required parameter
action plus a set of optional parameters depending on the chosen action.
Parameters
spec_path_or_url(string, optional)- Path to a local OpenAPI file inside the sandbox base_path, or an absolute URL to an OpenAPI document.
request_headers(object, optional)- A map of HTTP header name → value used only when
spec_path_or_urlis a remote HTTP(S) URL. For local files, any non-emptyrequest_headersvalue is rejected. - All header values must be strings. Technical headers such as
Host,Content-Length,Transfer-Encoding,Connection,Proxy-Connection,Upgrade,TEandTrailerare forbidden. - Header values containing carriage return or line feed characters (
\r,\n) are rejected. - Header names are validated against the HTTP token syntax and duplicates differing only by letter case are not allowed.
- Sensitive header values may be visible to the surrounding tool-call infrastructure and should not be used in environments that do not safely mask tool arguments.
- A map of HTTP header name → value used only when
action(string, required)- One of:
list_endpoints– list endpoints in a paginated wayendpoint_details– show details for a specific endpointschema– fetch a schema definition from componentssearch– perform a simple text search over endpoints
- One of:
page(integer, optional)- Page number for
list_endpoints(default is1).
- Page number for
limit(integer, optional)- Page size for
list_endpoints(default is10, maximum is100).
- Page size for
path(string, optional)- OpenAPI path of the endpoint (e.g.
/users/{id}), used withendpoint_details.
- OpenAPI path of the endpoint (e.g.
method(string, optional)- HTTP method of the endpoint (e.g.
GET,POST), used withendpoint_details.
- HTTP method of the endpoint (e.g.
schema_name(string, optional)- Name of the schema in OpenAPI components, used with
schema.
- Name of the schema in OpenAPI components, used with
query(string, optional)- Free‑text search query, used with
search.
- Free‑text search query, used with
Example: remote spec with API key header
use AdachSoft\AiToolCall\SPI\Collection\KeyValueMap;
use AdachSoft\AiToolCall\SPI\Dto\ToolCallRequestDto;
use AdachSoft\OpenApiReaderTool\OpenApiTool;
use AdachSoft\OpenApiReaderTool\OpenApiToolFactory;
$factory = new OpenApiToolFactory();
$tool = $factory->create(new ConfigMap([
'base_path' => __DIR__ . '/specs',
]));
$request = new ToolCallRequestDto(
'openapi_reader',
new KeyValueMap([
'spec_path_or_url' => 'https://example.test/openapi.json',
'request_headers' => [
'X-API-Key' => 'secret',
],
'action' => 'list_endpoints',
'page' => 1,
'limit' => 10,
]),
);
$result = $tool->callTool($request);
$endpoints = $result->result->get('data');
Redirect handling and security
All local file accesses are performed relative to the configured base_path using
adachsoft/sandbox-contracts. This means:
- the tool cannot read files outside the sandbox root,
- invalid or escaping paths result in clear
InvalidToolCallExceptionerrors.
Remote HTTP(S) documents are fetched through a Guzzle HTTP client with a custom redirect policy:
- redirects are followed manually for HTTP status codes 301, 302, 303, 307 and 308;
- at most 5 redirect hops are allowed; exceeding this limit fails the request;
- each redirect
Locationheader must point to the same origin as the initial URL (same scheme, host and effective port, taking 80/443 as defaults for HTTP/HTTPS); - redirects changing scheme, host or effective port are rejected before any request is sent to the target URL;
- only final responses with a 2xx status code are accepted;
- 401 and 403 responses are reported as authorization errors without echoing any header values; other non-2xx statuses are reported with the status code and URL only, without response body or request options.
Sensitive header values and full header maps are never included in error messages
raised by this library, but they may still be logged or recorded by the surrounding
AI orchestration or tool-call infrastructure. Do not pass production secrets in
request_headers unless your environment masks or redacts tool arguments safely.
Basic usage example
The exact integration depends on how you wire tools in your AI orchestration. Below is a minimal, framework‑agnostic example of a single tool call against a local file:
use AdachSoft\AiToolCall\SPI\Collection\KeyValueMap;
use AdachSoft\AiToolCall\SPI\Dto\ToolCallRequestDto;
use AdachSoft\OpenApiReaderTool\OpenApiTool;
use AdachSoft\OpenApiReaderTool\OpenApiToolFactory;
$factory = new OpenApiToolFactory();
$tool = $factory->create(new ConfigMap([
'base_path' => __DIR__ . '/specs',
]));
$request = new ToolCallRequestDto(
'openapi_reader',
new KeyValueMap([
'spec_path_or_url' => 'openapi.yaml',
'action' => 'list_endpoints',
'page' => 1,
'limit' => 10,
]),
);
$result = $tool->callTool($request);
// $result->result is a KeyValueMap with key "data" holding the returned array
$endpoints = $result->result->get('data');
License
This library is released under the MIT License.