|
dolibarr 25.0.0-alpha
|
Class ToolApiBridge. More...


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. | |
Class ToolApiBridge.
Exposes enabled REST API endpoints as MCP tools (read-only POC).
Definition at line 68 of file api_bridge.class.php.
| ToolApiBridge::__construct | ( | $db, | |
| $user = null, | |||
| $conf = null ) |
Constructor.
| DoliDB | $db | Database handler |
| User | null | $user | Acting user provided by McpHandler (the caller; tool calls run with this user's rights) |
| Conf | null | $conf | Dolibarr config (optional) |
Reimplemented from McpTool.
Definition at line 619 of file api_bridge.class.php.
|
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.
| array<string,array{suffix?:string,description?:string,params?:array<string,string>}> | $methods Whitelisted methods |
Definition at line 806 of file api_bridge.class.php.
References getDolGlobalString().
Referenced by getDefinitions().
|
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).
| array{module:string,path:string,class:string,label:string} | $ep Endpoint entry | |
| string | $key | Endpoint key (e.g. 'thirdparties') |
| string | $method | Whitelisted API method name (e.g. 'index', 'get') |
| string | $toolname | Generated tool name |
| array{suffix?:string,description?:string,params?:array<string,string>} | $meta Hand-written enrichment for this method |
Definition at line 983 of file api_bridge.class.php.
References docTypeToJson(), and liftInlineTags().
Referenced by getDefinitions().
|
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.
Definition at line 792 of file api_bridge.class.php.
Referenced by getDefinitions().
|
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.
Definition at line 918 of file api_bridge.class.php.
References $conf, dol_mkdir(), and getDolGlobalString().
Referenced by getDefinitions().
|
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.
Definition at line 667 of file api_bridge.class.php.
References $module, dol_buildpath(), dol_osencode(), dolGetModulesDirs(), getModuleDirForApiClass(), and isModEnabled().
Referenced by getDefinitions().
|
private |
Convert a docblock type to a JSON Schema type.
| string | $type | Docblock type (may be a union like int|string) |
Definition at line 1189 of file api_bridge.class.php.
Referenced by buildToolDefinition().
| 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.
| string | $name | The tool name (e.g. 'api_thirdparties_list'). |
| array<string,mixed> | $args The tool arguments (named). |
Reimplemented from McpTool.
Definition at line 1276 of file api_bridge.class.php.
References aiStripPersonalExtrafields(), extrafieldsElementForEndpoint(), getDefinitions(), getDolGlobalInt(), and loadApiRuntime().
|
private |
Map a bridge endpoint key to the element type ExtraFields uses.
| string | $key | Endpoint key from the enrichment map. |
Definition at line 1238 of file api_bridge.class.php.
Referenced by execute().
| ToolApiBridge::getCategories | ( | ) |
Return categories this tool belongs to.
Reimplemented from McpTool.
Definition at line 1220 of file api_bridge.class.php.
| ToolApiBridge::getDefinitions | ( | ) |
Returns tool definitions derived from the enabled REST API endpoints.
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().
| ToolApiBridge::getRequiredRights | ( | string | $toolName | ) |
Rights are enforced by the REST API classes themselves.
| string | $toolName | Tool being executed. |
Reimplemented from McpTool.
Definition at line 1210 of file api_bridge.class.php.
|
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.
| ?string | $desc | Parameter description, as written in the docblock (may be null) |
| string | $ptype | JSON Schema type already determined for this parameter |
| array<string,mixed> | $constraints Filled with the JSON Schema constraints found |
Definition at line 1095 of file api_bridge.class.php.
References restlerPatternToJsonSchema(), and tagValueToNumber().
Referenced by buildToolDefinition().
|
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.
Definition at line 636 of file api_bridge.class.php.
Referenced by execute(), and getDefinitions().
|
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.
| string | $key | Endpoint key |
Definition at line 749 of file api_bridge.class.php.
Referenced by getDefinitions().
|
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.
| string | $value | Raw tag value, e.g. "/^[0-9,]*$/i" |
Definition at line 1166 of file api_bridge.class.php.
Referenced by liftInlineTags().
|
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.
| string | $value | Numeric tag value, already checked with is_numeric() |
Definition at line 1148 of file api_bridge.class.php.
Referenced by liftInlineTags().
|
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.
| string | $cachefile | Target file from defsCacheFile() |
Definition at line 953 of file api_bridge.class.php.
Referenced by getDefinitions().
| 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.
| const ToolApiBridge::ENDPOINT_CATEGORIES |
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.