@dobbyai/mcp-external 1.0.3 → 1.1.0
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/__tests__/agent-mail-tools.test.d.ts +8 -0
- package/dist/__tests__/agent-mail-tools.test.d.ts.map +1 -0
- package/dist/__tests__/agent-mail-tools.test.js +262 -0
- package/dist/__tests__/agent-mail-tools.test.js.map +1 -0
- package/dist/__tests__/annotations.test.d.ts +8 -0
- package/dist/__tests__/annotations.test.d.ts.map +1 -0
- package/dist/__tests__/annotations.test.js +108 -0
- package/dist/__tests__/annotations.test.js.map +1 -0
- package/dist/__tests__/auth.test.d.ts +7 -0
- package/dist/__tests__/auth.test.d.ts.map +1 -0
- package/dist/__tests__/auth.test.js +116 -0
- package/dist/__tests__/auth.test.js.map +1 -0
- package/dist/__tests__/integration/protocol.test.d.ts +8 -0
- package/dist/__tests__/integration/protocol.test.d.ts.map +1 -0
- package/dist/__tests__/integration/protocol.test.js +104 -0
- package/dist/__tests__/integration/protocol.test.js.map +1 -0
- package/dist/__tests__/mcp-integrations.test.d.ts +8 -0
- package/dist/__tests__/mcp-integrations.test.d.ts.map +1 -0
- package/dist/__tests__/mcp-integrations.test.js +375 -0
- package/dist/__tests__/mcp-integrations.test.js.map +1 -0
- package/dist/__tests__/memory-graph-tools.test.d.ts +8 -0
- package/dist/__tests__/memory-graph-tools.test.d.ts.map +1 -0
- package/dist/__tests__/memory-graph-tools.test.js +265 -0
- package/dist/__tests__/memory-graph-tools.test.js.map +1 -0
- package/dist/__tests__/schedule-tools.test.d.ts +8 -0
- package/dist/__tests__/schedule-tools.test.d.ts.map +1 -0
- package/dist/__tests__/schedule-tools.test.js +290 -0
- package/dist/__tests__/schedule-tools.test.js.map +1 -0
- package/dist/__tests__/tiers.test.d.ts +7 -0
- package/dist/__tests__/tiers.test.d.ts.map +1 -0
- package/dist/__tests__/tiers.test.js +103 -0
- package/dist/__tests__/tiers.test.js.map +1 -0
- package/dist/__tests__/tools.test.d.ts +7 -0
- package/dist/__tests__/tools.test.d.ts.map +1 -0
- package/dist/__tests__/tools.test.js +143 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/__tests__/transport.test.d.ts +7 -0
- package/dist/__tests__/transport.test.d.ts.map +1 -0
- package/dist/__tests__/transport.test.js +55 -0
- package/dist/__tests__/transport.test.js.map +1 -0
- package/dist/__tests__/web-eval-tools.test.d.ts +8 -0
- package/dist/__tests__/web-eval-tools.test.d.ts.map +1 -0
- package/dist/__tests__/web-eval-tools.test.js +252 -0
- package/dist/__tests__/web-eval-tools.test.js.map +1 -0
- package/dist/__tests__/workflow-tools.test.d.ts +8 -0
- package/dist/__tests__/workflow-tools.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-tools.test.js +268 -0
- package/dist/__tests__/workflow-tools.test.js.map +1 -0
- package/dist/auth/oauth-provider.d.ts +34 -0
- package/dist/auth/oauth-provider.d.ts.map +1 -0
- package/dist/auth/oauth-provider.js +75 -0
- package/dist/auth/oauth-provider.js.map +1 -0
- package/dist/auth/token-verifier.d.ts +40 -0
- package/dist/auth/token-verifier.d.ts.map +1 -0
- package/dist/auth/token-verifier.js +138 -0
- package/dist/auth/token-verifier.js.map +1 -0
- package/dist/http-server.d.ts +35 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +175 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.js +131 -36
- package/dist/index.js.map +1 -1
- package/dist/lib/dobby-client.d.ts +50 -20
- package/dist/lib/dobby-client.d.ts.map +1 -1
- package/dist/lib/dobby-client.js +50 -0
- package/dist/lib/dobby-client.js.map +1 -1
- package/dist/tools/agent-mail.d.ts +153 -0
- package/dist/tools/agent-mail.d.ts.map +1 -0
- package/dist/tools/agent-mail.js +340 -0
- package/dist/tools/agent-mail.js.map +1 -0
- package/dist/tools/approvals.d.ts +24 -0
- package/dist/tools/approvals.d.ts.map +1 -1
- package/dist/tools/approvals.js +24 -0
- package/dist/tools/approvals.js.map +1 -1
- package/dist/tools/crew-builder.d.ts +24 -0
- package/dist/tools/crew-builder.d.ts.map +1 -1
- package/dist/tools/crew-builder.js +24 -0
- package/dist/tools/crew-builder.js.map +1 -1
- package/dist/tools/crewai.d.ts +24 -0
- package/dist/tools/crewai.d.ts.map +1 -1
- package/dist/tools/crewai.js +24 -0
- package/dist/tools/crewai.js.map +1 -1
- package/dist/tools/exa.d.ts +161 -0
- package/dist/tools/exa.d.ts.map +1 -0
- package/dist/tools/exa.js +228 -0
- package/dist/tools/exa.js.map +1 -0
- package/dist/tools/github-mcp.d.ts +303 -0
- package/dist/tools/github-mcp.d.ts.map +1 -0
- package/dist/tools/github-mcp.js +397 -0
- package/dist/tools/github-mcp.js.map +1 -0
- package/dist/tools/governance.d.ts +129 -0
- package/dist/tools/governance.d.ts.map +1 -0
- package/dist/tools/governance.js +171 -0
- package/dist/tools/governance.js.map +1 -0
- package/dist/tools/index.d.ts +3589 -159
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +250 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/jira.d.ts +60 -0
- package/dist/tools/jira.d.ts.map +1 -1
- package/dist/tools/jira.js +60 -0
- package/dist/tools/jira.js.map +1 -1
- package/dist/tools/knowledge-base.d.ts +144 -0
- package/dist/tools/knowledge-base.d.ts.map +1 -0
- package/dist/tools/knowledge-base.js +179 -0
- package/dist/tools/knowledge-base.js.map +1 -0
- package/dist/tools/mcp-metrics.d.ts +62 -0
- package/dist/tools/mcp-metrics.d.ts.map +1 -0
- package/dist/tools/mcp-metrics.js +270 -0
- package/dist/tools/mcp-metrics.js.map +1 -0
- package/dist/tools/mcp-tools.d.ts +12 -0
- package/dist/tools/mcp-tools.d.ts.map +1 -1
- package/dist/tools/mcp-tools.js +12 -0
- package/dist/tools/mcp-tools.js.map +1 -1
- package/dist/tools/mem0.d.ts +168 -0
- package/dist/tools/mem0.d.ts.map +1 -0
- package/dist/tools/mem0.js +255 -0
- package/dist/tools/mem0.js.map +1 -0
- package/dist/tools/memory-graph.d.ts +197 -0
- package/dist/tools/memory-graph.d.ts.map +1 -0
- package/dist/tools/memory-graph.js +545 -0
- package/dist/tools/memory-graph.js.map +1 -0
- package/dist/tools/messages.d.ts +12 -0
- package/dist/tools/messages.d.ts.map +1 -1
- package/dist/tools/messages.js +12 -0
- package/dist/tools/messages.js.map +1 -1
- package/dist/tools/moltbook.d.ts +564 -0
- package/dist/tools/moltbook.d.ts.map +1 -0
- package/dist/tools/moltbook.js +792 -0
- package/dist/tools/moltbook.js.map +1 -0
- package/dist/tools/ops.d.ts +219 -0
- package/dist/tools/ops.d.ts.map +1 -0
- package/dist/tools/ops.js +360 -0
- package/dist/tools/ops.js.map +1 -0
- package/dist/tools/schedules.d.ts +196 -0
- package/dist/tools/schedules.d.ts.map +1 -0
- package/dist/tools/schedules.js +264 -0
- package/dist/tools/schedules.js.map +1 -0
- package/dist/tools/services.d.ts +6 -0
- package/dist/tools/services.d.ts.map +1 -1
- package/dist/tools/services.js +6 -0
- package/dist/tools/services.js.map +1 -1
- package/dist/tools/tasks.d.ts +45 -0
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +49 -4
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/tiers.d.ts +39 -0
- package/dist/tools/tiers.d.ts.map +1 -0
- package/dist/tools/tiers.js +138 -0
- package/dist/tools/tiers.js.map +1 -0
- package/dist/tools/unified-agents.d.ts +62 -0
- package/dist/tools/unified-agents.d.ts.map +1 -0
- package/dist/tools/unified-agents.js +147 -0
- package/dist/tools/unified-agents.js.map +1 -0
- package/dist/tools/web-eval.d.ts +172 -0
- package/dist/tools/web-eval.d.ts.map +1 -0
- package/dist/tools/web-eval.js +347 -0
- package/dist/tools/web-eval.js.map +1 -0
- package/dist/tools/workflow.d.ts +171 -0
- package/dist/tools/workflow.d.ts.map +1 -0
- package/dist/tools/workflow.js +518 -0
- package/dist/tools/workflow.js.map +1 -0
- package/package.json +8 -3
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Automation MCP Tools Tests — Phase 2 + Session 3 updates
|
|
3
|
+
*
|
|
4
|
+
* Tests for task classification, auto-assign with health check,
|
|
5
|
+
* dynamic agent mapping, workload monitoring, and assignment rules.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=workflow-tools.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/workflow-tools.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Automation MCP Tools Tests — Phase 2 + Session 3 updates
|
|
3
|
+
*
|
|
4
|
+
* Tests for task classification, auto-assign with health check,
|
|
5
|
+
* dynamic agent mapping, workload monitoring, and assignment rules.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
8
|
+
// Mock DobbyClient with request method and tenantId
|
|
9
|
+
const mockClient = {
|
|
10
|
+
apiUrl: 'http://localhost:3000',
|
|
11
|
+
apiKey: 'test-api-key',
|
|
12
|
+
tenantId: 'tenant_test123',
|
|
13
|
+
request: vi.fn(),
|
|
14
|
+
};
|
|
15
|
+
// Mock global fetch
|
|
16
|
+
const mockFetch = vi.fn();
|
|
17
|
+
vi.stubGlobal('fetch', mockFetch);
|
|
18
|
+
// ============================================
|
|
19
|
+
// Task Classification (Dynamic Agent Map)
|
|
20
|
+
// ============================================
|
|
21
|
+
describe('Workflow: Task Classification', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
vi.resetAllMocks();
|
|
24
|
+
// Default: API unavailable — uses fallback defaults
|
|
25
|
+
mockClient.request.mockRejectedValue(new Error('Connection refused'));
|
|
26
|
+
});
|
|
27
|
+
it('classifies backend tasks correctly with markdown response', async () => {
|
|
28
|
+
const { handleWorkflowClassifyTask } = await import('../tools/workflow.js');
|
|
29
|
+
const result = await handleWorkflowClassifyTask(mockClient, {
|
|
30
|
+
title: 'Add new API endpoint for user management',
|
|
31
|
+
description: 'Create FastAPI route with pydantic validation',
|
|
32
|
+
});
|
|
33
|
+
const text = result.content[0].text;
|
|
34
|
+
expect(text).toContain('## Task Classification');
|
|
35
|
+
expect(text).toContain('**Category:** backend');
|
|
36
|
+
expect(text).toContain('**Worker:** dobby-backend-agent');
|
|
37
|
+
expect(text).toContain('### Next Steps');
|
|
38
|
+
expect(text).toContain('workflow_auto_assign');
|
|
39
|
+
});
|
|
40
|
+
it('classifies frontend tasks correctly', async () => {
|
|
41
|
+
const { handleWorkflowClassifyTask } = await import('../tools/workflow.js');
|
|
42
|
+
const result = await handleWorkflowClassifyTask(mockClient, {
|
|
43
|
+
title: 'Fix React component layout issue',
|
|
44
|
+
description: 'Update CSS with Tailwind for mobile responsiveness',
|
|
45
|
+
});
|
|
46
|
+
const text = result.content[0].text;
|
|
47
|
+
expect(text).toContain('**Category:** frontend');
|
|
48
|
+
expect(text).toContain('**Worker:** dobby-frontend-agent');
|
|
49
|
+
});
|
|
50
|
+
it('classifies security tasks correctly', async () => {
|
|
51
|
+
const { handleWorkflowClassifyTask } = await import('../tools/workflow.js');
|
|
52
|
+
const result = await handleWorkflowClassifyTask(mockClient, {
|
|
53
|
+
title: 'Fix authentication vulnerability in OAuth flow',
|
|
54
|
+
});
|
|
55
|
+
const text = result.content[0].text;
|
|
56
|
+
expect(text).toContain('**Category:** security');
|
|
57
|
+
expect(text).toContain('**Worker:** dobby-security-agent');
|
|
58
|
+
});
|
|
59
|
+
it('classifies database tasks correctly', async () => {
|
|
60
|
+
const { handleWorkflowClassifyTask } = await import('../tools/workflow.js');
|
|
61
|
+
const result = await handleWorkflowClassifyTask(mockClient, {
|
|
62
|
+
title: 'Create BigQuery migration for new table',
|
|
63
|
+
description: 'Add schema with partition by created_at',
|
|
64
|
+
});
|
|
65
|
+
const text = result.content[0].text;
|
|
66
|
+
expect(text).toContain('**Category:** database');
|
|
67
|
+
expect(text).toContain('**Worker:** dobby-database-agent');
|
|
68
|
+
});
|
|
69
|
+
it('classifies testing tasks to QA lead coordinator', async () => {
|
|
70
|
+
const { handleWorkflowClassifyTask } = await import('../tools/workflow.js');
|
|
71
|
+
const result = await handleWorkflowClassifyTask(mockClient, {
|
|
72
|
+
title: 'Add pytest coverage for auth module',
|
|
73
|
+
description: 'Write vitest mock fixtures and e2e spec',
|
|
74
|
+
});
|
|
75
|
+
const text = result.content[0].text;
|
|
76
|
+
expect(text).toContain('**Category:** testing');
|
|
77
|
+
expect(text).toContain('**Coordinator:** dobby-qa-lead-agent');
|
|
78
|
+
expect(text).toContain('**Worker:** dobby-test-writer-agent');
|
|
79
|
+
});
|
|
80
|
+
it('defaults to backend for unrecognized tasks', async () => {
|
|
81
|
+
const { handleWorkflowClassifyTask } = await import('../tools/workflow.js');
|
|
82
|
+
const result = await handleWorkflowClassifyTask(mockClient, {
|
|
83
|
+
title: 'Do something very generic',
|
|
84
|
+
description: 'This has no specific keywords at all',
|
|
85
|
+
});
|
|
86
|
+
const text = result.content[0].text;
|
|
87
|
+
expect(text).toContain('**Category:** backend');
|
|
88
|
+
expect(text).toContain('**Confidence:** 30%');
|
|
89
|
+
});
|
|
90
|
+
it('uses dynamic agent map from API when available', async () => {
|
|
91
|
+
const { handleWorkflowClassifyTask } = await import('../tools/workflow.js');
|
|
92
|
+
mockClient.request.mockResolvedValueOnce({
|
|
93
|
+
data: {
|
|
94
|
+
agents: [
|
|
95
|
+
{ agent_id: 'custom-backend-v2', agent_layer: 'worker', group: 'dev' },
|
|
96
|
+
{ agent_id: 'custom-dev-lead', agent_layer: 'coordinator', group: 'dev' },
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
const result = await handleWorkflowClassifyTask(mockClient, {
|
|
101
|
+
title: 'Add new API endpoint for user management',
|
|
102
|
+
});
|
|
103
|
+
const text = result.content[0].text;
|
|
104
|
+
expect(text).toContain('**Category:** backend');
|
|
105
|
+
// Should use dynamic coordinator from API
|
|
106
|
+
expect(text).toContain('**Coordinator:** custom-dev-lead');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
// ============================================
|
|
110
|
+
// Auto-Assign (API call + health check)
|
|
111
|
+
// ============================================
|
|
112
|
+
describe('Workflow: Auto-Assign', () => {
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
vi.resetAllMocks();
|
|
115
|
+
mockClient.request.mockRejectedValue(new Error('Connection refused'));
|
|
116
|
+
});
|
|
117
|
+
it('calls API and returns markdown assignment result', async () => {
|
|
118
|
+
const { handleWorkflowAutoAssign } = await import('../tools/workflow.js');
|
|
119
|
+
// Health check call + auto-assign API call — both succeed
|
|
120
|
+
mockFetch
|
|
121
|
+
.mockResolvedValueOnce({
|
|
122
|
+
ok: true,
|
|
123
|
+
json: () => Promise.resolve({ agent_status: 'active' }),
|
|
124
|
+
})
|
|
125
|
+
.mockResolvedValueOnce({
|
|
126
|
+
ok: true,
|
|
127
|
+
json: () => Promise.resolve({
|
|
128
|
+
task_id: 'task_abc123',
|
|
129
|
+
assigned_coordinator: 'dobby-dev-coordinator-agent',
|
|
130
|
+
assigned_worker: 'dobby-backend-agent',
|
|
131
|
+
}),
|
|
132
|
+
});
|
|
133
|
+
const result = await handleWorkflowAutoAssign(mockClient, {
|
|
134
|
+
task_id: 'task_abc123',
|
|
135
|
+
title: 'Add API endpoint',
|
|
136
|
+
});
|
|
137
|
+
const text = result.content[0].text;
|
|
138
|
+
expect(text).toContain('## Auto-Assignment Result');
|
|
139
|
+
expect(text).toContain('**Status:** assigned');
|
|
140
|
+
});
|
|
141
|
+
it('returns local classification as fallback when API unavailable', async () => {
|
|
142
|
+
const { handleWorkflowAutoAssign } = await import('../tools/workflow.js');
|
|
143
|
+
// All fetch calls fail (health check + auto-assign API)
|
|
144
|
+
mockFetch.mockRejectedValue(new Error('Connection refused'));
|
|
145
|
+
const result = await handleWorkflowAutoAssign(mockClient, {
|
|
146
|
+
task_id: 'task_abc123',
|
|
147
|
+
title: 'Fix security vulnerability in authentication',
|
|
148
|
+
});
|
|
149
|
+
expect(result.isError).toBeUndefined();
|
|
150
|
+
const text = result.content[0].text;
|
|
151
|
+
expect(text).toContain('**Status:** suggestion_only');
|
|
152
|
+
expect(text).toContain('**Category:** security');
|
|
153
|
+
expect(text).toContain('**Worker:** dobby-security-agent');
|
|
154
|
+
});
|
|
155
|
+
it('shows health warning when agent is paused', async () => {
|
|
156
|
+
const { handleWorkflowAutoAssign } = await import('../tools/workflow.js');
|
|
157
|
+
// Health check returns paused status
|
|
158
|
+
mockFetch
|
|
159
|
+
.mockResolvedValueOnce({
|
|
160
|
+
ok: true,
|
|
161
|
+
json: () => Promise.resolve({ agent_status: 'paused' }),
|
|
162
|
+
})
|
|
163
|
+
// Auto-assign API call
|
|
164
|
+
.mockResolvedValueOnce({
|
|
165
|
+
ok: true,
|
|
166
|
+
json: () => Promise.resolve({ task_id: 'task_abc123', assigned: true }),
|
|
167
|
+
});
|
|
168
|
+
const result = await handleWorkflowAutoAssign(mockClient, {
|
|
169
|
+
task_id: 'task_abc123',
|
|
170
|
+
title: 'Add API endpoint for backend',
|
|
171
|
+
});
|
|
172
|
+
const text = result.content[0].text;
|
|
173
|
+
expect(text).toContain('**Health Warning:**');
|
|
174
|
+
expect(text).toContain('paused');
|
|
175
|
+
});
|
|
176
|
+
it('returns error when API returns non-ok response', async () => {
|
|
177
|
+
const { handleWorkflowAutoAssign } = await import('../tools/workflow.js');
|
|
178
|
+
// Health check fails (no problem)
|
|
179
|
+
mockFetch
|
|
180
|
+
.mockRejectedValueOnce(new Error('Health unavailable'))
|
|
181
|
+
// Auto-assign API returns 404
|
|
182
|
+
.mockResolvedValueOnce({
|
|
183
|
+
ok: false,
|
|
184
|
+
status: 404,
|
|
185
|
+
text: () => Promise.resolve('Task not found'),
|
|
186
|
+
});
|
|
187
|
+
const result = await handleWorkflowAutoAssign(mockClient, {
|
|
188
|
+
task_id: 'task_nonexistent',
|
|
189
|
+
title: 'Some task',
|
|
190
|
+
});
|
|
191
|
+
expect(result.isError).toBe(true);
|
|
192
|
+
const text = result.content[0].text;
|
|
193
|
+
expect(text).toContain('**Status:** error');
|
|
194
|
+
expect(text).toContain('### Error');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
// ============================================
|
|
198
|
+
// Agent Workload
|
|
199
|
+
// ============================================
|
|
200
|
+
describe('Workflow: Agent Workload', () => {
|
|
201
|
+
beforeEach(() => {
|
|
202
|
+
vi.resetAllMocks();
|
|
203
|
+
mockClient.request.mockRejectedValue(new Error('Connection refused'));
|
|
204
|
+
});
|
|
205
|
+
it('returns workload data from API', async () => {
|
|
206
|
+
const { handleWorkflowAgentWorkload } = await import('../tools/workflow.js');
|
|
207
|
+
mockFetch.mockResolvedValueOnce({
|
|
208
|
+
ok: true,
|
|
209
|
+
json: () => Promise.resolve({
|
|
210
|
+
agents: [
|
|
211
|
+
{ agent_id: 'dobby-backend-agent', active_tasks: 2 },
|
|
212
|
+
{ agent_id: 'dobby-frontend-agent', active_tasks: 0 },
|
|
213
|
+
],
|
|
214
|
+
}),
|
|
215
|
+
});
|
|
216
|
+
const result = await handleWorkflowAgentWorkload(mockClient, {});
|
|
217
|
+
const data = JSON.parse(result.content[0].text);
|
|
218
|
+
expect(data.agents).toHaveLength(2);
|
|
219
|
+
});
|
|
220
|
+
it('returns dynamic agent hierarchy as fallback when API unavailable', async () => {
|
|
221
|
+
const { handleWorkflowAgentWorkload } = await import('../tools/workflow.js');
|
|
222
|
+
mockFetch.mockRejectedValueOnce(new Error('Connection refused'));
|
|
223
|
+
const result = await handleWorkflowAgentWorkload(mockClient, {});
|
|
224
|
+
const data = JSON.parse(result.content[0].text);
|
|
225
|
+
expect(data.note).toContain('Could not reach Dobby API');
|
|
226
|
+
expect(data.agents).toBeDefined();
|
|
227
|
+
expect(data.agents.length).toBeGreaterThan(0);
|
|
228
|
+
expect(data.agents.some((a) => a.category === 'backend')).toBe(true);
|
|
229
|
+
expect(data.agents.some((a) => a.category === 'security')).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
// ============================================
|
|
233
|
+
// Input Validation
|
|
234
|
+
// ============================================
|
|
235
|
+
describe('Workflow: Input Validation', () => {
|
|
236
|
+
it('auto_assign task_id has pattern validation', async () => {
|
|
237
|
+
const { workflowTools } = await import('../tools/workflow.js');
|
|
238
|
+
const autoAssignSchema = workflowTools.workflow_auto_assign.inputSchema;
|
|
239
|
+
expect(autoAssignSchema.properties.task_id.pattern).toBe('^task_[a-zA-Z0-9_-]+$');
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
// ============================================
|
|
243
|
+
// Tool Registration
|
|
244
|
+
// ============================================
|
|
245
|
+
describe('Workflow: Tool Registration', () => {
|
|
246
|
+
it('all workflow tools are in allTools', async () => {
|
|
247
|
+
const { allTools } = await import('../tools/index.js');
|
|
248
|
+
expect(allTools.workflow_classify_task).toBeDefined();
|
|
249
|
+
expect(allTools.workflow_auto_assign).toBeDefined();
|
|
250
|
+
expect(allTools.workflow_agent_workload).toBeDefined();
|
|
251
|
+
expect(allTools.workflow_assignment_rules).toBeDefined();
|
|
252
|
+
});
|
|
253
|
+
it('workflow tools have correct schemas', async () => {
|
|
254
|
+
const { workflowTools } = await import('../tools/workflow.js');
|
|
255
|
+
for (const [name, tool] of Object.entries(workflowTools)) {
|
|
256
|
+
expect(tool.name).toBe(name);
|
|
257
|
+
expect(tool.description).toBeTruthy();
|
|
258
|
+
expect(tool.inputSchema.type).toBe('object');
|
|
259
|
+
expect(tool.inputSchema.properties).toBeDefined();
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
it('total tool count includes workflow tools', async () => {
|
|
263
|
+
const { allTools } = await import('../tools/index.js');
|
|
264
|
+
const toolCount = Object.keys(allTools).length;
|
|
265
|
+
expect(toolCount).toBeGreaterThanOrEqual(54);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
//# sourceMappingURL=workflow-tools.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-tools.test.js","sourceRoot":"","sources":["../../src/__tests__/workflow-tools.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Proxy Provider
|
|
3
|
+
*
|
|
4
|
+
* Creates a ProxyOAuthServerProvider that delegates all OAuth operations
|
|
5
|
+
* to the web app (dobby-ai.com). The MCP server never stores tokens or
|
|
6
|
+
* client registrations — it only proxies.
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* Claude Code → MCP server (proxy) → Web app OAuth endpoints
|
|
10
|
+
*/
|
|
11
|
+
import { ProxyOAuthServerProvider } from '@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js';
|
|
12
|
+
import { TokenVerifier } from './token-verifier.js';
|
|
13
|
+
export interface OAuthProviderConfig {
|
|
14
|
+
/** Web app base URL where OAuth endpoints live (e.g. https://dobby-ai.com) */
|
|
15
|
+
issuerUrl: string;
|
|
16
|
+
/** MCP server public URL (e.g. https://mcp.dobby-ai.com) */
|
|
17
|
+
mcpPublicUrl: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create a ProxyOAuthServerProvider that delegates to the web app.
|
|
21
|
+
*
|
|
22
|
+
* The provider:
|
|
23
|
+
* - Redirects /authorize to web app's /oauth/authorize
|
|
24
|
+
* - Proxies /token to web app's /oauth/token
|
|
25
|
+
* - Proxies /revoke to web app's /oauth/revoke
|
|
26
|
+
* - Proxies /register to web app's /oauth/register
|
|
27
|
+
* - Verifies tokens via TokenVerifier (with 60s LRU cache)
|
|
28
|
+
* - Fetches client info from web app's /oauth/register/:clientId
|
|
29
|
+
*/
|
|
30
|
+
export declare function createOAuthProvider(config: OAuthProviderConfig): {
|
|
31
|
+
provider: ProxyOAuthServerProvider;
|
|
32
|
+
tokenVerifier: TokenVerifier;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=oauth-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-provider.d.ts","sourceRoot":"","sources":["../../src/auth/oauth-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,kEAAkE,CAAC;AAE5G,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMpD,MAAM,WAAW,mBAAmB;IAClC,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG;IAChE,QAAQ,EAAE,wBAAwB,CAAC;IACnC,aAAa,EAAE,aAAa,CAAC;CAC9B,CAoDA"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Proxy Provider
|
|
3
|
+
*
|
|
4
|
+
* Creates a ProxyOAuthServerProvider that delegates all OAuth operations
|
|
5
|
+
* to the web app (dobby-ai.com). The MCP server never stores tokens or
|
|
6
|
+
* client registrations — it only proxies.
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* Claude Code → MCP server (proxy) → Web app OAuth endpoints
|
|
10
|
+
*/
|
|
11
|
+
import { ProxyOAuthServerProvider } from '@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js';
|
|
12
|
+
import { TokenVerifier } from './token-verifier.js';
|
|
13
|
+
// ============================================
|
|
14
|
+
// Create Provider
|
|
15
|
+
// ============================================
|
|
16
|
+
/**
|
|
17
|
+
* Create a ProxyOAuthServerProvider that delegates to the web app.
|
|
18
|
+
*
|
|
19
|
+
* The provider:
|
|
20
|
+
* - Redirects /authorize to web app's /oauth/authorize
|
|
21
|
+
* - Proxies /token to web app's /oauth/token
|
|
22
|
+
* - Proxies /revoke to web app's /oauth/revoke
|
|
23
|
+
* - Proxies /register to web app's /oauth/register
|
|
24
|
+
* - Verifies tokens via TokenVerifier (with 60s LRU cache)
|
|
25
|
+
* - Fetches client info from web app's /oauth/register/:clientId
|
|
26
|
+
*/
|
|
27
|
+
export function createOAuthProvider(config) {
|
|
28
|
+
const { issuerUrl } = config;
|
|
29
|
+
const baseOAuthUrl = issuerUrl.replace(/\/$/, '');
|
|
30
|
+
// Token verifier with LRU cache
|
|
31
|
+
const tokenVerifier = new TokenVerifier(issuerUrl);
|
|
32
|
+
const provider = new ProxyOAuthServerProvider({
|
|
33
|
+
endpoints: {
|
|
34
|
+
authorizationUrl: `${baseOAuthUrl}/oauth/authorize`,
|
|
35
|
+
tokenUrl: `${baseOAuthUrl}/oauth/token`,
|
|
36
|
+
revocationUrl: `${baseOAuthUrl}/oauth/revoke`,
|
|
37
|
+
registrationUrl: `${baseOAuthUrl}/oauth/register`,
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* Verify access token — called by requireBearerAuth middleware.
|
|
41
|
+
* Uses LRU cache (60s TTL) for performance.
|
|
42
|
+
*/
|
|
43
|
+
verifyAccessToken: async (token) => {
|
|
44
|
+
return tokenVerifier.verifyAccessToken(token);
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* Fetch client information from the web app.
|
|
48
|
+
* Called during OAuth flow to validate client_id.
|
|
49
|
+
*/
|
|
50
|
+
getClient: async (clientId) => {
|
|
51
|
+
try {
|
|
52
|
+
const response = await fetch(`${baseOAuthUrl}/oauth/register/${clientId}`, {
|
|
53
|
+
method: 'GET',
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
if (response.status === 404)
|
|
60
|
+
return undefined;
|
|
61
|
+
console.error(`[OAuth] Failed to fetch client ${clientId}: ${response.status}`);
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
return await response.json();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
const msg = error instanceof Error ? error.message : 'Unknown error';
|
|
68
|
+
console.error(`[OAuth] Error fetching client ${clientId}:`, msg);
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
return { provider, tokenVerifier };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=oauth-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-provider.js","sourceRoot":"","sources":["../../src/auth/oauth-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,kEAAkE,CAAC;AAE5G,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAapD,+CAA+C;AAC/C,kBAAkB;AAClB,+CAA+C;AAE/C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAI7D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAC7B,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAElD,gCAAgC;IAChC,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;IAEnD,MAAM,QAAQ,GAAG,IAAI,wBAAwB,CAAC;QAC5C,SAAS,EAAE;YACT,gBAAgB,EAAE,GAAG,YAAY,kBAAkB;YACnD,QAAQ,EAAE,GAAG,YAAY,cAAc;YACvC,aAAa,EAAE,GAAG,YAAY,eAAe;YAC7C,eAAe,EAAE,GAAG,YAAY,iBAAiB;SAClD;QAED;;;WAGG;QACH,iBAAiB,EAAE,KAAK,EAAE,KAAa,EAAE,EAAE;YACzC,OAAO,aAAa,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC;QAED;;;WAGG;QACH,SAAS,EAAE,KAAK,EAAE,QAAgB,EAAmD,EAAE;YACrF,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,YAAY,mBAAmB,QAAQ,EAAE,EAAE;oBACzE,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;qBACnC;iBACF,CAAC,CAAC;gBAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;wBAAE,OAAO,SAAS,CAAC;oBAC9C,OAAO,CAAC,KAAK,CAAC,kCAAkC,QAAQ,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;oBAChF,OAAO,SAAS,CAAC;gBACnB,CAAC;gBAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAgC,CAAC;YAC7D,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;gBACrE,OAAO,CAAC,KAAK,CAAC,iCAAiC,QAAQ,GAAG,EAAE,GAAG,CAAC,CAAC;gBACjE,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Verifier
|
|
3
|
+
*
|
|
4
|
+
* Validates OAuth access tokens (dobby_at_*) by calling the web app's
|
|
5
|
+
* token validation endpoint. Results are cached locally with 60s TTL
|
|
6
|
+
* to avoid per-request latency.
|
|
7
|
+
*/
|
|
8
|
+
import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
|
|
9
|
+
export interface TokenInfo {
|
|
10
|
+
user_id: string;
|
|
11
|
+
org_id: string;
|
|
12
|
+
tenant_id: string;
|
|
13
|
+
scope: string;
|
|
14
|
+
client_id: string;
|
|
15
|
+
expires_at?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class TokenVerifier {
|
|
18
|
+
private cache;
|
|
19
|
+
private issuerUrl;
|
|
20
|
+
constructor(issuerUrl: string);
|
|
21
|
+
/**
|
|
22
|
+
* Verify an access token and return AuthInfo for the MCP SDK.
|
|
23
|
+
* Uses LRU cache with 60s TTL.
|
|
24
|
+
*/
|
|
25
|
+
verifyAccessToken(token: string): Promise<AuthInfo>;
|
|
26
|
+
/**
|
|
27
|
+
* Get the resolved tenant context from a cached token.
|
|
28
|
+
* Returns undefined if token is not cached (call verifyAccessToken first).
|
|
29
|
+
*/
|
|
30
|
+
getTokenInfo(token: string): TokenInfo | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Validate token against the web app's OAuth introspection endpoint.
|
|
33
|
+
*/
|
|
34
|
+
private validateRemote;
|
|
35
|
+
/** Clear the token cache (for testing) */
|
|
36
|
+
clearCache(): void;
|
|
37
|
+
/** Get cache size (for monitoring) */
|
|
38
|
+
get cacheSize(): number;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=token-verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-verifier.d.ts","sourceRoot":"","sources":["../../src/auth/token-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAM1E,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAyDD,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,EAAE,MAAM;IAK7B;;;OAGG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAgCzD;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIlD;;OAEG;YACW,cAAc;IAgD5B,0CAA0C;IAC1C,UAAU,IAAI,IAAI;IAIlB,sCAAsC;IACtC,IAAI,SAAS,IAAI,MAAM,CAEtB;CACF"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Verifier
|
|
3
|
+
*
|
|
4
|
+
* Validates OAuth access tokens (dobby_at_*) by calling the web app's
|
|
5
|
+
* token validation endpoint. Results are cached locally with 60s TTL
|
|
6
|
+
* to avoid per-request latency.
|
|
7
|
+
*/
|
|
8
|
+
// ============================================
|
|
9
|
+
// LRU Cache
|
|
10
|
+
// ============================================
|
|
11
|
+
const CACHE_TTL_MS = 60_000; // 60 seconds
|
|
12
|
+
const CACHE_MAX_SIZE = 1000;
|
|
13
|
+
class TokenCache {
|
|
14
|
+
cache = new Map();
|
|
15
|
+
get(token) {
|
|
16
|
+
const entry = this.cache.get(token);
|
|
17
|
+
if (!entry)
|
|
18
|
+
return undefined;
|
|
19
|
+
if (Date.now() > entry.expiresAt) {
|
|
20
|
+
this.cache.delete(token);
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
// Move to end (LRU)
|
|
24
|
+
this.cache.delete(token);
|
|
25
|
+
this.cache.set(token, entry);
|
|
26
|
+
return entry;
|
|
27
|
+
}
|
|
28
|
+
set(token, entry) {
|
|
29
|
+
// Evict oldest if at capacity
|
|
30
|
+
if (this.cache.size >= CACHE_MAX_SIZE) {
|
|
31
|
+
const firstKey = this.cache.keys().next().value;
|
|
32
|
+
if (firstKey !== undefined) {
|
|
33
|
+
this.cache.delete(firstKey);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
this.cache.set(token, entry);
|
|
37
|
+
}
|
|
38
|
+
clear() {
|
|
39
|
+
this.cache.clear();
|
|
40
|
+
}
|
|
41
|
+
get size() {
|
|
42
|
+
return this.cache.size;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// ============================================
|
|
46
|
+
// Token Verifier
|
|
47
|
+
// ============================================
|
|
48
|
+
export class TokenVerifier {
|
|
49
|
+
cache = new TokenCache();
|
|
50
|
+
issuerUrl;
|
|
51
|
+
constructor(issuerUrl) {
|
|
52
|
+
// Remove trailing slash
|
|
53
|
+
this.issuerUrl = issuerUrl.replace(/\/$/, '');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Verify an access token and return AuthInfo for the MCP SDK.
|
|
57
|
+
* Uses LRU cache with 60s TTL.
|
|
58
|
+
*/
|
|
59
|
+
async verifyAccessToken(token) {
|
|
60
|
+
// Check cache first
|
|
61
|
+
const cached = this.cache.get(token);
|
|
62
|
+
if (cached) {
|
|
63
|
+
return cached.authInfo;
|
|
64
|
+
}
|
|
65
|
+
// Validate against web app
|
|
66
|
+
const tokenInfo = await this.validateRemote(token);
|
|
67
|
+
const authInfo = {
|
|
68
|
+
token,
|
|
69
|
+
clientId: tokenInfo.client_id,
|
|
70
|
+
scopes: tokenInfo.scope ? tokenInfo.scope.split(' ') : [],
|
|
71
|
+
expiresAt: tokenInfo.expires_at,
|
|
72
|
+
extra: {
|
|
73
|
+
user_id: tokenInfo.user_id,
|
|
74
|
+
org_id: tokenInfo.org_id,
|
|
75
|
+
tenant_id: tokenInfo.tenant_id,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
// Cache the result
|
|
79
|
+
this.cache.set(token, {
|
|
80
|
+
authInfo,
|
|
81
|
+
tokenInfo,
|
|
82
|
+
expiresAt: Date.now() + CACHE_TTL_MS,
|
|
83
|
+
});
|
|
84
|
+
return authInfo;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the resolved tenant context from a cached token.
|
|
88
|
+
* Returns undefined if token is not cached (call verifyAccessToken first).
|
|
89
|
+
*/
|
|
90
|
+
getTokenInfo(token) {
|
|
91
|
+
return this.cache.get(token)?.tokenInfo;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Validate token against the web app's OAuth introspection endpoint.
|
|
95
|
+
*/
|
|
96
|
+
async validateRemote(token) {
|
|
97
|
+
const url = `${this.issuerUrl}/oauth/token/introspect`;
|
|
98
|
+
const response = await fetch(url, {
|
|
99
|
+
method: 'POST',
|
|
100
|
+
headers: {
|
|
101
|
+
'Content-Type': 'application/json',
|
|
102
|
+
'Authorization': `Bearer ${token}`,
|
|
103
|
+
},
|
|
104
|
+
body: JSON.stringify({ token }),
|
|
105
|
+
});
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
const status = response.status;
|
|
108
|
+
if (status === 401 || status === 403) {
|
|
109
|
+
throw new Error('Invalid or expired access token');
|
|
110
|
+
}
|
|
111
|
+
throw new Error(`Token validation failed (${status})`);
|
|
112
|
+
}
|
|
113
|
+
const data = await response.json();
|
|
114
|
+
if (!data.active) {
|
|
115
|
+
throw new Error('Token is not active');
|
|
116
|
+
}
|
|
117
|
+
if (!data.org_id || !data.tenant_id) {
|
|
118
|
+
throw new Error('Token missing org_id or tenant_id — cannot resolve tenant context');
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
user_id: data.user_id || '',
|
|
122
|
+
org_id: data.org_id,
|
|
123
|
+
tenant_id: data.tenant_id,
|
|
124
|
+
scope: data.scope || '',
|
|
125
|
+
client_id: data.client_id || '',
|
|
126
|
+
expires_at: data.exp,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** Clear the token cache (for testing) */
|
|
130
|
+
clearCache() {
|
|
131
|
+
this.cache.clear();
|
|
132
|
+
}
|
|
133
|
+
/** Get cache size (for monitoring) */
|
|
134
|
+
get cacheSize() {
|
|
135
|
+
return this.cache.size;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=token-verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-verifier.js","sourceRoot":"","sources":["../../src/auth/token-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Server for Dobby MCP
|
|
3
|
+
*
|
|
4
|
+
* Express app serving MCP over Streamable HTTP transport with OAuth 2.1 auth.
|
|
5
|
+
* Runs alongside the existing STDIO mode — selected via --transport http.
|
|
6
|
+
*
|
|
7
|
+
* Endpoints:
|
|
8
|
+
* GET /.well-known/oauth-authorization-server — OAuth metadata (via mcpAuthRouter)
|
|
9
|
+
* GET /authorize — Redirect to web app consent page (via mcpAuthRouter)
|
|
10
|
+
* POST /token — Token exchange proxy (via mcpAuthRouter)
|
|
11
|
+
* POST /register — Dynamic client registration proxy (via mcpAuthRouter)
|
|
12
|
+
* POST /revoke — Token revocation proxy (via mcpAuthRouter)
|
|
13
|
+
* POST /mcp — Streamable HTTP MCP endpoint (Bearer auth required)
|
|
14
|
+
* GET /mcp — SSE stream for Streamable HTTP (Bearer auth required)
|
|
15
|
+
* DELETE /mcp — Session termination (Bearer auth required)
|
|
16
|
+
* GET /health — Health check (no auth)
|
|
17
|
+
*/
|
|
18
|
+
import express from 'express';
|
|
19
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
20
|
+
import type { TokenVerifier } from './auth/token-verifier.js';
|
|
21
|
+
export interface HttpServerConfig {
|
|
22
|
+
/** Port to listen on (default: 8080) */
|
|
23
|
+
port: number;
|
|
24
|
+
/** Web app base URL where OAuth endpoints live */
|
|
25
|
+
issuerUrl: string;
|
|
26
|
+
/** MCP server public URL */
|
|
27
|
+
mcpPublicUrl: string;
|
|
28
|
+
/** Factory to create a connected MCP Server for each session */
|
|
29
|
+
createMcpServer: () => Promise<Server>;
|
|
30
|
+
}
|
|
31
|
+
export declare function startHttpServer(config: HttpServerConfig): Promise<{
|
|
32
|
+
app: express.Express;
|
|
33
|
+
tokenVerifier: TokenVerifier;
|
|
34
|
+
}>;
|
|
35
|
+
//# sourceMappingURL=http-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAG9B,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAKnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAM9D,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,eAAe,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACxC;AAaD,wBAAsB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC;IACvE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;CAC9B,CAAC,CAoKD"}
|