dolibarr 25.0.0-alpha
ToolApiBridge Class Reference

Class ToolApiBridge. More...

Inheritance diagram for ToolApiBridge:
Collaboration diagram for ToolApiBridge:

Public Member Functions

 __construct ($db, $user=null, $conf=null)
 Constructor.
 
 getDefinitions ()
 Returns tool definitions derived from the enabled REST API endpoints.
 
 getRequiredRights (string $toolName)
 Rights are enforced by the REST API classes themselves.
 
 getCategories ()
 Return categories this tool belongs to.
 
 execute (string $name, array $args)
 Execute a bridged tool: authenticate the acting user, call the API method in-process with positional arguments, catch RestException.
 
- Public Member Functions inherited from McpTool
 isSystem ()
 Return true if this is a system/infrastructure tool that must always remain visible and executable regardless of the admin allow-list.
 
 writeConfirmationPreview (string $toolName, array $args)
 Preview of what a call would write, or NO_WRITE for a read tool.
 

Public Attributes

const ENDPOINT_CATEGORIES
 Endpoint key -> intent categories of the assistant's query classifier (classifyIntentUniversal() in parse_intent.php: billing, commercial, thirdparty, stock, project, reporting).
 
const BRIDGE_DEFAULT_LIMIT = 25
 Default and ceiling applied to list 'limit' parameters when called through the bridge.
 
- Public Attributes inherited from McpTool
const RIGHTS_UNDECLARED = 'undeclared'
 Default of getRequiredRights(): the class never declared anything, deny.
 
const NO_WRITE = ''
 Returned by writeConfirmationPreview() when the tool writes nothing.
 

Private Member Functions

 loadApiRuntime ()
 Load the REST API runtime (Restler autoloader + DolibarrApi base classes), mirroring the bootstrap sequence of htdocs/api/index.php, so that the endpoint classes (which extend DolibarrApi and throw RestException) can be loaded and executed outside the Restler HTTP runtime.
 
 discoverEndpoints ()
 Discover the REST API endpoints of every enabled module.
 
 resolveEndpointClass (string $key)
 Load an endpoint's api file and resolve its real class name (lazy, cached in $this->endpoints).
 
 defaultMethods ()
 Methods exposed for an endpoint carrying no hand-written entry.
 
 applyMethodRestriction (array $methods)
 Apply the AI_MCP_API_BRIDGE_METHODS restriction.
 
 defsCacheFile ()
 Path of the definitions cache file for the CURRENT state, or '' when no writable temp directory exists.
 
 writeDefsCache (string $cachefile)
 Persist the generated definitions/routes/endpoints, pruning cache files of previous states so stale signatures do not pile up.
 
 buildToolDefinition (array $ep, string $key, string $method, string $toolname, array $meta=[])
 Build one MCP tool definition from an API class method: reflection + docblock give the skeleton, then the hand-written per-method enrichment is merged over it ('description' appended, 'params' overriding parameter docs, shared common docs as last fallback).
 
 liftInlineTags ($desc, string $ptype, array &$constraints)
 Lift Restler's inline validation tags out of a parameter description.
 
 tagValueToNumber (string $value)
 Convert a numeric tag value to the PHP number JSON encodes as a number.
 
 restlerPatternToJsonSchema (string $value)
 Convert a Restler {@pattern} value to a JSON Schema pattern.
 
 docTypeToJson (string $type)
 Convert a docblock type to a JSON Schema type.
 
 extrafieldsElementForEndpoint ($key)
 Map a bridge endpoint key to the element type ExtraFields uses.
 

Detailed Description

Class ToolApiBridge.

Exposes enabled REST API endpoints as MCP tools (read-only POC).

Definition at line 68 of file api_bridge.class.php.

Constructor & Destructor Documentation

◆ __construct()

ToolApiBridge::__construct ( $db,
$user = null,
$conf = null )

Constructor.

Parameters
DoliDB$dbDatabase handler
User | null$userActing user provided by McpHandler (the caller; tool calls run with this user's rights)
Conf | null$confDolibarr config (optional)

Reimplemented from McpTool.

Definition at line 619 of file api_bridge.class.php.

References conf(), and user.

Member Function Documentation

◆ applyMethodRestriction()

ToolApiBridge::applyMethodRestriction ( array $methods)
private

Apply the AI_MCP_API_BRIDGE_METHODS restriction.

Intersection only: the constant can narrow what the whitelist exposes — on every endpoint, enriched or not — but can never add a method to it, so it can never turn on a write method behind the whitelist's back.

Parameters
array<string,array{suffix?:string,description?:string,params?:array<string,string>}>$methods Whitelisted methods
Returns
array<string, array{suffix?:string, description?:string, params?:array<string,string>}> Restricted methods

Definition at line 806 of file api_bridge.class.php.

References getDolGlobalString().

Referenced by getDefinitions().

◆ buildToolDefinition()

ToolApiBridge::buildToolDefinition ( array $ep,
string $key,
string $method,
string $toolname,
array $meta = [] )
private

Build one MCP tool definition from an API class method: reflection + docblock give the skeleton, then the hand-written per-method enrichment is merged over it ('description' appended, 'params' overriding parameter docs, shared common docs as last fallback).

Parameters
array{module:string,path:string,class:string,label:string}$ep Endpoint entry
string$keyEndpoint key (e.g. 'thirdparties')
string$methodWhitelisted API method name (e.g. 'index', 'get')
string$toolnameGenerated tool name
array{suffix?:string,description?:string,params?:array<string,string>}$meta Hand-written enrichment for this method
Returns
array<string, mixed>|null Tool definition, or null on reflection failure

Definition at line 983 of file api_bridge.class.php.

References docTypeToJson(), and liftInlineTags().

Referenced by getDefinitions().

◆ defaultMethods()

ToolApiBridge::defaultMethods ( )
private

Methods exposed for an endpoint carrying no hand-written entry.

Deliberately the read-only pair, per the review that merged this bridge ("we must start with only few methods exposed"). Discovery widens which endpoints are reachable, never what may be done to them: a write method still has to be whitelisted consciously, behind a confirmation gate.

Returns
array<string, array{}> Method name => empty enrichment

Definition at line 792 of file api_bridge.class.php.

Referenced by getDefinitions().

◆ defsCacheFile()

ToolApiBridge::defsCacheFile ( )
private

Path of the definitions cache file for the CURRENT state, or '' when no writable temp directory exists.

The state signature is part of the file name, so any relevant change - a module (de)activated, a Dolibarr upgrade, another entity, an edit of this file (which holds the enrichments), or a change of the DB-driven restrictions (AI_MCP_API_BRIDGE, AI_MCP_API_BRIDGE_METHODS) - simply points to a different file: no explicit invalidation hook to maintain, and an administrator RESTRICTING what the AI may reach takes effect on the very next request (review sonikf). External-module API updates that change none of these are covered by the TTL.

Returns
string Absolute cache file path, or '' to skip caching

Definition at line 918 of file api_bridge.class.php.

References $conf, dol_mkdir(), and getDolGlobalString().

Referenced by getDefinitions().

◆ discoverEndpoints()

ToolApiBridge::discoverEndpoints ( )
private

Discover the REST API endpoints of every enabled module.

Mirrors the scan htdocs/api/index.php performs to register endpoints with Restler, so the bridge exposes exactly the API surface the REST layer exposes — external modules included — instead of a list maintained by hand.

The walk is the same in both places: dolGetModulesDirs() gives the module directories, each mod*.class.php names a module, getModuleDirForApiClass() maps it to the directory holding its API classes, and every api_<key>.class.php there is one endpoint. A few modules are named differently in their descriptor and in isModEnabled(); those exceptions are copied from api/index.php rather than reinvented, so the two stay in step.

Note the class name is resolved through class_exists(), which is case-insensitive in PHP: api_agendaevents.class.php yields the candidate "Agendaevents" and still matches the declared AgendaEvents. Reflection is then used to recover the real spelling for display.

Returns
array<string, array{module:string, path:string, candidate:string, class:string, label:string}> Endpoints keyed by name

Definition at line 667 of file api_bridge.class.php.

References $module, dol_buildpath(), dol_osencode(), dolGetModulesDirs(), getModuleDirForApiClass(), and isModEnabled().

Referenced by getDefinitions().

◆ docTypeToJson()

ToolApiBridge::docTypeToJson ( string $type)
private

Convert a docblock type to a JSON Schema type.

Parameters
string$typeDocblock type (may be a union like int|string)
Returns
string JSON Schema type

Definition at line 1189 of file api_bridge.class.php.

Referenced by buildToolDefinition().

◆ execute()

ToolApiBridge::execute ( string $name,
array $args )

Execute a bridged tool: authenticate the acting user, call the API method in-process with positional arguments, catch RestException.

Parameters
string$nameThe tool name (e.g. 'api_thirdparties_list').
array<string,mixed>$args The tool arguments (named).
Returns
mixed Result array, or ["error" => ...] on failure.

Reimplemented from McpTool.

Definition at line 1276 of file api_bridge.class.php.

References aiStripPersonalExtrafields(), extrafieldsElementForEndpoint(), getDefinitions(), getDolGlobalInt(), and loadApiRuntime().

◆ extrafieldsElementForEndpoint()

ToolApiBridge::extrafieldsElementForEndpoint ( $key)
private

Map a bridge endpoint key to the element type ExtraFields uses.

Parameters
string$keyEndpoint key from the enrichment map.
Returns
string ExtraFields element type, '' when the objects carry none.

Definition at line 1238 of file api_bridge.class.php.

Referenced by execute().

◆ getCategories()

ToolApiBridge::getCategories ( )

Return categories this tool belongs to.

Returns
array<string> List of categories

Reimplemented from McpTool.

Definition at line 1220 of file api_bridge.class.php.

◆ getDefinitions()

ToolApiBridge::getDefinitions ( )

Returns tool definitions derived from the enabled REST API endpoints.

Returns
list<array<string, mixed>> Array of tool definitions.

Reimplemented from McpTool.

Definition at line 821 of file api_bridge.class.php.

References applyMethodRestriction(), buildToolDefinition(), defaultMethods(), defsCacheFile(), discoverEndpoints(), dol_now(), getDolGlobalInt(), isModEnabled(), loadApiRuntime(), resolveEndpointClass(), and writeDefsCache().

Referenced by execute().

◆ getRequiredRights()

ToolApiBridge::getRequiredRights ( string $toolName)

Rights are enforced by the REST API classes themselves.

Parameters
string$toolNameTool being executed.
Returns
string RIGHTS_ENFORCED_DOWNSTREAM

Reimplemented from McpTool.

Definition at line 1210 of file api_bridge.class.php.

◆ liftInlineTags()

ToolApiBridge::liftInlineTags ( $desc,
string $ptype,
array & $constraints )
private

Lift Restler's inline validation tags out of a parameter description.

The REST API documents constraints the way Restler reads them to build swagger.json: {@min 1}, {@max 100}, {@choice yes,no}, {@pattern /re/flags}. Those carry exactly what JSON Schema calls minimum, maximum, enum and pattern, so they are translated instead of being shown to the model as part of the sentence. Tags with no JSON Schema equivalent ({@type} names a PHP class, {@from} names the HTTP source, which in-process calls have no use for) are removed from the text and otherwise ignored.

Parameters
?string$descParameter description, as written in the docblock (may be null)
string$ptypeJSON Schema type already determined for this parameter
array<string,mixed>$constraints Filled with the JSON Schema constraints found
Returns
string The description with every inline tag removed

Definition at line 1095 of file api_bridge.class.php.

References restlerPatternToJsonSchema(), and tagValueToNumber().

Referenced by buildToolDefinition().

◆ loadApiRuntime()

ToolApiBridge::loadApiRuntime ( )
private

Load the REST API runtime (Restler autoloader + DolibarrApi base classes), mirroring the bootstrap sequence of htdocs/api/index.php, so that the endpoint classes (which extend DolibarrApi and throw RestException) can be loaded and executed outside the Restler HTTP runtime.

Returns
void

Definition at line 636 of file api_bridge.class.php.

Referenced by execute(), and getDefinitions().

◆ resolveEndpointClass()

ToolApiBridge::resolveEndpointClass ( string $key)
private

Load an endpoint's api file and resolve its real class name (lazy, cached in $this->endpoints).

class_exists() is case-insensitive, so the candidate "Agendaevents" matches the declared AgendaEvents; reflection then recovers the real spelling.

Parameters
string$keyEndpoint key
Returns
bool True when the class is resolved

Definition at line 749 of file api_bridge.class.php.

Referenced by getDefinitions().

◆ restlerPatternToJsonSchema()

ToolApiBridge::restlerPatternToJsonSchema ( string $value)
private

Convert a Restler {@pattern} value to a JSON Schema pattern.

JSON Schema patterns are ECMA-262 regexps with no delimiters and no flags, so the PCRE delimiters are stripped. A flag that changes what the regexp accepts cannot be carried over; rather than silently tightening the constraint, the pattern is then dropped and only the description keeps the information. The one exception is /i on a regexp holding no letter, where the flag has nothing to act on.

Parameters
string$valueRaw tag value, e.g. "/^[0-9,]*$/i"
Returns
string JSON Schema pattern, or '' when it cannot be expressed

Definition at line 1166 of file api_bridge.class.php.

Referenced by liftInlineTags().

◆ tagValueToNumber()

ToolApiBridge::tagValueToNumber ( string $value)
private

Convert a numeric tag value to the PHP number JSON encodes as a number.

{@min 0} must reach the model as 0, not "0": a JSON Schema minimum given as a string is not a minimum.

Parameters
string$valueNumeric tag value, already checked with is_numeric()
Returns
int|float

Definition at line 1148 of file api_bridge.class.php.

Referenced by liftInlineTags().

◆ writeDefsCache()

ToolApiBridge::writeDefsCache ( string $cachefile)
private

Persist the generated definitions/routes/endpoints, pruning cache files of previous states so stale signatures do not pile up.

Written to a temporary name then renamed, so a concurrent reader never sees a truncated file.

Parameters
string$cachefileTarget file from defsCacheFile()
Returns
void

Definition at line 953 of file api_bridge.class.php.

Referenced by getDefinitions().

Member Data Documentation

◆ BRIDGE_DEFAULT_LIMIT

const ToolApiBridge::BRIDGE_DEFAULT_LIMIT = 25

Default and ceiling applied to list 'limit' parameters when called through the bridge.

API methods default to 100 full objects — too much model context for a single call; everything stays reachable via 'page'.

Definition at line 107 of file api_bridge.class.php.

◆ ENDPOINT_CATEGORIES

const ToolApiBridge::ENDPOINT_CATEGORIES
Initial value:
= array(
'thirdparties' => array('thirdparty', 'billing', 'commercial'),
'categories' => array('thirdparty', 'stock'),
'invoices' => array('billing', 'thirdparty'),
'proposals' => array('commercial', 'thirdparty'),
'orders' => array('commercial', 'thirdparty'),
'products' => array('stock', 'commercial'),
'stockmovements' => array('stock'),
'warehouses' => array('stock'),
'projects' => array('project'),
'tasks' => array('project'),
'agendaevents' => array('thirdparty', 'project'),
'interventions' => array('project', 'commercial'),
'contracts' => array('commercial', 'billing'),
'members' => array('thirdparty', 'billing'),
'subscriptions' => array('thirdparty', 'billing'),
'expensereports' => array('billing'),
'tickets' => array('thirdparty', 'project'),
'shipments' => array('stock', 'commercial', 'thirdparty'),
'receptions' => array('stock', 'thirdparty')
)

Endpoint key -> intent categories of the assistant's query classifier (classifyIntentUniversal() in parse_intent.php: billing, commercial, thirdparty, stock, project, reporting).

On Latin-script queries the classifier prefilters which tools the model sees, so bridge tools MUST carry this vocabulary — anything else gets every bridge tool filtered out of the prompt. Endpoints absent from this map (external modules) fall back to all categories so they stay selectable.

Definition at line 80 of file api_bridge.class.php.


The documentation for this class was generated from the following file: