Skip to content

Agents over MCP, phase 3: Identity Applications - #7

Merged
jcombs-pointblue merged 11 commits into
mainfrom
feature/mcp-phase3
Oct 31, 2026
Merged

jcombs-pointblue merged 11 commits into
mainfrom
feature/mcp-phase3

Conversation

@jcombs-pointblue

Copy link
Copy Markdown
Contributor

Phase 3 of docs/MCP.md: Identity Applications tools for agent keys.

Stacked on #6 (base feature/mcp-phase2), and needs DirXMLDev 0.60.0: it pins dirxmldev.version 0.60.0, which carries the new IdApps client (PointBlueTechnology/DirXMLDev#118). CI fails until that release exists, because it downloads core's released jar. Merge order: #4, #5, #6; DirXMLDev #118 and its 0.60.0 release; then this.

What's in it

  • Settings > Directory > Identity Applications for agents (PUT /api/v2/directories/{id}/apps): the address, the OSP client (rbpmrest) and its secret. The secret is sealed, never returned, and required: OSP gives refresh tokens only to a client with a secret.
  • Authorizing (AgentApps):
    • Making a key with a password also does one OSP password grant (the person's DN works as the username, checked on the lab). The key keeps only the refresh token, sealed with the console's key, and shows authorized.
    • Access tokens stay in memory and are renewed with the refresh token (core's IdApps), so oidpInstanceData doesn't grow per call.
    • A refused refresh (400/401) marks the key authorize-again. Its tools then answer authorize-again until the owner uses POST /api/v2/agent-keys/{id}/authorize {password} (Agent keys > Authorize).
    • If the grant fails, the key is still made, and the answer carries appsProblem.
    • Keys made with single sign-on get no Identity Applications tools: the console has no password to sign in with.
  • Tools, as the person:
    • reads: my_tasks, task, my_requests, request_detail, assignments, request_definitions, request_definition;
    • changes, for a key that may make changes (editor or operator): approve_tasks, deny_tasks, start_request, request_role, request_resource.
    • Changes follow the approval setting like any other: an approval runs the Identity Applications call then, with the key's token. They're audited as apps.<tool>.
  • Agent keys page: an Identity Applications column (authorized / authorize again / no) with an Authorize dialog, and a note in the new-key form.

Calls checked on the lab before building on them

  • POST /assignments/list {"dn"} gives a person's assignments.
  • GET /IDMProv/rest/catalog/prds?q=* gives the request definitions. On idm254 the catalog still listed two PRDs deleted from the vault (including my earlier second-approver test PRD, which is gone from the vault), so request_definition (the permission index) is the check. This is recorded in core's docs/idapps-rest.md §11.

Decision for you

Identity Applications changes need the key to carry editor or operator, so a read-only key can't approve tasks. Say if you'd rather give them their own key option.

Tests

  • AgentsTest.identityApplicationsAsThePerson, against a stand-in for OSP and Identity Applications:
    • the client secret is required and never returned;
    • one password grant, with the DN, and the refresh token sealed on disk;
    • the tools offered by role;
    • reads renew the access token with the refresh token, never a second password sign-in;
    • approve_tasks waits, is approved, and the task call is made;
    • a refused refresh gives authorize-again, and authorizing with the password restores it.
  • All 166 server tests and 53 UI tests pass; npm run build passes. This was run with core 0.60.0-SNAPSHOT installed locally.
  • Live on idm254 with LiveAgentsAppsCheck, all steps passing:
    • the applications admin, added for the run to a scratch group mapped to editor, signed in directly and made a key, authorized with one OSP grant;
    • my_tasks, my_requests, assignments (9) and request_definitions (12) answered as the user;
    • approve_tasks for a task that doesn't exist waited, was approved, and Identity Applications refused it. This runs the whole path without starting a workflow;
    • the key was revoked, the membership removed and the container deleted.

🤖 Generated with Claude Code

jcombs-pointblue and others added 8 commits October 30, 2026 13:19
eDirectory refuses the proxied-authorization control for disabled and
expired accounts, but accepts it for an account locked by intruder
detection: on the lab (9.3.3) the locked account's own bind returned 53
while a proxied read as it succeeded. So a locked person could sign in
through single sign-on and act in the console.

OidcLogin's search now reads lockedByIntruder and loginIntruderResetTime
and refuses with the new code "locked". A lock whose reset time has
passed counts as over: eDirectory leaves the attribute TRUE after the
reset until the next login (checked on the lab with a real lockout).
A single sign-on session reaching another server (Server.on) checks the
same on that server before acting as the person there. The service
account check covers reading the two attributes, and the live check
LivePhase3Check covers a locked and a lapsed account.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent keys (docs/MCP.md): a person signed in directly or with single
sign-on makes a key under their name > Agent keys (password typed again,
or a sign-in within 10 minutes). dc_ + 32 random bytes, SHA-256 kept in
agents/keys.json on the data volume, outside the versioned configuration
and outside backups. Viewer always, editor and operator only if the person
has them, never admin, no task presets. 30 days by default, at most the
directory's longest life (90) and 14 days with single sign-on; 14 days
unused stops a key. Admins list and revoke everyone's.

A key's calls run as the person the way single sign-on does: the service
account's connection with the proxied-authorization control, and the
engine opened acting as them. On every call the console reads the
person's account as the service account and refuses a locked (intruder
detection: eDirectory accepts the control for it), disabled or expired
one; direct sign-in grants come from that read, single sign-on grants
from the last sign-in.

/mcp: JSON-RPC 2.0, Streamable HTTP, stateless. 22 read tools, each an
in-process call to the existing API with the key's session (Mcp.Local),
so roles, scopes and rights stay the API's. A key works only there.

Per directory (Settings > Directory > Agent keys): on/off (off by
default), longest life, and approveChanges, required by default, for the
change tools of phase 2. Audit: agent-key.create/revoke/use, and the
actor's agent (label and id) on entries made with a key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A test user made for the run (no password) signs in through a fake
provider, makes a key, and its agent calls /mcp: whoami, reads under the
control, the object inspector, Identity Manager under the user's rights;
then a locked, an unlocked and a disabled account, and a revoked key. The
container is deleted at the end. Passed on idm254 (eDirectory 9.3.3, IDM
4.10.2), 2026-10-30.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change tools, offered only when the key has the role, its scopes
reaching the object: enable, disable and unlock an account, add to and
remove from a group (editor); start and stop a driver, run and abort a
job, resynchronize a driver, migrate an object into the application and
objects from it (operator); change_status.

With the directory's approveChanges on (the default) a change is kept as
pending (AgentChanges, in memory, an hour) and the agent gets a link,
/agent-keys?change=<id>. The key's owner reviews it there and approves
it (typing the directory's name on production) or declines it; approving
makes the API call then, in-process, as the key, checked again. With
approval off the call is made at once, with confirm as the production
directory's name. Audited as agent-change.request/approve/decline, and the
change itself as the agent.

Account changes and unlock now explain eDirectory's "no such attribute"
answer to a write without rights under proxied authorization as
insufficient-rights, as object edits already did.

LiveAgentsCheck covers approving, declining and approval off; passed on
idm254 2026-10-30.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A directory with an Identity Applications address (Settings > Directory:
address, OSP client, its secret sealed) offers its keys Identity
Applications tools. Making a key with a password signs its person in to
Identity Applications once (OSP password grant, with their DN); the key
keeps only the refresh token, sealed with the console's key, and access
tokens stay in memory (AgentApps, on DirXMLDev 0.60.0's IdApps). When
the refresh token stops working the tools answer authorize-again until
the person authorizes the key again (POST /api/v2/agent-keys/{id}/authorize).

Tools, as the person: my_tasks, task, my_requests, request_detail,
assignments, request_definitions, request_definition; and, for a key that
may make changes (editor or operator), approve_tasks, deny_tasks,
start_request, request_role, request_resource, which follow the approval
setting like any change and are audited as apps.<tool>.

LiveAgentsAppsCheck passed on idm254 2026-10-30. Pins DirXMLDev 0.60.0,
which carries IdApps (DirXMLDev#118).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Identity Applications tools on DirXMLDev 0.60.0's new IdApps calls:
search_permissions and who_has (assignments/identities; only people under
the applications' user search root), others_tasks, request_tasks; and,
for a key that may make changes, revoke_role and revoke_resource (the
resource's assignment instance ids looked up first; a person who does not
hold it is refused), retract_request, and form_data on approve/deny_tasks
(through tasks/v2). Changes follow the approval setting like the others.

LiveAgentsAppsCheck: a scratch role made through the catalog API and a
holder in the user search root; request_role approved, who_has lists the
holder, revoke_role approved, the role gone; the role, user and the run's
request objects (found by their reasons) removed. Passed on idm254
2026-10-30.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jcombs-pointblue

Copy link
Copy Markdown
Contributor Author

Added in 1a5d9ce: the next Identity Applications tools.

  • Reads: search_permissions, who_has, others_tasks, request_tasks.
  • Changes, for a key that may make changes: revoke_role, revoke_resource, retract_request, and form_data on approve_tasks and deny_tasks (through tasks/v2).

They're built on the new IdApps calls in PointBlueTechnology/DirXMLDev#118. The calls are documented in the private PointBlueTechnology/idapps-rest repository.

Live on idm254 with LiveAgentsAppsCheck, all steps passing:

  • a scratch role made through the catalog API, and a holder inside the user search root;
  • request_role approved, and who_has listed the holder;
  • revoke_role approved, and the role was gone;
  • the role, the user and the run's request objects removed afterwards.

Tests: 167 server tests pass.

🤖 Generated with Claude Code

jcombs-pointblue and others added 2 commits October 30, 2026 19:33
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	console-server/src/main/java/com/pointblue/console/server/http/Agents.java
#	console-server/src/main/java/com/pointblue/console/server/http/Mcp.java
#	console-server/src/main/java/com/pointblue/console/server/http/Server.java
#	console-server/src/test/java/com/pointblue/console/server/http/AgentsTest.java
#	console-server/src/test/java/com/pointblue/console/server/live/LiveAgentsCheck.java
#	console-web/src/api.ts
#	console-web/src/help/content.ts
#	console-web/src/pages/AgentKeysPage.tsx
#	console-web/src/pages/SettingsPage.tsx
#	docs/API.md
#	docs/MCP.md
#	docs/STATUS.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jcombs-pointblue
jcombs-pointblue changed the base branch from feature/mcp-phase2 to main October 31, 2026 00:38
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	console-server/src/main/java/com/pointblue/console/server/http/AgentChanges.java
#	console-server/src/main/java/com/pointblue/console/server/http/Agents.java
#	console-server/src/main/java/com/pointblue/console/server/http/Mcp.java
#	console-server/src/main/java/com/pointblue/console/server/http/Server.java
#	console-server/src/test/java/com/pointblue/console/server/http/AgentsTest.java
#	console-web/src/help/content.ts
#	console-web/src/pages/AgentKeysPage.tsx
#	docs/API.md
#	docs/MCP.md
#	docs/STATUS.md
@jcombs-pointblue
jcombs-pointblue merged commit 54bdbee into main Oct 31, 2026
1 check passed
@jcombs-pointblue
jcombs-pointblue deleted the feature/mcp-phase3 branch October 31, 2026 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant