@zincapp/mcp-server 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config.js CHANGED
@@ -39,7 +39,9 @@ export function loadConfig() {
39
39
  }
40
40
  return {
41
41
  agentToken,
42
- apiBaseUrl: apiBaseUrl || 'https://api.zincapp.com/api',
42
+ // api.zincapp.com serves the API at the root (agent/v1/…), NOT under /api — that prefix
43
+ // belongs to the my.zincapp.com portal gateway. Override with ZINCAPP_API_URL if needed.
44
+ apiBaseUrl: apiBaseUrl || 'https://api.zincapp.com',
43
45
  locale: locale || 'en',
44
46
  };
45
47
  }
@@ -15,33 +15,38 @@ const EditSchema = z.object({
15
15
  ntId: z.number().nullable().optional(),
16
16
  });
17
17
  export function registerApplyCompletion(server, client) {
18
- server.tool('apply_completion', 'Apply confirmed field completions to waste removals, ATTRIBUTED TO A REAL HUMAN. The operator ' +
19
- 'must supply a fresh Google id-token (googleIdToken) the write is recorded in the audit log ' +
20
- 'under that person, never a system user. Two internal steps: begin-session verifies Google + ' +
21
- 'the operator\'s write permission and mints a short-lived, single-use, batch-bound token; apply ' +
22
- 'then writes each edit through the framework (hooks + audit fire). Requires the RETIRADAS_WRITE ' +
23
- 'scope + companyId in the allowlist. Only apply edits the human has explicitly confirmed.', {
24
- companyId: z.number().describe('The company (tenant) id, e.g. 9'),
25
- googleIdToken: z.string().describe('A fresh Google id-token identifying the operator authorizing the write'),
18
+ server.tool('apply_completion', 'Apply confirmed field completions to waste removals, UNDER YOUR ACTIVE OPERATOR ELEVATION. ' +
19
+ 'You (the platform operator) must first elevate into the company from the web (IAM) this ' +
20
+ 'tool NEVER opens an elevation itself (that requires the web step-up). It checks your current ' +
21
+ 'elevation, and if you are not elevated into this company it asks you to do so in the web, then ' +
22
+ 'applies each confirmed edit through the framework (hooks + audit fire) as the elevated ' +
23
+ '_sysadmin, recording the real operator in the elevation audit trail. Requires the ' +
24
+ 'RETIRADAS_WRITE scope + companyId in the token allowlist. Only apply edits you have confirmed.', {
25
+ companyId: z.number().describe('The company (tenant) id you are elevated into, e.g. 9'),
26
26
  edits: z.array(EditSchema).describe('The confirmed edits (from propose_completion), one per removal'),
27
- }, async ({ companyId, googleIdToken, edits }) => {
28
- // Step 1: exchange the Google id-token for a short-lived apply token bound to THIS batch.
29
- const begin = await client.post('/mwm/retirada/session/begin', {
30
- companyId,
31
- googleIdToken,
32
- edits,
33
- });
34
- // Step 2: apply the batch, carrying the token. The backend re-verifies the binding + human.
35
- const result = await client.post('/mwm/retirada/apply', { companyId, confirm: true, edits }, { 'X-Agent-Apply-Token': begin.applyToken });
27
+ }, async ({ companyId, edits }) => {
28
+ // Step 1: check the operator's current elevation (opened in the web with step-up).
29
+ const elev = await client.get('/mwm/retirada/operator/current-elevation');
30
+ if (!elev.elevated) {
31
+ return { content: [{ type: 'text', text: `No estás elevado a ningún tenant. Elévate a la company ${companyId} desde el portal web ` +
32
+ `(IAM → elevar), y luego vuelve a lanzar apply_completion.` }] };
33
+ }
34
+ if (elev.companyId !== companyId) {
35
+ return { content: [{ type: 'text', text: `Estás elevado a la company ${elev.companyId}, no a la ${companyId}. Des-elévate y eleva a ` +
36
+ `la ${companyId} desde el portal web, luego vuelve a lanzar apply_completion.` }] };
37
+ }
38
+ // Step 2: apply under the active elevation. The backend re-verifies eligibility + the live OPEN.
39
+ const result = await client.post('/mwm/retirada/apply-elevated', { companyId, confirm: true, edits });
36
40
  const ok = result.applied.length;
37
41
  const bad = result.failed.length;
38
42
  const failLines = bad
39
43
  ? '\n\n### Fallidos\n' + result.failed.map(f => `- Retirada ${f.removalId}: ${f.error}`).join('\n')
40
44
  : '';
41
45
  const text = `# Aplicado · company ${companyId}\n` +
42
- `${ok} retirada(s) actualizada(s)${bad ? `, ${bad} con error` : ''}, atribuidas al operator.\n` +
46
+ `${ok} retirada(s) actualizada(s)${bad ? `, ${bad} con error` : ''}, bajo tu elevación de operador.\n` +
43
47
  (ok ? '\nAplicadas: ' + result.applied.join(', ') : '') +
44
- failLines;
48
+ failLines +
49
+ `\n\n_Recuerda des-elevarte desde el portal web con un motivo cuando termines._`;
45
50
  return { content: [{ type: 'text', text }] };
46
51
  });
47
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zincapp/mcp-server",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "MCP server for ZincApp — search docs, read API reference, execute sandbox calls, and audit/complete waste removals (retiradas)",
5
5
  "type": "module",
6
6
  "bin": {