29require
'../../main.inc.php';
38require_once DOL_DOCUMENT_ROOT .
"/core/lib/admin.lib.php";
39require_once DOL_DOCUMENT_ROOT .
"/core/class/html.form.class.php";
40require_once DOL_DOCUMENT_ROOT .
"/core/class/doleditor.class.php";
41require_once DOL_DOCUMENT_ROOT .
"/ai/lib/ai.lib.php";
42require_once DOL_DOCUMENT_ROOT .
"/core/lib/functions2.lib.php";
43require_once DOL_DOCUMENT_ROOT .
"/core/lib/security.lib.php";
46$langs->loadLangs(array(
"admin",
"website",
"other"));
57$action =
GETPOST(
'action',
'aZ09');
58$backtopage =
GETPOST(
'backtopage',
'alpha');
66if ($action ==
'update') {
69 if (GETPOSTISSET(
'AI_ASK_FOR_CONFIRMATION')) {
71 if ($res <= 0) $error++;
74 if (GETPOSTISSET(
'AI_LOG_RETENTION')) {
81 if (GETPOSTISSET(
'AI_DEFAULT_INPUT_MODE')) {
88 if (GETPOSTISSET(
'AI_INTENT_PROMPT')) {
101 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mainmenu=home");
106if ($action ==
'test_provider') {
107 $service =
GETPOST(
'service_key',
'aZ09');
113 if (preg_match(
'/^crypted:/', $credential)) {
114 $credential =
dol_decode(substr($credential, 8));
115 } elseif (preg_match(
'/^dolcrypt:/', $credential)) {
120 if ($credential !==
null) {
123 if ($res[
'success']) {
124 setEventMessages($langs->trans(
"ConnectionSuccessful") . $res[
'message'],
null,
'mesgs');
126 setEventMessages($langs->trans(
"ConnectionFailed") . $res[
'message'],
null,
'errors');
133if ($action ==
'update_external') {
137 if (GETPOSTISSET(
'AI_MCP_USER_ID')) {
150 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mainmenu=home");
155if ($action ==
'generate_key') {
158 if (empty($newKey)) {
177llxHeader(
'', $langs->trans($title),
$help_url,
'', 0, 0,
'',
'',
'',
'mod-ai page-admin');
179$linkback =
'<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.
'/admin/modules.php?restore_lastsearch_values=1').
'">'.
img_picto($langs->trans(
"BackToModuleList"),
'back',
'class="pictofixedwidth"').
'<span class="hideonsmartphone">'.$langs->trans(
"BackToModuleList").
'</span></a>';
187print
'<span class="opacitymedium">' . $langs->trans(
"ConfigHelp") .
'</span><br><br>';
195$defaultPromptText =
" ROLE: Dolibarr ERP AI.
196GOAL: Map user intent to specific JSON commands.
1991. OUTPUT: Single valid JSON object ONLY. No Markdown. No text.
200 Format: {\"tool\": \"tool_name\", \"arguments\": {\"argument_name\": \"argument_value\", ...}}
2012. TOOLS: Use ONLY provided tools. If no tool or thirdparty fits, you must first use 'respond_to_user' to inform user.
2023. ARGS: strict adherence to schema. Do not invent parameters.
2034. MISSING INFO: If a required argument (like an ID) is missing, use 'ask_for_clarification'.
2045. SAFETY: For DELETE/UPDATE actions, you MUST use 'ask_for_confirmation'.";
209print
'<div class="neutral">';
215print $form->textwithpicto($langs->trans(
'EnableMCPServer'), $langs->trans(
'DisableMCPAI'));
219print ajax_constantonoff(
'AI_MCP_ENABLED', array(),
null, 0, 0, 1);
344 print
load_fiche_titre($langs->trans(
"AiMcpExternalAccess"),
'',
'fas fa-lock-open');
346 print
'<form method="POST" action="'.$_SERVER[
"PHP_SELF"].
'">';
347 print
'<input type="hidden" name="token" value="'.newToken().
'">';
348 print
'<input type="hidden" name="action" value="update_external">';
350 print
'<div class="div-table-responsive-no-min">';
351 print
'<table class="noborder centpercent">';
354 print
'<tr class="oddeven">';
355 print
'<td>Service User <span class="fa fa-info-circle" title="' . $langs->trans(
"UserPermissionsTooltip") .
'"></span></td>';
357 print
'<div style="display: flex; align-items: center;">';
358 print $form->select_dolusers(
getDolGlobalInt(
'AI_MCP_USER_ID'),
'AI_MCP_USER_ID', 1);
359 print
' <input type="submit" class="button" value="'.$langs->trans(
"Save").
'" style="margin-left: 20px;">';
361 print
'<span class="opacitymedium small">' . $langs->trans(
"DedicatedUserRecommendation") .
'</span>';
365 print
'<tr class="oddeven">';
366 print
'<td width="30%">API Key</td>';
369 print
'<input type="text" id="apikey" value="'.$apiKey.
'" readonly style="width:400px; padding:6px; background:#f4f4f4; border:1px solid #ccc; color:#555;">';
370 print
' <a class="button smallpaddingimp" href="'.$_SERVER[
"PHP_SELF"].
'?action=generate_key&token='.newToken().
'">Generate New Key</a>';
372 print
'<span class="opacitymedium">' . $langs->trans(
"NoKeyWarning") .
'</span>';
373 print
' <a class="button smallpaddingimp" href="' . $_SERVER[
"PHP_SELF"] .
'?action=generate_key&token=' . newToken() .
'">' . $langs->trans(
"GenerateKey") .
'</a>';
380 print
'<tr class="oddeven">';
381 print
'<td>Endpoint URL</td>';
383 print
'<input type="text" id="endpoint" value="'.$endpoint.
'" readonly style="width:600px; border:none; background:transparent;">';
394 print
'<div style="background:#fcfcfc; border:1px solid #eee; padding:15px; border-radius:5px;">';
395 print
'<strong>' . $langs->trans(
"ClaudeDesktopConfig") .
'</strong><br>';
396 print
'<pre style="background:#333; color:#fff; padding:10px; border-radius:4px; overflow:auto; margin-top:10px;">';
397 echo htmlspecialchars(
'
402 "args": ["/path/to/mcp-bridge.js"],
404 "DOLIBARR_URL": "'.$endpoint.
'",
405 "DOLIBARR_API_KEY": "'.($apiKey ? $apiKey :
"YOUR_KEY_HERE").
'"
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
testAIConnection(string $service, string $key, string $url)
Tests the connection to an AI service using its API key and URL by sending message "Hello".
aiAdminPrepareHead()
Prepare admin pages header.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dolGetRandomBytes($length)
Return a string of random bytes (hexa string) with length = $length for cryptographic purposes.
dol_decode($chain, $key='1')
Decode a base 64 encoded + specific delta change.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
dolDecrypt($chain, $key='', $patterntotest='')
Decode a string with a symmetric encryption.
if( $action=='update') if($action=='test_provider') if( $action=='update_external') if($action=='generate_key') $help_url
ACTIONS.