agentschat-mcp 0.36.10 ā 0.36.12
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/CHANGELOG.md +61 -0
- package/README.md +28 -12
- package/codex/README.md +25 -2
- package/dist/server.js +42 -3
- package/package.json +3 -2
- package/scripts/ensure-grok-wakes.mjs +138 -7
- package/scripts/example-agy-mcp-wrapper.sh +41 -0
- package/scripts/example-url-wake-ensure.sh +37 -2
- package/scripts/example-url-wake-receiver.mjs +81 -5
- package/skills/grok-wake-keepalive.md +45 -13
- package/skills/hermes-host-keepalive.md +33 -12
- package/skills/onboarding.md +132 -22
- package/skills/url-wake-keepalive.md +64 -6
- package/src/identity-guard.ts +37 -0
- package/src/server.ts +31 -2
package/src/server.ts
CHANGED
|
@@ -79,6 +79,9 @@ import {
|
|
|
79
79
|
parseGuardRecord,
|
|
80
80
|
emptyGuardRecord,
|
|
81
81
|
IDENTITY_GUARD_FILENAME,
|
|
82
|
+
expectedAgentIdFromEnv,
|
|
83
|
+
expectedAgentIdViolation,
|
|
84
|
+
EXPECT_PIN_EXEMPT_TOOLS,
|
|
82
85
|
type GuardIdentity,
|
|
83
86
|
type IdentityGuardRecord,
|
|
84
87
|
} from "./identity-guard.ts";
|
|
@@ -613,6 +616,16 @@ const guardBootIdentity: GuardIdentity = {
|
|
|
613
616
|
if (AGENT_ID) persistGuardRecord(guardRecord);
|
|
614
617
|
}
|
|
615
618
|
|
|
619
|
+
// Optional expected-id pin (AGENTSCHAT_EXPECT_AGENT_ID / AGENTCHAT_EXPECT_AGENT_ID):
|
|
620
|
+
// a per-bot launcher declares which agent this process must be. Mismatch ā loud
|
|
621
|
+
// stderr now, and write tools refuse at call time (checked against the LIVE id,
|
|
622
|
+
// so a switch_profile to the right profile clears it).
|
|
623
|
+
const EXPECTED_AGENT_ID = expectedAgentIdFromEnv(process.env);
|
|
624
|
+
{
|
|
625
|
+
const v = AGENT_ID ? expectedAgentIdViolation(EXPECTED_AGENT_ID, AGENT_ID) : null;
|
|
626
|
+
if (v) process.stderr.write(`\n[agentchat] šØ ${v}\n\n`);
|
|
627
|
+
}
|
|
628
|
+
|
|
616
629
|
// Update display name if provided via CLI
|
|
617
630
|
if (cliArgs.name && profile.display_name !== cliArgs.name) {
|
|
618
631
|
profile.display_name = cliArgs.name;
|
|
@@ -2248,6 +2261,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2248
2261
|
return { content: [{ type: "text", text: `šØ ${identityGateMessage}` }], isError: true };
|
|
2249
2262
|
}
|
|
2250
2263
|
|
|
2264
|
+
// Expected-id pin: refuse writes while the live identity is not the one the
|
|
2265
|
+
// launcher pinned. whoami + switch_profile stay open so the agent can fix it.
|
|
2266
|
+
if (EXPECTED_AGENT_ID && !EXPECT_PIN_EXEMPT_TOOLS.has(name) && TOOL_ANNOTATIONS[name]?.readOnlyHint !== true) {
|
|
2267
|
+
const pinViolation = expectedAgentIdViolation(EXPECTED_AGENT_ID, AGENT_ID);
|
|
2268
|
+
if (pinViolation) {
|
|
2269
|
+
return { content: [{ type: "text", text: `šØ ${pinViolation}` }], isError: true };
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2251
2273
|
if (name === "list_skills") {
|
|
2252
2274
|
const { chat_id } = (args || {}) as { chat_id?: string };
|
|
2253
2275
|
const out: any = {
|
|
@@ -3169,7 +3191,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3169
3191
|
const wasGated = identityGateMessage !== "";
|
|
3170
3192
|
const text = `Profile: ${profile.display_name || AGENT_ID}\nAgent ID: ${AGENT_ID}\nServer: ${REST_URL}\nWeb chat: ${REST_URL}/chat/${encodeURIComponent(AGENT_ID)}\nWebSocket: ${wsState}${sessionId ? `\nSession: ${sessionId.slice(0, 12)}...` : ""}\n${healthLine}\n${authLine}\n${claimedLine}${claimHint ? `\n${claimHint}` : ""}\nCapabilities: ${CAPABILITIES.join(", ")}\nProfile file: ${activeProfileFile ?? (anonymousMode ? "(none ā anonymous, no profile written)" : "(none ā credentials from environment)")}`;
|
|
3171
3193
|
if (wasGated) confirmLiveIdentityTrusted();
|
|
3172
|
-
|
|
3194
|
+
const pinViolation = expectedAgentIdViolation(EXPECTED_AGENT_ID, AGENT_ID);
|
|
3195
|
+
const pinLine = EXPECTED_AGENT_ID
|
|
3196
|
+
? `\nExpected agent (AGENTCHAT_EXPECT_AGENT_ID): ${EXPECTED_AGENT_ID} ā ${pinViolation ? "MISMATCH, write tools refused" : "ok"}`
|
|
3197
|
+
: "";
|
|
3198
|
+
return { content: [{ type: "text", text: gateNotice + text + pinLine }] };
|
|
3173
3199
|
}
|
|
3174
3200
|
|
|
3175
3201
|
if (name === "list_channels") {
|
|
@@ -3367,7 +3393,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
3367
3393
|
const newProfile = readIdentityProfile(targetFile);
|
|
3368
3394
|
applyIdentityFromProfile(newProfile, targetFile);
|
|
3369
3395
|
|
|
3370
|
-
|
|
3396
|
+
const pinNote = EXPECTED_AGENT_ID && AGENT_ID !== EXPECTED_AGENT_ID
|
|
3397
|
+
? `\nšØ Still not the expected agent "${EXPECTED_AGENT_ID}" (AGENTCHAT_EXPECT_AGENT_ID) ā write tools stay refused.`
|
|
3398
|
+
: "";
|
|
3399
|
+
return { content: [{ type: "text", text: `Switched to profile "${profile_name}" (${AGENT_ID}). Reconnecting...\nScope: this switch applies only to THIS MCP process. It is not saved ā a new or restarted MCP process starts again from its launch profile (--profile / AGENTSCHAT_PROFILE). Re-check with whoami at the start of every wake.${pinNote}` }] };
|
|
3371
3400
|
}
|
|
3372
3401
|
|
|
3373
3402
|
if (name === "list_channel_docs") {
|