@agent-deck/backend 1.2.8 → 1.2.10
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/.tsbuildinfo +1 -1
- package/dist/lib/agent-deck-context.d.ts +1 -1
- package/dist/lib/agent-deck-context.d.ts.map +1 -1
- package/dist/lib/agent-deck-context.js +7 -26
- package/dist/lib/agent-deck-context.js.map +1 -1
- package/dist/lib/client-scope.d.ts +4 -0
- package/dist/lib/client-scope.d.ts.map +1 -1
- package/dist/lib/client-scope.js +15 -1
- package/dist/lib/client-scope.js.map +1 -1
- package/dist/mcp-server.d.ts +8 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +82 -216
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-session-binding.d.ts +3 -4
- package/dist/mcp-session-binding.d.ts.map +1 -1
- package/dist/mcp-session-binding.js +3 -10
- package/dist/mcp-session-binding.js.map +1 -1
- package/dist/routes/scope.d.ts.map +1 -1
- package/dist/routes/scope.js +78 -58
- package/dist/routes/scope.js.map +1 -1
- package/dist/scope/badge.d.ts +3 -0
- package/dist/scope/badge.d.ts.map +1 -0
- package/dist/scope/badge.js +23 -0
- package/dist/scope/badge.js.map +1 -0
- package/dist/scope/bindings-sidecar.d.ts +2 -5
- package/dist/scope/bindings-sidecar.d.ts.map +1 -1
- package/dist/scope/bindings-sidecar.js +13 -17
- package/dist/scope/bindings-sidecar.js.map +1 -1
- package/dist/scope/display.d.ts +3 -3
- package/dist/scope/display.d.ts.map +1 -1
- package/dist/scope/display.js +41 -31
- package/dist/scope/display.js.map +1 -1
- package/dist/scope/live-display-registry.d.ts +25 -0
- package/dist/scope/live-display-registry.d.ts.map +1 -0
- package/dist/scope/live-display-registry.js +64 -0
- package/dist/scope/live-display-registry.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -1
- package/package.json +2 -2
- package/static-ui/assets/index-CQoBRW1p.js +409 -0
- package/static-ui/assets/index-wleyGzod.css +1 -0
- package/static-ui/index.html +2 -2
- package/static-ui/assets/index-BnvBkGNu.js +0 -404
- package/static-ui/assets/index-D2upmaZj.css +0 -1
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AgentDeckContextError = void 0;
|
|
4
4
|
exports.resolveAgentDeckId = resolveAgentDeckId;
|
|
5
5
|
const shared_1 = require("@agent-deck/shared");
|
|
6
|
-
const repo_deck_1 = require("../scope/repo-deck");
|
|
7
6
|
class AgentDeckContextError extends Error {
|
|
8
7
|
constructor(message) {
|
|
9
8
|
super(message);
|
|
@@ -15,34 +14,16 @@ function headerValue(request, name) {
|
|
|
15
14
|
const value = request.headers[name];
|
|
16
15
|
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
17
16
|
}
|
|
18
|
-
/** Resolve which deck an agent request is scoped to (
|
|
17
|
+
/** Resolve which deck an agent request is scoped to (session deck id header only). */
|
|
19
18
|
async function resolveAgentDeckId(request, db) {
|
|
20
19
|
const deckIdHeader = headerValue(request, shared_1.AGENT_DECK_DECK_ID_HEADER);
|
|
21
|
-
if (deckIdHeader) {
|
|
22
|
-
|
|
23
|
-
if (!deck) {
|
|
24
|
-
throw new AgentDeckContextError(`Deck not found: ${deckIdHeader}`);
|
|
25
|
-
}
|
|
26
|
-
return deckIdHeader;
|
|
20
|
+
if (!deckIdHeader) {
|
|
21
|
+
throw new AgentDeckContextError('No bound deck — call bind_workspace with deckId (use get_decks to list decks) or switch_bound_deck');
|
|
27
22
|
}
|
|
28
|
-
const
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
manifest = await (0, repo_deck_1.loadRepoDeckManifest)(workspaceRoot);
|
|
33
|
-
}
|
|
34
|
-
catch (error) {
|
|
35
|
-
throw new AgentDeckContextError(error instanceof repo_deck_1.RepoDeckManifestError ? error.message : 'Failed to load repo deck manifest');
|
|
36
|
-
}
|
|
37
|
-
if (!manifest) {
|
|
38
|
-
throw new AgentDeckContextError(`No ${'.agent-deck/deck.yaml'} found in workspace: ${workspaceRoot}`);
|
|
39
|
-
}
|
|
40
|
-
const deck = await db.getDeck(manifest.deck_id);
|
|
41
|
-
if (!deck) {
|
|
42
|
-
throw new AgentDeckContextError(`deck_id in repo manifest not found in Agent Deck: ${manifest.deck_id}`);
|
|
43
|
-
}
|
|
44
|
-
return manifest.deck_id;
|
|
23
|
+
const deck = await db.getDeck(deckIdHeader);
|
|
24
|
+
if (!deck) {
|
|
25
|
+
throw new AgentDeckContextError(`Deck not found: ${deckIdHeader}`);
|
|
45
26
|
}
|
|
46
|
-
|
|
27
|
+
return deckIdHeader;
|
|
47
28
|
}
|
|
48
29
|
//# sourceMappingURL=agent-deck-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-deck-context.js","sourceRoot":"","sources":["../../src/lib/agent-deck-context.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"agent-deck-context.js","sourceRoot":"","sources":["../../src/lib/agent-deck-context.ts"],"names":[],"mappings":";;;AAiBA,gDAgBC;AAhCD,+CAA+D;AAG/D,MAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AALD,sDAKC;AAED,SAAS,WAAW,CAAC,OAAuB,EAAE,IAAY;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC;AAED,sFAAsF;AAC/E,KAAK,UAAU,kBAAkB,CACtC,OAAuB,EACvB,EAAmB;IAEnB,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,EAAE,kCAAyB,CAAC,CAAC;IACrE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,qBAAqB,CAC7B,oGAAoG,CACrG,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,qBAAqB,CAAC,mBAAmB,YAAY,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC"}
|
|
@@ -6,6 +6,10 @@ export declare function sanitizeServiceForAgent(service: Service): Service;
|
|
|
6
6
|
export declare function getClientScope(request: FastifyRequest): ClientScope;
|
|
7
7
|
export declare function isDashboardClient(request: FastifyRequest): boolean;
|
|
8
8
|
export declare function requireDashboardClient(request: FastifyRequest): void;
|
|
9
|
+
export declare function requireAgentClient(request: FastifyRequest): void;
|
|
10
|
+
export declare class AgentClientOnlyError extends Error {
|
|
11
|
+
constructor(message?: string);
|
|
12
|
+
}
|
|
9
13
|
export declare class DashboardOnlyError extends Error {
|
|
10
14
|
constructor(message?: string);
|
|
11
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-scope.d.ts","sourceRoot":"","sources":["../../src/lib/client-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,
|
|
1
|
+
{"version":3,"file":"client-scope.d.ts","sourceRoot":"","sources":["../../src/lib/client-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAIL,IAAI,EACJ,OAAO,EACR,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;AAchD,sEAAsE;AACtE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAUjE;AASD,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAMnE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAElE;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAIpE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAKhE;AAED,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,SAAuD;CAI3E;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,SAA4D;CAIhF;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,WAAW,EAClB,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI,CASN;AAED,qCAAqC;AACrC,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,WAAW,EAClB,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI,CAEN"}
|
package/dist/lib/client-scope.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DashboardOnlyError = void 0;
|
|
3
|
+
exports.DashboardOnlyError = exports.AgentClientOnlyError = void 0;
|
|
4
4
|
exports.sanitizeServiceForAgent = sanitizeServiceForAgent;
|
|
5
5
|
exports.getClientScope = getClientScope;
|
|
6
6
|
exports.isDashboardClient = isDashboardClient;
|
|
7
7
|
exports.requireDashboardClient = requireDashboardClient;
|
|
8
|
+
exports.requireAgentClient = requireAgentClient;
|
|
8
9
|
exports.applyDeckScope = applyDeckScope;
|
|
9
10
|
exports.applyDeckCredentialScope = applyDeckCredentialScope;
|
|
10
11
|
const shared_1 = require("@agent-deck/shared");
|
|
@@ -50,6 +51,19 @@ function requireDashboardClient(request) {
|
|
|
50
51
|
throw new DashboardOnlyError();
|
|
51
52
|
}
|
|
52
53
|
}
|
|
54
|
+
function requireAgentClient(request) {
|
|
55
|
+
const value = request.headers[shared_1.AGENT_DECK_CLIENT_HEADER];
|
|
56
|
+
if (typeof value !== 'string' || value.toLowerCase() !== shared_1.AGENT_DECK_AGENT_CLIENT) {
|
|
57
|
+
throw new AgentClientOnlyError();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
class AgentClientOnlyError extends Error {
|
|
61
|
+
constructor(message = 'This operation requires an Agent Deck agent client') {
|
|
62
|
+
super(message);
|
|
63
|
+
this.name = 'AgentClientOnlyError';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.AgentClientOnlyError = AgentClientOnlyError;
|
|
53
67
|
class DashboardOnlyError extends Error {
|
|
54
68
|
constructor(message = 'This operation requires the Agent Deck dashboard client') {
|
|
55
69
|
super(message);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-scope.js","sourceRoot":"","sources":["../../src/lib/client-scope.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"client-scope.js","sourceRoot":"","sources":["../../src/lib/client-scope.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-server.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export declare class AgentDeckMCPServer {
|
|
|
9
9
|
/** Per-session workspace + optional deck override (see mcp-session-binding.ts). */
|
|
10
10
|
private sessionBinding;
|
|
11
11
|
private activeSessionId;
|
|
12
|
+
/** Session badge from the backend registry (POST /api/scope/live-display response). */
|
|
13
|
+
private badgeBySession;
|
|
14
|
+
private lastTouchAtMs;
|
|
12
15
|
private get server();
|
|
13
16
|
constructor(port?: number, backendUrl?: string);
|
|
14
17
|
private createMcpServer;
|
|
@@ -16,7 +19,11 @@ export declare class AgentDeckMCPServer {
|
|
|
16
19
|
private getAgentHeaders;
|
|
17
20
|
private fetchDeck;
|
|
18
21
|
private buildBindingPayload;
|
|
19
|
-
private
|
|
22
|
+
private registerLiveDisplay;
|
|
23
|
+
private static readonly TOUCH_DEBOUNCE_MS;
|
|
24
|
+
/** Fire-and-forget lastActivityAt bump; only for sessions the registry knows. */
|
|
25
|
+
private touchLiveDisplay;
|
|
26
|
+
private unregisterLiveDisplay;
|
|
20
27
|
private callBackendAPI;
|
|
21
28
|
private getBoundDeckId;
|
|
22
29
|
private toolResult;
|
package/dist/mcp-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AASA,OAAO,OAA8B,MAAM,SAAS,CAAC;AAmBrD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,GAAG,CAAsB;IACjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAiC;IACjD,mFAAmF;IACnF,OAAO,CAAC,wBAAwB,CAAwB;IACxD,mFAAmF;IACnF,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,eAAe,CAAqB;IAC5C,uFAAuF;IACvF,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,aAAa,CAA6B;IAElD,OAAO,KAAK,MAAM,GAKjB;gBAEW,IAAI,GAAE,MAAa,EAAE,UAAU,GAAE,MAAgC;IAc7E,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;YAIT,SAAS;YAkBT,mBAAmB;YAgBnB,mBAAmB;IA+BjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAElD,iFAAiF;IACjF,OAAO,CAAC,gBAAgB;YAmBV,qBAAqB;YAUrB,cAAc;YAwCd,cAAc;IAQ5B,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,SAAS;IAIjB,6EAA6E;IAC7E,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,UAAU;IAkpBlB,OAAO,CAAC,cAAc;IA8MtB,OAAO,CAAC,WAAW;IA2CnB,OAAO,CAAC,kBAAkB;YAKZ,aAAa;YA2Db,uBAAuB;IAkB/B,KAAK;IAiCL,IAAI;CAeX"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -10,13 +10,9 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
|
10
10
|
const shared_1 = require("@agent-deck/shared");
|
|
11
11
|
const express_1 = __importDefault(require("express"));
|
|
12
12
|
const node_crypto_1 = require("node:crypto");
|
|
13
|
-
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
14
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
15
13
|
const zod_1 = require("zod");
|
|
16
|
-
const repo_deck_1 = require("./scope/repo-deck");
|
|
17
14
|
const version_1 = require("./lib/version");
|
|
18
15
|
const mcp_session_binding_1 = require("./mcp-session-binding");
|
|
19
|
-
const bindings_sidecar_1 = require("./scope/bindings-sidecar");
|
|
20
16
|
const agentClientHeaders = {
|
|
21
17
|
[shared_1.AGENT_DECK_CLIENT_HEADER]: shared_1.AGENT_DECK_AGENT_CLIENT,
|
|
22
18
|
Accept: 'application/json',
|
|
@@ -31,6 +27,9 @@ class AgentDeckMCPServer {
|
|
|
31
27
|
/** Per-session workspace + optional deck override (see mcp-session-binding.ts). */
|
|
32
28
|
sessionBinding;
|
|
33
29
|
activeSessionId;
|
|
30
|
+
/** Session badge from the backend registry (POST /api/scope/live-display response). */
|
|
31
|
+
badgeBySession = new Map();
|
|
32
|
+
lastTouchAtMs = new Map();
|
|
34
33
|
get server() {
|
|
35
34
|
if (!this.mcpServerForRegistration) {
|
|
36
35
|
throw new Error('Internal: MCP server not in registration context');
|
|
@@ -78,18 +77,22 @@ class AgentDeckMCPServer {
|
|
|
78
77
|
}
|
|
79
78
|
return body.data;
|
|
80
79
|
}
|
|
81
|
-
async buildBindingPayload(sessionId
|
|
80
|
+
async buildBindingPayload(sessionId) {
|
|
82
81
|
const snapshot = this.sessionBinding.getBinding(sessionId);
|
|
83
82
|
const deck = await this.callBackendAPI('/api/scope/deck');
|
|
83
|
+
const badge = this.badgeBySession.get(sessionId);
|
|
84
|
+
const cardCounts = deck ? (0, shared_1.countDeckCards)(deck) : { mcp: 0, credentials: 0, playbooks: 0 };
|
|
84
85
|
return {
|
|
85
86
|
workspaceRoot: snapshot.workspaceRoot,
|
|
86
87
|
deck_id: deck?.id,
|
|
87
88
|
deck_name: deck?.name,
|
|
88
|
-
deck_source: (0, mcp_session_binding_1.resolveDeckBindingSource)(snapshot
|
|
89
|
+
deck_source: (0, mcp_session_binding_1.resolveDeckBindingSource)(snapshot),
|
|
89
90
|
session_deck_override: this.sessionBinding.hasSessionDeckOverride(sessionId),
|
|
91
|
+
badge,
|
|
92
|
+
display_summary: (0, shared_1.formatDisplayLine)(deck?.name ?? null, cardCounts, { badge }),
|
|
90
93
|
};
|
|
91
94
|
}
|
|
92
|
-
async
|
|
95
|
+
async registerLiveDisplay(sessionId) {
|
|
93
96
|
const snapshot = this.sessionBinding.getBinding(sessionId);
|
|
94
97
|
if (!snapshot.workspaceRoot) {
|
|
95
98
|
return;
|
|
@@ -98,14 +101,51 @@ class AgentDeckMCPServer {
|
|
|
98
101
|
if (!deck?.id || !deck?.name) {
|
|
99
102
|
return;
|
|
100
103
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
const clientName = this.sessions.get(sessionId)?.server.server.getClientVersion()?.name;
|
|
105
|
+
const result = await this.callBackendAPI('/api/scope/live-display', {
|
|
106
|
+
method: 'POST',
|
|
107
|
+
headers: { 'Content-Type': 'application/json' },
|
|
108
|
+
body: JSON.stringify({
|
|
109
|
+
mcpSessionId: sessionId,
|
|
110
|
+
workspaceRoot: snapshot.workspaceRoot,
|
|
111
|
+
deckId: deck.id,
|
|
112
|
+
deckName: deck.name,
|
|
113
|
+
source: (0, mcp_session_binding_1.resolveDeckBindingSource)(snapshot),
|
|
114
|
+
clientName,
|
|
115
|
+
cardCounts: (0, shared_1.countDeckCards)(deck),
|
|
116
|
+
updatedAt: new Date().toISOString(),
|
|
117
|
+
}),
|
|
108
118
|
});
|
|
119
|
+
if (result && typeof result.badge === 'string') {
|
|
120
|
+
this.badgeBySession.set(sessionId, result.badge);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
static TOUCH_DEBOUNCE_MS = 5_000;
|
|
124
|
+
/** Fire-and-forget lastActivityAt bump; only for sessions the registry knows. */
|
|
125
|
+
touchLiveDisplay(sessionId) {
|
|
126
|
+
if (!this.badgeBySession.has(sessionId)) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
if (now - (this.lastTouchAtMs.get(sessionId) ?? 0) < AgentDeckMCPServer.TOUCH_DEBOUNCE_MS) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
this.lastTouchAtMs.set(sessionId, now);
|
|
134
|
+
void this.callBackendAPI(`/api/scope/live-display/${encodeURIComponent(sessionId)}/touch`, {
|
|
135
|
+
method: 'POST',
|
|
136
|
+
headers: { 'Content-Type': 'application/json' },
|
|
137
|
+
body: JSON.stringify({ at: new Date().toISOString() }),
|
|
138
|
+
}).catch(() => { });
|
|
139
|
+
}
|
|
140
|
+
async unregisterLiveDisplay(sessionId) {
|
|
141
|
+
try {
|
|
142
|
+
await this.callBackendAPI(`/api/scope/live-display/${encodeURIComponent(sessionId)}`, {
|
|
143
|
+
method: 'DELETE',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// Best effort when MCP session closes.
|
|
148
|
+
}
|
|
109
149
|
}
|
|
110
150
|
async callBackendAPI(endpoint, init = {}) {
|
|
111
151
|
try {
|
|
@@ -168,84 +208,52 @@ class AgentDeckMCPServer {
|
|
|
168
208
|
setupTools() {
|
|
169
209
|
this.registerTool("bind_workspace", {
|
|
170
210
|
title: "Bind Workspace",
|
|
171
|
-
description: "Bind this MCP session to a workspace root
|
|
211
|
+
description: "Bind this MCP session to a workspace root and deck. Use get_decks to list deck ids.",
|
|
172
212
|
inputSchema: {
|
|
173
213
|
workspaceRoot: zod_1.z.string(),
|
|
174
|
-
deckId: zod_1.z.string().uuid()
|
|
214
|
+
deckId: zod_1.z.string().uuid(),
|
|
175
215
|
},
|
|
176
216
|
}, async ({ workspaceRoot, deckId }) => {
|
|
177
217
|
try {
|
|
178
218
|
const sessionId = this.getSessionId();
|
|
179
219
|
this.sessionBinding.setWorkspace(sessionId, workspaceRoot);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
await this.writeBindingSidecar(sessionId);
|
|
185
|
-
return {
|
|
186
|
-
content: [{
|
|
187
|
-
type: "text",
|
|
188
|
-
text: JSON.stringify({
|
|
189
|
-
...payload,
|
|
190
|
-
deck_name: deck.name,
|
|
191
|
-
message: 'Session bound with deck override. .agent-deck/deck.yaml is unchanged; other MCP sessions can use a different deck at the same path.',
|
|
192
|
-
}, null, 2),
|
|
193
|
-
}],
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
this.sessionBinding.clearDeckId(sessionId);
|
|
197
|
-
const resolved = await fetch(`${this.backendUrl}/api/scope/resolve`, {
|
|
198
|
-
method: 'POST',
|
|
199
|
-
headers: { ...agentClientHeaders, 'Content-Type': 'application/json' },
|
|
200
|
-
body: JSON.stringify({ workspaceRoot }),
|
|
201
|
-
});
|
|
202
|
-
const body = (await resolved.json());
|
|
203
|
-
if (!body.success || !body.data) {
|
|
204
|
-
throw new Error(body.error ??
|
|
205
|
-
'Failed to resolve workspace deck. Pass deckId to bind without deck.yaml, or call setup_repo_deck.');
|
|
206
|
-
}
|
|
207
|
-
const { data } = body;
|
|
208
|
-
const payload = await this.buildBindingPayload(sessionId, data.manifest.deck_id);
|
|
209
|
-
await this.writeBindingSidecar(sessionId, data.manifest.deck_id);
|
|
220
|
+
const deck = await this.fetchDeck(deckId);
|
|
221
|
+
this.sessionBinding.setDeckId(sessionId, deckId);
|
|
222
|
+
await this.registerLiveDisplay(sessionId);
|
|
223
|
+
const payload = await this.buildBindingPayload(sessionId);
|
|
210
224
|
return {
|
|
211
225
|
content: [{
|
|
212
226
|
type: "text",
|
|
213
227
|
text: JSON.stringify({
|
|
214
228
|
...payload,
|
|
215
|
-
|
|
216
|
-
message: 'Session bound
|
|
229
|
+
deck_name: deck.name,
|
|
230
|
+
message: 'Session bound to deck.',
|
|
217
231
|
}, null, 2),
|
|
218
232
|
}],
|
|
219
233
|
};
|
|
220
234
|
}
|
|
221
235
|
catch (error) {
|
|
222
|
-
|
|
223
|
-
const hint = message.includes('deck.yaml') || message.includes('No .agent-deck')
|
|
224
|
-
? ' Pass deckId on bind_workspace, call setup_repo_deck, or get_repo_deck_status to diagnose.'
|
|
225
|
-
: '';
|
|
226
|
-
return {
|
|
227
|
-
content: [{ type: "text", text: JSON.stringify({ error: message + hint }, null, 2) }],
|
|
228
|
-
};
|
|
236
|
+
return this.toolError(error);
|
|
229
237
|
}
|
|
230
238
|
});
|
|
231
239
|
this.registerTool("switch_bound_deck", {
|
|
232
240
|
title: "Switch Bound Deck",
|
|
233
|
-
description: "Switch the deck for this MCP session only.
|
|
241
|
+
description: "Switch the deck for this MCP session only. Use when multiple agent sessions share the same workspace path.",
|
|
234
242
|
inputSchema: { deckId: zod_1.z.string().uuid() },
|
|
235
243
|
}, async ({ deckId }) => {
|
|
236
244
|
try {
|
|
237
245
|
const sessionId = this.getSessionId();
|
|
238
246
|
const deck = await this.fetchDeck(deckId);
|
|
239
247
|
this.sessionBinding.setDeckId(sessionId, deckId);
|
|
248
|
+
await this.registerLiveDisplay(sessionId);
|
|
240
249
|
const payload = await this.buildBindingPayload(sessionId);
|
|
241
|
-
await this.writeBindingSidecar(sessionId);
|
|
242
250
|
return {
|
|
243
251
|
content: [{
|
|
244
252
|
type: "text",
|
|
245
253
|
text: JSON.stringify({
|
|
246
254
|
...payload,
|
|
247
255
|
deck_name: deck.name,
|
|
248
|
-
message: 'Session deck switched. Other sessions
|
|
256
|
+
message: 'Session deck switched. Other sessions are unchanged.',
|
|
249
257
|
}, null, 2),
|
|
250
258
|
}],
|
|
251
259
|
};
|
|
@@ -256,31 +264,27 @@ class AgentDeckMCPServer {
|
|
|
256
264
|
});
|
|
257
265
|
this.registerTool("get_session_binding", {
|
|
258
266
|
title: "Get Session Binding",
|
|
259
|
-
description: "Show workspace and effective deck for this MCP session
|
|
267
|
+
description: "Show workspace and effective deck for this MCP session (session override or env default).",
|
|
260
268
|
inputSchema: {},
|
|
261
269
|
}, async () => {
|
|
262
270
|
try {
|
|
263
271
|
const sessionId = this.getSessionId();
|
|
264
272
|
const snapshot = this.sessionBinding.getBinding(sessionId);
|
|
265
|
-
let manifestDeckId;
|
|
266
|
-
if (snapshot.workspaceRoot && !snapshot.deckSource) {
|
|
267
|
-
const manifest = await (0, repo_deck_1.loadRepoDeckManifest)(snapshot.workspaceRoot);
|
|
268
|
-
manifestDeckId = manifest?.deck_id;
|
|
269
|
-
}
|
|
270
273
|
const deck = await this.callBackendAPI('/api/scope/deck');
|
|
274
|
+
const badge = this.badgeBySession.get(sessionId);
|
|
271
275
|
const cardCounts = deck ? (0, shared_1.countDeckCards)(deck) : { mcp: 0, credentials: 0, playbooks: 0 };
|
|
272
|
-
const displaySummary = (0, shared_1.formatDisplayLine)(deck?.name ?? null, cardCounts);
|
|
276
|
+
const displaySummary = (0, shared_1.formatDisplayLine)(deck?.name ?? null, cardCounts, { badge });
|
|
273
277
|
return {
|
|
274
278
|
content: [{
|
|
275
279
|
type: "text",
|
|
276
280
|
text: JSON.stringify({
|
|
277
281
|
workspaceRoot: snapshot.workspaceRoot,
|
|
278
|
-
|
|
282
|
+
session_deck_id: snapshot.deckId,
|
|
279
283
|
session_deck_source: snapshot.deckSource,
|
|
280
|
-
repo_manifest_deck_id: manifestDeckId,
|
|
281
284
|
effective_deck_id: deck?.id,
|
|
282
285
|
effective_deck_name: deck?.name,
|
|
283
|
-
effective_deck_source: (0, mcp_session_binding_1.resolveDeckBindingSource)(snapshot
|
|
286
|
+
effective_deck_source: (0, mcp_session_binding_1.resolveDeckBindingSource)(snapshot),
|
|
287
|
+
badge,
|
|
284
288
|
display_summary: displaySummary,
|
|
285
289
|
}, null, 2),
|
|
286
290
|
}],
|
|
@@ -290,147 +294,6 @@ class AgentDeckMCPServer {
|
|
|
290
294
|
return this.toolError(error);
|
|
291
295
|
}
|
|
292
296
|
});
|
|
293
|
-
this.registerTool("get_repo_deck_status", {
|
|
294
|
-
title: "Get Repo Deck Status",
|
|
295
|
-
description: "Check whether .agent-deck/deck.yaml exists in a workspace and whether it links to a valid deck",
|
|
296
|
-
inputSchema: { workspaceRoot: zod_1.z.string() },
|
|
297
|
-
}, async ({ workspaceRoot }) => {
|
|
298
|
-
try {
|
|
299
|
-
const filePath = (0, repo_deck_1.repoDeckManifestFilePath)(workspaceRoot);
|
|
300
|
-
const manifest = await (0, repo_deck_1.loadRepoDeckManifest)(workspaceRoot);
|
|
301
|
-
if (!manifest) {
|
|
302
|
-
const decks = await this.callBackendAPI('/api/decks');
|
|
303
|
-
return {
|
|
304
|
-
content: [{
|
|
305
|
-
type: "text",
|
|
306
|
-
text: JSON.stringify({
|
|
307
|
-
status: 'missing',
|
|
308
|
-
workspaceRoot,
|
|
309
|
-
expectedPath: shared_1.REPO_DECK_MANIFEST_PATH,
|
|
310
|
-
message: 'No .agent-deck/deck.yaml found. Use setup_repo_deck to create one.',
|
|
311
|
-
availableDecks: Array.isArray(decks)
|
|
312
|
-
? decks.map((d) => ({ id: d.id, name: d.name }))
|
|
313
|
-
: decks,
|
|
314
|
-
}, null, 2),
|
|
315
|
-
}],
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
const resolved = await fetch(`${this.backendUrl}/api/scope/resolve`, {
|
|
319
|
-
method: 'POST',
|
|
320
|
-
headers: { ...agentClientHeaders, 'Content-Type': 'application/json' },
|
|
321
|
-
body: JSON.stringify({ workspaceRoot }),
|
|
322
|
-
});
|
|
323
|
-
const body = (await resolved.json());
|
|
324
|
-
return {
|
|
325
|
-
content: [{
|
|
326
|
-
type: "text",
|
|
327
|
-
text: JSON.stringify({
|
|
328
|
-
status: body.success ? 'ok' : 'invalid',
|
|
329
|
-
workspaceRoot,
|
|
330
|
-
filePath,
|
|
331
|
-
manifest,
|
|
332
|
-
deck: body.data?.deck,
|
|
333
|
-
error: body.success ? undefined : body.error,
|
|
334
|
-
}, null, 2),
|
|
335
|
-
}],
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
catch (error) {
|
|
339
|
-
return {
|
|
340
|
-
content: [{ type: "text", text: JSON.stringify({ error: String(error) }, null, 2) }],
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
this.registerTool("setup_repo_deck", {
|
|
345
|
-
title: "Setup Repo Deck",
|
|
346
|
-
description: "Create or verify .agent-deck/deck.yaml in a repo. Links the workspace to an Agent Deck by deck_id. Optionally writes the file.",
|
|
347
|
-
inputSchema: {
|
|
348
|
-
workspaceRoot: zod_1.z.string(),
|
|
349
|
-
deckId: zod_1.z.string().uuid().optional(),
|
|
350
|
-
deckName: zod_1.z.string().optional(),
|
|
351
|
-
writeFile: zod_1.z.boolean().optional(),
|
|
352
|
-
},
|
|
353
|
-
}, async ({ workspaceRoot, deckId, deckName, writeFile = true }) => {
|
|
354
|
-
try {
|
|
355
|
-
const sessionId = this.getSessionId();
|
|
356
|
-
const existing = await (0, repo_deck_1.loadRepoDeckManifest)(workspaceRoot);
|
|
357
|
-
if (existing) {
|
|
358
|
-
this.sessionBinding.setWorkspace(sessionId, workspaceRoot);
|
|
359
|
-
const resolved = await fetch(`${this.backendUrl}/api/scope/resolve`, {
|
|
360
|
-
method: 'POST',
|
|
361
|
-
headers: { ...agentClientHeaders, 'Content-Type': 'application/json' },
|
|
362
|
-
body: JSON.stringify({ workspaceRoot }),
|
|
363
|
-
});
|
|
364
|
-
const body = (await resolved.json());
|
|
365
|
-
if (!body.success || !body.data) {
|
|
366
|
-
throw new Error(body.error ?? 'Existing manifest is invalid');
|
|
367
|
-
}
|
|
368
|
-
return {
|
|
369
|
-
content: [{
|
|
370
|
-
type: "text",
|
|
371
|
-
text: JSON.stringify({
|
|
372
|
-
status: 'existing',
|
|
373
|
-
workspaceRoot,
|
|
374
|
-
manifestPath: body.data.manifestPath,
|
|
375
|
-
deck_id: body.data.manifest.deck_id,
|
|
376
|
-
deck_name: body.data.deck.name,
|
|
377
|
-
message: 'Workspace already linked. Session bound to this deck.',
|
|
378
|
-
}, null, 2),
|
|
379
|
-
}],
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
if (!deckId) {
|
|
383
|
-
const decks = await this.callBackendAPI('/api/decks');
|
|
384
|
-
return {
|
|
385
|
-
content: [{
|
|
386
|
-
type: "text",
|
|
387
|
-
text: JSON.stringify({
|
|
388
|
-
status: 'needs_deck_id',
|
|
389
|
-
workspaceRoot,
|
|
390
|
-
expectedPath: shared_1.REPO_DECK_MANIFEST_PATH,
|
|
391
|
-
message: 'Pick a deck id from the dashboard (My Decks → copy icon) and call setup_repo_deck again with deckId.',
|
|
392
|
-
availableDecks: Array.isArray(decks)
|
|
393
|
-
? decks.map((d) => ({ id: d.id, name: d.name }))
|
|
394
|
-
: decks,
|
|
395
|
-
}, null, 2),
|
|
396
|
-
}],
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
const deck = await this.callBackendAPI(`/api/decks/${deckId}`);
|
|
400
|
-
if (!deck?.id) {
|
|
401
|
-
throw new Error(`Deck not found: ${deckId}`);
|
|
402
|
-
}
|
|
403
|
-
const content = (0, repo_deck_1.formatRepoDeckManifest)(deckId, deckName ?? deck.name);
|
|
404
|
-
const dirPath = node_path_1.default.join(node_path_1.default.resolve(workspaceRoot), '.agent-deck');
|
|
405
|
-
const filePath = (0, repo_deck_1.repoDeckManifestFilePath)(workspaceRoot);
|
|
406
|
-
if (writeFile) {
|
|
407
|
-
await promises_1.default.mkdir(dirPath, { recursive: true });
|
|
408
|
-
await promises_1.default.writeFile(filePath, content, 'utf8');
|
|
409
|
-
}
|
|
410
|
-
this.sessionBinding.setWorkspace(sessionId, workspaceRoot);
|
|
411
|
-
return {
|
|
412
|
-
content: [{
|
|
413
|
-
type: "text",
|
|
414
|
-
text: JSON.stringify({
|
|
415
|
-
status: writeFile ? 'created' : 'preview',
|
|
416
|
-
workspaceRoot,
|
|
417
|
-
filePath,
|
|
418
|
-
deck_id: deckId,
|
|
419
|
-
deck_name: deck.name,
|
|
420
|
-
manifestContent: content,
|
|
421
|
-
message: writeFile
|
|
422
|
-
? 'Created .agent-deck/deck.yaml and bound this session to the deck.'
|
|
423
|
-
: 'Preview only — set writeFile true to write the file.',
|
|
424
|
-
}, null, 2),
|
|
425
|
-
}],
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
catch (error) {
|
|
429
|
-
return {
|
|
430
|
-
content: [{ type: "text", text: JSON.stringify({ error: String(error) }, null, 2) }],
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
297
|
// Get all decks (metadata only; credentials stripped unless bound)
|
|
435
298
|
this.registerTool("get_decks", {
|
|
436
299
|
title: "Get Decks",
|
|
@@ -451,7 +314,7 @@ class AgentDeckMCPServer {
|
|
|
451
314
|
});
|
|
452
315
|
this.registerTool("get_bound_deck", {
|
|
453
316
|
title: "Get Bound Deck",
|
|
454
|
-
description: "Get the deck bound to this session (session deckId
|
|
317
|
+
description: "Get the deck bound to this session (session deckId or env AGENT_DECK_DECK_ID)",
|
|
455
318
|
inputSchema: {},
|
|
456
319
|
}, async () => {
|
|
457
320
|
try {
|
|
@@ -1111,7 +974,7 @@ class AgentDeckMCPServer {
|
|
|
1111
974
|
}
|
|
1112
975
|
});
|
|
1113
976
|
this.server.resource("bound_deck", "agent-deck://bound-deck", {
|
|
1114
|
-
description: "Deck bound
|
|
977
|
+
description: "Deck bound to this MCP session",
|
|
1115
978
|
mimeType: "application/json"
|
|
1116
979
|
}, async () => {
|
|
1117
980
|
try {
|
|
@@ -1230,8 +1093,9 @@ class AgentDeckMCPServer {
|
|
|
1230
1093
|
async handleMcpPost(req, res) {
|
|
1231
1094
|
const sessionIdHeader = this.getSessionIdHeader(req);
|
|
1232
1095
|
const existing = sessionIdHeader ? this.sessions.get(sessionIdHeader) : undefined;
|
|
1233
|
-
if (existing) {
|
|
1096
|
+
if (existing && sessionIdHeader) {
|
|
1234
1097
|
this.activeSessionId = sessionIdHeader;
|
|
1098
|
+
this.touchLiveDisplay(sessionIdHeader);
|
|
1235
1099
|
await existing.transport.handleRequest(req, res, req.body);
|
|
1236
1100
|
return;
|
|
1237
1101
|
}
|
|
@@ -1263,6 +1127,9 @@ class AgentDeckMCPServer {
|
|
|
1263
1127
|
if (sessionId) {
|
|
1264
1128
|
this.sessions.delete(sessionId);
|
|
1265
1129
|
this.sessionBinding.clearSession(sessionId);
|
|
1130
|
+
this.badgeBySession.delete(sessionId);
|
|
1131
|
+
this.lastTouchAtMs.delete(sessionId);
|
|
1132
|
+
void this.unregisterLiveDisplay(sessionId);
|
|
1266
1133
|
}
|
|
1267
1134
|
};
|
|
1268
1135
|
await server.connect(transport);
|
|
@@ -1284,6 +1151,7 @@ class AgentDeckMCPServer {
|
|
|
1284
1151
|
return;
|
|
1285
1152
|
}
|
|
1286
1153
|
this.activeSessionId = sessionId;
|
|
1154
|
+
this.touchLiveDisplay(sessionId);
|
|
1287
1155
|
await session.transport.handleRequest(req, res);
|
|
1288
1156
|
}
|
|
1289
1157
|
async start() {
|
|
@@ -1293,12 +1161,10 @@ class AgentDeckMCPServer {
|
|
|
1293
1161
|
this.app.listen(this.port, () => {
|
|
1294
1162
|
console.log(`✅ Agent Deck MCP Server is ready to accept connections`);
|
|
1295
1163
|
console.log(`📋 Available tools:`);
|
|
1296
|
-
console.log(` - bind_workspace: Bind session to workspace
|
|
1164
|
+
console.log(` - bind_workspace: Bind session to workspace + deck (deckId required)`);
|
|
1297
1165
|
console.log(` - switch_bound_deck: Switch deck for this session only`);
|
|
1298
1166
|
console.log(` - get_session_binding: Show session workspace + effective deck`);
|
|
1299
|
-
console.log(` -
|
|
1300
|
-
console.log(` - setup_repo_deck: Create .agent-deck/deck.yaml for a repo`);
|
|
1301
|
-
console.log(` - get_bound_deck: Get workspace-bound deck`);
|
|
1167
|
+
console.log(` - get_bound_deck: Get session-bound deck`);
|
|
1302
1168
|
console.log(` - list_service_tools: List tools for a specific service`);
|
|
1303
1169
|
console.log(` - call_service_tool: Call a tool on a service`);
|
|
1304
1170
|
console.log(`📋 Available resources:`);
|