@theronap/agnoclast-mcp 0.9.201 → 0.9.203

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/lib/diagnose.mjs CHANGED
@@ -515,6 +515,11 @@ const PATH_TOOLS = {
515
515
  'intake/claim': 'intake_claim', 'intake/materialize': 'intake_materialize', 'staged': 'staged_records', 'brains': 'my_brains',
516
516
  'session-ping': 'session_ping', 'session-signals': 'session_signals', 'skills': 'skills',
517
517
  'ingest': 'capture', 'node-types': 'capture', 'obligations/candidates': 'capture',
518
+ // Named 2026-10-02 (obligation bbb5a8b5): these hook and cron endpoints were filing as `other`, which the
519
+ // server cannot trace. cli_paths_named.test.mjs now fails on any endpoint the CLI calls without a name.
520
+ 'ingest/route': 'capture', 'staged/promote': 'capture', 'pressing/ack': 'arrivals_notice',
521
+ 'resolve-candidates': 'resolve', 'resolve-apply': 'resolve', 'timeline/graphify': 'graphify_sync',
522
+ 'brain/capture-default': 'set_capture_brain',
518
523
  }
519
524
 
520
525
  /** PURE. The tool an outage on `url` belongs to: the running tool if known, else a path mapping, else 'other'. */
package/lib/server.mjs CHANGED
@@ -20,6 +20,7 @@ import { repoFullNameFrom, workingFilesFrom } from './capture.mjs'
20
20
  import { findTranscript, createWorkedFilesTracker } from './working_files.mjs'
21
21
  import { spawnObligationWorker } from './obligations_worker.mjs'
22
22
  import { renderObligations, renderPageObligations, tierReads, who } from './obligations_render.mjs'
23
+ import { renderSettings } from './settings_render.mjs'
23
24
  import { formatCreated, formatDryRun, formatSources, homeFromArgs, pickSource, renderHomeProblem } from './custom_sources.mjs'
24
25
 
25
26
  // PAGE tiers (ADR-0071). Six for a PAGE; a RECORD keeps three (`privacy` on log_session and
@@ -2980,6 +2981,58 @@ function renderNudge(payload) {
2980
2981
  },
2981
2982
  )
2982
2983
 
2984
+ // ADR-0074 — a person's own settings. The August 2026 ruling is "notices are on by default, and you
2985
+ // turn one off by telling the assistant"; these two tools are how the assistant does that.
2986
+ server.registerTool(
2987
+ 'my_settings',
2988
+ {
2989
+ title: 'My settings',
2990
+ description: "The person's own Agnoclast settings: which notices they get without asking (meetings about to start, deadlines within the hour, what is due today, hand-offs, lapses) and their timezone. The same settings as the Settings page in the console. Read this before answering \"why am I (not) being told about X\".",
2991
+ inputSchema: {},
2992
+ },
2993
+ async () => {
2994
+ let res
2995
+ try {
2996
+ res = await fetchCortex(`${BASE}/api/settings`, { headers: { Authorization: `Bearer ${TOKEN}` } })
2997
+ } catch (e) { return toolError(`Could not reach settings: ${e.message}`) }
2998
+ const out = await res.json().catch(() => null)
2999
+ if (!res.ok) return toolError(`Could not read settings: ${out?.detail ?? out?.error ?? res.status}`)
3000
+ return { content: [{ type: 'text', text: renderSettings(out) }] }
3001
+ },
3002
+ )
3003
+
3004
+ server.registerTool(
3005
+ 'set_setting',
3006
+ {
3007
+ title: 'Change one of my settings',
3008
+ description: "Change one of the person's own settings — ONLY when they asked you to (\"stop telling me what's due today\", \"set my timezone to Denver\"). Never on your own initiative, and never to quiet something you find noisy: a notice the person did not turn off is one they rely on. Pass `key` and `value` for a notice (keys from my_settings, e.g. notices.due_today = false), or `timezone` alone with an IANA name such as America/Denver. Say what you changed, and that they can change it back in Settings.",
3009
+ inputSchema: {
3010
+ key: z.string().optional().describe('the setting, exactly as my_settings lists it, e.g. notices.due_today'),
3011
+ value: z.boolean().optional().describe('true = on, false = off'),
3012
+ timezone: z.string().optional().describe('instead of key/value: an IANA timezone, e.g. America/Denver'),
3013
+ },
3014
+ },
3015
+ async ({ key, value, timezone }) => {
3016
+ const body = timezone ? { timezone } : { key, value }
3017
+ let res
3018
+ try {
3019
+ res = await fetchCortex(`${BASE}/api/settings`, {
3020
+ method: 'POST',
3021
+ headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
3022
+ body: JSON.stringify(body),
3023
+ })
3024
+ } catch (e) { return toolError(`Could not reach settings: ${e.message}`) }
3025
+ const out = await res.json().catch(() => null)
3026
+ if (!res.ok) return toolError(`Not changed: ${out?.detail ?? out?.error ?? res.status}`)
3027
+ const text = timezone
3028
+ ? `Timezone set to ${out.timezone} on ${out.memberships} brain${out.memberships === 1 ? '' : 's'}. They can change it in Settings.`
3029
+ : !out.changed
3030
+ ? `${out.key} was already ${out.value ? 'on' : 'off'} — nothing changed.`
3031
+ : `${out.key} is now ${out.value ? 'ON' : 'OFF'}. They can turn it back ${out.value ? 'off' : 'on'} in Settings (or ask you).`
3032
+ return { content: [{ type: 'text', text }] }
3033
+ },
3034
+ )
3035
+
2983
3036
  server.registerTool(
2984
3037
  'set_obligation_tier',
2985
3038
  {
@@ -0,0 +1,21 @@
1
+ // PURE: what my_settings prints (ADR-0074). Out of server.mjs so a test can reach it.
2
+ //
3
+ // Says ON/OFF per notice with the person's own words for it, and names the default when a setting has
4
+ // been changed from it — "off (default on)" is the line that answers "why am I not hearing about X?".
5
+ const one = (s) => String(s ?? '').replace(/\s+/g, ' ').trim().slice(0, 160)
6
+
7
+ export function renderSettings(view) {
8
+ const settings = Array.isArray(view?.settings) ? view.settings : []
9
+ const lines = ['NOTICES — what Agnoclast tells this person without being asked (sessions and desktop):']
10
+ for (const s of settings) {
11
+ const state = s.value ? 'ON ' : 'OFF'
12
+ const changed = s.value !== s.default ? ` (changed — default ${s.default ? 'on' : 'off'})` : ''
13
+ lines.push(` ${state} ${one(s.key)} — ${one(s.label)}${changed}`)
14
+ }
15
+ if (!settings.length) lines.push(' (none returned — the server may predate settings)')
16
+ lines.push('')
17
+ lines.push(`TIMEZONE: ${view?.timezone ? one(view.timezone) : 'not set'}`)
18
+ lines.push('')
19
+ lines.push('Change one only when the person asks: set_setting. They can also change these in Settings (console avatar menu, or ⌘, in the desktop app).')
20
+ return lines.join('\n')
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theronap/agnoclast-mcp",
3
- "version": "0.9.201",
3
+ "version": "0.9.203",
4
4
  "description": "Connect your AI assistant to Cortex — your org's projects, activity, gaps, and directives, scoped to you.",
5
5
  "type": "module",
6
6
  "bin": {